Skip to content

Commit 8e1b7e9

Browse files
authored
Merge pull request #157 from simple-login/refactor/simplify-dialog-presentations
Simplify dialog presentations
2 parents 06242a2 + dd4c046 commit 8e1b7e9

9 files changed

Lines changed: 97 additions & 253 deletions

File tree

app/src/main/java/io/simplelogin/android/MainActivity.kt

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import androidx.compose.material3.SnackbarHost
4545
import androidx.compose.material3.SnackbarHostState
4646
import androidx.compose.material3.SnackbarResult
4747
import androidx.compose.material3.Text
48-
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
4948
import androidx.compose.material3.rememberDrawerState
5049
import androidx.compose.runtime.Composable
5150
import androidx.compose.runtime.DisposableEffect
@@ -72,7 +71,6 @@ import dagger.hilt.android.AndroidEntryPoint
7271
import dagger.hilt.android.lifecycle.HiltViewModel
7372
import io.simplelogin.android.root.AppRoot
7473
import io.simplelogin.android.root.AppRootViewModel
75-
import io.simplelogin.android.root.supportsMultiplePanes
7674
import io.simplelogin.core.common.ProtonLinkManager
7775
import io.simplelogin.core.common.ProtonLoginManager
7876
import io.simplelogin.core.common.di.LoadingState
@@ -128,8 +126,6 @@ class MainActivity : AppCompatActivity() {
128126
}
129127
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
130128
val scope = rememberCoroutineScope()
131-
val windowAdaptiveInfo = currentWindowAdaptiveInfo()
132-
val asDialog = windowAdaptiveInfo.supportsMultiplePanes()
133129
val appRooState by appRootViewModel.stateFlow.collectAsState()
134130
val userInfo by viewModel.userInfoStateFlow.collectAsState()
135131

@@ -155,9 +151,7 @@ class MainActivity : AppCompatActivity() {
155151
}
156152

157153
fun openAccountSettings() {
158-
closeDrawerAndExecute {
159-
appRootViewModel.showAccountSettingsScreen(asDialog)
160-
}
154+
closeDrawerAndExecute(appRootViewModel::showAccountSettingsScreen)
161155
}
162156

163157
SimpleLoginTheme(darkTheme = darkTheme, dynamicColor = devicePreferences.dynamicColor) {
@@ -173,22 +167,16 @@ class MainActivity : AppCompatActivity() {
173167
openAccountSettings()
174168
},
175169
onMailboxesClick = {
176-
closeDrawerAndExecute {
177-
appRootViewModel.showMailboxesScreen(asDialog)
178-
}
170+
closeDrawerAndExecute(appRootViewModel::showMailboxesScreen)
179171
},
180172
onCustomDomainsClick = {
181-
closeDrawerAndExecute {
182-
appRootViewModel.showCustomDomainsScreen(asDialog)
183-
}
173+
closeDrawerAndExecute(appRootViewModel::showCustomDomainsScreen)
184174
},
185175
onAccountSettingsClick = {
186176
openAccountSettings()
187177
},
188178
onDeviceSettingsClick = {
189-
closeDrawerAndExecute {
190-
appRootViewModel.showDeviceSettingsScreen(asDialog)
191-
}
179+
closeDrawerAndExecute(appRootViewModel::showDeviceSettingsScreen)
192180
},
193181
onContactUsClick = {
194182
closeDrawerAndExecute(::openContactUsPage)

app/src/main/java/io/simplelogin/android/home/HomeScreen.kt

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import androidx.compose.material3.Icon
2424
import androidx.compose.material3.Scaffold
2525
import androidx.compose.material3.Surface
2626
import androidx.compose.material3.TopAppBarDefaults
27-
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
2827
import androidx.compose.runtime.Composable
2928
import androidx.compose.runtime.LaunchedEffect
3029
import androidx.compose.runtime.collectAsState
@@ -41,26 +40,20 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
4140
import androidx.compose.ui.platform.LocalContext
4241
import androidx.compose.ui.res.stringResource
4342
import androidx.compose.ui.unit.dp
44-
import androidx.compose.ui.window.Dialog
45-
import androidx.compose.ui.window.DialogProperties
4643
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
4744
import io.simplelogin.android.R
4845
import io.simplelogin.android.home.topbar.NormalTopAppBar
4946
import io.simplelogin.android.home.topbar.SearchTopAppBar
50-
import io.simplelogin.android.root.supportsMultiplePanes
5147
import io.simplelogin.core.designsystem.TitledFAB
5248
import io.simplelogin.core.designsystem.clickableRippleDisabled
5349
import io.simplelogin.core.designsystem.noAliasesMessage
5450
import io.simplelogin.core.designsystem.theme.SlColor
5551
import io.simplelogin.core.model.api.Alias
56-
import io.simplelogin.core.model.api.ApiKey
5752
import io.simplelogin.core.model.api.RandomMode
5853
import io.simplelogin.core.model.ui.AliasAction
59-
import io.simplelogin.core.model.ui.DialogPayload
6054
import io.simplelogin.core.ui.EditTextDialog
6155
import io.simplelogin.feature.aliasdetail.FullScreenDialog
6256
import io.simplelogin.feature.aliaslist.AliasList
63-
import io.simplelogin.feature.createalias.CreateAliasScreen
6457
import kotlinx.coroutines.FlowPreview
6558
import kotlinx.coroutines.flow.Flow
6659
import kotlinx.coroutines.flow.debounce
@@ -82,12 +75,10 @@ fun HomeScreen(
8275
}
8376

8477
var isSearching by rememberSaveable { mutableStateOf(false) }
85-
var createAliasDialogPayload by rememberSaveable { mutableStateOf<DialogPayload?>(null) }
8678
var fullScreenAlias by rememberSaveable { mutableStateOf<Alias?>(null) }
8779

8880
val backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
8981
var fabExpanded by rememberSaveable { mutableStateOf(false) }
90-
val windowAdaptiveInfo = currentWindowAdaptiveInfo()
9182

9283
LaunchedEffect(Unit) {
9384
createdAliasFlow.collect { alias ->
@@ -121,13 +112,7 @@ fun HomeScreen(
121112
onViewDetails = onViewDetails,
122113
onViewContacts = onViewContacts,
123114
onEnterFullScreen = { fullScreenAlias = it },
124-
onCustomAliasClick = {
125-
if (windowAdaptiveInfo.supportsMultiplePanes()) {
126-
createAliasDialogPayload = DialogPayload(ApiKey(viewModel.apiKeyValue))
127-
} else {
128-
onCreateAlias()
129-
}
130-
}
115+
onCustomAliasClick = onCreateAlias
131116
)
132117
}
133118

@@ -137,22 +122,6 @@ fun HomeScreen(
137122
onDismiss = { fullScreenAlias = null }
138123
)
139124
}
140-
141-
createAliasDialogPayload?.let { payload ->
142-
Dialog(
143-
onDismissRequest = { createAliasDialogPayload = null },
144-
properties = DialogProperties(usePlatformDefaultWidth = windowAdaptiveInfo.supportsMultiplePanes())
145-
) {
146-
CreateAliasScreen(
147-
apiKeyValue = payload.apiKey.value,
148-
onAliasCreated = {
149-
createAliasDialogPayload = null
150-
viewModel.handleCreatedAlias(it)
151-
},
152-
onDismiss = { createAliasDialogPayload = null }
153-
)
154-
}
155-
}
156125
}
157126

158127
@Suppress("CyclomaticComplexMethod")

app/src/main/java/io/simplelogin/android/root/AppRoot.kt

Lines changed: 22 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,21 @@ import androidx.compose.material3.Text
99
import androidx.compose.material3.TextButton
1010
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
1111
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
12-
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
12+
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfoV2
1313
import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective
1414
import androidx.compose.material3.adaptive.navigation3.ListDetailSceneStrategy
1515
import androidx.compose.material3.adaptive.navigation3.rememberListDetailSceneStrategy
1616
import androidx.compose.runtime.Composable
1717
import androidx.compose.runtime.collectAsState
1818
import androidx.compose.runtime.getValue
19+
import androidx.compose.runtime.remember
1920
import androidx.compose.ui.Modifier
2021
import androidx.compose.ui.platform.LocalConfiguration
2122
import androidx.compose.ui.res.stringResource
2223
import androidx.compose.ui.unit.dp
23-
import androidx.compose.ui.window.Dialog
2424
import androidx.navigation3.runtime.NavKey
2525
import androidx.navigation3.runtime.entryProvider
26+
import androidx.navigation3.scene.DialogSceneStrategy
2627
import androidx.navigation3.ui.NavDisplay
2728
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_MEDIUM_LOWER_BOUND
2829
import io.simplelogin.android.R
@@ -94,8 +95,7 @@ fun AppRoot(
9495
onOpenDrawer: () -> Unit
9596
) = with(viewModel) {
9697
val backStack by navBackStack.collectAsState()
97-
val dialogStack by dialogStack.collectAsState()
98-
val activeDialog = dialogStack.lastOrNull()
98+
val showLogOutDialog by showLogOutDialog.collectAsState()
9999
val configuration = LocalConfiguration.current
100100
val screenWidth = configuration.screenWidthDp.dp
101101

@@ -104,19 +104,22 @@ fun AppRoot(
104104
} else {
105105
screenWidth * 0.5f
106106
}
107-
val windowAdaptiveInfo = currentWindowAdaptiveInfo()
107+
val windowAdaptiveInfo = currentWindowAdaptiveInfoV2()
108+
val numberOfPanes = if (windowAdaptiveInfo.supportsMultiplePanes()) 2 else 1
108109
val listDetailSceneStrategy = rememberListDetailSceneStrategy<NavKey>(
109110
directive = calculatePaneScaffoldDirective(windowAdaptiveInfo).copy(
110111
defaultPanePreferredWidth = listPaneWidth,
111-
maxHorizontalPartitions = if (windowAdaptiveInfo.supportsMultiplePanes()) 2 else 1,
112+
maxHorizontalPartitions = numberOfPanes,
112113
horizontalPartitionSpacerSize = 0.dp
113114
)
114115
)
116+
val dialogStrategy = remember { DialogSceneStrategy<NavKey>() }
117+
val dialogMetadata = if (numberOfPanes > 1) DialogSceneStrategy.dialog() else emptyMap()
115118

116119
NavDisplay(
117120
modifier = modifier,
118121
backStack = backStack,
119-
sceneStrategies = listOf(listDetailSceneStrategy),
122+
sceneStrategies = listOf(listDetailSceneStrategy, dialogStrategy),
120123
entryProvider = entryProvider {
121124
entry<InitializationDestination> {}
122125

@@ -139,7 +142,7 @@ fun AppRoot(
139142
)
140143
}
141144

142-
entry<CreateAliasDestination> { key ->
145+
entry<CreateAliasDestination>(metadata = dialogMetadata) { key ->
143146
CreateAliasScreen(
144147
apiKeyValue = key.apiKey,
145148
onAliasCreated = viewModel::handleCreatedAlias,
@@ -182,52 +185,46 @@ fun AppRoot(
182185
)
183186
}
184187

185-
entry<DeviceSettingsDestination> {
188+
entry<DeviceSettingsDestination>(metadata = dialogMetadata) {
186189
DeviceSettingsScreen(onDismiss = viewModel::goBack)
187190
}
188191

189-
entry<AccountSettingsDestination> { key ->
192+
entry<AccountSettingsDestination>(metadata = dialogMetadata) { key ->
190193
AccountSettingsScreen(
191194
apiKeyValue = key.apiKey,
192195
onDismiss = viewModel::goBack
193196
)
194197
}
195198

196-
entry<MailboxesDestination> { key ->
199+
entry<MailboxesDestination>(metadata = dialogMetadata) { key ->
197200
MailboxesScreen(
198201
apiKeyValue = key.apiKey,
199202
onDismiss = viewModel::goBack
200203
)
201204
}
202205

203-
entry<CustomDomainsDestination> { key ->
206+
entry<CustomDomainsDestination>(metadata = dialogMetadata) { key ->
204207
CustomDomainsScreen(
205208
apiKeyValue = key.apiKey,
206209
onViewDetails = {
207-
viewModel.showCustomDomainDetails(
208-
domain = it,
209-
asDialog = false
210-
)
210+
viewModel.showCustomDomainDetails(domain = it)
211211
},
212212
onDismiss = viewModel::goBack
213213
)
214214
}
215215

216-
entry<CustomDomainDetailsDestination> { key ->
216+
entry<CustomDomainDetailsDestination>(metadata = dialogMetadata) { key ->
217217
CustomDomainDetailsScreen(
218218
domain = key.domain,
219219
apiKeyValue = key.apiKey,
220220
onDismiss = viewModel::goBack,
221221
onViewDeletedAliases = {
222-
viewModel.showCustomDomainDeletedAliases(
223-
domain = key.domain,
224-
asDialog = false
225-
)
222+
viewModel.showCustomDomainDeletedAliases(domain = key.domain)
226223
}
227224
)
228225
}
229226

230-
entry<CustomDomainDeletedAliasesDestination> { key ->
227+
entry<CustomDomainDeletedAliasesDestination>(metadata = dialogMetadata) { key ->
231228
CustomDomainDeletedAliasesScreen(
232229
domain = key.domain,
233230
apiKeyValue = key.apiKey,
@@ -237,8 +234,8 @@ fun AppRoot(
237234
}
238235
)
239236

240-
when (activeDialog) {
241-
AppRootDialog.LogOut -> AlertDialog(
237+
if (showLogOutDialog) {
238+
AlertDialog(
242239
onDismissRequest = ::dismissActiveDialog,
243240
title = { Text(stringResource(R.string.sign_out)) },
244241
text = { Text(stringResource(R.string.sign_out_message)) },
@@ -253,58 +250,8 @@ fun AppRoot(
253250
}
254251
}
255252
)
256-
257-
AppRootDialog.DeviceSettings -> Dialog(onDismissRequest = ::dismissActiveDialog) {
258-
DeviceSettingsScreen(onDismiss = ::dismissActiveDialog)
259-
}
260-
261-
is AppRootDialog.AccountSettings -> Dialog(onDismissRequest = ::dismissActiveDialog) {
262-
AccountSettingsScreen(
263-
apiKeyValue = activeDialog.apiKey.value,
264-
onDismiss = ::dismissActiveDialog
265-
)
266-
}
267-
268-
is AppRootDialog.Mailboxes -> Dialog(onDismissRequest = ::dismissActiveDialog) {
269-
MailboxesScreen(
270-
apiKeyValue = activeDialog.apiKey.value,
271-
onDismiss = ::dismissActiveDialog
272-
)
273-
}
274-
275-
is AppRootDialog.CustomDomains -> Dialog(onDismissRequest = ::dismissActiveDialog) {
276-
CustomDomainsScreen(
277-
apiKeyValue = activeDialog.apiKey.value,
278-
onViewDetails = { showCustomDomainDetails(domain = it, asDialog = true) },
279-
onDismiss = ::dismissActiveDialog
280-
)
281-
}
282-
283-
is AppRootDialog.CustomDomainDetails -> Dialog(onDismissRequest = ::dismissActiveDialog) {
284-
CustomDomainDetailsScreen(
285-
domain = activeDialog.domain,
286-
apiKeyValue = activeDialog.apiKey.value,
287-
onDismiss = ::dismissActiveDialog,
288-
onViewDeletedAliases = {
289-
viewModel.showCustomDomainDeletedAliases(
290-
domain = activeDialog.domain,
291-
asDialog = true
292-
)
293-
}
294-
)
295-
}
296-
297-
is AppRootDialog.CustomDomainDeletedAliases -> Dialog(onDismissRequest = ::dismissActiveDialog) {
298-
CustomDomainDeletedAliasesScreen(
299-
domain = activeDialog.domain,
300-
apiKeyValue = activeDialog.apiKey.value,
301-
onDismiss = ::dismissActiveDialog
302-
)
303-
}
304-
305-
null -> Unit
306253
}
307254
}
308255

309-
fun WindowAdaptiveInfo.supportsMultiplePanes(): Boolean =
256+
private fun WindowAdaptiveInfo.supportsMultiplePanes(): Boolean =
310257
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND)

app/src/main/java/io/simplelogin/android/root/AppRootDialog.kt

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)