11import { shell } from "@tauri-apps/api" ;
22import { t } from "i18next" ;
3- import { useState } from "react" ;
3+ import { useCallback , useMemo , useState } from "react" ;
44import {
55 StyleSheet ,
66 TouchableOpacity ,
@@ -23,39 +23,63 @@ import Languages from "./Tab/Languages";
2323
2424const MODAL_WIDTH = 500 ;
2525const MODAL_HEIGHT = 300 ;
26+ const TITLEBAR_HEIGHT = 25 ;
27+
28+ type TabType = "general" | "languages" | "advanced" ;
2629
2730const SettingsModal = ( ) => {
2831 const { height, width } = useWindowDimensions ( ) ;
2932 const { nativeAppVersion, version } = useAppState ( ) ;
3033 const { theme } = useTheme ( ) ;
3134 const { hide, visible } = useSettingsModal ( ) ;
32- const [ selectedTab , setSelectedTab ] = useState ( "general" ) ;
35+ const [ selectedTab , setSelectedTab ] = useState < TabType > ( "general" ) ;
3336 const { language } = useGenericPersistentState ( ) ;
3437
35- const tabs = [
36- { label : t ( "settings_general_tab_title" ) , type : "general" } ,
37- { label : t ( "settings_lang_tab_title" ) , type : "languages" } ,
38- { label : t ( "settings_advanced_tab_title" ) , type : "advanced" } ,
39- ] ;
38+ const tabs = useMemo (
39+ ( ) => [
40+ { label : t ( "settings_general_tab_title" ) , type : "general" } ,
41+ { label : t ( "settings_lang_tab_title" ) , type : "languages" } ,
42+ { label : t ( "settings_advanced_tab_title" ) , type : "advanced" } ,
43+ ] ,
44+ [ ]
45+ ) ;
46+
47+ const tabComponents = useMemo (
48+ ( ) => ( {
49+ general : < General /> ,
50+ languages : < Languages /> ,
51+ advanced : < Advanced /> ,
52+ } ) ,
53+ [ ]
54+ ) ;
55+
56+ const handleTabChange = useCallback ( ( type : TabType ) => {
57+ setSelectedTab ( type ) ;
58+ } , [ ] ) ;
4059
41- const renderTab = ( ) => {
42- if ( selectedTab === "general" ) return < General /> ;
43- else if ( selectedTab === "languages" ) return < Languages /> ;
44- else if ( selectedTab === "advanced" ) return < Advanced /> ;
45- else return null ;
46- } ;
60+ const handleDismiss = useCallback ( ( ) => {
61+ hide ( ) ;
62+ } , [ hide ] ) ;
63+
64+ const handleOpenMpPress = useCallback ( ( ) => {
65+ shell . open ( "https://open.mp/" ) ;
66+ } , [ ] ) ;
67+
68+ const handleGithubPress = useCallback ( ( ) => {
69+ shell . open ( "https://github.com/openmultiplayer/launcher/" ) ;
70+ } , [ ] ) ;
4771
4872 if ( ! visible ) {
4973 return null ;
5074 }
5175
5276 return (
53- < StaticModal onDismiss = { ( ) => hide ( ) } key = { "settings-" + language } >
77+ < StaticModal onDismiss = { handleDismiss } key = { "settings-" + language } >
5478 < View
5579 style = { [
5680 styles . container ,
5781 {
58- top : height / 2 - MODAL_HEIGHT / 2 - 25 , // titlebar height is 25
82+ top : height / 2 - MODAL_HEIGHT / 2 - TITLEBAR_HEIGHT ,
5983 left : width / 2 - MODAL_WIDTH / 2 ,
6084 height : MODAL_HEIGHT ,
6185 width : MODAL_WIDTH ,
@@ -65,48 +89,25 @@ const SettingsModal = () => {
6589 >
6690 < TabBar
6791 list = { tabs }
68- onChange = { ( type ) => setSelectedTab ( type ) }
92+ onChange = { ( type ) => handleTabChange ( type as TabType ) }
6993 selected = { selectedTab }
70- style = { {
71- height : sc ( 30 ) ,
72- paddingHorizontal : sc ( 15 ) ,
73- marginTop : sc ( 15 ) ,
74- } }
94+ style = { styles . tabBar }
7595 />
76- { renderTab ( ) }
96+ { tabComponents [ selectedTab ] }
7797 < View style = { styles . appInfoContainer } >
7898 < Text size = { 2 } color = { theme . textPrimary } >
7999 { t ( "settings_credits_made_by" ) } { " " }
80- < Text
81- size = { 2 }
82- onPress = { ( ) => shell . open ( "https://open.mp/" ) }
83- color = { theme . primary }
84- >
100+ < Text size = { 2 } onPress = { handleOpenMpPress } color = { theme . primary } >
85101 open.mp
86102 </ Text > { " " }
87103 |{ " " }
88- < Text
89- size = { 2 }
90- onPress = { ( ) =>
91- shell . open ( "https://github.com/openmultiplayer/launcher/" )
92- }
93- color = { theme . primary }
94- >
104+ < Text size = { 2 } onPress = { handleGithubPress } color = { theme . primary } >
95105 { t ( "settings_credits_view_source_on_github" ) }
96106 </ Text > { " " }
97107 | v{ nativeAppVersion } Build { version }
98108 </ Text >
99109 </ View >
100- < TouchableOpacity
101- style = { {
102- position : "absolute" ,
103- top : sc ( 15 ) ,
104- right : sc ( 15 ) ,
105- height : sc ( 20 ) ,
106- width : sc ( 20 ) ,
107- } }
108- onPress = { ( ) => hide ( ) }
109- >
110+ < TouchableOpacity style = { styles . closeButton } onPress = { handleDismiss } >
110111 < Icon
111112 image = { images . icons . close }
112113 size = { sc ( 20 ) }
@@ -130,12 +131,24 @@ const styles = StyleSheet.create({
130131 shadowOpacity : 0.9 ,
131132 shadowRadius : 10 ,
132133 } ,
134+ tabBar : {
135+ height : sc ( 30 ) ,
136+ paddingHorizontal : sc ( 15 ) ,
137+ marginTop : sc ( 15 ) ,
138+ } ,
133139 appInfoContainer : {
134140 height : 30 ,
135141 justifyContent : "center" ,
136142 width : "100%" ,
137143 alignItems : "center" ,
138144 } ,
145+ closeButton : {
146+ position : "absolute" ,
147+ top : sc ( 15 ) ,
148+ right : sc ( 15 ) ,
149+ height : sc ( 20 ) ,
150+ width : sc ( 20 ) ,
151+ } ,
139152} ) ;
140153
141154export default SettingsModal ;
0 commit comments