From 95cee83bf42255f84c71f0a4d57c225945c44e42 Mon Sep 17 00:00:00 2001 From: kuekhaoyang Date: Thu, 25 Dec 2025 16:57:15 +0800 Subject: [PATCH] feat: Synchronize environment-provided subscription sources with user settings. --- app/api/config/route.ts | 2 ++ components/PasswordGate.tsx | 5 +++++ lib/store/settings-store.ts | 45 ++++++++++++++++++++++++++++++++----- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/app/api/config/route.ts b/app/api/config/route.ts index 97a4772..ffb8b54 100644 --- a/app/api/config/route.ts +++ b/app/api/config/route.ts @@ -8,10 +8,12 @@ import { NextRequest, NextResponse } from 'next/server'; export const runtime = 'edge'; const ACCESS_PASSWORD = process.env.ACCESS_PASSWORD || ''; +const SUBSCRIPTION_SOURCES = process.env.SUBSCRIPTION_SOURCES || process.env.NEXT_PUBLIC_SUBSCRIPTION_SOURCES || ''; export async function GET() { return NextResponse.json({ hasEnvPassword: ACCESS_PASSWORD.length > 0, + subscriptionSources: SUBSCRIPTION_SOURCES, }); } diff --git a/components/PasswordGate.tsx b/components/PasswordGate.tsx index 2aa9e5b..4a9bf4b 100644 --- a/components/PasswordGate.tsx +++ b/components/PasswordGate.tsx @@ -25,6 +25,11 @@ export function PasswordGate({ children }: { children: React.ReactNode }) { const res = await fetch('/api/config'); const data = await res.json(); setHasEnvPassword(data.hasEnvPassword); + + // Sync subscription sources if provided by environment + if (data.subscriptionSources) { + settingsStore.syncEnvSubscriptions(data.subscriptionSources); + } } catch { // Silently fail - env password not available } diff --git a/lib/store/settings-store.ts b/lib/store/settings-store.ts index 9f77af6..531b433 100644 --- a/lib/store/settings-store.ts +++ b/lib/store/settings-store.ts @@ -44,12 +44,8 @@ export const getDefaultAdultSources = (): VideoSource[] => ADULT_SOURCES; -function getEnvSubscriptions(): SourceSubscription[] { - if (typeof process === 'undefined' || !process.env.NEXT_PUBLIC_SUBSCRIPTION_SOURCES) { - return []; - } - - const envValue = process.env.NEXT_PUBLIC_SUBSCRIPTION_SOURCES.trim(); +function getEnvSubscriptions(customValue?: string): SourceSubscription[] { + const envValue = (customValue || process.env.SUBSCRIPTION_SOURCES || process.env.NEXT_PUBLIC_SUBSCRIPTION_SOURCES || '').trim(); if (!envValue) return []; // 1. Try JSON @@ -231,6 +227,43 @@ export const settingsStore = { return importSettings(jsonString, (s) => this.saveSettings(s), this.getSettings()); }, + syncEnvSubscriptions(rawEnvValue: string): void { + if (typeof window === 'undefined') return; + + const currentSettings = this.getSettings(); + const envSubs = getEnvSubscriptions(rawEnvValue); + + if (envSubs.length === 0) return; + + const mergedSubscriptions = [...currentSettings.subscriptions]; + let changed = false; + + envSubs.forEach(envSub => { + const existingIndex = mergedSubscriptions.findIndex(s => s.url === envSub.url); + if (existingIndex > -1) { + // Only update if something meaningful changed to avoid unnecessary re-renders + if (mergedSubscriptions[existingIndex].name !== envSub.name) { + mergedSubscriptions[existingIndex] = { + ...mergedSubscriptions[existingIndex], + name: envSub.name, + autoRefresh: true + }; + changed = true; + } + } else { + mergedSubscriptions.push(envSub); + changed = true; + } + }); + + if (changed) { + this.saveSettings({ + ...currentSettings, + subscriptions: mergedSubscriptions + }); + } + }, + resetToDefaults(): void { if (typeof window !== 'undefined') { localStorage.removeItem(SETTINGS_KEY);