1- import React , { useMemo , useState } from "react" ;
1+ import React , { useMemo , useState , useEffect } from "react" ;
22import { useSearchParams } from "react-router-dom" ;
33import { Download , File as FileIcon , Loader2 , AlertCircle } from "lucide-react" ;
44import { AppConfig , WorkerResponse } from "../../types" ;
55import { DEFAULT_WORKER_URL } from "../../types" ;
6+ import {
7+ CONFIG_STORAGE_KEY ,
8+ THEME_STORAGE_KEY ,
9+ t ,
10+ DEFAULT_LANG ,
11+ } from "../../constants" ;
612
713// Helper to decode the share payload
814// payload = base64(json({ w: workerUrl, f: fileId, n: fileName }))
@@ -21,6 +27,55 @@ export function SharePage() {
2127 const [ searchParams ] = useSearchParams ( ) ;
2228 const shareParam = searchParams . get ( "s" ) ;
2329
30+ // Theme State
31+ type Theme = "light" | "dark" | "system" ;
32+ const [ theme , setTheme ] = useState < Theme > ( ( ) => {
33+ const saved = localStorage . getItem ( THEME_STORAGE_KEY ) ;
34+ // Migration: if saved is boolean (old), convert to 'light'/'dark'
35+ if ( saved === "true" ) return "dark" ;
36+ if ( saved === "false" ) return "light" ;
37+ // Remove quotes if they exist (JSON.stringify adds them)
38+ const cleanSaved = saved ? saved . replace ( / " / g, "" ) : null ;
39+ return ( cleanSaved as Theme ) || "system" ;
40+ } ) ;
41+ useEffect ( ( ) => {
42+ const applyTheme = ( ) => {
43+ const isDark =
44+ theme === "dark" ||
45+ ( theme === "system" &&
46+ window . matchMedia ( "(prefers-color-scheme: dark)" ) . matches ) ;
47+
48+ if ( isDark ) {
49+ document . documentElement . classList . add ( "dark" ) ;
50+ } else {
51+ document . documentElement . classList . remove ( "dark" ) ;
52+ }
53+ } ;
54+
55+ applyTheme ( ) ;
56+ localStorage . setItem ( THEME_STORAGE_KEY , theme ) ;
57+
58+ if ( theme === "system" ) {
59+ const mediaQuery = window . matchMedia ( "(prefers-color-scheme: dark)" ) ;
60+ const handler = ( ) => applyTheme ( ) ;
61+ mediaQuery . addEventListener ( "change" , handler ) ;
62+ return ( ) => mediaQuery . removeEventListener ( "change" , handler ) ;
63+ }
64+ } , [ theme ] ) ;
65+
66+ // Lang
67+ const [ language , setLanguage ] = useState ( ( ) => {
68+ const saved = localStorage . getItem ( CONFIG_STORAGE_KEY ) ;
69+ return saved
70+ ? JSON . parse ( saved ) . language
71+ : ( navigator . languages ?. [ 0 ] || navigator . language ) . split ( "-" ) [ 0 ] ||
72+ DEFAULT_LANG ;
73+ } ) ;
74+ useEffect ( ( ) => {
75+ document . documentElement . lang = language ;
76+ localStorage . setItem ( CONFIG_STORAGE_KEY , JSON . stringify ( { language } ) ) ;
77+ } , [ language ] ) ;
78+
2479 const result = React . useMemo ( ( ) => {
2580 if ( ! shareParam ) {
2681 return { error : "Invalid share link: Missing parameters" } ;
@@ -69,7 +124,9 @@ export function SharePage() {
69124 return (
70125 < div className = "flex flex-col items-center justify-center h-screen bg-slate-50 dark:bg-slate-900 text-slate-800 dark:text-white p-4" >
71126 < AlertCircle className = "w-12 h-12 text-red-500 mb-4" />
72- < h1 className = "text-xl font-bold mb-2" > Error</ h1 >
127+ < h1 className = "text-xl font-bold mb-2" >
128+ { t ( language , "share_error_title" ) }
129+ </ h1 >
73130 < p className = "text-slate-500 dark:text-slate-400" > { result . error } </ p >
74131 </ div >
75132 ) ;
@@ -93,20 +150,24 @@ export function SharePage() {
93150 < h2 className = "text-2xl font-bold text-slate-900 dark:text-white mb-2 break-all" >
94151 { result . fileInfo . fileName }
95152 </ h2 >
96- < p className = "text-slate-500 dark:text-slate-400 mb-8" > Shared File</ p >
153+ < p className = "text-slate-500 dark:text-slate-400 mb-8" >
154+ { t ( language , "share_file_label" ) }
155+ </ p >
97156
98157 < a
99158 href = { result . fileInfo . downloadUrl }
100159 className = "block w-full py-4 bg-telegram-500 hover:bg-telegram-600 text-white rounded-xl font-bold text-lg shadow-lg shadow-telegram-500/20 transition-all transform hover:-translate-y-1 active:translate-y-0"
101160 >
102161 < div className = "flex items-center justify-center gap-2" >
103162 < Download className = "w-6 h-6" />
104- Download
163+ { t ( language , "share_download_button" ) }
105164 </ div >
106165 </ a >
107166
108167 < div className = "mt-8 pt-6 border-t border-slate-100 dark:border-slate-700" >
109- < p className = "text-xs text-slate-400" > Hosted via TeleCloud</ p >
168+ < p className = "text-xs text-slate-400" >
169+ { t ( language , "share_footer_hostedVia" ) }
170+ </ p >
110171 </ div >
111172 </ div >
112173 </ div >
0 commit comments