Dinh Long Nguyen a30eb7f968
feat: Jan Web (reusing Jan Desktop UI) (#6298)
* add platform guards

* add service management

* fix types

* move to zustand for servicehub

* update App Updater

* update tauri missing move

* update app updater

* refactor: move PlatformFeatures to separate const file

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* change tauri fetch name

* update implementation

* update extension fetch

* make web version run properly

* disabled unused web settings

* fix all tests

* fix lint

* fix tests

* add mock for extension

* fix build

* update make and mise

* fix tsconfig for web-extensions

* fix loader type

* cleanup

* fix test

* update error handling + mcp should be working

* Update mcp init

* use separate is_web_app build property

* Remove fixed model catalog url

* fix additional tests

* fix download issue (event emitter not implemented correctly)

* Update Title html

* fix app logs

* update root tsx render timing

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-05 01:47:46 +07:00

53 lines
1.5 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-unused-vars */
/**
* Web Dialog Service - Web implementation
* Provides web-specific implementations for dialog operations
*/
import type { DialogService, DialogOpenOptions } from './types'
export class WebDialogService implements DialogService {
async open(options?: DialogOpenOptions): Promise<string | string[] | null> {
// Web fallback - create hidden input element
return new Promise((resolve) => {
const input = document.createElement('input')
input.type = 'file'
input.multiple = options?.multiple ?? false
if (options?.directory) {
input.webkitdirectory = true
}
if (options?.filters) {
const extensions = options.filters.flatMap(filter =>
filter.extensions.map(ext => `.${ext}`)
)
input.accept = extensions.join(',')
}
input.onchange = (e) => {
const files = (e.target as HTMLInputElement).files
if (!files || files.length === 0) {
resolve(null)
return
}
if (options?.multiple) {
resolve(Array.from(files).map(file => file.name))
} else {
resolve(files[0].name)
}
}
input.oncancel = () => resolve(null)
input.click()
})
}
async save(_options?: DialogOpenOptions): Promise<string | null> {
// Web doesn't support save dialogs in same way
// Return a default filename or null
console.warn('Save dialog not supported in web environment')
return null
}
}