Skip to content
Merged
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
16 changes: 15 additions & 1 deletion app/src/androidMain/kotlin/net/cacheux/nvp/app/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.Modifier
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
Expand All @@ -17,13 +20,15 @@ import kotlinx.coroutines.launch
import net.cacheux.nvp.app.BuildConfig.DEMO_VERSION
import net.cacheux.nvp.app.repository.ActivityRequirer
import net.cacheux.nvp.app.repository.PenInfoRepository
import net.cacheux.nvp.app.repository.Theme
import net.cacheux.nvp.app.ui.ScreenWrapper
import net.cacheux.nvp.app.utils.csvFilename
import net.cacheux.nvp.app.utils.toCsv
import net.cacheux.nvp.app.viewmodel.MainScreenViewModel
import net.cacheux.nvp.app.viewmodel.PenSettingsViewModel
import net.cacheux.nvp.app.viewmodel.SettingsViewModel
import net.cacheux.nvp.ui.MainDropdownMenuActions
import net.cacheux.nvp.ui.asStateWrapper
import javax.inject.Inject

@AndroidEntryPoint
Expand All @@ -40,7 +45,16 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)

setContent {
MaterialTheme {
val isDark = when(settingsViewModel.theme.asStateWrapper().value) {
Theme.THEME_LIGHT -> false
Theme.THEME_DARK -> true
Theme.THEME_SYSTEM -> isSystemInDarkTheme()
else -> false
}

MaterialTheme(
colorScheme = if (isDark) darkColorScheme() else lightColorScheme()
) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import net.cacheux.nvp.app.repository.Theme.THEME_LIGHT
import net.cacheux.nvp.app.utils.PreferenceStateFlowWrapper
import net.cacheux.nvplib.utils.StateFlowWrapper

Expand All @@ -13,12 +14,18 @@ class DatastorePreferencesRepository(context: Context): PreferencesRepository {
private val dataStore = context.dataStore

private object PreferencesKeys {
val THEME = intPreferencesKey("theme")
val GROUP_ENABLED = booleanPreferencesKey("group_enabled")
val GROUP_DELAY = intPreferencesKey("group_delay")
val AUTO_IGNORE_ENABLED = booleanPreferencesKey("auto_ignore_enabled")
val AUTO_IGNORE_VALUE = intPreferencesKey("auto_ignore_value")
}

override val theme: StateFlowWrapper<Int> =
PreferenceStateFlowWrapper(
datastore = dataStore, key = PreferencesKeys.THEME, initialValue = THEME_LIGHT
)

override val groupEnabled: StateFlowWrapper<Boolean> =
PreferenceStateFlowWrapper(
dataStore, PreferencesKeys.GROUP_ENABLED, true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ package net.cacheux.nvp.app.repository

import net.cacheux.nvplib.utils.StateFlowWrapper

object Theme {
const val THEME_LIGHT = 0
const val THEME_DARK = 1
const val THEME_SYSTEM = 2
}

interface PreferencesRepository {
val theme: StateFlowWrapper<Int>

val groupEnabled: StateFlowWrapper<Boolean>
val groupDelay: StateFlowWrapper<Int>
val autoIgnoreEnabled: StateFlowWrapper<Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ fun ScreenWrapper(
SettingsScreen(
params = SettingsScreenParams(
onBack = { currentScreen = CurrentScreen.Main },
theme = settingsViewModel.theme.asStateWrapper(),
groupDose = settingsViewModel.groupEnabled.asStateWrapper(),
groupDelay = settingsViewModel.groupDelay.asStateWrapper(),
autoIgnoreEnabled = settingsViewModel.autoIgnoreEnabled.asStateWrapper(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import net.cacheux.nvp.app.repository.PreferencesRepository
open class BaseSettingsViewModel(
preferencesRepository: PreferencesRepository
): ViewModel() {
val theme = preferencesRepository.theme
val groupEnabled = preferencesRepository.groupEnabled
val groupDelay = preferencesRepository.groupDelay
val autoIgnoreEnabled = preferencesRepository.autoIgnoreEnabled
Expand Down
57 changes: 37 additions & 20 deletions app/src/desktopMain/kotlin/main.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import androidx.room.Room
Expand All @@ -12,6 +16,7 @@ import kotlinx.coroutines.launch
import net.cacheux.nvp.app.repository.PreferencesRepositoryImpl
import net.cacheux.nvp.app.repository.StorageRepository
import net.cacheux.nvp.app.repository.TestPenInfoRepository
import net.cacheux.nvp.app.repository.Theme
import net.cacheux.nvp.app.ui.ScreenWrapper
import net.cacheux.nvp.app.usecase.DoseListUseCase
import net.cacheux.nvp.app.utils.csvFilename
Expand All @@ -20,6 +25,7 @@ import net.cacheux.nvp.app.viewmodel.BasePenSettingsViewModel
import net.cacheux.nvp.app.viewmodel.BaseSettingsViewModel
import net.cacheux.nvp.app.viewmodel.MainScreenViewModel
import net.cacheux.nvp.ui.MainDropdownMenuActions
import net.cacheux.nvp.ui.asStateWrapper
import net.cacheux.nvplib.storage.room.NvpDatabase
import net.cacheux.nvplib.storage.room.RoomDoseStorage

Expand Down Expand Up @@ -71,27 +77,38 @@ fun main() = application {
// TODO feedback message
}

ScreenWrapper(
mainScreenViewModel = mainScreenViewModel,
penSettingsViewModel = penSettingsViewModel,
settingsViewModel = settingsViewModel,
val isDark = when(settingsViewModel.theme.asStateWrapper().value) {
Theme.THEME_LIGHT -> false
Theme.THEME_DARK -> true
Theme.THEME_SYSTEM -> isSystemInDarkTheme()
else -> false
}

MaterialTheme(
colorScheme = if (isDark) darkColorScheme() else lightColorScheme()
) {
ScreenWrapper(
mainScreenViewModel = mainScreenViewModel,
penSettingsViewModel = penSettingsViewModel,
settingsViewModel = settingsViewModel,

dropdownMenuActions = MainDropdownMenuActions(
onLoadingClick = { loadRawDataPicker.launch() },
onExportCsv = {
ioScope.launch {
saveCsvPicker.launch(
baseName = csvFilename(mainScreenViewModel.getCurrentPen().value),
extension = "csv",
bytes = mainScreenViewModel.flatDoseList.first().toCsv().toByteArray()
)
}
},
onImportCsv = { loadCsvPicker.launch() },
onInitDemo = { mainScreenViewModel.initDemoData() }
),
dropdownMenuActions = MainDropdownMenuActions(
onLoadingClick = { loadRawDataPicker.launch() },
onExportCsv = {
ioScope.launch {
saveCsvPicker.launch(
baseName = csvFilename(mainScreenViewModel.getCurrentPen().value),
extension = "csv",
bytes = mainScreenViewModel.flatDoseList.first().toCsv().toByteArray()
)
}
},
onImportCsv = { loadCsvPicker.launch() },
onInitDemo = { mainScreenViewModel.initDemoData() }
),

demoVersion = true
)
demoVersion = true
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.cacheux.nvp.app.repository

import net.cacheux.nvplib.utils.StateFlowWrapper
import net.cacheux.nvplib.utils.stateFlowWrapper
import java.io.File
import java.util.Properties
Expand All @@ -14,6 +15,7 @@ class PreferencesRepositoryImpl: PreferencesRepository {
}
}

override val theme: StateFlowWrapper<Int> = stateFlowWrapper(Theme.THEME_LIGHT)
override val groupEnabled = booleanStateFlowWrapper("groupEnabled", "true")
override val groupDelay = intStateFlowWrapper("groupDelay", "60")
override val autoIgnoreEnabled = booleanStateFlowWrapper("autoIgnoreEnabled", "true")
Expand Down
1 change: 1 addition & 0 deletions ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ kotlin {
commonMain.dependencies {
implementation(project(":model"))
implementation(project(":utils"))
implementation(libs.kotlinx.coroutines.core)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
Expand Down
4 changes: 4 additions & 0 deletions ui/src/commonMain/composeResources/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

<!-- Settings screen -->
<string name="settings">Paramètres</string>
<string name="theme">Thème</string>
<string name="theme_light">Clair</string>
<string name="theme_dark">Sombre</string>
<string name="theme_system">Système</string>
<string name="group_doses">Grouper les doses</string>
<string name="group_doses_details">Afficher les doses dans l'intervalle spécifié comme une seule</string>
<string name="group_delay">Intervalle de groupe</string>
Expand Down
4 changes: 4 additions & 0 deletions ui/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

<!-- Settings screen -->
<string name="settings">Settings</string>
<string name="theme">Theme</string>
<string name="theme_light">Light</string>
<string name="theme_dark">Dark</string>
<string name="theme_system">System</string>
<string name="group_doses">Group doses</string>
<string name="group_doses_details">Display all doses within the specified delay as one</string>
<string name="group_delay">Group delay</string>
Expand Down
15 changes: 10 additions & 5 deletions ui/src/commonMain/kotlin/net/cacheux/nvp/ui/DoseGroupDetails.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontStyle
Expand Down Expand Up @@ -51,7 +50,7 @@ fun DoseGroupDetails(
val selected = remember { mutableStateListOf<Dose>() }

Column(
modifier = modifier.background(Color.White)
modifier = modifier.background(MaterialTheme.colorScheme.background)
.testTag("doseGroupDetails")
.pointerInput(doseGroup) {
detectTapGestures(
Expand Down Expand Up @@ -118,21 +117,27 @@ fun DoseDetails(
) {
Box(
modifier
.background(Color.White)
.background(MaterialTheme.colorScheme.surfaceContainer)
.padding(4.dp),
) {
Row {
Text(
modifier = Modifier.weight(1f),
text = dose.displayedValue(),
fontWeight = FontWeight.Bold,
color = if (dose.ignored) Color.LightGray else Color.Black
color = if (dose.ignored)
MaterialTheme.colorScheme.onSurfaceVariant
else
MaterialTheme.colorScheme.onSurface
)

Text(
text = format.format(Date(dose.time)),
fontStyle = FontStyle.Italic,
color = if (dose.ignored) Color.LightGray else Color.DarkGray
color = if (dose.ignored)
MaterialTheme.colorScheme.onSurfaceVariant
else
MaterialTheme.colorScheme.onSurface
)
}
}
Expand Down
24 changes: 17 additions & 7 deletions ui/src/commonMain/kotlin/net/cacheux/nvp/ui/DoseList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand Down Expand Up @@ -49,7 +50,8 @@ fun DoseList(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.padding(8.dp),
.padding(8.dp)
.background(MaterialTheme.colorScheme.surfaceBright),
contentAlignment = Alignment.Center,
) {
Text(
Expand Down Expand Up @@ -93,7 +95,8 @@ fun DoseListHeader(
Text(
text = headerDate.format(Date(date)),
fontSize = 14.sp,
fontWeight = FontWeight.SemiBold
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
}
}
Expand All @@ -110,23 +113,28 @@ fun DoseListItem(
Box(
modifier = Modifier
.background(
color = dose.doses.first().color.hexToColor().copy(alpha = 0.5f)
color = dose.doses.first().color.hexToColor().copy(
alpha = if (isInDarkMode()) 0.3f else 0.5f
)
)
.fillMaxWidth()
.clickable { onClick(dose) }
) {
Column(
modifier = Modifier
.padding(horizontal = 4.dp)
.fillMaxWidth()
) {
Text(
fontSize = 14.sp,
fontStyle = FontStyle.Italic,
color = MaterialTheme.colorScheme.onSurface,
text = format.format(Date(dose.getTime()))
)
Text(
fontSize = 18.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface,
text = dose.displayedTotal()
)

Expand All @@ -153,10 +161,12 @@ fun DoseListPreview() {
testDoseGroup(testDateTime(12, 1, 15, date = 2), 14),
testDoseGroup(testDateTime(12, 1, 14, date = 3), 14),
)
DoseList(
items,
currentDoseGroup = current
)
MaterialTheme(colorScheme = darkColorScheme()) {
DoseList(
items,
currentDoseGroup = current
)
}
}

@Preview
Expand Down
Loading