fix: sync runtime config into settings

This commit is contained in:
kuekhaoyang
2026-04-08 13:36:09 +08:00
parent e93c259e4a
commit 4db08dbf72
4 changed files with 87 additions and 61 deletions
+14 -7
View File
@@ -65,18 +65,25 @@ async function generateProfileId(password: string): Promise<string> {
return hashArray.slice(0, 8).map(b => b.toString(16).padStart(2, '0')).join(''); return hashArray.slice(0, 8).map(b => b.toString(16).padStart(2, '0')).join('');
} }
export async function GET() { function getPublicAuthConfig() {
const hasAuth = !!(effectiveAdminPassword || ACCOUNTS);
const runtimeFeatures = getRuntimeFeatures(); const runtimeFeatures = getRuntimeFeatures();
return NextResponse.json({ return {
hasAuth,
hasPremiumAuth: !!PREMIUM_PASSWORD,
persistSession: PERSIST_SESSION, persistSession: PERSIST_SESSION,
subscriptionSources: SUBSCRIPTION_SOURCES, subscriptionSources: SUBSCRIPTION_SOURCES,
iptvSources: runtimeFeatures.iptvEnabled ? IPTV_SOURCES : '', iptvSources: runtimeFeatures.iptvEnabled ? IPTV_SOURCES : '',
mergeSources: MERGE_SOURCES, mergeSources: MERGE_SOURCES,
danmakuApiUrl: DANMAKU_API_URL, danmakuApiUrl: DANMAKU_API_URL,
};
}
export async function GET() {
const hasAuth = !!(effectiveAdminPassword || ACCOUNTS);
return NextResponse.json({
hasAuth,
hasPremiumAuth: !!PREMIUM_PASSWORD,
...getPublicAuthConfig(),
}); });
} }
@@ -119,7 +126,7 @@ export async function POST(request: NextRequest) {
name: '管理员', name: '管理员',
role: 'super_admin', role: 'super_admin',
profileId, profileId,
persistSession: PERSIST_SESSION, ...getPublicAuthConfig(),
}); });
} }
@@ -133,7 +140,7 @@ export async function POST(request: NextRequest) {
name: account.name, name: account.name,
role: account.role, role: account.role,
profileId, profileId,
persistSession: PERSIST_SESSION, ...getPublicAuthConfig(),
customPermissions: account.customPermissions.length > 0 ? account.customPermissions : undefined, customPermissions: account.customPermissions.length > 0 ? account.customPermissions : undefined,
}); });
} }
@@ -36,26 +36,34 @@ export function usePremiumSettingsPage() {
const [blockedCategories, setBlockedCategories] = useState<string[]>([]); const [blockedCategories, setBlockedCategories] = useState<string[]>([]);
useEffect(() => { useEffect(() => {
// Sources come from main settings store const syncFromStores = () => {
const settings = settingsStore.getSettings(); const settings = settingsStore.getSettings();
setPremiumSources(settings.premiumSources || []); const modeSettings = premiumModeSettingsStore.getSettings();
setLocale(settings.locale);
// Mode-specific settings come from premium mode settings store setPremiumSources(settings.premiumSources || []);
const modeSettings = premiumModeSettingsStore.getSettings(); setLocale(settings.locale);
setRealtimeLatency(modeSettings.realtimeLatency); setBlockedCategories(settings.blockedCategories || []);
setSearchDisplayMode(modeSettings.searchDisplayMode);
setFullscreenType(modeSettings.fullscreenType);
setProxyMode(modeSettings.proxyMode);
setSeekStepSeconds(modeSettings.seekStepSeconds);
setRememberScrollPosition(modeSettings.rememberScrollPosition);
setDanmakuApiUrl(modeSettings.danmakuApiUrl);
setDanmakuOpacity(modeSettings.danmakuOpacity);
setDanmakuFontSize(modeSettings.danmakuFontSize);
setDanmakuDisplayArea(modeSettings.danmakuDisplayArea);
// blockedCategories is global setRealtimeLatency(modeSettings.realtimeLatency);
setBlockedCategories(settings.blockedCategories || []); setSearchDisplayMode(modeSettings.searchDisplayMode);
setFullscreenType(modeSettings.fullscreenType);
setProxyMode(modeSettings.proxyMode);
setSeekStepSeconds(modeSettings.seekStepSeconds);
setRememberScrollPosition(modeSettings.rememberScrollPosition);
setDanmakuApiUrl(modeSettings.danmakuApiUrl);
setDanmakuOpacity(modeSettings.danmakuOpacity);
setDanmakuFontSize(modeSettings.danmakuFontSize);
setDanmakuDisplayArea(modeSettings.danmakuDisplayArea);
};
syncFromStores();
const unsubscribeSettings = settingsStore.subscribe(syncFromStores);
const unsubscribePremiumSettings = premiumModeSettingsStore.subscribe(syncFromStores);
return () => {
unsubscribeSettings();
unsubscribePremiumSettings();
};
}, []); }, []);
// --- Source management (uses main settingsStore) --- // --- Source management (uses main settingsStore) ---
+22 -17
View File
@@ -48,23 +48,28 @@ export function useSettingsPage() {
const [blockedCategories, setBlockedCategories] = useState<string[]>([]); const [blockedCategories, setBlockedCategories] = useState<string[]>([]);
useEffect(() => { useEffect(() => {
const settings = settingsStore.getSettings(); const syncFromStore = () => {
setSources(settings.sources || []); const settings = settingsStore.getSettings();
setSubscriptions(settings.subscriptions || []); setSources(settings.sources || []);
setSortBy(settings.sortBy); setSubscriptions(settings.subscriptions || []);
setRealtimeLatency(settings.realtimeLatency); setSortBy(settings.sortBy);
setSearchDisplayMode(settings.searchDisplayMode); setRealtimeLatency(settings.realtimeLatency);
setFullscreenType(settings.fullscreenType); setSearchDisplayMode(settings.searchDisplayMode);
setProxyMode(settings.proxyMode); setFullscreenType(settings.fullscreenType);
setSeekStepSeconds(settings.seekStepSeconds); setProxyMode(settings.proxyMode);
setRememberScrollPosition(settings.rememberScrollPosition); setSeekStepSeconds(settings.seekStepSeconds);
setLocale(settings.locale); setRememberScrollPosition(settings.rememberScrollPosition);
setVideoTogetherEnabled(settings.videoTogetherEnabled); setLocale(settings.locale);
setDanmakuApiUrl(settings.danmakuApiUrl); setVideoTogetherEnabled(settings.videoTogetherEnabled);
setDanmakuOpacity(settings.danmakuOpacity); setDanmakuApiUrl(settings.danmakuApiUrl);
setDanmakuFontSize(settings.danmakuFontSize); setDanmakuOpacity(settings.danmakuOpacity);
setDanmakuDisplayArea(settings.danmakuDisplayArea); setDanmakuFontSize(settings.danmakuFontSize);
setBlockedCategories(settings.blockedCategories || []); setDanmakuDisplayArea(settings.danmakuDisplayArea);
setBlockedCategories(settings.blockedCategories || []);
};
syncFromStore();
return settingsStore.subscribe(syncFromStore);
}, []); }, []);
const handleSourcesChange = (newSources: VideoSource[]) => { const handleSourcesChange = (newSources: VideoSource[]) => {
+25 -19
View File
@@ -65,6 +65,29 @@ function syncDanmakuApiUrl(rawValue: string) {
} }
} }
function applyRuntimeConfig(data: {
subscriptionSources?: string;
iptvSources?: string;
mergeSources?: string;
danmakuApiUrl?: string;
}) {
if (data.subscriptionSources) {
settingsStore.syncEnvSubscriptions(data.subscriptionSources);
}
if (data.iptvSources) {
syncIPTVSources(data.iptvSources);
}
if (data.mergeSources) {
syncMergeSources(data.mergeSources);
}
if (data.danmakuApiUrl) {
syncDanmakuApiUrl(data.danmakuApiUrl);
}
}
export function PasswordGate({ children, hasAuth: initialHasAuth }: { children: React.ReactNode, hasAuth: boolean }) { export function PasswordGate({ children, hasAuth: initialHasAuth }: { children: React.ReactNode, hasAuth: boolean }) {
// Enable background subscription syncing globally // Enable background subscription syncing globally
useSubscriptionSync(); useSubscriptionSync();
@@ -102,25 +125,7 @@ export function PasswordGate({ children, hasAuth: initialHasAuth }: { children:
if (mounted) { if (mounted) {
setHasAuth(data.hasAuth); setHasAuth(data.hasAuth);
setPersistSession(data.persistSession); setPersistSession(data.persistSession);
applyRuntimeConfig(data);
// Sync subscriptions
if (data.subscriptionSources) {
settingsStore.syncEnvSubscriptions(data.subscriptionSources);
}
// Sync IPTV sources from env
if (data.iptvSources) {
syncIPTVSources(data.iptvSources);
}
// Sync merge sources setting from env
if (data.mergeSources) {
syncMergeSources(data.mergeSources);
}
if (data.danmakuApiUrl) {
syncDanmakuApiUrl(data.danmakuApiUrl);
}
// Re-evaluate lock status with confirmed server state // Re-evaluate lock status with confirmed server state
const confirmLocked = data.hasAuth && !isAuthenticated; const confirmLocked = data.hasAuth && !isAuthenticated;
@@ -149,6 +154,7 @@ export function PasswordGate({ children, hasAuth: initialHasAuth }: { children:
const data = await res.json(); const data = await res.json();
if (data.valid) { if (data.valid) {
applyRuntimeConfig(data);
setSession({ setSession({
profileId: data.profileId, profileId: data.profileId,
name: data.name, name: data.name,