11import resources from "virtual:i18next-loader" ;
22import {
3- ArrowHookUpLeft24Regular ,
43 ContentView24Regular ,
5- Dismiss24Regular ,
64 History24Regular ,
7- Image24Regular ,
85 Keyboard12324Regular ,
96 LocalLanguage24Regular ,
107 PaddingLeft24Regular ,
@@ -15,32 +12,15 @@ import {
1512 Timer24Regular ,
1613 TopSpeed24Regular ,
1714} from "@fluentui/react-icons" ;
18- import {
19- Box ,
20- Button ,
21- Card ,
22- Flex ,
23- Heading ,
24- IconButton ,
25- Select ,
26- Slider ,
27- Switch ,
28- Text ,
29- TextField ,
30- } from "@radix-ui/themes" ;
15+ import { Box , Card , Flex , Heading , Select , Slider , Switch , Text , TextField } from "@radix-ui/themes" ;
3116import { useAtom } from "jotai" ;
32- import { useCallback , useRef , useState } from "react" ;
17+ import { useState } from "react" ;
3318import { useTranslation } from "react-i18next" ;
3419import { playbackRateAtom , volumeAtom } from "$/modules/audio/states" ;
3520import {
3621 autosaveEnabledAtom ,
3722 autosaveIntervalAtom ,
3823 autosaveLimitAtom ,
39- customBackgroundBlurAtom ,
40- customBackgroundBrightnessAtom ,
41- customBackgroundImageAtom ,
42- customBackgroundMaskAtom ,
43- customBackgroundOpacityAtom ,
4424 LayoutMode ,
4525 layoutModeAtom ,
4626 SyncJudgeMode ,
@@ -52,6 +32,10 @@ import {
5232 KeyBindingTriggerMode ,
5333 keyBindingTriggerModeAtom ,
5434} from "$/utils/keybindings" ;
35+ import {
36+ SettingsCustomBackgroundCard ,
37+ SettingsCustomBackgroundSettings ,
38+ } from "./customBackground" ;
5539
5640const languageOptions : readonly string [ ] = Object . keys ( resources ) ;
5741
@@ -61,21 +45,6 @@ export const SettingsCommonTab = () => {
6145 const [ keyBindingTriggerMode , setKeyBindingTriggerMode ] = useAtom (
6246 keyBindingTriggerModeAtom ,
6347 ) ;
64- const [ customBackgroundImage , setCustomBackgroundImage ] = useAtom (
65- customBackgroundImageAtom ,
66- ) ;
67- const [ customBackgroundOpacity , setCustomBackgroundOpacity ] = useAtom (
68- customBackgroundOpacityAtom ,
69- ) ;
70- const [ customBackgroundMask , setCustomBackgroundMask ] = useAtom (
71- customBackgroundMaskAtom ,
72- ) ;
73- const [ customBackgroundBlur , setCustomBackgroundBlur ] = useAtom (
74- customBackgroundBlurAtom ,
75- ) ;
76- const [ customBackgroundBrightness , setCustomBackgroundBrightness ] = useAtom (
77- customBackgroundBrightnessAtom ,
78- ) ;
7948 const [ smartFirstWord , setSmartFirstWord ] = useAtom ( smartFirstWordAtom ) ;
8049 const [ smartLastWord , setSmartLastWord ] = useAtom ( smartLastWordAtom ) ;
8150 const [ volume , setVolume ] = useAtom ( volumeAtom ) ;
@@ -85,7 +54,6 @@ export const SettingsCommonTab = () => {
8554 const [ autosaveLimit , setAutosaveLimit ] = useAtom ( autosaveLimitAtom ) ;
8655 const { t, i18n } = useTranslation ( ) ;
8756 const currentLanguage = i18n . resolvedLanguage || i18n . language ;
88- const backgroundFileInputRef = useRef < HTMLInputElement > ( null ) ;
8957 const [ showBackgroundSettings , setShowBackgroundSettings ] = useState ( false ) ;
9058
9159 const getLanguageName = ( code : string , locale : string ) => {
@@ -118,193 +86,11 @@ export const SettingsCommonTab = () => {
11886 return code ;
11987 } ;
12088
121- const onSelectBackgroundFile = useCallback ( ( file : File ) => {
122- const reader = new FileReader ( ) ;
123- reader . onload = ( ) => {
124- if ( typeof reader . result === "string" ) {
125- setCustomBackgroundImage ( reader . result ) ;
126- }
127- } ;
128- reader . readAsDataURL ( file ) ;
129- } , [ setCustomBackgroundImage ] ) ;
130-
13189 if ( showBackgroundSettings ) {
13290 return (
133- < Flex direction = "column" gap = "4" >
134- < Flex align = "center" justify = "between" >
135- < Heading size = "4" >
136- { t ( "settings.common.customBackground" , "自定义背景" ) }
137- </ Heading >
138- < IconButton
139- variant = "ghost"
140- onClick = { ( ) => setShowBackgroundSettings ( false ) }
141- >
142- < Dismiss24Regular />
143- </ IconButton >
144- </ Flex >
145-
146- < Card >
147- < Flex direction = "column" gap = "3" >
148- < Text size = "1" color = "gray" >
149- { t (
150- "settings.common.customBackgroundDesc" ,
151- "选择一张图片作为背景。" ,
152- ) }
153- </ Text >
154- < input
155- ref = { backgroundFileInputRef }
156- type = "file"
157- accept = "image/*"
158- style = { { display : "none" } }
159- onChange = { ( event ) => {
160- const file = event . target . files ?. [ 0 ] ;
161- if ( ! file ) return ;
162- onSelectBackgroundFile ( file ) ;
163- event . target . value = "" ;
164- } }
165- />
166- < Flex gap = "2" align = "center" >
167- < Button
168- variant = "soft"
169- onClick = { ( ) => backgroundFileInputRef . current ?. click ( ) }
170- >
171- { t ( "settings.common.customBackgroundPick" , "选择图片" ) }
172- </ Button >
173- < Button
174- variant = "ghost"
175- disabled = { ! customBackgroundImage }
176- onClick = { ( ) => setCustomBackgroundImage ( null ) }
177- >
178- { t ( "settings.common.customBackgroundClear" , "清除" ) }
179- </ Button >
180- </ Flex >
181- </ Flex >
182- </ Card >
183-
184- < Card >
185- < Flex direction = "column" gap = "2" >
186- < Flex align = "center" justify = "between" >
187- < Text > { t ( "settings.common.customBackgroundOpacity" , "透明度" ) } </ Text >
188- < Flex align = "center" gap = "2" >
189- < Text wrap = "nowrap" color = "gray" size = "1" >
190- { Math . round ( customBackgroundOpacity * 100 ) } %
191- </ Text >
192- { customBackgroundOpacity !== 0.4 && (
193- < IconButton
194- variant = "ghost"
195- size = "1"
196- onClick = { ( ) => setCustomBackgroundOpacity ( 0.4 ) }
197- >
198- < ArrowHookUpLeft24Regular />
199- </ IconButton >
200- ) }
201- </ Flex >
202- </ Flex >
203- < Slider
204- min = { 0 }
205- max = { 1 }
206- step = { 0.01 }
207- value = { [ customBackgroundOpacity ] }
208- onValueChange = { ( v ) => setCustomBackgroundOpacity ( v [ 0 ] ) }
209- />
210- { customBackgroundOpacity >= 0.5 && (
211- < Text size = "1" color = "orange" >
212- { t (
213- "settings.common.customBackgroundOpacityWarning" ,
214- "如果这个数值太高可能让你看不清页面上的内容。" ,
215- ) }
216- </ Text >
217- ) }
218- </ Flex >
219- </ Card >
220-
221- < Card style = { { marginBottom : "var(--space-1)" } } >
222- < Flex direction = "column" gap = "2" >
223- < Flex align = "center" justify = "between" >
224- < Text > { t ( "settings.common.customBackgroundMask" , "遮罩" ) } </ Text >
225- < Flex align = "center" gap = "2" >
226- < Text wrap = "nowrap" color = "gray" size = "1" >
227- { Math . round ( customBackgroundMask * 100 ) } %
228- </ Text >
229- { customBackgroundMask !== 0.2 && (
230- < IconButton
231- variant = "ghost"
232- size = "1"
233- onClick = { ( ) => setCustomBackgroundMask ( 0.2 ) }
234- >
235- < ArrowHookUpLeft24Regular />
236- </ IconButton >
237- ) }
238- </ Flex >
239- </ Flex >
240- < Slider
241- min = { 0 }
242- max = { 1 }
243- step = { 0.01 }
244- value = { [ customBackgroundMask ] }
245- onValueChange = { ( v ) => setCustomBackgroundMask ( v [ 0 ] ) }
246- />
247- </ Flex >
248- </ Card >
249-
250- < Card >
251- < Flex direction = "column" gap = "2" >
252- < Flex align = "center" justify = "between" >
253- < Text > { t ( "settings.common.customBackgroundBlur" , "模糊半径" ) } </ Text >
254- < Flex align = "center" gap = "2" >
255- < Text wrap = "nowrap" color = "gray" size = "1" >
256- { customBackgroundBlur . toFixed ( 0 ) } px
257- </ Text >
258- { customBackgroundBlur !== 0 && (
259- < IconButton
260- variant = "ghost"
261- size = "1"
262- onClick = { ( ) => setCustomBackgroundBlur ( 0 ) }
263- >
264- < ArrowHookUpLeft24Regular />
265- </ IconButton >
266- ) }
267- </ Flex >
268- </ Flex >
269- < Slider
270- min = { 0 }
271- max = { 30 }
272- step = { 1 }
273- value = { [ customBackgroundBlur ] }
274- onValueChange = { ( v ) => setCustomBackgroundBlur ( v [ 0 ] ) }
275- />
276- </ Flex >
277- </ Card >
278-
279- < Card >
280- < Flex direction = "column" gap = "2" >
281- < Flex align = "center" justify = "between" >
282- < Text > { t ( "settings.common.customBackgroundBrightness" , "亮度" ) } </ Text >
283- < Flex align = "center" gap = "2" >
284- < Text wrap = "nowrap" color = "gray" size = "1" >
285- { Math . round ( customBackgroundBrightness * 100 ) } %
286- </ Text >
287- { customBackgroundBrightness !== 1 && (
288- < IconButton
289- variant = "ghost"
290- size = "1"
291- onClick = { ( ) => setCustomBackgroundBrightness ( 1 ) }
292- >
293- < ArrowHookUpLeft24Regular />
294- </ IconButton >
295- ) }
296- </ Flex >
297- </ Flex >
298- < Slider
299- min = { 0.5 }
300- max = { 1.5 }
301- step = { 0.01 }
302- value = { [ customBackgroundBrightness ] }
303- onValueChange = { ( v ) => setCustomBackgroundBrightness ( v [ 0 ] ) }
304- />
305- </ Flex >
306- </ Card >
307- </ Flex >
91+ < SettingsCustomBackgroundSettings
92+ onClose = { ( ) => setShowBackgroundSettings ( false ) }
93+ />
30894 ) ;
30995 }
31096
@@ -392,37 +178,9 @@ export const SettingsCommonTab = () => {
392178 </ Flex >
393179 </ Card >
394180
395- < Card style = { { width : "100%" , marginBottom : "var(--space-1)" } } >
396- < Flex gap = "3" align = "center" >
397- < Image24Regular />
398- < Box flexGrow = "1" >
399- < Flex align = "center" justify = "between" gap = "4" >
400- < Flex direction = "column" gap = "1" >
401- < Text >
402- { t ( "settings.common.customBackground" , "自定义背景" ) }
403- </ Text >
404- < Text size = "1" color = "gray" >
405- { customBackgroundImage
406- ? t (
407- "settings.common.customBackgroundEnabled" ,
408- "已设置背景" ,
409- )
410- : t (
411- "settings.common.customBackgroundDesc" ,
412- "选择一张图片作为背景。" ,
413- ) }
414- </ Text >
415- </ Flex >
416- < Button
417- variant = "soft"
418- onClick = { ( ) => setShowBackgroundSettings ( true ) }
419- >
420- { t ( "settings.common.customBackgroundManage" , "设置" ) }
421- </ Button >
422- </ Flex >
423- </ Box >
424- </ Flex >
425- </ Card >
181+ < SettingsCustomBackgroundCard
182+ onOpen = { ( ) => setShowBackgroundSettings ( true ) }
183+ />
426184 </ Flex >
427185
428186 < Flex direction = "column" gap = "3" >
0 commit comments