Skip to content

Commit

Permalink
Merge pull request #120 from TimerTiTi/82-setting
Browse files Browse the repository at this point in the history
close #82 setting
  • Loading branch information
koreatlwls authored May 5, 2024
2 parents 27f8e25 + 2f4bc36 commit 3a7a891
Show file tree
Hide file tree
Showing 48 changed files with 1,440 additions and 28 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ dependencies {
implementation(project(":data:sleep:impl"))
implementation(project(":data:alarm:impl"))
implementation(project(":data:graph:impl"))
implementation(project(":data:notification:impl"))

implementation(platform(libs.firebase.bom))
implementation(libs.firebase.analytics)
Expand Down
5 changes: 4 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,7 @@
-keepclassmembers class * {
@com.squareup.moshi.FromJson <methods>;
@com.squareup.moshi.ToJson <methods>;
}
}

-keepattributes Signature
-keepclassmembers class com.titi.app.feature.setting.model.** {*;}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
android:label="${appName}"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.TiTi"
tools:targetApi="31">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ data class TdsColorsPalette(
val textColor: Color = Color.Unspecified,
val backgroundColor: Color = Color.Unspecified,
val secondaryBackgroundColor: Color = Color.Unspecified,
val groupedBackgroundColor: Color = Color.Unspecified,
val switchBackgroundColor: Color = Color.Unspecified,
val alertBackgroundColor: Color = Color.Unspecified,
val tertiaryBackgroundColor: Color = Color.Unspecified,
Expand Down Expand Up @@ -52,7 +53,8 @@ val TdsLightColorsPalette = TdsColorsPalette(
d12 = Color(0xFF928AEA),
textColor = Color(0xFF000000),
backgroundColor = Color(0xFFFFFFFF),
secondaryBackgroundColor = Color(0xFFF2F2F7),
secondaryBackgroundColor = Color(0xFFFFFFFF),
groupedBackgroundColor = Color(0xFFF2F2F7),
switchBackgroundColor = Color(0xFFE9E9EB),
alertBackgroundColor = Color(0xD1EEEEEE),
tertiaryBackgroundColor = Color(0xFFFFFFFF),
Expand Down Expand Up @@ -85,6 +87,7 @@ val TdsDarkColorsPalette = TdsColorsPalette(
textColor = Color(0xFFFFFFFF),
backgroundColor = Color(0xFF000000),
secondaryBackgroundColor = Color(0xFF1C1C1E),
groupedBackgroundColor = Color(0xFF000000),
switchBackgroundColor = Color(0xFF39393D),
alertBackgroundColor = Color(0xD12B2B2B),
tertiaryBackgroundColor = Color(0xFF2C2C2E),
Expand Down Expand Up @@ -118,6 +121,7 @@ enum class TdsColor {
TEXT,
BACKGROUND,
SECONDARY_BACKGROUND,
GROUPED_BACKGROUND,
SWITCH_BACKGROUND,
ALERT_BACKGROUND,
TERTIARY_BACKGROUND,
Expand Down Expand Up @@ -154,6 +158,7 @@ enum class TdsColor {
TEXT -> TiTiTheme.colors.textColor
BACKGROUND -> TiTiTheme.colors.backgroundColor
SECONDARY_BACKGROUND -> TiTiTheme.colors.secondaryBackgroundColor
GROUPED_BACKGROUND -> TiTiTheme.colors.groupedBackgroundColor
SWITCH_BACKGROUND -> TiTiTheme.colors.switchBackgroundColor
ALERT_BACKGROUND -> TiTiTheme.colors.alertBackgroundColor
TERTIARY_BACKGROUND -> TiTiTheme.colors.tertiaryBackgroundColor
Expand Down
1 change: 1 addition & 0 deletions core/designsystem/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<string name="bottom_timer_text">Timer</string>
<string name="bottom_stopwatch_text">Stopwatch</string>
<string name="bottom_log_text">Log</string>
<string name="bottom_setting_text">Setting</string>

<string name="sum_time" translatable="false">누적 시간</string>
<string name="timer" translatable="false">타이머</string>
Expand Down
7 changes: 7 additions & 0 deletions data/notification/api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
plugins {
id("titi.android.library-no-hilt")
}

android {
namespace = "com.titi.app.data.notification.api"
}
4 changes: 4 additions & 0 deletions data/notification/api/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.titi.app.data.notification.api

import com.titi.app.data.notification.api.model.NotificationRepositoryModel
import kotlinx.coroutines.flow.Flow

interface NotificationRepository {
suspend fun setNotification(notificationRepositoryModel: NotificationRepositoryModel)

fun getNotificationFlow(): Flow<NotificationRepositoryModel>

suspend fun getNotification(): NotificationRepositoryModel
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.titi.app.data.notification.api.model

data class NotificationRepositoryModel(
val timerFiveMinutesBeforeTheEnd: Boolean = true,
val timerBeforeTheEnd: Boolean = true,
val stopwatch: Boolean = true,
)
11 changes: 11 additions & 0 deletions data/notification/impl/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
id("titi.android.data.local")
}

android {
namespace = "com.titi.app.data.notification.impl"
}

dependencies {
implementation(project(":data:notification:api"))
}
4 changes: 4 additions & 0 deletions data/notification/impl/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.titi.app.data.notification.impl.di

import android.content.Context
import com.titi.app.data.notification.impl.local.NotificationDataStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
internal object DataStoreModule {
@Provides
@Singleton
fun provideNotificationDataStore(@ApplicationContext context: Context) =
NotificationDataStore(context)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.titi.app.data.notification.impl.di

import com.titi.app.data.notification.api.NotificationRepository
import com.titi.app.data.notification.impl.repository.NotificationRepositoryImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
internal interface RepositoryModule {
@Binds
@Singleton
fun provideNotificationRepository(
notificationRepositoryImpl: NotificationRepositoryImpl,
): NotificationRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.titi.app.data.notification.impl.local

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.titi.app.core.util.fromJson
import com.titi.app.core.util.readFlowValue
import com.titi.app.core.util.readValue
import com.titi.app.core.util.storeValue
import com.titi.app.core.util.toJson
import com.titi.app.data.notification.impl.local.model.NotificationEntity
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

internal class NotificationDataStore(context: Context) {
private val dataStore: DataStore<Preferences> = context.dataStore

suspend fun setNotification(notificationEntity: NotificationEntity) {
dataStore.storeValue(NOTIFICATION_KEY, notificationEntity.toJson())
}

fun getNotificationFlow(): Flow<NotificationEntity?> =
dataStore.readFlowValue(NOTIFICATION_KEY).map { it?.fromJson() }

suspend fun getNotification(): NotificationEntity? =
dataStore.readValue(NOTIFICATION_KEY)?.fromJson()

companion object {
private const val NOTIFICATION_PREF_NAME = "notificationPrefName"
private val NOTIFICATION_KEY = stringPreferencesKey("notificationKey")

private val Context.dataStore: DataStore<Preferences>
by preferencesDataStore(NOTIFICATION_PREF_NAME)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.titi.app.data.notification.impl.local.model

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
internal data class NotificationEntity(
val timerFiveMinutesBeforeTheEnd: Boolean,
val timerBeforeTheEnd: Boolean,
val stopwatch: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.titi.app.data.notification.impl.mapper

import com.titi.app.data.notification.api.model.NotificationRepositoryModel
import com.titi.app.data.notification.impl.local.model.NotificationEntity

internal fun NotificationEntity.toRepositoryModel() = NotificationRepositoryModel(
timerFiveMinutesBeforeTheEnd = timerFiveMinutesBeforeTheEnd,
timerBeforeTheEnd = timerBeforeTheEnd,
stopwatch = stopwatch,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.titi.app.data.notification.impl.mapper

import com.titi.app.data.notification.api.model.NotificationRepositoryModel
import com.titi.app.data.notification.impl.local.model.NotificationEntity

internal fun NotificationRepositoryModel.toLocalModel() = NotificationEntity(
timerFiveMinutesBeforeTheEnd = timerFiveMinutesBeforeTheEnd,
timerBeforeTheEnd = timerBeforeTheEnd,
stopwatch = stopwatch,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.titi.app.data.notification.impl.repository

import com.titi.app.data.notification.api.NotificationRepository
import com.titi.app.data.notification.api.model.NotificationRepositoryModel
import com.titi.app.data.notification.impl.local.NotificationDataStore
import com.titi.app.data.notification.impl.mapper.toLocalModel
import com.titi.app.data.notification.impl.mapper.toRepositoryModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

internal class NotificationRepositoryImpl @Inject constructor(
private val notificationDataStore: NotificationDataStore,
) : NotificationRepository {
override suspend fun setNotification(notificationRepositoryModel: NotificationRepositoryModel) {
notificationDataStore.setNotification(notificationRepositoryModel.toLocalModel())
}

override fun getNotificationFlow(): Flow<NotificationRepositoryModel> =
notificationDataStore.getNotificationFlow()
.map { it?.toRepositoryModel() ?: NotificationRepositoryModel() }

override suspend fun getNotification(): NotificationRepositoryModel {
return notificationDataStore.getNotification()?.toRepositoryModel()
?: NotificationRepositoryModel()
}
}
1 change: 1 addition & 0 deletions domain/alarm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ android {

dependencies {
implementation(project(":data:alarm:api"))
implementation(project(":data:notification:api"))

implementation(libs.threetenabp)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.titi.app.domain.alarm.usecase

import com.titi.app.data.alarm.api.AlarmRepository
import com.titi.app.data.notification.api.NotificationRepository
import com.titi.app.domain.alarm.mapper.toRepositoryModel
import com.titi.app.domain.alarm.model.Alarm
import com.titi.app.domain.alarm.model.Alarms
Expand All @@ -9,29 +10,33 @@ import org.threeten.bp.ZonedDateTime

class SetStopWatchAlarmUseCase @Inject constructor(
private val alarmRepository: AlarmRepository,
private val notificationRepository: NotificationRepository,
) {
suspend operator fun invoke(title: String, finishMessage: String, measureTime: Long) {
alarmRepository.cancelAlarms()

val now = ZonedDateTime.now()
val finishTimeRange = (measureTime / ONE_HOUR_SECONDS) + 1..TWENTY_FOUR_HOURS
val alarms =
Alarms(
alarms = finishTimeRange.map {
Alarm(
title = title,
message = "$it$finishMessage",
finishTime = now.plusSeconds(
it * ONE_HOUR_SECONDS - measureTime,
).toString(),
)
},
)
val alarms = Alarms(
alarms = finishTimeRange.map {
Alarm(
title = title,
message = "$it$finishMessage",
finishTime = now.plusSeconds(
it * ONE_HOUR_SECONDS - measureTime,
).toString(),
)
},
)

if (alarmRepository.canScheduleExactAlarms()) {
alarmRepository.setExactAlarms(alarms.toRepositoryModel())
} else {
alarmRepository.addExactAlarms(alarms.toRepositoryModel())
val notification = notificationRepository.getNotification()

if (notification.stopwatch) {
if (alarmRepository.canScheduleExactAlarms()) {
alarmRepository.setExactAlarms(alarms.toRepositoryModel())
} else {
alarmRepository.addExactAlarms(alarms.toRepositoryModel())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.titi.app.domain.alarm.usecase

import com.titi.app.data.alarm.api.AlarmRepository
import com.titi.app.data.notification.api.NotificationRepository
import com.titi.app.domain.alarm.mapper.toRepositoryModel
import com.titi.app.domain.alarm.model.Alarm
import com.titi.app.domain.alarm.model.Alarms
Expand All @@ -9,6 +10,7 @@ import org.threeten.bp.ZonedDateTime

class SetTimerAlarmUseCase @Inject constructor(
private val alarmRepository: AlarmRepository,
private val notificationRepository: NotificationRepository,
) {
suspend operator fun invoke(
title: String,
Expand All @@ -26,17 +28,23 @@ class SetTimerAlarmUseCase @Inject constructor(
null
}

val notification = notificationRepository.getNotification()
val alarms = Alarms(
alarms = mutableListOf<Alarm>().apply {
add(
Alarm(
title = title,
message = finishMessage,
finishTime = finishTime,
),
)
if (notification.timerBeforeTheEnd) {
add(
Alarm(
title = title,
message = finishMessage,
finishTime = finishTime,
),
)
}

if (fiveMinutesBeforeFinishTime != null) {
if (
fiveMinutesBeforeFinishTime != null &&
notification.timerFiveMinutesBeforeTheEnd
) {
add(
Alarm(
title = title,
Expand Down
2 changes: 2 additions & 0 deletions feature/main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ dependencies {
implementation(project(":feature:time"))
implementation(project(":feature:log"))
implementation(project(":feature:popup"))
implementation(project(":feature:setting"))
implementation(project(":feature:webview"))

implementation(libs.androidx.splashscreen)
implementation(libs.androidx.material3.window.size)
Expand Down
Loading

0 comments on commit 3a7a891

Please sign in to comment.