@@ -6,12 +6,17 @@ import androidx.compose.foundation.layout.Column
66import androidx.compose.foundation.layout.Row
77import androidx.compose.foundation.layout.Spacer
88import androidx.compose.foundation.layout.fillMaxWidth
9+ import androidx.compose.foundation.layout.heightIn
910import androidx.compose.foundation.layout.padding
1011import androidx.compose.foundation.layout.size
1112import androidx.compose.foundation.layout.width
13+ import androidx.compose.foundation.layout.widthIn
1214import androidx.compose.foundation.shape.RoundedCornerShape
1315import androidx.compose.material3.Card
1416import androidx.compose.material3.CardDefaults
17+ import androidx.compose.material3.DropdownMenuItem
18+ import androidx.compose.material3.ExperimentalMaterial3Api
19+ import androidx.compose.material3.ExposedDropdownMenuBox
1520import androidx.compose.material3.Icon
1621import androidx.compose.material3.MaterialTheme
1722import androidx.compose.material3.Switch
@@ -34,6 +39,7 @@ import androidx.navigation.NavController
3439import com.amrdeveloper.linkhub.BuildConfig
3540import com.amrdeveloper.linkhub.R
3641import com.amrdeveloper.linkhub.data.Theme
42+ import com.amrdeveloper.linkhub.ui.theme.supportedFontFamilies
3743import com.amrdeveloper.linkhub.util.UiPreferences
3844import com.amrdeveloper.linkhub.util.openLinkIntent
3945import com.amrdeveloper.linkhub.util.packageName
@@ -60,13 +66,15 @@ fun SettingsScreen(
6066 }
6167
6268 Column (modifier = Modifier .padding(8 .dp)) {
63- TextMenuOption (
69+ // Info section
70+ SimpleSettingOption (
6471 text = " Version ${BuildConfig .VERSION_NAME } " ,
6572 icon = R .drawable.ic_version,
6673 onClick = {}
6774 )
6875
69- TextSwitchMenuOption (
76+ // UI Settings section
77+ SwitchSettingOption (
7078 text = " Dark mode" ,
7179 icon = R .drawable.ic_dark_mode,
7280 isChecked = uiPreferences.getThemeType() == Theme .DARK ,
@@ -80,7 +88,18 @@ fun SettingsScreen(
8088 }
8189 )
8290
83- TextSwitchMenuOption (
91+ DropdownSettingOption (
92+ text = " Font family" ,
93+ icon = R .drawable.ic_font,
94+ defaultSelectedIndex = supportedFontFamilies.keys.indexOf(uiPreferences.getFontFamilyName())
95+ .coerceAtLeast(0 ),
96+ options = supportedFontFamilies.keys.toList(),
97+ onOptionSelected = { fondFamily ->
98+ uiPreferences.setFontFamilyName(fondFamily)
99+ }
100+ )
101+
102+ SwitchSettingOption (
84103 text = " Show Counter" ,
85104 icon = R .drawable.ic_click,
86105 isChecked = uiPreferences.isClickCounterEnabled(),
@@ -89,7 +108,7 @@ fun SettingsScreen(
89108 }
90109 )
91110
92- TextSwitchMenuOption (
111+ SwitchSettingOption (
93112 text = " Auto saving" ,
94113 icon = R .drawable.ic_save,
95114 isChecked = uiPreferences.isAutoSavingEnabled(),
@@ -98,7 +117,7 @@ fun SettingsScreen(
98117 }
99118 )
100119
101- TextSwitchMenuOption (
120+ SwitchSettingOption (
102121 text = " Remember last folder" ,
103122 icon = R .drawable.ic_folders,
104123 isChecked = uiPreferences.isDefaultFolderEnabled(),
@@ -107,50 +126,50 @@ fun SettingsScreen(
107126 }
108127 )
109128
110- TextMenuOption (
129+ SimpleSettingOption (
111130 text = " Password" ,
112131 icon = R .drawable.ic_password,
113132 onClick = { navController.navigate(R .id.configPasswordFragment) }
114133 )
115134
116- TextMenuOption (
135+ SimpleSettingOption (
117136 text = " Import/Export" ,
118137 icon = R .drawable.ic_import_export,
119138 onClick = { navController.navigate(R .id.importExportFragment) }
120139 )
121140
122- // Open source
123- TextMenuOption (
141+ // Open source section
142+ SimpleSettingOption (
124143 text = " Source code" ,
125144 icon = R .drawable.ic_code,
126145 onClick = { selectedUrlOptionToOpen = REPOSITORY_URL }
127146 )
128147
129- TextMenuOption (
148+ SimpleSettingOption (
130149 text = " Sponsor" ,
131150 icon = R .drawable.ic_github_sponsor,
132151 onClick = {
133152 selectedUrlOptionToOpen = REPOSITORY_SPONSORSHIP_URL
134153 }
135154 )
136155
137- TextMenuOption (
156+ SimpleSettingOption (
138157 text = " Contributors" ,
139158 icon = R .drawable.ic_team,
140159 onClick = {
141160 selectedUrlOptionToOpen = REPOSITORY_CONTRIBUTORS_URL
142161 }
143162 )
144163
145- TextMenuOption (
164+ SimpleSettingOption (
146165 text = " Issues" ,
147166 icon = R .drawable.ic_problems,
148167 onClick = {
149168 selectedUrlOptionToOpen = REPOSITORY_ISSUES_URL
150169 }
151170 )
152171
153- TextMenuOption (
172+ SimpleSettingOption (
154173 text = " Share" ,
155174 icon = R .drawable.ic_share,
156175 onClick = { selectedUrlOptionToOpen = PLAY_STORE_URL }
@@ -159,19 +178,15 @@ fun SettingsScreen(
159178}
160179
161180@Composable
162- private fun TextMenuOption (text : String , icon : Int , onClick : () -> Unit = {}) {
181+ private fun SimpleSettingOption (text : String , icon : Int , onClick : () -> Unit = {}) {
163182 Card (
164183 modifier = Modifier
165184 .fillMaxWidth()
166185 .clickable { onClick() }
167186 .padding(4 .dp),
168187 shape = RoundedCornerShape (12 .dp),
169- colors = CardDefaults .cardColors(
170- containerColor = MaterialTheme .colorScheme.surfaceVariant,
171- ),
172- elevation = CardDefaults .cardElevation(
173- defaultElevation = 6 .dp
174- )
188+ colors = CardDefaults .cardColors(containerColor = MaterialTheme .colorScheme.surfaceVariant),
189+ elevation = CardDefaults .cardElevation(defaultElevation = 6 .dp)
175190 ) {
176191 Row (
177192 verticalAlignment = Alignment .CenterVertically ,
@@ -195,7 +210,7 @@ private fun TextMenuOption(text: String, icon: Int, onClick: () -> Unit = {}) {
195210}
196211
197212@Composable
198- private fun TextSwitchMenuOption (
213+ private fun SwitchSettingOption (
199214 text : String ,
200215 icon : Int ,
201216 isChecked : Boolean = false,
@@ -249,3 +264,91 @@ private fun TextSwitchMenuOption(
249264 }
250265 }
251266}
267+
268+ @OptIn(ExperimentalMaterial3Api ::class )
269+ @Composable
270+ private fun DropdownSettingOption (
271+ text : String ,
272+ icon : Int ,
273+ options : List <String >,
274+ defaultSelectedIndex : Int = 0,
275+ onOptionSelected : (String ) -> Unit = {}
276+ ) {
277+ var expanded by remember { mutableStateOf(false ) }
278+ var selectedIndex by remember { mutableStateOf(defaultSelectedIndex) }
279+
280+ Card (
281+ modifier = Modifier
282+ .fillMaxWidth()
283+ .padding(4 .dp),
284+ shape = RoundedCornerShape (12 .dp),
285+ colors = CardDefaults .cardColors(
286+ containerColor = MaterialTheme .colorScheme.surfaceVariant,
287+ ),
288+ elevation = CardDefaults .cardElevation(
289+ defaultElevation = 6 .dp
290+ )
291+ ) {
292+ Row (
293+ verticalAlignment = Alignment .CenterVertically ,
294+ modifier = Modifier .padding(8 .dp)
295+ ) {
296+ Icon (
297+ painter = painterResource(icon),
298+ contentDescription = " Font Icon" ,
299+ tint = Color .Unspecified ,
300+ modifier = Modifier .size(20 .dp)
301+ )
302+
303+ Spacer (modifier = Modifier .width(8 .dp))
304+
305+ Text (
306+ text = text,
307+ style = MaterialTheme .typography.bodyLarge
308+ )
309+
310+ Spacer (modifier = Modifier .weight(1f ))
311+
312+ ExposedDropdownMenuBox (
313+ expanded = expanded,
314+ onExpandedChange = { expanded = ! expanded }) {
315+
316+ Row (
317+ modifier = Modifier .clickable {
318+ expanded = true
319+ },
320+ verticalAlignment = Alignment .CenterVertically
321+ ) {
322+ Icon (
323+ painter = painterResource(R .drawable.ic_arrow_down),
324+ contentDescription = " Arrow down" ,
325+ tint = Color .Unspecified ,
326+ modifier = Modifier .size(20 .dp)
327+ )
328+ Spacer (modifier = Modifier .width(4 .dp))
329+ Text (options[selectedIndex])
330+ }
331+
332+ ExposedDropdownMenu (
333+ expanded = expanded,
334+ onDismissRequest = { expanded = false },
335+ modifier = Modifier
336+ .heightIn(max = 200 .dp)
337+ .widthIn(min = 100 .dp)
338+ ) {
339+ options.forEachIndexed { index, selectionOption ->
340+ DropdownMenuItem (
341+ text = { Text (selectionOption) },
342+ onClick = {
343+ expanded = false
344+ selectedIndex = index
345+ onOptionSelected(selectionOption)
346+ },
347+ )
348+ }
349+ }
350+ }
351+ }
352+ }
353+
354+ }
0 commit comments