Skip to content

Commit 0af8551

Browse files
committed
refactor: introduce SettingsGroup/SettingsItem layout components and auto-save for text fields
1 parent a4c457f commit 0af8551

13 files changed

Lines changed: 939 additions & 845 deletions

src/components/PathSettingsModal.tsx

Lines changed: 161 additions & 114 deletions
Large diffs are not rendered by default.

src/hooks/features/useBgmAuthController.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { listen } from "@tauri-apps/api/event";
22
import { open as openurl } from "@tauri-apps/plugin-shell";
3-
import { useCallback, useEffect, useState } from "react";
3+
import { useCallback, useEffect, useRef, useState } from "react";
44
import { useTranslation } from "react-i18next";
55
import { buildManualBgmAuth, completeBgmAuth } from "@/api/bgm";
66
import { useAllSettings, useUpdateSettings } from "@/hooks/queries/useSettings";
@@ -36,6 +36,7 @@ export function useBgmAuthController() {
3636
const [isOAuthLoading, setIsOAuthLoading] = useState(isBgmOAuthRunning);
3737
const [isCompletingAuth, setIsCompletingAuth] = useState(false);
3838
const [isSavingToken, setIsSavingToken] = useState(false);
39+
const isSavingTokenRef = useRef(false);
3940

4041
useEffect(() => {
4142
setInputToken(bgmToken);
@@ -55,8 +56,16 @@ export function useBgmAuthController() {
5556

5657
const handleSaveToken = async () => {
5758
const accessToken = inputToken.trim();
59+
if (accessToken === bgmToken || isSavingTokenRef.current) return;
60+
5861
try {
62+
isSavingTokenRef.current = true;
5963
setIsSavingToken(true);
64+
if (!accessToken) {
65+
await logoutBgmAuth();
66+
return;
67+
}
68+
6069
const auth = await buildManualBgmAuth(accessToken);
6170

6271
await updateSettingsMutation.mutateAsync({
@@ -75,12 +84,32 @@ export function useBgmAuthController() {
7584
),
7685
);
7786
} finally {
87+
isSavingTokenRef.current = false;
7888
setIsSavingToken(false);
7989
}
8090
};
8191

82-
const handleClearToken = () => {
92+
const handleClearToken = async () => {
8393
setInputToken("");
94+
if (!bgmToken || isSavingTokenRef.current) return;
95+
96+
try {
97+
isSavingTokenRef.current = true;
98+
setIsSavingToken(true);
99+
await logoutBgmAuth();
100+
snackbar.success(
101+
t("pages.Settings.bgmTokenSettings.logoutSuccess", "已退出 BGM 登录"),
102+
);
103+
} catch (error) {
104+
console.error(error);
105+
setInputToken(bgmToken);
106+
snackbar.error(
107+
t("pages.Settings.bgmTokenSettings.logoutError", "退出登录失败"),
108+
);
109+
} finally {
110+
isSavingTokenRef.current = false;
111+
setIsSavingToken(false);
112+
}
84113
};
85114

86115
const handleOAuthLogin = useCallback(async () => {

src/locales/en-US.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,13 +613,17 @@
613613
"userInfo": "User info"
614614
},
615615
"cardClickMode": {
616+
"description": "Controls single-click behavior for game cards in the library and collections. Double-click always launches the game.",
616617
"navigate": "Navigation Mode (Single click to view details)",
617618
"select": "Selection Mode (Single click to select game)",
618619
"title": "Card Click Mode"
619620
},
620621
"closeApp": "Exit application",
622+
"closeAppDescription": "Close the window and end the application process.",
621623
"closeSettings": "Close Settings",
624+
"closeSettingsDescription": "Choose whether closing the window asks for confirmation and what happens when confirmation is skipped.",
622625
"closeToTray": "Minimize to tray",
626+
"closeToTrayDescription": "Keep the application running in the system tray after closing the window.",
623627
"collectionSync": {
624628
"bgmDescription": "Try to read the BGM collection status when adding a game, and sync local status changes back to BGM.",
625629
"bgmTitle": "Enable Bangumi collection sync",
@@ -630,6 +634,7 @@
630634
},
631635
"databaseBackup": {
632636
"autoBackupOnExit": "Auto backup on exit",
637+
"autoBackupOnExitDescription": "When enabled, the database is backed up when the application exits normally. Also backing up custom covers may delay exit.",
633638
"autoIncludeCovers": "Also back up custom covers",
634639
"autoMinIntervalHelp": "Use 0 to back up every time you exit",
635640
"autoMinIntervalHours": "Minimum interval (hours)",
@@ -723,6 +728,7 @@
723728
"systemDescription": "Manage startup, logs, close behavior, and time tracking mode."
724729
},
725730
"skipCloseRemind": "Don't remind again",
731+
"skipCloseRemindDescription": "Skip the close confirmation and immediately perform the selected default action.",
726732
"spoilerLevel": {
727733
"description": "Select spoiler level to get appropriate tag content",
728734
"level0": "0 - No Spoiler",

src/locales/ja-JP.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,13 +600,17 @@
600600
"userInfo": "ユーザー情報"
601601
},
602602
"cardClickMode": {
603+
"description": "ライブラリとコレクションのゲームカードをシングルクリックしたときの動作です。どちらのモードでもダブルクリックでゲームを起動できます。",
603604
"navigate": "ナビゲーションモード(シングルクリックで詳細表示)",
604605
"select": "選択モード(シングルクリックでゲーム選択)",
605606
"title": "カードクリックモード"
606607
},
607608
"closeApp": "アプリを終了",
609+
"closeAppDescription": "ウィンドウを閉じてアプリケーションを終了します。",
608610
"closeSettings": "終了設定",
611+
"closeSettingsDescription": "ウィンドウを閉じる際の確認表示と、確認を省略した場合の既定動作を設定します。",
609612
"closeToTray": "トレイに最小化",
613+
"closeToTrayDescription": "ウィンドウを閉じた後もシステムトレイでアプリを実行します。",
610614
"collectionSync": {
611615
"bgmDescription": "ゲーム追加時に BGM のコレクション状態を読み取り、ローカルで状態を変更したときに BGM に同期します。",
612616
"bgmTitle": "Bangumi コレクション同期を有効化",
@@ -617,6 +621,7 @@
617621
},
618622
"databaseBackup": {
619623
"autoBackupOnExit": "終了時に自動バックアップ",
624+
"autoBackupOnExitDescription": "有効にすると、アプリが正常終了する際にデータベースを自動でバックアップします。カスタムカバーも同時にバックアップすると、終了に時間がかかる場合があります。",
620625
"autoIncludeCovers": "カスタムカバーもバックアップ",
621626
"autoMinIntervalHelp": "0 にすると終了ごとにバックアップします",
622627
"autoMinIntervalHours": "最小間隔(時間)",
@@ -710,6 +715,7 @@
710715
"systemDescription": "起動、ログ、終了動作、時間計測モードを管理します。"
711716
},
712717
"skipCloseRemind": "再度確認しない",
718+
"skipCloseRemindDescription": "終了確認を表示せず、下で選択した既定動作をすぐに実行します。",
713719
"spoilerLevel": {
714720
"description": "ネタバレレベルを選択して、適切なタグコンテンツを取得する",
715721
"level0": "0 - ネタバレなし",

src/locales/zh-CN.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,13 +600,17 @@
600600
"userInfo": "用户信息"
601601
},
602602
"cardClickMode": {
603+
"description": "仓库与收藏夹游戏卡片单击的行为(两种模式下均可双击游戏卡片启动游戏)。",
603604
"navigate": "导航模式(单击跳转详情页)",
604605
"select": "选择模式(单击选择游戏)",
605606
"title": "卡片点击模式"
606607
},
607608
"closeApp": "直接退出应用",
609+
"closeAppDescription": "关闭窗口后结束应用进程。",
608610
"closeSettings": "关闭设置",
611+
"closeSettingsDescription": "点击关闭按钮是否显示关闭确认弹窗,并选择跳过确认弹窗后的默认行为。",
609612
"closeToTray": "最小化到托盘",
613+
"closeToTrayDescription": "关闭窗口后应用继续在系统托盘中运行。",
610614
"collectionSync": {
611615
"bgmDescription": "添加游戏时尝试读取 BGM 收藏状态,本地修改状态时同步回 BGM。",
612616
"bgmTitle": "启用 Bangumi 收藏同步",
@@ -617,6 +621,7 @@
617621
},
618622
"databaseBackup": {
619623
"autoBackupOnExit": "退出时自动备份",
624+
"autoBackupOnExitDescription": "开启后,软件正常退出时会自动备份数据库;如果同时启用自定义封面备份,可能会延长退出时间。",
620625
"autoIncludeCovers": "同时备份自定义封面",
621626
"autoMinIntervalHelp": "填 0 表示每次退出都备份",
622627
"autoMinIntervalHours": "最小间隔(小时)",
@@ -710,6 +715,7 @@
710715
"systemDescription": "管理启动、日志、关闭行为和计时模式。"
711716
},
712717
"skipCloseRemind": "不再提醒",
718+
"skipCloseRemindDescription": "开启后不再显示关闭确认弹窗,直接执行下方选择的默认行为。",
713719
"spoilerLevel": {
714720
"description": "选择剧透等级以获取合适的标签内容",
715721
"level0": "0 - 无剧透",

src/locales/zh-TW.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,13 +600,17 @@
600600
"userInfo": "使用者資訊"
601601
},
602602
"cardClickMode": {
603+
"description": "遊戲庫與收藏夾遊戲卡片單擊時的行為(兩種模式下皆可雙擊遊戲卡片啟動遊戲)。",
603604
"navigate": "導航模式(單擊跳轉詳情頁)",
604605
"select": "選擇模式(單擊選擇遊戲)",
605606
"title": "卡片點擊模式"
606607
},
607608
"closeApp": "直接退出應用",
609+
"closeAppDescription": "關閉視窗後結束應用程式行程。",
608610
"closeSettings": "關閉設定",
611+
"closeSettingsDescription": "點擊關閉按鈕時是否顯示關閉確認彈窗,並選擇略過確認彈窗後的預設行為。",
609612
"closeToTray": "最小化到系統匣",
613+
"closeToTrayDescription": "關閉視窗後應用程式繼續在系統匣中執行。",
610614
"collectionSync": {
611615
"bgmDescription": "新增遊戲時會嘗試讀取 BGM 收藏狀態,本地修改狀態時會同步回 BGM。",
612616
"bgmTitle": "啟用 Bangumi 收藏同步",
@@ -617,6 +621,7 @@
617621
},
618622
"databaseBackup": {
619623
"autoBackupOnExit": "退出時自動備份",
624+
"autoBackupOnExitDescription": "開啟後,軟體正常退出時會自動備份資料庫;如果同時啟用自訂封面備份,可能會延長退出時間。",
620625
"autoIncludeCovers": "同時備份自訂封面",
621626
"autoMinIntervalHelp": "填 0 表示每次退出都備份",
622627
"autoMinIntervalHours": "最小間隔(小時)",
@@ -710,6 +715,7 @@
710715
"systemDescription": "管理啟動、日誌、關閉行為與計時模式。"
711716
},
712717
"skipCloseRemind": "不再提醒",
718+
"skipCloseRemindDescription": "開啟後不再顯示關閉確認彈窗,直接執行下方選擇的預設行為。",
713719
"spoilerLevel": {
714720
"description": "選擇劇透等級以獲取適當的標籤內容",
715721
"level0": "0 - 無劇透",

0 commit comments

Comments
 (0)