Will be handling guild/channel browsing - Bumped CMP material 3, so we don't have to use jetpack anymore - Added coil for images later on - Added a bajillion placeholder images
114 lines
4.4 KiB
Kotlin
114 lines
4.4 KiB
Kotlin
package moe.lava.neon.ui
|
|
|
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
|
import androidx.compose.material3.MaterialExpressiveTheme
|
|
import androidx.compose.material3.MotionScheme
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
|
import androidx.navigation3.runtime.NavKey
|
|
import androidx.navigation3.runtime.entryProvider
|
|
import androidx.navigation3.runtime.rememberNavBackStack
|
|
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
|
import androidx.navigation3.ui.NavDisplay
|
|
import androidx.savedstate.serialization.SavedStateConfiguration
|
|
import co.touchlab.kermit.Logger
|
|
import dev.zacsweers.metro.createGraph
|
|
import dev.zacsweers.metrox.viewmodel.LocalMetroViewModelFactory
|
|
import kotlinx.serialization.Serializable
|
|
import kotlinx.serialization.modules.SerializersModule
|
|
import kotlinx.serialization.modules.polymorphic
|
|
import moe.lava.neon.ui.di.AppUiGraph
|
|
import moe.lava.neon.ui.screens.Login
|
|
import moe.lava.neon.ui.screens.Sample
|
|
import moe.lava.neon.ui.screens.navigator.Navigator
|
|
import moe.lava.neon.ui.screens.navigator.NavigatorModel
|
|
import moe.lava.neon.ui.screens.navigator.NavigatorPreviewProvider
|
|
import kotlin.system.exitProcess
|
|
|
|
private object Route {
|
|
@Serializable
|
|
data object Login : NavKey
|
|
|
|
@Serializable
|
|
data object Sample : NavKey
|
|
|
|
@Serializable
|
|
data class Navigator(val left: Boolean) : NavKey
|
|
}
|
|
|
|
private val config = SavedStateConfiguration {
|
|
serializersModule = SerializersModule {
|
|
polymorphic(NavKey::class) {
|
|
subclass(Route.Login::class, Route.Login.serializer())
|
|
subclass(Route.Sample::class, Route.Sample.serializer())
|
|
subclass(Route.Navigator::class, Route.Navigator.serializer())
|
|
}
|
|
}
|
|
}
|
|
|
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
|
@Composable
|
|
fun App() {
|
|
Thread.setDefaultUncaughtExceptionHandler { t: Thread, e: Throwable ->
|
|
Logger.withTag("neon.thrhandler").a("Uncaught from $t: ${e}\n${e.stackTraceToString()}", e)
|
|
exitProcess(1)
|
|
}
|
|
|
|
val uiGraph = createGraph<AppUiGraph>()
|
|
val graph = uiGraph.core
|
|
CaptchaBinder(graph.api)
|
|
CompositionLocalProvider(LocalMetroViewModelFactory provides uiGraph.metroViewModelFactory) {
|
|
MaterialExpressiveTheme(
|
|
colorScheme = getColorScheme(),
|
|
motionScheme = MotionScheme.expressive(),
|
|
) {
|
|
val init = if (graph.auth.token != null) Route.Sample else Route.Login
|
|
val backStack = rememberNavBackStack(config, init)
|
|
NavDisplay(
|
|
backStack = backStack,
|
|
entryDecorators = listOf(
|
|
rememberSaveableStateHolderNavEntryDecorator(),
|
|
rememberViewModelStoreNavEntryDecorator(),
|
|
),
|
|
onBack = { backStack.removeLastOrNull() },
|
|
entryProvider = entryProvider {
|
|
entry<Route.Login> {
|
|
Login(
|
|
onSuccess = {
|
|
backStack.clear()
|
|
backStack.add(Route.Sample)
|
|
}
|
|
)
|
|
}
|
|
entry<Route.Sample> {
|
|
Sample(
|
|
navTest = {
|
|
backStack.add(Route.Navigator(it))
|
|
},
|
|
onRequestLogout = {
|
|
backStack.clear()
|
|
backStack.add(Route.Login)
|
|
}
|
|
)
|
|
}
|
|
entry<Route.Navigator> { key ->
|
|
if (key.left) {
|
|
Navigator(
|
|
NavigatorPreviewProvider.base2.copy(
|
|
guildNavPosition = NavigatorModel.GuildNavPosition.LeftSidebar
|
|
)
|
|
)
|
|
} else {
|
|
Navigator(
|
|
NavigatorPreviewProvider.base2.copy(
|
|
guildNavPosition = NavigatorModel.GuildNavPosition.BottomSheet
|
|
)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|