Skip to content

Commit 4e4e30a

Browse files
committed
refactor: modulize home page
ui: align ProviderModelSheetContent with MD3 expressive
1 parent be235c5 commit 4e4e30a

9 files changed

Lines changed: 1385 additions & 952 deletions

File tree

app/src/main/kotlin/me/nanova/summaryexpressive/ui/AppNavigation.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import androidx.navigation3.runtime.entryProvider
1515
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
1616
import androidx.navigation3.ui.NavDisplay
1717
import me.nanova.summaryexpressive.ui.page.HistoryScreen
18-
import me.nanova.summaryexpressive.ui.page.HomeScreen
1918
import me.nanova.summaryexpressive.ui.page.OnboardingScreen
19+
import me.nanova.summaryexpressive.ui.page.home.HomeScreen
2020
import me.nanova.summaryexpressive.ui.page.settings.AdvancedSummarySetupScreen
2121
import me.nanova.summaryexpressive.ui.page.settings.SettingsScreen
2222
import me.nanova.summaryexpressive.vm.AppViewModel

app/src/main/kotlin/me/nanova/summaryexpressive/ui/page/HomeScreen.kt

Lines changed: 0 additions & 951 deletions
This file was deleted.
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package me.nanova.summaryexpressive.ui.page.home
2+
3+
import androidx.activity.compose.BackHandler
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.padding
6+
import androidx.compose.material.icons.Icons
7+
import androidx.compose.material.icons.filled.Add
8+
import androidx.compose.material.icons.filled.Close
9+
import androidx.compose.material.icons.rounded.CameraAlt
10+
import androidx.compose.material.icons.rounded.Check
11+
import androidx.compose.material.icons.rounded.ContentPaste
12+
import androidx.compose.material.icons.rounded.Description
13+
import androidx.compose.material.icons.rounded.Image
14+
import androidx.compose.material.icons.rounded.Refresh
15+
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
16+
import androidx.compose.material3.FloatingActionButton
17+
import androidx.compose.material3.FloatingActionButtonMenu
18+
import androidx.compose.material3.FloatingActionButtonMenuItem
19+
import androidx.compose.material3.Icon
20+
import androidx.compose.material3.LoadingIndicator
21+
import androidx.compose.material3.Text
22+
import androidx.compose.material3.ToggleFloatingActionButton
23+
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
24+
import androidx.compose.material3.animateFloatingActionButton
25+
import androidx.compose.runtime.Composable
26+
import androidx.compose.runtime.derivedStateOf
27+
import androidx.compose.runtime.getValue
28+
import androidx.compose.runtime.mutableStateOf
29+
import androidx.compose.runtime.remember
30+
import androidx.compose.runtime.saveable.rememberSaveable
31+
import androidx.compose.runtime.setValue
32+
import androidx.compose.ui.Alignment
33+
import androidx.compose.ui.Modifier
34+
import androidx.compose.ui.graphics.vector.rememberVectorPainter
35+
import androidx.compose.ui.res.stringResource
36+
import androidx.compose.ui.semantics.contentDescription
37+
import androidx.compose.ui.semantics.semantics
38+
import androidx.compose.ui.semantics.stateDescription
39+
import androidx.compose.ui.tooling.preview.Preview
40+
import androidx.compose.ui.unit.dp
41+
import me.nanova.summaryexpressive.R
42+
import me.nanova.summaryexpressive.ui.theme.SummaryExpressiveTheme
43+
44+
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
45+
@Composable
46+
fun HomeFloatingActionButtons(
47+
fabVisible: Boolean,
48+
onPaste: () -> Unit,
49+
onSummarize: () -> Unit,
50+
isLoading: Boolean,
51+
hasResult: Boolean,
52+
isDirty: Boolean,
53+
onShowSnackBar: (String) -> Unit,
54+
onLaunchFilePicker: () -> Unit,
55+
onLaunchImagePicker: () -> Unit,
56+
onLaunchCamera: () -> Unit,
57+
modifier: Modifier = Modifier,
58+
) {
59+
val stillLoading = stringResource(id = R.string.stillLoading)
60+
var menuExpanded by rememberSaveable { mutableStateOf(false) }
61+
62+
BackHandler(menuExpanded) { menuExpanded = false }
63+
64+
val attachmentItems = listOf(
65+
Triple(Icons.Rounded.Image, "Image", onLaunchImagePicker),
66+
Triple(Icons.Rounded.CameraAlt, "Camera", onLaunchCamera),
67+
Triple(Icons.Rounded.Description, "Document", onLaunchFilePicker)
68+
)
69+
70+
Column(
71+
modifier = modifier,
72+
horizontalAlignment = Alignment.CenterHorizontally
73+
) {
74+
FloatingActionButtonMenu(
75+
expanded = menuExpanded,
76+
button = {
77+
ToggleFloatingActionButton(
78+
checked = menuExpanded,
79+
onCheckedChange = { if (!isLoading) menuExpanded = !menuExpanded },
80+
modifier = Modifier
81+
.semantics {
82+
stateDescription = if (menuExpanded) "Expanded" else "Collapsed"
83+
contentDescription = "Toggle attachments menu"
84+
}
85+
.animateFloatingActionButton(
86+
visible = fabVisible,
87+
alignment = Alignment.BottomEnd
88+
)
89+
) {
90+
val imageVector by remember {
91+
derivedStateOf {
92+
if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.Filled.Add
93+
}
94+
}
95+
Icon(
96+
painter = rememberVectorPainter(imageVector),
97+
contentDescription = "More actions",
98+
modifier = Modifier.animateIcon({ checkedProgress }),
99+
)
100+
}
101+
},
102+
) {
103+
attachmentItems.forEach { (icon, text, onClick) ->
104+
FloatingActionButtonMenuItem(
105+
icon = { Icon(icon, contentDescription = null) },
106+
text = { Text(text) },
107+
onClick = {
108+
onClick()
109+
menuExpanded = false
110+
}
111+
)
112+
}
113+
}
114+
115+
FloatingActionButton(
116+
onClick = { if (!isLoading) onPaste() },
117+
modifier = Modifier
118+
.padding(bottom = 16.dp)
119+
.animateFloatingActionButton(
120+
visible = fabVisible && !menuExpanded,
121+
alignment = Alignment.BottomEnd
122+
)
123+
) {
124+
Icon(
125+
imageVector = Icons.Rounded.ContentPaste,
126+
contentDescription = "Paste from clipboard",
127+
)
128+
}
129+
130+
FloatingActionButton(
131+
onClick = {
132+
if (isLoading) onShowSnackBar(stillLoading)
133+
else onSummarize()
134+
},
135+
modifier = Modifier.animateFloatingActionButton(
136+
visible = fabVisible && !menuExpanded,
137+
alignment = Alignment.TopStart
138+
)
139+
) {
140+
if (isLoading) {
141+
LoadingIndicator()
142+
} else if (hasResult && !isDirty) {
143+
Icon(
144+
imageVector = Icons.Rounded.Refresh,
145+
contentDescription = stringResource(R.string.regenerate)
146+
)
147+
} else {
148+
Icon(
149+
imageVector = Icons.Rounded.Check,
150+
contentDescription = "Summarize"
151+
)
152+
}
153+
}
154+
}
155+
}
156+
157+
@Preview
158+
@Composable
159+
private fun HomeFloatingActionButtonsPreview() {
160+
SummaryExpressiveTheme {
161+
HomeFloatingActionButtons(
162+
fabVisible = true,
163+
onPaste = {},
164+
onSummarize = {},
165+
isLoading = false,
166+
hasResult = false,
167+
isDirty = false,
168+
onShowSnackBar = {},
169+
onLaunchFilePicker = {},
170+
onLaunchImagePicker = {},
171+
onLaunchCamera = {}
172+
)
173+
}
174+
}

0 commit comments

Comments
 (0)