From 86ee87ac225f8af3549d2295b90c6a5c1cfd40b4 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Sun, 8 Oct 2023 22:36:49 +0700 Subject: [PATCH 1/7] Client App [Tauri Updater] [+] feat(global.d.ts): add updater interface to the Window interface [+] feat(cn.ts): add success and failed translations for update [+] feat(en.ts): add success and failed translations for update [+] feat(id.ts): add success and failed translations for update [+] feat(update.ts): add logic to check and install updates, and show toast messages for success and failure [+] fix(tauri.conf.json): enable dialog for Tauri updater --- app/global.d.ts | 5 +++++ app/locales/cn.ts | 2 ++ app/locales/en.ts | 2 ++ app/locales/id.ts | 2 ++ app/store/update.ts | 11 +++++++++++ src-tauri/tauri.conf.json | 2 +- 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/global.d.ts b/app/global.d.ts index e0a2c3f0686..ef60e3d8e1a 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -25,5 +25,10 @@ declare interface Window { isPermissionGranted(): Promise; sendNotification(options: string | Options): void; }; + updater: { + checkUpdate(): Promise; + installUpdate(): Promise; + onUpdaterEvent(handler: (status: UpdateStatusResult) => void): Promise; + }; }; } diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 4cd963fb8e2..96d9d335a33 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -167,6 +167,8 @@ const cn = { IsChecking: "正在检查更新...", FoundUpdate: (x: string) => `发现新版本:${x}`, GoToUpdate: "前往更新", + Success: "更新成功。", + Failed: "更新失败。", }, SendKey: "发送键", Theme: "主题", diff --git a/app/locales/en.ts b/app/locales/en.ts index 928c4b72d4e..54514d86753 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -169,6 +169,8 @@ const en: LocaleType = { IsChecking: "Checking update...", FoundUpdate: (x: string) => `Found new version: ${x}`, GoToUpdate: "Update", + Success: "Update Succesfull.", + Failed: "Update Failed.", }, SendKey: "Send Key", Theme: "Theme", diff --git a/app/locales/id.ts b/app/locales/id.ts index b5e4a70b751..95cbd039aa1 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -156,6 +156,8 @@ const id: PartialLocaleType = { IsChecking: "Memeriksa pembaruan...", FoundUpdate: (x: string) => `Versi terbaru ditemukan: ${x}`, GoToUpdate: "Perbarui Sekarang", + Success: "Pembaruan Berhasil.", + Failed: "Pembaruan Gagal.", }, AutoGenerateTitle: { Title: "Hasilkan Judul Otomatis", diff --git a/app/store/update.ts b/app/store/update.ts index 2b088a13d7a..d423b4ae050 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -4,6 +4,7 @@ import { getClientConfig } from "../config/client"; import { createPersistStore } from "../utils/store"; import ChatGptIcon from "../icons/chatgpt.png"; import Locale from "../locales"; +import { showToast } from "../components/ui-lib"; const ONE_MINUTE = 60 * 1000; const isApp = !!getClientConfig()?.isApp; @@ -109,6 +110,16 @@ export const useUpdateStore = createPersistStore( icon: `${ChatGptIcon.src}`, sound: "Default" }); + // this a wild for updating client app + window.__TAURI__?.updater.checkUpdate().then((updateResult) => { + if (updateResult.status === "DONE") { + window.__TAURI__?.updater.installUpdate(); + showToast(Locale.Settings.Update.Success); + } + }).catch((e) => { + console.error("[Check Update Error]", e); + showToast(Locale.Settings.Update.Failed); + }); } } }); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 68f9c07c037..3e90120d420 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -93,7 +93,7 @@ "endpoints": [ "https://github.com/Yidadaa/ChatGPT-Next-Web/releases/latest/download/latest.json" ], - "dialog": false, + "dialog": true, "windows": { "installMode": "passive" }, From e27797fa90b71889092ec3081a6ed1f64493dc90 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Mon, 9 Oct 2023 01:07:33 +0700 Subject: [PATCH 2/7] Client App [Tauri] [Dev Stuff] [+] feat(global.d.ts): add support for opening dialog, displaying message, and asking for confirmation --- app/global.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/global.d.ts b/app/global.d.ts index ef60e3d8e1a..c7626a21434 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -16,6 +16,10 @@ declare interface Window { invoke(command: string, payload?: Record): Promise; dialog: { save(options?: Record): Promise; + open(options?: OpenDialogOptions): Promise; + // support locale language + message(message: string, options?: string | MessageDialogOptions): Promise; + ask(message: string, options?: string | ConfirmDialogOptions): Promise; }; fs: { writeBinaryFile(path: string, data: Uint8Array): Promise; From faf9cd70af21767a9be81aea4db017e1f9690168 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Mon, 9 Oct 2023 21:49:34 +0700 Subject: [PATCH 3/7] Client App [Tauri] [Dev Stuff] [+] chore(global.d.ts): add http module to global declaration file --- app/global.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/global.d.ts b/app/global.d.ts index c7626a21434..a7f44b53298 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -34,5 +34,10 @@ declare interface Window { installUpdate(): Promise; onUpdaterEvent(handler: (status: UpdateStatusResult) => void): Promise; }; + // can do route in client app like CORS fetch, currently is not enabled yet only module added. + http: { + fetch(url: string, options?: FetchOptions): Promise>; + getClient(options?: ClientOptions): Promise + }; }; } From 6633dfc0e8e06947db23db5b731f3b4c6fbdf713 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Tue, 10 Oct 2023 03:37:37 +0700 Subject: [PATCH 4/7] Chroe Client App [Tauri] [Dev Stuff] This Chroe Commits faf9cd70af21767a9be81aea4db017e1f9690168. [+] chore(global.d.ts): add missing semicolon in the declaration of `getClient` function --- app/global.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/global.d.ts b/app/global.d.ts index a7f44b53298..eb0ab025197 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -37,7 +37,7 @@ declare interface Window { // can do route in client app like CORS fetch, currently is not enabled yet only module added. http: { fetch(url: string, options?: FetchOptions): Promise>; - getClient(options?: ClientOptions): Promise + getClient(options?: ClientOptions): Promise; }; }; } From b5d921c9b23a70837c190460c263e6d1c01c393d Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Tue, 10 Oct 2023 04:19:51 +0700 Subject: [PATCH 5/7] Feat Client App [Tauri Updater] [+] feat(settings.tsx): add support for checking and installing updates using Tauri updater [+] fix(update.ts): remove showToast call after installing update --- app/components/settings.tsx | 25 ++++++++++++++++++++++--- app/store/update.ts | 1 - 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 8ed6b77383c..4b4ce652677 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -683,9 +683,28 @@ export function Settings() { {checkingUpdate ? ( ) : hasNewVersion ? ( - - {Locale.Settings.Update.GoToUpdate} - + <> + {clientConfig?.isApp ? ( + } + text={Locale.Settings.Update.GoToUpdate} + onClick={() => { + window.__TAURI__?.updater.checkUpdate().then((updateResult) => { + if (updateResult.status === "DONE") { + window.__TAURI__?.updater.installUpdate(); + } + }).catch((e) => { + console.error("[Check Update Error]", e); + showToast(Locale.Settings.Update.Failed); + }); + }} + /> + ) : ( + + {Locale.Settings.Update.GoToUpdate} + + )} + ) : ( } diff --git a/app/store/update.ts b/app/store/update.ts index d423b4ae050..fb5805a6c1e 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -114,7 +114,6 @@ export const useUpdateStore = createPersistStore( window.__TAURI__?.updater.checkUpdate().then((updateResult) => { if (updateResult.status === "DONE") { window.__TAURI__?.updater.installUpdate(); - showToast(Locale.Settings.Update.Success); } }).catch((e) => { console.error("[Check Update Error]", e); From 7c8cfaad9ef8b92061c54456a85668406cbadb71 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Tue, 10 Oct 2023 04:58:17 +0700 Subject: [PATCH 6/7] Fix & Feat Client App [Tauri Updater] [Settings Page] [+] fix(settings.tsx): refactor update logic into a separate function and download icon and text for update button [+] feat(settings.tsx): add error handling for update check and display toast message --- app/components/settings.tsx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 4b4ce652677..43bc4db7a40 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -565,6 +565,14 @@ export function Settings() { setCheckingUpdate(true); updateStore.getLatestVersion(force).then(() => { setCheckingUpdate(false); + window.__TAURI__?.updater.checkUpdate().then((updateResult) => { + if (updateResult.status === "DONE") { + window.__TAURI__?.updater.installUpdate(); + } + }).catch((e) => { + console.error("[Check Update Error]", e); + showToast(Locale.Settings.Update.Failed); + }); }); console.log("[Update] local version ", updateStore.version); @@ -686,18 +694,9 @@ export function Settings() { <> {clientConfig?.isApp ? ( } + icon={} text={Locale.Settings.Update.GoToUpdate} - onClick={() => { - window.__TAURI__?.updater.checkUpdate().then((updateResult) => { - if (updateResult.status === "DONE") { - window.__TAURI__?.updater.installUpdate(); - } - }).catch((e) => { - console.error("[Check Update Error]", e); - showToast(Locale.Settings.Update.Failed); - }); - }} + onClick={() => checkUpdate(true)} /> ) : ( From 1aa658bec42bcbfe177606d8469e379f824b12c2 Mon Sep 17 00:00:00 2001 From: H0llyW00dzZ Date: Tue, 10 Oct 2023 13:42:27 +0700 Subject: [PATCH 7/7] Client App [Restart] [Chat Commands] Note : This Runtime `Edge` [+] feat(command.ts): add support for restart command in chat commands [+] fix(command.ts): remove restart command from chat commands if not running in app environment [+] feat(chat.tsx): add restart command functionality to restart the client [+] feat(global.d.ts): add relaunch method to process object in window interface [+] feat(locales): add translations for restart command in English, Chinese, and Indonesian --- app/command.ts | 16 +++++++++++++--- app/components/chat.tsx | 1 + app/global.d.ts | 3 +++ app/locales/cn.ts | 1 + app/locales/en.ts | 1 + app/locales/id.ts | 1 + 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/app/command.ts b/app/command.ts index e515e5f0bb4..fc349bfe201 100644 --- a/app/command.ts +++ b/app/command.ts @@ -1,6 +1,9 @@ import { useEffect } from "react"; import { useSearchParams } from "react-router-dom"; import Locale from "./locales"; +import { getClientConfig } from "@/app/config/client"; + +const isApp = !!getClientConfig()?.isApp; type Command = (param: string) => void; interface Commands { @@ -37,6 +40,7 @@ interface ChatCommands { newm?: Command; next?: Command; prev?: Command; + restart?: Command; clear?: Command; del?: Command; } @@ -44,6 +48,12 @@ interface ChatCommands { export const ChatCommandPrefix = ":"; export function useChatCommand(commands: ChatCommands = {}) { + const chatCommands = { ...commands }; + + if (!isApp) { + delete chatCommands.restart; + } + function extract(userInput: string) { return ( userInput.startsWith(ChatCommandPrefix) ? userInput.slice(1) : userInput @@ -53,7 +63,7 @@ export function useChatCommand(commands: ChatCommands = {}) { function search(userInput: string) { const input = extract(userInput); const desc = Locale.Chat.Commands; - return Object.keys(commands) + return Object.keys(chatCommands) .filter((c) => c.startsWith(input)) .map((c) => ({ title: desc[c as keyof ChatCommands], @@ -63,11 +73,11 @@ export function useChatCommand(commands: ChatCommands = {}) { function match(userInput: string) { const command = extract(userInput); - const matched = typeof commands[command] === "function"; + const matched = typeof chatCommands[command] === "function"; return { matched, - invoke: () => matched && commands[command]!(userInput), + invoke: () => matched && chatCommands[command]!(userInput), }; } diff --git a/app/components/chat.tsx b/app/components/chat.tsx index cca096eb874..f89a888270d 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -657,6 +657,7 @@ function _Chat() { newm: () => navigate(Path.NewChat), prev: () => chatStore.nextSession(-1), next: () => chatStore.nextSession(1), + restart: () => window.__TAURI__?.process.relaunch(), clear: () => chatStore.updateCurrentSession( (session) => (session.clearContextIndex = session.messages.length), diff --git a/app/global.d.ts b/app/global.d.ts index eb0ab025197..29dc0faf431 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -24,6 +24,9 @@ declare interface Window { fs: { writeBinaryFile(path: string, data: Uint8Array): Promise; }; + process: { + relaunch(): Promise; + }; notification:{ requestPermission(): Promise; isPermissionGranted(): Promise; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 96d9d335a33..84b5f6e77c9 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -48,6 +48,7 @@ const cn = { newm: "从面具新建聊天", next: "下一个聊天", prev: "上一个聊天", + restart: "重新启动客户端", clear: "清除上下文", del: "删除聊天", }, diff --git a/app/locales/en.ts b/app/locales/en.ts index 54514d86753..17992ffa720 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -50,6 +50,7 @@ const en: LocaleType = { newm: "Start a new chat with mask", next: "Next Chat", prev: "Previous Chat", + restart: "Restart a client", clear: "Clear Context", del: "Delete Chat", }, diff --git a/app/locales/id.ts b/app/locales/id.ts index 95cbd039aa1..9af946f8cdf 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -37,6 +37,7 @@ const id: PartialLocaleType = { newm: "Mulai Chat Baru dengan Masks", next: "Chat Selanjutnya", prev: "Chat Sebelumnya", + restart: "Restart klien", clear: "Bersihkan Percakapan", del: "Hapus Chat", },