From 3bfcdf9c41c9a8311cb8c4b6a8a9bc5f05ce322d Mon Sep 17 00:00:00 2001 From: Eric R Date: Thu, 28 Sep 2023 06:10:22 -0400 Subject: [PATCH 01/13] [ADDED] MacOS detect --- app/utils.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/utils.ts b/app/utils.ts index 37c17dd76..67d008b93 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -173,3 +173,15 @@ export function autoGrowTextArea(dom: HTMLTextAreaElement) { export function getCSSVar(varName: string) { return getComputedStyle(document.body).getPropertyValue(varName).trim(); } + +/** + * Detects if the Operation system is MacOS + */ +export function isMacOS(): boolean { + if (window !== 'undefined') { + let userAgent = window?.navigator?.userAgent + if (userAgent.indexOf('Mac') != -1) return true + } + + return false +} From f3d5fc7a845aeba3dc120b46196dc3978c77faef Mon Sep 17 00:00:00 2001 From: Eric R Date: Thu, 28 Sep 2023 06:11:48 -0400 Subject: [PATCH 02/13] [FIXED] now the default key should be CMD on MacOS --- app/store/config.ts | 3 ++- app/utils.ts | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/store/config.ts b/app/store/config.ts index 956e5f3eb..53df36ec2 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -1,4 +1,5 @@ import { LLMModel } from "../client/api"; +import { isMacOS } from "../utils"; import { getClientConfig } from "../config/client"; import { DEFAULT_INPUT_TEMPLATE, @@ -27,7 +28,7 @@ export enum Theme { export const DEFAULT_CONFIG = { lastUpdate: Date.now(), // timestamp, to merge state - submitKey: SubmitKey.CtrlEnter as SubmitKey, + submitKey: isMacOS() ? SubmitKey.MetaEnter : SubmitKey.CtrlEnter, avatar: "1f603", fontSize: 14, theme: Theme.Auto as Theme, diff --git a/app/utils.ts b/app/utils.ts index 67d008b93..3db8e7c41 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -178,10 +178,10 @@ export function getCSSVar(varName: string) { * Detects if the Operation system is MacOS */ export function isMacOS(): boolean { - if (window !== 'undefined') { - let userAgent = window?.navigator?.userAgent - if (userAgent.indexOf('Mac') != -1) return true - } + if (typeof window !== "undefined") { + let userAgent = window?.navigator?.userAgent; + if (userAgent.indexOf("Mac") != -1) return true; + } - return false + return false; } From f1ca03e3788d89295f889eb67da270adbee6137f Mon Sep 17 00:00:00 2001 From: EricGit Date: Thu, 28 Sep 2023 13:21:17 -0400 Subject: [PATCH 03/13] [FIXED] now it should detects all macintosh --- app/utils.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 3db8e7c41..1b76285cc 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -175,13 +175,13 @@ export function getCSSVar(varName: string) { } /** - * Detects if the Operation system is MacOS + * Detects Macintosh */ export function isMacOS(): boolean { if (typeof window !== "undefined") { - let userAgent = window?.navigator?.userAgent; - if (userAgent.indexOf("Mac") != -1) return true; + let userAgent = window.navigator.userAgent.toLocaleLowerCase(); + const macintosh = /iphone|ipad|ipod|macintosh/.test(userAgent) + return !!macintosh } - - return false; + return false } From 4a599e986f1c56c3e3543e61b9403bdd01593c37 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Sat, 30 Sep 2023 22:16:34 +0700 Subject: [PATCH 04/13] UI Page [Auth Page] [+] feat(auth.tsx): add support for resetting access token in resetAccessCode function [+] fix(auth.tsx): fix formatting issue in resetAccessCode function [+] feat(locales): add support for sub tips in Auth component for multiple languages : - Add sub tips in Arabic locale (ar.ts) - Add sub tips in Bengali locale (bn.ts) - Add sub tips in Chinese locale (cn.ts) - Add sub tips in English locale (en.ts) - Add sub tips in Indonesian locale (id.ts) --- app/components/auth.tsx | 23 ++++++++++++++++++----- app/locales/ar.ts | 1 + app/locales/bn.ts | 1 + app/locales/cn.ts | 1 + app/locales/en.ts | 1 + app/locales/id.ts | 8 ++++++-- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/app/components/auth.tsx b/app/components/auth.tsx index 9a5b0c655..4e5ab8dc6 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -15,7 +15,7 @@ export function AuthPage() { const access = useAccessStore(); const goHome = () => navigate(Path.Home); - const resetAccessCode = () => access.updateCode(""); // Reset access code to empty string + const resetAccessCode = () => { access.updateCode(""); access.updateToken(""); }; // Reset access code to empty string useEffect(() => { if (getClientConfig()?.isApp) { @@ -42,6 +42,16 @@ export function AuthPage() { access.updateCode(e.currentTarget.value); }} /> +
{Locale.Auth.SubTips}
+ { + access.updateToken(e.currentTarget.value); + }} + />
- { - resetAccessCode(); - goHome(); - }} /> + { + resetAccessCode(); + goHome(); + }} + />
); diff --git a/app/locales/ar.ts b/app/locales/ar.ts index 520cb2635..d5844acd6 100644 --- a/app/locales/ar.ts +++ b/app/locales/ar.ts @@ -10,6 +10,7 @@ const ar: PartialLocaleType = { Auth: { Title: "تحتاج إلى رمز الوصول", Tips: "يرجى إدخال رمز الوصول أدناه", + SubTips: "أو أدخل مفتاح واجهة برمجة تطبيقات OpenAI الخاص بك", Input: "رمز الوصول", Confirm: "تأكيد", Later: "لاحقًا", diff --git a/app/locales/bn.ts b/app/locales/bn.ts index 2d2266b3f..2db132cec 100644 --- a/app/locales/bn.ts +++ b/app/locales/bn.ts @@ -10,6 +10,7 @@ const bn: PartialLocaleType = { Auth: { Title: "একটি অ্যাক্সেস কোড প্রয়োজন", Tips: "নীচে অ্যাক্সেস কোড ইনপুট করুন", + SubTips: "অথবা আপনার OpenAI API কী প্রবেশ করুন", Input: "অ্যাক্সেস কোড", Confirm: "নিশ্চিত করুন", Later: "পরে", diff --git a/app/locales/cn.ts b/app/locales/cn.ts index b2afc7534..8eeef9e01 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -13,6 +13,7 @@ const cn = { Auth: { Title: "需要密码", Tips: "管理员开启了密码验证,请在下方填入访问码", + SubTips: "或者输入你的 OpenAI API 密钥", Input: "在此处填写访问码", Confirm: "确认", Later: "稍后再说", diff --git a/app/locales/en.ts b/app/locales/en.ts index 697d09d1f..458d53dd5 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -15,6 +15,7 @@ const en: LocaleType = { Auth: { Title: "Need Access Code", Tips: "Please enter access code below", + SubTips: "Or enter your OpenAI API Key", Input: "access code", Confirm: "Confirm", Later: "Later", diff --git a/app/locales/id.ts b/app/locales/id.ts index 244c5ade1..4b61f6434 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -1,15 +1,19 @@ +import { getClientConfig } from "../config/client"; import { SubmitKey } from "../store/config"; import { PartialLocaleType } from "./index"; +const isApp = !!getClientConfig()?.isApp; const id: PartialLocaleType = { WIP: "Coming Soon...", Error: { - Unauthorized: - "Akses tidak diizinkan. Silakan [otorisasi](/#/auth) dengan memasukkan kode akses.", + Unauthorized: isApp + ? "Kunci API tidak valid, silakan periksa di halaman [Pengaturan](/#/settings)." + : "Akses tidak diizinkan, silakan masukkan kode akses di halaman [autentikasi](/#/auth), atau masukkan kunci API OpenAI Anda.", }, Auth: { Title: "Diperlukan Kode Akses", Tips: "Masukkan kode akses di bawah", + SubTips: "Atau masukkan kunci API OpenAI Anda", Input: "Kode Akses", Confirm: "Konfirmasi", Later: "Nanti", From bc00be9065a9ea1af8ab38925400f2bfd8dc10b3 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Sat, 30 Sep 2023 22:33:18 +0700 Subject: [PATCH 05/13] Feat & Fix UI Page [Auth Page] [+] feat(auth.tsx): add goChat function to navigate to chat page [+] fix(auth.tsx): change onClick event from goHome to goChat --- app/components/auth.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/auth.tsx b/app/components/auth.tsx index 4e5ab8dc6..8e2b964ab 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -15,6 +15,7 @@ export function AuthPage() { const access = useAccessStore(); const goHome = () => navigate(Path.Home); + const goChat = () => navigate(Path.Chat); const resetAccessCode = () => { access.updateCode(""); access.updateToken(""); }; // Reset access code to empty string useEffect(() => { @@ -57,7 +58,7 @@ export function AuthPage() { Date: Sat, 30 Sep 2023 22:59:24 +0700 Subject: [PATCH 06/13] Refactor Locale Indonesia [+] refactor(id.ts): remove unused import and isApp variable [+] fix(id.ts): update Unauthorized error message --- app/locales/id.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/locales/id.ts b/app/locales/id.ts index 4b61f6434..1036e66b6 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -1,15 +1,11 @@ -import { getClientConfig } from "../config/client"; import { SubmitKey } from "../store/config"; import { PartialLocaleType } from "./index"; -const isApp = !!getClientConfig()?.isApp; const id: PartialLocaleType = { WIP: "Coming Soon...", Error: { - Unauthorized: isApp - ? "Kunci API tidak valid, silakan periksa di halaman [Pengaturan](/#/settings)." - : "Akses tidak diizinkan, silakan masukkan kode akses di halaman [autentikasi](/#/auth), atau masukkan kunci API OpenAI Anda.", - }, + Unauthorized: "Akses tidak diizinkan, silakan masukkan kode akses atau masukkan kunci API OpenAI Anda. di halaman [autentikasi](/#/auth) atau di halaman [Pengaturan](/#/settings).", + }, Auth: { Title: "Diperlukan Kode Akses", Tips: "Masukkan kode akses di bawah", From 04b638aa064e346f72a6fcef295f151379c1be17 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Sun, 1 Oct 2023 00:23:19 +0700 Subject: [PATCH 07/13] Fix & Refactor UI Page [Auth Page] [+] fix(auth.tsx): fix conditional rendering of token input field [+] refactor(auth.tsx): improve code readability by using conditional rendering for token input field --- app/components/auth.tsx | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/app/components/auth.tsx b/app/components/auth.tsx index 8e2b964ab..b82d0e894 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -43,16 +43,20 @@ export function AuthPage() { access.updateCode(e.currentTarget.value); }} /> -
{Locale.Auth.SubTips}
- { - access.updateToken(e.currentTarget.value); - }} - /> + {!access.hideUserApiKey ? ( + <> +
{Locale.Auth.SubTips}
+ { + access.updateToken(e.currentTarget.value); + }} + /> + + ) : null}
Date: Tue, 3 Oct 2023 08:08:11 +0700 Subject: [PATCH 08/13] Client App [Notification] [+] feat(global.d.ts): add support for window.__TAURI__.notification methods [+] feat(update.ts): add notification for new version availability [+] fix(Cargo.toml): add tauri feature "notification-all" to enable notifications [+] fix(tauri.conf.json): enable all notification features in tauri configuration --- app/global.d.ts | 5 +++++ app/store/update.ts | 29 +++++++++++++++++++++++++++++ src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 6 ++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/app/global.d.ts b/app/global.d.ts index 524ce77db..dc1d52653 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -13,5 +13,10 @@ declare module "*.svg"; declare interface Window { __TAURI__?: { writeText(text: string): Promise; + notification:{ + requestPermission(): Promise; + isPermissionGranted(): Promise; + sendNotification(options: string | Options): void; + }; }; } diff --git a/app/store/update.ts b/app/store/update.ts index 42b86586c..facb57321 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -2,8 +2,10 @@ import { FETCH_COMMIT_URL, FETCH_TAG_URL, StoreKey } from "../constant"; import { api } from "../client/api"; import { getClientConfig } from "../config/client"; import { createPersistStore } from "../utils/store"; +import ChatGptIcon from "../icons/chatgpt.png"; const ONE_MINUTE = 60 * 1000; +const isApp = !!getClientConfig()?.isApp; function formatVersionDate(t: string) { const d = new Date(+t); @@ -80,6 +82,33 @@ export const useUpdateStore = createPersistStore( set(() => ({ remoteVersion: remoteId, })); + if (window.__TAURI__?.notification && isApp) { + // Check if notification permission is granted + await window.__TAURI__?.notification.isPermissionGranted().then((granted) => { + if (!granted) { + // Send a notification without waiting for permission (because we don't neeed a permisison once client is already click "check") + window.__TAURI__?.notification.sendNotification({ + title: "ChatGPT Next Web", + body: `A new version (${remoteId}) is available.`, + icon: `${ChatGptIcon.src}`, + sound: "Default" + }); + } else { + // Request permission to show notifications + window.__TAURI__?.notification.requestPermission().then((permission) => { + if (permission === 'granted') { + // Show a notification using Tauri + window.__TAURI__?.notification.sendNotification({ + title: "ChatGPT Next Web", + body: `A new version (${remoteId}) is available.`, + icon: `${ChatGptIcon.src}`, + sound: "Default" + }); + } + }); + } + }); + } console.log("[Got Upstream] ", remoteId); } catch (error) { console.error("[Fetch Upstream Commit Id]", error); diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ac5d04e83..fee1c860f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.3.0", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.3.0", features = ["clipboard-all", "dialog-all", "shell-open", "updater", "window-close", "window-hide", "window-maximize", "window-minimize", "window-set-icon", "window-set-ignore-cursor-events", "window-set-resizable", "window-show", "window-start-dragging", "window-unmaximize", "window-unminimize"] } +tauri = { version = "1.3.0", features = ["notification-all", "fs-all", "clipboard-all", "dialog-all", "shell-open", "updater", "window-close", "window-hide", "window-maximize", "window-minimize", "window-set-icon", "window-set-ignore-cursor-events", "window-set-resizable", "window-show", "window-start-dragging", "window-unmaximize", "window-unminimize"] } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } [features] diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 77b02a3ba..147fc9944 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -44,6 +44,12 @@ "startDragging": true, "unmaximize": true, "unminimize": true + }, + "fs": { + "all": true + }, + "notification": { + "all": true } }, "bundle": { From d2ad01a9ffd8fd0645013aca862c691af3c2f01f Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Tue, 3 Oct 2023 08:49:03 +0700 Subject: [PATCH 09/13] Client App Fix Issue [Bug] 'export' button does not work #2884 [+] fix(exporter.tsx): add async keyword to download function [+] feat(exporter.tsx): add support for saving image file using window.__TAURI__ API [+] feat(global.d.ts): add types for window.__TAURI__ API methods [+] feat(locales): add translations for download success and failure messages [+] feat(sync.ts): add support for generating backup file name with date and time [+] fix(utils.ts): add async keyword to downloadAs function and add support for saving file using window.__TAURI__ API --- app/components/exporter.tsx | 58 ++++++++++++++++++++++++++++--------- app/global.d.ts | 7 +++++ app/locales/cn.ts | 4 +++ app/locales/en.ts | 4 +++ app/locales/id.ts | 4 +++ app/store/sync.ts | 8 ++++- app/utils.ts | 43 ++++++++++++++++++++++----- 7 files changed, 106 insertions(+), 22 deletions(-) diff --git a/app/components/exporter.tsx b/app/components/exporter.tsx index 5b3e8a9a1..0a885d874 100644 --- a/app/components/exporter.tsx +++ b/app/components/exporter.tsx @@ -433,25 +433,55 @@ export function ImagePreviewer(props: { const isMobile = useMobileScreen(); - const download = () => { + const download = async () => { showToast(Locale.Export.Image.Toast); const dom = previewRef.current; if (!dom) return; - toPng(dom) - .then((blob) => { - if (!blob) return; - - if (isMobile || getClientConfig()?.isApp) { - showImageModal(blob); + + const isApp = getClientConfig()?.isApp; + + try { + const blob = await toPng(dom); + if (!blob) return; + + if (isMobile || (isApp && window.__TAURI__)) { + if (isApp && window.__TAURI__) { + const result = await window.__TAURI__.dialog.save({ + defaultPath: `${props.topic}.png`, + filters: [ + { + name: "PNG Files", + extensions: ["png"], + }, + { + name: "All Files", + extensions: ["*"], + }, + ], + }); + + if (result !== null) { + const response = await fetch(blob); + const buffer = await response.arrayBuffer(); + const uint8Array = new Uint8Array(buffer); + await window.__TAURI__.fs.writeBinaryFile(result, uint8Array); + showToast(Locale.Download.Success); + } else { + showToast(Locale.Download.Failed); + } } else { - const link = document.createElement("a"); - link.download = `${props.topic}.png`; - link.href = blob; - link.click(); - refreshPreview(); + showImageModal(blob); } - }) - .catch((e) => console.log("[Export Image] ", e)); + } else { + const link = document.createElement("a"); + link.download = `${props.topic}.png`; + link.href = blob; + link.click(); + refreshPreview(); + } + } catch (error) { + showToast(Locale.Download.Failed); + } }; const refreshPreview = () => { diff --git a/app/global.d.ts b/app/global.d.ts index dc1d52653..e0a2c3f06 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -13,6 +13,13 @@ declare module "*.svg"; declare interface Window { __TAURI__?: { writeText(text: string): Promise; + invoke(command: string, payload?: Record): Promise; + dialog: { + save(options?: Record): Promise; + }; + fs: { + writeBinaryFile(path: string, data: Uint8Array): Promise; + }; notification:{ requestPermission(): Promise; isPermissionGranted(): Promise; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index b2afc7534..746f3580b 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -323,6 +323,10 @@ const cn = { Success: "已写入剪切板", Failed: "复制失败,请赋予剪切板权限", }, + Download: { + Success: "内容已下载到您的目录。", + Failed: "下载失败。", + }, Context: { Toast: (x: any) => `包含 ${x} 条预设提示词`, Edit: "当前对话设置", diff --git a/app/locales/en.ts b/app/locales/en.ts index 697d09d1f..62823b051 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -329,6 +329,10 @@ const en: LocaleType = { Success: "Copied to clipboard", Failed: "Copy failed, please grant permission to access clipboard", }, + Download: { + Success: "Content downloaded to your directory.", + Failed: "Download failed.", + }, Context: { Toast: (x: any) => `With ${x} contextual prompts`, Edit: "Current Chat Settings", diff --git a/app/locales/id.ts b/app/locales/id.ts index 244c5ade1..7e1366f96 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -301,6 +301,10 @@ const id: PartialLocaleType = { Failed: "Gagal menyalin, mohon berikan izin untuk mengakses clipboard atau Clipboard API tidak didukung (Tauri)", }, + Download: { + Success: "Konten berhasil diunduh ke direktori Anda.", + Failed: "Unduhan gagal.", + }, Context: { Toast: (x: any) => `Dengan ${x} promp kontekstual`, Edit: "Pengaturan Obrolan Saat Ini", diff --git a/app/store/sync.ts b/app/store/sync.ts index c194162fc..c34ae7b9b 100644 --- a/app/store/sync.ts +++ b/app/store/sync.ts @@ -1,3 +1,4 @@ +import { getClientConfig } from "../config/client"; import { Updater } from "../typing"; import { ApiPath, STORAGE_KEY, StoreKey } from "../constant"; import { createPersistStore } from "../utils/store"; @@ -20,6 +21,7 @@ export interface WebDavConfig { password: string; } +const isApp = !!getClientConfig()?.isApp; export type SyncStore = GetStoreState; const DEFAULT_SYNC_STATE = { @@ -57,7 +59,11 @@ export const useSyncStore = createPersistStore( export() { const state = getLocalAppState(); - const fileName = `Backup-${new Date().toLocaleString()}.json`; + const datePart = isApp + ? `${new Date().toLocaleDateString().replace(/\//g, '_')} ${new Date().toLocaleTimeString().replace(/:/g, '_')}` + : new Date().toLocaleString(); + + const fileName = `Backup-${datePart}.json`; downloadAs(JSON.stringify(state), fileName); }, diff --git a/app/utils.ts b/app/utils.ts index 37c17dd76..19e55ce63 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -31,12 +31,41 @@ export async function copyToClipboard(text: string) { } } -export function downloadAs(text: string, filename: string) { - const element = document.createElement("a"); - element.setAttribute( - "href", - "data:text/plain;charset=utf-8," + encodeURIComponent(text), - ); +export async function downloadAs(text: string, filename: string) { + if (window.__TAURI__) { + const result = await window.__TAURI__.dialog.save({ + defaultPath: `${filename}`, + filters: [ + { + name: `${filename.split('.').pop()} files`, + extensions: [`${filename.split('.').pop()}`], + }, + { + name: "All Files", + extensions: ["*"], + }, + ], + }); + + if (result !== null) { + try { + await window.__TAURI__.fs.writeBinaryFile( + result, + new Uint8Array([...text].map((c) => c.charCodeAt(0))) + ); + showToast(Locale.Download.Success); + } catch (error) { + showToast(Locale.Download.Failed); + } + } else { + showToast(Locale.Download.Failed); + } + } else { + const element = document.createElement("a"); + element.setAttribute( + "href", + "data:text/plain;charset=utf-8," + encodeURIComponent(text), + ); element.setAttribute("download", filename); element.style.display = "none"; @@ -46,7 +75,7 @@ export function downloadAs(text: string, filename: string) { document.body.removeChild(element); } - +} export function readFromFile() { return new Promise((res, rej) => { const fileInput = document.createElement("input"); From ddfd05b008a80238eea870eba7e84e142dd74c47 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Tue, 3 Oct 2023 09:12:41 +0700 Subject: [PATCH 10/13] Fix & Feat Client App [Notification] [+] fix(update.ts): remove unnecessary notification sending when permission is not granted [+] feat(update.ts): add notification for already up to date version --- app/store/update.ts | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/app/store/update.ts b/app/store/update.ts index facb57321..5a08e36a3 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -86,24 +86,28 @@ export const useUpdateStore = createPersistStore( // Check if notification permission is granted await window.__TAURI__?.notification.isPermissionGranted().then((granted) => { if (!granted) { - // Send a notification without waiting for permission (because we don't neeed a permisison once client is already click "check") - window.__TAURI__?.notification.sendNotification({ - title: "ChatGPT Next Web", - body: `A new version (${remoteId}) is available.`, - icon: `${ChatGptIcon.src}`, - sound: "Default" - }); + return } else { // Request permission to show notifications window.__TAURI__?.notification.requestPermission().then((permission) => { if (permission === 'granted') { - // Show a notification using Tauri - window.__TAURI__?.notification.sendNotification({ - title: "ChatGPT Next Web", - body: `A new version (${remoteId}) is available.`, - icon: `${ChatGptIcon.src}`, - sound: "Default" - }); + if (version === remoteId) { + // Show a notification using Tauri + window.__TAURI__?.notification.sendNotification({ + title: "ChatGPT Next Web", + body: "Already up to date", + icon: `${ChatGptIcon.src}`, + sound: "Default" + }); + } else { + // Show a notification for the new version using Tauri + window.__TAURI__?.notification.sendNotification({ + title: "ChatGPT Next Web", + body: `A new version (${remoteId}) is available.`, + icon: `${ChatGptIcon.src}`, + sound: "Default" + }); + } } }); } From b558d1afc6a95d917500064bb77870864ccc1958 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Wed, 4 Oct 2023 02:10:26 +0700 Subject: [PATCH 11/13] Feat & Fix "Client App [Notification]" [+] feat(update.ts): add support for localization in update notifications [+] fix(update.ts): add missing semicolon in useUpdateStore function --- app/store/update.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/store/update.ts b/app/store/update.ts index 5a08e36a3..2b088a13d 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -3,6 +3,7 @@ import { api } from "../client/api"; import { getClientConfig } from "../config/client"; import { createPersistStore } from "../utils/store"; import ChatGptIcon from "../icons/chatgpt.png"; +import Locale from "../locales"; const ONE_MINUTE = 60 * 1000; const isApp = !!getClientConfig()?.isApp; @@ -86,7 +87,7 @@ export const useUpdateStore = createPersistStore( // Check if notification permission is granted await window.__TAURI__?.notification.isPermissionGranted().then((granted) => { if (!granted) { - return + return; } else { // Request permission to show notifications window.__TAURI__?.notification.requestPermission().then((permission) => { @@ -95,15 +96,16 @@ export const useUpdateStore = createPersistStore( // Show a notification using Tauri window.__TAURI__?.notification.sendNotification({ title: "ChatGPT Next Web", - body: "Already up to date", + body: `${Locale.Settings.Update.IsLatest}`, icon: `${ChatGptIcon.src}`, sound: "Default" }); } else { + const updateMessage = Locale.Settings.Update.FoundUpdate(`${remoteId}`); // Show a notification for the new version using Tauri window.__TAURI__?.notification.sendNotification({ title: "ChatGPT Next Web", - body: `A new version (${remoteId}) is available.`, + body: updateMessage, icon: `${ChatGptIcon.src}`, sound: "Default" }); From 88f8c43472db225184287640fb09eae9aa122b3f Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Tue, 3 Oct 2023 21:09:41 +0800 Subject: [PATCH 12/13] Improve tw locale --- app/locales/tw.ts | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 15f6648e6..e9f38d097 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -7,13 +7,13 @@ const tw: PartialLocaleType = { Unauthorized: "目前您的狀態是未授權,請前往[設定頁面](/#/auth)輸入授權碼。", }, ChatItem: { - ChatItemCount: (count: number) => `${count} 條對話`, + ChatItemCount: (count: number) => `${count} 則對話`, }, Chat: { - SubTitle: (count: number) => `您已經與 ChatGPT 進行了 ${count} 條對話`, + SubTitle: (count: number) => `您已經與 ChatGPT 進行了 ${count} 則對話`, Actions: { - ChatList: "查看訊息列表", - CompressedHistory: "查看壓縮後的歷史 Prompt", + ChatList: "檢視訊息列表", + CompressedHistory: "檢視壓縮後的歷史 Prompt", Export: "匯出聊天紀錄", Copy: "複製", Stop: "停止", @@ -23,15 +23,15 @@ const tw: PartialLocaleType = { Rename: "重新命名對話", Typing: "正在輸入…", Input: (submitKey: string) => { - var inputHints = `輸入訊息後,按下 ${submitKey} 鍵即可發送`; + var inputHints = `輸入訊息後,按下 ${submitKey} 鍵即可傳送`; if (submitKey === String(SubmitKey.Enter)) { inputHints += ",Shift + Enter 鍵換行"; } return inputHints; }, - Send: "發送", + Send: "傳送", Config: { - Reset: "重置預設", + Reset: "重設", SaveAs: "另存新檔", }, }, @@ -46,7 +46,7 @@ const tw: PartialLocaleType = { Title: "上下文記憶 Prompt", EmptyContent: "尚未記憶", Copy: "複製全部", - Send: "發送記憶", + Send: "傳送記憶", Reset: "重設對話", ResetConfirm: "重設後將清除目前對話記錄以及歷史記憶,確認重設?", }, @@ -71,22 +71,22 @@ const tw: PartialLocaleType = { }, InjectSystemPrompts: { Title: "匯入系統提示", - SubTitle: "強制在每個請求的訊息列表開頭添加一個模擬 ChatGPT 的系統提示", + SubTitle: "強制在每個請求的訊息列表開頭新增一個模擬 ChatGPT 的系統提示", }, Update: { - Version: (x: string) => `當前版本:${x}`, + Version: (x: string) => `目前版本:${x}`, IsLatest: "已是最新版本", CheckUpdate: "檢查更新", IsChecking: "正在檢查更新...", FoundUpdate: (x: string) => `發現新版本:${x}`, GoToUpdate: "前往更新", }, - SendKey: "發送鍵", + SendKey: "傳送鍵", Theme: "主題", TightBorder: "緊湊邊框", SendPreviewBubble: { Title: "預覽氣泡", - SubTitle: "在預覽氣泡中預覽 Markdown 内容", + SubTitle: "在預覽氣泡中預覽 Markdown 內容", }, Mask: { Splash: { @@ -101,7 +101,7 @@ const tw: PartialLocaleType = { }, List: "自定義提示詞列表", ListCount: (builtin: number, custom: number) => - `內建 ${builtin} 條,用戶定義 ${custom} 條`, + `內建 ${builtin} 條,使用者定義 ${custom} 條`, Edit: "編輯", Modal: { Title: "提示詞列表", @@ -132,7 +132,7 @@ const tw: PartialLocaleType = { }, IsChecking: "正在檢查…", Check: "重新檢查", - NoAccess: "輸入API Key查看餘額", + NoAccess: "輸入 API Key 檢視餘額", }, AccessCode: { Title: "授權碼", @@ -150,7 +150,7 @@ const tw: PartialLocaleType = { }, PresencePenalty: { Title: "話題新穎度 (presence_penalty)", - SubTitle: "值越大,越有可能擴展到新話題", + SubTitle: "值越大,越有可能拓展到新話題", }, FrequencyPenalty: { Title: "頻率懲罰度 (frequency_penalty)", @@ -163,7 +163,7 @@ const tw: PartialLocaleType = { Error: "出錯了,請稍後再嘗試", Prompt: { History: (content: string) => - "這是 AI 與用戶的歷史聊天總結,作為前情提要:" + content, + "這是 AI 與使用者的歷史聊天總結,作為前情提要:" + content, Topic: "Use the language used by the user (e.g. en for english conversation, zh-hant for chinese conversation, etc.) to generate a title (at most 6 words) summarizing our conversation without any lead-in, quotation marks, preamble like 'Title:', direct text copies, single-word replies, quotation marks, translations, or brackets. Remove enclosing quotation marks. The title should make third-party grasp the essence of the conversation in first sight.", Summarize: @@ -192,16 +192,16 @@ const tw: PartialLocaleType = { Item: { Info: (count: number) => `包含 ${count} 條預設對話`, Chat: "對話", - View: "查看", + View: "檢視", Edit: "編輯", - Delete: "删除", - DeleteConfirm: "確認删除?", + Delete: "刪除", + DeleteConfirm: "確認刪除?", }, EditModal: { Title: (readonly: boolean) => - `編輯預設面具 ${readonly ? "(只读)" : ""}`, + `編輯預設面具 ${readonly ? "(只讀)" : ""}`, Download: "下載預設", - Clone: "克隆預設", + Clone: "複製預設", }, Config: { Avatar: "角色頭像", @@ -215,7 +215,7 @@ const tw: PartialLocaleType = { SubTitle: "現在開始,與面具背後的靈魂思維碰撞", More: "搜尋更多", NotShow: "不再呈現", - ConfirmNoShow: "確認禁用?禁用後可以随時在設定中重新啟用。", + ConfirmNoShow: "確認停用?停用後可以隨時在設定中重新啟用。", }, UI: { Confirm: "確認", From e35c807216a3813cd902dc3c2cf20b818c639242 Mon Sep 17 00:00:00 2001 From: Yifei Zhang Date: Sat, 7 Oct 2023 23:48:50 +0800 Subject: [PATCH 13/13] Update tauri.conf.json --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 77b02a3ba..8161e79e8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "ChatGPT Next Web", - "version": "2.9.7" + "version": "2.9.8" }, "tauri": { "allowlist": {