Compare commits

...

24 Commits

Author SHA1 Message Date
Yifei Zhang
13c1d2fd2b Merge pull request #2946 from H0llyW00dzZ/ClientApp 2023-10-07 23:50:49 +08:00
Yifei Zhang
e35c807216 Update tauri.conf.json 2023-10-07 23:48:50 +08:00
Yifei Zhang
5a2cc6f154 Merge pull request #2927 from lifeeric/MACOS 2023-10-07 23:10:43 +08:00
Yifei Zhang
ef3e8e6fac Merge pull request #2933 from H0llyW00dzZ/authpage 2023-10-07 23:03:56 +08:00
H0llyW00dzZ
b558d1afc6 Feat & Fix "Client App [Notification]"
[+] feat(update.ts): add support for localization in update notifications
[+] fix(update.ts): add missing semicolon in useUpdateStore function
2023-10-04 02:10:26 +07:00
H0llyW00dzZ
ddfd05b008 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
2023-10-03 09:12:41 +07:00
H0llyW00dzZ
d2ad01a9ff 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
2023-10-03 08:49:03 +07:00
H0llyW00dzZ
64a17abfe2 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
2023-10-03 08:08:11 +07:00
H0llyW00dzZ
04b638aa06 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
2023-10-01 00:23:19 +07:00
H0llyW00dzZ
31e30906d0 Refactor Locale Indonesia
[+] refactor(id.ts): remove unused import and isApp variable
[+] fix(id.ts): update Unauthorized error message
2023-09-30 22:59:24 +07:00
H0llyW00dzZ
bc00be9065 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
2023-09-30 22:33:18 +07:00
H0llyW00dzZ
4a599e986f 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)
2023-09-30 22:16:34 +07:00
EricGit
f1ca03e378 [FIXED] now it should detects all macintosh 2023-09-28 13:21:17 -04:00
Eric R
f3d5fc7a84 [FIXED] now the default key should be CMD on MacOS 2023-09-28 06:50:31 -04:00
Eric R
3bfcdf9c41 [ADDED] MacOS detect 2023-09-28 06:10:22 -04:00
Yifei Zhang
144200e315 Merge pull request #2912 from Algorithm5838/Algorithm5838-patch-1 2023-09-27 17:18:15 +08:00
Algorithm5838
398e229c77 Update chat.tsx 2023-09-26 21:49:17 +03:00
Algorithm5838
6a61fe5776 Update chat.tsx 2023-09-26 20:45:09 +03:00
Yifei Zhang
9835206452 Merge pull request #2905 from H0llyW00dzZ/ref#2895 2023-09-26 10:50:49 +08:00
H0llyW00dzZ
70b0580fb7 UI Page [sidebar]
[+] fix(sidebar.tsx): update onClick function to conditionally navigate to different paths based on config.dontShowMaskSplashScreen value

Ref : [Feature] Make the mask selection more streamlined Yidadaa#2895
2023-09-26 04:59:19 +07:00
Yifei Zhang
23eb7732d7 feat: support more http status check for webdav 2023-09-20 17:47:35 +08:00
Yifei Zhang
26e50cefea Update chat.tsx 2023-09-20 02:09:14 +08:00
Yifei Zhang
588e907181 Merge pull request #2873 from Yidadaa/bugfix-0919 2023-09-19 23:42:09 +08:00
Yidadaa
eae7d6260f fix: should not tight border in desktop app 2023-09-19 23:26:52 +08:00
18 changed files with 224 additions and 44 deletions

View File

@@ -15,7 +15,8 @@ export function AuthPage() {
const access = useAccessStore(); const access = useAccessStore();
const goHome = () => navigate(Path.Home); const goHome = () => navigate(Path.Home);
const resetAccessCode = () => access.updateCode(""); // Reset access code to empty string const goChat = () => navigate(Path.Chat);
const resetAccessCode = () => { access.updateCode(""); access.updateToken(""); }; // Reset access code to empty string
useEffect(() => { useEffect(() => {
if (getClientConfig()?.isApp) { if (getClientConfig()?.isApp) {
@@ -42,17 +43,34 @@ export function AuthPage() {
access.updateCode(e.currentTarget.value); access.updateCode(e.currentTarget.value);
}} }}
/> />
{!access.hideUserApiKey ? (
<>
<div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div>
<input
className={styles["auth-input"]}
type="password"
placeholder={Locale.Settings.Token.Placeholder}
value={access.token}
onChange={(e) => {
access.updateToken(e.currentTarget.value);
}}
/>
</>
) : null}
<div className={styles["auth-actions"]}> <div className={styles["auth-actions"]}>
<IconButton <IconButton
text={Locale.Auth.Confirm} text={Locale.Auth.Confirm}
type="primary" type="primary"
onClick={goHome} onClick={goChat}
/>
<IconButton
text={Locale.Auth.Later}
onClick={() => {
resetAccessCode();
goHome();
}}
/> />
<IconButton text={Locale.Auth.Later} onClick={() => {
resetAccessCode();
goHome();
}} />
</div> </div>
</div> </div>
); );

View File

@@ -937,7 +937,7 @@ function _Chat() {
const isTouchTopEdge = e.scrollTop <= edgeThreshold; const isTouchTopEdge = e.scrollTop <= edgeThreshold;
const isTouchBottomEdge = bottomHeight >= e.scrollHeight - edgeThreshold; const isTouchBottomEdge = bottomHeight >= e.scrollHeight - edgeThreshold;
const isHitBottom = const isHitBottom =
bottomHeight >= e.scrollHeight - (isMobileScreen ? 0 : 10); bottomHeight >= e.scrollHeight - (isMobileScreen ? 4 : 10);
const prevPageMsgIndex = msgRenderIndex - CHAT_PAGE_SIZE; const prevPageMsgIndex = msgRenderIndex - CHAT_PAGE_SIZE;
const nextPageMsgIndex = msgRenderIndex + CHAT_PAGE_SIZE; const nextPageMsgIndex = msgRenderIndex + CHAT_PAGE_SIZE;
@@ -1155,7 +1155,13 @@ function _Chat() {
{isUser ? ( {isUser ? (
<Avatar avatar={config.avatar} /> <Avatar avatar={config.avatar} />
) : ( ) : (
<MaskAvatar mask={session.mask} /> <>
{["system"].includes(message.role) ? (
<Avatar avatar="2699-fe0f" />
) : (
<MaskAvatar mask={session.mask} />
)}
</>
)} )}
</div> </div>

View File

@@ -433,25 +433,55 @@ export function ImagePreviewer(props: {
const isMobile = useMobileScreen(); const isMobile = useMobileScreen();
const download = () => { const download = async () => {
showToast(Locale.Export.Image.Toast); showToast(Locale.Export.Image.Toast);
const dom = previewRef.current; const dom = previewRef.current;
if (!dom) return; if (!dom) return;
toPng(dom)
.then((blob) => { const isApp = getClientConfig()?.isApp;
if (!blob) return;
try {
if (isMobile || getClientConfig()?.isApp) { const blob = await toPng(dom);
showImageModal(blob); 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 { } else {
const link = document.createElement("a"); showImageModal(blob);
link.download = `${props.topic}.png`;
link.href = blob;
link.click();
refreshPreview();
} }
}) } else {
.catch((e) => console.log("[Export Image] ", e)); const link = document.createElement("a");
link.download = `${props.topic}.png`;
link.href = blob;
link.click();
refreshPreview();
}
} catch (error) {
showToast(Locale.Download.Failed);
}
}; };
const refreshPreview = () => { const refreshPreview = () => {

View File

@@ -115,7 +115,10 @@ const loadAsyncGoogleFont = () => {
getClientConfig()?.buildMode === "export" ? remoteFontUrl : proxyFontUrl; getClientConfig()?.buildMode === "export" ? remoteFontUrl : proxyFontUrl;
linkEl.rel = "stylesheet"; linkEl.rel = "stylesheet";
linkEl.href = linkEl.href =
googleFontUrl + "/css2?family=" + encodeURIComponent("Noto Sans:wght@300;400;700;900") + "&display=swap"; googleFontUrl +
"/css2?family=" +
encodeURIComponent("Noto Sans:wght@300;400;700;900") +
"&display=swap";
document.head.appendChild(linkEl); document.head.appendChild(linkEl);
}; };
@@ -125,6 +128,8 @@ function Screen() {
const isHome = location.pathname === Path.Home; const isHome = location.pathname === Path.Home;
const isAuth = location.pathname === Path.Auth; const isAuth = location.pathname === Path.Auth;
const isMobileScreen = useMobileScreen(); const isMobileScreen = useMobileScreen();
const shouldTightBorder =
config.tightBorder && !isMobileScreen && !getClientConfig()?.isApp;
useEffect(() => { useEffect(() => {
loadAsyncGoogleFont(); loadAsyncGoogleFont();
@@ -134,11 +139,9 @@ function Screen() {
<div <div
className={ className={
styles.container + styles.container +
` ${ ` ${shouldTightBorder ? styles["tight-container"] : styles.container} ${
config.tightBorder && !isMobileScreen getLang() === "ar" ? styles["rtl-screen"] : ""
? styles["tight-container"] }`
: styles.container
} ${getLang() === "ar" ? styles["rtl-screen"] : ""}`
} }
> >
{isAuth ? ( {isAuth ? (

View File

@@ -160,7 +160,13 @@ export function SideBar(props: { className?: string }) {
icon={<MaskIcon />} icon={<MaskIcon />}
text={shouldNarrow ? undefined : Locale.Mask.Name} text={shouldNarrow ? undefined : Locale.Mask.Name}
className={styles["sidebar-bar-button"]} className={styles["sidebar-bar-button"]}
onClick={() => navigate(Path.NewChat, { state: { fromHome: true } })} onClick={() => {
if (config.dontShowMaskSplashScreen !== true) {
navigate(Path.NewChat, { state: { fromHome: true } });
} else {
navigate(Path.Masks, { state: { fromHome: true } });
}
}}
shadow shadow
/> />
<IconButton <IconButton

12
app/global.d.ts vendored
View File

@@ -13,5 +13,17 @@ declare module "*.svg";
declare interface Window { declare interface Window {
__TAURI__?: { __TAURI__?: {
writeText(text: string): Promise<void>; writeText(text: string): Promise<void>;
invoke(command: string, payload?: Record<string, unknown>): Promise<any>;
dialog: {
save(options?: Record<string, unknown>): Promise<string | null>;
};
fs: {
writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
};
notification:{
requestPermission(): Promise<Permission>;
isPermissionGranted(): Promise<boolean>;
sendNotification(options: string | Options): void;
};
}; };
} }

View File

@@ -10,6 +10,7 @@ const ar: PartialLocaleType = {
Auth: { Auth: {
Title: "تحتاج إلى رمز الوصول", Title: "تحتاج إلى رمز الوصول",
Tips: "يرجى إدخال رمز الوصول أدناه", Tips: "يرجى إدخال رمز الوصول أدناه",
SubTips: "أو أدخل مفتاح واجهة برمجة تطبيقات OpenAI الخاص بك",
Input: "رمز الوصول", Input: "رمز الوصول",
Confirm: "تأكيد", Confirm: "تأكيد",
Later: "لاحقًا", Later: "لاحقًا",

View File

@@ -10,6 +10,7 @@ const bn: PartialLocaleType = {
Auth: { Auth: {
Title: "একটি অ্যাক্সেস কোড প্রয়োজন", Title: "একটি অ্যাক্সেস কোড প্রয়োজন",
Tips: "নীচে অ্যাক্সেস কোড ইনপুট করুন", Tips: "নীচে অ্যাক্সেস কোড ইনপুট করুন",
SubTips: "অথবা আপনার OpenAI API কী প্রবেশ করুন",
Input: "অ্যাক্সেস কোড", Input: "অ্যাক্সেস কোড",
Confirm: "নিশ্চিত করুন", Confirm: "নিশ্চিত করুন",
Later: "পরে", Later: "পরে",

View File

@@ -13,6 +13,7 @@ const cn = {
Auth: { Auth: {
Title: "需要密码", Title: "需要密码",
Tips: "管理员开启了密码验证,请在下方填入访问码", Tips: "管理员开启了密码验证,请在下方填入访问码",
SubTips: "或者输入你的 OpenAI API 密钥",
Input: "在此处填写访问码", Input: "在此处填写访问码",
Confirm: "确认", Confirm: "确认",
Later: "稍后再说", Later: "稍后再说",
@@ -323,6 +324,10 @@ const cn = {
Success: "已写入剪切板", Success: "已写入剪切板",
Failed: "复制失败,请赋予剪切板权限", Failed: "复制失败,请赋予剪切板权限",
}, },
Download: {
Success: "内容已下载到您的目录。",
Failed: "下载失败。",
},
Context: { Context: {
Toast: (x: any) => `包含 ${x} 条预设提示词`, Toast: (x: any) => `包含 ${x} 条预设提示词`,
Edit: "当前对话设置", Edit: "当前对话设置",

View File

@@ -15,6 +15,7 @@ const en: LocaleType = {
Auth: { Auth: {
Title: "Need Access Code", Title: "Need Access Code",
Tips: "Please enter access code below", Tips: "Please enter access code below",
SubTips: "Or enter your OpenAI API Key",
Input: "access code", Input: "access code",
Confirm: "Confirm", Confirm: "Confirm",
Later: "Later", Later: "Later",
@@ -329,6 +330,10 @@ const en: LocaleType = {
Success: "Copied to clipboard", Success: "Copied to clipboard",
Failed: "Copy failed, please grant permission to access clipboard", Failed: "Copy failed, please grant permission to access clipboard",
}, },
Download: {
Success: "Content downloaded to your directory.",
Failed: "Download failed.",
},
Context: { Context: {
Toast: (x: any) => `With ${x} contextual prompts`, Toast: (x: any) => `With ${x} contextual prompts`,
Edit: "Current Chat Settings", Edit: "Current Chat Settings",

View File

@@ -4,12 +4,12 @@ import { PartialLocaleType } from "./index";
const id: PartialLocaleType = { const id: PartialLocaleType = {
WIP: "Coming Soon...", WIP: "Coming Soon...",
Error: { Error: {
Unauthorized: Unauthorized: "Akses tidak diizinkan, silakan masukkan kode akses atau masukkan kunci API OpenAI Anda. di halaman [autentikasi](/#/auth) atau di halaman [Pengaturan](/#/settings).",
"Akses tidak diizinkan. Silakan [otorisasi](/#/auth) dengan memasukkan kode akses.", },
},
Auth: { Auth: {
Title: "Diperlukan Kode Akses", Title: "Diperlukan Kode Akses",
Tips: "Masukkan kode akses di bawah", Tips: "Masukkan kode akses di bawah",
SubTips: "Atau masukkan kunci API OpenAI Anda",
Input: "Kode Akses", Input: "Kode Akses",
Confirm: "Konfirmasi", Confirm: "Konfirmasi",
Later: "Nanti", Later: "Nanti",
@@ -301,6 +301,10 @@ const id: PartialLocaleType = {
Failed: Failed:
"Gagal menyalin, mohon berikan izin untuk mengakses clipboard atau Clipboard API tidak didukung (Tauri)", "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: { Context: {
Toast: (x: any) => `Dengan ${x} promp kontekstual`, Toast: (x: any) => `Dengan ${x} promp kontekstual`,
Edit: "Pengaturan Obrolan Saat Ini", Edit: "Pengaturan Obrolan Saat Ini",

View File

@@ -1,4 +1,5 @@
import { LLMModel } from "../client/api"; import { LLMModel } from "../client/api";
import { isMacOS } from "../utils";
import { getClientConfig } from "../config/client"; import { getClientConfig } from "../config/client";
import { import {
DEFAULT_INPUT_TEMPLATE, DEFAULT_INPUT_TEMPLATE,
@@ -27,7 +28,7 @@ export enum Theme {
export const DEFAULT_CONFIG = { export const DEFAULT_CONFIG = {
lastUpdate: Date.now(), // timestamp, to merge state lastUpdate: Date.now(), // timestamp, to merge state
submitKey: SubmitKey.CtrlEnter as SubmitKey, submitKey: isMacOS() ? SubmitKey.MetaEnter : SubmitKey.CtrlEnter,
avatar: "1f603", avatar: "1f603",
fontSize: 14, fontSize: 14,
theme: Theme.Auto as Theme, theme: Theme.Auto as Theme,

View File

@@ -1,3 +1,4 @@
import { getClientConfig } from "../config/client";
import { Updater } from "../typing"; import { Updater } from "../typing";
import { ApiPath, STORAGE_KEY, StoreKey } from "../constant"; import { ApiPath, STORAGE_KEY, StoreKey } from "../constant";
import { createPersistStore } from "../utils/store"; import { createPersistStore } from "../utils/store";
@@ -20,6 +21,7 @@ export interface WebDavConfig {
password: string; password: string;
} }
const isApp = !!getClientConfig()?.isApp;
export type SyncStore = GetStoreState<typeof useSyncStore>; export type SyncStore = GetStoreState<typeof useSyncStore>;
const DEFAULT_SYNC_STATE = { const DEFAULT_SYNC_STATE = {
@@ -57,7 +59,11 @@ export const useSyncStore = createPersistStore(
export() { export() {
const state = getLocalAppState(); 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); downloadAs(JSON.stringify(state), fileName);
}, },

View File

@@ -2,8 +2,11 @@ import { FETCH_COMMIT_URL, FETCH_TAG_URL, StoreKey } from "../constant";
import { api } from "../client/api"; import { api } from "../client/api";
import { getClientConfig } from "../config/client"; import { getClientConfig } from "../config/client";
import { createPersistStore } from "../utils/store"; import { createPersistStore } from "../utils/store";
import ChatGptIcon from "../icons/chatgpt.png";
import Locale from "../locales";
const ONE_MINUTE = 60 * 1000; const ONE_MINUTE = 60 * 1000;
const isApp = !!getClientConfig()?.isApp;
function formatVersionDate(t: string) { function formatVersionDate(t: string) {
const d = new Date(+t); const d = new Date(+t);
@@ -80,6 +83,38 @@ export const useUpdateStore = createPersistStore(
set(() => ({ set(() => ({
remoteVersion: remoteId, remoteVersion: remoteId,
})); }));
if (window.__TAURI__?.notification && isApp) {
// Check if notification permission is granted
await window.__TAURI__?.notification.isPermissionGranted().then((granted) => {
if (!granted) {
return;
} else {
// Request permission to show notifications
window.__TAURI__?.notification.requestPermission().then((permission) => {
if (permission === 'granted') {
if (version === remoteId) {
// Show a notification using Tauri
window.__TAURI__?.notification.sendNotification({
title: "ChatGPT Next Web",
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: updateMessage,
icon: `${ChatGptIcon.src}`,
sound: "Default"
});
}
}
});
}
});
}
console.log("[Got Upstream] ", remoteId); console.log("[Got Upstream] ", remoteId);
} catch (error) { } catch (error) {
console.error("[Fetch Upstream Commit Id]", error); console.error("[Fetch Upstream Commit Id]", error);

View File

@@ -31,12 +31,41 @@ export async function copyToClipboard(text: string) {
} }
} }
export function downloadAs(text: string, filename: string) { export async function downloadAs(text: string, filename: string) {
const element = document.createElement("a"); if (window.__TAURI__) {
element.setAttribute( const result = await window.__TAURI__.dialog.save({
"href", defaultPath: `${filename}`,
"data:text/plain;charset=utf-8," + encodeURIComponent(text), 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.setAttribute("download", filename);
element.style.display = "none"; element.style.display = "none";
@@ -46,7 +75,7 @@ export function downloadAs(text: string, filename: string) {
document.body.removeChild(element); document.body.removeChild(element);
} }
}
export function readFromFile() { export function readFromFile() {
return new Promise<string>((res, rej) => { return new Promise<string>((res, rej) => {
const fileInput = document.createElement("input"); const fileInput = document.createElement("input");
@@ -173,3 +202,15 @@ export function autoGrowTextArea(dom: HTMLTextAreaElement) {
export function getCSSVar(varName: string) { export function getCSSVar(varName: string) {
return getComputedStyle(document.body).getPropertyValue(varName).trim(); return getComputedStyle(document.body).getPropertyValue(varName).trim();
} }
/**
* Detects Macintosh
*/
export function isMacOS(): boolean {
if (typeof window !== "undefined") {
let userAgent = window.navigator.userAgent.toLocaleLowerCase();
const macintosh = /iphone|ipad|ipod|macintosh/.test(userAgent)
return !!macintosh
}
return false
}

View File

@@ -21,7 +21,7 @@ export function createWebDavClient(store: SyncStore) {
proxyUrl, proxyUrl,
}); });
console.log("[WebDav] check", res.status, res.statusText); console.log("[WebDav] check", res.status, res.statusText);
return [201, 200, 404, 401].includes(res.status); return [201, 200, 404, 301, 302, 307, 308].includes(res.status);
} catch (e) { } catch (e) {
console.error("[WebDav] failed to check", e); console.error("[WebDav] failed to check", e);
} }

View File

@@ -17,7 +17,7 @@ tauri-build = { version = "1.3.0", features = [] }
[dependencies] [dependencies]
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } 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" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
[features] [features]

View File

@@ -9,7 +9,7 @@
}, },
"package": { "package": {
"productName": "ChatGPT Next Web", "productName": "ChatGPT Next Web",
"version": "2.9.7" "version": "2.9.8"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {
@@ -44,6 +44,12 @@
"startDragging": true, "startDragging": true,
"unmaximize": true, "unmaximize": true,
"unminimize": true "unminimize": true
},
"fs": {
"all": true
},
"notification": {
"all": true
} }
}, },
"bundle": { "bundle": {