Skip to content

Commit

Permalink
Implement proper storage for notification settings
Browse files Browse the repository at this point in the history
  • Loading branch information
zsmb13 committed Feb 10, 2025
1 parent 60f43a7 commit 36d8a65
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 16 deletions.
2 changes: 2 additions & 0 deletions shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import org.jetbrains.kotlinconf.screens.PrivacyPolicyViewModel
import org.jetbrains.kotlinconf.screens.ScheduleViewModel
import org.jetbrains.kotlinconf.screens.SessionViewModel
import org.jetbrains.kotlinconf.screens.SettingsViewModel
import org.jetbrains.kotlinconf.screens.StartNotificationsViewModel
import org.jetbrains.kotlinconf.storage.ApplicationStorage
import org.jetbrains.kotlinconf.storage.MultiplatformSettingsStorage
import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme
Expand Down Expand Up @@ -77,6 +78,7 @@ private fun koinConfiguration(context: ApplicationContext) = koinConfiguration {
viewModelOf(::SessionViewModel)
viewModelOf(::SettingsViewModel)
viewModelOf(::NewsListViewModel)
viewModelOf(::StartNotificationsViewModel)
viewModelOf(::NewsDetailViewModel)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,19 @@ class ConferenceService(
fun requestNotificationPermissions() {
scope.launch {
storage.setNotificationsAllowed(true)
storage.setNotificationSettings(NotificationSettings()) // Set default values (all true)
notificationManager.requestPermission()
}
}

fun getNotificationSettings(): Flow<NotificationSettings> = storage.getNotificationSettings()

fun setNotificationSettings(settings: NotificationSettings) {
scope.launch {
storage.setNotificationSettings(settings)
}
}

/**
* Vote for session.
*/
Expand Down
14 changes: 8 additions & 6 deletions shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/Model.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.jetbrains.kotlinconf

import io.ktor.util.date.*
import kotlinx.serialization.*
import org.jetbrains.kotlinconf.utils.*
import io.ktor.util.date.GMTDate
import kotlinx.serialization.Serializable
import org.jetbrains.kotlinconf.utils.GMTDateSerializer
import org.jetbrains.kotlinconf.utils.time
import kotlin.jvm.JvmInline

typealias GMTDateSerializable = @Serializable(GMTDateSerializer::class) GMTDate
Expand Down Expand Up @@ -97,8 +98,9 @@ class NewsItem(
val content: String,
)

@Serializable
data class NotificationSettings(
val scheduleUpdates: Boolean,
val kotlinConfNews: Boolean,
val jetbrainsNews: Boolean,
val scheduleUpdates: Boolean = true,
val kotlinConfNews: Boolean = true,
val jetbrainsNews: Boolean = true,
)
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ fun SettingsScreen(
viewModel.setTheme(theme)
},
onNotificationSettingsChange = onNotificationSettingsChange,
viewModel = viewModel,
modifier = Modifier
.drawWithContent {
graphicsLayer.record {
Expand Down Expand Up @@ -114,6 +115,7 @@ private fun SettingsScreenImpl(
currentTheme: Theme,
onThemeChange: (Theme) -> Unit,
onNotificationSettingsChange: (NotificationSettings) -> Unit,
viewModel: SettingsViewModel,
modifier: Modifier = Modifier,
) {
ScreenWithTitle(
Expand All @@ -140,12 +142,11 @@ private fun SettingsScreenImpl(

Divider(thickness = 1.dp, color = KotlinConfTheme.colors.strokePale)

// TODO populate with real values https://github.com/JetBrains/kotlinconf-app/issues/252
var notificationSettings by remember { mutableStateOf(NotificationSettings(false, false, false)) }
val notificationSettings by viewModel.notificationSettings.collectAsStateWithLifecycle()
NotificationSettings(
notificationSettings = notificationSettings,
onChangeSettings = { newSettings ->
notificationSettings = newSettings
viewModel.setNotificationSettings(newSettings)
onNotificationSettingsChange(newSettings)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import org.jetbrains.kotlinconf.ConferenceService
import org.jetbrains.kotlinconf.NotificationSettings
import org.jetbrains.kotlinconf.Theme

class SettingsViewModel(
Expand All @@ -14,7 +15,14 @@ class SettingsViewModel(
val theme: StateFlow<Theme> = service.getTheme()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), Theme.SYSTEM)

val notificationSettings: StateFlow<NotificationSettings> = service.getNotificationSettings()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), NotificationSettings())

fun setTheme(theme: Theme) {
service.setTheme(theme)
}

fun setNotificationSettings(settings: NotificationSettings) {
service.setNotificationSettings(settings)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinconfapp.shared.generated.resources.kodee_notifications
import kotlinconfapp.shared.generated.resources.notifications_description
import kotlinconfapp.shared.generated.resources.notifications_lets_get_started
Expand All @@ -28,14 +26,15 @@ import org.jetbrains.kotlinconf.NotificationSettings
import org.jetbrains.kotlinconf.ui.components.Button
import org.jetbrains.kotlinconf.ui.components.StyledText
import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme
import org.koin.compose.viewmodel.koinViewModel
import kotlinconfapp.shared.generated.resources.Res as AppRes

@Composable
fun StartNotificationsScreen(
onDone: (NotificationSettings) -> Unit,
viewModel: StartNotificationsViewModel = koinViewModel(),
) {
// TODO populate with real values https://github.com/JetBrains/kotlinconf-app/issues/252
var notificationSettings by remember { mutableStateOf(NotificationSettings(false, false, false)) }
val notificationSettings by viewModel.notificationSettings.collectAsStateWithLifecycle()

Column(modifier = Modifier.fillMaxSize()) {
Column(
Expand All @@ -59,7 +58,10 @@ fun StartNotificationsScreen(
stringResource(AppRes.string.notifications_description),
color = KotlinConfTheme.colors.longText,
)
NotificationSettings(notificationSettings, { notificationSettings = it })
NotificationSettings(
notificationSettings = notificationSettings,
onChangeSettings = { viewModel.setNotificationSettings(it) }
)
}

Row(
Expand All @@ -68,7 +70,10 @@ fun StartNotificationsScreen(
) {
Button(
label = stringResource(AppRes.string.notifications_lets_get_started),
onClick = { onDone(notificationSettings) },
onClick = {
viewModel.requestNotificationPermissions()
onDone(notificationSettings)
},
modifier = Modifier.weight(1f),
primary = true,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.jetbrains.kotlinconf.screens

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import org.jetbrains.kotlinconf.ConferenceService
import org.jetbrains.kotlinconf.NotificationSettings

class StartNotificationsViewModel(
private val service: ConferenceService,
) : ViewModel() {
val notificationSettings: StateFlow<NotificationSettings> = service.getNotificationSettings()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), NotificationSettings())

fun setNotificationSettings(settings: NotificationSettings) {
service.setNotificationSettings(settings)
}

fun requestNotificationPermissions() {
service.requestNotificationPermissions()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.jetbrains.kotlinconf.storage
import kotlinx.coroutines.flow.Flow
import org.jetbrains.kotlinconf.Conference
import org.jetbrains.kotlinconf.NewsItem
import org.jetbrains.kotlinconf.NotificationSettings
import org.jetbrains.kotlinconf.SessionId
import org.jetbrains.kotlinconf.Theme

Expand All @@ -27,4 +28,7 @@ interface ApplicationStorage {

fun getNews(): Flow<List<NewsItem>>
suspend fun setNews(value: List<NewsItem>)

fun getNotificationSettings(): Flow<NotificationSettings>
suspend fun setNotificationSettings(value: NotificationSettings)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import kotlinx.serialization.json.Json
import org.jetbrains.kotlinconf.ApplicationContext
import org.jetbrains.kotlinconf.Conference
import org.jetbrains.kotlinconf.NewsItem
import org.jetbrains.kotlinconf.NotificationSettings
import org.jetbrains.kotlinconf.SessionId
import org.jetbrains.kotlinconf.Theme

Expand Down Expand Up @@ -50,6 +51,15 @@ class MultiplatformSettingsStorage(context: ApplicationContext) : ApplicationSto
Json.encodeToString(value)
)

override fun getNotificationSettings(): Flow<NotificationSettings> =
settings.getStringOrNullFlow(Keys.NOTIFICATION_SETTINGS)
.map { it?.let { Json.decodeFromString<NotificationSettings>(it) } ?: NotificationSettings() }

override suspend fun setNotificationSettings(value: NotificationSettings) = settings.set(
Keys.NOTIFICATION_SETTINGS,
Json.encodeToString(value)
)

private object Keys {
const val USER_ID = "userid2025"
const val ONBOARDING_COMPLETE = "onboardingComplete"
Expand All @@ -58,5 +68,6 @@ class MultiplatformSettingsStorage(context: ApplicationContext) : ApplicationSto
const val CONFERENCE_CACHE = "conferenceCache"
const val NEWS_CACHE = "newsCache"
const val FAVORITES = "favorites"
const val NOTIFICATION_SETTINGS = "notificationSettings"
}
}

0 comments on commit 36d8a65

Please sign in to comment.