Skip to content

Commit ec7de1b

Browse files
committed
feat: Implement FloatingAddConfigButtonGroup for system TTS list
This commit introduces a new `FloatingAddConfigButtonGroup` component to the system TTS list screen. This component replaces the previous dropdown menu for adding new TTS configurations. - Created `FloatingAddConfigButtonGroup.kt` to house the new UI. - Implemented the `FloatingActionButtonMenu` to display add options. - Replaced the old `IconButton` and `DropdownMenu` with `FloatingAddConfigButtonGroup`. - Added strings for `expended` and `collapsed` states. - Localized new string resources.
1 parent 1142be7 commit ec7de1b

File tree

9 files changed

+194
-68
lines changed

9 files changed

+194
-68
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.github.jing332.tts_server_android.compose.systts.list
2+
3+
import androidx.activity.compose.BackHandler
4+
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.layout.Spacer
6+
import androidx.compose.foundation.layout.height
7+
import androidx.compose.material.icons.Icons
8+
import androidx.compose.material.icons.filled.Add
9+
import androidx.compose.material.icons.filled.AddCard
10+
import androidx.compose.material.icons.filled.Close
11+
import androidx.compose.material.icons.filled.Javascript
12+
import androidx.compose.material.icons.filled.MusicNote
13+
import androidx.compose.material.icons.filled.PhoneAndroid
14+
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
15+
import androidx.compose.material3.FloatingActionButtonMenu
16+
import androidx.compose.material3.FloatingActionButtonMenuItem
17+
import androidx.compose.material3.Icon
18+
import androidx.compose.material3.Text
19+
import androidx.compose.material3.ToggleFloatingActionButton
20+
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
21+
import androidx.compose.material3.animateFloatingActionButton
22+
import androidx.compose.runtime.Composable
23+
import androidx.compose.runtime.derivedStateOf
24+
import androidx.compose.runtime.getValue
25+
import androidx.compose.runtime.mutableStateOf
26+
import androidx.compose.runtime.remember
27+
import androidx.compose.runtime.setValue
28+
import androidx.compose.ui.Alignment
29+
import androidx.compose.ui.Modifier
30+
import androidx.compose.ui.graphics.vector.rememberVectorPainter
31+
import androidx.compose.ui.platform.LocalContext
32+
import androidx.compose.ui.res.stringResource
33+
import androidx.compose.ui.semantics.contentDescription
34+
import androidx.compose.ui.semantics.semantics
35+
import androidx.compose.ui.semantics.stateDescription
36+
import androidx.compose.ui.semantics.traversalIndex
37+
import androidx.compose.ui.unit.dp
38+
import com.github.jing332.tts_server_android.R
39+
40+
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
41+
@Composable
42+
fun FloatingAddConfigButtonGroup(
43+
modifier: Modifier = Modifier,
44+
visible: Boolean = true,
45+
addBgm: () -> Unit,
46+
addLocal: () -> Unit,
47+
addPlugin: () -> Unit,
48+
addGroup: () -> Unit,
49+
) {
50+
var expended by remember { mutableStateOf(false) }
51+
BackHandler(expended) {
52+
expended = false
53+
}
54+
55+
56+
val context = LocalContext.current
57+
FloatingActionButtonMenu(
58+
modifier = modifier
59+
// .background(
60+
// if (expended) MaterialTheme.colorScheme.surface.copy(alpha = 0.5f) else Color.Unspecified,
61+
// shape = MaterialTheme.shapes.medium
62+
// )
63+
.clickable(null, null, expended) {
64+
expended = false
65+
},
66+
expanded = expended,
67+
button = {
68+
ToggleFloatingActionButton(
69+
modifier =
70+
Modifier
71+
.semantics {
72+
traversalIndex = -1f
73+
stateDescription =
74+
if (expended) context.getString(R.string.expended) else context.getString(
75+
R.string.collapsed
76+
)
77+
contentDescription = context.getString(R.string.add_config)
78+
}
79+
.animateFloatingActionButton(
80+
visible = visible || expended,
81+
alignment = Alignment.BottomEnd
82+
),
83+
checked = expended,
84+
onCheckedChange = { expended = !expended }
85+
) {
86+
val imageVector by remember {
87+
derivedStateOf {
88+
if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.Filled.Add
89+
}
90+
}
91+
Icon(
92+
painter = rememberVectorPainter(imageVector),
93+
contentDescription = null,
94+
modifier = Modifier.animateIcon({ checkedProgress })
95+
)
96+
}
97+
}
98+
) {
99+
FloatingActionButtonMenuItem(
100+
onClick = {
101+
addBgm()
102+
expended = false
103+
},
104+
text = { Text(stringResource(R.string.add_local_tts)) },
105+
icon = { Icon(Icons.Default.PhoneAndroid, null) }
106+
)
107+
Spacer(Modifier.height(2.dp))
108+
FloatingActionButtonMenuItem(
109+
onClick = {
110+
addLocal()
111+
expended = false
112+
},
113+
text = { Text(stringResource(R.string.systts_add_plugin_tts)) },
114+
icon = { Icon(Icons.Default.Javascript, null) }
115+
)
116+
Spacer(Modifier.height(2.dp))
117+
FloatingActionButtonMenuItem(
118+
119+
onClick = {
120+
addPlugin()
121+
expended = false
122+
},
123+
text = { Text(stringResource(R.string.add_bgm_tts)) },
124+
icon = { Icon(Icons.Default.MusicNote, null) }
125+
)
126+
Spacer(Modifier.height(2.dp))
127+
FloatingActionButtonMenuItem(
128+
onClick = {
129+
addGroup()
130+
expended = false
131+
},
132+
text = { Text(stringResource(R.string.add_group)) },
133+
icon = { Icon(Icons.Default.AddCard, null) },
134+
// modifier =
135+
// Modifier.semantics {
136+
// isTraversalGroup = true
137+
// // Add a custom a11y action to allow closing the menu when focusing
138+
// // the last menu item, since the close button comes before the first
139+
// // menu item in the traversal order.
140+
// customActions =
141+
// listOf(
142+
// CustomAccessibilityAction(
143+
// label = context.getString(R.string.close),
144+
// action = {
145+
// expended = false
146+
// true
147+
// }
148+
// )
149+
// )
150+
// },
151+
)
152+
}
153+
}
154+

app/src/main/java/com/github/jing332/tts_server_android/compose/systts/list/ListManagerScreen.kt

Lines changed: 26 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.jing332.tts_server_android.compose.systts.list
22

3-
import androidx.annotation.StringRes
43
import androidx.compose.foundation.ExperimentalFoundationApi
54
import androidx.compose.foundation.layout.Box
65
import androidx.compose.foundation.layout.Spacer
@@ -11,14 +10,7 @@ import androidx.compose.foundation.lazy.LazyColumn
1110
import androidx.compose.foundation.lazy.itemsIndexed
1211
import androidx.compose.foundation.lazy.rememberLazyListState
1312
import androidx.compose.material.icons.Icons
14-
import androidx.compose.material.icons.filled.Add
15-
import androidx.compose.material.icons.filled.AddCard
16-
import androidx.compose.material.icons.filled.Audiotrack
17-
import androidx.compose.material.icons.filled.Javascript
1813
import androidx.compose.material.icons.filled.MoreVert
19-
import androidx.compose.material.icons.filled.PhoneAndroid
20-
import androidx.compose.material3.DropdownMenu
21-
import androidx.compose.material3.DropdownMenuItem
2214
import androidx.compose.material3.ExperimentalMaterial3Api
2315
import androidx.compose.material3.Icon
2416
import androidx.compose.material3.IconButton
@@ -32,6 +24,7 @@ import androidx.compose.runtime.remember
3224
import androidx.compose.runtime.rememberCoroutineScope
3325
import androidx.compose.runtime.saveable.rememberSaveable
3426
import androidx.compose.runtime.setValue
27+
import androidx.compose.ui.Alignment
3528
import androidx.compose.ui.Modifier
3629
import androidx.compose.ui.platform.LocalContext
3730
import androidx.compose.ui.res.stringResource
@@ -266,64 +259,6 @@ internal fun ListManagerScreen(
266259
NavTopAppBar(drawerState = drawerState, title = {
267260
Text(stringResource(id = R.string.system_tts))
268261
}, actions = {
269-
var showAddMenu by remember { mutableStateOf(false) }
270-
IconButton(onClick = { showAddMenu = true }) {
271-
Icon(Icons.Default.Add, stringResource(id = R.string.add_config))
272-
273-
DropdownMenu(expanded = showAddMenu,
274-
onDismissRequest = { showAddMenu = false }) {
275-
276-
@Composable
277-
fun MenuItem(
278-
icon: @Composable () -> Unit,
279-
@StringRes title: Int,
280-
onClick: () -> Unit,
281-
) {
282-
DropdownMenuItem(text = {
283-
Text(stringResource(id = title))
284-
}, onClick = {
285-
showAddMenu = false
286-
onClick()
287-
}, leadingIcon = icon)
288-
}
289-
290-
291-
MenuItem(
292-
icon = { Icon(Icons.Default.PhoneAndroid, null) },
293-
title = R.string.add_local_tts
294-
) {
295-
navigateToEdit(
296-
SystemTtsV2(
297-
config = TtsConfigurationDTO(
298-
source = LocalTtsSource(locale = AppConst.localeCode)
299-
)
300-
)
301-
)
302-
}
303-
304-
MenuItem(
305-
icon = { Icon(Icons.Default.Javascript, null) },
306-
title = R.string.systts_add_plugin_tts
307-
) {
308-
addPluginDialog = true
309-
}
310-
311-
MenuItem(
312-
icon = { Icon(Icons.Default.Audiotrack, null) },
313-
title = R.string.add_bgm_tts
314-
) {
315-
navigateToEdit(SystemTtsV2(config = BgmConfiguration()))
316-
}
317-
318-
MenuItem(
319-
icon = { Icon(Icons.Default.AddCard, null) },
320-
title = R.string.add_group
321-
) {
322-
addGroupDialog = true
323-
}
324-
}
325-
}
326-
327262
IconButton(onClick = { showOptions = true }) {
328263
Icon(Icons.Default.MoreVert, stringResource(id = R.string.more_options))
329264
MenuMoreOptions(
@@ -336,7 +271,6 @@ internal fun ListManagerScreen(
336271
},
337272
) { paddingValues ->
338273
Box(Modifier.padding(top = paddingValues.calculateTopPadding())) {
339-
340274
LazyColumn(
341275
Modifier
342276
.fillMaxSize()
@@ -450,10 +384,34 @@ internal fun ListManagerScreen(
450384
}
451385

452386
item {
453-
Spacer(Modifier.height(60.dp))
387+
Spacer(Modifier.height(100.dp))
454388
}
455389
}
456390

391+
FloatingAddConfigButtonGroup(
392+
modifier = Modifier
393+
.align(Alignment.BottomEnd)
394+
.padding(12.dp),
395+
visible = true,
396+
addBgm = {
397+
navigateToEdit(SystemTtsV2(config = BgmConfiguration()))
398+
},
399+
addLocal = {
400+
navigateToEdit(
401+
SystemTtsV2(
402+
config = TtsConfigurationDTO(
403+
source = LocalTtsSource(locale = AppConst.localeCode)
404+
)
405+
)
406+
)
407+
},
408+
addPlugin = {
409+
addPluginDialog = true
410+
},
411+
addGroup = {
412+
addGroupDialog = true
413+
}
414+
)
457415

458416
LaunchedEffect(key1 = Unit) {
459417
withIO {

app/src/main/res/values-en/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,4 +464,6 @@
464464
<string name="login">登录</string>
465465
<string name="reload">重新加载</string>
466466
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
467+
<string name="expended">已展开</string>
468+
<string name="collapsed">已收起</string>
467469
</resources>

app/src/main/res/values-fa/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,4 +468,6 @@
468468
<string name="login">登录</string>
469469
<string name="reload">重新加载</string>
470470
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
471+
<string name="expended">已展开</string>
472+
<string name="collapsed">已收起</string>
471473
</resources>

app/src/main/res/values-ja/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,6 @@
461461
<string name="login">登录</string>
462462
<string name="reload">重新加载</string>
463463
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
464+
<string name="expended">已展开</string>
465+
<string name="collapsed">已收起</string>
464466
</resources>

app/src/main/res/values-zh-rHK/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,6 @@
461461
<string name="login">登录</string>
462462
<string name="reload">重新加载</string>
463463
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
464+
<string name="expended">已展开</string>
465+
<string name="collapsed">已收起</string>
464466
</resources>

app/src/main/res/values-zh-rTW/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,4 +453,6 @@
453453
<string name="login">登录</string>
454454
<string name="reload">重新加载</string>
455455
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
456+
<string name="expended">已展开</string>
457+
<string name="collapsed">已收起</string>
456458
</resources>

app/src/main/res/values-zh/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,4 +459,6 @@
459459
<string name="login">登录</string>
460460
<string name="reload">重新加载</string>
461461
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
462+
<string name="expended">已展开</string>
463+
<string name="collapsed">已收起</string>
462464
</resources>

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,4 +494,6 @@
494494
<string name="login">登录</string>
495495
<string name="reload">重新加载</string>
496496
<string name="current_playing_bgm">当前背景音乐:%1$s</string>
497+
<string name="expended">已展开</string>
498+
<string name="collapsed">已收起</string>
497499
</resources>

0 commit comments

Comments
 (0)