Skip to content

Commit 36d8a65

Browse files
committed
Implement proper storage for notification settings
1 parent 60f43a7 commit 36d8a65

File tree

9 files changed

+82
-16
lines changed

9 files changed

+82
-16
lines changed

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/App.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import org.jetbrains.kotlinconf.screens.PrivacyPolicyViewModel
1919
import org.jetbrains.kotlinconf.screens.ScheduleViewModel
2020
import org.jetbrains.kotlinconf.screens.SessionViewModel
2121
import org.jetbrains.kotlinconf.screens.SettingsViewModel
22+
import org.jetbrains.kotlinconf.screens.StartNotificationsViewModel
2223
import org.jetbrains.kotlinconf.storage.ApplicationStorage
2324
import org.jetbrains.kotlinconf.storage.MultiplatformSettingsStorage
2425
import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme
@@ -77,6 +78,7 @@ private fun koinConfiguration(context: ApplicationContext) = koinConfiguration {
7778
viewModelOf(::SessionViewModel)
7879
viewModelOf(::SettingsViewModel)
7980
viewModelOf(::NewsListViewModel)
81+
viewModelOf(::StartNotificationsViewModel)
8082
viewModelOf(::NewsDetailViewModel)
8183
}
8284

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/ConferenceService.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,19 @@ class ConferenceService(
142142
fun requestNotificationPermissions() {
143143
scope.launch {
144144
storage.setNotificationsAllowed(true)
145+
storage.setNotificationSettings(NotificationSettings()) // Set default values (all true)
145146
notificationManager.requestPermission()
146147
}
147148
}
148149

150+
fun getNotificationSettings(): Flow<NotificationSettings> = storage.getNotificationSettings()
151+
152+
fun setNotificationSettings(settings: NotificationSettings) {
153+
scope.launch {
154+
storage.setNotificationSettings(settings)
155+
}
156+
}
157+
149158
/**
150159
* Vote for session.
151160
*/

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/Model.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package org.jetbrains.kotlinconf
22

3-
import io.ktor.util.date.*
4-
import kotlinx.serialization.*
5-
import org.jetbrains.kotlinconf.utils.*
3+
import io.ktor.util.date.GMTDate
4+
import kotlinx.serialization.Serializable
5+
import org.jetbrains.kotlinconf.utils.GMTDateSerializer
6+
import org.jetbrains.kotlinconf.utils.time
67
import kotlin.jvm.JvmInline
78

89
typealias GMTDateSerializable = @Serializable(GMTDateSerializer::class) GMTDate
@@ -97,8 +98,9 @@ class NewsItem(
9798
val content: String,
9899
)
99100

101+
@Serializable
100102
data class NotificationSettings(
101-
val scheduleUpdates: Boolean,
102-
val kotlinConfNews: Boolean,
103-
val jetbrainsNews: Boolean,
103+
val scheduleUpdates: Boolean = true,
104+
val kotlinConfNews: Boolean = true,
105+
val jetbrainsNews: Boolean = true,
104106
)

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/SettingsScreen.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ fun SettingsScreen(
8484
viewModel.setTheme(theme)
8585
},
8686
onNotificationSettingsChange = onNotificationSettingsChange,
87+
viewModel = viewModel,
8788
modifier = Modifier
8889
.drawWithContent {
8990
graphicsLayer.record {
@@ -114,6 +115,7 @@ private fun SettingsScreenImpl(
114115
currentTheme: Theme,
115116
onThemeChange: (Theme) -> Unit,
116117
onNotificationSettingsChange: (NotificationSettings) -> Unit,
118+
viewModel: SettingsViewModel,
117119
modifier: Modifier = Modifier,
118120
) {
119121
ScreenWithTitle(
@@ -140,12 +142,11 @@ private fun SettingsScreenImpl(
140142

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

143-
// TODO populate with real values https://github.com/JetBrains/kotlinconf-app/issues/252
144-
var notificationSettings by remember { mutableStateOf(NotificationSettings(false, false, false)) }
145+
val notificationSettings by viewModel.notificationSettings.collectAsStateWithLifecycle()
145146
NotificationSettings(
146147
notificationSettings = notificationSettings,
147148
onChangeSettings = { newSettings ->
148-
notificationSettings = newSettings
149+
viewModel.setNotificationSettings(newSettings)
149150
onNotificationSettingsChange(newSettings)
150151
}
151152
)

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/SettingsViewModel.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import kotlinx.coroutines.flow.SharingStarted
66
import kotlinx.coroutines.flow.StateFlow
77
import kotlinx.coroutines.flow.stateIn
88
import org.jetbrains.kotlinconf.ConferenceService
9+
import org.jetbrains.kotlinconf.NotificationSettings
910
import org.jetbrains.kotlinconf.Theme
1011

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

18+
val notificationSettings: StateFlow<NotificationSettings> = service.getNotificationSettings()
19+
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), NotificationSettings())
20+
1721
fun setTheme(theme: Theme) {
1822
service.setTheme(theme)
1923
}
24+
25+
fun setNotificationSettings(settings: NotificationSettings) {
26+
service.setNotificationSettings(settings)
27+
}
2028
}

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/screens/StartNotificationsScreen.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ import androidx.compose.foundation.rememberScrollState
1313
import androidx.compose.foundation.verticalScroll
1414
import androidx.compose.runtime.Composable
1515
import androidx.compose.runtime.getValue
16-
import androidx.compose.runtime.mutableStateOf
17-
import androidx.compose.runtime.remember
18-
import androidx.compose.runtime.setValue
1916
import androidx.compose.ui.Modifier
2017
import androidx.compose.ui.unit.dp
18+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2119
import kotlinconfapp.shared.generated.resources.kodee_notifications
2220
import kotlinconfapp.shared.generated.resources.notifications_description
2321
import kotlinconfapp.shared.generated.resources.notifications_lets_get_started
@@ -28,14 +26,15 @@ import org.jetbrains.kotlinconf.NotificationSettings
2826
import org.jetbrains.kotlinconf.ui.components.Button
2927
import org.jetbrains.kotlinconf.ui.components.StyledText
3028
import org.jetbrains.kotlinconf.ui.theme.KotlinConfTheme
29+
import org.koin.compose.viewmodel.koinViewModel
3130
import kotlinconfapp.shared.generated.resources.Res as AppRes
3231

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

4039
Column(modifier = Modifier.fillMaxSize()) {
4140
Column(
@@ -59,7 +58,10 @@ fun StartNotificationsScreen(
5958
stringResource(AppRes.string.notifications_description),
6059
color = KotlinConfTheme.colors.longText,
6160
)
62-
NotificationSettings(notificationSettings, { notificationSettings = it })
61+
NotificationSettings(
62+
notificationSettings = notificationSettings,
63+
onChangeSettings = { viewModel.setNotificationSettings(it) }
64+
)
6365
}
6466

6567
Row(
@@ -68,7 +70,10 @@ fun StartNotificationsScreen(
6870
) {
6971
Button(
7072
label = stringResource(AppRes.string.notifications_lets_get_started),
71-
onClick = { onDone(notificationSettings) },
73+
onClick = {
74+
viewModel.requestNotificationPermissions()
75+
onDone(notificationSettings)
76+
},
7277
modifier = Modifier.weight(1f),
7378
primary = true,
7479
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.jetbrains.kotlinconf.screens
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewModelScope
5+
import kotlinx.coroutines.flow.SharingStarted
6+
import kotlinx.coroutines.flow.StateFlow
7+
import kotlinx.coroutines.flow.stateIn
8+
import org.jetbrains.kotlinconf.ConferenceService
9+
import org.jetbrains.kotlinconf.NotificationSettings
10+
11+
class StartNotificationsViewModel(
12+
private val service: ConferenceService,
13+
) : ViewModel() {
14+
val notificationSettings: StateFlow<NotificationSettings> = service.getNotificationSettings()
15+
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), NotificationSettings())
16+
17+
fun setNotificationSettings(settings: NotificationSettings) {
18+
service.setNotificationSettings(settings)
19+
}
20+
21+
fun requestNotificationPermissions() {
22+
service.requestNotificationPermissions()
23+
}
24+
}

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/storage/ApplicationStorage.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.jetbrains.kotlinconf.storage
33
import kotlinx.coroutines.flow.Flow
44
import org.jetbrains.kotlinconf.Conference
55
import org.jetbrains.kotlinconf.NewsItem
6+
import org.jetbrains.kotlinconf.NotificationSettings
67
import org.jetbrains.kotlinconf.SessionId
78
import org.jetbrains.kotlinconf.Theme
89

@@ -27,4 +28,7 @@ interface ApplicationStorage {
2728

2829
fun getNews(): Flow<List<NewsItem>>
2930
suspend fun setNews(value: List<NewsItem>)
31+
32+
fun getNotificationSettings(): Flow<NotificationSettings>
33+
suspend fun setNotificationSettings(value: NotificationSettings)
3034
}

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/storage/MultiplatformSettingsStorage.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import kotlinx.serialization.json.Json
1212
import org.jetbrains.kotlinconf.ApplicationContext
1313
import org.jetbrains.kotlinconf.Conference
1414
import org.jetbrains.kotlinconf.NewsItem
15+
import org.jetbrains.kotlinconf.NotificationSettings
1516
import org.jetbrains.kotlinconf.SessionId
1617
import org.jetbrains.kotlinconf.Theme
1718

@@ -50,6 +51,15 @@ class MultiplatformSettingsStorage(context: ApplicationContext) : ApplicationSto
5051
Json.encodeToString(value)
5152
)
5253

54+
override fun getNotificationSettings(): Flow<NotificationSettings> =
55+
settings.getStringOrNullFlow(Keys.NOTIFICATION_SETTINGS)
56+
.map { it?.let { Json.decodeFromString<NotificationSettings>(it) } ?: NotificationSettings() }
57+
58+
override suspend fun setNotificationSettings(value: NotificationSettings) = settings.set(
59+
Keys.NOTIFICATION_SETTINGS,
60+
Json.encodeToString(value)
61+
)
62+
5363
private object Keys {
5464
const val USER_ID = "userid2025"
5565
const val ONBOARDING_COMPLETE = "onboardingComplete"
@@ -58,5 +68,6 @@ class MultiplatformSettingsStorage(context: ApplicationContext) : ApplicationSto
5868
const val CONFERENCE_CACHE = "conferenceCache"
5969
const val NEWS_CACHE = "newsCache"
6070
const val FAVORITES = "favorites"
71+
const val NOTIFICATION_SETTINGS = "notificationSettings"
6172
}
6273
}

0 commit comments

Comments
 (0)