- Updated CommentItem component to accept the comment object in the onLike callback, allowing for more detailed like handling. - Added a like button for replies, improving user interaction with nested comments. - Refactored handleLikeComment function in PostDetailScreen for optimized state management and error handling during like operations. - Enhanced SettingsScreen to provide debug information for theme preferences, improving user experience in theme selection. - Updated themeStore to dynamically manage system theme changes and improve overall theme handling.
168 lines
4.4 KiB
TypeScript
168 lines
4.4 KiB
TypeScript
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import { Appearance, AppState, AppStateStatus } from 'react-native';
|
|
import { create } from 'zustand';
|
|
import { useEffect, useRef } 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>;
|
|
};
|
|
|
|
/** 获取系统主题 */
|
|
function getSystemScheme(): ResolvedScheme {
|
|
const scheme = Appearance.getColorScheme();
|
|
return scheme === 'dark' ? 'dark' : 'light';
|
|
}
|
|
|
|
const initialSystemScheme = getSystemScheme();
|
|
|
|
export const useThemeStore = create<ThemeState>((set, get) => ({
|
|
preference: 'system',
|
|
systemScheme: initialSystemScheme,
|
|
hydrated: false,
|
|
...buildState('system', initialSystemScheme),
|
|
|
|
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 = getSystemScheme();
|
|
set({
|
|
preference,
|
|
hydrated: true,
|
|
systemScheme,
|
|
...buildState(preference, systemScheme),
|
|
});
|
|
},
|
|
}));
|
|
|
|
/** 在根布局中同步系统配色并恢复持久化偏好 */
|
|
export function ThemeBootstrap() {
|
|
const setSystemScheme = useThemeStore((s) => s.setSystemScheme);
|
|
const hydrate = useThemeStore((s) => s.hydrate);
|
|
const appState = useRef<AppStateStatus>(AppState.currentState);
|
|
|
|
useEffect(() => {
|
|
void hydrate();
|
|
}, [hydrate]);
|
|
|
|
// 监听系统主题变化
|
|
useEffect(() => {
|
|
const subscription = Appearance.addChangeListener(({ colorScheme }) => {
|
|
const newScheme = colorScheme === 'dark' ? 'dark' : 'light';
|
|
setSystemScheme(newScheme);
|
|
});
|
|
|
|
return () => {
|
|
subscription.remove();
|
|
};
|
|
}, [setSystemScheme]);
|
|
|
|
// 监听应用状态变化,从后台恢复时重新检测系统主题
|
|
useEffect(() => {
|
|
const subscription = AppState.addEventListener('change', (nextAppState) => {
|
|
if (
|
|
appState.current.match(/inactive|background/) &&
|
|
nextAppState === 'active'
|
|
) {
|
|
setSystemScheme(getSystemScheme());
|
|
}
|
|
appState.current = nextAppState;
|
|
});
|
|
|
|
return () => {
|
|
subscription.remove();
|
|
};
|
|
}, [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);
|
|
}
|
|
|
|
// 导出调试函数
|
|
export { getSystemScheme }; |