From b8259e7794d1a15e4985f46d5cc79974a12f0541 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 11 Jul 2025 00:05:52 +0700 Subject: [PATCH] feat: add HF token setting --- extensions/download-extension/src/index.ts | 44 ++++++++------ web-app/src/hooks/useGeneralSetting.ts | 23 ++++++++ web-app/src/locales/en/settings.json | 2 + web-app/src/routes/settings/general.tsx | 69 ++++++++++++++-------- 4 files changed, 96 insertions(+), 42 deletions(-) diff --git a/extensions/download-extension/src/index.ts b/extensions/download-extension/src/index.ts index 11315ba85..be193ef6c 100644 --- a/extensions/download-extension/src/index.ts +++ b/extensions/download-extension/src/index.ts @@ -1,6 +1,6 @@ -import { invoke } from '@tauri-apps/api/core'; -import { listen } from '@tauri-apps/api/event'; -import { BaseExtension, events } from '@janhq/core'; +import { invoke } from '@tauri-apps/api/core' +import { listen } from '@tauri-apps/api/event' +import { BaseExtension, events } from '@janhq/core' export enum Settings { hfToken = 'hf-token', @@ -24,7 +24,7 @@ export default class DownloadManager extends BaseExtension { this.hfToken = await this.getSetting(Settings.hfToken, undefined) } - async onUnload() { } + async onUnload() {} async downloadFile( url: string, @@ -39,26 +39,36 @@ export default class DownloadManager extends BaseExtension { ) } + onSettingUpdate(key: string, value: T): void { + if (key === Settings.hfToken) { + this.hfToken = value as string + } + } + async downloadFiles( items: DownloadItem[], taskId: string, onProgress?: (transferred: number, total: number) => void ) { // relay tauri events to onProgress callback - const unlisten = await listen(`download-${taskId}`, (event) => { - if (onProgress) { - let payload = event.payload - onProgress(payload.transferred, payload.total) + const unlisten = await listen( + `download-${taskId}`, + (event) => { + if (onProgress) { + let payload = event.payload + onProgress(payload.transferred, payload.total) + } } - }) + ) try { - await invoke( - "download_files", - { items, taskId, headers: this._getHeaders() }, - ) + await invoke('download_files', { + items, + taskId, + headers: this._getHeaders(), + }) } catch (error) { - console.error("Error downloading task", taskId, error) + console.error('Error downloading task', taskId, error) throw error } finally { unlisten() @@ -67,16 +77,16 @@ export default class DownloadManager extends BaseExtension { async cancelDownload(taskId: string) { try { - await invoke("cancel_download_task", { taskId }) + await invoke('cancel_download_task', { taskId }) } catch (error) { - console.error("Error cancelling download:", error) + console.error('Error cancelling download:', error) throw error } } _getHeaders() { return { - ...(this.hfToken && { Authorization: `Bearer ${this.hfToken}` }) + ...(this.hfToken && { Authorization: `Bearer ${this.hfToken}` }), } } } diff --git a/web-app/src/hooks/useGeneralSetting.ts b/web-app/src/hooks/useGeneralSetting.ts index 6f4a36fa4..6d8a9e22e 100644 --- a/web-app/src/hooks/useGeneralSetting.ts +++ b/web-app/src/hooks/useGeneralSetting.ts @@ -1,11 +1,14 @@ import { create } from 'zustand' import { persist, createJSONStorage } from 'zustand/middleware' import { localStorageKey } from '@/constants/localStorage' +import { ExtensionManager } from '@/lib/extension' type LeftPanelStoreState = { currentLanguage: Language spellCheckChatInput: boolean experimentalFeatures: boolean + huggingfaceToken?: string + setHuggingfaceToken: (token: string) => void setExperimentalFeatures: (value: boolean) => void setSpellCheckChatInput: (value: boolean) => void setCurrentLanguage: (value: Language) => void @@ -17,9 +20,29 @@ export const useGeneralSetting = create()( currentLanguage: 'en', spellCheckChatInput: true, experimentalFeatures: false, + huggingfaceToken: undefined, setExperimentalFeatures: (value) => set({ experimentalFeatures: value }), setSpellCheckChatInput: (value) => set({ spellCheckChatInput: value }), setCurrentLanguage: (value) => set({ currentLanguage: value }), + setHuggingfaceToken: (token) => { + set({ huggingfaceToken: token }) + ExtensionManager.getInstance() + .getByName('@janhq/download-extension') + ?.getSettings() + .then((settings) => { + if (settings) { + const newSettings = settings.map((e) => { + if (e.key === 'hf-token') { + e.controllerProps.value = token + } + return e + }) + ExtensionManager.getInstance() + .getByName('@janhq/download-extension') + ?.updateSettings(newSettings) + } + }) + }, }), { name: localStorageKey.settingGeneral, diff --git a/web-app/src/locales/en/settings.json b/web-app/src/locales/en/settings.json index 66ce9e102..4eeb825d5 100644 --- a/web-app/src/locales/en/settings.json +++ b/web-app/src/locales/en/settings.json @@ -212,6 +212,8 @@ "factoryResetDesc": "This will reset all app settings to their defaults. This can't be undone. We only recommend this if the app is corrupted.", "cancel": "Cancel", "reset": "Reset", + "huggingfaceToken": "HuggingFace Token", + "huggingfaceTokenDesc": "Your HuggingFace API token for accessing models.", "resources": "Resources", "documentation": "Documentation", "documentationDesc": "Learn how to use Jan and explore its features.", diff --git a/web-app/src/routes/settings/general.tsx b/web-app/src/routes/settings/general.tsx index 68919e1a7..abcaa7da1 100644 --- a/web-app/src/routes/settings/general.tsx +++ b/web-app/src/routes/settings/general.tsx @@ -45,6 +45,7 @@ import { isDev } from '@/lib/utils' import { emit } from '@tauri-apps/api/event' import { stopAllModels } from '@/services/models' import { SystemEvent } from '@/types/events' +import { Input } from '@/components/ui/input' // eslint-disable-next-line @typescript-eslint/no-explicit-any export const Route = createFileRoute(route.settings.general as any)({ @@ -58,6 +59,8 @@ function General() { setSpellCheckChatInput, experimentalFeatures, setExperimentalFeatures, + huggingfaceToken, + setHuggingfaceToken, } = useGeneralSetting() const openFileTitle = (): string => { @@ -245,20 +248,6 @@ function General() { /> - {/* Advanced */} - - setExperimentalFeatures(e)} - /> - } - /> - - {/* Data folder */} - - {/* Other */} - + {/* Advanced */} + setSpellCheckChatInput(e)} + checked={experimentalFeatures} + onCheckedChange={(e) => setExperimentalFeatures(e)} /> } /> @@ -464,6 +448,41 @@ function General() { /> + {/* Other */} + + setSpellCheckChatInput(e)} + /> + } + /> + setHuggingfaceToken(e.target.value)} + placeholder={'hf_xxx'} + required + /> + } + /> + + {/* Resources */}