commit 54263ce89a079a71737966602ed021fa2fdd5e94
parent e1e087aeb6aa9a0a73f62193b67a28dfec25e1a0
Author: MTRNord <mtrnord1@gmail.com>
Date: Wed, 27 Sep 2023 13:37:45 +0200
Feat: Implement very basic Roomlist
Diffstat:
4 files changed, 99 insertions(+), 18 deletions(-)
diff --git a/build.gradle.kts b/build.gradle.kts
@@ -24,6 +24,8 @@ kotlin {
implementation(compose.runtime)
implementation(libs.trixnity.messenger)
implementation(libs.kobweb.silk)
+ implementation(libs.decompose)
+ implementation(libs.decompose.extensions.compose.jetbrains)
}
}
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
@@ -4,12 +4,15 @@ kotlin = "1.9.10"
trixnity = "1.0.6"
koin = "1.1.0"
kobweb = "0.14.0"
+decompose = "2.1.0-compose-experimental"
[libraries]
trixnity-messenger = { module = "de.connect2x:trixnity-messenger", version.ref = "trixnity" }
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" }
kobweb-silk = { module = "com.varabyte.kobweb:kobweb-silk", version.ref = "kobweb" }
+decompose-extensions-compose-jetbrains = { module = "com.arkivanov.decompose:extensions-compose-jetbrains", version.ref = "decompose" }
+decompose = { module = "com.arkivanov.decompose:decompose", version.ref = "decompose" }
[plugins]
jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "jetbrains-compose" }
diff --git a/src/jsMain/kotlin/Main.kt b/src/jsMain/kotlin/Main.kt
@@ -3,23 +3,21 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import com.arkivanov.decompose.DefaultComponentContext
+import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import com.arkivanov.essenty.lifecycle.LifecycleRegistry
import com.varabyte.kobweb.silk.SilkStyleSheet
import com.varabyte.kobweb.silk.init.initSilk
import com.varabyte.kobweb.silk.init.setSilkVariables
import de.connect2x.trixnity.messenger.DefaultMatrixClientService
import de.connect2x.trixnity.messenger.trixnityMessengerModule
-import de.connect2x.trixnity.messenger.viewmodel.MainViewModel
import de.connect2x.trixnity.messenger.viewmodel.RootRouter
import de.connect2x.trixnity.messenger.viewmodel.RootViewModel
import de.connect2x.trixnity.messenger.viewmodel.RootViewModelImpl
import de.connect2x.trixnity.messenger.viewmodel.connecting.MatrixClientInitializationViewModel
-import de.connect2x.trixnity.messenger.viewmodel.util.toFlow
import io.github.oshai.kotlinlogging.KotlinLoggingConfiguration
import io.github.oshai.kotlinlogging.Level
import kotlinx.browser.document
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.mapLatest
import org.jetbrains.compose.web.css.Style
import org.jetbrains.compose.web.css.padding
import org.jetbrains.compose.web.css.px
@@ -28,6 +26,7 @@ import org.jetbrains.compose.web.dom.Text
import org.jetbrains.compose.web.renderComposable
import org.koin.dsl.koinApplication
import org.w3c.dom.HTMLElement
+import pages.Main
fun main() {
KotlinLoggingConfiguration.LOG_LEVEL = Level.DEBUG
@@ -63,41 +62,32 @@ fun main() {
@Composable
fun Base(rootViewModel: RootViewModel) {
// Trixnity messenger router
- // FIXME: This seems to loose type info?
- val routerState by rootViewModel.rootStack.toFlow()
- .mapLatest { it.active.instance }.collectAsState(RootRouter.RootWrapper.None)
-
- when (routerState) {
+ val routerState by rootViewModel.rootStack.subscribeAsState()
+ when (val route = routerState.active.instance) {
is RootRouter.RootWrapper.None -> {
None()
}
is RootRouter.RootWrapper.MatrixClientInitialization -> {
- Init((routerState as RootRouter.RootWrapper.MatrixClientInitialization).matrixClientInitializationViewModel)
+ Init(route.matrixClientInitializationViewModel)
} // show initialization of the MatrixClient (aka loading screen)
is RootRouter.RootWrapper.Main -> {
- Main((routerState as RootRouter.RootWrapper.Main).mainViewModel)
+ Main(route.mainViewModel)
}
is RootRouter.RootWrapper.AddMatrixAccount -> {
- Login((routerState as RootRouter.RootWrapper.AddMatrixAccount).addMatrixAccountViewModel)
+ Login(route.addMatrixAccountViewModel)
}
is RootRouter.RootWrapper.PasswordLogin -> {
- PasswordLogin((routerState as RootRouter.RootWrapper.PasswordLogin).passwordLoginViewModel)
+ PasswordLogin(route.passwordLoginViewModel)
}
else -> {} // add more cases
}
}
-@Composable
-fun Main(mainViewModel: MainViewModel) {
- Div({ style { padding(25.px) } }) {
- Text("Main")
- }
-}
@Composable
fun Init(matrixClientInitializationViewModel: MatrixClientInitializationViewModel) {
diff --git a/src/jsMain/kotlin/pages/Main.kt b/src/jsMain/kotlin/pages/Main.kt
@@ -0,0 +1,86 @@
+package pages
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
+import com.varabyte.kobweb.compose.css.borderRight
+import de.connect2x.trixnity.messenger.viewmodel.MainViewModel
+import de.connect2x.trixnity.messenger.viewmodel.roomlist.RoomListElementViewModel
+import de.connect2x.trixnity.messenger.viewmodel.roomlist.RoomListRouter
+import de.connect2x.trixnity.messenger.viewmodel.roomlist.RoomListViewModel
+import org.jetbrains.compose.web.css.*
+import org.jetbrains.compose.web.dom.Div
+import org.jetbrains.compose.web.dom.Text
+
+
+@Composable
+fun Main(mainViewModel: MainViewModel) {
+ mainViewModel.start()
+ val roomListData by mainViewModel.roomListRouterStack.subscribeAsState()
+ val roomList = roomListData.active.instance
+
+
+ Div({
+ style {
+ display(DisplayStyle.Flex)
+ flexDirection(FlexDirection.Row)
+ gap(2.px)
+ height(100.percent)
+ }
+ }) {
+ Div({
+ style {
+ height(100.percent)
+ width(25.em)
+ display(DisplayStyle.Flex)
+ flexDirection(FlexDirection.Column)
+ gap(2.px)
+ borderRight(width = 1.px, style = LineStyle.Solid, color = Color("black"))
+ padding(4.px)
+ }
+ }) {
+ if (roomList is RoomListRouter.RoomListWrapper.List) {
+ RoomList(roomList.roomListViewModel)
+ }
+ }
+ Div({
+ style {
+ display(DisplayStyle.Flex)
+ flexDirection(FlexDirection.Column)
+ gap(2.px)
+ height(100.percent)
+ width(100.percent)
+ padding(4.px)
+ }
+ }) {
+ Text("Room")
+ }
+ }
+}
+
+@Composable
+fun RoomList(roomListViewModel: RoomListViewModel) {
+ val initialSyncFinished by roomListViewModel.initialSyncFinished.collectAsState();
+ val selectedRoomId by roomListViewModel.selectedRoomId.collectAsState();
+ val rooms by roomListViewModel.sortedRoomListElementViewModels.collectAsState();
+
+ if (!initialSyncFinished) {
+ Div({
+ classes("lds-dual-ring")
+ })
+ } else {
+ rooms.forEach { room ->
+ Room(room.second, room.first == selectedRoomId)
+ }
+ }
+}
+
+@Composable
+fun Room(roomViewModel: RoomListElementViewModel, selected: Boolean) {
+ val roomName by roomViewModel.roomName.collectAsState();
+ val roomId = roomViewModel.roomId
+ Div {
+ Text(roomName ?: roomId.full)
+ }
+}