| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- import '@vaadin/vaadin-context-menu'
- import copyToClipboard from 'copy-text-to-clipboard'
- import { Injectable, Inject } from '@angular/core'
- import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
- import { PlatformService, ClipboardContent, MenuItemOptions, MessageBoxOptions, MessageBoxResult, FileUpload, FileUploadOptions, FileDownload, DirectoryDownload, HTMLFileUpload, DirectoryUpload } from 'tabby-core'
- // eslint-disable-next-line no-duplicate-imports
- import type { ContextMenuElement, ContextMenuItem } from '@vaadin/vaadin-context-menu'
- import { MessageBoxModalComponent } from './components/messageBoxModal.component'
- import './styles.scss'
- @Injectable()
- export class WebPlatformService extends PlatformService {
- private menu: ContextMenuElement
- private contextMenuHandlers = new Map<ContextMenuItem, () => void>()
- private fileSelector: HTMLInputElement
- constructor (
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
- @Inject('WEB_CONNECTOR') private connector: any,
- private ngbModal: NgbModal,
- ) {
- super()
- this.menu = window.document.createElement('vaadin-context-menu')
- this.menu.addEventListener('item-selected', e => {
- this.contextMenuHandlers.get(e.detail.value)?.()
- })
- document.body.appendChild(this.menu)
- this.fileSelector = document.createElement('input')
- this.fileSelector.type = 'file'
- this.fileSelector.style.visibility = 'hidden'
- document.body.appendChild(this.fileSelector)
- }
- readClipboard (): string {
- return ''
- }
- setClipboard (content: ClipboardContent): void {
- copyToClipboard(content.text)
- }
- async loadConfig (): Promise<string> {
- return this.connector.loadConfig()
- }
- async saveConfig (content: string): Promise<void> {
- await this.connector.saveConfig(content)
- }
- getOSRelease (): string {
- return '1.0'
- }
- openExternal (url: string): void {
- window.open(url)
- }
- getAppVersion (): string {
- return this.connector.getAppVersion()
- }
- async listFonts (): Promise<string[]> {
- return []
- }
- popupContextMenu (menu: MenuItemOptions[], event?: MouseEvent): void {
- this.contextMenuHandlers.clear()
- this.menu.items = menu
- .filter(x => x.type !== 'separator')
- .map(x => this.remapMenuItem(x))
- setTimeout(() => {
- this.menu.open(event)
- }, 10)
- }
- private remapMenuItem (item: MenuItemOptions): ContextMenuItem {
- const cmi = {
- text: item.label,
- disabled: !(item.enabled ?? true),
- checked: item.checked,
- children: item.submenu?.map(i => this.remapMenuItem(i)),
- }
- if (item.click) {
- this.contextMenuHandlers.set(cmi, item.click)
- }
- return cmi
- }
- async showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult> {
- const modal = this.ngbModal.open(MessageBoxModalComponent, {
- backdrop: 'static',
- })
- const instance: MessageBoxModalComponent = modal.componentInstance
- instance.options = options
- try {
- const response = await modal.result
- return { response }
- } catch {
- return { response: options.cancelId ?? 1 }
- }
- }
- quit (): void {
- window.close()
- }
- async startDownload (name: string, mode: number, size: number): Promise<FileDownload|null> {
- const transfer = new HTMLFileDownload(name, mode, size)
- this.fileTransferStarted.next(transfer)
- return transfer
- }
- async startDownloadDirectory (_name: string, _estimatedSize?: number): Promise<DirectoryDownload|null> {
- throw new Error('Unsupported')
- }
- startUpload (options?: FileUploadOptions): Promise<FileUpload[]> {
- return new Promise(resolve => {
- this.fileSelector.onchange = () => {
- const transfers: FileUpload[] = []
- const fileList = this.fileSelector.files!
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- for (let i = 0; i < (fileList.length ?? 0); i++) {
- const file = fileList[i]
- const transfer = new HTMLFileUpload(file)
- this.fileTransferStarted.next(transfer)
- transfers.push(transfer)
- if (!options?.multiple) {
- break
- }
- }
- resolve(transfers)
- }
- this.fileSelector.click()
- })
- }
- async startUploadDirectory (_paths?: string[]): Promise<DirectoryUpload> {
- return new DirectoryUpload()
- }
- setErrorHandler (handler: (_: any) => void): void {
- window.addEventListener('error', handler)
- }
- async pickDirectory (): Promise<string> {
- throw new Error('Unsupported')
- }
- }
- class HTMLFileDownload extends FileDownload {
- private buffers: Uint8Array[] = []
- constructor (
- private name: string,
- private mode: number,
- private size: number,
- ) {
- super()
- }
- getName (): string {
- return this.name
- }
- getMode (): number {
- return this.mode
- }
- getSize (): number {
- return this.size
- }
- async write (buffer: Uint8Array): Promise<void> {
- this.buffers.push(Uint8Array.from(buffer))
- this.increaseProgress(buffer.length)
- if (this.isComplete()) {
- this.finish()
- }
- }
- finish () {
- const blob = new Blob(this.buffers, { type: 'application/octet-stream' })
- const element = window.document.createElement('a')
- element.href = window.URL.createObjectURL(blob)
- element.download = this.name
- document.body.appendChild(element)
- element.click()
- document.body.removeChild(element)
- }
- // eslint-disable-next-line @typescript-eslint/no-empty-function
- close (): void { }
- }
|