Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ kotlin {

implementation(libs.kotlinx.serialization.json)

implementation(libs.compose.navigation)
implementation(libs.compose.viewmodel)
implementation(libs.decompose.core)
implementation(libs.decompose.compose)
implementation(libs.essenty.lifecycle)
implementation(libs.essenty.lifecycle.coroutines)

implementation(libs.room.runtime)
implementation(libs.room.sqlite)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.CompositionLocalProvider
import com.arkivanov.decompose.defaultComponentContext
import core.database.getDatabaseBuilder
import core.platform.AndroidImagePicker
import di.LocalPlatform
import di.Platform
import di.PlatformConfiguration
import di.PlatformSDK
import root.RootComponent
import root.RootContent

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -63,11 +66,16 @@ class MainActivity : AppCompatActivity() {
appDatabase = appDatabase
)

val rootComponent = RootComponent(
componentContext = defaultComponentContext(),
di = PlatformSDK.di
)

setContent {
CompositionLocalProvider(
LocalPlatform provides Platform.Android
) {
App()
App(rootComponent)
}
}
}
Expand Down
50 changes: 5 additions & 45 deletions composeApp/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import androidx.compose.runtime.*
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import data.features.settings.LocalSettingsEventBus
import data.features.settings.SettingsEventBus
import navigation.LocalNavHost
import screens.create.CreateHabitFlow
import navigation.MainScreen
import screens.splash.SplashScreen
import root.RootComponent
import root.RootContent
import themes.MainTheme

@Composable
fun App() {
fun App(rootComponent: RootComponent) {
val settingsEventBus = remember { SettingsEventBus() }
val currentSettings by settingsEventBus.currentSettings.collectAsState()

Expand All @@ -27,7 +20,7 @@ fun App() {
CompositionLocalProvider(
LocalSettingsEventBus provides settingsEventBus
) {
JetHabitApp()
RootContent(rootComponent)
}
}
}
Expand All @@ -47,39 +40,6 @@ fun PreviewApp(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalSettingsEventBus provides settingsEventBus,
content = content
)
}
}

enum class AppScreens(val title: String) {
Splash("splash"), Main("main"), Create("create"), Detail("detail")
}

@Composable
private fun JetHabitApp(
navController: NavHostController = rememberNavController()
) {
val backStackEntry by navController.currentBackStackEntryAsState()
val currentScreen = backStackEntry?.destination?.route ?: AppScreens.Splash.title

CompositionLocalProvider(
LocalNavHost provides navController
) {
NavHost(
navController = navController,
startDestination = AppScreens.Splash.title
) {
composable(route = AppScreens.Splash.title) {
SplashScreen(navController)
}

composable(route = AppScreens.Main.title) {
MainScreen()
}

composable(route = AppScreens.Create.title) {
CreateHabitFlow()
}
}
)
}
}
43 changes: 0 additions & 43 deletions composeApp/src/commonMain/kotlin/base/BaseViewModel.kt

This file was deleted.

5 changes: 0 additions & 5 deletions composeApp/src/commonMain/kotlin/di/Inject.kt

This file was deleted.

18 changes: 13 additions & 5 deletions composeApp/src/commonMain/kotlin/di/PlatformSDK.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import org.kodein.di.instance
import org.kodein.di.singleton

object PlatformSDK {
private var _di: DirectDI? = null
val di: DirectDI
private var _di: DI? = null
private var _directDI: DirectDI? = null

val di: DI
get() = requireNotNull(_di)

val directDI: DirectDI
get() = requireNotNull(_directDI)

fun init(
configuration: PlatformConfiguration,
appDatabase: Any? = null
Expand All @@ -27,17 +32,20 @@ object PlatformSDK {
provideImagePicker()
}

_di = DI {
val kodeinDI = DI {
importAll(
configModule,
platformModule,
databaseModule(),
featureModule()
)
}.direct
}

_di = kodeinDI
_directDI = kodeinDI.direct
}

inline fun <reified T> instance(): T {
return di.instance()
return directDI.instance()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package feature.chat.presentation

import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import feature.chat.presentation.models.ChatEvent
import feature.chat.presentation.models.ChatMessage
import feature.chat.presentation.models.ChatViewState
import org.kodein.di.DI
import org.kodein.di.DIAware

class ChatComponent(
componentContext: ComponentContext,
override val di: DI
) : ComponentContext by componentContext, DIAware {

private val _state = MutableValue(ChatViewState())
val state: Value<ChatViewState> = _state

fun onEvent(viewEvent: ChatEvent) {
when (viewEvent) {
is ChatEvent.MessageChanged -> _state.value = _state.value.copy(currentMessage = viewEvent.text)
is ChatEvent.ApiKeyChanged -> _state.value = _state.value.copy(apiKey = viewEvent.key)
ChatEvent.SendClicked -> sendMessage()
}
}

private fun sendMessage() {
val text = _state.value.currentMessage.trim()
if (text.isEmpty()) return
val updatedMessages = _state.value.messages + ChatMessage(text, true)
val reply = generateReply(text)
_state.value = _state.value.copy(
messages = updatedMessages + ChatMessage(reply, false),
currentMessage = ""
)
}

private fun generateReply(message: String): String {
val calories = message.filter { it.isDigit() }.toIntOrNull()
return if (calories != null) {
"You logged $calories kcal. Consider adjusting your meal plan if this exceeds your goal."
} else {
"Thanks for the message!"
}
}
}

This file was deleted.

13 changes: 5 additions & 8 deletions composeApp/src/commonMain/kotlin/feature/chat/ui/ChatScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import feature.chat.presentation.ChatViewModel
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import feature.chat.presentation.ChatComponent
import feature.chat.presentation.models.ChatEvent
import feature.chat.presentation.models.ChatMessage
import org.jetbrains.compose.resources.stringResource
Expand All @@ -26,12 +24,11 @@ import ui.themes.components.JetHabitButton

@Composable
fun ChatScreen(
navController: NavController,
viewModel: ChatViewModel = viewModel { ChatViewModel() }
component: ChatComponent
) {
val viewState by viewModel.viewStates().collectAsState()
val viewState by component.state.subscribeAsState()

ChatView(viewState = viewState) { viewModel.obtainEvent(it) }
ChatView(viewState = viewState) { component.onEvent(it) }
}

@Composable
Expand Down
Loading
Loading