mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 03:27:43 +01:00
feat: add not login tips (#244)
This commit is contained in:
@@ -26,7 +26,6 @@
|
||||
"@tauri-apps/plugin-websocket": "~2.3.0",
|
||||
"@tauri-apps/plugin-window": "2.0.0-alpha.1",
|
||||
"ahooks": "^3.8.4",
|
||||
"axios": "^1.8.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^16.4.7",
|
||||
"filesize": "^10.1.6",
|
||||
|
||||
157
pnpm-lock.yaml
generated
157
pnpm-lock.yaml
generated
@@ -47,9 +47,6 @@ importers:
|
||||
ahooks:
|
||||
specifier: ^3.8.4
|
||||
version: 3.8.4(react@18.3.1)
|
||||
axios:
|
||||
specifier: ^1.8.1
|
||||
version: 1.8.1
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
@@ -1363,9 +1360,6 @@ packages:
|
||||
async-retry@1.3.3:
|
||||
resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==}
|
||||
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
atomically@2.0.3:
|
||||
resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==}
|
||||
|
||||
@@ -1376,9 +1370,6 @@ packages:
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
|
||||
axios@1.8.1:
|
||||
resolution: {integrity: sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==}
|
||||
|
||||
bail@2.0.2:
|
||||
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
|
||||
|
||||
@@ -1419,10 +1410,6 @@ packages:
|
||||
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -1503,10 +1490,6 @@ packages:
|
||||
color-name@1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
comma-separated-tokens@2.0.3:
|
||||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||
|
||||
@@ -1766,10 +1749,6 @@ packages:
|
||||
delaunator@5.0.1:
|
||||
resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -1794,10 +1773,6 @@ packages:
|
||||
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
@@ -1824,22 +1799,6 @@ packages:
|
||||
error-ex@1.3.2:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
|
||||
es-define-property@1.0.1:
|
||||
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-errors@1.3.0:
|
||||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-set-tostringtag@2.1.0:
|
||||
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild@0.21.5:
|
||||
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -1923,23 +1882,10 @@ packages:
|
||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
follow-redirects@1.15.9:
|
||||
resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
|
||||
foreground-child@3.3.1:
|
||||
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
form-data@4.0.2:
|
||||
resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
fraction.js@4.3.7:
|
||||
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
||||
|
||||
@@ -1962,14 +1908,6 @@ packages:
|
||||
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-proto@1.0.1:
|
||||
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-stream@8.0.1:
|
||||
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
|
||||
engines: {node: '>=16'}
|
||||
@@ -2023,10 +1961,6 @@ packages:
|
||||
resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
gopd@1.2.0:
|
||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
graceful-fs@4.2.10:
|
||||
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
|
||||
|
||||
@@ -2036,14 +1970,6 @@ packages:
|
||||
hachure-fill@0.5.2:
|
||||
resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
|
||||
|
||||
has-symbols@1.1.0:
|
||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2409,10 +2335,6 @@ packages:
|
||||
engines: {node: '>= 18'}
|
||||
hasBin: true
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
|
||||
|
||||
@@ -4519,8 +4441,6 @@ snapshots:
|
||||
dependencies:
|
||||
retry: 0.13.1
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
atomically@2.0.3:
|
||||
dependencies:
|
||||
stubborn-fs: 1.2.5
|
||||
@@ -4536,14 +4456,6 @@ snapshots:
|
||||
postcss: 8.5.3
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
axios@1.8.1:
|
||||
dependencies:
|
||||
follow-redirects: 1.15.9
|
||||
form-data: 4.0.2
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
bail@2.0.2: {}
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
@@ -4589,11 +4501,6 @@ snapshots:
|
||||
dependencies:
|
||||
run-applescript: 7.0.0
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
camelcase-css@2.0.1: {}
|
||||
@@ -4662,10 +4569,6 @@ snapshots:
|
||||
|
||||
color-name@1.1.4: {}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
comma-separated-tokens@2.0.3: {}
|
||||
|
||||
commander@4.1.1: {}
|
||||
@@ -4938,8 +4841,6 @@ snapshots:
|
||||
dependencies:
|
||||
robust-predicates: 3.0.2
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
devlop@1.1.0:
|
||||
@@ -4960,12 +4861,6 @@ snapshots:
|
||||
|
||||
dotenv@16.4.7: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
electron-to-chromium@1.5.112: {}
|
||||
@@ -4984,21 +4879,6 @@ snapshots:
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
|
||||
es-define-property@1.0.1: {}
|
||||
|
||||
es-errors@1.3.0: {}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
es-set-tostringtag@2.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.3.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
esbuild@0.21.5:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.21.5
|
||||
@@ -5136,20 +5016,11 @@ snapshots:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
follow-redirects@1.15.9: {}
|
||||
|
||||
foreground-child@3.3.1:
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
signal-exit: 4.1.0
|
||||
|
||||
form-data@4.0.2:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
es-set-tostringtag: 2.1.0
|
||||
mime-types: 2.1.35
|
||||
|
||||
fraction.js@4.3.7: {}
|
||||
|
||||
fs.realpath@1.0.0: {}
|
||||
@@ -5163,24 +5034,6 @@ snapshots:
|
||||
|
||||
get-east-asian-width@1.3.0: {}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.1.1
|
||||
function-bind: 1.1.2
|
||||
get-proto: 1.0.1
|
||||
gopd: 1.2.0
|
||||
has-symbols: 1.1.0
|
||||
hasown: 2.0.2
|
||||
math-intrinsics: 1.1.0
|
||||
|
||||
get-proto@1.0.1:
|
||||
dependencies:
|
||||
dunder-proto: 1.0.1
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
get-stream@8.0.1: {}
|
||||
|
||||
get-stream@9.0.1:
|
||||
@@ -5252,20 +5105,12 @@ snapshots:
|
||||
slash: 5.1.0
|
||||
unicorn-magic: 0.1.0
|
||||
|
||||
gopd@1.2.0: {}
|
||||
|
||||
graceful-fs@4.2.10: {}
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
hachure-fill@0.5.2: {}
|
||||
|
||||
has-symbols@1.1.0: {}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
dependencies:
|
||||
has-symbols: 1.1.0
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
@@ -5625,8 +5470,6 @@ snapshots:
|
||||
|
||||
marked@13.0.3: {}
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import { isTauri } from "@tauri-apps/api/core";
|
||||
import { fetch as tauriFetchModule } from "@tauri-apps/plugin-http";
|
||||
|
||||
import { clientEnv } from "@/utils/env";
|
||||
|
||||
// Use a conditional fetch depending on whether it's in a Tauri environment or web
|
||||
let customFetch: typeof window.fetch | typeof tauriFetchModule = window.fetch;
|
||||
|
||||
if (isTauri()) {
|
||||
customFetch = tauriFetchModule;
|
||||
}
|
||||
|
||||
interface FetchRequestConfig {
|
||||
url: string;
|
||||
method?: "GET" | "POST" | "PUT" | "DELETE";
|
||||
headers?: Record<string, string>;
|
||||
body?: any;
|
||||
timeout?: number;
|
||||
parseAs?: "json" | "text" | "binary";
|
||||
baseURL?: string;
|
||||
}
|
||||
|
||||
interface FetchResponse<T = any> {
|
||||
data: T;
|
||||
status: number;
|
||||
statusText: string;
|
||||
headers: Headers;
|
||||
}
|
||||
|
||||
// Timeout function to reject after the specified time (in ms)
|
||||
const timeoutPromise = (ms: number) => {
|
||||
return new Promise<never>((_, reject) =>
|
||||
setTimeout(() => reject(new Error(`Request timed out after ${ms} ms`)), ms)
|
||||
);
|
||||
};
|
||||
|
||||
// The main fetch function that switches between Tauri and web fetch based on environment
|
||||
export const tauriFetch = async <T = any>({
|
||||
url,
|
||||
method = "GET",
|
||||
headers = {},
|
||||
body,
|
||||
timeout = 30,
|
||||
parseAs = "json",
|
||||
baseURL = clientEnv.COCO_SERVER_URL
|
||||
}: FetchRequestConfig): Promise<FetchResponse<T>> => {
|
||||
try {
|
||||
url = baseURL + url;
|
||||
|
||||
if (method !== "GET") {
|
||||
headers["Content-Type"] = "application/json";
|
||||
}
|
||||
|
||||
const fetchPromise = customFetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body: method !== "GET" ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
|
||||
const response = await Promise.race([
|
||||
fetchPromise,
|
||||
timeoutPromise(timeout * 1000),
|
||||
]);
|
||||
|
||||
const statusText = response.ok ? "OK" : "Error";
|
||||
|
||||
// Handle empty or non-JSON responses gracefully
|
||||
let data: any = null;
|
||||
if (response.ok && response.headers.get("Content-Type")?.includes("application/json")) {
|
||||
const text = await response.text();
|
||||
data = text ? JSON.parse(text) : null;
|
||||
} else if (parseAs === "text") {
|
||||
data = await response.text();
|
||||
} else if (parseAs === "binary") {
|
||||
data = await response.arrayBuffer();
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
status: response.status,
|
||||
statusText,
|
||||
headers: response.headers,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
34
src/assets/images/login-dark.svg
Normal file
34
src/assets/images/login-dark.svg
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 3</title>
|
||||
<defs>
|
||||
<rect id="path-1" x="0" y="0" width="80" height="80"></rect>
|
||||
</defs>
|
||||
<g id="不可用提示" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="对话-未登录" transform="translate(-300, -152)">
|
||||
<g id="编组-3" transform="translate(300, 152)">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="矩形"></g>
|
||||
<g id="编组-7" mask="url(#mask-2)" stroke="#D8D8D8" stroke-linejoin="round" stroke-width="2">
|
||||
<g transform="translate(40.1174, 42.9894) rotate(18) translate(-40.1174, -42.9894)translate(4.2836, -1.1681)">
|
||||
<polyline id="路径" stroke-linecap="round" points="59.1875017 40.24271 51.0736701 32.24271 18.1473879 32.674758 11.1875017 39.6712322"></polyline>
|
||||
<path d="M10.9295011,65.0735178 C15.4119608,73.3475841 24.1708112,78.9666151 34.2420566,78.9666151 C48.8754069,78.9666151 60.7380811,67.1039409 60.7380811,52.4705906 C60.7380811,39.7604963 51.788708,29.1406401 39.8476032,26.5686633" id="路径" stroke-linecap="round" transform="translate(35.8338, 52.7676) rotate(54) translate(-35.8338, -52.7676)"></path>
|
||||
<path d="M11.7376647,39.1753202 C18.8464577,40.9618544 23.4439561,39.4110588 25.5301598,34.5229334 C28.0332335,38.3361178 31.3504939,40.24271 35.4819412,40.24271 C41.6791121,40.24271 44.3918829,34.8103094 44.6599103,34.24271 C47.794477,39.3790355 52.6370074,41.1912541 59.1875017,39.6793657" id="路径-16"></path>
|
||||
<path d="M24.1812108,75.5251943 C22.2902174,72.5032493 20.9749339,65.6812238 23.9032268,56.24271 C24.8257299,66.8179552 27.9236731,73.4384846 33.1970563,76.1042981 C41.1071312,80.1030185 45.6140524,73.1021739 46.8031597,62.3735214 C47.4651356,68.7556799 47.2719901,72.9855883 46.2237233,75.0632467" id="路径-17" stroke-linecap="round"></path>
|
||||
<path d="M30.228274,28.6819562 C30.228274,23.6648076 26.1610714,19.597605 21.1439227,19.597605 C16.1267741,19.597605 12.0595715,23.6648076 12.0595715,28.6819562" id="路径" transform="translate(21.1439, 24.1398) rotate(-21) translate(-21.1439, -24.1398)"></path>
|
||||
<path d="M25.6860984,28.6819562 C25.6860984,23.6648076 23.6524971,19.597605 21.1439227,19.597605 C18.6353484,19.597605 16.6017471,23.6648076 16.6017471,28.6819562" id="路径" transform="translate(21.1439, 24.1398) rotate(-21) translate(-21.1439, -24.1398)"></path>
|
||||
<line x1="14.1875017" y1="31.24271" x2="31.1875017" y2="25.24271" id="路径-18" stroke-linecap="round"></line>
|
||||
<line x1="19.1875017" y1="20.24271" x2="24.1875017" y2="32.24271" id="路径-19" stroke-linecap="round"></line>
|
||||
<polyline id="路径-20" stroke-linecap="round" transform="translate(53.1152, 14.1827) rotate(-7) translate(-53.1152, -14.1827)" points="42.6151971 27.1827281 51.6756128 1.93876599 63.6151971 1.18272808"></polyline>
|
||||
<line x1="55.6702216" y1="18.6299671" x2="61.5910272" y2="18.2159441" id="路径-2" stroke-linecap="round"></line>
|
||||
<line x1="35.7394234" y1="15.7021435" x2="39.2106463" y2="13.8564616" id="路径-2备份" stroke-linecap="round"></line>
|
||||
<line x1="58.5383652" y1="15.3936027" x2="58.9596123" y2="21.417717" id="路径-3" stroke-linecap="round"></line>
|
||||
<line x1="36.603056" y1="12.9710524" x2="38.4809422" y2="16.5028428" id="路径-3备份" stroke-linecap="round"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
34
src/assets/images/login-light.svg
Normal file
34
src/assets/images/login-light.svg
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 3</title>
|
||||
<defs>
|
||||
<rect id="path-1" x="0" y="0" width="80" height="80"></rect>
|
||||
</defs>
|
||||
<g id="不可用提示" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="对话-未登录" transform="translate(-300, -152)">
|
||||
<g id="编组-3" transform="translate(300, 152)">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="矩形"></g>
|
||||
<g id="编组-7" mask="url(#mask-2)" stroke="#333333" stroke-linejoin="round" stroke-width="2">
|
||||
<g transform="translate(40.1174, 42.9894) rotate(18) translate(-40.1174, -42.9894)translate(4.2836, -1.1681)">
|
||||
<polyline id="路径" stroke-linecap="round" points="59.1875017 40.24271 51.0736701 32.24271 18.1473879 32.674758 11.1875017 39.6712322"></polyline>
|
||||
<path d="M10.9295011,65.0735178 C15.4119608,73.3475841 24.1708112,78.9666151 34.2420566,78.9666151 C48.8754069,78.9666151 60.7380811,67.1039409 60.7380811,52.4705906 C60.7380811,39.7604963 51.788708,29.1406401 39.8476032,26.5686633" id="路径" stroke-linecap="round" transform="translate(35.8338, 52.7676) rotate(54) translate(-35.8338, -52.7676)"></path>
|
||||
<path d="M11.7376647,39.1753202 C18.8464577,40.9618544 23.4439561,39.4110588 25.5301598,34.5229334 C28.0332335,38.3361178 31.3504939,40.24271 35.4819412,40.24271 C41.6791121,40.24271 44.3918829,34.8103094 44.6599103,34.24271 C47.794477,39.3790355 52.6370074,41.1912541 59.1875017,39.6793657" id="路径-16"></path>
|
||||
<path d="M24.1812108,75.5251943 C22.2902174,72.5032493 20.9749339,65.6812238 23.9032268,56.24271 C24.8257299,66.8179552 27.9236731,73.4384846 33.1970563,76.1042981 C41.1071312,80.1030185 45.6140524,73.1021739 46.8031597,62.3735214 C47.4651356,68.7556799 47.2719901,72.9855883 46.2237233,75.0632467" id="路径-17" stroke-linecap="round"></path>
|
||||
<path d="M30.228274,28.6819562 C30.228274,23.6648076 26.1610714,19.597605 21.1439227,19.597605 C16.1267741,19.597605 12.0595715,23.6648076 12.0595715,28.6819562" id="路径" transform="translate(21.1439, 24.1398) rotate(-21) translate(-21.1439, -24.1398)"></path>
|
||||
<path d="M25.6860984,28.6819562 C25.6860984,23.6648076 23.6524971,19.597605 21.1439227,19.597605 C18.6353484,19.597605 16.6017471,23.6648076 16.6017471,28.6819562" id="路径" transform="translate(21.1439, 24.1398) rotate(-21) translate(-21.1439, -24.1398)"></path>
|
||||
<line x1="14.1875017" y1="31.24271" x2="31.1875017" y2="25.24271" id="路径-18" stroke-linecap="round"></line>
|
||||
<line x1="19.1875017" y1="20.24271" x2="24.1875017" y2="32.24271" id="路径-19" stroke-linecap="round"></line>
|
||||
<polyline id="路径-20" stroke-linecap="round" transform="translate(53.1152, 14.1827) rotate(-7) translate(-53.1152, -14.1827)" points="42.6151971 27.1827281 51.6756128 1.93876599 63.6151971 1.18272808"></polyline>
|
||||
<line x1="55.6702216" y1="18.6299671" x2="61.5910272" y2="18.2159441" id="路径-2" stroke-linecap="round"></line>
|
||||
<line x1="35.7394234" y1="15.7021435" x2="39.2106463" y2="13.8564616" id="路径-2备份" stroke-linecap="round"></line>
|
||||
<line x1="58.5383652" y1="15.3936027" x2="58.9596123" y2="21.417717" id="路径-3" stroke-linecap="round"></line>
|
||||
<line x1="36.603056" y1="12.9710524" x2="38.4809422" y2="16.5028428" id="路径-3备份" stroke-linecap="round"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -24,6 +24,7 @@ import { useSearchStore } from "@/stores/searchStore";
|
||||
import { IServer } from "@/stores/appStore";
|
||||
import FileList from "@/components/Search/FileList";
|
||||
import { Greetings } from "./Greetings";
|
||||
import ConnectPrompt from "./ConnectPrompt";
|
||||
|
||||
interface ChatAIProps {
|
||||
isTransitioned: boolean;
|
||||
@@ -85,6 +86,8 @@ const ChatAI = memo(
|
||||
const [activeChat, setActiveChat] = useState<Chat>();
|
||||
const [timedoutShow, setTimedoutShow] = useState(false);
|
||||
const [errorShow, setErrorShow] = useState(false);
|
||||
const [IsLogin, setIsLogin] = useState(false);
|
||||
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const curChatEndRef = useRef(curChatEnd);
|
||||
@@ -106,7 +109,8 @@ const ChatAI = memo(
|
||||
if (!server?.id) return;
|
||||
try {
|
||||
console.log("reconnect", server.id);
|
||||
await invoke("connect_to_server", { id: server.id });
|
||||
const res: any = await invoke("connect_to_server", { id: server.id });
|
||||
console.log(1111, res)
|
||||
setConnected(true);
|
||||
} catch (error) {
|
||||
console.error("Failed to connect:", error);
|
||||
@@ -462,7 +466,11 @@ const ChatAI = memo(
|
||||
console.error("Failed to fetch user data:", error);
|
||||
}
|
||||
},
|
||||
[JSON.stringify(activeChat?.messages), isSearchActive, isDeepThinkActive]
|
||||
[
|
||||
JSON.stringify(activeChat?.messages),
|
||||
isSearchActive,
|
||||
isDeepThinkActive,
|
||||
]
|
||||
);
|
||||
|
||||
const handleSendMessage = useCallback(
|
||||
@@ -539,7 +547,10 @@ const ChatAI = memo(
|
||||
};
|
||||
}, []);
|
||||
|
||||
const chatHistory = async (chat: Chat, callback?: (chat: Chat) => void) => {
|
||||
const chatHistory = async (
|
||||
chat: Chat,
|
||||
callback?: (chat: Chat) => void
|
||||
) => {
|
||||
try {
|
||||
let response: any = await invoke("session_chat_history", {
|
||||
serverId: currentService?.id,
|
||||
@@ -554,9 +565,9 @@ const ChatAI = memo(
|
||||
...chat,
|
||||
messages: hits,
|
||||
};
|
||||
console.log("id_history2", updatedChat)
|
||||
console.log("id_history2", updatedChat);
|
||||
setActiveChat(updatedChat);
|
||||
callback && callback(updatedChat)
|
||||
callback && callback(updatedChat);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch user data:", error);
|
||||
}
|
||||
@@ -671,85 +682,89 @@ const ChatAI = memo(
|
||||
activeChat={activeChat}
|
||||
reconnect={reconnect}
|
||||
isChatPage={isChatPage}
|
||||
setIsLogin={setIsLogin}
|
||||
/>
|
||||
{/* Chat messages */}
|
||||
<div className="flex flex-col h-full justify-between overflow-hidden">
|
||||
<div className="flex-1 w-full overflow-x-hidden overflow-y-auto border-t border-[rgba(0,0,0,0.1)] dark:border-[rgba(255,255,255,0.15)] custom-scrollbar relative">
|
||||
<Greetings />
|
||||
{activeChat?.messages?.map((message, index) => (
|
||||
<ChatMessage
|
||||
key={message._id + index}
|
||||
message={message}
|
||||
isTyping={false}
|
||||
onResend={handleSendMessage}
|
||||
/>
|
||||
))}
|
||||
{(query_intent ||
|
||||
fetch_source ||
|
||||
pick_source ||
|
||||
deep_read ||
|
||||
think ||
|
||||
response) &&
|
||||
activeChat?._id ? (
|
||||
<ChatMessage
|
||||
key={"current"}
|
||||
message={{
|
||||
_id: "current",
|
||||
_source: {
|
||||
type: "assistant",
|
||||
message: "",
|
||||
question: Question,
|
||||
},
|
||||
}}
|
||||
onResend={handleSendMessage}
|
||||
isTyping={!curChatEnd}
|
||||
query_intent={query_intent}
|
||||
fetch_source={fetch_source}
|
||||
pick_source={pick_source}
|
||||
deep_read={deep_read}
|
||||
think={think}
|
||||
response={response}
|
||||
/>
|
||||
) : null}
|
||||
{timedoutShow ? (
|
||||
<ChatMessage
|
||||
key={"timedout"}
|
||||
message={{
|
||||
_id: "timedout",
|
||||
_source: {
|
||||
type: "assistant",
|
||||
message: t("assistant.chat.timedout"),
|
||||
question: Question,
|
||||
},
|
||||
}}
|
||||
onResend={handleSendMessage}
|
||||
isTyping={false}
|
||||
/>
|
||||
) : null}
|
||||
{errorShow ? (
|
||||
<ChatMessage
|
||||
key={"error"}
|
||||
message={{
|
||||
_id: "error",
|
||||
_source: {
|
||||
type: "assistant",
|
||||
message: t("assistant.chat.error"),
|
||||
question: Question,
|
||||
},
|
||||
}}
|
||||
onResend={handleSendMessage}
|
||||
isTyping={false}
|
||||
/>
|
||||
) : null}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
|
||||
{uploadFiles.length > 0 && (
|
||||
<div className="max-h-[120px] overflow-auto p-2">
|
||||
<FileList />
|
||||
{IsLogin ? (
|
||||
<div className="flex flex-col h-full justify-between overflow-hidden">
|
||||
<div className="flex-1 w-full overflow-x-hidden overflow-y-auto border-t border-[rgba(0,0,0,0.1)] dark:border-[rgba(255,255,255,0.15)] custom-scrollbar relative">
|
||||
<Greetings />
|
||||
{activeChat?.messages?.map((message, index) => (
|
||||
<ChatMessage
|
||||
key={message._id + index}
|
||||
message={message}
|
||||
isTyping={false}
|
||||
onResend={handleSendMessage}
|
||||
/>
|
||||
))}
|
||||
{(query_intent ||
|
||||
fetch_source ||
|
||||
pick_source ||
|
||||
deep_read ||
|
||||
think ||
|
||||
response) &&
|
||||
activeChat?._id ? (
|
||||
<ChatMessage
|
||||
key={"current"}
|
||||
message={{
|
||||
_id: "current",
|
||||
_source: {
|
||||
type: "assistant",
|
||||
message: "",
|
||||
question: Question,
|
||||
},
|
||||
}}
|
||||
onResend={handleSendMessage}
|
||||
isTyping={!curChatEnd}
|
||||
query_intent={query_intent}
|
||||
fetch_source={fetch_source}
|
||||
pick_source={pick_source}
|
||||
deep_read={deep_read}
|
||||
think={think}
|
||||
response={response}
|
||||
/>
|
||||
) : null}
|
||||
{timedoutShow ? (
|
||||
<ChatMessage
|
||||
key={"timedout"}
|
||||
message={{
|
||||
_id: "timedout",
|
||||
_source: {
|
||||
type: "assistant",
|
||||
message: t("assistant.chat.timedout"),
|
||||
question: Question,
|
||||
},
|
||||
}}
|
||||
onResend={handleSendMessage}
|
||||
isTyping={false}
|
||||
/>
|
||||
) : null}
|
||||
{errorShow ? (
|
||||
<ChatMessage
|
||||
key={"error"}
|
||||
message={{
|
||||
_id: "error",
|
||||
_source: {
|
||||
type: "assistant",
|
||||
message: t("assistant.chat.error"),
|
||||
question: Question,
|
||||
},
|
||||
}}
|
||||
onResend={handleSendMessage}
|
||||
isTyping={false}
|
||||
/>
|
||||
) : null}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{uploadFiles.length > 0 && (
|
||||
<div className="max-h-[120px] overflow-auto p-2">
|
||||
<FileList />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<ConnectPrompt />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ interface ChatHeaderProps {
|
||||
isSidebarOpen: boolean;
|
||||
activeChat: Chat | undefined;
|
||||
reconnect: (server?: IServer) => void;
|
||||
setIsLogin: (isLogin: boolean) => void;
|
||||
isChatPage?: boolean;
|
||||
}
|
||||
|
||||
@@ -48,6 +49,7 @@ export function ChatHeader({
|
||||
setIsSidebarOpen,
|
||||
activeChat,
|
||||
reconnect,
|
||||
setIsLogin,
|
||||
isChatPage = false,
|
||||
}: ChatHeaderProps) {
|
||||
const { t } = useTranslation();
|
||||
@@ -70,7 +72,7 @@ export function ChatHeader({
|
||||
const enabledServers = (res as IServer[]).filter(
|
||||
(server) => server.enabled !== false
|
||||
);
|
||||
// console.log("list_coco_servers", enabledServers);
|
||||
console.log("list_coco_servers", enabledServers);
|
||||
setServerList(enabledServers);
|
||||
|
||||
if (resetSelection && enabledServers.length > 0) {
|
||||
@@ -103,7 +105,8 @@ export function ChatHeader({
|
||||
if (!connected) return;
|
||||
try {
|
||||
console.log("disconnect");
|
||||
await invoke("disconnect");
|
||||
const res: any = await invoke("disconnect");
|
||||
console.log(121212213213123, res)
|
||||
setConnected(false);
|
||||
} catch (error) {
|
||||
console.error("Failed to disconnect:", error);
|
||||
@@ -119,6 +122,12 @@ export function ChatHeader({
|
||||
setMessages(""); // Clear previous messages
|
||||
onCreateNewChat();
|
||||
//
|
||||
if (!server.public && !server.profile) {
|
||||
setIsLogin(false);
|
||||
return;
|
||||
}
|
||||
setIsLogin(true);
|
||||
//
|
||||
if (!(isCurrent && connected)) {
|
||||
await disconnect();
|
||||
reconnect && reconnect(server);
|
||||
|
||||
42
src/components/Assistant/ConnectPrompt.tsx
Normal file
42
src/components/Assistant/ConnectPrompt.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
|
||||
import LoginDark from "@/assets/images/login-dark.svg";
|
||||
import LoginLight from "@/assets/images/login-light.svg";
|
||||
import { useTheme } from "@/contexts/ThemeContext";
|
||||
|
||||
const ConnectPrompt = () => {
|
||||
const { t } = useTranslation();
|
||||
const { theme } = useTheme();
|
||||
|
||||
const logo = theme === "dark" ? LoginDark : LoginLight;
|
||||
|
||||
const handleConnect = async () => {
|
||||
emit("open_settings", "connect");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full w-full text-sm text-[#333] dark:text-[#d8d8d8]">
|
||||
<div className="flex flex-col items-center text-center p-6">
|
||||
<img
|
||||
src={logo}
|
||||
className="w-20 h-20 mb-4"
|
||||
alt={t("assistant.chat.logo_alt")}
|
||||
/>
|
||||
<p>{t("assistant.chat.welcome")}</p>
|
||||
<p className="mb-4 w-[388px]">{t("assistant.chat.connect_tip")}</p>
|
||||
|
||||
<button
|
||||
className="flex items-center gap-2 px-6 py-2 rounded-md text-[#0072ff] transition-colors"
|
||||
onClick={handleConnect}
|
||||
>
|
||||
<span>{t("assistant.chat.connect")}</span>
|
||||
<ExternalLink size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectPrompt;
|
||||
@@ -1,9 +1,8 @@
|
||||
import { useEffect, useCallback } from "react";
|
||||
import { listen} from "@tauri-apps/api/event";
|
||||
import { listen, emit } from "@tauri-apps/api/event";
|
||||
import { WebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
|
||||
import { isMetaOrCtrlKey } from "@/utils/keyboardUtils";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
|
||||
interface CreateWindowOptions {
|
||||
label?: string;
|
||||
@@ -17,8 +16,6 @@ interface CreateWindowOptions {
|
||||
}
|
||||
|
||||
export default function useSettingsWindow() {
|
||||
const setTabIndex = useAppStore((state) => state.setTabIndex);
|
||||
|
||||
const openSettingsWindow = useCallback((tab?: string) => {
|
||||
const url = tab ? `/ui/settings?tab=${tab}` : `/ui/settings`;
|
||||
const options: CreateWindowOptions = {
|
||||
@@ -37,6 +34,10 @@ export default function useSettingsWindow() {
|
||||
resizable: false,
|
||||
center: true,
|
||||
url,
|
||||
data: {
|
||||
tab,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
};
|
||||
|
||||
// Check if the window already exists
|
||||
@@ -67,11 +68,11 @@ export default function useSettingsWindow() {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const unlisten = listen("open_settings", (event) => {
|
||||
const unlisten = listen("open_settings", async (event) => {
|
||||
console.log("open_settings event received:", event);
|
||||
const tab = event.payload as string | "";
|
||||
|
||||
setTabIndex(tab)
|
||||
emit("tab_index", tab);
|
||||
openSettingsWindow(tab);
|
||||
});
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
@@ -119,7 +119,11 @@
|
||||
"timedout": "Request timed out. Please try again later.",
|
||||
"noServers": "No servers found",
|
||||
"addServer": "Add Server",
|
||||
"error": "Request error. Please try again later."
|
||||
"error": "Request error. Please try again later.",
|
||||
"logo_alt": "Login Logo",
|
||||
"welcome": "Welcome to Coco AI",
|
||||
"connect_tip": "To start a conversation, please connect to the service and log in to your account.",
|
||||
"connect": "Connect"
|
||||
},
|
||||
"input": {
|
||||
"stopMessage": "Stop message",
|
||||
|
||||
@@ -119,7 +119,11 @@
|
||||
"timedout": "请求超时,请稍后再试。",
|
||||
"noServers": "暂无可用服务器",
|
||||
"addServer": "添加服务器",
|
||||
"error": "请求错误,请稍后再试。"
|
||||
"error": "请求错误,请稍后再试。",
|
||||
"logo_alt": "登录图标",
|
||||
"welcome": "欢迎使用 Coco AI",
|
||||
"connect_tip": "要开始对话,请连接服务并登录您的账户。",
|
||||
"connect": "连接"
|
||||
},
|
||||
"input": {
|
||||
"stopMessage": "停止生成",
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react";
|
||||
import { Settings, Puzzle, Settings2, Info, Server } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
|
||||
import SettingsPanel from "@/components/Settings/SettingsPanel";
|
||||
import GeneralSettings from "@/components/Settings/GeneralSettings";
|
||||
import AboutView from "@/components/Settings/AboutView";
|
||||
import Cloud from "@/components/Cloud/Cloud.tsx";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
|
||||
const tabIndexMap: { [key: string]: number } = {
|
||||
'general': 0,
|
||||
'extensions': 1,
|
||||
'connect': 2,
|
||||
'advanced': 3,
|
||||
'about': 4
|
||||
};
|
||||
|
||||
function SettingsPage() {
|
||||
const { t } = useTranslation();
|
||||
@@ -21,8 +29,21 @@ function SettingsPage() {
|
||||
{ name: t("settings.tabs.about"), icon: Info },
|
||||
];
|
||||
|
||||
const tabIndex = useAppStore((state) => state.tabIndex);
|
||||
const [defaultIndex, setDefaultIndex] = useState<number>(tabIndex);
|
||||
const [defaultIndex, setDefaultIndex] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
const unlisten = listen("tab_index", (event) => {
|
||||
const tabName = event.payload as string;
|
||||
const index = tabIndexMap[tabName];
|
||||
if (index !== -1) {
|
||||
setDefaultIndex(index);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlisten.then(fn => fn());
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -14,6 +14,8 @@ export interface IServer {
|
||||
icon: string;
|
||||
};
|
||||
enabled: boolean;
|
||||
public: boolean;
|
||||
profile?: any;
|
||||
available?: boolean;
|
||||
health?: {
|
||||
status: string;
|
||||
@@ -40,8 +42,6 @@ export type IAppStore = {
|
||||
setEndpoint: (endpoint: AppEndpoint) => void,
|
||||
language: string;
|
||||
setLanguage: (language: string) => void;
|
||||
tabIndex: number;
|
||||
setTabIndex: (tabName: string) => void;
|
||||
isPinned: boolean,
|
||||
setIsPinned: (isPinned: boolean) => void,
|
||||
initializeListeners: () => void;
|
||||
@@ -84,17 +84,6 @@ export const useAppStore = create<IAppStore>()(
|
||||
},
|
||||
language: "en",
|
||||
setLanguage: (language: string) => set({ language }),
|
||||
tabIndex: 0,
|
||||
setTabIndex: (tabName: string) => {
|
||||
const tabIndexMap: { [key: string]: number } = {
|
||||
'general': 0,
|
||||
'extensions': 1,
|
||||
'connect': 2,
|
||||
'advanced': 3,
|
||||
'about': 4
|
||||
};
|
||||
set({ tabIndex: tabIndexMap[tabName || "general"] || 0 })
|
||||
},
|
||||
isPinned: false,
|
||||
setIsPinned: (isPinned: boolean) => set({ isPinned }),
|
||||
initializeListeners: () => {
|
||||
|
||||
Reference in New Issue
Block a user