This commit is contained in:
Rafał Kobyłko 2023-08-25 22:41:28 +02:00
parent bb93dc9e1a
commit c9f55a5e4e
149 changed files with 1541 additions and 90 deletions

View File

@ -1,6 +1,7 @@
package com.twofasapp.ui.main
import android.app.Activity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material.ExperimentalMaterialApi
@ -14,10 +15,14 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.google.accompanist.navigation.material.BottomSheetNavigator
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
import com.google.accompanist.navigation.material.bottomSheet
import com.twofasapp.android.navigation.Modal
import com.twofasapp.android.navigation.NavAnimation
import com.twofasapp.android.navigation.NavArg
import com.twofasapp.android.navigation.Screen
import com.twofasapp.android.navigation.clearGraphBackStack
import com.twofasapp.android.navigation.intentFor
import com.twofasapp.android.navigation.withArg
@ -32,8 +37,12 @@ import com.twofasapp.feature.browserext.notification.BrowserExtGraph
import com.twofasapp.feature.browserext.notification.browserExtNavigation
import com.twofasapp.feature.externalimport.navigation.ExternalImportGraph
import com.twofasapp.feature.externalimport.navigation.externalImportNavigation
import com.twofasapp.feature.home.navigation.GuideInitRoute
import com.twofasapp.feature.home.navigation.GuidePagerRoute
import com.twofasapp.feature.home.navigation.GuidesRoute
import com.twofasapp.feature.home.navigation.HomeGraph
import com.twofasapp.feature.home.navigation.HomeNavigationListener
import com.twofasapp.feature.home.navigation.HomeNode
import com.twofasapp.feature.home.navigation.NotificationsGraph
import com.twofasapp.feature.home.navigation.homeNavigation
import com.twofasapp.feature.home.navigation.notificationsNavigation
@ -73,6 +82,12 @@ internal fun MainNavHost(
var recentlyAddedService by remember { mutableStateOf<RecentlyAddedService?>(null) }
BackHandler(enabled = bottomSheetNavigator.navigatorSheetState.isVisible) {
scope.launch {
navController.popBackStack()
}
}
ModalBottomSheet(
onDismissRequest = {
if (recentlyAddedService != null) {
@ -135,11 +150,11 @@ internal fun MainNavHost(
override fun openAddServiceModal() {
recentlyAddedService = null
navController.navigate(ModalNavigation.AddService.route)
navController.navigate(Modal.AddService.route)
}
override fun openFocusServiceModal(id: Long) {
navController.navigate(ModalNavigation.FocusService.route.replace("{id}", id.toString()))
navController.navigate(Modal.FocusService.route.replace("{id}", id.toString()))
}
}
)
@ -166,13 +181,15 @@ internal fun MainNavHost(
browserExtNavigation(navController = navController)
securityNavigation(navController = navController)
bottomSheet(ModalNavigation.AddService.route) {
bottomSheet(Modal.AddService.route, listOf(NavArg.AddServiceInitRoute)) {
AddServiceModal(
onAddedSuccessfully = { recentlyAddedService = it }
initRoute = it.arguments?.getString(NavArg.AddServiceInitRoute.name),
onAddedSuccessfully = { recentlyAddedService = it },
openGuides = { navController.navigate(Screen.Guides.route) }
)
}
bottomSheet(ModalNavigation.FocusService.route, listOf(FocusServiceModalNavArg.ServiceId)) {
bottomSheet(Modal.FocusService.route, listOf(FocusServiceModalNavArg.ServiceId)) {
FocusServiceModal(
openService = {
navController.navigate(ServiceGraph.route.withArg(ServiceNavArg.ServiceId, it))
@ -180,6 +197,41 @@ internal fun MainNavHost(
}
)
}
composable(Screen.Guides.route) {
GuidesRoute(
openGuide = { navController.navigate(Screen.GuideInit.routeWithArgs(NavArg.Guide to it.name)) }
)
}
composable(Screen.GuideInit.route, listOf(NavArg.Guide)) {
GuideInitRoute(
guide = enumValueOf(it.arguments!!.getString(NavArg.Guide.name)!!),
openGuide = { guide, guideVariantIndex ->
navController.navigate(
Screen.GuidePager.routeWithArgs(
NavArg.Guide to guide.name,
NavArg.GuideVariantIndex to guideVariantIndex,
)
)
}
)
}
composable(Screen.GuidePager.route, listOf(NavArg.Guide, NavArg.GuideVariantIndex)) {
GuidePagerRoute(
guide = enumValueOf(it.arguments!!.getString(NavArg.Guide.name)!!),
guideVariantIndex = it.arguments!!.getInt(NavArg.GuideVariantIndex.name),
openAddScan = {
navController.popBackStack(HomeNode.Services.route, false)
navController.navigate(Modal.AddService.route)
},
openAddManually = {
navController.popBackStack(HomeNode.Services.route, false)
navController.navigate(Modal.AddService.routeWithArgs(NavArg.AddServiceInitRoute to "manual"))
},
)
}
}
}
}

View File

@ -7,12 +7,14 @@ import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NamedNavArgument
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.navigation.material.BottomSheetNavigator
@ -25,6 +27,7 @@ import com.twofasapp.designsystem.TwTheme
import com.twofasapp.feature.home.navigation.HomeGraph
import com.twofasapp.feature.startup.navigation.StartupGraph
import org.koin.androidx.compose.koinViewModel
import timber.log.Timber
@OptIn(ExperimentalMaterialNavigationApi::class, ExperimentalMaterialApi::class)
@Composable
@ -55,6 +58,22 @@ internal fun MainScreen(
val bottomSheetNavigator = remember { BottomSheetNavigator(sheetState) }
val navController: NavHostController = rememberNavController(bottomSheetNavigator)
val context = LocalContext.current
LaunchedEffect(Unit){
navController.addOnDestinationChangedListener { _, destination, arguments ->
val argumentsLog: String = if (destination.arguments.isEmpty()) {
""
} else {
"args=" + destination.arguments.map {
@Suppress("DEPRECATION")
"${it.key}=${arguments?.get(it.key)}"
}.toString()
}
Timber.tag("NavController").d("route=${destination.route} $argumentsLog")
}
}
if (uiState.startDestination != null && uiState.selectedTheme != null) {
CompositionLocalProvider(
LocalAppTheme provides when (uiState.selectedTheme!!) {

View File

@ -1,7 +0,0 @@
package com.twofasapp.ui.main
sealed class ModalNavigation(val route: String) {
object FocusService : ModalNavigation("modal/focusservice/{id}")
object AddService : ModalNavigation("modal/addservice")
}

View File

@ -0,0 +1,13 @@
package com.twofasapp.android.navigation
import androidx.navigation.NamedNavArgument
sealed class Modal(val route: String) {
fun routeWithArgs(vararg args: Pair<NamedNavArgument, Any>): String {
return route.replaceArgsInRoute(*args)
}
data object FocusService : Modal("modal/focusservice/{id}")
data object AddService : Modal("modal/addservice?init={${NavArg.AddServiceInitRoute.name}}")
}

View File

@ -0,0 +1,10 @@
package com.twofasapp.android.navigation
import androidx.navigation.NavType
import androidx.navigation.navArgument
object NavArg {
val AddServiceInitRoute = navArgument("AddServiceInitRoute") { type = NavType.StringType; nullable = true; defaultValue = null }
val Guide = navArgument("Guide") { type = NavType.StringType; }
val GuideVariantIndex = navArgument("GuideVariantIndex") { type = NavType.IntType; }
}

View File

@ -23,4 +23,10 @@ fun NamedNavArgument.withDefault(any: Any?): NamedNavArgument {
fun <T> SavedStateHandle.getOrThrow(key: String): T {
return get<T>(key) ?: throw IllegalNavArgException(key)
}
internal fun String.replaceArgsInRoute(vararg args: Pair<NamedNavArgument, Any>): String {
var routeWithArgs = this
args.forEach { arg -> routeWithArgs = routeWithArgs.withArg(arg.first, arg.second) }
return routeWithArgs
}

View File

@ -0,0 +1,14 @@
package com.twofasapp.android.navigation
import androidx.navigation.NamedNavArgument
sealed class Screen(val route: String) {
fun routeWithArgs(vararg args: Pair<NamedNavArgument, Any>): String {
return route.replaceArgsInRoute(*args)
}
data object Guides : Screen("guides")
data object GuideInit : Screen("guides/init?guide={${NavArg.Guide.name}}")
data object GuidePager : Screen("guides/pager?guide={${NavArg.Guide.name}}&variant={${NavArg.GuideVariantIndex.name}}")
}

View File

@ -1,7 +1,10 @@
package com.twofasapp.designsystem.internal
import androidx.compose.runtime.Composable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance
import com.twofasapp.designsystem.TwTheme
abstract class ThemeColors {
abstract val background: Color
@ -44,3 +47,6 @@ abstract class ThemeColors {
val LocalThemeColors = staticCompositionLocalOf<ThemeColors> {
ThemeColorsLight()
}
@Composable
fun isDarkTheme() = TwTheme.color.background.luminance() < 0.5

View File

@ -8,6 +8,7 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import com.twofasapp.designsystem.R
import com.twofasapp.designsystem.TwTheme
@Immutable
@Stable

View File

@ -140,6 +140,7 @@ fun DsService(
ServiceInfo(
text = state.info,
textStyles = textStyles,
style = style,
modifier = Modifier.fillMaxWidth(),
)

View File

@ -64,6 +64,7 @@ fun DsServiceModal(
ServiceInfo(
text = state.info,
textStyles = ServiceTextDefaults.modal(),
style = ServiceStyle.Default,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)

View File

@ -49,7 +49,7 @@ fun DsServiceSimple(
Column(Modifier.weight(1f)) {
ServiceName(text = state.name)
ServiceInfo(text = state.info)
ServiceInfo(text = state.info, spacer = false)
}
content()

View File

@ -3,7 +3,8 @@ package com.twofasapp.designsystem.service.atoms
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -11,6 +12,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.twofasapp.designsystem.TwTheme
import com.twofasapp.designsystem.service.ServiceStyle
import com.twofasapp.locale.TwLocale
@Composable
@ -25,7 +27,7 @@ internal fun ServiceName(
color = TwTheme.color.onSurfacePrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
modifier = modifier.padding(bottom = 2.dp),
)
}
@ -33,6 +35,8 @@ internal fun ServiceName(
@Composable
internal fun ServiceInfo(
text: String?,
style: ServiceStyle = ServiceStyle.Default,
spacer: Boolean = true,
modifier: Modifier = Modifier,
textStyles: ServiceTextStyle = ServiceTextDefaults.default(),
) {
@ -45,8 +49,17 @@ internal fun ServiceInfo(
overflow = TextOverflow.Ellipsis,
modifier = modifier,
)
} else {
Spacer(Modifier.width(4.dp))
}
if (spacer) {
Spacer(
Modifier.size(
when (style) {
ServiceStyle.Default -> 12.dp
ServiceStyle.Compact -> 2.dp
}
)
)
}
}
@ -55,6 +68,6 @@ internal fun ServiceInfo(
private fun Preview() {
Column {
ServiceName(text = TwLocale.strings.placeholder, modifier = Modifier.fillMaxWidth())
ServiceInfo(text = TwLocale.strings.placeholderMedium, modifier = Modifier.fillMaxWidth())
ServiceInfo(text = TwLocale.strings.placeholderMedium, modifier = Modifier.fillMaxWidth(), style = ServiceStyle.Default)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Some files were not shown because too many files have changed in this diff Show More