feat: switch to reimagined compose nav (#40)
This commit is contained in:
parent
4373ff771d
commit
dfbdb9092d
5 changed files with 160 additions and 149 deletions
|
|
@ -79,15 +79,15 @@ dependencies {
|
|||
// AndroidX
|
||||
implementation("androidx.core:core-ktx:1.9.0")
|
||||
implementation("androidx.core:core-splashscreen:1.0.0")
|
||||
implementation("androidx.activity:activity-compose:1.6.0")
|
||||
implementation("androidx.paging:paging-compose:1.0.0-alpha16")
|
||||
implementation("androidx.activity:activity-compose:1.6.1")
|
||||
implementation("androidx.paging:paging-compose:1.0.0-alpha17")
|
||||
|
||||
// Compose
|
||||
val composeVersion = "1.3.0-beta02"
|
||||
implementation("androidx.compose.ui:ui:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui-tooling:$composeVersion")
|
||||
implementation("androidx.compose.material:material-icons-extended:$composeVersion")
|
||||
implementation("androidx.compose.material3:material3:1.0.0-rc01")
|
||||
implementation("androidx.compose.material3:material3:1.0.0")
|
||||
|
||||
// accompanist dependencies
|
||||
val accompanistVersion = "0.26.3-beta"
|
||||
|
|
@ -107,17 +107,17 @@ dependencies {
|
|||
implementation("io.insert-koin:koin-androidx-compose:$koinVersion")
|
||||
|
||||
// Other
|
||||
implementation("dev.olshevski.navigation:reimagined:1.3.0")
|
||||
implementation("io.coil-kt:coil-compose:2.2.1")
|
||||
implementation("com.github.X1nto:Taxi:1.2.0")
|
||||
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
||||
implementation("io.github.diamondminer88:zip-android:2.1.0@aar")
|
||||
implementation("com.aliucord:axml:1.0.1")
|
||||
implementation("com.android.tools.build:apksig:7.4.0-beta02")
|
||||
implementation("com.android.tools.build:apksig:7.4.0-beta04")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
|
||||
}
|
||||
|
||||
fun getCurrentBranch(): String? =
|
||||
exec("git", "name-rev", "--name-only", "HEAD")
|
||||
exec("git", "symbolic-ref", "--short", "HEAD")
|
||||
|
||||
fun getLatestCommit(): String? =
|
||||
exec("git", "rev-parse", "--short", "HEAD")
|
||||
|
|
|
|||
|
|
@ -11,18 +11,16 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import com.aliucord.manager.domain.manager.PreferencesManager
|
||||
import com.aliucord.manager.ui.dialog.StoragePermissionsDialog
|
||||
import com.aliucord.manager.ui.dialog.UpdaterDialog
|
||||
import com.aliucord.manager.ui.navigation.AppDestination
|
||||
import com.aliucord.manager.ui.navigation.HomeDestination
|
||||
import com.aliucord.manager.ui.navigation.*
|
||||
import com.aliucord.manager.ui.screen.*
|
||||
import com.aliucord.manager.ui.theme.ManagerTheme
|
||||
import com.aliucord.manager.ui.theme.Theme
|
||||
import com.xinto.taxi.*
|
||||
import dev.olshevski.navigation.reimagined.*
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
val aliucordDir = Environment.getExternalStorageDirectory().resolve("Aliucord")
|
||||
|
|
@ -41,16 +39,10 @@ class MainActivity : ComponentActivity() {
|
|||
isDarkTheme = preferences.theme == Theme.DARK || preferences.theme == Theme.SYSTEM && isSystemInDarkTheme(),
|
||||
isDynamicColor = preferences.dynamicColor
|
||||
) {
|
||||
val navigator = rememberBackstackNavigator<AppDestination>(AppDestination.Home)
|
||||
val homeRootNavigator = rememberNavigator(HomeDestination.HOME)
|
||||
val navController = rememberNavController<AppDestination>(AppDestination.Home)
|
||||
|
||||
BackHandler {
|
||||
if (!navigator.pop()) {
|
||||
if (homeRootNavigator.currentDestination == HomeDestination.HOME)
|
||||
finish()
|
||||
else
|
||||
homeRootNavigator.replace(HomeDestination.HOME)
|
||||
}
|
||||
navController.back()
|
||||
}
|
||||
|
||||
StoragePermissionsDialog()
|
||||
|
|
@ -64,28 +56,34 @@ class MainActivity : ComponentActivity() {
|
|||
UpdaterDialog()
|
||||
}
|
||||
|
||||
Taxi(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
navigator = navigator,
|
||||
transitionSpec = { fadeIn() with fadeOut() }
|
||||
) { destination ->
|
||||
when (destination) {
|
||||
is AppDestination.Home -> MainRootScreen(
|
||||
mainRootNavigator = homeRootNavigator,
|
||||
onInstallClick = { navigator.push(AppDestination.Install(it)) },
|
||||
onAboutClick = { navigator.push(AppDestination.About) }
|
||||
)
|
||||
|
||||
AnimatedNavHost(
|
||||
controller = navController,
|
||||
transitionSpec = { _, _, _ -> fadeIn() with fadeOut() }
|
||||
) {
|
||||
when (val dest = this.currentHostEntry.destination) {
|
||||
is BaseScreenDestination -> BaseScreen(
|
||||
currentNavItem = dest,
|
||||
bottomNavItems = listOf(AppDestination.Home, AppDestination.Plugins, AppDestination.Settings),
|
||||
onNavChanged = { navController.navigate(it) }
|
||||
) {
|
||||
when (dest) {
|
||||
is AppDestination.Home -> HomeScreen(
|
||||
onClickInstall = { data ->
|
||||
navController.replaceAll(AppDestination.Install(data))
|
||||
}
|
||||
)
|
||||
is AppDestination.Plugins -> PluginsScreen()
|
||||
is AppDestination.Settings -> SettingsScreen()
|
||||
}
|
||||
}
|
||||
is AppDestination.Install -> InstallerScreen(
|
||||
installData = destination.installData,
|
||||
onBackClick = navigator::pop
|
||||
installData = dest.installData,
|
||||
onBackClick = { navController.back() }
|
||||
)
|
||||
|
||||
is AppDestination.About -> AboutScreen(
|
||||
onBackClick = navigator::pop
|
||||
onBackClick = { navController.back() }
|
||||
)
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.aliucord.manager.ui.navigation
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
|
|
@ -7,32 +9,58 @@ import androidx.compose.material.icons.outlined.*
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.ui.screen.InstallData
|
||||
import com.xinto.taxi.Destination
|
||||
import dev.olshevski.navigation.reimagined.*
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.parcelize.RawValue
|
||||
|
||||
@Parcelize
|
||||
sealed interface AppDestination : Destination {
|
||||
sealed class BaseScreenDestination(
|
||||
val selectedIcon: @RawValue ImageVector,
|
||||
val unselectedIcon: @RawValue ImageVector,
|
||||
@StringRes val label: Int
|
||||
) : AppDestination
|
||||
|
||||
@Parcelize
|
||||
sealed interface AppDestination : Parcelable {
|
||||
@Parcelize
|
||||
object Home : AppDestination
|
||||
object Home : BaseScreenDestination(
|
||||
Icons.Default.Home,
|
||||
Icons.Outlined.Home,
|
||||
R.string.navigation_home
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
object Plugins : BaseScreenDestination(
|
||||
Icons.Default.Extension,
|
||||
Icons.Outlined.Extension,
|
||||
R.string.plugins_title
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
object Settings : BaseScreenDestination(
|
||||
Icons.Default.Settings,
|
||||
Icons.Outlined.Settings,
|
||||
R.string.navigation_settings
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class Install(val installData: InstallData) : AppDestination
|
||||
|
||||
@Parcelize
|
||||
object About : AppDestination
|
||||
|
||||
@Parcelize
|
||||
object Settings : AppDestination
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
enum class HomeDestination(
|
||||
val selectedIcon: @RawValue ImageVector,
|
||||
val unselectedIcon: @RawValue ImageVector,
|
||||
@StringRes val label: Int
|
||||
) : Destination {
|
||||
HOME(Icons.Default.Home, Icons.Outlined.Home, R.string.navigation_home),
|
||||
PLUGINS(Icons.Default.Extension, Icons.Outlined.Extension, R.string.plugins_title),
|
||||
SETTINGS(Icons.Default.Settings, Icons.Outlined.Settings, R.string.navigation_settings)
|
||||
context(Activity)
|
||||
fun NavController<AppDestination>.back() {
|
||||
val topDest = backstack.entries.lastOrNull()?.destination
|
||||
|
||||
if (topDest == AppDestination.Home) {
|
||||
finish()
|
||||
} else if (topDest is BaseScreenDestination) {
|
||||
replaceAll(AppDestination.Home)
|
||||
} else if (backstack.entries.size > 1) {
|
||||
pop()
|
||||
} else {
|
||||
replaceAll(AppDestination.Home)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.aliucord.manager.ui.navigation
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.ui.screen.*
|
||||
|
||||
@Composable
|
||||
fun BaseScreen(
|
||||
currentNavItem: BaseScreenDestination,
|
||||
bottomNavItems: List<BaseScreenDestination>,
|
||||
onNavChanged: (AppDestination) -> Unit,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(stringResource(currentNavItem.label)) },
|
||||
actions = {
|
||||
val localUriHandler = LocalUriHandler.current
|
||||
|
||||
IconButton(
|
||||
onClick = {
|
||||
localUriHandler.openUri("https://discord.gg/${BuildConfig.SUPPORT_SERVER}")
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_discord),
|
||||
contentDescription = stringResource(R.string.support_server)
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(onClick = { onNavChanged(AppDestination.About) }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Info,
|
||||
contentDescription = stringResource(R.string.navigation_about)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
NavigationBar {
|
||||
for (navItem in bottomNavItems) {
|
||||
NavigationBarItem(
|
||||
selected = currentNavItem == navItem,
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = if (currentNavItem == navItem) {
|
||||
navItem.selectedIcon
|
||||
} else {
|
||||
navItem.unselectedIcon
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(navItem.label)) },
|
||||
onClick = { onNavChanged(navItem) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
) { paddingValues ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
package com.aliucord.manager.ui.screen
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.ui.navigation.HomeDestination
|
||||
import com.xinto.taxi.RegularNavigator
|
||||
import com.xinto.taxi.Taxi
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun MainRootScreen(
|
||||
mainRootNavigator: RegularNavigator<HomeDestination>,
|
||||
onInstallClick: (InstallData) -> Unit,
|
||||
onAboutClick: () -> Unit
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(stringResource(mainRootNavigator.currentDestination.label)) },
|
||||
actions = {
|
||||
val localUriHandler = LocalUriHandler.current
|
||||
|
||||
IconButton(
|
||||
onClick = {
|
||||
localUriHandler.openUri("https://discord.gg/${BuildConfig.SUPPORT_SERVER}")
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_discord),
|
||||
contentDescription = stringResource(R.string.support_server)
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(onClick = onAboutClick) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Info,
|
||||
contentDescription = stringResource(R.string.navigation_about)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
val currentDestination = mainRootNavigator.currentDestination
|
||||
|
||||
NavigationBar {
|
||||
HomeDestination.values().forEach { destination ->
|
||||
NavigationBarItem(
|
||||
selected = currentDestination == destination,
|
||||
icon = {
|
||||
if (currentDestination == destination) {
|
||||
Icon(
|
||||
imageVector = destination.selectedIcon,
|
||||
contentDescription = stringResource(destination.label)
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = destination.unselectedIcon,
|
||||
contentDescription = stringResource(destination.label)
|
||||
)
|
||||
}
|
||||
},
|
||||
label = { Text(stringResource(destination.label)) },
|
||||
onClick = { mainRootNavigator.replace(destination) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
) { paddingValues ->
|
||||
Taxi(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.fillMaxSize(),
|
||||
navigator = mainRootNavigator,
|
||||
transitionSpec = { fadeIn() with fadeOut() }
|
||||
) { destination ->
|
||||
when (destination) {
|
||||
HomeDestination.HOME -> HomeScreen(
|
||||
onClickInstall = onInstallClick
|
||||
)
|
||||
|
||||
HomeDestination.PLUGINS -> PluginsScreen()
|
||||
HomeDestination.SETTINGS -> SettingsScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue