diff --git a/apps/desktop-client/package.json b/apps/desktop-client/package.json index 0525cfb..2855635 100644 --- a/apps/desktop-client/package.json +++ b/apps/desktop-client/package.json @@ -11,7 +11,7 @@ "type": "module", "main": "out/main/bootstrap.cjs", "scripts": { - "dev": "unset ELECTRON_RUN_AS_NODE && electron-vite dev --inspect=9229", + "dev": "electron-vite dev --inspect=9229", "build": "electron-vite build", "package:mac": "pnpm run build && electron-builder --mac --arm64,universal", "package:win": "pnpm run build && electron-builder --win --x64", diff --git a/apps/desktop-client/src/main/bootstrap.ts b/apps/desktop-client/src/main/bootstrap.ts index 218b4d2..888967e 100644 --- a/apps/desktop-client/src/main/bootstrap.ts +++ b/apps/desktop-client/src/main/bootstrap.ts @@ -2,7 +2,7 @@ import { readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { shell } from "electron"; -import { BrowserWindow, app, ipcMain, nativeTheme } from "electron/main"; +import { BrowserWindow, Menu, app, ipcMain, nativeTheme } from "electron/main"; import type { BrowserWindow as ElectronBrowserWindow, IpcMainInvokeEvent, @@ -132,6 +132,15 @@ const SETTINGS_WINDOW_SIZE: WindowSizePreset = { resizable: true, }; +function suppressNativeWindowMenu(window?: ElectronBrowserWindow): void { + if (process.platform === "darwin") { + return; + } + Menu.setApplicationMenu(null); + window?.setMenu(null); + window?.setMenuBarVisibility(false); +} + function windowModePath(): string { return join(app.getPath("userData"), "window-mode.json"); } @@ -463,6 +472,7 @@ async function createAppWindow(mode: WindowMode): Promise resizable: initial.resizable, maximizable: initial.resizable, fullscreenable: initial.resizable, + autoHideMenuBar: true, backgroundColor: mode === "login" ? "#eaf2ff" : nativeTheme.shouldUseDarkColors ? "#15191a" : "#f0f2f5", webPreferences: { preload: preloadPath(), @@ -472,6 +482,7 @@ async function createAppWindow(mode: WindowMode): Promise }, }); appWindowModes.set(window, mode); + suppressNativeWindowMenu(window); if (!initial.resizable) { window.setMinimumSize(initial.minWidth, initial.minHeight); @@ -548,6 +559,7 @@ async function createSettingsWindow(): Promise { }, }); appWindowModes.set(window, "settings"); + suppressNativeWindowMenu(window); window.once("closed", () => { if (settingsWindow === window) { @@ -703,6 +715,7 @@ if (!hasSingleInstanceLock) { app.exit(0); } else { app.whenReady().then(async () => { + suppressNativeWindowMenu(); currentWindowMode = readPersistedWindowMode(); initDesktopAppSettings(); registerBridgeHandlers(); diff --git a/apps/desktop-client/src/renderer/composables/useDesktopSession.ts b/apps/desktop-client/src/renderer/composables/useDesktopSession.ts index 41c992c..93c3ab9 100644 --- a/apps/desktop-client/src/renderer/composables/useDesktopSession.ts +++ b/apps/desktop-client/src/renderer/composables/useDesktopSession.ts @@ -375,7 +375,7 @@ async function syncRuntimeSessionToMain(next: DesktopSession | null = session.va function formatLoginError(err: unknown): string { if (err instanceof ApiClientError) { const messages: Record = { - invalid_credentials: "邮箱或密码错误", + invalid_credentials: "账号或密码错误", login_rate_limited: "登录请求过于频繁", login_locked: "登录已被临时保护", login_in_progress: "登录请求正在处理中", diff --git a/apps/desktop-client/src/renderer/views/LoginView.vue b/apps/desktop-client/src/renderer/views/LoginView.vue index be556c8..894cac9 100644 --- a/apps/desktop-client/src/renderer/views/LoginView.vue +++ b/apps/desktop-client/src/renderer/views/LoginView.vue @@ -7,10 +7,14 @@ const { apiBaseURL, error, pending, setApiBaseURL, login } = useDesktopSession() const menuOpen = ref(false); const showServerDialog = ref(false); const rememberPassword = ref(!!localStorage.getItem("geo_rankly_saved_password")); +const savedIdentifier = + localStorage.getItem("geo_rankly_saved_identifier") + ?? localStorage.getItem("geo_rankly_saved_email") + ?? ""; const form = reactive({ apiBaseURL: apiBaseURL.value, - email: localStorage.getItem("geo_rankly_saved_email") || "", + identifier: savedIdentifier, password: localStorage.getItem("geo_rankly_saved_password") || "", }); @@ -49,16 +53,17 @@ function saveServerSettings() { async function submitLogin() { if (rememberPassword.value) { - localStorage.setItem("geo_rankly_saved_email", form.email); + localStorage.setItem("geo_rankly_saved_identifier", form.identifier); + localStorage.removeItem("geo_rankly_saved_email"); localStorage.setItem("geo_rankly_saved_password", form.password); } else { + localStorage.removeItem("geo_rankly_saved_identifier"); localStorage.removeItem("geo_rankly_saved_email"); localStorage.removeItem("geo_rankly_saved_password"); } await login({ - identifier: form.email, - email: form.email, + identifier: form.identifier, password: form.password, }); await window.desktopBridge?.app?.setWindowMode?.("main", { source: "login" }); @@ -111,10 +116,10 @@ onBeforeUnmount(() => {