From fa6a9c2dccb12dfe3dfa77a51e3b20085aff6355 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 27 Jan 2024 20:15:24 -0500 Subject: [PATCH] Re-arch base tab navigation --- .../greenmiststudios/common/components/App.kt | 5 ++- .../common/components/screens/AgendaScreen.kt | 22 ++++++++++ .../components/screens/CalendarScreen.kt | 25 ----------- .../common/components/screens/HomeScreen.kt | 2 + .../screens/{ListsScreen.kt => TodoScreen.kt} | 41 ++++++++++++------- .../common/di/CommonModule.kt | 1 - .../common/di/PresenterModule.kt | 4 +- .../common/presenters/HomePresenter.kt | 2 + .../common/presenters/MoleculePresenter.kt | 6 ++- .../{ListsPresenter.kt => TodoPresenter.kt} | 16 ++++---- .../common/resources/StringManager.kt | 4 +- .../greenmiststudios/common/screens/Tab.kt | 12 +++--- .../common/uiutils/LoggingEventReceiver.kt | 5 +++ .../common/uiutils/PreviewContainer.kt | 22 ++++++++++ .../common/viewmodels/ListsViewModel.kt | 12 ------ .../common/viewmodels/TodoViewModel.kt | 12 ++++++ .../common/components/screens/TodoPreview.kt | 41 +++++++++++++++++++ gradle/libs.versions.toml | 1 + 18 files changed, 159 insertions(+), 74 deletions(-) create mode 100644 common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/AgendaScreen.kt delete mode 100644 common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/CalendarScreen.kt rename common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/{ListsScreen.kt => TodoScreen.kt} (66%) rename common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/{ListsPresenter.kt => TodoPresenter.kt} (77%) create mode 100644 common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/LoggingEventReceiver.kt create mode 100644 common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/PreviewContainer.kt delete mode 100644 common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/ListsViewModel.kt create mode 100644 common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/TodoViewModel.kt create mode 100644 common/src/jvmMain/kotlin/com/greenmiststudios/common/components/screens/TodoPreview.kt diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/App.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/App.kt index 14367a4..e5c4278 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/App.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/App.kt @@ -54,6 +54,7 @@ internal fun App() { ) ) { CompositionLocalProvider( + // TODO: Move to dependency injection LocalStringManager provides RealStringManager(), ) { BottomSheetNavigator( @@ -67,8 +68,8 @@ internal fun App() { modifier = Modifier.fillMaxWidth(), ) { TabItem(Tab.Home) - TabItem(Tab.Lists) - TabItem(Tab.Calendar) + TabItem(Tab.Todo) + TabItem(Tab.Agenda) } }, ) { diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/AgendaScreen.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/AgendaScreen.kt new file mode 100644 index 0000000..25ef577 --- /dev/null +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/AgendaScreen.kt @@ -0,0 +1,22 @@ +package com.greenmiststudios.common.components.screens + +import androidx.compose.runtime.Composable +import com.greenmiststudios.common.components.TopAppBarWithContent +import com.greenmiststudios.common.screens.Screen + +public object AgendaScreen : Screen { + override val params: Unit = Unit + + @Composable + override fun Content() { + AgendaScreen(Unit, {}) + } +} + +@Suppress("UNUSED_PARAMETER") +@Composable +public fun AgendaScreen(viewModel: Unit, onEvent: (Unit) -> Unit) { + TopAppBarWithContent { + //TODO + } +} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/CalendarScreen.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/CalendarScreen.kt deleted file mode 100644 index 7d1f74a..0000000 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/CalendarScreen.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.greenmiststudios.common.components.screens - -import androidx.compose.runtime.Composable -import com.greenmiststudios.common.components.TopAppBarWithContent -import com.greenmiststudios.common.presenters.HomePresenter -import com.greenmiststudios.common.screens.Screen -import com.greenmiststudios.common.screens.bindPresenter -import com.greenmiststudios.common.viewmodels.HomeViewEvent -import com.greenmiststudios.common.viewmodels.HomeViewModel - -public object CalendarScreen : Screen { - override val params: Unit = Unit - - @Composable - override fun Content() { - CalendarScreen(Unit, {}) - } -} - -@Composable -public fun CalendarScreen(viewModel: Unit, onEvent: (Unit) -> Unit) { - TopAppBarWithContent { - //TODO - } -} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/HomeScreen.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/HomeScreen.kt index e03566f..db61809 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/HomeScreen.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/HomeScreen.kt @@ -22,11 +22,13 @@ public object HomeScreen : Screen { } } +@Suppress("UNUSED_PARAMETER") @Composable private fun HomeScreen(viewModel: HomeViewModel, onEvent: (HomeViewEvent) -> Unit) { TopAppBarWithContent { Box(modifier = Modifier.fillMaxWidth()) { Text("Home") } + } } \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/ListsScreen.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/TodoScreen.kt similarity index 66% rename from common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/ListsScreen.kt rename to common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/TodoScreen.kt index b17571a..a1a2643 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/ListsScreen.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/components/screens/TodoScreen.kt @@ -17,30 +17,28 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.unit.dp -import cafe.adriel.voyager.navigator.LocalNavigator import com.greenmiststudios.common.components.ActionButton import com.greenmiststudios.common.components.TopAppBarWithContent -import com.greenmiststudios.common.presenters.ListsPresenter +import com.greenmiststudios.common.presenters.TodoPresenter import com.greenmiststudios.common.screens.Screen import com.greenmiststudios.common.screens.bindPresenter -import com.greenmiststudios.common.viewmodels.ListsViewEvent -import com.greenmiststudios.common.viewmodels.ListsViewEvent.AddList -import com.greenmiststudios.common.viewmodels.ListsViewModel +import com.greenmiststudios.common.uiutils.LoggingEventReceiver +import com.greenmiststudios.common.viewmodels.TodoViewEvent +import com.greenmiststudios.common.viewmodels.TodoViewEvent.AddList +import com.greenmiststudios.common.viewmodels.TodoViewModel -public object ListsScreen : Screen { +public object TodoScreen : Screen { override val params: Unit = Unit @Composable override fun Content() { - val binding = bindPresenter() - ListsScreen(listsViewModel = binding.viewModel, onEvent = binding.onEvent) + val binding = bindPresenter() + TodoScreen(todoViewModel = binding.viewModel, onEvent = binding.onEvent) } } @Composable -public fun ListsScreen(listsViewModel: ListsViewModel, onEvent: (ListsViewEvent) -> Unit) { - val navigator = LocalNavigator.current!! - +public fun TodoScreen(todoViewModel: TodoViewModel, onEvent: (TodoViewEvent) -> Unit) { TopAppBarWithContent( modifier = Modifier.fillMaxSize(), actionButtons = listOf( @@ -53,8 +51,16 @@ public fun ListsScreen(listsViewModel: ListsViewModel, onEvent: (ListsViewEvent) modifier = Modifier, verticalArrangement = spacedBy(16.dp), ) { - items(listsViewModel.lists.size, key = { listsViewModel.lists[it].id }) { - val list = listsViewModel.lists[it] + item(key = TodoListKeys.ListHeader.key) { + Text( + modifier = Modifier.padding(horizontal = 16.dp), + text = "Lists", + style = MaterialTheme.typography.titleMedium + ) + } + + items(todoViewModel.lists.size, key = { todoViewModel.lists[it].id }) { + val list = todoViewModel.lists[it] Card( modifier = Modifier @@ -62,7 +68,7 @@ public fun ListsScreen(listsViewModel: ListsViewModel, onEvent: (ListsViewEvent) .fillMaxWidth() .wrapContentHeight() .clickable(onClickLabel = list.name) { - onEvent(ListsViewEvent.OpenList(list.id)) + onEvent(TodoViewEvent.OpenList(list.id)) }, ) { Column( @@ -81,4 +87,11 @@ public fun ListsScreen(listsViewModel: ListsViewModel, onEvent: (ListsViewEvent) } } } +} + +public enum class TodoListKeys { + ListHeader, + ; + + public val key: String = this.name } \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/di/CommonModule.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/di/CommonModule.kt index cac313f..02501af 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/di/CommonModule.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/di/CommonModule.kt @@ -1,7 +1,6 @@ package com.greenmiststudios.common.di import com.greenmiststudios.common.persistance.createDatabase -import com.greenmiststudios.common.presenters.ListsPresenter import org.koin.core.module.Module import org.koin.dsl.module diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/di/PresenterModule.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/di/PresenterModule.kt index 76e874f..bf82eb8 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/di/PresenterModule.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/di/PresenterModule.kt @@ -3,12 +3,12 @@ package com.greenmiststudios.common.di import com.greenmiststudios.common.di.qualifiers.Threading.IO import com.greenmiststudios.common.presenters.EditListPresenter import com.greenmiststudios.common.presenters.HomePresenter -import com.greenmiststudios.common.presenters.ListsPresenter +import com.greenmiststudios.common.presenters.TodoPresenter import org.koin.core.module.Module import org.koin.dsl.module public val presenterModule: Module = module { factory { EditListPresenter(screen = get(), navigator = get(), database = get(), ioContext = get(IO)) } - factory { ListsPresenter(database = get(), navigator = get(), ioContext = get(IO)) } + factory { TodoPresenter(database = get(), navigator = get(), ioContext = get(IO)) } factory { HomePresenter() } } \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/HomePresenter.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/HomePresenter.kt index 3bd3405..a1742af 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/HomePresenter.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/HomePresenter.kt @@ -7,6 +7,8 @@ import com.greenmiststudios.common.viewmodels.HomeViewModel import kotlinx.coroutines.flow.Flow public class HomePresenter : MoleculePresenter { + + @Suppress("UNUSED_ANONYMOUS_PARAMETER") @Composable override fun models(events: Flow): HomeViewModel { LaunchedEffect(Unit) { diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/MoleculePresenter.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/MoleculePresenter.kt index b4dc165..16470bd 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/MoleculePresenter.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/MoleculePresenter.kt @@ -3,7 +3,9 @@ package com.greenmiststudios.common.presenters import androidx.compose.runtime.Composable import kotlinx.coroutines.flow.Flow -public interface MoleculePresenter { +public interface MoleculePresenter: Presenter { @Composable public fun models(events: Flow): Model -} \ No newline at end of file +} + +public interface Presenter \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/ListsPresenter.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/TodoPresenter.kt similarity index 77% rename from common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/ListsPresenter.kt rename to common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/TodoPresenter.kt index 47496aa..bdf84c5 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/ListsPresenter.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/presenters/TodoPresenter.kt @@ -11,26 +11,26 @@ import com.greenmiststudios.common.components.screens.EditListScreen import com.greenmiststudios.common.data.TidyList import com.greenmiststudios.common.data.TidyListItem import com.greenmiststudios.common.navigation.Navigator -import com.greenmiststudios.common.viewmodels.ListsViewEvent -import com.greenmiststudios.common.viewmodels.ListsViewModel +import com.greenmiststudios.common.viewmodels.TodoViewEvent +import com.greenmiststudios.common.viewmodels.TodoViewModel import com.greenmiststudios.tidy.Database import com.greenmiststudios.tidy.GetAllListsWithItems import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlin.coroutines.CoroutineContext -public class ListsPresenter( +public class TodoPresenter( private val navigator: Navigator, private val database: Database, private val ioContext: CoroutineContext, -) : MoleculePresenter { +) : MoleculePresenter { @Composable - override fun models(events: Flow): ListsViewModel { + override fun models(events: Flow): TodoViewModel { LaunchedEffect(Unit) { events.collect { when (it) { - ListsViewEvent.AddList -> navigator.goTo(EditListScreen(EditListScreen.Config.CreateList)) - is ListsViewEvent.OpenList -> navigator.goTo(EditListScreen(EditListScreen.Config.EditList(it.id))) + TodoViewEvent.AddList -> navigator.goTo(EditListScreen(EditListScreen.Config.CreateList)) + is TodoViewEvent.OpenList -> navigator.goTo(EditListScreen(EditListScreen.Config.EditList(it.id))) } } } @@ -42,7 +42,7 @@ public class ListsPresenter( .map { it.asTidyList() } }.collectAsState(emptyList()) - return ListsViewModel(lists) + return TodoViewModel(lists) } } diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/resources/StringManager.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/resources/StringManager.kt index 3eae6d3..e3494cc 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/resources/StringManager.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/resources/StringManager.kt @@ -7,6 +7,6 @@ public interface StringManager { public enum class StringKey(public val value: String) { APP_NAME("Tidy"), TAB_HOME("Home"), - TAB_CALENDAR("Calendar"), - TAB_LISTS("Lists"), + TAB_AGENDA("Agenda"), + TAB_TODO("Todo"), } \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/screens/Tab.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/screens/Tab.kt index 8014c58..683ad8c 100644 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/screens/Tab.kt +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/screens/Tab.kt @@ -10,9 +10,9 @@ import cafe.adriel.voyager.navigator.CurrentScreen import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions -import com.greenmiststudios.common.components.screens.CalendarScreen +import com.greenmiststudios.common.components.screens.AgendaScreen import com.greenmiststudios.common.components.screens.HomeScreen -import com.greenmiststudios.common.components.screens.ListsScreen +import com.greenmiststudios.common.components.screens.TodoScreen import com.greenmiststudios.common.providers.LocalStringManager import com.greenmiststudios.common.resources.StringKey import cafe.adriel.voyager.core.screen.Screen as VoyagerScreen @@ -37,23 +37,23 @@ public sealed class Tab( ) } - public data object Lists : com.greenmiststudios.common.screens.Tab(ListsScreen) { + public data object Todo : com.greenmiststudios.common.screens.Tab(TodoScreen) { override val options: TabOptions @Composable get() = TabOptions( index = 1u, icon = rememberVectorPainter(Icons.Outlined.Assignment), - title = LocalStringManager.current[StringKey.TAB_LISTS], + title = LocalStringManager.current[StringKey.TAB_TODO], ) } - public data object Calendar : com.greenmiststudios.common.screens.Tab(CalendarScreen) { + public data object Agenda : com.greenmiststudios.common.screens.Tab(AgendaScreen) { override val options: TabOptions @Composable get() = TabOptions( index = 2u, icon = rememberVectorPainter(Icons.Outlined.CalendarMonth), - title = LocalStringManager.current[StringKey.TAB_CALENDAR], + title = LocalStringManager.current[StringKey.TAB_AGENDA], ) } } diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/LoggingEventReceiver.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/LoggingEventReceiver.kt new file mode 100644 index 0000000..7040312 --- /dev/null +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/LoggingEventReceiver.kt @@ -0,0 +1,5 @@ +package com.greenmiststudios.common.uiutils + +internal fun LoggingEventReceiver(): (T) -> Unit = { + println("PreviewLoggingEventReceiver: $it") +} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/PreviewContainer.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/PreviewContainer.kt new file mode 100644 index 0000000..e92923f --- /dev/null +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/uiutils/PreviewContainer.kt @@ -0,0 +1,22 @@ +package com.greenmiststudios.common.uiutils + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import com.greenmiststudios.common.di.startTidyKoin +import com.greenmiststudios.common.providers.LocalStringManager +import com.greenmiststudios.common.resources.RealStringManager +import org.koin.mp.KoinPlatformTools + +@Composable +public fun TidyPreview(content: @Composable () -> Unit) { + if (KoinPlatformTools.defaultContext().getOrNull() == null) { + startTidyKoin() + } + + CompositionLocalProvider( + // TODO: Move to dependency injection + LocalStringManager provides RealStringManager(), + ) { + content() + } +} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/ListsViewModel.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/ListsViewModel.kt deleted file mode 100644 index 915a642..0000000 --- a/common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/ListsViewModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.greenmiststudios.common.viewmodels - -import com.greenmiststudios.common.data.TidyList - -public data class ListsViewModel( - val lists: List, -) - -public sealed interface ListsViewEvent { - public data object AddList : ListsViewEvent - public data class OpenList(val id: String) : ListsViewEvent -} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/TodoViewModel.kt b/common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/TodoViewModel.kt new file mode 100644 index 0000000..6c68262 --- /dev/null +++ b/common/src/commonMain/kotlin/com/greenmiststudios/common/viewmodels/TodoViewModel.kt @@ -0,0 +1,12 @@ +package com.greenmiststudios.common.viewmodels + +import com.greenmiststudios.common.data.TidyList + +public data class TodoViewModel( + val lists: List, +) + +public sealed interface TodoViewEvent { + public data object AddList : TodoViewEvent + public data class OpenList(val id: String) : TodoViewEvent +} \ No newline at end of file diff --git a/common/src/jvmMain/kotlin/com/greenmiststudios/common/components/screens/TodoPreview.kt b/common/src/jvmMain/kotlin/com/greenmiststudios/common/components/screens/TodoPreview.kt new file mode 100644 index 0000000..4e8c81f --- /dev/null +++ b/common/src/jvmMain/kotlin/com/greenmiststudios/common/components/screens/TodoPreview.kt @@ -0,0 +1,41 @@ +package com.greenmiststudios.common.components.screens + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.runtime.Composable +import com.greenmiststudios.common.data.TidyList +import com.greenmiststudios.common.data.TidyListItem +import com.greenmiststudios.common.di.startTidyKoin +import com.greenmiststudios.common.uiutils.LoggingEventReceiver +import com.greenmiststudios.common.uiutils.TidyPreview +import com.greenmiststudios.common.viewmodels.TodoViewModel +import org.koin.mp.KoinPlatformTools + +@Preview +@Composable +public fun TodoPreview(): Unit = TidyPreview { + if (KoinPlatformTools.defaultContext().getOrNull() == null) { + startTidyKoin() + } + + TodoScreen( + todoViewModel = TodoViewModel(emptyList()), + onEvent = LoggingEventReceiver(), + ) +} + +@Preview +@Composable +public fun TodoPreviewWithItems(): Unit = TidyPreview { + if (KoinPlatformTools.defaultContext().getOrNull() == null) { + startTidyKoin() + } + + TodoScreen( + todoViewModel = TodoViewModel(listOf( + TidyList("1", "List 1", emptyList()), + TidyList("2", "List 2", listOf(TidyListItem("1", "Item 1", false))), + TidyList("3", "List 3", emptyList()), + )), + onEvent = LoggingEventReceiver(), + ) +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c6f8114..91052f2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,7 @@ voyager = "1.0.0" sqldelight = "2.0.1" androidx-compose = "1.6.0" paparazzi = "1.3.2" +skiko = "0.7.70" android-compileSdk = "34" android-targetSdk = "34" android-minSdk = "24"