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
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.ohnalmwo.data.di

import com.ohnalmwo.data.repository.LocationRepositoryImpl
import com.ohnalmwo.data.repository.NotificationRepositoryImpl
import com.ohnalmwo.data.repository.SettingRepositoryImpl
import com.ohnalmwo.data.repository.WeatherRepositoryImpl
import com.ohnalmwo.domain.repository.LocationRepository
import com.ohnalmwo.domain.repository.NotificationRepository
import com.ohnalmwo.domain.repository.SettingRepository
import com.ohnalmwo.domain.repository.WeatherRepository
import com.ohnalmwo.network.datasource.notification.NotificationDataSourceImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -32,4 +35,10 @@ abstract class RepositoryModule {
abstract fun bindSettingRepository(
settingRepositoryImpl: SettingRepositoryImpl
): SettingRepository

@Binds
@Singleton
abstract fun bindNotificationRepository(
notificationRepositoryImpl: NotificationRepositoryImpl
): NotificationRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ohnalmwo.data.repository

import com.ohnalmwo.domain.repository.NotificationRepository
import com.ohnalmwo.network.datasource.notification.NotificationDataSource
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class NotificationRepositoryImpl @Inject constructor(
private val notificationDataSource: NotificationDataSource
) : NotificationRepository {
override suspend fun saveDeviceToken(deviceToken: String, alarmTime: String): Flow<Unit> {
return notificationDataSource.saveDeviceToken(deviceToken = deviceToken, alarmTime = alarmTime)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ class SettingRepositoryImpl @Inject constructor(
override fun getAlarmState(): Flow<Switch> {
return localSettingDataSource.getAlarmState()
}

override suspend fun setAlarmTime(alarmTime: String) {
localSettingDataSource.setAlarmTime(alarmTime = alarmTime)
}

override fun getAlarmTime(): Flow<String> {
return localSettingDataSource.getAlarmTime()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ interface SettingDataSource {
suspend fun setAlarmState(alarmState: String)

fun getAlarmState(): Flow<Switch>

suspend fun setAlarmTime(alarmTime: String)

fun getAlarmTime(): Flow<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ package com.ohnalmwo.datastore.datasource.setting
import android.util.Log
import androidx.datastore.core.DataStore
import com.ohnalmwo.datastore.Locations
import com.ohnalmwo.datastore.NotificationTime
import com.ohnalmwo.datastore.SettingInfo
import com.ohnalmwo.datastore.mapper.toData
import com.ohnalmwo.datastore.mapper.toDomain
import com.ohnalmwo.datastore.serializer.NotificationTimeSerializer
import com.ohnalmwo.model.LocationInfo
import com.ohnalmwo.model.enum.Switch
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class SettingDataSourceImpl @Inject constructor (
private val settingInfo: DataStore<SettingInfo>
private val settingInfo: DataStore<SettingInfo>,
private val notificationTime: DataStore<NotificationTime>,
) : SettingDataSource {
override suspend fun setAlarmState(alarmState: String) {
settingInfo.updateData {
Expand All @@ -31,4 +34,17 @@ class SettingDataSourceImpl @Inject constructor (
else -> Switch.OFF
}
}

override suspend fun setAlarmTime(alarmTime: String) {
notificationTime.updateData {
it.toBuilder()
.setTime(alarmTime)
.build()
}
}

override fun getAlarmTime(): Flow<String> =
notificationTime.data.map {
it.time ?: "00:00"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.dataStoreFile
import com.ohnalmwo.datastore.Locations
import com.ohnalmwo.datastore.NotificationTime
import com.ohnalmwo.datastore.SettingInfo
import com.ohnalmwo.datastore.serializer.LocationsSerializer
import com.ohnalmwo.datastore.serializer.NotificationTimeSerializer
import com.ohnalmwo.datastore.serializer.SettingSerializer
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -41,4 +43,16 @@ object DataStoreModule {
) {
context.dataStoreFile("settingInfo.pb")
}

@Provides
@Singleton
fun provideNotificationDataStore(
@ApplicationContext context: Context,
notificationTimeSerializer: NotificationTimeSerializer
): DataStore<NotificationTime> =
DataStoreFactory.create(
serializer = notificationTimeSerializer,
) {
context.dataStoreFile("notificationTime.pb")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ohnalmwo.datastore.serializer

import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer
import com.google.protobuf.InvalidProtocolBufferException
import com.ohnalmwo.datastore.NotificationTime
import java.io.InputStream
import java.io.OutputStream
import javax.inject.Inject

class NotificationTimeSerializer @Inject constructor() : Serializer<NotificationTime> {
override val defaultValue: NotificationTime = NotificationTime.getDefaultInstance()

override suspend fun readFrom(input: InputStream): NotificationTime =
try {
NotificationTime.parseFrom(input)
} catch (e: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto", e)
}

override suspend fun writeTo(t: NotificationTime, output: OutputStream) {
t.writeTo(output)
}
}
8 changes: 8 additions & 0 deletions core/datastore/src/main/proto/notificationTime.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
syntax = "proto3";

option java_package = "com.ohnalmwo.datastore";
option java_multiple_files = true;

message NotificationTime {
string time = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.ohnalmwo.domain.repository

import kotlinx.coroutines.flow.Flow

interface NotificationRepository {
suspend fun saveDeviceToken(deviceToken: String, alarmTime: String): Flow<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ interface SettingRepository {
suspend fun setAlarmState(alarmState: String)

fun getAlarmState(): Flow<Switch>

suspend fun setAlarmTime(alarmTime: String)

fun getAlarmTime(): Flow<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ohnalmwo.domain.usecase.setting

import com.ohnalmwo.domain.repository.SettingRepository
import com.ohnalmwo.model.enum.Switch
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class GetAlarmTimeUseCase @Inject constructor(
private val settingRepository: SettingRepository
) {
operator fun invoke(): Flow<String> =
settingRepository.getAlarmTime()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ohnalmwo.domain.usecase.setting

import com.ohnalmwo.domain.repository.SettingRepository
import javax.inject.Inject

class SetAlarmTimeUseCase @Inject constructor(
private val settingRepository: SettingRepository
) {
suspend operator fun invoke(alarmTime: String) {
settingRepository.setAlarmTime(alarmTime = alarmTime)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ohnalmwo.network.api

import com.ohnalmwo.network.dto.LocationResponse
import kotlinx.coroutines.flow.Flow
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query

interface NotificationAPI {
@POST("notification")
suspend fun saveDeviceToken(
@Query("deviceToken") deviceToken: String,
@Query("alarmTime") alarmTime: String,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ohnalmwo.network.datasource.notification

import com.ohnalmwo.network.dto.LocationResponse
import kotlinx.coroutines.flow.Flow

interface NotificationDataSource {
suspend fun saveDeviceToken(deviceToken: String, alarmTime: String): Flow<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ohnalmwo.network.datasource.notification

import com.ohnalmwo.network.api.LocationAPI
import com.ohnalmwo.network.api.NotificationAPI
import com.ohnalmwo.network.dto.LocationResponse
import com.ohnalmwo.network.util.ApiHandler
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import javax.inject.Inject

class NotificationDataSourceImpl @Inject constructor(
private val notificationAPI: NotificationAPI
) : NotificationDataSource {
override suspend fun saveDeviceToken(deviceToken: String, alarmTime: String): Flow<Unit> = flow {
ApiHandler<Unit>().request {
notificationAPI.saveDeviceToken(deviceToken = deviceToken, alarmTime = alarmTime)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.ohnalmwo.network.di
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.ohnalmwo.network.BuildConfig
import com.ohnalmwo.network.api.LocationAPI
import com.ohnalmwo.network.api.NotificationAPI
import com.ohnalmwo.network.api.WeatherAPI
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -69,4 +70,9 @@ object NetworkModule {
@Singleton
fun provideLocationAPI(retrofit: Retrofit): LocationAPI =
retrofit.create(LocationAPI::class.java)

@Provides
@Singleton
fun provideNotificationAPI(retrofit: Retrofit): NotificationAPI =
retrofit.create(NotificationAPI::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.ohnalmwo.network.di

import com.ohnalmwo.network.datasource.location.LocationDataSource
import com.ohnalmwo.network.datasource.location.LocationDataSourceImpl
import com.ohnalmwo.network.datasource.notification.NotificationDataSource
import com.ohnalmwo.network.datasource.notification.NotificationDataSourceImpl
import com.ohnalmwo.network.datasource.weather.WeatherDataSource
import com.ohnalmwo.network.datasource.weather.WeatherDataSourceImpl
import dagger.Binds
Expand All @@ -24,4 +26,10 @@ abstract class RemoteDataSourceModule {
abstract fun bindLocationDataSource(
locationDataSourceImpl: LocationDataSourceImpl
): LocationDataSource

@Binds
@Singleton
abstract fun bindNotificationDataSource(
notificationDataSourceImpl: NotificationDataSourceImpl
): NotificationDataSource
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fun SettingAlarmRoute(

LaunchedEffect(Unit) {
viewModel.getAlarmState()
viewModel.getAlarmTime()
}

LaunchedEffect(effect) {
Expand All @@ -50,13 +51,20 @@ fun SettingAlarmRoute(

SettingAlarmScreen(
state = state,
onAlarmStateChange = { viewModel.sendEvent(SettingEvent.OnChangeAlarmState(it))},
onAlarmStateChange = { viewModel.sendEvent(SettingEvent.OnChangeAlarmState(it)) },
onSetAlarmTime = { updatedHour, updatedMinute, updatedAmPm ->
viewModel.sendEvent(
SettingEvent.OnChangeAlarmTime(hour = updatedHour, minute = updatedMinute, amPm = updatedAmPm)
)
},
navigateToBack = {
val desiredAlarmState = if (state.alarmState) Switch.ON else Switch.OFF

if (desiredAlarmState != state.isAlarmOn)
viewModel.setAlarmState(desiredAlarmState) else
viewModel.sendEffect(SettingEffect.NavigateToBack)
if (desiredAlarmState != state.isAlarmOn) {
viewModel.setAlarmState(desiredAlarmState)
} else {
viewModel.setAlarmTime(state.hour,state.minute,state.amPm)
}
}
)
}
Expand All @@ -65,12 +73,9 @@ fun SettingAlarmRoute(
fun SettingAlarmScreen(
state: SettingState,
onAlarmStateChange: (Boolean) -> Unit,
onSetAlarmTime: (Int, Int, String) -> Unit,
navigateToBack: () -> Unit
) {
var hour by remember { mutableIntStateOf(8) }
var minute by remember { mutableIntStateOf(0) }
var amPm by remember { mutableStateOf("PM") }

Column(
modifier = Modifier
.fillMaxSize()
Expand All @@ -95,13 +100,11 @@ fun SettingAlarmScreen(

if (state.alarmState) {
AlarmTimeSection(
hour = hour,
minute = minute,
amPm = amPm,
hour = state.hour,
minute = state.minute,
amPm = state.amPm,
onTimeUpdated = { updatedHour, updatedMinute, updatedAmPm ->
hour = updatedHour
minute = updatedMinute
amPm = updatedAmPm
onSetAlarmTime(updatedHour, updatedMinute, updatedAmPm)
}
)
}
Expand Down
Loading