feat(Theme): enhance theming and UI consistency across components
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 8m15s
Frontend CI / ota-android (push) Successful in 10m56s
Frontend CI / build-android-apk (push) Successful in 1h3m22s

- Updated app.json to set userInterfaceStyle to automatic for improved theme adaptability.
- Refactored layout components to utilize useAppColors for dynamic theming, ensuring consistent color usage.
- Introduced SystemChrome component to manage system UI background color based on theme.
- Enhanced TabsLayout, ProfileStackLayout, and other components to leverage new theming structure.
- Improved QRCodeScanner, SearchBar, and CommentItem styles to align with the updated theme system.
- Consolidated styles in SystemMessageItem and TabBar for better maintainability and visual coherence.
This commit is contained in:
lafay
2026-03-25 05:16:54 +08:00
parent 90d834695f
commit 4ee3079b9f
86 changed files with 6777 additions and 5890 deletions

View File

@@ -44,6 +44,17 @@ export { userManager } from './userManager';
export {
useHomeTabBarVisibilityStore,
} from './homeTabBarVisibilityStore';
export {
useAppColors,
useThemePreference,
useResolvedColorScheme,
useSetThemePreference,
usePaperThemeFromStore,
ThemeBootstrap,
useThemeStore,
type ThemePreference,
type ResolvedScheme,
} from './themeStore';
export {
useConversations as useMessageManagerConversations,
useMessages,

133
src/stores/themeStore.ts Normal file
View File

@@ -0,0 +1,133 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useColorScheme } from 'react-native';
import { create } from 'zustand';
import { useEffect } from 'react';
import { lightColors, darkColors, type AppColors } from '../theme/palettes';
import { buildPaperTheme } from '../theme/paperTheme';
import type { MD3Theme } from 'react-native-paper';
const STORAGE_KEY = 'app_theme_preference';
export type ThemePreference = 'light' | 'dark' | 'system';
export type ResolvedScheme = 'light' | 'dark';
function computeResolved(pref: ThemePreference, system: ResolvedScheme): ResolvedScheme {
return pref === 'system' ? system : pref;
}
function buildState(
preference: ThemePreference,
systemScheme: ResolvedScheme
): {
resolvedScheme: ResolvedScheme;
colors: AppColors;
paperTheme: MD3Theme;
} {
const resolvedScheme = computeResolved(preference, systemScheme);
const isDark = resolvedScheme === 'dark';
const colors = isDark ? darkColors : lightColors;
return {
resolvedScheme,
colors,
paperTheme: buildPaperTheme(colors, isDark),
};
}
type ThemeState = {
preference: ThemePreference;
systemScheme: ResolvedScheme;
hydrated: boolean;
resolvedScheme: ResolvedScheme;
colors: AppColors;
paperTheme: MD3Theme;
setPreference: (p: ThemePreference) => Promise<void>;
setSystemScheme: (s: ResolvedScheme) => void;
hydrate: () => Promise<void>;
};
const initialSystem: ResolvedScheme = 'light';
export const useThemeStore = create<ThemeState>((set, get) => ({
preference: 'system',
systemScheme: initialSystem,
hydrated: false,
...buildState('system', initialSystem),
setSystemScheme: (systemScheme) => {
const { preference, systemScheme: cur } = get();
if (cur === systemScheme) return;
set({
systemScheme,
...buildState(preference, systemScheme),
});
},
setPreference: async (preference) => {
try {
await AsyncStorage.setItem(STORAGE_KEY, preference);
} catch {
/* ignore */
}
const { systemScheme } = get();
set({
preference,
...buildState(preference, systemScheme),
});
},
hydrate: async () => {
let preference: ThemePreference = 'system';
try {
const raw = await AsyncStorage.getItem(STORAGE_KEY);
if (raw === 'light' || raw === 'dark' || raw === 'system') {
preference = raw;
}
} catch {
/* ignore */
}
const { systemScheme } = get();
set({
preference,
hydrated: true,
...buildState(preference, systemScheme),
});
},
}));
/** 在根布局中同步系统配色并恢复持久化偏好 */
export function ThemeBootstrap() {
const system = useColorScheme();
const setSystemScheme = useThemeStore((s) => s.setSystemScheme);
const hydrate = useThemeStore((s) => s.hydrate);
useEffect(() => {
void hydrate();
}, [hydrate]);
useEffect(() => {
setSystemScheme(system === 'dark' ? 'dark' : 'light');
}, [system, setSystemScheme]);
return null;
}
export function useAppColors() {
return useThemeStore((s) => s.colors);
}
export function useThemePreference() {
return useThemeStore((s) => s.preference);
}
export function useResolvedColorScheme() {
return useThemeStore((s) => s.resolvedScheme);
}
export function useSetThemePreference() {
return useThemeStore((s) => s.setPreference);
}
export function usePaperThemeFromStore() {
return useThemeStore((s) => s.paperTheme);
}