diff --git a/.idea/ChatHistory_schema_v2.xml b/.idea/ChatHistory_schema_v2.xml
index 7fda096..58efa3a 100644
--- a/.idea/ChatHistory_schema_v2.xml
+++ b/.idea/ChatHistory_schema_v2.xml
@@ -4,7 +4,7 @@
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 88ea3aa..c4f31a7 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,5 +1,40 @@
+
+
+
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index c113d21..91161d9 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 0007cff..fe812ac 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -2,7 +2,6 @@ plugins {
alias(libs.plugins.android.gradle)
id("kotlin-android")
alias(libs.plugins.serialization)
- id("dagger.hilt.android.plugin")
id("org.jetbrains.kotlin.plugin.parcelize")
alias(libs.plugins.google.services)
alias(libs.plugins.crashlytics.gradle)
@@ -91,8 +90,6 @@ dependencies {
testImplementation(libs.coroutines.test)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.androidx.test.espresso.core)
- androidTestImplementation(libs.hilt.android.testing)
- kspAndroidTest(libs.hilt.android.compiler)
testImplementation(libs.mockk)
implementation(libs.androidx.room.runtime)
@@ -105,12 +102,6 @@ dependencies {
implementation(libs.coroutines.android)
implementation(libs.androidx.activity.compose)
- implementation(libs.androidx.hilt.navigation.compose)
-
- implementation(libs.timber)
-
- implementation(libs.hilt.android)
- ksp(libs.hilt.android.compiler)
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.analytics)
@@ -143,4 +134,14 @@ dependencies {
implementation(libs.lyricist)
ksp(libs.lyricist.processor)
+
+ val koinBom = platform(libs.koin.bom)
+ implementation(koinBom)
+ implementation(libs.koin.core)
+ implementation(libs.koin.android)
+ implementation(libs.koin.compose)
+ implementation(libs.koin.compose.viewmodel)
+
+ implementation(libs.kermit)
+ implementation(libs.kermit.crashlytics)
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/AlarmReceiver.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/AlarmReceiver.kt
index c0bd56c..ef21413 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/AlarmReceiver.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/AlarmReceiver.kt
@@ -7,24 +7,23 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.PowerManager
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.framework.Usecases
-import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
-import timber.log.Timber
-import javax.inject.Inject
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
/**
* [BroadcastReceiver] to be notified by the [android.app.AlarmManager].
*/
-@AndroidEntryPoint
-class AlarmReceiver : BroadcastReceiver() {
- @Inject lateinit var usecases: Usecases
+class AlarmReceiver : BroadcastReceiver(), KoinComponent {
+ val usecases: Usecases by inject()
@OptIn(DelicateCoroutinesApi::class)
override fun onReceive(context: Context, intent: Intent) {
- Timber.d("onReceive() - intent ${intent.action}")
+ Logger.d("onReceive() - intent ${intent.action}")
if (intent.action == ALARM_ACTION) {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
@@ -48,12 +47,12 @@ class AlarmReceiver : BroadcastReceiver() {
"android.intent.action.QUICKBOOT_POWERON",
"android.intent.action.MY_PACKAGE_REPLACED",
AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED -> {
- Timber.d("Reboot Reboot!!")
+ Logger.d("Reboot Reboot!!")
usecases.rescheduleFutureAlarms()
}
else -> {
- Timber.e("action: ${intent?.action}")
- Timber.e("Action not supported")
+ Logger.e("action: ${intent?.action}")
+ Logger.e("Action not supported")
}
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/AlarmApplication.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/AlarmApplication.kt
index 579ee58..6f5fdba 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/AlarmApplication.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/AlarmApplication.kt
@@ -1,15 +1,27 @@
package com.timilehinaregbesola.mathalarm.framework.app
import android.app.Application
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.ui.ExperimentalComposeUiApi
+import co.touchlab.kermit.Logger
import com.google.firebase.messaging.FirebaseMessaging
-import dagger.hilt.android.HiltAndroidApp
-import timber.log.Timber
+import com.timilehinaregbesola.mathalarm.framework.app.di.appModule
+import kotlinx.coroutines.InternalCoroutinesApi
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
-@HiltAndroidApp
class AlarmApplication : Application() {
+ @OptIn(ExperimentalAnimationApi::class, ExperimentalComposeUiApi::class,
+ ExperimentalFoundationApi::class, InternalCoroutinesApi::class
+ )
override fun onCreate() {
super.onCreate()
- Timber.plant(Timber.DebugTree())
+ startKoin {
+ androidContext(this@AlarmApplication)
+ modules(appModule)
+ }
+ Logger.setTag("MathAlarm")
FirebaseMessaging.getInstance().subscribeToTopic("all")
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/di/AppModule.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/di/AppModule.kt
index 449fad1..cefd92b 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/di/AppModule.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/framework/app/di/AppModule.kt
@@ -1,19 +1,22 @@
package com.timilehinaregbesola.mathalarm.framework.app.di
-import android.app.Application
-import android.content.Context
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.room.Room
+import co.touchlab.kermit.ExperimentalKermitApi
+import co.touchlab.kermit.Logger
+import co.touchlab.kermit.StaticConfig
+import co.touchlab.kermit.crashlytics.CrashlyticsLogWriter
+import co.touchlab.kermit.platformLogWriter
+import com.timilehinaregbesola.mathalarm.data.AlarmDataSource
import com.timilehinaregbesola.mathalarm.data.AlarmRepository
import com.timilehinaregbesola.mathalarm.framework.RoomAlarmDataSource
import com.timilehinaregbesola.mathalarm.framework.Usecases
import com.timilehinaregbesola.mathalarm.framework.app.permission.AlarmPermission
import com.timilehinaregbesola.mathalarm.framework.app.permission.AndroidVersion
import com.timilehinaregbesola.mathalarm.framework.app.permission.AndroidVersionImpl
-import com.timilehinaregbesola.mathalarm.framework.database.AlarmDao
import com.timilehinaregbesola.mathalarm.framework.database.AlarmDatabase
import com.timilehinaregbesola.mathalarm.framework.database.AlarmMapper
import com.timilehinaregbesola.mathalarm.framework.database.MIGRATION_2_3
@@ -27,6 +30,10 @@ import com.timilehinaregbesola.mathalarm.interactors.PlayerWrapper
import com.timilehinaregbesola.mathalarm.notification.AlarmNotificationScheduler
import com.timilehinaregbesola.mathalarm.notification.MathAlarmNotification
import com.timilehinaregbesola.mathalarm.notification.MathAlarmNotificationChannel
+import com.timilehinaregbesola.mathalarm.presentation.alarmlist.AlarmListViewModel
+import com.timilehinaregbesola.mathalarm.presentation.alarmmath.AlarmMathViewModel
+import com.timilehinaregbesola.mathalarm.presentation.alarmsettings.AlarmSettingsViewModel
+import com.timilehinaregbesola.mathalarm.presentation.appsettings.AlarmPreferencesImpl
import com.timilehinaregbesola.mathalarm.presentation.appsettings.AppThemeOptionsMapper
import com.timilehinaregbesola.mathalarm.provider.DateTimeProvider
import com.timilehinaregbesola.mathalarm.provider.DateTimeProviderImpl
@@ -44,155 +51,121 @@ import com.timilehinaregbesola.mathalarm.usecases.ShowAlarm
import com.timilehinaregbesola.mathalarm.usecases.SnoozeAlarm
import com.timilehinaregbesola.mathalarm.usecases.UpdateAlarm
import com.timilehinaregbesola.mathalarm.utils.getAlarmManager
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.qualifiers.ApplicationContext
-import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.InternalCoroutinesApi
-import javax.inject.Singleton
-
+import org.koin.android.ext.koin.androidApplication
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.module.dsl.viewModel
+import org.koin.core.parameter.parametersOf
+import org.koin.core.scope.Scope
+import org.koin.dsl.module
+
+@OptIn(ExperimentalKermitApi::class)
@ExperimentalFoundationApi
@ExperimentalComposeUiApi
@InternalCoroutinesApi
@ExperimentalAnimationApi
-@Module
-@InstallIn(SingletonComponent::class)
-object AppModule {
- @Provides
- @Singleton
- fun provideNoteDatabase(app: Application): AlarmDatabase {
- return Room.databaseBuilder(
- app,
+val appModule = module {
+ single {
+ Room.databaseBuilder(
+ androidApplication(),
AlarmDatabase::class.java,
"alarm_history_database"
).addMigrations(MIGRATION_2_3, MIGRATION_3_4).build()
}
- @Provides
- @Singleton
- fun provideAlarmDao(database: AlarmDatabase): AlarmDao {
- return database.alarmDatabaseDao
- }
+ single { get().alarmDatabaseDao }
- @Provides
- @Singleton
- fun provideAlarmMapper(): AlarmMapper {
- return AlarmMapper()
- }
+ single { AlarmMapper() }
- @Provides
- @Singleton
- fun provideThemeMapper(): AppThemeOptionsMapper {
- return AppThemeOptionsMapper()
- }
+ single { AppThemeOptionsMapper() }
- @Provides
- @Singleton
- fun provideCalenderProvider(): DateTimeProvider {
- return DateTimeProviderImpl()
- }
+ single { DateTimeProviderImpl() }
- @Provides
- @Singleton
- fun provideScheduleNextAlarm(interactor: AlarmInteractor): ScheduleNextAlarm {
- return ScheduleNextAlarm(interactor)
- }
+ single { ScheduleNextAlarm(get()) }
- @Provides
- @Singleton
- fun provideDataSource(alarmDao: AlarmDao, mapper: AlarmMapper): RoomAlarmDataSource {
- return RoomAlarmDataSource(alarmDao, mapper)
- }
+ single { RoomAlarmDataSource(get(), get()) }
- @Provides
- @Singleton
- fun provideRepository(alarmDataSource: RoomAlarmDataSource): AlarmRepository {
- return AlarmRepository(alarmDataSource)
- }
+ single { AlarmRepository(get()) }
- @Provides
- @Singleton
- fun provideAlarmInteractor(alarmManager: AlarmNotificationScheduler): AlarmInteractor {
- return AlarmInteractorImpl(alarmManager)
- }
+ single { AlarmInteractorImpl(get(), getWith("AlarmInteractorImpl")) }
- @Provides
- @Singleton
- fun provideInteractors(
- repository: AlarmRepository,
- alarmInteractor: AlarmInteractor,
- notificationInteractor: NotificationInteractor,
- calendarProvider: DateTimeProvider,
- scheduleNextAlarm: ScheduleNextAlarm
- ): Usecases {
- return Usecases(
- addAlarm = AddAlarm(repository),
- clearAlarms = ClearAlarms(repository, alarmInteractor),
- deleteAlarm = DeleteAlarm(repository, alarmInteractor),
- findAlarm = FindAlarm(repository),
- getSavedAlarms = GetSavedAlarms(repository),
- updateAlarm = UpdateAlarm(repository),
- scheduleAlarm = ScheduleAlarm(repository, alarmInteractor),
- completeAlarm = CompleteAlarm(repository, alarmInteractor, notificationInteractor),
- rescheduleFutureAlarms = RescheduleFutureAlarms(repository, alarmInteractor),
- scheduleNextAlarm = ScheduleNextAlarm(alarmInteractor),
- showAlarm = ShowAlarm(repository, notificationInteractor, scheduleNextAlarm),
- snoozeAlarm = SnoozeAlarm(calendarProvider, notificationInteractor, alarmInteractor, repository),
- cancelAlarm = CancelAlarm(alarmInteractor)
+ single {
+ Usecases(
+ addAlarm = AddAlarm(get()),
+ clearAlarms = ClearAlarms(get(), get()),
+ deleteAlarm = DeleteAlarm(get(), get()),
+ findAlarm = FindAlarm(get()),
+ getSavedAlarms = GetSavedAlarms(get()),
+ updateAlarm = UpdateAlarm(get()),
+ scheduleAlarm = ScheduleAlarm(get(), get()),
+ completeAlarm = CompleteAlarm(get(), get(), get()),
+ rescheduleFutureAlarms = RescheduleFutureAlarms(get(), get()),
+ scheduleNextAlarm = get(),
+ showAlarm = ShowAlarm(get(), get(), get()),
+ snoozeAlarm = SnoozeAlarm(get(), get(), get(), get()),
+ cancelAlarm = CancelAlarm(get())
)
}
@OptIn(ExperimentalMaterial3Api::class)
- @Provides
- @Singleton
- fun provideAlarmNotification(
- @ApplicationContext context: Context,
- channel: MathAlarmNotificationChannel,
- player: AudioPlayer
- ): MathAlarmNotification {
- return MathAlarmNotification(context, channel, player)
+ single {
+ MathAlarmNotification(
+ androidContext(),
+ get(),
+ get(),
+ getWith("MathAlarmNotification")
+ )
}
- @Provides
- @Singleton
- fun provideAudioPlayer(@ApplicationContext context: Context): AudioPlayer {
- return PlayerWrapper(context)
- }
+ single { PlayerWrapper(androidContext(), getWith("PlayerWrapper")) }
+
+ single { MathAlarmNotificationChannel(androidContext()) }
- @Provides
- @Singleton
- fun provideAlarmNotificationChannel(@ApplicationContext context: Context): MathAlarmNotificationChannel {
- return MathAlarmNotificationChannel(context)
+ single {
+ AlarmPreferencesImpl(
+ androidContext(),
+ AppThemeOptionsMapper(),
+ getWith("AlarmPreferencesImpl")
+ )
}
@OptIn(
ExperimentalAnimationApi::class,
InternalCoroutinesApi::class,
ExperimentalComposeUiApi::class,
- ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class
+ ExperimentalFoundationApi::class,
+ ExperimentalMaterial3Api::class
)
- @Provides
- @Singleton
- fun provideNotificationInteractor(alarmNotification: MathAlarmNotification): NotificationInteractor {
- return NotificationInteractorImpl(alarmNotification)
+ single {
+ NotificationInteractorImpl(
+ get(),
+ getWith("NotificationInteractorImpl")
+ )
}
- @Provides
- @Singleton
- fun provideNotificationScheduler(@ApplicationContext context: Context): AlarmNotificationScheduler {
- return AlarmNotificationScheduler(context)
- }
+ single { AlarmNotificationScheduler(androidContext(), getWith("AlarmNotificationScheduler")) }
- @Provides
- @Singleton
- fun provideAndroidVersion(): AndroidVersion {
- return AndroidVersionImpl()
+ single { AndroidVersionImpl() }
+
+ single {
+ AlarmPermission(androidContext().getAlarmManager(), get())
}
- @Provides
- @Singleton
- fun provideAlarmPermission(@ApplicationContext context: Context, version: AndroidVersion): AlarmPermission {
- return AlarmPermission(context.getAlarmManager(), version)
+ single { (tag: String) ->
+ Logger(
+ StaticConfig(
+ logWriterList = listOf(
+ platformLogWriter(),
+ CrashlyticsLogWriter()
+ )
+ ), tag
+ )
}
+
+ viewModel { AlarmListViewModel(get(), get(), getWith("AlarmListViewModel")) }
+ viewModel { AlarmSettingsViewModel(get()) }
+ viewModel { AlarmMathViewModel(get(), get(), getWith("AlarmMathViewModel")) }
}
+
+internal inline fun Scope.getWith(vararg params: Any?): T =
+ get(parameters = { parametersOf(*params) })
\ No newline at end of file
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AlarmInteractorImpl.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AlarmInteractorImpl.kt
index cf3b3a3..98b91dc 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AlarmInteractorImpl.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AlarmInteractorImpl.kt
@@ -1,22 +1,28 @@
package com.timilehinaregbesola.mathalarm.interactors
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.domain.model.Alarm
import com.timilehinaregbesola.mathalarm.notification.AlarmNotificationScheduler
-import timber.log.Timber
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
+import org.koin.core.parameter.parametersOf
-class AlarmInteractorImpl(private val alarmManager: AlarmNotificationScheduler) :
- AlarmInteractor {
+class AlarmInteractorImpl(
+ private val alarmManager: AlarmNotificationScheduler,
+ private val logger: Logger
+) :
+ AlarmInteractor, KoinComponent {
override fun schedule(alarm: Alarm, reschedule: Boolean): Boolean {
- Timber.d("AlarmInteractorImpl.schedule called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}, reschedule=$reschedule")
+ logger.d("AlarmInteractorImpl.schedule called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}, reschedule=$reschedule")
val result = alarmManager.scheduleAlarm(alarm, reschedule)
- Timber.d("AlarmInteractorImpl.schedule result for alarmId=${alarm.alarmId}: $result")
+ logger.d("AlarmInteractorImpl.schedule result for alarmId=${alarm.alarmId}: $result")
return result
}
override fun cancel(alarm: Alarm) {
- Timber.d("AlarmInteractorImpl.cancel called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}")
+ logger.d("AlarmInteractorImpl.cancel called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}")
alarmManager.cancelAlarm(alarm)
- Timber.d("AlarmInteractorImpl.cancel completed for alarmId=${alarm.alarmId}")
+ logger.d("AlarmInteractorImpl.cancel completed for alarmId=${alarm.alarmId}")
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AudioPlayer.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AudioPlayer.kt
index ed06b78..fcdbc03 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AudioPlayer.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/AudioPlayer.kt
@@ -4,7 +4,7 @@ import android.content.Context
import android.media.AudioAttributes
import android.media.MediaPlayer
import android.net.Uri
-import timber.log.Timber
+import co.touchlab.kermit.Logger
interface AudioPlayer {
@@ -29,6 +29,7 @@ interface AudioPlayer {
class PlayerWrapper(
// val resources: Resources,
val context: Context,
+ private val logger: Logger
) : AudioPlayer {
override fun setDataSource(alarmtone: Uri) {
// Fall back on the default alarm if the database does not have an
@@ -46,7 +47,7 @@ class PlayerWrapper(
override fun init() {
player = MediaPlayer().apply {
setOnErrorListener { mp, _, _ ->
- Timber.e("Error occurred while playing audio.")
+ logger.e("Error occurred while playing audio.")
mp.stop()
mp.release()
player = null
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/NotificationInteractorImpl.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/NotificationInteractorImpl.kt
index 20253e8..530d8de 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/NotificationInteractorImpl.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/interactors/NotificationInteractorImpl.kt
@@ -4,10 +4,10 @@ import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.ExperimentalComposeUiApi
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.domain.model.Alarm
import com.timilehinaregbesola.mathalarm.notification.MathAlarmNotification
import kotlinx.coroutines.InternalCoroutinesApi
-import timber.log.Timber
@ExperimentalFoundationApi
@ExperimentalMaterial3Api
@@ -16,10 +16,11 @@ import timber.log.Timber
@ExperimentalAnimationApi
internal class NotificationInteractorImpl(
private val alarmNotification: MathAlarmNotification,
+ private val logger: Logger
) : NotificationInteractor {
override fun show(alarm: Alarm) {
- Timber.d("show - alarmId = ${alarm.alarmId}")
+ logger.d("show - alarmId = ${alarm.alarmId}")
if (alarm.repeat) {
alarmNotification.showRepeating(alarm)
} else {
@@ -28,7 +29,7 @@ internal class NotificationInteractorImpl(
}
override fun dismiss(notificationId: Long) {
- Timber.d("dismiss - alarmId = $notificationId")
+ logger.d("dismiss - alarmId = $notificationId")
alarmNotification.dismiss(notificationId)
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/AlarmNotificationScheduler.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/AlarmNotificationScheduler.kt
index 08c705b..a120199 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/AlarmNotificationScheduler.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/AlarmNotificationScheduler.kt
@@ -7,6 +7,7 @@ import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.Intent
import android.os.Build
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.AlarmReceiver
import com.timilehinaregbesola.mathalarm.AlarmReceiver.Companion.ALARM_ACTION
import com.timilehinaregbesola.mathalarm.AlarmReceiver.Companion.EXTRA_TASK
@@ -26,7 +27,6 @@ import kotlinx.datetime.TimeZone
import kotlinx.datetime.plus
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
-import timber.log.Timber
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
import kotlin.time.Instant
@@ -34,7 +34,7 @@ import kotlin.time.Instant
/**
* Alarm manager to schedule an event based on the time from a Alarm.
*/
-class AlarmNotificationScheduler(private val context: Context) {
+class AlarmNotificationScheduler(private val context: Context, private val logger: Logger) {
/**
* Schedules all the alarm of the object at once including repeating ones
@@ -45,7 +45,7 @@ class AlarmNotificationScheduler(private val context: Context) {
@OptIn(ExperimentalTime::class)
@SuppressLint("UnspecifiedImmutableFlag")
fun scheduleAlarm(passedAlarm: Alarm, reschedule: Boolean): Boolean {
- Timber.d("Schedule alarm for id=${passedAlarm.alarmId}, time=${passedAlarm.hour}:${passedAlarm.minute}, repeat=${passedAlarm.repeat}, repeatDays=${passedAlarm.repeatDays}, reschedule=$reschedule")
+ logger.d("Schedule alarm for id=${passedAlarm.alarmId}, time=${passedAlarm.hour}:${passedAlarm.minute}, repeat=${passedAlarm.repeat}, repeatDays=${passedAlarm.repeatDays}, reschedule=$reschedule")
val alarmIntent = Intent(context, AlarmReceiver::class.java).apply {
action = ALARM_ACTION
putExtra(EXTRA_TASK, passedAlarm.alarmId)
@@ -57,20 +57,20 @@ class AlarmNotificationScheduler(private val context: Context) {
// If there is no day set, set the alarm on the closest possible date
if (passedAlarm.repeatDays == "FFFFFFF") {
- Timber.d("No repeat days set, determining closest possible date")
+ logger.d("No repeat days set, determining closest possible date")
val dateTime = passedAlarm.initLocalDateTimeInSystemZone()
val instant = dateTime.toInstant(tz)
val nowInstant = Clock.System.now()
- Timber.d("Alarm datetime: $dateTime, instant: $instant, now: $nowInstant")
+ logger.d("Alarm datetime: $dateTime, instant: $instant, now: $nowInstant")
var dayOfTheWeek = dateTime.date.dayOfWeek.toIndex()
- Timber.d("Current day of week: $dayOfTheWeek")
+ logger.d("Current day of week: $dayOfTheWeek")
if (instant > nowInstant) { // set it today
val sb = StringBuilder("FFFFFFF")
sb.setCharAt(dayOfTheWeek, 'T')
passedAlarm.repeatDays = sb.toString()
- Timber.d("Alarm time is in the future, setting for today. New repeatDays: ${passedAlarm.repeatDays}")
+ logger.d("Alarm time is in the future, setting for today. New repeatDays: ${passedAlarm.repeatDays}")
} else { // alarm time already passed for the day so set it tomorrow
val sb = StringBuilder("FFFFFFF")
if (dayOfTheWeek == SAT) { // if it is saturday
@@ -80,31 +80,31 @@ class AlarmNotificationScheduler(private val context: Context) {
}
sb.setCharAt(dayOfTheWeek, 'T')
passedAlarm.repeatDays = sb.toString()
- Timber.d("Alarm time already passed, setting for tomorrow (day $dayOfTheWeek). New repeatDays: ${passedAlarm.repeatDays}")
+ logger.d("Alarm time already passed, setting for tomorrow (day $dayOfTheWeek). New repeatDays: ${passedAlarm.repeatDays}")
}
}
for (i in SUN..SAT) {
if (passedAlarm.repeatDays[i] == 'T') {
- Timber.d("Processing day $i (${fullDays[i]}) which is set to true")
+ logger.d("Processing day $i (${fullDays[i]}) which is set to true")
val nowInstant = Clock.System.now()
val localNow = nowInstant.toLocalDateTime(tz)
val todayDate = localNow.date
val currentDay = todayDate.dayOfWeek.toIndex()
- Timber.d("Current day: $currentDay (${fullDays[currentDay]})")
+ logger.d("Current day: $currentDay (${fullDays[currentDay]})")
val daysUntilAlarm: Int
val targetDate: LocalDate
val alarmTimeToday = passedAlarm.initLocalDateTimeInSystemZone()
val alarmInstantToday = alarmTimeToday.toInstant(tz)
- Timber.d("Alarm time today would be: $alarmTimeToday (${alarmInstantToday})")
- Timber.d("Current time is: $localNow (${nowInstant})")
+ logger.d("Alarm time today would be: $alarmTimeToday (${alarmInstantToday})")
+ logger.d("Current time is: $localNow (${nowInstant})")
val isPastToday = alarmInstantToday < nowInstant
- Timber.d("Is alarm time past for today? $isPastToday")
+ logger.d("Is alarm time past for today? $isPastToday")
if (currentDay > i || (currentDay == i && isPastToday)) {
// days left till end of week(sat) + the day of the week of the alarm
@@ -113,13 +113,13 @@ class AlarmNotificationScheduler(private val context: Context) {
// end of week + 1 (to sunday) + day of week alarm is on = 3 + 1 + 2 = 6
daysUntilAlarm = SAT - currentDay + 1 + i
targetDate = todayDate.plus(DatePeriod(days = daysUntilAlarm))
- Timber.d("Current day ($currentDay) > alarm day ($i) or same day but time passed, scheduling for next week")
- Timber.d("Days until alarm: $daysUntilAlarm, target date: $targetDate")
+ logger.d("Current day ($currentDay) > alarm day ($i) or same day but time passed, scheduling for next week")
+ logger.d("Days until alarm: $daysUntilAlarm, target date: $targetDate")
} else {
daysUntilAlarm = i - currentDay
targetDate = todayDate.plus(DatePeriod(days = daysUntilAlarm))
- Timber.d("Current day ($currentDay) <= alarm day ($i) and time not passed, scheduling for this week")
- Timber.d("Days until alarm: $daysUntilAlarm, target date: $targetDate")
+ logger.d("Current day ($currentDay) <= alarm day ($i) and time not passed, scheduling for this week")
+ logger.d("Days until alarm: $daysUntilAlarm, target date: $targetDate")
}
val targetDateTime = LocalDateTime(
@@ -132,10 +132,10 @@ class AlarmNotificationScheduler(private val context: Context) {
.append(passedAlarm.hour).append(passedAlarm.minute)
val id = stringId.toString().split("-").joinToString("")
val intentId = id.toInt()
- Timber.d("Generated intent ID: $intentId for alarm ID: ${passedAlarm.alarmId}, day: $i, time: ${passedAlarm.hour}:${passedAlarm.minute}")
+ logger.d("Generated intent ID: $intentId for alarm ID: ${passedAlarm.alarmId}, day: $i, time: ${passedAlarm.hour}:${passedAlarm.minute}")
// Check if a previous alarm has been set
- Timber.d("Checking if a previous alarm with this ID already exists")
+ logger.d("Checking if a previous alarm with this ID already exists")
val isSet = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
context,
@@ -148,14 +148,14 @@ class AlarmNotificationScheduler(private val context: Context) {
}
if (isSet != null) {
- Timber.d("An alarm with ID $intentId already exists")
+ logger.d("An alarm with ID $intentId already exists")
hasExistingAlarms = true
if (!reschedule) {
- Timber.d("Not rescheduling because reschedule flag is false")
+ logger.d("Not rescheduling because reschedule flag is false")
// context.showToast(R.string.alarm_duplicate_toast_text)
} else {
// If reschedule is true, cancel the existing alarm and create a new one
- Timber.d("Canceling existing alarm because reschedule flag is true")
+ logger.d("Canceling existing alarm because reschedule flag is true")
context.cancelAlarm(isSet)
isSet.cancel()
}
@@ -163,7 +163,7 @@ class AlarmNotificationScheduler(private val context: Context) {
// If reschedule is true or no existing alarm was found, create a new one
if (isSet == null || reschedule) {
- Timber.d("Proceeding to create new alarm")
+ logger.d("Proceeding to create new alarm")
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
@@ -189,20 +189,20 @@ class AlarmNotificationScheduler(private val context: Context) {
// Return true if we scheduled new alarms OR if there were existing alarms
if (alarmIntentList.isEmpty() && !hasExistingAlarms) {
- Timber.w("No alarms were scheduled and no existing alarms found")
+ logger.w("No alarms were scheduled and no existing alarms found")
return false
}
- Timber.d("Scheduling ${alarmIntentList.size} alarms")
+ logger.d("Scheduling ${alarmIntentList.size} alarms")
for (i in alarmIntentList.indices) {
val pendingIntent = alarmIntentList[i]
val instant = timeInstants[i]
- Timber.d("Scheduling alarm #${i+1}/${alarmIntentList.size} for time: ${instant}")
+ logger.d("Scheduling alarm #${i+1}/${alarmIntentList.size} for time: ${instant}")
context.setExactAlarm(instant.toEpochMilliseconds(), pendingIntent)
- Timber.d("Alarm #${i+1} scheduled successfully")
+ logger.d("Alarm #${i+1} scheduled successfully")
}
- Timber.d("All ${alarmIntentList.size} alarms scheduled successfully, returning true")
+ logger.d("All ${alarmIntentList.size} alarms scheduled successfully, returning true")
return true
}
@@ -212,7 +212,7 @@ class AlarmNotificationScheduler(private val context: Context) {
* @param alarm alarm to be canceled
*/
fun cancelAlarm(alarm: Alarm) {
- Timber.d("AlarmNotificationScheduler.cancelAlarm called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}")
+ logger.d("AlarmNotificationScheduler.cancelAlarm called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}")
val receiverIntent = Intent(context, AlarmReceiver::class.java)
receiverIntent.action = ALARM_ACTION
@@ -221,13 +221,13 @@ class AlarmNotificationScheduler(private val context: Context) {
var canceledCount = 0
for (i in 0..6) { // For each day of the week
if (alarm.repeatDays.getOrNull(i) == 'T') {
- Timber.d("Canceling alarm for day $i (${fullDays[i]})")
+ logger.d("Canceling alarm for day $i (${fullDays[i]})")
val stringId: StringBuilder = StringBuilder().append(alarm.alarmId).append(i)
.append(alarm.hour).append(alarm.minute)
val id = stringId.toString().split("-").joinToString("")
val intentId = id.toInt()
- Timber.d("Generated intent ID: $intentId for alarm ID: ${alarm.alarmId}, day: $i, time: ${alarm.hour}:${alarm.minute}")
+ logger.d("Generated intent ID: $intentId for alarm ID: ${alarm.alarmId}, day: $i, time: ${alarm.hour}:${alarm.minute}")
val cancelPendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(
@@ -245,14 +245,14 @@ class AlarmNotificationScheduler(private val context: Context) {
)
}
- Timber.d("Calling context.cancelAlarm for intent ID: $intentId")
+ logger.d("Calling context.cancelAlarm for intent ID: $intentId")
context.cancelAlarm(cancelPendingIntent)
cancelPendingIntent.cancel()
- Timber.d("Alarm canceled for day $i (${fullDays[i]})")
+ logger.d("Alarm canceled for day $i (${fullDays[i]})")
canceledCount++
}
}
- Timber.d("AlarmNotificationScheduler.cancelAlarm completed for alarmId=${alarm.alarmId}, canceled $canceledCount alarms")
+ logger.d("AlarmNotificationScheduler.cancelAlarm completed for alarmId=${alarm.alarmId}, canceled $canceledCount alarms")
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/MathAlarmNotification.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/MathAlarmNotification.kt
index 0202ae5..d98e376 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/MathAlarmNotification.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/notification/MathAlarmNotification.kt
@@ -13,6 +13,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.core.app.NotificationCompat
import androidx.core.net.toUri
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.AlarmReceiver
import com.timilehinaregbesola.mathalarm.R
import com.timilehinaregbesola.mathalarm.domain.model.Alarm
@@ -22,7 +23,6 @@ import com.timilehinaregbesola.mathalarm.presentation.MainActivity
import com.timilehinaregbesola.mathalarm.utils.getNotificationManager
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.serialization.json.Json
-import timber.log.Timber
import java.io.InputStream
import java.net.URLEncoder
@@ -38,6 +38,7 @@ class MathAlarmNotification(
private val context: Context,
private val channel: MathAlarmNotificationChannel,
private val player: AudioPlayer,
+ private val logger: Logger
) {
/**
* Shows the [MathAlarmNotification] based on the given Alarm.
@@ -45,7 +46,7 @@ class MathAlarmNotification(
* @param alarm the alarm event to be shown in the notification
*/
fun show(alarm: Alarm) {
- Timber.d("Showing notification for '${alarm.title}'")
+ logger.d("Showing notification for '${alarm.title}'")
val builder = buildNotification(alarm)
// builder.addAction(getCompleteAction(alarm))
var uriExists: Boolean
@@ -59,7 +60,7 @@ class MathAlarmNotification(
uriExists = true
} catch (e: Exception) {
uriExists = false
- Timber.w("File corresponding to the uri does not exist $toneUri")
+ logger.w("File corresponding to the uri does not exist $toneUri")
}
toneUri = if (uriExists) toneUri else RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
setDataSource(toneUri)
@@ -74,7 +75,7 @@ class MathAlarmNotification(
* @param alarm the task to be shown in the notification
*/
fun showRepeating(alarm: Alarm) {
- Timber.d("Showing repeating notification for '${alarm.title}'")
+ logger.d("Showing repeating notification for '${alarm.title}'")
val builder = buildNotification(alarm)
context.getNotificationManager()?.notify(alarm.alarmId.toInt(), builder.build())
}
@@ -85,7 +86,7 @@ class MathAlarmNotification(
* @param notificationId the notification id to be dismissed
*/
fun dismiss(notificationId: Long) {
- Timber.d("Dismissing notification id '$notificationId'")
+ logger.d("Dismissing notification id '$notificationId'")
player.stop()
context.getNotificationManager()?.cancel(notificationId.toInt())
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/MainActivity.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/MainActivity.kt
index 4615cd8..4c8114e 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/MainActivity.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/MainActivity.kt
@@ -24,21 +24,18 @@ import com.timilehinaregbesola.mathalarm.presentation.appsettings.shouldUseDarkC
import com.timilehinaregbesola.mathalarm.presentation.ui.MathAlarmTheme
import com.timilehinaregbesola.mathalarm.presentation.ui.darkPrimary
import com.timilehinaregbesola.mathalarm.utils.strings.Strings
-import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.InternalCoroutinesApi
+import org.koin.android.ext.android.inject
import java.net.URLDecoder
import java.nio.charset.StandardCharsets
-import javax.inject.Inject
@ExperimentalFoundationApi
@ExperimentalMaterial3Api
@ExperimentalComposeUiApi
@InternalCoroutinesApi
@ExperimentalAnimationApi
-@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
- @Inject
- lateinit var preferences: AlarmPreferencesImpl
+ val preferences: AlarmPreferencesImpl by inject()
private lateinit var lyricist: Lyricist
override fun onCreate(savedInstanceState: Bundle?) {
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/AlarmListViewModel.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/AlarmListViewModel.kt
index 35f8b4f..ea2ee6f 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/AlarmListViewModel.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/AlarmListViewModel.kt
@@ -2,24 +2,22 @@ package com.timilehinaregbesola.mathalarm.presentation.alarmlist
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.domain.model.Alarm
import com.timilehinaregbesola.mathalarm.framework.Usecases
import com.timilehinaregbesola.mathalarm.framework.app.permission.AlarmPermission
import com.timilehinaregbesola.mathalarm.utils.UiEvent
import com.timilehinaregbesola.mathalarm.utils.UiEvent.Navigate
import com.timilehinaregbesola.mathalarm.utils.UiEvent.ShowSnackbar
-import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.launch
-import timber.log.Timber
-import javax.inject.Inject
-@HiltViewModel
-class AlarmListViewModel @Inject constructor(
+class AlarmListViewModel(
private val usecases: Usecases,
val permission: AlarmPermission,
+ private val logger: Logger
) : ViewModel() {
var alarms = usecases.getSavedAlarms()
@@ -36,15 +34,15 @@ class AlarmListViewModel @Inject constructor(
sendUiEvent(Navigate(event.alarm))
}
is AlarmListEvent.OnAlarmOnChange -> {
- Timber.d("OnAlarmOnChange event received: alarmId=${event.alarm.alarmId}, isOn=${event.isOn}")
+ logger.d("OnAlarmOnChange event received: alarmId=${event.alarm.alarmId}, isOn=${event.isOn}")
viewModelScope.launch {
- Timber.d("Updating alarm in database: alarmId=${event.alarm.alarmId}, setting isOn=${event.isOn}")
+ logger.d("Updating alarm in database: alarmId=${event.alarm.alarmId}, setting isOn=${event.isOn}")
usecases.addAlarm(event.alarm.copy(isOn = event.isOn))
if (event.isOn) {
- Timber.d("Alarm is being turned ON, scheduling: alarmId=${event.alarm.alarmId}")
+ logger.d("Alarm is being turned ON, scheduling: alarmId=${event.alarm.alarmId}")
usecases.scheduleAlarm(event.alarm, false)
} else {
- Timber.d("Alarm is being turned OFF: alarmId=${event.alarm.alarmId}")
+ logger.d("Alarm is being turned OFF: alarmId=${event.alarm.alarmId}")
// Cancel
}
}
@@ -75,7 +73,7 @@ class AlarmListViewModel @Inject constructor(
clearAlarmsSelected = true
viewModelScope.launch {
alarms.takeWhile { clearAlarmsSelected }.collect { list ->
- Timber.d("öooo")
+ logger.d("öooo")
usecases.clearAlarms(list)
clearAlarmsSelected = false
}
@@ -101,21 +99,21 @@ class AlarmListViewModel @Inject constructor(
}
fun scheduleAlarm(alarm: Alarm, reschedule: Boolean, message: String) {
- Timber.d("scheduleAlarm called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}, reschedule=$reschedule")
+ logger.d("scheduleAlarm called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}, reschedule=$reschedule")
viewModelScope.launch {
- Timber.d("Calling usecases.scheduleAlarm for alarmId=${alarm.alarmId}")
+ logger.d("Calling usecases.scheduleAlarm for alarmId=${alarm.alarmId}")
usecases.scheduleAlarm(alarm, reschedule)
- Timber.d("scheduleAlarm completed for alarmId=${alarm.alarmId}, showing snackbar message: $message")
+ logger.d("scheduleAlarm completed for alarmId=${alarm.alarmId}, showing snackbar message: $message")
sendUiEvent(ShowSnackbar(message = message))
}
}
fun cancelAlarm(alarm: Alarm) {
- Timber.d("cancelAlarm called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}")
+ logger.d("cancelAlarm called: alarmId=${alarm.alarmId}, time=${alarm.hour}:${alarm.minute}, repeat=${alarm.repeat}, repeatDays=${alarm.repeatDays}")
viewModelScope.launch {
- Timber.d("Calling usecases.cancelAlarm for alarmId=${alarm.alarmId}")
+ logger.d("Calling usecases.cancelAlarm for alarmId=${alarm.alarmId}")
usecases.cancelAlarm(alarm)
- Timber.d("cancelAlarm completed for alarmId=${alarm.alarmId}")
+ logger.d("cancelAlarm completed for alarmId=${alarm.alarmId}")
}
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/components/AlarmListScreen.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/components/AlarmListScreen.kt
index b5fb73e..c88c860 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/components/AlarmListScreen.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmlist/components/AlarmListScreen.kt
@@ -38,7 +38,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
-import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation3.runtime.NavBackStack
import cafe.adriel.lyricist.strings
import com.timilehinaregbesola.mathalarm.R
@@ -61,6 +60,7 @@ import com.timilehinaregbesola.mathalarm.utils.UiEvent.Navigate
import com.timilehinaregbesola.mathalarm.utils.UiEvent.ShowSnackbar
import com.timilehinaregbesola.mathalarm.utils.getTimeLeft
import kotlinx.serialization.json.Json
+import org.koin.compose.viewmodel.koinViewModel
@SuppressLint("UnrememberedMutableState")
@ExperimentalAnimationApi
@@ -68,7 +68,7 @@ import kotlinx.serialization.json.Json
@ExperimentalMaterial3Api
@Composable
fun ListDisplayScreen(
- viewModel: AlarmListViewModel = hiltViewModel(),
+ viewModel: AlarmListViewModel = koinViewModel(),
backstack: NavBackStack,
darkTheme: Boolean,
) {
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/AlarmMathViewModel.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/AlarmMathViewModel.kt
index 6a8e6dd..db0cc33 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/AlarmMathViewModel.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/AlarmMathViewModel.kt
@@ -4,11 +4,13 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.domain.model.Alarm
import com.timilehinaregbesola.mathalarm.framework.Usecases
import com.timilehinaregbesola.mathalarm.interactors.AudioPlayer
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.*
+import kotlinx.coroutines.InternalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -16,12 +18,12 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
-import javax.inject.Inject
+import kotlinx.coroutines.launch
-@HiltViewModel
-class AlarmMathViewModel @Inject constructor(
+class AlarmMathViewModel(
private val usecases: Usecases,
val audioPlayer: AudioPlayer,
+ private val logger: Logger
) : ViewModel() {
private val _state = MutableStateFlow(ToneState.Stopped())
val state: StateFlow = _state.asStateFlow()
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/components/MathScreen.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/components/MathScreen.kt
index 79e2170..cc286c7 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/components/MathScreen.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmmath/components/MathScreen.kt
@@ -36,8 +36,8 @@ import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -58,9 +58,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
-import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation3.runtime.NavBackStack
import cafe.adriel.lyricist.strings
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.domain.model.Alarm
import com.timilehinaregbesola.mathalarm.framework.database.AlarmEntity
import com.timilehinaregbesola.mathalarm.framework.database.AlarmMapper
@@ -100,7 +100,7 @@ import com.timilehinaregbesola.mathalarm.presentation.ui.spacing
import com.timilehinaregbesola.mathalarm.presentation.ui.unSelectedDay
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
-import timber.log.Timber
+import org.koin.compose.viewmodel.koinViewModel
import java.io.IOException
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@@ -111,7 +111,7 @@ import java.io.IOException
fun MathScreen(
backStack: NavBackStack,
alarm: AlarmEntity,
- viewModel: AlarmMathViewModel = hiltViewModel(),
+ viewModel: AlarmMathViewModel = koinViewModel(),
darkTheme: Boolean,
fromSheet: Boolean = false
) {
@@ -189,7 +189,7 @@ fun MathScreen(
}
}
} else {
- Timber.d("Tone not available")
+ Logger.d("Tone not available")
viewModel.onEvent(MathScreenEvent.OnToneError("Tone not available"))
}
onDispose {
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/AlarmSettingsViewModel.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/AlarmSettingsViewModel.kt
index ce9c8d1..16553f3 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/AlarmSettingsViewModel.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/AlarmSettingsViewModel.kt
@@ -13,16 +13,13 @@ import com.timilehinaregbesola.mathalarm.framework.Usecases
import com.timilehinaregbesola.mathalarm.utils.getFormatTime
import com.timilehinaregbesola.mathalarm.utils.initLocalDateTimeInSystemZone
import com.timilehinaregbesola.mathalarm.utils.toIndex
-import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.datetime.LocalDateTime
-import javax.inject.Inject
-@HiltViewModel
-class AlarmSettingsViewModel @Inject constructor(
+class AlarmSettingsViewModel(
private val usecases: Usecases,
) : ViewModel() {
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/AlarmBottomSheet.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/AlarmBottomSheet.kt
index 06b7c3f..7801b1a 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/AlarmBottomSheet.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/AlarmBottomSheet.kt
@@ -53,9 +53,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.app.NotificationManagerCompat
import androidx.core.net.toUri
-import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation3.runtime.NavBackStack
import cafe.adriel.lyricist.strings
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.framework.database.AlarmEntity
import com.timilehinaregbesola.mathalarm.framework.database.AlarmMapper
import com.timilehinaregbesola.mathalarm.presentation.alarmlist.components.DialogArguments
@@ -104,12 +104,12 @@ import kotlinx.datetime.LocalTime
import kotlinx.datetime.format
import kotlinx.datetime.format.char
import kotlinx.serialization.json.Json
-import timber.log.Timber
+import org.koin.compose.viewmodel.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AlarmBottomSheet(
- viewModel: AlarmSettingsViewModel = hiltViewModel(),
+ viewModel: AlarmSettingsViewModel = koinViewModel(),
backstack: NavBackStack,
darkTheme: Boolean,
alarm: AlarmEntity,
@@ -195,7 +195,7 @@ fun AlarmBottomSheet(
try {
pickToneLauncher.launch(null)
} catch (e: Exception) {
- Timber.e(e)
+ Logger.e("error launching tone picker", e)
viewModel.onEvent(
OnToneError(message = noPickerText)
)
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/LabelTextField.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/LabelTextField.kt
index 9d7a984..5aa31d9 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/LabelTextField.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/alarmsettings/components/LabelTextField.kt
@@ -25,16 +25,20 @@ fun LabelTextField(
onValueChange: (TextFieldValue) -> Unit,
) {
TextField(
- value = text,
- onValueChange = onValueChange,
- leadingIcon = { Icon(imageVector = Icons.Outlined.Label, contentDescription = null) },
modifier = Modifier
.padding(horizontal = MaterialTheme.spacing.medium)
.fillMaxWidth(),
+ value = text,
+ onValueChange = onValueChange,
+ leadingIcon = { Icon(imageVector = Icons.Outlined.Label, contentDescription = null) },
label = label,
placeholder = placeholder,
singleLine = true,
- colors = colors(unfocusedContainerColor = Transparent, focusedContainerColor = Transparent)
+ colors = colors(
+ unfocusedContainerColor = Transparent,
+ focusedContainerColor = Transparent,
+ cursorColor = MaterialTheme.colorScheme.onSurface
+ )
)
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/AlarmPreferencesImpl.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/AlarmPreferencesImpl.kt
index afab82a..bd6faf8 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/AlarmPreferencesImpl.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/AlarmPreferencesImpl.kt
@@ -4,18 +4,20 @@ import android.content.Context
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.intPreferencesKey
+import co.touchlab.kermit.Logger
import com.timilehinaregbesola.mathalarm.presentation.appsettings.AlarmPreferences.Theme
import com.timilehinaregbesola.mathalarm.utils.dataStore
-import dagger.hilt.android.qualifiers.ApplicationContext
-import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
-import timber.log.Timber
import java.io.IOException
-import javax.inject.Inject
-class AlarmPreferencesImpl @Inject constructor(
- @ApplicationContext private val context: Context,
- private val mapper: AppThemeOptionsMapper
+class AlarmPreferencesImpl(
+ private val context: Context,
+ private val mapper: AppThemeOptionsMapper,
+ private val logger: Logger
) : AlarmPreferences {
companion object {
val APP_THEME_OPTION = intPreferencesKey("mathalarm_theme_option")
@@ -34,14 +36,14 @@ class AlarmPreferencesImpl @Inject constructor(
override fun loadAppTheme(): Flow {
return context.dataStore.data.catch { exception ->
if (exception is IOException) {
- Timber.e("Error reading preferences: ", exception)
+ logger.e("Error reading preferences: ", exception)
emit(emptyPreferences())
} else {
throw exception
}
}.map { preferences ->
val id = preferences[APP_THEME_OPTION] ?: DataStoreTheme.SYSTEM.id
- val result = DataStoreTheme.values().find { it.id == id } ?: DataStoreTheme.SYSTEM
+ val result = DataStoreTheme.entries.find { it.id == id } ?: DataStoreTheme.SYSTEM
mapper.toRepo(result)
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/components/AppSettingsScreen.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/components/AppSettingsScreen.kt
index 6ed6d33..f35abbc 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/components/AppSettingsScreen.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/presentation/appsettings/components/AppSettingsScreen.kt
@@ -1,6 +1,8 @@
package com.timilehinaregbesola.mathalarm.presentation.appsettings.components
import android.content.Intent
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -35,6 +37,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
@@ -47,6 +50,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import cafe.adriel.lyricist.strings
import com.timilehinaregbesola.mathalarm.BuildConfig
+import com.timilehinaregbesola.mathalarm.framework.app.di.appModule
import com.timilehinaregbesola.mathalarm.presentation.appsettings.AlarmPreferences.Theme
import com.timilehinaregbesola.mathalarm.presentation.appsettings.AlarmPreferences.Theme.DARK
import com.timilehinaregbesola.mathalarm.presentation.appsettings.AlarmPreferences.Theme.LIGHT
@@ -66,7 +70,10 @@ import com.timilehinaregbesola.mathalarm.presentation.appsettings.shouldUseDarkC
import com.timilehinaregbesola.mathalarm.presentation.ui.MathAlarmTheme
import com.timilehinaregbesola.mathalarm.presentation.ui.spacing
import com.timilehinaregbesola.mathalarm.utils.email
+import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.launch
+import org.koin.compose.KoinApplicationPreview
+import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -263,13 +270,18 @@ fun HelpItem(
}
}
+@OptIn(ExperimentalAnimationApi::class, ExperimentalComposeUiApi::class,
+ ExperimentalFoundationApi::class, InternalCoroutinesApi::class
+)
@Preview
@Composable
private fun PreviewSettingsScreen() {
- MathAlarmTheme {
- AppSettingsScreen(
- pref = AlarmPreferencesImpl(LocalContext.current, AppThemeOptionsMapper())
- ) {}
+ KoinApplicationPreview(application = { modules(appModule) }) {
+ MathAlarmTheme {
+ AppSettingsScreen(
+ pref = koinInject()
+ ) {}
+ }
}
}
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/ContextExtensions.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/ContextExtensions.kt
index ae7c471..574462d 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/ContextExtensions.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/ContextExtensions.kt
@@ -14,9 +14,10 @@ import android.provider.Settings
import androidx.core.app.ActivityCompat
import androidx.core.app.AlarmManagerCompat
import androidx.core.content.ContextCompat
-import timber.log.Timber
+import co.touchlab.kermit.Logger
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
+import androidx.core.net.toUri
/**
* Sets a alarm using [AlarmManagerCompat] to be triggered based on the given parameter.
@@ -37,24 +38,24 @@ fun Context.setExactAlarm(
if (adjustedTriggerTime <= currentTime) {
// If the alarm time is in the past, add one week (7 days) to the trigger time
- Timber.w("Alarm time is in the past, scheduling for next week")
+ Logger.w(messageString = "Alarm time is in the past, scheduling for next week", tag = "Context setExactAlarm")
val oneWeekInMillis = 7 * 24 * 60 * 60 * 1000L
adjustedTriggerTime += oneWeekInMillis
}
if (operation == null) {
- Timber.e("PendingIntent is null, cannot schedule alarm")
+ Logger.e(messageString = "PendingIntent is null, cannot schedule alarm", tag = "Context setExactAlarm")
return
}
val manager = getAlarmManager()
if (manager == null) {
- Timber.e("AlarmManager is null, cannot schedule alarm")
+ Logger.e(messageString = "AlarmManager is null, cannot schedule alarm", tag = "Context setExactAlarm")
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !manager.canScheduleExactAlarms()) {
- Timber.e("Cannot schedule exact alarms - permission not granted on Android S+")
+ Logger.e(messageString = "Cannot schedule exact alarms - permission not granted on Android S+", tag = "Context setExactAlarm")
return
}
@@ -65,9 +66,9 @@ fun Context.setExactAlarm(
adjustedTriggerTime,
operation
)
- Timber.d("Alarm scheduled successfully")
+ Logger.d(messageString = "Alarm scheduled successfully", tag = "Context setExactAlarm")
} catch (e: Exception) {
- Timber.e(e, "Failed to schedule alarm")
+ Logger.e(e, tag = "Context setExactAlarm") {"Failed to schedule alarm"}
}
}
@@ -77,25 +78,25 @@ fun Context.setExactAlarm(
* @param operation action to be canceled
*/
fun Context.cancelAlarm(operation: PendingIntent?) {
- Timber.d("cancelAlarm called with operation=${operation?.hashCode()}")
+ Logger.d(messageString = "cancelAlarm called with operation=${operation?.hashCode()}", tag = "Context cancelAlarm")
if (operation == null) {
- Timber.e("PendingIntent is null, cannot cancel alarm")
+ Logger.e(messageString = "PendingIntent is null, cannot cancel alarm", tag = "Context cancelAlarm")
return
}
val manager = getAlarmManager()
if (manager == null) {
- Timber.e("AlarmManager is null, cannot cancel alarm")
+ Logger.e(messageString = "AlarmManager is null, cannot cancel alarm", tag = "Context cancelAlarm")
return
}
try {
- Timber.d("Canceling alarm with AlarmManager.cancel")
+ Logger.d(messageString = "Canceling alarm with AlarmManager.cancel", tag = "Context cancelAlarm")
manager.cancel(operation)
- Timber.d("Alarm canceled successfully")
+ Logger.d(messageString = "Alarm canceled successfully", tag = "Context cancelAlarm")
} catch (e: Exception) {
- Timber.e(e, "Failed to cancel alarm")
+ Logger.e(e, tag = "Context cancelAlarm") {"Failed to cancel alarm"}
}
}
@@ -106,7 +107,7 @@ fun Context.email(
text: String = "",
) {
val intent = Intent(Intent.ACTION_SENDTO)
- intent.data = Uri.parse("mailto:")
+ intent.data = "mailto:".toUri()
if (email.isNotEmpty()) {
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/FirebaseMessagingService.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/FirebaseMessagingService.kt
index e5f4081..91d0ace 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/FirebaseMessagingService.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/FirebaseMessagingService.kt
@@ -22,14 +22,11 @@ import com.timilehinaregbesola.mathalarm.BuildConfig
import com.timilehinaregbesola.mathalarm.R
import com.timilehinaregbesola.mathalarm.notification.MathAlarmNotificationChannel
import com.timilehinaregbesola.mathalarm.presentation.MainActivity
-import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.InternalCoroutinesApi
-import javax.inject.Inject
+import org.koin.android.ext.android.inject
-@AndroidEntryPoint
class FirebaseMessagingService : FirebaseMessagingService() {
- @Inject
- lateinit var channel: MathAlarmNotificationChannel
+ val channel: MathAlarmNotificationChannel by inject()
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (remoteMessage.data.isNotEmpty()) {
val updateApp = remoteMessage.data["updateApp"]!!.toInt()
diff --git a/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/Permissions.kt b/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/Permissions.kt
index 09bed86..63bb1c7 100644
--- a/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/Permissions.kt
+++ b/app/src/main/java/com/timilehinaregbesola/mathalarm/utils/Permissions.kt
@@ -11,7 +11,7 @@ import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import androidx.core.net.toUri
-import timber.log.Timber
+import co.touchlab.kermit.Logger
/**
* Checks if all ringtones can be played, and requests permissions if it is not the case
@@ -30,7 +30,7 @@ fun checkPermissions(
player.setDataSource(activity, alarmtone.toUri())
player.apply {
setOnErrorListener { mp, _, _ ->
- Timber.e("Error occured while playing audio.")
+ Logger.e("Error occured while playing audio.")
mp.stop()
mp.release()
true
@@ -55,7 +55,7 @@ fun checkPermissions(
.setNegativeButton(android.R.string.cancel, null)
.show()
} catch (e: Exception) {
- Timber.e("Was not able to show dialog to request permission, continue without the dialog")
+ Logger.e("Was not able to show dialog to request permission, continue without the dialog")
activity.requestPermissions(arrayOf(READ_EXTERNAL_STORAGE), 3)
}
}
diff --git a/build.gradle.kts b/build.gradle.kts
index a8bc91a..9e85fd5 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,7 +7,6 @@ plugins {
alias(libs.plugins.kotlin.gradle) apply false
alias(libs.plugins.google.services) apply false
alias(libs.plugins.crashlytics.gradle) apply false
- alias(libs.plugins.hilt.gradle) apply false
}
tasks.register("clean") {
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 4777b85..faed8a6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -20,6 +20,7 @@ hilt_android = "2.57.1"
hilt_android_compiler = "2.57.1"
hilt_nav_compose = "1.2.0"
# @pin
+kermit = "2.0.8"
kotlin = "2.2.0"
kotlinx_serialization = "1.9.0"
lottie = "6.6.7"
@@ -38,6 +39,7 @@ nav3Material = "1.0.0-SNAPSHOT"
lifecycleViewmodel = "1.0.0-SNAPSHOT"
appcompat = "1.7.1"
datetime = "0.7.1"
+koin-bom = "4.1.1"
[libraries]
android-material = { module = "com.google.android.material:material", version.ref = "material" }
@@ -53,12 +55,10 @@ androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "splashscreen" }
androidx-datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx_datastore" }
-androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hilt_nav_compose" }
androidx-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx_ktx" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidx_room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "androidx_room" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "androidx_room" }
-androidx-test-core = { module = "androidx.test:core", version.ref = "androidx_test_core" }
androidx-test-core-ktx = "androidx.test:core-ktx:1.7.0"
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "test_espresso_core" }
androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "test_junit_ext" }
@@ -75,24 +75,27 @@ firebase-analytics = { module = "com.google.firebase:firebase-analytics-ktx" }
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase" }
firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics" }
firebase-messaging = { module = "com.google.firebase:firebase-messaging" }
-hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt_android" }
-hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt_android_compiler" }
-hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt_android_compiler" }
junit = { module = "junit:junit", version.ref = "test_junit" }
+kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
+kermit-crashlytics = { module = "co.touchlab:kermit-crashlytics", version.ref = "kermit" }
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx_serialization" }
lottie-compose = { module = "com.airbnb.android:lottie-compose", version.ref = "lottie" }
lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" }
lyricist-processor = { module = "cafe.adriel.lyricist:lyricist-processor", version.ref = "lyricist" }
mockk = { module = "io.mockk:mockk", version.ref = "test_mockk" }
-plugin-ksp = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
+koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin-bom" }
+koin-core = { module = "io.insert-koin:koin-core" }
+koin-android = { module = "io.insert-koin:koin-android" }
+koin-compose = { module = "io.insert-koin:koin-compose" }
+koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel" }
+koin-compose-viewmodel-navigation = { module = "io.insert-koin:koin-compose-viewmodel-navigation" }
[plugins]
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
android-gradle = { id = "com.android.application", version.ref = "android_gradle_plugin" }
crashlytics-gradle = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics_plugin" }
-hilt-gradle = { id = "com.google.dagger.hilt.android", version.ref = "hilt_android" }
kotlin-gradle = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
google-services = { id = "com.google.gms.google-services", version.ref = "google_services" }