From 68a884bc9b737405e0ddcefd959d27edbe029333 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Mon, 16 Dec 2024 20:37:10 +0900 Subject: [PATCH 01/15] :sparkles: :: Change hour,minute,amPm state --- .../ohnalmwo/setting/SettingAlarmScreen.kt | 22 +++++++++---------- .../setting/viewmodel/SettingScreenReducer.kt | 19 ++++++++++++++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt b/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt index 9396e3d..eeebb57 100644 --- a/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt +++ b/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt @@ -50,7 +50,12 @@ 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 @@ -65,12 +70,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() @@ -95,13 +97,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) } ) } diff --git a/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingScreenReducer.kt b/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingScreenReducer.kt index faafc4e..44288ee 100644 --- a/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingScreenReducer.kt +++ b/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingScreenReducer.kt @@ -16,6 +16,7 @@ class SettingScreenReducer : data object SetAlarmState : SettingEvent() data class GetAlarmState(val isLoading: Boolean, val isAlarmOn: Switch) : SettingEvent() data class OnChangeAlarmState(val alarmState: Boolean) : SettingEvent() + data class OnChangeAlarmTime(val hour: Int, val minute: Int, val amPm: String) : SettingEvent() } @Immutable @@ -27,13 +28,19 @@ class SettingScreenReducer : data class SettingState( val isLoading: Boolean, val isAlarmOn: Switch, - val alarmState: Boolean + val alarmState: Boolean, + val hour: Int, + val minute: Int, + val amPm: String ) : Reducer.ViewState { companion object { fun initial() = SettingState( isLoading = true, isAlarmOn = Switch.OFF, - alarmState = false + alarmState = false, + hour = 8, + minute = 0, + amPm = "PM" ) } } @@ -60,5 +67,13 @@ class SettingScreenReducer : alarmState = event.alarmState ) to null } + + is SettingEvent.OnChangeAlarmTime -> { + previousState.copy( + hour = event.hour, + minute = event.minute, + amPm = event.amPm + ) to null + } } } \ No newline at end of file From d4bbb56945f6efcc601bfa369e0a578d0ab29cfa Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Wed, 18 Dec 2024 08:42:56 +0900 Subject: [PATCH 02/15] :sparkles: :: Add setAlarmTime dataSource --- .../datastore/datasource/setting/SettingDataSource.kt | 2 ++ .../datastore/datasource/setting/SettingDataSourceImpl.kt | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt index efe5dc9..9045792 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt @@ -8,4 +8,6 @@ interface SettingDataSource { suspend fun setAlarmState(alarmState: String) fun getAlarmState(): Flow + + suspend fun setAlarmTime(alarmTime: String) } \ No newline at end of file diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt index 467f340..479fce3 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt @@ -31,4 +31,12 @@ class SettingDataSourceImpl @Inject constructor ( else -> Switch.OFF } } + + override suspend fun setAlarmTime(alarmTime: String) { + settingInfo.updateData { + it.toBuilder() + .setAlarm(alarmTime) + .build() + } + } } \ No newline at end of file From 9b0521e39b198540de0788e95877dbb03f24fa77 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Wed, 18 Dec 2024 08:43:11 +0900 Subject: [PATCH 03/15] :sparkles: :: Add setAlarmTime Repository --- .../com/ohnalmwo/data/repository/SettingRepositoryImpl.kt | 4 ++++ .../java/com/ohnalmwo/domain/repository/SettingRepository.kt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt b/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt index 91d0069..5ac1e88 100644 --- a/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt +++ b/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt @@ -16,4 +16,8 @@ class SettingRepositoryImpl @Inject constructor( override fun getAlarmState(): Flow { return localSettingDataSource.getAlarmState() } + + override suspend fun setAlarmTime(alarmTime: String) { + localSettingDataSource.setAlarmTime(alarmTime = alarmTime) + } } \ No newline at end of file diff --git a/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt b/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt index 80fe3e7..e2f6119 100644 --- a/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt +++ b/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt @@ -7,4 +7,6 @@ interface SettingRepository { suspend fun setAlarmState(alarmState: String) fun getAlarmState(): Flow + + suspend fun setAlarmTime(alarmTime: String) } \ No newline at end of file From 7d7d03c8b0f5ab31fe062d717c6a4aa9cdc88bef Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Thu, 19 Dec 2024 08:32:13 +0900 Subject: [PATCH 04/15] :sparkles: :: Add SetAlarmTimeUseCase --- .../domain/usecase/setting/SetAlarmTimeUseCase.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/SetAlarmTimeUseCase.kt diff --git a/core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/SetAlarmTimeUseCase.kt b/core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/SetAlarmTimeUseCase.kt new file mode 100644 index 0000000..1beb103 --- /dev/null +++ b/core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/SetAlarmTimeUseCase.kt @@ -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) + } +} \ No newline at end of file From 76a69fc04f12742a528f2dc38397d225899db098 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Thu, 19 Dec 2024 08:56:27 +0900 Subject: [PATCH 05/15] :sparkles: :: Add notificationTime.proto --- .../setting/SettingDataSourceImpl.kt | 9 ++++--- .../ohnalmwo/datastore/di/DataStoreModule.kt | 14 +++++++++++ .../serializer/NotificationTimeSerializer.kt | 24 +++++++++++++++++++ .../src/main/proto/notificationTime.proto | 8 +++++++ 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 core/datastore/src/main/java/com/ohnalmwo/datastore/serializer/NotificationTimeSerializer.kt create mode 100644 core/datastore/src/main/proto/notificationTime.proto diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt index 479fce3..b8b0511 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt @@ -3,9 +3,11 @@ 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 @@ -13,7 +15,8 @@ import kotlinx.coroutines.flow.map import javax.inject.Inject class SettingDataSourceImpl @Inject constructor ( - private val settingInfo: DataStore + private val settingInfo: DataStore, + private val notificationTime: DataStore, ) : SettingDataSource { override suspend fun setAlarmState(alarmState: String) { settingInfo.updateData { @@ -33,9 +36,9 @@ class SettingDataSourceImpl @Inject constructor ( } override suspend fun setAlarmTime(alarmTime: String) { - settingInfo.updateData { + notificationTime.updateData { it.toBuilder() - .setAlarm(alarmTime) + .setTime(alarmTime) .build() } } diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt index 3fc2f02..18aa46a 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt @@ -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 @@ -41,4 +43,16 @@ object DataStoreModule { ) { context.dataStoreFile("settingInfo.pb") } + + @Provides + @Singleton + fun provideNotificationDataStore( + @ApplicationContext context: Context, + notificationTimeSerializer: NotificationTimeSerializer + ): DataStore = + DataStoreFactory.create( + serializer = notificationTimeSerializer, + ) { + context.dataStoreFile("settingInfo.pb") + } } \ No newline at end of file diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/serializer/NotificationTimeSerializer.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/serializer/NotificationTimeSerializer.kt new file mode 100644 index 0000000..519d324 --- /dev/null +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/serializer/NotificationTimeSerializer.kt @@ -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 { + 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) + } +} \ No newline at end of file diff --git a/core/datastore/src/main/proto/notificationTime.proto b/core/datastore/src/main/proto/notificationTime.proto new file mode 100644 index 0000000..f405f25 --- /dev/null +++ b/core/datastore/src/main/proto/notificationTime.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "com.ohnalmwo.datastore"; +option java_multiple_files = true; + +message NotificationTime { + string time = 1; +} \ No newline at end of file From 9bb6bcef2ce4899f75f20ac40121629f55a04d5f Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Mon, 23 Dec 2024 10:12:26 +0900 Subject: [PATCH 06/15] :sparkles: :: Use setAlarmTimeUseCase --- .../setting/viewmodel/SettingViewModel.kt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt b/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt index 3b745d8..7703325 100644 --- a/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt +++ b/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt @@ -1,12 +1,15 @@ package com.ohnalmwo.setting.viewmodel +import android.util.Log import androidx.lifecycle.viewModelScope import com.ohnalmwo.common.base.BaseViewModel import com.ohnalmwo.common.result.Result import com.ohnalmwo.common.result.asResult import com.ohnalmwo.domain.usecase.location.GetSavedLocationsUseCase +import com.ohnalmwo.domain.usecase.notification.SaveDeviceTokenUseCase import com.ohnalmwo.domain.usecase.setting.GetAlarmStateUseCase import com.ohnalmwo.domain.usecase.setting.SetAlarmStateUseCase +import com.ohnalmwo.domain.usecase.setting.SetAlarmTimeUseCase import com.ohnalmwo.model.enum.Switch import com.ohnalmwo.setting.viewmodel.SettingScreenReducer.* import dagger.hilt.android.lifecycle.HiltViewModel @@ -16,7 +19,8 @@ import javax.inject.Inject @HiltViewModel class SettingViewModel @Inject constructor( private val setAlarmStateUseCase: SetAlarmStateUseCase, - private val getAlarmStateUseCase: GetAlarmStateUseCase + private val getAlarmStateUseCase: GetAlarmStateUseCase, + private val setAlarmTimeUseCase: SetAlarmTimeUseCase ) : BaseViewModel( initialState = SettingState.initial(), reducer = SettingScreenReducer() @@ -37,4 +41,17 @@ class SettingViewModel @Inject constructor( } } } + + fun setAlarmTime(hour: Int, minute: Int, amPm: String) = viewModelScope.launch { + setAlarmTimeUseCase(formatAlarmTime(hour = hour, minute = minute, amPm = amPm)) + sendEvent(SettingEvent.SetAlarmState) + } + + private fun formatAlarmTime(hour: Int, minute: Int, amPm: String): String { + val formattedHour = if (amPm == "PM" && hour < 12) hour + 12 + else if (amPm == "AM" && hour == 12) 0 + else hour + + return "%02d:%02d".format(formattedHour, minute) + } } \ No newline at end of file From 5624ebb38023194734467a069d828f9d09389215 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Mon, 23 Dec 2024 10:21:57 +0900 Subject: [PATCH 07/15] :memo: :: Modify provideNotificationDataStore --- .../src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt index 18aa46a..3966870 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/di/DataStoreModule.kt @@ -53,6 +53,6 @@ object DataStoreModule { DataStoreFactory.create( serializer = notificationTimeSerializer, ) { - context.dataStoreFile("settingInfo.pb") + context.dataStoreFile("notificationTime.pb") } } \ No newline at end of file From 7911c455fe5cf592e51785e7a96d9d5e78de320a Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Mon, 23 Dec 2024 10:23:22 +0900 Subject: [PATCH 08/15] :memo: :: Add set alarm in screen --- .../main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt b/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt index eeebb57..2bdd8de 100644 --- a/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt +++ b/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt @@ -59,9 +59,11 @@ fun SettingAlarmRoute( 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) + } } ) } From d5f6045fc9be83f9c2470e135dd6caf0542b3677 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 17:58:43 +0900 Subject: [PATCH 09/15] :memo: :: Add getAlarmTime data source --- .../datastore/datasource/setting/SettingDataSource.kt | 2 ++ .../datastore/datasource/setting/SettingDataSourceImpl.kt | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt index 9045792..d1ea59d 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSource.kt @@ -10,4 +10,6 @@ interface SettingDataSource { fun getAlarmState(): Flow suspend fun setAlarmTime(alarmTime: String) + + fun getAlarmTime(): Flow } \ No newline at end of file diff --git a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt index b8b0511..b9f4a6e 100644 --- a/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt +++ b/core/datastore/src/main/java/com/ohnalmwo/datastore/datasource/setting/SettingDataSourceImpl.kt @@ -42,4 +42,9 @@ class SettingDataSourceImpl @Inject constructor ( .build() } } + + override fun getAlarmTime(): Flow = + notificationTime.data.map { + it.time ?: "00:00" + } } \ No newline at end of file From 247b4f1451ba1d6066f19466be23e1f4e4c2774a Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 17:58:59 +0900 Subject: [PATCH 10/15] :memo: :: Add getAlarmTime repository --- .../com/ohnalmwo/data/repository/SettingRepositoryImpl.kt | 4 ++++ .../java/com/ohnalmwo/domain/repository/SettingRepository.kt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt b/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt index 5ac1e88..79a2e81 100644 --- a/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt +++ b/core/data/src/main/java/com/ohnalmwo/data/repository/SettingRepositoryImpl.kt @@ -20,4 +20,8 @@ class SettingRepositoryImpl @Inject constructor( override suspend fun setAlarmTime(alarmTime: String) { localSettingDataSource.setAlarmTime(alarmTime = alarmTime) } + + override fun getAlarmTime(): Flow { + return localSettingDataSource.getAlarmTime() + } } \ No newline at end of file diff --git a/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt b/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt index e2f6119..a362206 100644 --- a/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt +++ b/core/domain/src/main/java/com/ohnalmwo/domain/repository/SettingRepository.kt @@ -9,4 +9,6 @@ interface SettingRepository { fun getAlarmState(): Flow suspend fun setAlarmTime(alarmTime: String) + + fun getAlarmTime(): Flow } \ No newline at end of file From 91fe6fe240e2607fe81eabf03eebd2caefb2b17c Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 17:59:27 +0900 Subject: [PATCH 11/15] :memo: :: Add GetAlarmTimeUseCase --- .../domain/usecase/setting/GetAlarmTimeUseCase.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/GetAlarmTimeUseCase.kt diff --git a/core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/GetAlarmTimeUseCase.kt b/core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/GetAlarmTimeUseCase.kt new file mode 100644 index 0000000..e69352a --- /dev/null +++ b/core/domain/src/main/java/com/ohnalmwo/domain/usecase/setting/GetAlarmTimeUseCase.kt @@ -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 = + settingRepository.getAlarmTime() +} \ No newline at end of file From e557d4b0ef23e3494e54b858ea5e3e2069289227 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 18:01:23 +0900 Subject: [PATCH 12/15] :memo: :: Use GetAlarmTimeUseCase --- .../ohnalmwo/setting/SettingAlarmScreen.kt | 1 + .../setting/viewmodel/SettingViewModel.kt | 28 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt b/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt index 2bdd8de..520d396 100644 --- a/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt +++ b/feature/setting/src/main/java/com/ohnalmwo/setting/SettingAlarmScreen.kt @@ -38,6 +38,7 @@ fun SettingAlarmRoute( LaunchedEffect(Unit) { viewModel.getAlarmState() + viewModel.getAlarmTime() } LaunchedEffect(effect) { diff --git a/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt b/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt index 7703325..d954b0e 100644 --- a/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt +++ b/feature/setting/src/main/java/com/ohnalmwo/setting/viewmodel/SettingViewModel.kt @@ -8,6 +8,7 @@ import com.ohnalmwo.common.result.asResult import com.ohnalmwo.domain.usecase.location.GetSavedLocationsUseCase import com.ohnalmwo.domain.usecase.notification.SaveDeviceTokenUseCase import com.ohnalmwo.domain.usecase.setting.GetAlarmStateUseCase +import com.ohnalmwo.domain.usecase.setting.GetAlarmTimeUseCase import com.ohnalmwo.domain.usecase.setting.SetAlarmStateUseCase import com.ohnalmwo.domain.usecase.setting.SetAlarmTimeUseCase import com.ohnalmwo.model.enum.Switch @@ -20,7 +21,8 @@ import javax.inject.Inject class SettingViewModel @Inject constructor( private val setAlarmStateUseCase: SetAlarmStateUseCase, private val getAlarmStateUseCase: GetAlarmStateUseCase, - private val setAlarmTimeUseCase: SetAlarmTimeUseCase + private val setAlarmTimeUseCase: SetAlarmTimeUseCase, + private val getAlarmTimeUseCase: GetAlarmTimeUseCase ) : BaseViewModel( initialState = SettingState.initial(), reducer = SettingScreenReducer() @@ -47,6 +49,18 @@ class SettingViewModel @Inject constructor( sendEvent(SettingEvent.SetAlarmState) } + fun getAlarmTime() = viewModelScope.launch { + getAlarmTimeUseCase() + .asResult() + .collect { result -> + when (result) { + is Result.Loading -> Unit + is Result.Success -> convertTime(result.data) + is Result.Error -> Unit + } + } + } + private fun formatAlarmTime(hour: Int, minute: Int, amPm: String): String { val formattedHour = if (amPm == "PM" && hour < 12) hour + 12 else if (amPm == "AM" && hour == 12) 0 @@ -54,4 +68,16 @@ class SettingViewModel @Inject constructor( return "%02d:%02d".format(formattedHour, minute) } + + private fun convertTime(time: String) { + val parts = time.split(":") + + val hour = parts[0].toInt() + val minute = parts[1].toInt() + + val amPm = if (hour >= 12) "PM" else "AM" + val adjustedHour = if (hour % 12 == 0) 12 else hour % 12 + + sendEvent(SettingEvent.OnChangeAlarmTime(hour = adjustedHour, minute = minute, amPm = amPm)) + } } \ No newline at end of file From f39142b42185f4ca2cbc044f46daf5ce89fbf5e8 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 19:55:17 +0900 Subject: [PATCH 13/15] :memo: :: Add NotificationAPI --- .../com/ohnalmwo/network/api/NotificationAPI.kt | 15 +++++++++++++++ .../java/com/ohnalmwo/network/di/NetworkModule.kt | 6 ++++++ 2 files changed, 21 insertions(+) create mode 100644 core/network/src/main/java/com/ohnalmwo/network/api/NotificationAPI.kt diff --git a/core/network/src/main/java/com/ohnalmwo/network/api/NotificationAPI.kt b/core/network/src/main/java/com/ohnalmwo/network/api/NotificationAPI.kt new file mode 100644 index 0000000..a50ad68 --- /dev/null +++ b/core/network/src/main/java/com/ohnalmwo/network/api/NotificationAPI.kt @@ -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, + ) +} \ No newline at end of file diff --git a/core/network/src/main/java/com/ohnalmwo/network/di/NetworkModule.kt b/core/network/src/main/java/com/ohnalmwo/network/di/NetworkModule.kt index b7d66aa..5550f28 100644 --- a/core/network/src/main/java/com/ohnalmwo/network/di/NetworkModule.kt +++ b/core/network/src/main/java/com/ohnalmwo/network/di/NetworkModule.kt @@ -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 @@ -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) } \ No newline at end of file From 5a4e5776c7d55a6b8525156ce1831689ae238030 Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 19:55:32 +0900 Subject: [PATCH 14/15] :memo: :: Add NotificationDataSource --- .../notification/NotificationDataSource.kt | 8 ++++++++ .../NotificationDataSourceImpl.kt | 19 +++++++++++++++++++ .../network/di/RemoteDataSourceModule.kt | 8 ++++++++ 3 files changed, 35 insertions(+) create mode 100644 core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSource.kt create mode 100644 core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSourceImpl.kt diff --git a/core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSource.kt b/core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSource.kt new file mode 100644 index 0000000..4361bf3 --- /dev/null +++ b/core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSource.kt @@ -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 +} \ No newline at end of file diff --git a/core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSourceImpl.kt b/core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSourceImpl.kt new file mode 100644 index 0000000..1ad3a49 --- /dev/null +++ b/core/network/src/main/java/com/ohnalmwo/network/datasource/notification/NotificationDataSourceImpl.kt @@ -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 = flow { + ApiHandler().request { + notificationAPI.saveDeviceToken(deviceToken = deviceToken, alarmTime = alarmTime) + } + } +} \ No newline at end of file diff --git a/core/network/src/main/java/com/ohnalmwo/network/di/RemoteDataSourceModule.kt b/core/network/src/main/java/com/ohnalmwo/network/di/RemoteDataSourceModule.kt index f3be8dd..c65e0c4 100644 --- a/core/network/src/main/java/com/ohnalmwo/network/di/RemoteDataSourceModule.kt +++ b/core/network/src/main/java/com/ohnalmwo/network/di/RemoteDataSourceModule.kt @@ -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 @@ -24,4 +26,10 @@ abstract class RemoteDataSourceModule { abstract fun bindLocationDataSource( locationDataSourceImpl: LocationDataSourceImpl ): LocationDataSource + + @Binds + @Singleton + abstract fun bindNotificationDataSource( + notificationDataSourceImpl: NotificationDataSourceImpl + ): NotificationDataSource } \ No newline at end of file From c419e517cadca5297c653aeea78e1468131302ce Mon Sep 17 00:00:00 2001 From: GSM-Minseok Date: Tue, 31 Dec 2024 19:55:42 +0900 Subject: [PATCH 15/15] :memo: :: Add NotificationRepository --- .../java/com/ohnalmwo/data/di/RepositoryModule.kt | 9 +++++++++ .../data/repository/NotificationRepositoryImpl.kt | 14 ++++++++++++++ .../domain/repository/NotificationRepository.kt | 7 +++++++ 3 files changed, 30 insertions(+) create mode 100644 core/data/src/main/java/com/ohnalmwo/data/repository/NotificationRepositoryImpl.kt create mode 100644 core/domain/src/main/java/com/ohnalmwo/domain/repository/NotificationRepository.kt diff --git a/core/data/src/main/java/com/ohnalmwo/data/di/RepositoryModule.kt b/core/data/src/main/java/com/ohnalmwo/data/di/RepositoryModule.kt index 4c905b0..f9ed490 100644 --- a/core/data/src/main/java/com/ohnalmwo/data/di/RepositoryModule.kt +++ b/core/data/src/main/java/com/ohnalmwo/data/di/RepositoryModule.kt @@ -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 @@ -32,4 +35,10 @@ abstract class RepositoryModule { abstract fun bindSettingRepository( settingRepositoryImpl: SettingRepositoryImpl ): SettingRepository + + @Binds + @Singleton + abstract fun bindNotificationRepository( + notificationRepositoryImpl: NotificationRepositoryImpl + ): NotificationRepository } \ No newline at end of file diff --git a/core/data/src/main/java/com/ohnalmwo/data/repository/NotificationRepositoryImpl.kt b/core/data/src/main/java/com/ohnalmwo/data/repository/NotificationRepositoryImpl.kt new file mode 100644 index 0000000..8ea434f --- /dev/null +++ b/core/data/src/main/java/com/ohnalmwo/data/repository/NotificationRepositoryImpl.kt @@ -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 { + return notificationDataSource.saveDeviceToken(deviceToken = deviceToken, alarmTime = alarmTime) + } +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/ohnalmwo/domain/repository/NotificationRepository.kt b/core/domain/src/main/java/com/ohnalmwo/domain/repository/NotificationRepository.kt new file mode 100644 index 0000000..c5dc191 --- /dev/null +++ b/core/domain/src/main/java/com/ohnalmwo/domain/repository/NotificationRepository.kt @@ -0,0 +1,7 @@ +package com.ohnalmwo.domain.repository + +import kotlinx.coroutines.flow.Flow + +interface NotificationRepository { + suspend fun saveDeviceToken(deviceToken: String, alarmTime: String): Flow +}