diff --git a/client/electron/src/App.tsx b/client/electron/src/App.tsx
index 3d54adc..6cad852 100644
--- a/client/electron/src/App.tsx
+++ b/client/electron/src/App.tsx
@@ -1,4 +1,6 @@
import { Suspense, lazy, useEffect } from 'react';
+
+import { initAppearanceSync, useAppearanceSync } from './stores/appearanceSync';
import { connectSSE } from './api/sse';
import { useAuthStore } from './stores/authStore';
import { useAccountStore } from './stores/accountStore';
@@ -69,6 +71,16 @@ export default function App() {
}
}, [phase]);
+ // 外观同步(主题 + 壁纸):服务端是权威、本地是缓存。
+ //
+ // 订阅一次就够:它内部盯着 background/theme/账号切换三个来源。拉取放在
+ // "已认证"之后 —— 在那之前没有令牌,拉了也只会把自己标成 local-only。
+ useEffect(() => initAppearanceSync(), []);
+ useEffect(() => {
+ if (phase !== 'authenticated') return;
+ void useAppearanceSync.getState().pull();
+ }, [phase]);
+
// 登录态就绪后拉取数据 + SSE
useEffect(() => {
if (phase !== 'authenticated') return;
diff --git a/client/electron/src/components/BackgroundPicker.tsx b/client/electron/src/components/BackgroundPicker.tsx
index d934ace..196792f 100644
--- a/client/electron/src/components/BackgroundPicker.tsx
+++ b/client/electron/src/components/BackgroundPicker.tsx
@@ -1,4 +1,6 @@
import { useRef, useState } from 'react';
+
+import { useAppearanceSync } from '../stores/appearanceSync';
import {
DEFAULT_BACKGROUND,
MAX_DATA_URL_BYTES,
@@ -64,6 +66,7 @@ export default function BackgroundPicker() {
背景
+
{active && (