From e5a328e284da302d725e94f6a0e6d557aa66db7b Mon Sep 17 00:00:00 2001 From: divisey <18656007202@163.com> Date: Thu, 8 Aug 2024 14:22:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20net=20state=20(#94?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- enjoy/src/api/client.ts | 4 + enjoy/src/i18n/en.json | 7 +- enjoy/src/i18n/zh-CN.json | 7 +- enjoy/src/main/window.ts | 8 + enjoy/src/preload.ts | 3 + .../renderer/components/misc/login-form.tsx | 5 + .../preferences/default-engine-settings.tsx | 2 +- .../renderer/components/preferences/index.ts | 3 +- .../components/preferences/network-state.tsx | 150 ++++++++++++++++++ .../components/preferences/preferences.tsx | 3 + .../components/preferences/proxy-settings.tsx | 32 +--- enjoy/src/types/enjoy-app.d.ts | 1 + enjoy/src/types/index.d.ts | 6 + 13 files changed, 196 insertions(+), 35 deletions(-) create mode 100644 enjoy/src/renderer/components/preferences/network-state.tsx diff --git a/enjoy/src/api/client.ts b/enjoy/src/api/client.ts index 10ebbab7..adc1ff52 100644 --- a/enjoy/src/api/client.ts +++ b/enjoy/src/api/client.ts @@ -64,6 +64,10 @@ export class Client { ); } + up() { + return this.api.get("/up"); + } + auth(params: { provider: "mixin" | "github" | "bandu" | "email"; code?: string; diff --git a/enjoy/src/i18n/en.json b/enjoy/src/i18n/en.json index 15031893..aa23dd2f 100644 --- a/enjoy/src/i18n/en.json +++ b/enjoy/src/i18n/en.json @@ -653,5 +653,10 @@ "continueLearning": "Continue learning", "enrollNow": "Enroll now", "enrollments": "Enrollments", - "noLikesYet": "No likes yet" + "noLikesYet": "No likes yet", + "apiConnectTime": "API Connect Time ({{apiUrl}})", + "ipInfo": "IP Information", + "platformInfo": "Platform Information", + "networkState": "Network State", + "connectError": "Connect Error" } diff --git a/enjoy/src/i18n/zh-CN.json b/enjoy/src/i18n/zh-CN.json index b289c69e..3d024095 100644 --- a/enjoy/src/i18n/zh-CN.json +++ b/enjoy/src/i18n/zh-CN.json @@ -653,5 +653,10 @@ "continueLearning": "继续练习", "enrollNow": "加入练习", "enrollments": "参加的课程", - "noLikesYet": "还没有点赞" + "noLikesYet": "还没有点赞", + "apiConnectTime": "API 延时 ({{apiUrl}})", + "ipInfo": "IP 信息", + "platformInfo": "设备信息", + "networkState": "网络状态", + "connectError": "连接错误" } diff --git a/enjoy/src/main/window.ts b/enjoy/src/main/window.ts index 9f1eed27..249278d0 100644 --- a/enjoy/src/main/window.ts +++ b/enjoy/src/main/window.ts @@ -280,6 +280,14 @@ main.init = () => { }); // App options + ipcMain.handle("app-platform-info", () => { + return { + platform: process.platform, + arch: process.arch, + version: process.getSystemVersion(), + }; + }); + ipcMain.handle("app-reset", () => { fs.removeSync(settings.userDataPath()); fs.removeSync(settings.file()); diff --git a/enjoy/src/preload.ts b/enjoy/src/preload.ts index d0782c10..be73fd47 100644 --- a/enjoy/src/preload.ts +++ b/enjoy/src/preload.ts @@ -6,6 +6,9 @@ import { Timeline } from "echogarden/dist/utilities/Timeline"; contextBridge.exposeInMainWorld("__ENJOY_APP__", { app: { + getPlatformInfo: () => { + return ipcRenderer.invoke("app-platform-info"); + }, reset: () => { ipcRenderer.invoke("app-reset"); }, diff --git a/enjoy/src/renderer/components/misc/login-form.tsx b/enjoy/src/renderer/components/misc/login-form.tsx index 95340385..930e75ac 100644 --- a/enjoy/src/renderer/components/misc/login-form.tsx +++ b/enjoy/src/renderer/components/misc/login-form.tsx @@ -25,6 +25,7 @@ import { MixinLoginButton, ProxySettings, ApiUrlSettings, + NetworkState, } from "@renderer/components"; import { EmailLoginForm } from "./email-login-form"; import { Client } from "@/api"; @@ -128,6 +129,8 @@ export const LoginForm = () => { + + @@ -166,6 +169,8 @@ export const LoginForm = () => { + + diff --git a/enjoy/src/renderer/components/preferences/default-engine-settings.tsx b/enjoy/src/renderer/components/preferences/default-engine-settings.tsx index 1a41d97c..32fe951d 100644 --- a/enjoy/src/renderer/components/preferences/default-engine-settings.tsx +++ b/enjoy/src/renderer/components/preferences/default-engine-settings.tsx @@ -56,7 +56,7 @@ export const DefaultEngineSettings = () => { if (form.watch("name") === "openai") { const customModels = openai?.models?.split(",")?.filter(Boolean); - return customModels.length ? customModels : providers.openai.models; + return customModels?.length ? customModels : providers.openai.models; } else { return providers.enjoyai.models; } diff --git a/enjoy/src/renderer/components/preferences/index.ts b/enjoy/src/renderer/components/preferences/index.ts index beeabdf4..b6355c1a 100644 --- a/enjoy/src/renderer/components/preferences/index.ts +++ b/enjoy/src/renderer/components/preferences/index.ts @@ -27,4 +27,5 @@ export * from "./theme-settings"; export * from "./proxy-settings"; -export * from "./whisper-model-options"; \ No newline at end of file +export * from "./whisper-model-options"; +export * from "./network-state"; diff --git a/enjoy/src/renderer/components/preferences/network-state.tsx b/enjoy/src/renderer/components/preferences/network-state.tsx new file mode 100644 index 00000000..41b63845 --- /dev/null +++ b/enjoy/src/renderer/components/preferences/network-state.tsx @@ -0,0 +1,150 @@ +import { Client } from "@/api"; +import { t } from "i18next"; +import { useState, useContext, useEffect, useMemo } from "react"; +import { AppSettingsProviderContext } from "@renderer/context"; +import { LoaderIcon } from "lucide-react"; + +export const NetworkState = () => { + const { apiUrl, EnjoyApp } = useContext(AppSettingsProviderContext); + + let timeoutId: ReturnType = null; + + const [apiConnected, setApiConnected] = useState(false); + const [apiConnecting, setApiConnecting] = useState(false); + const [apiConnectError, setApiConnectError] = useState(false); + const [apiConnectTime, setApiConnectTime] = useState(null); + + const [ipInfoError, setIpInfoError] = useState(false); + const [ipInfo, setIpInfo] = useState(null); + + const [platformInfo, setPlatformInfo] = useState(null); + + const items = useMemo(() => { + const apiStateColor = + apiConnectTime < 200 + ? "text-green-500" + : apiConnectTime < 800 + ? "text-yellow-500" + : "text-red-500"; + + return [ + { + title: t("apiConnectTime", { apiUrl }), + loading: !apiConnected && apiConnecting, + error: apiConnectError, + value: {apiConnectTime}ms, + }, + { + title: t("ipInfo"), + loading: false, + error: ipInfoError, + value: ( + + {ipInfo + ? `${ipInfo.ip} (${ipInfo.city}, ${ipInfo.country_name})` + : "-"} + + ), + }, + { + title: t("platformInfo"), + loading: false, + error: false, + value: ( + + {platformInfo + ? `${platformInfo.platform} ${platformInfo.arch} ${platformInfo.version}` + : "-"} + + ), + }, + ]; + }, [ + apiConnectTime, + apiConnecting, + apiConnected, + apiConnectError, + ipInfo, + ipInfoError, + platformInfo, + ]); + + useEffect(() => { + pollingAction(); + getPlatformInfo(); + + return () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + }; + }, []); + + async function pollingAction() { + await Promise.all([getApiConnectTime(), getIpInfo()]); + + timeoutId = setTimeout(() => pollingAction(), 10000); + } + + async function getApiConnectTime() { + setApiConnecting(true); + try { + const client = new Client({ baseUrl: apiUrl }); + const startTime = new Date().getTime(); + await client.up(); + const endTime = new Date().getTime(); + + setApiConnectTime(endTime - startTime); + setApiConnected(true); + } catch (error) { + setApiConnectError(true); + setApiConnected(false); + } + setApiConnecting(false); + } + + async function getIpInfo() { + try { + await fetch("https://ipapi.co/json") + .then((resp) => resp.json()) + .then((info) => setIpInfo(info)); + } catch (error) { + setIpInfoError(true); + } + } + + async function getPlatformInfo() { + const info = await EnjoyApp.app.getPlatformInfo(); + setPlatformInfo(info); + } + + return ( +
+
+
{t("networkState")}
+
+ +
+ {items.map((item, index) => { + return ( +
+
{item.title}
+
+ {item.loading ? ( + + ) : item.error ? ( + {t("connectError")} + ) : ( + item.value + )} +
+
+ ); + })} +
+
+ ); +}; diff --git a/enjoy/src/renderer/components/preferences/preferences.tsx b/enjoy/src/renderer/components/preferences/preferences.tsx index 6c793967..59a52f78 100644 --- a/enjoy/src/renderer/components/preferences/preferences.tsx +++ b/enjoy/src/renderer/components/preferences/preferences.tsx @@ -16,6 +16,7 @@ import { ResetAllSettings, NativeLanguageSettings, LearningLanguageSettings, + NetworkState, } from "@renderer/components"; import { useState } from "react"; import { Tooltip } from "react-tooltip"; @@ -56,6 +57,8 @@ export const Preferences = () => { + + diff --git a/enjoy/src/renderer/components/preferences/proxy-settings.tsx b/enjoy/src/renderer/components/preferences/proxy-settings.tsx index 70ea79d1..684f9485 100644 --- a/enjoy/src/renderer/components/preferences/proxy-settings.tsx +++ b/enjoy/src/renderer/components/preferences/proxy-settings.tsx @@ -12,13 +12,11 @@ import { Input, toast, } from "@renderer/components/ui"; -import { InfoIcon } from "lucide-react"; import { AppSettingsProviderContext } from "@renderer/context"; -import { useContext, useState, useEffect } from "react"; +import { useContext, useState } from "react"; export const ProxySettings = () => { const { proxy, setProxy } = useContext(AppSettingsProviderContext); - const [ipData, setIpData] = useState(null); const [editing, setEditing] = useState(false); const proxyConfigSchema = z.object({ @@ -51,22 +49,6 @@ export const ProxySettings = () => { }); }; - const checkIp = async () => { - fetch("https://ipapi.co/json") - .then((response) => response.json()) - .then((data) => { - setIpData(data); - }) - .catch((error) => { - toast.error(error.message); - setIpData(null); - }); - }; - - useEffect(() => { - checkIp(); - }, [proxy]); - return (
@@ -91,18 +73,6 @@ export const ProxySettings = () => { )} /> - {form.getValues("enabled") && ipData && ( -
-
-
- IP: {ipData.ip} ({ipData.city}, {ipData.country_name}) -
-
- -
-
-
- )}
diff --git a/enjoy/src/types/enjoy-app.d.ts b/enjoy/src/types/enjoy-app.d.ts index 3b93f8bb..3df3bb05 100644 --- a/enjoy/src/types/enjoy-app.d.ts +++ b/enjoy/src/types/enjoy-app.d.ts @@ -1,5 +1,6 @@ type EnjoyAppType = { app: { + getPlatformInfo: () => Promise; reset: () => Promise; resetSettings: () => Promise; relaunch: () => Promise; diff --git a/enjoy/src/types/index.d.ts b/enjoy/src/types/index.d.ts index d4dd696e..cad09d9c 100644 --- a/enjoy/src/types/index.d.ts +++ b/enjoy/src/types/index.d.ts @@ -177,3 +177,9 @@ type GptEngineSettingType = { baseUrl?: string; key?: string; }; + +type PlatformInfo = { + platform: string; + arch: string; + version: string; +};