diff --git a/android/build.gradle b/android/build.gradle index 83c5ba2f7..359a9ee8a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,6 +2,9 @@ buildscript { repositories { google() jcenter() + maven { + url "https://plugins.gradle.org/m2/" + } } dependencies { @@ -9,6 +12,7 @@ buildscript { classpath "com.neenbedankt.gradle.plugins:android-apt:1.8" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION" classpath "org.ajoberstar:grgit:1.5.0" + classpath "org.jlleitschuh.gradle:ktlint-gradle:9.4.1" } } @@ -18,4 +22,5 @@ allprojects { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } jcenter() } + apply plugin: "org.jlleitschuh.gradle.ktlint" } diff --git a/android/build.sh b/android/build.sh index 0e506ecf6..a6f23af76 100755 --- a/android/build.sh +++ b/android/build.sh @@ -67,6 +67,11 @@ run_adb_as_root() { $ADB root } +lint() { + log_info "Running ktlint..." + $GRADLE ktlintCheck || fail +} + build_apk() { log_info "Removing old APKs..." rm -vf build/*.apk @@ -258,6 +263,7 @@ case "$1" in build) shift; parse_opts $* + lint build_apk build_instrumentation_apk run_jvm_tests diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt index b82c78d6b..f10a8aaa8 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitsActivityTestComponent.kt @@ -19,12 +19,22 @@ package org.isoron.uhabits -import dagger.* -import org.isoron.uhabits.activities.habits.list.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.inject.* -import org.mockito.Mockito.* +import dagger.Component +import dagger.Module +import dagger.Provides +import org.isoron.uhabits.activities.habits.list.ListHabitsModule +import org.isoron.uhabits.activities.habits.list.views.CheckmarkButtonViewFactory +import org.isoron.uhabits.activities.habits.list.views.CheckmarkPanelViewFactory +import org.isoron.uhabits.activities.habits.list.views.HabitCardViewFactory +import org.isoron.uhabits.activities.habits.list.views.NumberButtonViewFactory +import org.isoron.uhabits.activities.habits.list.views.NumberPanelViewFactory +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.inject.ActivityContextModule +import org.isoron.uhabits.inject.ActivityScope +import org.isoron.uhabits.inject.HabitModule +import org.isoron.uhabits.inject.HabitsActivityModule +import org.isoron.uhabits.inject.HabitsApplicationComponent +import org.mockito.Mockito.mock @Module class TestModule { @@ -32,17 +42,20 @@ class TestModule { } @ActivityScope -@Component(modules = arrayOf( +@Component( + modules = arrayOf( ActivityContextModule::class, HabitsActivityModule::class, ListHabitsModule::class, HabitModule::class, TestModule::class -), dependencies = arrayOf(HabitsApplicationComponent::class)) + ), + dependencies = arrayOf(HabitsApplicationComponent::class) +) interface HabitsActivityTestComponent { fun getCheckmarkPanelViewFactory(): CheckmarkPanelViewFactory fun getHabitCardViewFactory(): HabitCardViewFactory fun getEntryButtonViewFactory(): CheckmarkButtonViewFactory fun getNumberButtonViewFactory(): NumberButtonViewFactory fun getNumberPanelViewFactory(): NumberPanelViewFactory -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/BackupTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/BackupTest.kt index 8bf21a904..9ac40caff 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/BackupTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/BackupTest.kt @@ -19,11 +19,20 @@ package org.isoron.uhabits.acceptance -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.acceptance.steps.* -import org.isoron.uhabits.acceptance.steps.CommonSteps.* -import org.junit.* +import androidx.test.filters.LargeTest +import org.isoron.uhabits.BaseUserInterfaceTest +import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText +import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp +import org.isoron.uhabits.acceptance.steps.CommonSteps.longClickText +import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText +import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDoesNotDisplayText +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps +import org.isoron.uhabits.acceptance.steps.clearBackupFolder +import org.isoron.uhabits.acceptance.steps.clearDownloadFolder +import org.isoron.uhabits.acceptance.steps.copyBackupToDownloadFolder +import org.isoron.uhabits.acceptance.steps.exportFullBackup +import org.isoron.uhabits.acceptance.steps.importBackupFromDownloadFolder +import org.junit.Test @LargeTest class BackupTest : BaseUserInterfaceTest() { @@ -44,4 +53,4 @@ class BackupTest : BaseUserInterfaceTest() { verifyDisplaysText("Wake up early") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/BackupSteps.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/BackupSteps.kt index ba1273a18..d22a28a69 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/BackupSteps.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/BackupSteps.kt @@ -19,10 +19,11 @@ package org.isoron.uhabits.acceptance.steps -import androidx.test.uiautomator.* -import org.isoron.uhabits.acceptance.steps.CommonSteps.* -import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.* -import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.* +import androidx.test.uiautomator.UiSelector +import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText +import org.isoron.uhabits.acceptance.steps.CommonSteps.device +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.SETTINGS +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu const val BACKUP_FOLDER = "/sdcard/Android/data/org.isoron.uhabits/files/Backups/" const val DOWNLOAD_FOLDER = "/sdcard/Download/" diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt index 960f30312..8557310bc 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt @@ -20,12 +20,13 @@ package org.isoron.uhabits.activities.habits.list.views import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.utils.* -import org.junit.* -import org.junit.runner.* +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.core.models.Entry +import org.isoron.uhabits.utils.PaletteUtils +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -96,4 +97,4 @@ class EntryButtonViewTest : BaseViewTest() { private fun assertRendersUnchecked() { assertRenders(view, "$PATH/render_unchecked.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt index 1efd3a673..f6a696670 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt @@ -19,18 +19,20 @@ package org.isoron.uhabits.activities.habits.list.views -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.hamcrest.CoreMatchers.* -import org.hamcrest.MatcherAssert.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.core.models.Entry.Companion.NO import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL -import org.isoron.uhabits.utils.* -import org.junit.* -import org.junit.runner.* +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.utils.PaletteUtils +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -44,13 +46,15 @@ class EntryPanelViewTest : BaseViewTest() { super.setUp() prefs.isCheckmarkSequenceReversed = false - val checkmarks = intArrayOf(YES_MANUAL, - YES_MANUAL, - YES_AUTO, - NO, - NO, - NO, - YES_MANUAL) + val checkmarks = intArrayOf( + YES_MANUAL, + YES_MANUAL, + YES_AUTO, + NO, + NO, + NO, + YES_MANUAL + ) view = component.getCheckmarkPanelViewFactory().create().apply { values = checkmarks @@ -112,4 +116,4 @@ class EntryPanelViewTest : BaseViewTest() { view.buttons[3].performLongClick() assertThat(timestamps, equalTo(listOf(day(3), day(5), day(6)))) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt index 341763c8b..33586f756 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewTest.kt @@ -19,22 +19,24 @@ package org.isoron.uhabits.activities.habits.list.views -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import org.junit.* -import org.junit.runner.* +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.utils.DateUtils +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest class HabitCardViewTest : BaseViewTest() { val PATH = "habits/list/HabitCardView" - lateinit private var view: HabitCardView - lateinit private var habit1: Habit - lateinit private var habit2: Habit + private lateinit var view: HabitCardView + private lateinit var habit1: Habit + private lateinit var habit2: Habit override fun setUp() { super.setUp() diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt index 1c83fdb4b..077fa2740 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -20,14 +20,14 @@ package org.isoron.uhabits.activities.habits.list.views import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.* -import androidx.test.runner.* -import org.hamcrest.CoreMatchers.* -import org.hamcrest.MatcherAssert.* -import org.isoron.uhabits.* -import org.isoron.uhabits.utils.* -import org.junit.* -import org.junit.runner.* +import androidx.test.filters.MediumTest +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.utils.PaletteUtils +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -104,4 +104,4 @@ class NumberButtonViewTest : BaseViewTest() { view.performLongClick() assertTrue(edited) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt index 2a660b2a0..a7d9d962b 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt @@ -20,15 +20,16 @@ package org.isoron.uhabits.activities.habits.list.views import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.* -import androidx.test.runner.* -import org.hamcrest.CoreMatchers.* -import org.hamcrest.MatcherAssert.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.utils.* -import org.junit.* -import org.junit.runner.* +import androidx.test.filters.MediumTest +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.utils.PaletteUtils +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -42,8 +43,14 @@ class NumberPanelViewTest : BaseViewTest() { super.setUp() prefs.isCheckmarkSequenceReversed = false - val checkmarks = doubleArrayOf(1400.0, 5300.0, 0.0, - 14600.0, 2500.0, 45000.0) + val checkmarks = doubleArrayOf( + 1400.0, + 5300.0, + 0.0, + 14600.0, + 2500.0, + 45000.0 + ) view = component.getNumberPanelViewFactory().create().apply { values = checkmarks @@ -107,4 +114,4 @@ class NumberPanelViewTest : BaseViewTest() { view.buttons[3].performLongClick() assertThat(timestamps, equalTo(listOf(day(3), day(5), day(6)))) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardTest.kt index 9ed442ced..ef40fb082 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardTest.kt @@ -18,12 +18,15 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.junit.* -import org.junit.runner.* +import android.view.LayoutInflater +import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -36,9 +39,9 @@ class FrequencyCardTest : BaseViewTest() { super.setUp() val habit = fixtures.createLongHabit() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.frequencyCard) as FrequencyCard + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.frequencyCard) as FrequencyCard view.update(FrequencyCardPresenter(habit, 0).present()) measureView(view, 800f, 600f) } @@ -47,4 +50,4 @@ class FrequencyCardTest : BaseViewTest() { fun testRender() { assertRenders(view, PATH + "render.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardTest.kt index 7458b20dd..040675c94 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardTest.kt @@ -18,12 +18,15 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.junit.* -import org.junit.runner.* +import android.view.LayoutInflater +import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -36,12 +39,16 @@ class HistoryCardTest : BaseViewTest() { super.setUp() val habit = fixtures.createLongHabit() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.historyCard) as HistoryCard - view.update(HistoryCardPresenter(habit = habit, - firstWeekday = 1, - isSkipEnabled = false).present()) + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.historyCard) as HistoryCard + view.update( + HistoryCardPresenter( + habit = habit, + firstWeekday = 1, + isSkipEnabled = false + ).present() + ) measureView(view, 800f, 600f) } @@ -49,4 +56,4 @@ class HistoryCardTest : BaseViewTest() { fun testRender() { assertRenders(view, PATH + "render.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardViewTest.kt index 17ec9e10c..8ee1e67e2 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardViewTest.kt @@ -18,15 +18,17 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import android.view.View.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.hamcrest.Matchers.* -import org.isoron.uhabits.* -import org.junit.* -import org.junit.Assert.* -import org.junit.runner.* +import android.view.LayoutInflater +import android.view.View.GONE +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.hamcrest.Matchers.equalTo +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.junit.Assert.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -38,9 +40,9 @@ class NotesCardViewTest : BaseViewTest() { override fun setUp() { super.setUp() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.notesCard) + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.notesCard) view.update(NotesCardViewModel(description = "This is a test description")) measureView(view, 800f, 200f) } @@ -55,4 +57,4 @@ class NotesCardViewTest : BaseViewTest() { view.update(NotesCardViewModel(description = "")) assertThat(view.visibility, equalTo(GONE)) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt index 06ea8b7a7..94de408bf 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt @@ -18,13 +18,16 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.junit.* -import org.junit.runner.* +import android.view.LayoutInflater +import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.PaletteColor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -36,16 +39,18 @@ class OverviewCardViewTest : BaseViewTest() { override fun setUp() { super.setUp() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.overviewCard) as OverviewCardView - view.update(OverviewCardViewModel( + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.overviewCard) as OverviewCardView + view.update( + OverviewCardViewModel( scoreToday = 0.74f, scoreMonthDiff = 0.23f, scoreYearDiff = 0.74f, totalCount = 44, color = PaletteColor(7), - )) + ) + ) measureView(view, 800f, 300f) } @@ -53,4 +58,4 @@ class OverviewCardViewTest : BaseViewTest() { fun testRender() { assertRenders(view, PATH + "render.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardTest.kt index 15029f830..035cf8678 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardTest.kt @@ -18,12 +18,15 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.junit.* -import org.junit.runner.* +import android.view.LayoutInflater +import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -36,9 +39,9 @@ class ScoreCardTest : BaseViewTest() { super.setUp() val habit = fixtures.createLongHabit() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.scoreCard) as ScoreCard + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.scoreCard) as ScoreCard view.update(ScoreCardPresenter(habit, 0).present(0)) measureView(view, 800f, 600f) } @@ -47,4 +50,4 @@ class ScoreCardTest : BaseViewTest() { fun testRender() { assertRenders(view, PATH + "render.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt index 5b1ececac..5321438e6 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt @@ -18,17 +18,15 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import androidx.test.ext.junit.runners.* -import org.junit.runner.RunWith +import android.view.LayoutInflater +import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest import org.isoron.uhabits.BaseViewTest -import org.isoron.uhabits.activities.habits.show.views.StreakCardView import org.isoron.uhabits.R -import org.isoron.uhabits.activities.habits.show.views.StreakCardViewTest -import org.isoron.uhabits.core.models.* -import org.junit.* -import java.lang.Exception +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -41,13 +39,15 @@ class StreakCardViewTest : BaseViewTest() { super.setUp() val habit = fixtures.createLongHabit() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.streakCard) as StreakCardView - view.update(StreakCardViewModel( + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.streakCard) as StreakCardView + view.update( + StreakCardViewModel( bestStreaks = habit.streaks.getBest(10), color = habit.color, - )) + ) + ) measureView(view, 800f, 600f) } @@ -55,4 +55,4 @@ class StreakCardViewTest : BaseViewTest() { fun testRender() { assertRenders(view, PATH + "render.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt index b611b5e99..44e425017 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt @@ -18,13 +18,15 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.view.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.junit.* -import org.junit.runner.* +import android.view.LayoutInflater +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.isoron.uhabits.BaseViewTest +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.PaletteColor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @MediumTest @@ -36,17 +38,19 @@ class SubtitleCardViewTest : BaseViewTest() { override fun setUp() { super.setUp() view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.subtitleCard) - view.update(SubtitleCardViewModel( + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.subtitleCard) + view.update( + SubtitleCardViewModel( color = PaletteColor(7), frequencyText = "3 times in 7 days", isNumerical = false, question = "Did you meditate this morning?", reminderText = "8:30 AM", targetText = "", - )) + ) + ) measureView(view, 800f, 200f) } @@ -54,4 +58,4 @@ class SubtitleCardViewTest : BaseViewTest() { fun testRender() { assertRenders(view, PATH + "render.png") } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/database/AutoBackupTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/database/AutoBackupTest.kt index 2d818b030..15a67df74 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/database/AutoBackupTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/database/AutoBackupTest.kt @@ -19,10 +19,12 @@ package org.isoron.uhabits.database -import org.isoron.uhabits.* -import org.isoron.uhabits.core.utils.* -import org.junit.* -import java.io.* +import org.isoron.uhabits.AndroidDirFinder +import org.isoron.uhabits.BaseAndroidTest +import org.isoron.uhabits.core.utils.DateUtils +import org.junit.Test +import java.io.File +import java.io.FileOutputStream class AutoBackupTest : BaseAndroidTest() { @Test @@ -32,7 +34,7 @@ class AutoBackupTest : BaseAndroidTest() { createTestFiles(basedir, 30) val autoBackup = AutoBackup(targetContext) - autoBackup.run(keep=5) + autoBackup.run(keep = 5) for (k in 1..25) assertDoesNotExist("${basedir.path}/test-$k.txt") for (k in 26..30) assertExists("${basedir.path}/test-$k.txt") @@ -77,4 +79,4 @@ class AutoBackupTest : BaseAndroidTest() { assertTrue(file.delete()) } } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt index b2ad2ed2b..dca0f2f17 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt @@ -18,18 +18,27 @@ */ package org.isoron.uhabits.intents -import android.content.ContentUris.* -import androidx.test.ext.junit.runners.* -import androidx.test.filters.* -import org.hamcrest.Matchers.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.reminders.ReminderScheduler.SchedulerResult.* -import org.isoron.uhabits.receivers.* -import org.junit.* -import org.junit.Assert.* -import org.junit.runner.* -import java.util.* -import java.util.Calendar.* +import android.content.ContentUris.parseId +import androidx.test.filters.MediumTest +import org.hamcrest.Matchers.equalTo +import org.isoron.uhabits.BaseAndroidTest +import org.isoron.uhabits.core.reminders.ReminderScheduler.SchedulerResult.OK +import org.isoron.uhabits.receivers.ReminderReceiver +import org.isoron.uhabits.receivers.WidgetReceiver +import org.junit.After +import org.junit.Assert.assertThat +import org.junit.Before +import org.junit.Test +import java.util.Calendar.DAY_OF_MONTH +import java.util.Calendar.DECEMBER +import java.util.Calendar.HOUR_OF_DAY +import java.util.Calendar.JUNE +import java.util.Calendar.MAY +import java.util.Calendar.MINUTE +import java.util.Calendar.MONTH +import java.util.Calendar.YEAR +import java.util.GregorianCalendar +import java.util.TimeZone class IntentSchedulerTest : BaseAndroidTest() { @@ -117,4 +126,4 @@ class IntentSchedulerTest : BaseAndroidTest() { val intent = WidgetReceiver.getLastReceivedIntent() assertNotNull(intent) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/ListHabitsRegressionTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/ListHabitsRegressionTest.kt index f4c1da0e7..4c39c5e11 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/ListHabitsRegressionTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/ListHabitsRegressionTest.kt @@ -19,15 +19,23 @@ package org.isoron.uhabits.regression -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.acceptance.steps.CommonSteps.* -import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.* -import org.isoron.uhabits.acceptance.steps.EditHabitSteps.* -import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.* -import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.* -import org.junit.* - +import androidx.test.filters.LargeTest +import org.isoron.uhabits.BaseUserInterfaceTest +import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.EDIT_HABIT +import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.LIST_HABITS +import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.SELECT_HABIT_TYPE +import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText +import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp +import org.isoron.uhabits.acceptance.steps.CommonSteps.longClickText +import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText +import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyShowsScreen +import org.isoron.uhabits.acceptance.steps.EditHabitSteps.clickSave +import org.isoron.uhabits.acceptance.steps.EditHabitSteps.typeName +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.ADD +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.DELETE +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu +import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.longPressCheckmarks +import org.junit.Test @LargeTest class ListHabitsRegressionTest : BaseUserInterfaceTest() { @@ -54,4 +62,4 @@ class ListHabitsRegressionTest : BaseUserInterfaceTest() { verifyDisplaysText("Hello world") longPressCheckmarks("Hello world", 3) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/SavedStateTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/SavedStateTest.kt index 0bea8f819..675fc9938 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/SavedStateTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/regression/SavedStateTest.kt @@ -19,12 +19,12 @@ package org.isoron.uhabits.regression -import androidx.test.filters.* -import org.isoron.uhabits.* -import org.isoron.uhabits.acceptance.steps.CommonSteps.* -import org.isoron.uhabits.activities.about.* -import org.junit.* -import java.lang.Thread.* +import androidx.test.filters.LargeTest +import org.isoron.uhabits.BaseUserInterfaceTest +import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp +import org.isoron.uhabits.activities.about.AboutActivity +import org.junit.Test +import java.lang.Thread.sleep @LargeTest class SavedStateTest : BaseUserInterfaceTest() { diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/sync/RemoteSyncServerTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/sync/RemoteSyncServerTest.kt index 896fa7d23..2cd5ca4a8 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/sync/RemoteSyncServerTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/sync/RemoteSyncServerTest.kt @@ -19,18 +19,29 @@ package org.isoron.uhabits.sync -import androidx.test.filters.* -import com.fasterxml.jackson.databind.* -import io.ktor.client.* -import io.ktor.client.engine.mock.* -import io.ktor.client.features.json.* -import io.ktor.client.request.* -import io.ktor.http.* -import junit.framework.Assert.* -import kotlinx.coroutines.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.sync.* -import org.junit.* +import androidx.test.filters.MediumTest +import com.fasterxml.jackson.databind.ObjectMapper +import io.ktor.client.HttpClient +import io.ktor.client.engine.mock.MockEngine +import io.ktor.client.engine.mock.MockRequestHandleScope +import io.ktor.client.engine.mock.respond +import io.ktor.client.engine.mock.respondError +import io.ktor.client.engine.mock.respondOk +import io.ktor.client.features.json.JsonFeature +import io.ktor.client.request.HttpRequestData +import io.ktor.client.request.HttpResponseData +import io.ktor.http.HttpStatusCode +import io.ktor.http.fullPath +import io.ktor.http.headersOf +import kotlinx.coroutines.runBlocking +import org.isoron.uhabits.BaseAndroidTest +import org.isoron.uhabits.core.sync.AbstractSyncServer +import org.isoron.uhabits.core.sync.GetDataVersionResponse +import org.isoron.uhabits.core.sync.KeyNotFoundException +import org.isoron.uhabits.core.sync.RegisterReponse +import org.isoron.uhabits.core.sync.ServiceUnavailable +import org.isoron.uhabits.core.sync.SyncData +import org.junit.Test @MediumTest class RemoteSyncServerTest : BaseAndroidTest() { @@ -115,23 +126,29 @@ class RemoteSyncServerTest : BaseAndroidTest() { return@runBlocking } - private fun server(expectedPath: String, - action: MockRequestHandleScope.(HttpRequestData) -> HttpResponseData + private fun server( + expectedPath: String, + action: MockRequestHandleScope.(HttpRequestData) -> HttpResponseData ): AbstractSyncServer { - return RemoteSyncServer(httpClient = HttpClient(MockEngine) { - install(JsonFeature) - engine { - addHandler { request -> - when (request.url.fullPath) { - expectedPath -> action(request) - else -> error("unexpected call: ${request.url.fullPath}") + return RemoteSyncServer( + httpClient = HttpClient(MockEngine) { + install(JsonFeature) + engine { + addHandler { request -> + when (request.url.fullPath) { + expectedPath -> action(request) + else -> error("unexpected call: ${request.url.fullPath}") + } } } - } - }, preferences = prefs) + }, + preferences = prefs + ) } private fun MockRequestHandleScope.respondWithJson(content: Any) = - respond(mapper.writeValueAsBytes(content), - headers = headersOf("Content-Type" to listOf("application/json"))) -} \ No newline at end of file + respond( + mapper.writeValueAsBytes(content), + headers = headersOf("Content-Type" to listOf("application/json")) + ) +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidBugReporter.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidBugReporter.kt index aace157a1..ccaaf9ba3 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidBugReporter.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidBugReporter.kt @@ -18,14 +18,21 @@ */ package org.isoron.uhabits -import android.content.* -import android.os.* -import android.view.* -import org.isoron.uhabits.inject.* -import java.io.* -import java.text.* -import java.util.* -import javax.inject.* +import android.content.Context +import android.os.Build +import android.os.Environment +import android.view.WindowManager +import org.isoron.uhabits.inject.AppContext +import java.io.BufferedReader +import java.io.File +import java.io.FileWriter +import java.io.IOException +import java.io.InputStreamReader +import java.text.SimpleDateFormat +import java.util.Date +import java.util.LinkedList +import java.util.Locale +import javax.inject.Inject open class AndroidBugReporter @Inject constructor(@AppContext private val context: Context) { @@ -56,7 +63,7 @@ open class AndroidBugReporter @Inject constructor(@AppContext private val contex var line: String? while (true) { line = bufferedReader.readLine() - if (line == null) break; + if (line == null) break log.addLast(line) if (log.size > maxLineCount) log.removeFirst() } @@ -79,7 +86,7 @@ open class AndroidBugReporter @Inject constructor(@AppContext private val contex try { val date = SimpleDateFormat("yyyy-MM-dd HHmmss", Locale.US).format(Date()) val dir = AndroidDirFinder(context).getFilesDir("Logs") - ?: throw IOException("log dir should not be null") + ?: throw IOException("log dir should not be null") val logFile = File(String.format("%s/Log %s.txt", dir.path, date)) val output = FileWriter(logFile) output.write(getBugReport()) @@ -106,5 +113,4 @@ open class AndroidBugReporter @Inject constructor(@AppContext private val contex appendln() } } - -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidDirFinder.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidDirFinder.kt index 0ec7ec2b9..0fc3fe284 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidDirFinder.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/AndroidDirFinder.kt @@ -20,7 +20,7 @@ package org.isoron.uhabits import android.content.Context import androidx.core.content.ContextCompat -import org.isoron.uhabits.inject.* +import org.isoron.uhabits.inject.AppContext import org.isoron.uhabits.utils.FileUtils import java.io.File import javax.inject.Inject @@ -28,8 +28,8 @@ import javax.inject.Inject class AndroidDirFinder @Inject constructor(@param:AppContext private val context: Context) { fun getFilesDir(relativePath: String): File? { return FileUtils.getDir( - ContextCompat.getExternalFilesDirs(context, null), - relativePath + ContextCompat.getExternalFilesDirs(context, null), + relativePath ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/BaseExceptionHandler.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/BaseExceptionHandler.kt index 151b97301..68f2d990a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/BaseExceptionHandler.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/BaseExceptionHandler.kt @@ -18,12 +18,12 @@ */ package org.isoron.uhabits -import android.app.* +import android.app.Activity class BaseExceptionHandler(private val activity: Activity) : Thread.UncaughtExceptionHandler { private val originalHandler: Thread.UncaughtExceptionHandler? = - Thread.getDefaultUncaughtExceptionHandler() + Thread.getDefaultUncaughtExceptionHandler() override fun uncaughtException(thread: Thread?, ex: Throwable?) { if (ex == null) return @@ -36,4 +36,4 @@ class BaseExceptionHandler(private val activity: Activity) : Thread.UncaughtExce } originalHandler?.uncaughtException(thread, ex) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt index f21e3d9e0..eb228e5b2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt @@ -19,16 +19,19 @@ package org.isoron.uhabits -import android.app.* -import android.content.* -import org.isoron.uhabits.core.database.* -import org.isoron.uhabits.core.reminders.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.* -import java.io.* +import android.app.Application +import android.content.Context +import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException +import org.isoron.uhabits.core.reminders.ReminderScheduler +import org.isoron.uhabits.core.ui.NotificationTray +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.AppContextModule +import org.isoron.uhabits.inject.DaggerHabitsApplicationComponent +import org.isoron.uhabits.inject.HabitsApplicationComponent +import org.isoron.uhabits.inject.HabitsModule +import org.isoron.uhabits.utils.DatabaseUtils +import org.isoron.uhabits.widgets.WidgetUpdater +import java.io.File /** * The Android application for Loop Habit Tracker. @@ -59,10 +62,10 @@ class HabitsApplication : Application() { val db = DatabaseUtils.getDatabaseFile(this) HabitsApplication.component = DaggerHabitsApplicationComponent - .builder() - .appContextModule(AppContextModule(context)) - .habitsModule(HabitsModule(db)) - .build() + .builder() + .appContextModule(AppContextModule(context)) + .habitsModule(HabitsModule(db)) + .build() DateUtils.setStartDayOffset(3, 0) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsBackupAgent.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsBackupAgent.kt index 4acc16b94..3f10e1a5d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsBackupAgent.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsBackupAgent.kt @@ -19,7 +19,9 @@ package org.isoron.uhabits -import android.app.backup.* +import android.app.backup.BackupAgentHelper +import android.app.backup.FileBackupHelper +import android.app.backup.SharedPreferencesBackupHelper /** * An Android BackupAgentHelper customized for this application. diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsDatabaseOpener.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsDatabaseOpener.kt index 639c55d63..0619e2f8a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsDatabaseOpener.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsDatabaseOpener.kt @@ -21,17 +21,18 @@ package org.isoron.uhabits -import android.content.* -import android.database.sqlite.* - -import org.isoron.uhabits.core.database.* -import org.isoron.uhabits.database.* -import java.io.* +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper +import org.isoron.uhabits.core.database.MigrationHelper +import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException +import org.isoron.uhabits.database.AndroidDatabase +import java.io.File class HabitsDatabaseOpener( - context: Context, - private val databaseFilename: String, - private val version: Int + context: Context, + private val databaseFilename: String, + private val version: Int ) : SQLiteOpenHelper(context, databaseFilename, null, version) { override fun onCreate(db: SQLiteDatabase) { @@ -45,18 +46,22 @@ class HabitsDatabaseOpener( db.disableWriteAheadLogging() } - override fun onUpgrade(db: SQLiteDatabase, - oldVersion: Int, - newVersion: Int) { + override fun onUpgrade( + db: SQLiteDatabase, + oldVersion: Int, + newVersion: Int + ) { db.disableWriteAheadLogging() if (db.version < 8) throw UnsupportedDatabaseVersionException() val helper = MigrationHelper(AndroidDatabase(db, File(databaseFilename))) helper.migrateTo(newVersion) } - override fun onDowngrade(db: SQLiteDatabase, - oldVersion: Int, - newVersion: Int) { + override fun onDowngrade( + db: SQLiteDatabase, + oldVersion: Int, + newVersion: Int + ) { throw UnsupportedDatabaseVersionException() } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt index 7469fde0e..6b7779534 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt @@ -19,37 +19,39 @@ package org.isoron.uhabits.activities -import android.app.* -import android.content.* -import android.content.res.Configuration.* -import android.os.Build.VERSION.* -import androidx.core.content.* +import android.app.Activity +import android.content.Context +import android.content.res.Configuration.UI_MODE_NIGHT_MASK +import android.content.res.Configuration.UI_MODE_NIGHT_YES +import android.os.Build.VERSION.SDK_INT +import androidx.core.content.ContextCompat import org.isoron.uhabits.R -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.inject.* +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.ThemeSwitcher +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.inject.ActivityScope @ActivityScope class AndroidThemeSwitcher constructor( - @ActivityContext val context: Context, - preferences: Preferences + @ActivityContext val context: Context, + preferences: Preferences ) : ThemeSwitcher(preferences) { override fun getSystemTheme(): Int { - if (SDK_INT < 29) return THEME_LIGHT; + if (SDK_INT < 29) return THEME_LIGHT val uiMode = context.resources.configuration.uiMode return if ((uiMode and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES) { - THEME_DARK; + THEME_DARK } else { - THEME_LIGHT; + THEME_LIGHT } } override fun applyDarkTheme() { context.setTheme(R.style.AppBaseThemeDark) (context as Activity).window.navigationBarColor = - ContextCompat.getColor(context, R.color.grey_900) + ContextCompat.getColor(context, R.color.grey_900) } override fun applyLightTheme() { @@ -59,6 +61,6 @@ constructor( override fun applyPureBlackTheme() { context.setTheme(R.style.AppBaseThemeDark_PureBlack) (context as Activity).window.navigationBarColor = - ContextCompat.getColor(context, R.color.black) + ContextCompat.getColor(context, R.color.black) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt index 84c10cb13..dcc25d906 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/HabitsDirFinder.kt @@ -18,15 +18,15 @@ */ package org.isoron.uhabits.activities -import org.isoron.uhabits.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.core.ui.screens.habits.show.* -import java.io.* -import javax.inject.* +import org.isoron.uhabits.AndroidDirFinder +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior +import java.io.File +import javax.inject.Inject class HabitsDirFinder @Inject constructor( - private val androidDirFinder: AndroidDirFinder + private val androidDirFinder: AndroidDirFinder ) : ShowHabitMenuBehavior.System, ListHabitsBehavior.DirFinder { override fun getCSVOutputDir(): File { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.kt index 24628a7fd..45e0fedb7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutActivity.kt @@ -18,10 +18,10 @@ */ package org.isoron.uhabits.activities.about -import android.os.* -import androidx.appcompat.app.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.activities.AndroidThemeSwitcher /** * Activity that allows the user to see information about the app itself. @@ -31,10 +31,12 @@ class AboutActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val app = application as HabitsApplication - val screen = AboutScreen(this, - app.component.intentFactory, - app.component.preferences) + val screen = AboutScreen( + this, + app.component.intentFactory, + app.component.preferences + ) AndroidThemeSwitcher(this, app.component.preferences).apply() setContentView(AboutView(this, screen)) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.kt index 2420cc79a..84db4b573 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.kt @@ -18,36 +18,37 @@ */ package org.isoron.uhabits.activities.about -import org.isoron.uhabits.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.intents.* -import org.isoron.uhabits.utils.* +import org.isoron.uhabits.R +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.intents.IntentFactory +import org.isoron.uhabits.utils.showMessage +import org.isoron.uhabits.utils.startActivitySafely class AboutScreen( - private val activity: AboutActivity, - private val intents: IntentFactory, - private val prefs: Preferences, + private val activity: AboutActivity, + private val intents: IntentFactory, + private val prefs: Preferences, ) { private var developerCountdown = 5 fun showRateAppWebsite() = - activity.startActivitySafely(intents.rateApp(activity)) + activity.startActivitySafely(intents.rateApp(activity)) fun showSendFeedbackScreen() = - activity.startActivitySafely(intents.sendFeedback(activity)) + activity.startActivitySafely(intents.sendFeedback(activity)) fun showSourceCodeWebsite() = - activity.startActivitySafely(intents.viewSourceCode(activity)) + activity.startActivitySafely(intents.viewSourceCode(activity)) fun showTranslationWebsite() = - activity.startActivitySafely(intents.helpTranslate(activity)) + activity.startActivitySafely(intents.helpTranslate(activity)) fun showPrivacyPolicyWebsite() = - activity.startActivitySafely(intents.privacyPolicy(activity)) + activity.startActivitySafely(intents.privacyPolicy(activity)) fun showCodeContributorsWebsite() = - activity.startActivitySafely(intents.codeContributors(activity)) + activity.startActivitySafely(intents.codeContributors(activity)) fun onPressDeveloperCountdown() { developerCountdown-- @@ -56,4 +57,4 @@ class AboutScreen( activity.showMessage(activity.resources.getString(R.string.you_are_now_a_developer)) } } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt index 719a1d0ab..c34297c52 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt @@ -18,19 +18,20 @@ */ package org.isoron.uhabits.activities.about -import android.annotation.* -import android.content.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.widget.FrameLayout +import org.isoron.uhabits.BuildConfig +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.databinding.AboutBinding +import org.isoron.uhabits.utils.setupToolbar @SuppressLint("ViewConstructor") class AboutView( - context: Context, - private val screen: AboutScreen, + context: Context, + private val screen: AboutScreen, ) : FrameLayout(context) { private var binding = AboutBinding.inflate(LayoutInflater.from(context)) @@ -38,9 +39,9 @@ class AboutView( init { addView(binding.root) setupToolbar( - toolbar = binding.toolbar, - color = PaletteColor(11), - title = resources.getString(R.string.about) + toolbar = binding.toolbar, + color = PaletteColor(11), + title = resources.getString(R.string.about) ) val version = resources.getString(R.string.version_n) binding.tvContributors.setOnClickListener { screen.showCodeContributorsWebsite() } @@ -52,4 +53,4 @@ class AboutView( binding.tvVersion.setOnClickListener { screen.onPressDeveloperCountdown() } binding.tvVersion.text = String.format(version, BuildConfig.VERSION_NAME) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt index de40e86bd..750ba7991 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt @@ -19,23 +19,25 @@ package org.isoron.uhabits.activities.common.dialogs -import android.app.* -import android.os.* -import android.util.* -import android.view.* -import android.widget.* -import androidx.appcompat.app.* +import android.app.Dialog +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.widget.EditText +import android.widget.RadioButton import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatDialogFragment import kotlinx.android.synthetic.main.frequency_picker_dialog.view.* -import org.isoron.uhabits.* +import org.isoron.uhabits.R - -class FrequencyPickerDialog(var freqNumerator: Int, - var freqDenominator: Int - ) : AppCompatDialogFragment() { +class FrequencyPickerDialog( + var freqNumerator: Int, + var freqDenominator: Int +) : AppCompatDialogFragment() { lateinit var contentView: View - var onFrequencyPicked: (num: Int, den: Int) -> Unit = {_,_ -> } + var onFrequencyPicked: (num: Int, den: Int) -> Unit = { _, _ -> } constructor() : this(1, 1) @@ -55,7 +57,7 @@ class FrequencyPickerDialog(var freqNumerator: Int, } contentView.everyXDaysTextView.setOnFocusChangeListener { v, hasFocus -> - if(hasFocus) check(contentView.everyXDaysRadioButton) + if (hasFocus) check(contentView.everyXDaysRadioButton) } contentView.xTimesPerWeekRadioButton.setOnClickListener { @@ -64,7 +66,7 @@ class FrequencyPickerDialog(var freqNumerator: Int, } contentView.xTimesPerWeekTextView.setOnFocusChangeListener { v, hasFocus -> - if(hasFocus) check(contentView.xTimesPerWeekRadioButton) + if (hasFocus) check(contentView.xTimesPerWeekRadioButton) } contentView.xTimesPerMonthRadioButton.setOnClickListener { @@ -73,13 +75,13 @@ class FrequencyPickerDialog(var freqNumerator: Int, } contentView.xTimesPerMonthTextView.setOnFocusChangeListener { v, hasFocus -> - if(hasFocus) check(contentView.xTimesPerMonthRadioButton) + if (hasFocus) check(contentView.xTimesPerMonthRadioButton) } return AlertDialog.Builder(activity!!) - .setView(contentView) - .setPositiveButton(R.string.save) { _, _ -> onSaveClicked() } - .create() + .setView(contentView) + .setPositiveButton(R.string.save) { _, _ -> onSaveClicked() } + .create() } private fun onSaveClicked() { @@ -129,7 +131,7 @@ class FrequencyPickerDialog(var freqNumerator: Int, private fun populateViews() { uncheckAll() if (freqNumerator == 1) { - if(freqDenominator == 1) { + if (freqDenominator == 1) { contentView.everyDayRadioButton.isChecked = true } else { contentView.everyXDaysRadioButton.isChecked = true @@ -137,7 +139,7 @@ class FrequencyPickerDialog(var freqNumerator: Int, focus(contentView.everyXDaysTextView) } } else { - if(freqDenominator == 7) { + if (freqDenominator == 7) { contentView.xTimesPerWeekRadioButton.isChecked = true contentView.xTimesPerWeekTextView.setText(freqNumerator.toString()) focus(contentView.xTimesPerWeekTextView) @@ -169,4 +171,4 @@ class FrequencyPickerDialog(var freqNumerator: Int, contentView.xTimesPerWeekTextView.clearFocus() contentView.xTimesPerMonthTextView.clearFocus() } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt index aba101a0c..a6aeba673 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -19,26 +19,31 @@ package org.isoron.uhabits.activities.common.dialogs -import android.content.* -import androidx.appcompat.app.* -import android.text.* -import android.view.* -import android.view.WindowManager.LayoutParams.* -import android.view.inputmethod.* -import android.widget.* +import android.content.Context +import android.content.DialogInterface +import android.text.InputFilter +import android.view.LayoutInflater +import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.NumberPicker +import android.widget.TextView +import androidx.appcompat.app.AlertDialog import org.isoron.uhabits.R -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* -import javax.inject.* +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.utils.InterfaceUtils +import javax.inject.Inject class NumberPickerFactory @Inject constructor( - @ActivityContext private val context: Context + @ActivityContext private val context: Context ) { - fun create(value: Double, - unit: String, - callback: ListHabitsBehavior.NumberPickerCallback): AlertDialog { + fun create( + value: Double, + unit: String, + callback: ListHabitsBehavior.NumberPickerCallback + ): AlertDialog { val inflater = LayoutInflater.from(context) val view = inflater.inflate(R.layout.number_picker_dialog, null) @@ -63,28 +68,31 @@ class NumberPickerFactory tvUnit.text = unit val dialog = AlertDialog.Builder(context) - .setView(view) - .setTitle(R.string.change_value) - .setPositiveButton(android.R.string.ok) { _, _ -> - picker.clearFocus() - val v = picker.value + 0.05 * picker2.value - callback.onNumberPicked(v) - } - .setOnDismissListener{ - callback.onNumberPickerDismissed() - } - .create() + .setView(view) + .setTitle(R.string.change_value) + .setPositiveButton(android.R.string.ok) { _, _ -> + picker.clearFocus() + val v = picker.value + 0.05 * picker2.value + callback.onNumberPicked(v) + } + .setOnDismissListener { + callback.onNumberPickerDismissed() + } + .create() dialog.setOnShowListener { picker.getChildAt(0)?.requestFocus() dialog.window?.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE) } - InterfaceUtils.setupEditorAction(picker, TextView.OnEditorActionListener { _, actionId, _ -> - if (actionId == EditorInfo.IME_ACTION_DONE) - dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick() - false - }) + InterfaceUtils.setupEditorAction( + picker, + TextView.OnEditorActionListener { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_DONE) + dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick() + false + } + ) return dialog } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt index 452c60369..c9adafbf5 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TaskProgressBar.kt @@ -19,19 +19,21 @@ package org.isoron.uhabits.activities.common.views -import android.content.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.core.tasks.* +import android.content.Context +import android.view.View +import android.widget.ProgressBar +import org.isoron.uhabits.core.tasks.Task +import org.isoron.uhabits.core.tasks.TaskRunner class TaskProgressBar( - context: Context, - private val runner: TaskRunner + context: Context, + private val runner: TaskRunner ) : ProgressBar( - context, - null, - android.R.attr.progressBarStyleHorizontal -), TaskRunner.Listener { + context, + null, + android.R.attr.progressBarStyleHorizontal +), + TaskRunner.Listener { init { visibility = View.GONE diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt index db18464db..2b7c8f77c 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt @@ -19,25 +19,38 @@ package org.isoron.uhabits.activities.habits.edit -import android.annotation.* -import android.content.res.* -import android.graphics.* -import android.os.* -import android.text.format.* -import android.view.* -import android.widget.* -import androidx.appcompat.app.* -import androidx.fragment.app.* -import com.android.datetimepicker.time.* +import android.annotation.SuppressLint +import android.content.res.ColorStateList +import android.graphics.Color +import android.os.Bundle +import android.text.format.DateFormat +import android.view.View +import android.widget.ArrayAdapter +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.DialogFragment +import com.android.datetimepicker.time.RadialPickerLayout +import com.android.datetimepicker.time.TimePickerDialog import kotlinx.android.synthetic.main.activity_edit_habit.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.activities.common.dialogs.* -import org.isoron.uhabits.core.commands.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* - +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory +import org.isoron.uhabits.activities.common.dialogs.FrequencyPickerDialog +import org.isoron.uhabits.activities.common.dialogs.WeekdayPickerDialog +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.commands.CreateHabitCommand +import org.isoron.uhabits.core.commands.EditHabitCommand +import org.isoron.uhabits.core.models.Frequency +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.models.Reminder +import org.isoron.uhabits.core.models.WeekdayList +import org.isoron.uhabits.databinding.ActivityEditHabitBinding +import org.isoron.uhabits.utils.ColorUtils +import org.isoron.uhabits.utils.formatTime +import org.isoron.uhabits.utils.toFormattedString +import org.isoron.uhabits.utils.toThemedAndroidColor class EditHabitActivity : AppCompatActivity() { @@ -143,7 +156,7 @@ class EditHabitActivity : AppCompatActivity() { arrayAdapter.add(getString(R.string.every_week)) arrayAdapter.add(getString(R.string.every_month)) builder.setAdapter(arrayAdapter) { dialog, which -> - freqDen = when(which) { + freqDen = when (which) { 1 -> 7 2 -> 30 else -> 1 @@ -159,20 +172,26 @@ class EditHabitActivity : AppCompatActivity() { val currentHour = if (reminderHour >= 0) reminderHour else 8 val currentMin = if (reminderMin >= 0) reminderMin else 0 val is24HourMode = DateFormat.is24HourFormat(this) - val dialog = TimePickerDialog.newInstance(object : TimePickerDialog.OnTimeSetListener { - override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) { - reminderHour = hourOfDay - reminderMin = minute - populateReminder() - } - - override fun onTimeCleared(view: RadialPickerLayout?) { - reminderHour = -1 - reminderMin = -1 - reminderDays = WeekdayList.EVERY_DAY - populateReminder() - } - }, currentHour, currentMin, is24HourMode, androidColor) + val dialog = TimePickerDialog.newInstance( + object : TimePickerDialog.OnTimeSetListener { + override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) { + reminderHour = hourOfDay + reminderMin = minute + populateReminder() + } + + override fun onTimeCleared(view: RadialPickerLayout?) { + reminderHour = -1 + reminderMin = -1 + reminderDays = WeekdayList.EVERY_DAY + populateReminder() + } + }, + currentHour, + currentMin, + is24HourMode, + androidColor + ) dialog.show(supportFragmentManager, "timePicker") } @@ -188,7 +207,7 @@ class EditHabitActivity : AppCompatActivity() { } binding.buttonSave.setOnClickListener { - if(validate()) save() + if (validate()) save() } for (fragment in supportFragmentManager.fragments) { @@ -226,14 +245,16 @@ class EditHabitActivity : AppCompatActivity() { val command = if (habitId >= 0) { EditHabitCommand( - component.habitList, - habitId, - habit) + component.habitList, + habitId, + habit + ) } else { CreateHabitCommand( - component.modelFactory, - component.habitList, - habit) + component.modelFactory, + component.habitList, + habit + ) } component.commandRunner.run(command) finish() @@ -246,11 +267,11 @@ class EditHabitActivity : AppCompatActivity() { isValid = false } if (habitType == Habit.NUMBER_HABIT) { - if(unitInput.text.isEmpty()) { + if (unitInput.text.isEmpty()) { unitInput.error = getString(R.string.validation_cannot_be_blank) isValid = false } - if(targetInput.text.isEmpty()) { + if (targetInput.text.isEmpty()) { targetInput.error = getString(R.string.validation_cannot_be_blank) isValid = false } @@ -282,7 +303,7 @@ class EditHabitActivity : AppCompatActivity() { freqDen == 31 -> getString(R.string.x_times_per_month, freqNum) else -> "Unknown" } - binding.numericalFrequencyPicker.text = when(freqDen) { + binding.numericalFrequencyPicker.text = when (freqDen) { 1 -> getString(R.string.every_day) 7 -> getString(R.string.every_week) 30 -> getString(R.string.every_month) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/HabitTypeDialog.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/HabitTypeDialog.kt index 39e8dfb4c..312637b1a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/HabitTypeDialog.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/HabitTypeDialog.kt @@ -19,20 +19,24 @@ package org.isoron.uhabits.activities.habits.edit -import android.os.* -import android.view.* -import androidx.appcompat.app.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.intents.* +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatDialogFragment +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.databinding.SelectHabitTypeBinding +import org.isoron.uhabits.intents.IntentFactory class HabitTypeDialog : AppCompatDialogFragment() { override fun getTheme() = R.style.Translucent - override fun onCreateView(inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { val binding = SelectHabitTypeBinding.inflate(inflater, container, false) binding.buttonYesNo.setOnClickListener { @@ -53,4 +57,4 @@ class HabitTypeDialog : AppCompatDialogFragment() { return binding.root } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt index 4736e69e9..a821c9229 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt @@ -19,22 +19,26 @@ package org.isoron.uhabits.activities.habits.list -import android.content.* -import android.os.* -import android.view.* -import androidx.appcompat.app.* -import kotlinx.coroutines.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.sync.* -import org.isoron.uhabits.core.tasks.* -import org.isoron.uhabits.core.ui.ThemeSwitcher.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.database.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.isoron.uhabits.BaseExceptionHandler +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.sync.SyncManager +import org.isoron.uhabits.core.tasks.TaskRunner +import org.isoron.uhabits.core.ui.ThemeSwitcher.THEME_DARK +import org.isoron.uhabits.core.utils.MidnightTimer +import org.isoron.uhabits.database.AutoBackup +import org.isoron.uhabits.inject.ActivityContextModule +import org.isoron.uhabits.inject.DaggerHabitsActivityComponent +import org.isoron.uhabits.utils.restartWithFade class ListHabitsActivity : AppCompatActivity() { @@ -55,10 +59,10 @@ class ListHabitsActivity : AppCompatActivity() { val appComponent = (applicationContext as HabitsApplication).component val component = DaggerHabitsActivityComponent - .builder() - .activityContextModule(ActivityContextModule(this)) - .habitsApplicationComponent(appComponent) - .build() + .builder() + .activityContextModule(ActivityContextModule(this)) + .habitsApplicationComponent(appComponent) + .build() component.themeSwitcher.apply() prefs = appComponent.preferences diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt index 20ba1d15a..d921b677b 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt @@ -19,22 +19,25 @@ package org.isoron.uhabits.activities.habits.list -import android.content.* -import android.view.* -import androidx.appcompat.app.* +import android.content.Context +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity import org.isoron.uhabits.R -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.inject.* -import javax.inject.* +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.ThemeSwitcher +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsMenuBehavior +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.inject.ActivityScope +import javax.inject.Inject @ActivityScope class ListHabitsMenu @Inject constructor( - @ActivityContext context: Context, - private val preferences: Preferences, - private val themeSwitcher: ThemeSwitcher, - private val behavior: ListHabitsMenuBehavior + @ActivityContext context: Context, + private val preferences: Preferences, + private val themeSwitcher: ThemeSwitcher, + private val behavior: ListHabitsMenuBehavior ) { val activity = (context as AppCompatActivity) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt index 8977d0398..c7d09b297 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsModule.kt @@ -19,18 +19,21 @@ package org.isoron.uhabits.activities.habits.list -import android.content.* -import dagger.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.inject.* -import javax.inject.* +import android.content.Context +import dagger.Binds +import dagger.Module +import org.isoron.uhabits.AndroidBugReporter +import org.isoron.uhabits.activities.HabitsDirFinder +import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsMenuBehavior +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsSelectionMenuBehavior +import org.isoron.uhabits.inject.AppContext +import javax.inject.Inject class BugReporterProxy @Inject constructor( - @AppContext context: Context + @AppContext context: Context ) : AndroidBugReporter(context), ListHabitsBehavior.BugReporter @Module diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt index 7d8a354e3..02d894488 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt @@ -19,33 +19,50 @@ package org.isoron.uhabits.activities.habits.list -import android.content.* -import android.view.ViewGroup.LayoutParams.* -import android.widget.* +import android.content.Context +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.widget.FrameLayout +import android.widget.RelativeLayout import org.isoron.uhabits.R -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.tasks.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* -import java.lang.Math.* -import javax.inject.* +import org.isoron.uhabits.activities.common.views.ScrollableChart +import org.isoron.uhabits.activities.common.views.TaskProgressBar +import org.isoron.uhabits.activities.habits.list.views.EmptyListView +import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter +import org.isoron.uhabits.activities.habits.list.views.HabitCardListView +import org.isoron.uhabits.activities.habits.list.views.HabitCardListViewFactory +import org.isoron.uhabits.activities.habits.list.views.HeaderView +import org.isoron.uhabits.activities.habits.list.views.HintView +import org.isoron.uhabits.core.models.ModelObservable +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.tasks.TaskRunner +import org.isoron.uhabits.core.ui.screens.habits.list.HintListFactory +import org.isoron.uhabits.core.utils.MidnightTimer +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.inject.ActivityScope +import org.isoron.uhabits.utils.addAtBottom +import org.isoron.uhabits.utils.addAtTop +import org.isoron.uhabits.utils.addBelow +import org.isoron.uhabits.utils.buildToolbar +import org.isoron.uhabits.utils.dim +import org.isoron.uhabits.utils.dp +import org.isoron.uhabits.utils.setupToolbar +import org.isoron.uhabits.utils.sres +import java.lang.Math.max +import java.lang.Math.min +import javax.inject.Inject const val MAX_CHECKMARK_COUNT = 60 @ActivityScope class ListHabitsRootView @Inject constructor( - @ActivityContext context: Context, - hintListFactory: HintListFactory, - preferences: Preferences, - midnightTimer: MidnightTimer, - runner: TaskRunner, - private val listAdapter: HabitCardListAdapter, - habitCardListViewFactory: HabitCardListViewFactory + @ActivityContext context: Context, + hintListFactory: HintListFactory, + preferences: Preferences, + midnightTimer: MidnightTimer, + runner: TaskRunner, + private val listAdapter: HabitCardListAdapter, + habitCardListViewFactory: HabitCardListViewFactory ) : FrameLayout(context), ModelObservable.Listener { val listView: HabitCardListView = habitCardListViewFactory.create() @@ -72,10 +89,10 @@ class ListHabitsRootView @Inject constructor( addAtBottom(hintView) } rootView.setupToolbar( - toolbar = tbar, - title = resources.getString(R.string.main_activity_title), - color = PaletteColor(17), - displayHomeAsUpEnabled = false, + toolbar = tbar, + title = resources.getString(R.string.main_activity_title), + color = PaletteColor(17), + displayHomeAsUpEnabled = false, ) addView(rootView, MATCH_PARENT, MATCH_PARENT) listAdapter.setListView(listView) @@ -86,11 +103,13 @@ class ListHabitsRootView @Inject constructor( } private fun setupControllers() { - header.setScrollController(object : ScrollableChart.ScrollController { - override fun onDataOffsetChanged(newDataOffset: Int) { - listView.dataOffset = newDataOffset + header.setScrollController( + object : ScrollableChart.ScrollController { + override fun onDataOffsetChanged(newDataOffset: Int) { + listView.dataOffset = newDataOffset + } } - }) + ) } override fun onAttachedToWindow() { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index a54f2545f..628cd7d8e 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -19,29 +19,58 @@ package org.isoron.uhabits.activities.habits.list -import android.app.* -import android.content.* -import android.util.* -import androidx.annotation.* -import androidx.appcompat.app.* -import dagger.* +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.util.Log +import androidx.appcompat.app.AppCompatActivity +import dagger.Lazy import org.isoron.uhabits.R -import org.isoron.uhabits.activities.common.dialogs.* -import org.isoron.uhabits.activities.habits.edit.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.commands.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.tasks.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.core.ui.callbacks.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.intents.* -import org.isoron.uhabits.tasks.* -import org.isoron.uhabits.utils.* -import java.io.* -import javax.inject.* +import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory +import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialogFactory +import org.isoron.uhabits.activities.common.dialogs.ConfirmSyncKeyDialogFactory +import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory +import org.isoron.uhabits.activities.habits.edit.HabitTypeDialog +import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter +import org.isoron.uhabits.core.commands.ArchiveHabitsCommand +import org.isoron.uhabits.core.commands.ChangeHabitColorCommand +import org.isoron.uhabits.core.commands.Command +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.commands.CreateHabitCommand +import org.isoron.uhabits.core.commands.DeleteHabitsCommand +import org.isoron.uhabits.core.commands.EditHabitCommand +import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.tasks.TaskRunner +import org.isoron.uhabits.core.ui.ThemeSwitcher +import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback +import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.COULD_NOT_EXPORT +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.COULD_NOT_GENERATE_BUG_REPORT +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.DATABASE_REPAIRED +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.FILE_NOT_RECOGNIZED +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.IMPORT_FAILED +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.IMPORT_SUCCESSFUL +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.SYNC_ENABLED +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.SYNC_KEY_ALREADY_INSTALLED +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsMenuBehavior +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsSelectionMenuBehavior +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.inject.ActivityScope +import org.isoron.uhabits.intents.IntentFactory +import org.isoron.uhabits.tasks.ExportDBTaskFactory +import org.isoron.uhabits.tasks.ImportDataTask +import org.isoron.uhabits.tasks.ImportDataTaskFactory +import org.isoron.uhabits.utils.copyTo +import org.isoron.uhabits.utils.restartWithFade +import org.isoron.uhabits.utils.showMessage +import org.isoron.uhabits.utils.showSendEmailScreen +import org.isoron.uhabits.utils.showSendFileScreen +import java.io.File +import java.io.IOException +import javax.inject.Inject const val RESULT_IMPORT_DATA = 101 const val RESULT_EXPORT_CSV = 102 @@ -54,19 +83,19 @@ const val REQUEST_SETTINGS = 107 @ActivityScope class ListHabitsScreen @Inject constructor( - @ActivityContext val context: Context, - private val commandRunner: CommandRunner, - private val intentFactory: IntentFactory, - private val themeSwitcher: ThemeSwitcher, - private val adapter: HabitCardListAdapter, - private val taskRunner: TaskRunner, - private val exportDBFactory: ExportDBTaskFactory, - private val importTaskFactory: ImportDataTaskFactory, - private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, - private val confirmSyncKeyDialogFactory: ConfirmSyncKeyDialogFactory, - private val colorPickerFactory: ColorPickerDialogFactory, - private val numberPickerFactory: NumberPickerFactory, - private val behavior: Lazy + @ActivityContext val context: Context, + private val commandRunner: CommandRunner, + private val intentFactory: IntentFactory, + private val themeSwitcher: ThemeSwitcher, + private val adapter: HabitCardListAdapter, + private val taskRunner: TaskRunner, + private val exportDBFactory: ExportDBTaskFactory, + private val importTaskFactory: ImportDataTaskFactory, + private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, + private val confirmSyncKeyDialogFactory: ConfirmSyncKeyDialogFactory, + private val colorPickerFactory: ColorPickerDialogFactory, + private val numberPickerFactory: NumberPickerFactory, + private val behavior: Lazy ) : CommandRunner.Listener, ListHabitsBehavior.Screen, ListHabitsMenuBehavior.Screen, @@ -76,7 +105,7 @@ class ListHabitsScreen fun onAttached() { commandRunner.addListener(this) - if(activity.intent.action == "android.intent.action.VIEW") { + if (activity.intent.action == "android.intent.action.VIEW") { val uri = activity.intent.data!!.toString() val parts = uri.replace(Regex("^.*sync/"), "").split("#") val syncKey = parts[0] @@ -172,16 +201,20 @@ class ListHabitsScreen } override fun showMessage(m: ListHabitsBehavior.Message) { - activity.showMessage(activity.resources.getString(when (m) { - COULD_NOT_EXPORT -> R.string.could_not_export - IMPORT_SUCCESSFUL -> R.string.habits_imported - IMPORT_FAILED -> R.string.could_not_import - DATABASE_REPAIRED -> R.string.database_repaired - COULD_NOT_GENERATE_BUG_REPORT -> R.string.bug_report_failed - FILE_NOT_RECOGNIZED -> R.string.file_not_recognized - SYNC_ENABLED -> R.string.sync_enabled - SYNC_KEY_ALREADY_INSTALLED -> R.string.sync_key_already_installed - })) + activity.showMessage( + activity.resources.getString( + when (m) { + COULD_NOT_EXPORT -> R.string.could_not_export + IMPORT_SUCCESSFUL -> R.string.habits_imported + IMPORT_FAILED -> R.string.could_not_import + DATABASE_REPAIRED -> R.string.database_repaired + COULD_NOT_GENERATE_BUG_REPORT -> R.string.bug_report_failed + FILE_NOT_RECOGNIZED -> R.string.file_not_recognized + SYNC_ENABLED -> R.string.sync_enabled + SYNC_KEY_ALREADY_INSTALLED -> R.string.sync_key_already_installed + } + ) + ) } override fun showSendBugReportToDeveloperScreen(log: String) { @@ -199,16 +232,20 @@ class ListHabitsScreen activity.startActivityForResult(intent, REQUEST_SETTINGS) } - override fun showColorPicker(defaultColor: PaletteColor, - callback: OnColorPickedCallback) { + override fun showColorPicker( + defaultColor: PaletteColor, + callback: OnColorPickedCallback + ) { val picker = colorPickerFactory.create(defaultColor) picker.setListener(callback) picker.show(activity.supportFragmentManager, "picker") } - override fun showNumberPicker(value: Double, - unit: String, - callback: ListHabitsBehavior.NumberPickerCallback) { + override fun showNumberPicker( + value: Double, + unit: String, + callback: ListHabitsBehavior.NumberPickerCallback + ) { numberPickerFactory.create(value, unit, callback).show() } @@ -219,49 +256,61 @@ class ListHabitsScreen private fun getExecuteString(command: Command): String? { when (command) { is ArchiveHabitsCommand -> { - return activity.resources.getQuantityString(R.plurals.toast_habits_archived, - command.selected.size) + return activity.resources.getQuantityString( + R.plurals.toast_habits_archived, + command.selected.size + ) } is ChangeHabitColorCommand -> { - return activity.resources.getQuantityString(R.plurals.toast_habits_changed, - command.selected.size) + return activity.resources.getQuantityString( + R.plurals.toast_habits_changed, + command.selected.size + ) } is CreateHabitCommand -> { return activity.resources.getString(R.string.toast_habit_created) } is DeleteHabitsCommand -> { - return activity.resources.getQuantityString(R.plurals.toast_habits_deleted, - command.selected.size) + return activity.resources.getQuantityString( + R.plurals.toast_habits_deleted, + command.selected.size + ) } is EditHabitCommand -> { return activity.resources.getQuantityString(R.plurals.toast_habits_changed, 1) } is UnarchiveHabitsCommand -> { - return activity.resources.getQuantityString(R.plurals.toast_habits_unarchived, - command.selected.size) + return activity.resources.getQuantityString( + R.plurals.toast_habits_unarchived, + command.selected.size + ) } else -> return null } } private fun onImportData(file: File, onFinished: () -> Unit) { - taskRunner.execute(importTaskFactory.create(file) { result -> - if (result == ImportDataTask.SUCCESS) { - adapter.refresh() - activity.showMessage(activity.resources.getString(R.string.habits_imported)) - } else if (result == ImportDataTask.NOT_RECOGNIZED) { - activity.showMessage(activity.resources.getString(R.string.file_not_recognized)) - } else { - activity.showMessage(activity.resources.getString(R.string.could_not_import)) + taskRunner.execute( + importTaskFactory.create(file) { result -> + if (result == ImportDataTask.SUCCESS) { + adapter.refresh() + activity.showMessage(activity.resources.getString(R.string.habits_imported)) + } else if (result == ImportDataTask.NOT_RECOGNIZED) { + activity.showMessage(activity.resources.getString(R.string.file_not_recognized)) + } else { + activity.showMessage(activity.resources.getString(R.string.could_not_import)) + } + onFinished() } - onFinished() - }) + ) } private fun onExportDB() { - taskRunner.execute(exportDBFactory.create { filename -> - if (filename != null) activity.showSendFileScreen(filename) - else activity.showMessage(activity.resources.getString(R.string.could_not_export)) - }) + taskRunner.execute( + exportDBFactory.create { filename -> + if (filename != null) activity.showSendFileScreen(filename) + else activity.showMessage(activity.resources.getString(R.string.could_not_export)) + } + ) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt index 42193fd08..74dae8cfb 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt @@ -19,30 +19,33 @@ package org.isoron.uhabits.activities.habits.list -import android.content.* -import android.view.* -import androidx.appcompat.app.* +import android.content.Context +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode -import dagger.* +import dagger.Lazy import org.isoron.uhabits.R -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.commands.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import javax.inject.* +import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter +import org.isoron.uhabits.activities.habits.list.views.HabitCardListController +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.NotificationTray +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsSelectionMenuBehavior +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.inject.ActivityScope +import javax.inject.Inject @ActivityScope class ListHabitsSelectionMenu @Inject constructor( - @ActivityContext context: Context, - private val listAdapter: HabitCardListAdapter, - var commandRunner: CommandRunner, - private val prefs: Preferences, - private val behavior: ListHabitsSelectionMenuBehavior, - private val listController: Lazy, - private val notificationTray: NotificationTray + @ActivityContext context: Context, + private val listAdapter: HabitCardListAdapter, + var commandRunner: CommandRunner, + private val prefs: Preferences, + private val behavior: ListHabitsSelectionMenuBehavior, + private val listController: Lazy, + private val notificationTray: NotificationTray ) : ActionMode.Callback { val activity = (context as AppCompatActivity) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt index bea2d4149..aadf0ddfd 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ButtonPanelView.kt @@ -19,17 +19,18 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.view.* -import android.view.View.MeasureSpec.* -import android.widget.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.view.View +import android.view.View.MeasureSpec.EXACTLY +import android.widget.LinearLayout +import org.isoron.uhabits.R +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.utils.dim +import org.isoron.uhabits.utils.toMeasureSpec abstract class ButtonPanelView( - context: Context, - val preferences: Preferences + context: Context, + val preferences: Preferences ) : LinearLayout(context), Preferences.Listener { @@ -79,10 +80,12 @@ abstract class ButtonPanelView( val buttonWidth = dim(R.dimen.checkmarkWidth) val buttonHeight = dim(R.dimen.checkmarkHeight) val width = (buttonWidth * buttonCount) - super.onMeasure(width.toMeasureSpec(EXACTLY), - buttonHeight.toMeasureSpec(EXACTLY)) + super.onMeasure( + width.toMeasureSpec(EXACTLY), + buttonHeight.toMeasureSpec(EXACTLY) + ) } protected abstract fun setupButtons() protected abstract fun createButton(): T -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt index 496db8c17..ff70f8dd7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -19,26 +19,35 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.graphics.* -import android.text.* -import android.view.* -import android.view.View.MeasureSpec.* -import com.google.auto.factory.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF +import android.text.TextPaint +import android.view.HapticFeedbackConstants +import android.view.View +import android.view.View.MeasureSpec.EXACTLY +import com.google.auto.factory.AutoFactory +import com.google.auto.factory.Provided +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.models.Entry.Companion.NO import org.isoron.uhabits.core.models.Entry.Companion.SKIP import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.utils.dim +import org.isoron.uhabits.utils.getFontAwesome +import org.isoron.uhabits.utils.showMessage +import org.isoron.uhabits.utils.sres +import org.isoron.uhabits.utils.toMeasureSpec @AutoFactory class CheckmarkButtonView( - @Provided @ActivityContext context: Context, - @Provided val preferences: Preferences + @Provided @ActivityContext context: Context, + @Provided val preferences: Preferences ) : View(context), View.OnClickListener, View.OnLongClickListener { @@ -65,7 +74,7 @@ class CheckmarkButtonView( } fun performToggle() { - value = if(preferences.isSkipEnabled) { + value = if (preferences.isSkipEnabled) { Entry.nextToggleValueWithSkip(value) } else { Entry.nextToggleValueWithoutSkip(value) @@ -93,8 +102,10 @@ class CheckmarkButtonView( override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val height = resources.getDimensionPixelSize(R.dimen.checkmarkHeight) val width = resources.getDimensionPixelSize(R.dimen.checkmarkWidth) - super.onMeasure(width.toMeasureSpec(EXACTLY), - height.toMeasureSpec(EXACTLY)) + super.onMeasure( + width.toMeasureSpec(EXACTLY), + height.toMeasureSpec(EXACTLY) + ) } private inner class Drawer { @@ -118,7 +129,7 @@ class CheckmarkButtonView( SKIP -> R.string.fa_skipped NO -> R.string.fa_times UNKNOWN -> { - if(preferences.areQuestionMarksEnabled()) R.string.fa_question + if (preferences.areQuestionMarksEnabled()) R.string.fa_question else R.string.fa_times } else -> R.string.fa_check diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt index a29a454b5..9aac2eaf6 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -19,19 +19,20 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import com.google.auto.factory.* -import org.isoron.uhabits.core.models.* +import android.content.Context +import com.google.auto.factory.AutoFactory +import com.google.auto.factory.Provided import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.ActivityContext @AutoFactory class CheckmarkPanelView( - @Provided @ActivityContext context: Context, - @Provided preferences: Preferences, - @Provided private val buttonFactory: CheckmarkButtonViewFactory + @Provided @ActivityContext context: Context, + @Provided preferences: Preferences, + @Provided private val buttonFactory: CheckmarkButtonViewFactory ) : ButtonPanelView(context, preferences) { var values = IntArray(0) @@ -46,7 +47,7 @@ class CheckmarkPanelView( setupButtons() } - var onToggle: (Timestamp, Int) -> Unit = {_, _ ->} + var onToggle: (Timestamp, Int) -> Unit = { _, _ -> } set(value) { field = value setupButtons() diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt index c92eb341f..5911bff38 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/EmptyListView.kt @@ -19,13 +19,19 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.view.* -import android.view.Gravity.* -import android.view.ViewGroup.LayoutParams.* -import android.widget.* -import org.isoron.uhabits.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.view.Gravity.CENTER +import android.view.View +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.widget.LinearLayout +import android.widget.TextView +import org.isoron.uhabits.R +import org.isoron.uhabits.utils.dp +import org.isoron.uhabits.utils.getFontAwesome +import org.isoron.uhabits.utils.sp +import org.isoron.uhabits.utils.sres +import org.isoron.uhabits.utils.str class EmptyListView(context: Context) : LinearLayout(context) { init { @@ -33,19 +39,27 @@ class EmptyListView(context: Context) : LinearLayout(context) { gravity = CENTER visibility = View.GONE - addView(TextView(context).apply { - text = str(R.string.fa_star_half_o) - typeface = getFontAwesome() - textSize = sp(40.0f) - gravity = CENTER - setTextColor(sres.getColor(R.attr.mediumContrastTextColor)) - }, MATCH_PARENT, WRAP_CONTENT) + addView( + TextView(context).apply { + text = str(R.string.fa_star_half_o) + typeface = getFontAwesome() + textSize = sp(40.0f) + gravity = CENTER + setTextColor(sres.getColor(R.attr.mediumContrastTextColor)) + }, + MATCH_PARENT, + WRAP_CONTENT + ) - addView(TextView(context).apply { - text = str(R.string.no_habits_found) - gravity = CENTER - setPadding(0, dp(20.0f).toInt(), 0, 0) - setTextColor(sres.getColor(R.attr.mediumContrastTextColor)) - }, MATCH_PARENT, WRAP_CONTENT) + addView( + TextView(context).apply { + text = str(R.string.no_habits_found) + gravity = CENTER + setPadding(0, dp(20.0f).toInt(), 0, 0) + setTextColor(sres.getColor(R.attr.mediumContrastTextColor)) + }, + MATCH_PARENT, + WRAP_CONTENT + ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt index 898bfc48c..6e11714e9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListController.kt @@ -19,12 +19,13 @@ package org.isoron.uhabits.activities.habits.list.views -import dagger.* -import org.isoron.uhabits.activities.habits.list.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.inject.* -import javax.inject.* +import dagger.Lazy +import org.isoron.uhabits.activities.habits.list.ListHabitsSelectionMenu +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.ModelObservable +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.inject.ActivityScope +import javax.inject.Inject /** * Controller responsible for receiving and processing the events generated by a @@ -33,9 +34,9 @@ import javax.inject.* */ @ActivityScope class HabitCardListController @Inject constructor( - private val adapter: HabitCardListAdapter, - private val behavior: ListHabitsBehavior, - private val selectionMenu: Lazy + private val adapter: HabitCardListAdapter, + private val behavior: ListHabitsBehavior, + private val selectionMenu: Lazy ) : HabitCardListView.Controller, ModelObservable.Listener { private val NORMAL_MODE = NormalMode() @@ -53,7 +54,7 @@ class HabitCardListController @Inject constructor( val habitFrom = adapter.getItem(from) val habitTo = adapter.getItem(to) - if(habitFrom == null || habitTo == null) return + if (habitFrom == null || habitTo == null) return adapter.performReorder(from, to) behavior.onReorderHabit(habitFrom, habitTo) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt index a4cb243cc..5b2bcfe97 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt @@ -19,24 +19,33 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.os.* -import androidx.recyclerview.widget.* -import androidx.recyclerview.widget.ItemTouchHelper.* -import android.view.* -import com.google.auto.factory.* -import dagger.* +import android.content.Context +import android.os.Bundle +import android.os.Parcelable +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.View +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.ItemTouchHelper.DOWN +import androidx.recyclerview.widget.ItemTouchHelper.END +import androidx.recyclerview.widget.ItemTouchHelper.START +import androidx.recyclerview.widget.ItemTouchHelper.UP +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.auto.factory.AutoFactory +import com.google.auto.factory.Provided +import dagger.Lazy import org.isoron.uhabits.R -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.inject.* +import org.isoron.uhabits.activities.common.views.BundleSavedState +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.inject.ActivityContext @AutoFactory class HabitCardListView( - @Provided @ActivityContext context: Context, - @Provided private val adapter: HabitCardListAdapter, - @Provided private val cardViewFactory: HabitCardViewFactory, - @Provided private val controller: Lazy + @Provided @ActivityContext context: Context, + @Provided private val adapter: HabitCardListAdapter, + @Provided private val cardViewFactory: HabitCardViewFactory, + @Provided private val controller: Lazy ) : RecyclerView(context, null, R.attr.scrollableRecyclerViewStyle) { var checkmarkCount: Int = 0 @@ -45,8 +54,8 @@ class HabitCardListView( set(value) { field = value attachedHolders - .map { it.itemView as HabitCardView } - .forEach { it.dataOffset = value } + .map { it.itemView as HabitCardView } + .forEach { it.dataOffset = value } } private val attachedHolders = mutableListOf() @@ -65,11 +74,13 @@ class HabitCardListView( return cardViewFactory.create() } - fun bindCardView(holder: HabitCardViewHolder, - habit: Habit, - score: Double, - checkmarks: IntArray, - selected: Boolean): View { + fun bindCardView( + holder: HabitCardViewHolder, + habit: Habit, + score: Double, + checkmarks: IntArray, + selected: Boolean + ): View { val cardView = holder.itemView as HabitCardView cardView.habit = habit cardView.isSelected = selected @@ -132,7 +143,7 @@ class HabitCardListView( } private inner class CardViewGestureDetector( - private val holder: HabitCardViewHolder + private val holder: HabitCardViewHolder ) : GestureDetector.SimpleOnGestureListener() { override fun onLongPress(e: MotionEvent) { @@ -149,20 +160,26 @@ class HabitCardListView( } inner class TouchHelperCallback : ItemTouchHelper.Callback() { - override fun getMovementFlags(recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder): Int { + override fun getMovementFlags( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder + ): Int { return makeMovementFlags(UP or DOWN, START or END) } - override fun onMove(recyclerView: RecyclerView, - from: RecyclerView.ViewHolder, - to: RecyclerView.ViewHolder): Boolean { + override fun onMove( + recyclerView: RecyclerView, + from: RecyclerView.ViewHolder, + to: RecyclerView.ViewHolder + ): Boolean { controller.get().drop(from.adapterPosition, to.adapterPosition) return true } - override fun onSwiped(viewHolder: RecyclerView.ViewHolder, - direction: Int) { + override fun onSwiped( + viewHolder: RecyclerView.ViewHolder, + direction: Int + ) { } override fun isItemViewSwipeEnabled() = false diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index c1851c9b1..1f12d6eb7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -19,29 +19,41 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.os.* -import android.os.Build.VERSION.* -import android.os.Build.VERSION_CODES.* -import android.text.* -import android.view.* -import android.view.ViewGroup.LayoutParams.* -import android.widget.* -import com.google.auto.factory.* +import android.content.Context +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES.LOLLIPOP +import android.os.Build.VERSION_CODES.M +import android.os.Handler +import android.os.Looper +import android.text.Layout +import android.text.TextUtils +import android.view.Gravity +import android.view.View +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.TextView +import com.google.auto.factory.AutoFactory +import com.google.auto.factory.Provided import org.isoron.uhabits.R -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* +import org.isoron.uhabits.activities.common.views.RingView +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.ModelObservable +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.utils.dp +import org.isoron.uhabits.utils.sres +import org.isoron.uhabits.utils.toThemedAndroidColor @AutoFactory class HabitCardView( - @Provided @ActivityContext context: Context, - @Provided private val checkmarkPanelFactory: CheckmarkPanelViewFactory, - @Provided private val numberPanelFactory: NumberPanelViewFactory, - @Provided private val behavior: ListHabitsBehavior + @Provided @ActivityContext context: Context, + @Provided private val checkmarkPanelFactory: CheckmarkPanelViewFactory, + @Provided private val numberPanelFactory: NumberPanelViewFactory, + @Provided private val behavior: ListHabitsBehavior ) : FrameLayout(context), ModelObservable.Listener { @@ -228,8 +240,10 @@ class HabitCardView( private fun triggerRipple(x: Float, y: Float) { val background = innerFrame.background if (SDK_INT >= LOLLIPOP) background.setHotspot(x, y) - background.state = intArrayOf(android.R.attr.state_pressed, - android.R.attr.state_enabled) + background.state = intArrayOf( + android.R.attr.state_pressed, + android.R.attr.state_enabled + ) Handler().postDelayed({ background.state = intArrayOf() }, 25) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt index 3f0b9d0ca..f8cf528f7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardViewHolder.kt @@ -19,8 +19,7 @@ package org.isoron.uhabits.activities.habits.list.views -import androidx.appcompat.widget.* -import android.view.* +import android.view.View import androidx.recyclerview.widget.RecyclerView class HabitCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt index 23620da03..b4c8c131b 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.kt @@ -19,24 +19,33 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.graphics.* -import android.os.Build.VERSION.* -import android.os.Build.VERSION_CODES.* -import android.text.* -import android.view.View.MeasureSpec.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.core.utils.DateUtils.* -import org.isoron.uhabits.utils.* -import java.util.* +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF +import android.graphics.Typeface +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES.LOLLIPOP +import android.text.TextPaint +import android.view.View.MeasureSpec.EXACTLY +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.common.views.ScrollableChart +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.utils.DateUtils.formatHeaderDate +import org.isoron.uhabits.core.utils.DateUtils.getStartOfTodayCalendarWithOffset +import org.isoron.uhabits.core.utils.MidnightTimer +import org.isoron.uhabits.utils.dim +import org.isoron.uhabits.utils.dp +import org.isoron.uhabits.utils.isRTL +import org.isoron.uhabits.utils.sres +import org.isoron.uhabits.utils.toMeasureSpec +import java.util.GregorianCalendar class HeaderView( - context: Context, - val prefs: Preferences, - val midnightTimer: MidnightTimer + context: Context, + val prefs: Preferences, + val midnightTimer: MidnightTimer ) : ScrollableChart(context), Preferences.Listener, MidnightTimer.MidnightListener { @@ -121,8 +130,12 @@ class HeaderView( if (isReversed) rect.offset(-(index + 1) * width, 0f) else rect.offset((index - buttonCount) * width, 0f) - if (isRTL()) rect.set(canvas.width - rect.right, rect.top, - canvas.width - rect.left, rect.bottom) + if (isRTL()) rect.set( + canvas.width - rect.right, + rect.top, + canvas.width - rect.left, + rect.bottom + ) val y1 = rect.centerY() - 0.25 * em val y2 = rect.centerY() + 1.25 * em diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt index 8bbbf8ea2..b80255488 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HintView.kt @@ -19,20 +19,21 @@ package org.isoron.uhabits.activities.habits.list.views -import android.animation.* -import android.content.* -import android.graphics.* -import android.graphics.Color.* -import android.view.* -import android.view.ViewGroup.LayoutParams.* -import android.widget.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.utils.* +import android.animation.AnimatorListenerAdapter +import android.content.Context +import android.graphics.Color.WHITE +import android.graphics.Typeface +import android.view.View +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.widget.LinearLayout +import android.widget.TextView +import org.isoron.uhabits.R +import org.isoron.uhabits.core.ui.screens.habits.list.HintList +import org.isoron.uhabits.utils.dp class HintView( - context: Context, - private val hintList: HintList + context: Context, + private val hintList: HintList ) : LinearLayout(context) { val hintContent: TextView diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 5383b28b3..356b0bd46 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -19,18 +19,25 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.graphics.* -import android.text.* -import android.view.* -import android.view.View.* -import com.google.auto.factory.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import android.graphics.Typeface +import android.text.TextPaint +import android.view.View +import android.view.View.OnClickListener +import android.view.View.OnLongClickListener +import com.google.auto.factory.AutoFactory +import com.google.auto.factory.Provided +import org.isoron.uhabits.R +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.utils.InterfaceUtils.getDimension -import java.text.* +import org.isoron.uhabits.utils.StyledResources +import org.isoron.uhabits.utils.getFontAwesome +import org.isoron.uhabits.utils.showMessage +import java.text.DecimalFormat private val BOLD_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.BOLD) private val NORMAL_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.NORMAL) @@ -50,8 +57,8 @@ fun Double.toShortString(): String = when { @AutoFactory class NumberButtonView( - @Provided @ActivityContext context: Context, - @Provided val preferences: Preferences + @Provided @ActivityContext context: Context, + @Provided val preferences: Preferences ) : View(context), OnClickListener, OnLongClickListener { @@ -148,10 +155,10 @@ class NumberButtonView( val label: String val typeface: Typeface - if(value >= 0) { + if (value >= 0) { label = value.toShortString() typeface = BOLD_TYPEFACE - } else if(preferences.areQuestionMarksEnabled()) { + } else if (preferences.areQuestionMarksEnabled()) { label = resources.getString(R.string.fa_question) typeface = getFontAwesome() } else { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt index f9dc47a67..25b17a8c2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt @@ -19,18 +19,19 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import com.google.auto.factory.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* +import android.content.Context +import com.google.auto.factory.AutoFactory +import com.google.auto.factory.Provided +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.ActivityContext @AutoFactory class NumberPanelView( - @Provided @ActivityContext context: Context, - @Provided preferences: Preferences, - @Provided private val buttonFactory: NumberButtonViewFactory + @Provided @ActivityContext context: Context, + @Provided preferences: Preferences, + @Provided private val buttonFactory: NumberButtonViewFactory ) : ButtonPanelView(context, preferences) { var values = DoubleArray(0) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt index bc97fb198..24595277d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/ShadowView.kt @@ -19,11 +19,12 @@ package org.isoron.uhabits.activities.habits.list.views -import android.content.* -import android.view.* -import android.view.View.MeasureSpec.* -import org.isoron.uhabits.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.view.View +import android.view.View.MeasureSpec.EXACTLY +import org.isoron.uhabits.R +import org.isoron.uhabits.utils.dp +import org.isoron.uhabits.utils.toMeasureSpec @Suppress("DEPRECATION") class ShadowView(context: Context) : View(context) { @@ -33,7 +34,9 @@ class ShadowView(context: Context) : View(context) { } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - super.onMeasure(widthMeasureSpec, - dp(2.0f).toInt().toMeasureSpec(EXACTLY)) + super.onMeasure( + widthMeasureSpec, + dp(2.0f).toInt().toMeasureSpec(EXACTLY) + ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index 3b167cf8c..bd1af8215 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -18,17 +18,25 @@ */ package org.isoron.uhabits.activities.habits.show -import android.content.* -import android.os.* -import android.view.* -import androidx.appcompat.app.* -import kotlinx.coroutines.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.activities.common.dialogs.* -import org.isoron.uhabits.core.commands.* -import org.isoron.uhabits.core.ui.screens.habits.show.* -import org.isoron.uhabits.intents.* +import android.content.ContentUris +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.isoron.uhabits.AndroidDirFinder +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.activities.HabitsDirFinder +import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialogFactory +import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory +import org.isoron.uhabits.core.commands.Command +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitBehavior +import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior +import org.isoron.uhabits.intents.IntentFactory class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { @@ -51,41 +59,41 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { view = ShowHabitView(this) presenter = ShowHabitPresenter( - context = this, - habit = habit, - preferences = appComponent.preferences, + context = this, + habit = habit, + preferences = appComponent.preferences, ) val screen = ShowHabitScreen( - activity = this, - confirmDeleteDialogFactory = ConfirmDeleteDialogFactory { this }, - habit = habit, - intentFactory = IntentFactory(), - numberPickerFactory = NumberPickerFactory(this), - widgetUpdater = appComponent.widgetUpdater, + activity = this, + confirmDeleteDialogFactory = ConfirmDeleteDialogFactory { this }, + habit = habit, + intentFactory = IntentFactory(), + numberPickerFactory = NumberPickerFactory(this), + widgetUpdater = appComponent.widgetUpdater, ) val behavior = ShowHabitBehavior( - commandRunner = commandRunner, - habit = habit, - habitList = habitList, - preferences = preferences, - screen = screen, + commandRunner = commandRunner, + habit = habit, + habitList = habitList, + preferences = preferences, + screen = screen, ) val menuBehavior = ShowHabitMenuBehavior( - commandRunner = commandRunner, - habit = habit, - habitList = habitList, - screen = screen, - system = HabitsDirFinder(AndroidDirFinder(this)), - taskRunner = appComponent.taskRunner, + commandRunner = commandRunner, + habit = habit, + habitList = habitList, + screen = screen, + system = HabitsDirFinder(AndroidDirFinder(this)), + taskRunner = appComponent.taskRunner, ) menu = ShowHabitMenu( - activity = this, - behavior = menuBehavior, - preferences = preferences, + activity = this, + behavior = menuBehavior, + preferences = preferences, ) view.onScoreCardSpinnerPosition = behavior::onScoreCardSpinnerPosition @@ -125,4 +133,3 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { } } } - diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitMenu.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitMenu.kt index 6f2db1c08..57783fd6d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitMenu.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitMenu.kt @@ -19,15 +19,16 @@ package org.isoron.uhabits.activities.habits.show -import android.view.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.ui.screens.habits.show.* +import android.view.Menu +import android.view.MenuItem +import org.isoron.uhabits.R +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior class ShowHabitMenu( - val activity: ShowHabitActivity, - val behavior: ShowHabitMenuBehavior, - val preferences: Preferences, + val activity: ShowHabitActivity, + val behavior: ShowHabitMenuBehavior, + val preferences: Preferences, ) { fun onCreateOptionsMenu(menu: Menu): Boolean { activity.menuInflater.inflate(R.menu.show_habit, menu) @@ -38,7 +39,7 @@ class ShowHabitMenu( } fun onOptionsItemSelected(item: MenuItem): Boolean { - when(item.itemId) { + when (item.itemId) { R.id.action_edit_habit -> { behavior.onEditHabit() return true @@ -58,4 +59,4 @@ class ShowHabitMenu( } return false } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.kt index 06232fa71..31d91fd42 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.kt @@ -19,28 +19,32 @@ package org.isoron.uhabits.activities.habits.show -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.common.dialogs.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.ui.callbacks.* -import org.isoron.uhabits.core.ui.screens.habits.list.* -import org.isoron.uhabits.core.ui.screens.habits.show.* -import org.isoron.uhabits.intents.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.* - +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialogFactory +import org.isoron.uhabits.activities.common.dialogs.HistoryEditorDialog +import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback +import org.isoron.uhabits.core.ui.callbacks.OnToggleCheckmarkListener +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitBehavior +import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior +import org.isoron.uhabits.intents.IntentFactory +import org.isoron.uhabits.utils.showMessage +import org.isoron.uhabits.utils.showSendFileScreen +import org.isoron.uhabits.widgets.WidgetUpdater class ShowHabitScreen( - val activity: ShowHabitActivity, - val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, - val habit: Habit, - val intentFactory: IntentFactory, - val numberPickerFactory: NumberPickerFactory, - val widgetUpdater: WidgetUpdater, + val activity: ShowHabitActivity, + val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, + val habit: Habit, + val intentFactory: IntentFactory, + val numberPickerFactory: NumberPickerFactory, + val widgetUpdater: WidgetUpdater, ) : ShowHabitBehavior.Screen, ShowHabitMenuBehavior.Screen { override fun showNumberPicker(value: Double, unit: String, callback: ListHabitsBehavior.NumberPickerCallback) { - numberPickerFactory.create(value, unit, callback).show(); + numberPickerFactory.create(value, unit, callback).show() } override fun updateWidgets() { @@ -81,4 +85,4 @@ class ShowHabitScreen( override fun close() { activity.finish() } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt index 9abb76a5d..562215dc8 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt @@ -19,28 +19,46 @@ package org.isoron.uhabits.activities.habits.show -import android.content.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.activities.habits.show.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.view.LayoutInflater +import android.widget.FrameLayout +import org.isoron.uhabits.activities.habits.show.views.BarCardPresenter +import org.isoron.uhabits.activities.habits.show.views.BarCardViewModel +import org.isoron.uhabits.activities.habits.show.views.FrequencyCardPresenter +import org.isoron.uhabits.activities.habits.show.views.FrequencyCardViewModel +import org.isoron.uhabits.activities.habits.show.views.HistoryCardPresenter +import org.isoron.uhabits.activities.habits.show.views.HistoryCardViewModel +import org.isoron.uhabits.activities.habits.show.views.NotesCardPresenter +import org.isoron.uhabits.activities.habits.show.views.NotesCardViewModel +import org.isoron.uhabits.activities.habits.show.views.OverviewCardPresenter +import org.isoron.uhabits.activities.habits.show.views.OverviewCardViewModel +import org.isoron.uhabits.activities.habits.show.views.ScoreCardPresenter +import org.isoron.uhabits.activities.habits.show.views.ScoreCardViewModel +import org.isoron.uhabits.activities.habits.show.views.StreakCardViewModel +import org.isoron.uhabits.activities.habits.show.views.StreakCartPresenter +import org.isoron.uhabits.activities.habits.show.views.SubtitleCardPresenter +import org.isoron.uhabits.activities.habits.show.views.SubtitleCardViewModel +import org.isoron.uhabits.activities.habits.show.views.TargetCardPresenter +import org.isoron.uhabits.activities.habits.show.views.TargetCardViewModel +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.databinding.ShowHabitBinding +import org.isoron.uhabits.utils.setupToolbar data class ShowHabitViewModel( - val title: String = "", - val isNumerical: Boolean = false, - val color: PaletteColor = PaletteColor(1), - val subtitle: SubtitleCardViewModel, - val overview: OverviewCardViewModel, - val notes: NotesCardViewModel, - val target: TargetCardViewModel, - val streaks: StreakCardViewModel, - val scores: ScoreCardViewModel, - val frequency: FrequencyCardViewModel, - val history: HistoryCardViewModel, - val bar: BarCardViewModel, + val title: String = "", + val isNumerical: Boolean = false, + val color: PaletteColor = PaletteColor(1), + val subtitle: SubtitleCardViewModel, + val overview: OverviewCardViewModel, + val notes: NotesCardViewModel, + val target: TargetCardViewModel, + val streaks: StreakCardViewModel, + val scores: ScoreCardViewModel, + val frequency: FrequencyCardViewModel, + val history: HistoryCardViewModel, + val bar: BarCardViewModel, ) class ShowHabitView(context: Context) : FrameLayout(context) { @@ -80,56 +98,56 @@ class ShowHabitView(context: Context) : FrameLayout(context) { } class ShowHabitPresenter( - val habit: Habit, - val context: Context, - val preferences: Preferences, + val habit: Habit, + val context: Context, + val preferences: Preferences, ) { private val subtitleCardPresenter = SubtitleCardPresenter(habit, context) private val overviewCardPresenter = OverviewCardPresenter(habit) private val notesCardPresenter = NotesCardPresenter(habit) private val targetCardPresenter = TargetCardPresenter( - habit = habit, - firstWeekday = preferences.firstWeekday, - resources = context.resources, + habit = habit, + firstWeekday = preferences.firstWeekday, + resources = context.resources, ) private val streakCartPresenter = StreakCartPresenter(habit) private val scoreCardPresenter = ScoreCardPresenter( - habit = habit, - firstWeekday = preferences.firstWeekday, + habit = habit, + firstWeekday = preferences.firstWeekday, ) private val frequencyCardPresenter = FrequencyCardPresenter( - habit = habit, - firstWeekday = preferences.firstWeekday, + habit = habit, + firstWeekday = preferences.firstWeekday, ) private val historyCardViewModel = HistoryCardPresenter( - habit = habit, - firstWeekday = preferences.firstWeekday, - isSkipEnabled = preferences.isSkipEnabled, + habit = habit, + firstWeekday = preferences.firstWeekday, + isSkipEnabled = preferences.isSkipEnabled, ) private val barCardPresenter = BarCardPresenter( - habit = habit, - firstWeekday = preferences.firstWeekday, + habit = habit, + firstWeekday = preferences.firstWeekday, ) suspend fun present(): ShowHabitViewModel { return ShowHabitViewModel( - title = habit.name, - color = habit.color, - isNumerical = habit.isNumerical, - subtitle = subtitleCardPresenter.present(), - overview = overviewCardPresenter.present(), - notes = notesCardPresenter.present(), - target = targetCardPresenter.present(), - streaks = streakCartPresenter.present(), - scores = scoreCardPresenter.present( - spinnerPosition = preferences.scoreCardSpinnerPosition - ), - frequency = frequencyCardPresenter.present(), - history = historyCardViewModel.present(), - bar = barCardPresenter.present( - boolSpinnerPosition = preferences.barCardBoolSpinnerPosition, - numericalSpinnerPosition = preferences.barCardNumericalSpinnerPosition, - ), + title = habit.name, + color = habit.color, + isNumerical = habit.isNumerical, + subtitle = subtitleCardPresenter.present(), + overview = overviewCardPresenter.present(), + notes = notesCardPresenter.present(), + target = targetCardPresenter.present(), + streaks = streakCartPresenter.present(), + scores = scoreCardPresenter.present( + spinnerPosition = preferences.scoreCardSpinnerPosition + ), + frequency = frequencyCardPresenter.present(), + history = historyCardViewModel.present(), + bar = barCardPresenter.present( + boolSpinnerPosition = preferences.barCardBoolSpinnerPosition, + numericalSpinnerPosition = preferences.barCardNumericalSpinnerPosition, + ), ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.kt index 5189d2dcf..56d6df3c2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCard.kt @@ -18,23 +18,27 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.AdapterView +import android.widget.LinearLayout import org.isoron.uhabits.activities.habits.show.views.ScoreCardPresenter.Companion.getTruncateField -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import org.isoron.uhabits.core.models.Entry +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.databinding.ShowHabitBarBinding +import org.isoron.uhabits.utils.toThemedAndroidColor data class BarCardViewModel( - val entries: List, - val bucketSize: Int, - val color: PaletteColor, - val isNumerical: Boolean, - val numericalSpinnerPosition: Int, - val boolSpinnerPosition: Int, + val entries: List, + val bucketSize: Int, + val color: PaletteColor, + val isNumerical: Boolean, + val numericalSpinnerPosition: Int, + val boolSpinnerPosition: Int, ) class BarCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -78,17 +82,17 @@ class BarCard(context: Context, attrs: AttributeSet) : LinearLayout(context, att } class BarCardPresenter( - val habit: Habit, - val firstWeekday: Int, + val habit: Habit, + val firstWeekday: Int, ) { val numericalBucketSizes = intArrayOf(1, 7, 31, 92, 365) val boolBucketSizes = intArrayOf(7, 31, 92, 365) fun present( - numericalSpinnerPosition: Int, - boolSpinnerPosition: Int, + numericalSpinnerPosition: Int, + boolSpinnerPosition: Int, ): BarCardViewModel { - val bucketSize = if(habit.isNumerical) { + val bucketSize = if (habit.isNumerical) { numericalBucketSizes[numericalSpinnerPosition] } else { boolBucketSizes[boolSpinnerPosition] @@ -101,19 +105,19 @@ class BarCardPresenter( } } else { habit.computedEntries.groupBy( - original = habit.computedEntries.getByInterval(oldest, today), - field = getTruncateField(bucketSize), - firstWeekday = firstWeekday, - isNumerical = habit.isNumerical, + original = habit.computedEntries.getByInterval(oldest, today), + field = getTruncateField(bucketSize), + firstWeekday = firstWeekday, + isNumerical = habit.isNumerical, ) } return BarCardViewModel( - entries = entries, - bucketSize = bucketSize, - color = habit.color, - isNumerical = habit.isNumerical, - numericalSpinnerPosition = numericalSpinnerPosition, - boolSpinnerPosition = boolSpinnerPosition, + entries = entries, + bucketSize = bucketSize, + color = habit.color, + isNumerical = habit.isNumerical, + numericalSpinnerPosition = numericalSpinnerPosition, + boolSpinnerPosition = boolSpinnerPosition, ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt index c424adbaa..fb9719672 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt @@ -18,19 +18,21 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* -import java.util.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.databinding.ShowHabitFrequencyBinding +import org.isoron.uhabits.utils.toThemedAndroidColor +import java.util.HashMap data class FrequencyCardViewModel( - val frequency: HashMap>, - val firstWeekday: Int, - val color: PaletteColor, + val frequency: HashMap>, + val firstWeekday: Int, + val color: PaletteColor, ) class FrequencyCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -47,14 +49,14 @@ class FrequencyCard(context: Context, attrs: AttributeSet) : LinearLayout(contex } class FrequencyCardPresenter( - val habit: Habit, - val firstWeekday: Int, + val habit: Habit, + val firstWeekday: Int, ) { fun present() = FrequencyCardViewModel( - color = habit.color, - frequency = habit.originalEntries.computeWeekdayFrequency( - isNumerical = habit.isNumerical - ), - firstWeekday = firstWeekday, + color = habit.color, + frequency = habit.originalEntries.computeWeekdayFrequency( + isNumerical = habit.isNumerical + ), + firstWeekday = firstWeekday, ) -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.kt index ee218b806..bcea34644 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCard.kt @@ -18,20 +18,21 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.databinding.ShowHabitHistoryBinding +import org.isoron.uhabits.utils.toThemedAndroidColor data class HistoryCardViewModel( - val entries: IntArray, - val color: PaletteColor, - val firstWeekday: Int, - val isNumerical: Boolean, - val isSkipEnabled: Boolean, + val entries: IntArray, + val color: PaletteColor, + val firstWeekday: Int, + val isNumerical: Boolean, + val isSkipEnabled: Boolean, ) class HistoryCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -54,20 +55,19 @@ class HistoryCard(context: Context, attrs: AttributeSet) : LinearLayout(context, if (data.isNumerical) { binding.historyChart.setNumerical(true) } - } } class HistoryCardPresenter( - val habit: Habit, - val firstWeekday: Int, - val isSkipEnabled: Boolean, + val habit: Habit, + val firstWeekday: Int, + val isSkipEnabled: Boolean, ) { fun present() = HistoryCardViewModel( - entries = habit.computedEntries.getAllValues(), - color = habit.color, - firstWeekday = firstWeekday, - isNumerical = habit.isNumerical, - isSkipEnabled = isSkipEnabled, + entries = habit.computedEntries.getAllValues(), + color = habit.color, + firstWeekday = firstWeekday, + isNumerical = habit.isNumerical, + isSkipEnabled = isSkipEnabled, ) -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt index 0bd0fe1d0..50e51d438 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt @@ -19,12 +19,12 @@ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.databinding.ShowHabitNotesBinding data class NotesCardViewModel(val description: String) @@ -43,6 +43,6 @@ class NotesCardView(context: Context, attrs: AttributeSet) : LinearLayout(contex class NotesCardPresenter(val habit: Habit) { fun present() = NotesCardViewModel( - description = habit.description, + description = habit.description, ) -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt index 2e1e2dfdb..cb3a8fce9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt @@ -18,24 +18,27 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* -import kotlinx.coroutines.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.invoke +import org.isoron.uhabits.R import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.databinding.ShowHabitOverviewBinding +import org.isoron.uhabits.utils.StyledResources +import org.isoron.uhabits.utils.toThemedAndroidColor data class OverviewCardViewModel( - val color: PaletteColor, - val scoreMonthDiff: Float, - val scoreYearDiff: Float, - val scoreToday: Float, - val totalCount: Long, + val color: PaletteColor, + val scoreMonthDiff: Float, + val scoreYearDiff: Float, + val scoreToday: Float, + val totalCount: Long, ) class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -43,8 +46,11 @@ class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(con private val binding = ShowHabitOverviewBinding.inflate(LayoutInflater.from(context), this) private fun formatPercentageDiff(percentageDiff: Float): String { - return String.format("%s%.0f%%", if (percentageDiff >= 0) "+" else "\u2212", - Math.abs(percentageDiff) * 100) + return String.format( + "%s%.0f%%", + if (percentageDiff >= 0) "+" else "\u2212", + Math.abs(percentageDiff) * 100 + ) } fun update(data: OverviewCardViewModel) { @@ -76,15 +82,15 @@ class OverviewCardPresenter(val habit: Habit) { val scoreLastMonth = scores.get(lastMonth).value.toFloat() val scoreLastYear = scores.get(lastYear).value.toFloat() val totalCount = habit.originalEntries.getKnown() - .filter { it.value == YES_MANUAL } - .count() - .toLong() + .filter { it.value == YES_MANUAL } + .count() + .toLong() return@IO OverviewCardViewModel( - color = habit.color, - scoreToday = scoreToday, - scoreMonthDiff = scoreToday - scoreLastMonth, - scoreYearDiff = scoreToday - scoreLastYear, - totalCount = totalCount, + color = habit.color, + scoreToday = scoreToday, + scoreMonthDiff = scoreToday - scoreLastMonth, + scoreYearDiff = scoreToday - scoreLastYear, + totalCount = totalCount, ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt index 8687f9fbc..2dcdc9d08 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCard.kt @@ -18,21 +18,29 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.core.utils.DateUtils.TruncateField.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.AdapterView +import android.widget.LinearLayout +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.models.Score +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.core.utils.DateUtils.TruncateField.DAY +import org.isoron.uhabits.core.utils.DateUtils.TruncateField.MONTH +import org.isoron.uhabits.core.utils.DateUtils.TruncateField.QUARTER +import org.isoron.uhabits.core.utils.DateUtils.TruncateField.WEEK_NUMBER +import org.isoron.uhabits.core.utils.DateUtils.TruncateField.YEAR +import org.isoron.uhabits.databinding.ShowHabitScoreBinding +import org.isoron.uhabits.utils.toThemedAndroidColor data class ScoreCardViewModel( - val scores: List, - val bucketSize: Int, - val spinnerPosition: Int, - val color: PaletteColor, + val scores: List, + val bucketSize: Int, + val spinnerPosition: Int, + val color: PaletteColor, ) class ScoreCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -60,8 +68,8 @@ class ScoreCard(context: Context, attrs: AttributeSet) : LinearLayout(context, a } class ScoreCardPresenter( - val habit: Habit, - val firstWeekday: Int, + val habit: Habit, + val firstWeekday: Int, ) { companion object { val BUCKET_SIZES = intArrayOf(1, 7, 31, 92, 365) @@ -86,18 +94,21 @@ class ScoreCardPresenter( val scores = habit.scores.getByInterval(oldest, today).groupBy { DateUtils.truncate(field, it.timestamp, firstWeekday) }.map { (timestamp, scores) -> - Score(timestamp, scores.map { - it.value - }.average()) + Score( + timestamp, + scores.map { + it.value + }.average() + ) }.sortedBy { it.timestamp }.reversed() return ScoreCardViewModel( - color = habit.color, - scores = scores, - bucketSize = bucketSize, - spinnerPosition = spinnerPosition, + color = habit.color, + scores = scores, + bucketSize = bucketSize, + spinnerPosition = spinnerPosition, ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCard.kt index 6035430fa..661cc8484 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCard.kt @@ -18,18 +18,21 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.util.* -import android.view.* -import android.widget.* -import kotlinx.coroutines.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.invoke +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.models.Streak +import org.isoron.uhabits.databinding.ShowHabitStreakBinding +import org.isoron.uhabits.utils.toThemedAndroidColor data class StreakCardViewModel( - val color: PaletteColor, - val bestStreaks: List + val color: PaletteColor, + val bestStreaks: List ) class StreakCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -46,8 +49,8 @@ class StreakCardView(context: Context, attrs: AttributeSet) : LinearLayout(conte class StreakCartPresenter(val habit: Habit) { suspend fun present(): StreakCardViewModel = Dispatchers.IO { return@IO StreakCardViewModel( - color = habit.color, - bestStreaks = habit.streaks.getBest(10), + color = habit.color, + bestStreaks = habit.streaks.getBest(10), ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt index 3ca85ee04..0e70c3e4f 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt @@ -18,26 +18,31 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.annotation.* -import android.content.* -import android.content.res.* -import android.util.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* -import java.util.* +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.Resources +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.LinearLayout +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.habits.list.views.toShortString +import org.isoron.uhabits.core.models.Frequency +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.databinding.ShowHabitSubtitleBinding +import org.isoron.uhabits.utils.InterfaceUtils +import org.isoron.uhabits.utils.formatTime +import org.isoron.uhabits.utils.toThemedAndroidColor +import java.util.Locale data class SubtitleCardViewModel( - val color: PaletteColor, - val frequencyText: String, - val isNumerical: Boolean, - val question: String, - val reminderText: String, - val targetText: String, + val color: PaletteColor, + val frequencyText: String, + val isNumerical: Boolean, + val question: String, + val reminderText: String, + val targetText: String, ) class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -75,8 +80,8 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con } class SubtitleCardPresenter( - val habit: Habit, - val context: Context, + val habit: Habit, + val context: Context, ) { val resources: Resources = context.resources @@ -87,12 +92,12 @@ class SubtitleCardPresenter( resources.getString(R.string.reminder_off) } return SubtitleCardViewModel( - color = habit.color, - frequencyText = habit.frequency.format(), - isNumerical = habit.isNumerical, - question = habit.question, - reminderText = reminderText, - targetText = "${habit.targetValue.toShortString()} ${habit.unit}", + color = habit.color, + frequencyText = habit.frequency.format(), + isNumerical = habit.isNumerical, + question = habit.question, + reminderText = reminderText, + targetText = "${habit.targetValue.toShortString()} ${habit.unit}", ) } @@ -122,12 +127,12 @@ class SubtitleCardPresenter( return resources.getString(R.string.every_x_days, den) } return String.format( - Locale.US, - "%d %s %d %s", - num, - resources.getString(R.string.times_every), - den, - resources.getString(R.string.days), + Locale.US, + "%d %s %d %s", + num, + resources.getString(R.string.times_every), + den, + resources.getString(R.string.days), ) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt index e69483b82..ff44ac4cd 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt @@ -18,24 +18,27 @@ */ package org.isoron.uhabits.activities.habits.show.views -import android.content.* -import android.content.res.* -import android.util.* -import android.view.* -import android.widget.* -import kotlinx.coroutines.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* -import java.util.* +import android.content.Context +import android.content.res.Resources +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.invoke +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.databinding.ShowHabitTargetBinding +import org.isoron.uhabits.utils.toThemedAndroidColor +import java.util.ArrayList +import java.util.Calendar data class TargetCardViewModel( - val color: PaletteColor, - val values: List = listOf(), - val targets: List = listOf(), - val labels: List = listOf(), + val color: PaletteColor, + val values: List = listOf(), + val targets: List = listOf(), + val labels: List = listOf(), ) class TargetCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -52,9 +55,9 @@ class TargetCardView(context: Context, attrs: AttributeSet) : LinearLayout(conte } class TargetCardPresenter( - val habit: Habit, - val firstWeekday: Int, - val resources: Resources, + val habit: Habit, + val firstWeekday: Int, + val resources: Resources, ) { suspend fun present(): TargetCardViewModel = Dispatchers.IO { val today = DateUtils.getTodayWithOffset() @@ -98,10 +101,10 @@ class TargetCardPresenter( labels.add(resources.getString(R.string.year)) return@IO TargetCardViewModel( - color = habit.color, - values = values, - labels = labels, - targets = targets, + color = habit.color, + values = values, + labels = labels, + targets = targets, ) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt index f405a072f..af868aedf 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt @@ -19,11 +19,10 @@ package org.isoron.uhabits.activities.intro -import android.graphics.* -import android.os.* - -import com.github.paolorotolo.appintro.* - +import android.graphics.Color +import android.os.Bundle +import com.github.paolorotolo.appintro.AppIntro2 +import com.github.paolorotolo.appintro.AppIntroFragment import org.isoron.uhabits.R /** @@ -34,17 +33,32 @@ class IntroActivity : AppIntro2() { override fun init(savedInstanceState: Bundle?) { showStatusBar(false) - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_1), - getString(R.string.intro_description_1), R.drawable.intro_icon_1, - Color.parseColor("#194673"))) + addSlide( + AppIntroFragment.newInstance( + getString(R.string.intro_title_1), + getString(R.string.intro_description_1), + R.drawable.intro_icon_1, + Color.parseColor("#194673") + ) + ) - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_2), - getString(R.string.intro_description_2), R.drawable.intro_icon_2, - Color.parseColor("#ffa726"))) + addSlide( + AppIntroFragment.newInstance( + getString(R.string.intro_title_2), + getString(R.string.intro_description_2), + R.drawable.intro_icon_2, + Color.parseColor("#ffa726") + ) + ) - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_4), - getString(R.string.intro_description_4), R.drawable.intro_icon_4, - Color.parseColor("#9575cd"))) + addSlide( + AppIntroFragment.newInstance( + getString(R.string.intro_title_4), + getString(R.string.intro_description_4), + R.drawable.intro_icon_4, + Color.parseColor("#9575cd") + ) + ) } override fun onNextPressed() {} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt index 322cef1c4..cc2d9a497 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt @@ -18,14 +18,15 @@ */ package org.isoron.uhabits.activities.settings -import android.os.* -import android.view.* -import androidx.appcompat.app.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* +import android.os.Bundle +import android.view.LayoutInflater +import androidx.appcompat.app.AppCompatActivity +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.databinding.SettingsActivityBinding +import org.isoron.uhabits.utils.setupToolbar class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -35,10 +36,10 @@ class SettingsActivity : AppCompatActivity() { val binding = SettingsActivityBinding.inflate(LayoutInflater.from(this)) binding.root.setupToolbar( - toolbar = binding.toolbar, - title = resources.getString(R.string.settings), - color = PaletteColor(11), + toolbar = binding.toolbar, + title = resources.getString(R.string.settings), + color = PaletteColor(11), ) setContentView(binding.root) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt index 8152dfb5b..ebe49d4a7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt @@ -19,25 +19,31 @@ package org.isoron.uhabits.activities.sync -import android.content.* +import android.content.ClipData import android.content.ClipboardManager -import android.graphics.* -import android.os.* -import android.text.* -import android.view.* -import androidx.appcompat.app.* -import com.google.zxing.* -import com.google.zxing.qrcode.* -import kotlinx.coroutines.* +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Color +import android.os.Bundle +import android.text.Html +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import com.google.zxing.BarcodeFormat +import com.google.zxing.qrcode.QRCodeWriter +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.invoke +import kotlinx.coroutines.launch +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.ui.screens.sync.SyncBehavior +import org.isoron.uhabits.databinding.ActivitySyncBinding +import org.isoron.uhabits.sync.RemoteSyncServer import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.ui.screens.sync.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.sync.* -import org.isoron.uhabits.utils.* - +import org.isoron.uhabits.utils.setupToolbar +import org.isoron.uhabits.utils.showMessage class SyncActivity : AppCompatActivity(), SyncBehavior.Screen { @@ -57,9 +63,9 @@ class SyncActivity : AppCompatActivity(), SyncBehavior.Screen { binding = ActivitySyncBinding.inflate(layoutInflater) binding.errorIcon.typeface = getFontAwesome(this) binding.root.setupToolbar( - toolbar = binding.toolbar, - color = PaletteColor(11), - title = resources.getString(R.string.device_sync), + toolbar = binding.toolbar, + color = PaletteColor(11), + title = resources.getString(R.string.device_sync), ) binding.syncLink.setOnClickListener { copyToClipboard() } binding.instructions.setText(Html.fromHtml(resources.getString(R.string.sync_instructions))) @@ -100,7 +106,6 @@ class SyncActivity : AppCompatActivity(), SyncBehavior.Screen { binding.progress.visibility = View.GONE binding.qrCode.visibility = View.VISIBLE binding.qrCode.setImageBitmap(generateQR(msg)) - } override suspend fun showLoadingScreen() { @@ -122,4 +127,4 @@ class SyncActivity : AppCompatActivity(), SyncBehavior.Screen { binding.syncLink.text = link showQR(link) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingActivity.kt index 1d266029b..a6d83575c 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingActivity.kt @@ -19,30 +19,31 @@ package org.isoron.uhabits.automation -import android.os.* -import androidx.appcompat.app.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.core.models.* +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.core.models.HabitMatcherBuilder class EditSettingActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val app = applicationContext as HabitsApplication val habits = app.component.habitList.getFiltered( - HabitMatcherBuilder() - .setArchivedAllowed(false) - .setCompletedAllowed(true) - .build()) + HabitMatcherBuilder() + .setArchivedAllowed(false) + .setCompletedAllowed(true) + .build() + ) AndroidThemeSwitcher(this, app.component.preferences).apply() val args = SettingUtils.parseIntent(this.intent, habits) val controller = EditSettingController(this) val view = EditSettingRootView( - context = this, - habitList = app.component.habitList, - onSave = controller::onSave, - args = args, + context = this, + habitList = app.component.habitList, + onSave = controller::onSave, + args = args, ) setContentView(view) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt index f0dc659cc..4991becd9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt @@ -19,11 +19,11 @@ package org.isoron.uhabits.automation -import android.app.* -import android.content.* -import android.os.* +import android.app.Activity +import android.content.Intent +import android.os.Bundle import org.isoron.uhabits.R -import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.models.Habit class EditSettingController(private val activity: Activity) { @@ -36,10 +36,13 @@ class EditSettingController(private val activity: Activity) { bundle.putInt("action", action) bundle.putLong("habit", habit.id!!) - activity.setResult(Activity.RESULT_OK, Intent().apply { - putExtra(EXTRA_STRING_BLURB, blurb) - putExtra(EXTRA_BUNDLE, bundle) - }) + activity.setResult( + Activity.RESULT_OK, + Intent().apply { + putExtra(EXTRA_STRING_BLURB, blurb) + putExtra(EXTRA_BUNDLE, bundle) + } + ) activity.finish() } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt index 8fae1294d..62e3724ad 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt @@ -19,23 +19,29 @@ package org.isoron.uhabits.automation -import android.R.layout.* -import android.annotation.* -import android.content.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.databinding.* -import org.isoron.uhabits.utils.* -import java.util.* +import android.R.layout.simple_spinner_dropdown_item +import android.R.layout.simple_spinner_item +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.FrameLayout +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.databinding.AutomationBinding +import org.isoron.uhabits.utils.setupToolbar +import java.util.LinkedList @SuppressLint("ViewConstructor") class EditSettingRootView( - context: Context, - private val habitList: HabitList, - private val onSave: (habit: Habit, action: Int) -> Unit, - args: SettingUtils.Arguments? + context: Context, + private val habitList: HabitList, + private val onSave: (habit: Habit, action: Int) -> Unit, + args: SettingUtils.Arguments? ) : FrameLayout(context) { private var binding = AutomationBinding.inflate(LayoutInflater.from(context)) @@ -43,10 +49,10 @@ class EditSettingRootView( init { addView(binding.root) setupToolbar( - toolbar = binding.toolbar, - title = resources.getString(R.string.app_name), - color = PaletteColor(11), - displayHomeAsUpEnabled = false, + toolbar = binding.toolbar, + title = resources.getString(R.string.app_name), + color = PaletteColor(11), + displayHomeAsUpEnabled = false, ) populateHabitSpinner() binding.habitSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { @@ -60,8 +66,8 @@ class EditSettingRootView( binding.buttonSave.setOnClickListener { val habit = habitList.getByPosition(binding.habitSpinner.selectedItemPosition) val action = mapSpinnerPositionToAction( - isNumerical = habit.isNumerical, - itemPosition = binding.actionSpinner.selectedItemPosition, + isNumerical = habit.isNumerical, + itemPosition = binding.actionSpinner.selectedItemPosition, ) onSave(habit, action) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/FireSettingReceiver.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/FireSettingReceiver.kt index b4f332f4e..7f2cef03b 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/FireSettingReceiver.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/FireSettingReceiver.kt @@ -19,14 +19,16 @@ package org.isoron.uhabits.automation -import android.content.* -import dagger.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.ui.widgets.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.receivers.* +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import dagger.Component +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.core.ui.widgets.WidgetBehavior +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.HabitsApplicationComponent +import org.isoron.uhabits.receivers.ReceiverScope const val ACTION_CHECK = 0 const val ACTION_UNCHECK = 1 @@ -44,9 +46,9 @@ class FireSettingReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val app = context.applicationContext as HabitsApplication val component = DaggerFireSettingReceiver_ReceiverComponent - .builder() - .habitsApplicationComponent(app.component) - .build() + .builder() + .habitsApplicationComponent(app.component) + .build() allHabits = app.component.habitList val args = SettingUtils.parseIntent(intent, allHabits) ?: return val timestamp = DateUtils.getTodayWithOffset() diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/SettingUtils.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/SettingUtils.kt index 1a56c91b8..1148271dd 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/SettingUtils.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/SettingUtils.kt @@ -15,4 +15,4 @@ object SettingUtils { } class Arguments(var action: Int, var habit: Habit) -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidCursor.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidCursor.kt index 703c43847..18f5efbae 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidCursor.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidCursor.kt @@ -19,7 +19,7 @@ package org.isoron.uhabits.database -import org.isoron.uhabits.core.database.* +import org.isoron.uhabits.core.database.Cursor class AndroidCursor(private val cursor: android.database.Cursor) : Cursor { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabase.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabase.kt index 803eeb423..c699d68b6 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabase.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabase.kt @@ -19,14 +19,14 @@ package org.isoron.uhabits.database -import android.content.* -import android.database.sqlite.* -import org.isoron.uhabits.core.database.* -import java.io.* +import android.content.ContentValues +import android.database.sqlite.SQLiteDatabase +import org.isoron.uhabits.core.database.Database +import java.io.File class AndroidDatabase( - private val db: SQLiteDatabase, - override val file: File?, + private val db: SQLiteDatabase, + override val file: File?, ) : Database { override fun beginTransaction() = db.beginTransaction() @@ -42,10 +42,10 @@ class AndroidDatabase( override fun execute(query: String, vararg params: Any) = db.execSQL(query, params) override fun update( - tableName: String, - values: Map, - where: String, - vararg params: String, + tableName: String, + values: Map, + where: String, + vararg params: String, ): Int { val contValues = mapToContentValues(values) return db.update(tableName, contValues, where, params) @@ -57,9 +57,9 @@ class AndroidDatabase( } override fun delete( - tableName: String, - where: String, - vararg params: String, + tableName: String, + where: String, + vararg params: String, ) { db.delete(tableName, where, params) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabaseOpener.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabaseOpener.kt index 1da591e48..b8d6da46d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabaseOpener.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AndroidDatabaseOpener.kt @@ -19,19 +19,20 @@ package org.isoron.uhabits.database -import android.database.sqlite.* -import org.isoron.uhabits.core.database.* -import java.io.* -import javax.inject.* +import android.database.sqlite.SQLiteDatabase +import org.isoron.uhabits.core.database.DatabaseOpener +import java.io.File +import javax.inject.Inject class AndroidDatabaseOpener @Inject constructor() : DatabaseOpener { override fun open(file: File): AndroidDatabase { return AndroidDatabase( - db = SQLiteDatabase.openDatabase( - file.absolutePath, - null, - SQLiteDatabase.OPEN_READWRITE, - ), - file = file) + db = SQLiteDatabase.openDatabase( + file.absolutePath, + null, + SQLiteDatabase.OPEN_READWRITE, + ), + file = file + ) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AutoBackup.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AutoBackup.kt index 4ea8cfce3..6527b8a51 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AutoBackup.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/database/AutoBackup.kt @@ -19,12 +19,12 @@ package org.isoron.uhabits.database -import android.content.* -import android.util.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.utils.* -import java.io.* +import android.content.Context +import android.util.Log +import org.isoron.uhabits.AndroidDirFinder +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.utils.DatabaseUtils +import java.io.File class AutoBackup(private val context: Context) { @@ -33,7 +33,7 @@ class AutoBackup(private val context: Context) { fun run(keep: Int = 5) { Log.i("AutoBackup", "Starting automatic backups...") val files = listBackupFiles() - var newestTimestamp = 0L; + var newestTimestamp = 0L if (files.isNotEmpty()) { newestTimestamp = files.last().lastModified() } @@ -61,4 +61,4 @@ class AutoBackup(private val context: Context) { } return files } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityContext.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityContext.kt index 64d19f958..12e64d224 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityContext.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityContext.kt @@ -18,9 +18,9 @@ */ package org.isoron.uhabits.inject -import javax.inject.* +import javax.inject.Qualifier @Qualifier @MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.RUNTIME) -annotation class ActivityContext \ No newline at end of file +annotation class ActivityContext diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityScope.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityScope.kt index ab47d9d1e..2bef1f048 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityScope.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/ActivityScope.kt @@ -18,10 +18,10 @@ */ package org.isoron.uhabits.inject -import javax.inject.* +import javax.inject.Scope /** * Scope used by objects that live as long as the activity is alive. */ @Scope -annotation class ActivityScope \ No newline at end of file +annotation class ActivityScope diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/AppContext.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/AppContext.kt index a97b0dba9..5c8d9b0d2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/AppContext.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/AppContext.kt @@ -23,4 +23,4 @@ import javax.inject.Qualifier @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) -annotation class AppContext \ No newline at end of file +annotation class AppContext diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitModule.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitModule.kt index fea9c4c36..4ca1ca73d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitModule.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitModule.kt @@ -19,8 +19,9 @@ package org.isoron.uhabits.inject -import dagger.* -import org.isoron.uhabits.core.models.* +import dagger.Module +import dagger.Provides +import org.isoron.uhabits.core.models.Habit @Module class HabitModule(private val habit: Habit) { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityComponent.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityComponent.kt index d7f7454c8..46a9c652e 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityComponent.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityComponent.kt @@ -19,20 +19,27 @@ package org.isoron.uhabits.inject -import dagger.* -import org.isoron.uhabits.activities.common.dialogs.* -import org.isoron.uhabits.activities.habits.list.* -import org.isoron.uhabits.activities.habits.list.views.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.core.ui.screens.habits.list.* +import dagger.Component +import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory +import org.isoron.uhabits.activities.habits.list.ListHabitsMenu +import org.isoron.uhabits.activities.habits.list.ListHabitsModule +import org.isoron.uhabits.activities.habits.list.ListHabitsRootView +import org.isoron.uhabits.activities.habits.list.ListHabitsScreen +import org.isoron.uhabits.activities.habits.list.ListHabitsSelectionMenu +import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter +import org.isoron.uhabits.core.ui.ThemeSwitcher +import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior @ActivityScope -@Component(modules = arrayOf( +@Component( + modules = arrayOf( ActivityContextModule::class, HabitsActivityModule::class, ListHabitsModule::class, HabitModule::class -), dependencies = arrayOf(HabitsApplicationComponent::class)) + ), + dependencies = arrayOf(HabitsApplicationComponent::class) +) interface HabitsActivityComponent { val colorPickerDialogFactory: ColorPickerDialogFactory val habitCardListAdapter: HabitCardListAdapter diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityModule.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityModule.kt index 464603c4e..e9788dcfb 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityModule.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsActivityModule.kt @@ -19,11 +19,12 @@ package org.isoron.uhabits.inject -import android.content.* -import dagger.* -import org.isoron.uhabits.activities.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.ui.* +import android.content.Context +import dagger.Module +import dagger.Provides +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.ThemeSwitcher @Module class HabitsActivityModule { @@ -31,8 +32,8 @@ class HabitsActivityModule { @Provides @ActivityScope fun getThemeSwitcher( - @ActivityContext context: Context, - prefs: Preferences + @ActivityContext context: Context, + prefs: Preferences ): ThemeSwitcher { return AndroidThemeSwitcher(context, prefs) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsModule.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsModule.kt index 98ce94389..b95ce41db 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsModule.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/inject/HabitsModule.kt @@ -19,28 +19,35 @@ package org.isoron.uhabits.inject -import android.content.* -import dagger.* -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.commands.* -import org.isoron.uhabits.core.database.* -import org.isoron.uhabits.core.io.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.models.sqlite.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.reminders.* -import org.isoron.uhabits.core.sync.* -import org.isoron.uhabits.core.tasks.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.database.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.intents.* -import org.isoron.uhabits.io.* -import org.isoron.uhabits.notifications.* -import org.isoron.uhabits.preferences.* -import org.isoron.uhabits.sync.* -import org.isoron.uhabits.utils.* -import java.io.* +import android.content.Context +import dagger.Module +import dagger.Provides +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.database.Database +import org.isoron.uhabits.core.database.DatabaseOpener +import org.isoron.uhabits.core.io.Logging +import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.core.models.ModelFactory +import org.isoron.uhabits.core.models.sqlite.SQLModelFactory +import org.isoron.uhabits.core.models.sqlite.SQLiteHabitList +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.preferences.WidgetPreferences +import org.isoron.uhabits.core.reminders.ReminderScheduler +import org.isoron.uhabits.core.sync.AbstractSyncServer +import org.isoron.uhabits.core.sync.NetworkManager +import org.isoron.uhabits.core.tasks.TaskRunner +import org.isoron.uhabits.core.ui.NotificationTray +import org.isoron.uhabits.database.AndroidDatabase +import org.isoron.uhabits.database.AndroidDatabaseOpener +import org.isoron.uhabits.intents.IntentScheduler +import org.isoron.uhabits.io.AndroidLogging +import org.isoron.uhabits.notifications.AndroidNotificationTray +import org.isoron.uhabits.preferences.SharedPreferencesStorage +import org.isoron.uhabits.sync.AndroidNetworkManager +import org.isoron.uhabits.sync.RemoteSyncServer +import org.isoron.uhabits.utils.DatabaseUtils +import java.io.File @Module class HabitsModule(dbFile: File) { @@ -56,10 +63,10 @@ class HabitsModule(dbFile: File) { @Provides @AppScope fun getReminderScheduler( - sys: IntentScheduler, - commandRunner: CommandRunner, - habitList: HabitList, - widgetPreferences: WidgetPreferences + sys: IntentScheduler, + commandRunner: CommandRunner, + habitList: HabitList, + widgetPreferences: WidgetPreferences ): ReminderScheduler { return ReminderScheduler(commandRunner, habitList, sys, widgetPreferences) } @@ -67,10 +74,10 @@ class HabitsModule(dbFile: File) { @Provides @AppScope fun getTray( - taskRunner: TaskRunner, - commandRunner: CommandRunner, - preferences: Preferences, - screen: AndroidNotificationTray + taskRunner: TaskRunner, + commandRunner: CommandRunner, + preferences: Preferences, + screen: AndroidNotificationTray ): NotificationTray { return NotificationTray(taskRunner, commandRunner, preferences, screen) } @@ -78,7 +85,7 @@ class HabitsModule(dbFile: File) { @Provides @AppScope fun getWidgetPreferences( - storage: SharedPreferencesStorage + storage: SharedPreferencesStorage ): WidgetPreferences { return WidgetPreferences(storage) } @@ -115,7 +122,7 @@ class HabitsModule(dbFile: File) { @Provides @AppScope - fun getSyncServer(preferences: Preferences) : AbstractSyncServer { + fun getSyncServer(preferences: Preferences): AbstractSyncServer { return RemoteSyncServer(preferences) } @@ -125,4 +132,3 @@ class HabitsModule(dbFile: File) { return db } } - diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt index 520758705..ecab807d0 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt @@ -19,23 +19,24 @@ package org.isoron.uhabits.intents -import android.content.* -import android.net.* -import org.isoron.uhabits.* -import org.isoron.uhabits.activities.about.* -import org.isoron.uhabits.activities.habits.edit.* -import org.isoron.uhabits.activities.habits.show.* -import org.isoron.uhabits.activities.intro.* -import org.isoron.uhabits.activities.settings.* -import org.isoron.uhabits.activities.sync.* -import org.isoron.uhabits.core.models.* -import javax.inject.* +import android.content.Context +import android.content.Intent +import android.net.Uri +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.about.AboutActivity +import org.isoron.uhabits.activities.habits.edit.EditHabitActivity +import org.isoron.uhabits.activities.habits.show.ShowHabitActivity +import org.isoron.uhabits.activities.intro.IntroActivity +import org.isoron.uhabits.activities.settings.SettingsActivity +import org.isoron.uhabits.activities.sync.SyncActivity +import org.isoron.uhabits.core.models.Habit +import javax.inject.Inject class IntentFactory @Inject constructor() { fun helpTranslate(context: Context) = - buildViewIntent(context.getString(R.string.translateURL)) + buildViewIntent(context.getString(R.string.translateURL)) fun openDocument() = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) @@ -43,33 +44,33 @@ class IntentFactory } fun rateApp(context: Context) = - buildViewIntent(context.getString(R.string.playStoreURL)) + buildViewIntent(context.getString(R.string.playStoreURL)) fun sendFeedback(context: Context) = - buildSendToIntent(context.getString(R.string.feedbackURL)) + buildSendToIntent(context.getString(R.string.feedbackURL)) fun privacyPolicy(context: Context) = - buildViewIntent(context.getString(R.string.privacyPolicyURL)) + buildViewIntent(context.getString(R.string.privacyPolicyURL)) fun startAboutActivity(context: Context) = - Intent(context, AboutActivity::class.java) + Intent(context, AboutActivity::class.java) fun startIntroActivity(context: Context) = - Intent(context, IntroActivity::class.java) + Intent(context, IntroActivity::class.java) fun startSettingsActivity(context: Context) = - Intent(context, SettingsActivity::class.java) + Intent(context, SettingsActivity::class.java) fun startShowHabitActivity(context: Context, habit: Habit) = - Intent(context, ShowHabitActivity::class.java).apply { - data = Uri.parse(habit.uriString) - } + Intent(context, ShowHabitActivity::class.java).apply { + data = Uri.parse(habit.uriString) + } fun viewFAQ(context: Context) = - buildViewIntent(context.getString(R.string.helpURL)) + buildViewIntent(context.getString(R.string.helpURL)) fun viewSourceCode(context: Context) = - buildViewIntent(context.getString(R.string.sourceCodeURL)) + buildViewIntent(context.getString(R.string.sourceCodeURL)) private fun buildSendToIntent(url: String) = Intent().apply { action = Intent.ACTION_SENDTO @@ -82,7 +83,7 @@ class IntentFactory } fun codeContributors(context: Context) = - buildViewIntent(context.getString(R.string.codeContributorsURL)) + buildViewIntent(context.getString(R.string.codeContributorsURL)) private fun startEditActivity(context: Context): Intent { return Intent(context, EditHabitActivity::class.java) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentParser.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentParser.kt index 792f43c08..15342bdb9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentParser.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentParser.kt @@ -19,13 +19,15 @@ package org.isoron.uhabits.intents -import android.content.* -import android.content.ContentUris.* -import android.net.* -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import javax.inject.* +import android.content.ContentUris.parseId +import android.content.Intent +import android.net.Uri +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.core.utils.DateUtils +import javax.inject.Inject @AppScope class IntentParser @@ -37,13 +39,13 @@ class IntentParser } fun copyIntentData(source: Intent, destination: Intent) { - destination.data = source.data; + destination.data = source.data destination.putExtra("timestamp", source.getLongExtra("timestamp", DateUtils.getTodayWithOffset().unixTime)) } private fun parseHabit(uri: Uri): Habit { - val habit = habits.getById(parseId(uri)) ?: - throw IllegalArgumentException("habit not found") + val habit = habits.getById(parseId(uri)) + ?: throw IllegalArgumentException("habit not found") return habit } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt index 2aa2eb75e..32ccfcff2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt @@ -19,37 +19,42 @@ package org.isoron.uhabits.intents -import android.app.* -import android.app.AlarmManager.* -import android.content.* -import android.content.Context.* -import android.os.Build.VERSION.* -import android.os.Build.VERSION_CODES.* -import android.util.* -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.reminders.ReminderScheduler.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import java.util.* -import javax.inject.* +import android.app.AlarmManager +import android.app.AlarmManager.RTC +import android.app.AlarmManager.RTC_WAKEUP +import android.app.PendingIntent +import android.content.Context +import android.content.Context.ALARM_SERVICE +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES.M +import android.util.Log +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.reminders.ReminderScheduler.SchedulerResult +import org.isoron.uhabits.core.reminders.ReminderScheduler.SystemScheduler +import org.isoron.uhabits.core.utils.DateFormats +import org.isoron.uhabits.inject.AppContext +import java.util.Date +import javax.inject.Inject @AppScope class IntentScheduler @Inject constructor( - @AppContext context: Context, - private val pendingIntents: PendingIntentFactory + @AppContext context: Context, + private val pendingIntents: PendingIntentFactory ) : SystemScheduler { private val manager = - context.getSystemService(ALARM_SERVICE) as AlarmManager + context.getSystemService(ALARM_SERVICE) as AlarmManager private fun schedule(timestamp: Long, intent: PendingIntent, alarmType: Int): SchedulerResult { val now = System.currentTimeMillis() Log.d("IntentScheduler", "timestamp=$timestamp now=$now") if (timestamp < now) { - Log.e("IntentScheduler", - "Ignoring attempt to schedule intent in the past.") + Log.e( + "IntentScheduler", + "Ignoring attempt to schedule intent in the past." + ) return SchedulerResult.IGNORED } if (SDK_INT >= M) @@ -59,9 +64,11 @@ class IntentScheduler return SchedulerResult.OK } - override fun scheduleShowReminder(reminderTime: Long, - habit: Habit, - timestamp: Long): SchedulerResult { + override fun scheduleShowReminder( + reminderTime: Long, + habit: Habit, + timestamp: Long + ): SchedulerResult { val intent = pendingIntents.showReminder(habit, reminderTime, timestamp) logReminderScheduled(habit, reminderTime) return schedule(reminderTime, intent, RTC_WAKEUP) @@ -81,7 +88,9 @@ class IntentScheduler val name = habit.name.substring(0, min) val df = DateFormats.getBackupDateFormat() val time = df.format(Date(reminderTime)) - Log.i("ReminderHelper", - String.format("Setting alarm (%s): %s", time, name)) + Log.i( + "ReminderHelper", + String.format("Setting alarm (%s): %s", time, name) + ) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt index 6d6222c25..e6c9f7b32 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt @@ -19,111 +19,138 @@ package org.isoron.uhabits.intents -import android.app.* -import android.app.PendingIntent.* -import android.content.* -import android.net.* -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.receivers.* -import javax.inject.* +import android.app.PendingIntent +import android.app.PendingIntent.FLAG_UPDATE_CURRENT +import android.app.PendingIntent.getBroadcast +import android.content.Context +import android.content.Intent +import android.net.Uri +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.inject.AppContext +import org.isoron.uhabits.receivers.ReminderReceiver +import org.isoron.uhabits.receivers.WidgetReceiver +import javax.inject.Inject @AppScope class PendingIntentFactory @Inject constructor( - @AppContext private val context: Context, - private val intentFactory: IntentFactory) { + @AppContext private val context: Context, + private val intentFactory: IntentFactory +) { fun addCheckmark(habit: Habit, timestamp: Timestamp?): PendingIntent = - PendingIntent.getBroadcast( - context, 1, - Intent(context, WidgetReceiver::class.java).apply { - data = Uri.parse(habit.uriString) - action = WidgetReceiver.ACTION_ADD_REPETITION - if (timestamp != null) putExtra("timestamp", timestamp.unixTime) - }, - FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast( + context, + 1, + Intent(context, WidgetReceiver::class.java).apply { + data = Uri.parse(habit.uriString) + action = WidgetReceiver.ACTION_ADD_REPETITION + if (timestamp != null) putExtra("timestamp", timestamp.unixTime) + }, + FLAG_UPDATE_CURRENT + ) fun dismissNotification(habit: Habit): PendingIntent = - PendingIntent.getBroadcast( - context, 0, - Intent(context, ReminderReceiver::class.java).apply { - action = WidgetReceiver.ACTION_DISMISS_REMINDER - data = Uri.parse(habit.uriString) - }, - FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast( + context, + 0, + Intent(context, ReminderReceiver::class.java).apply { + action = WidgetReceiver.ACTION_DISMISS_REMINDER + data = Uri.parse(habit.uriString) + }, + FLAG_UPDATE_CURRENT + ) fun removeRepetition(habit: Habit): PendingIntent = - PendingIntent.getBroadcast( - context, 3, - Intent(context, WidgetReceiver::class.java).apply { - action = WidgetReceiver.ACTION_REMOVE_REPETITION - data = Uri.parse(habit.uriString) - }, - FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast( + context, + 3, + Intent(context, WidgetReceiver::class.java).apply { + action = WidgetReceiver.ACTION_REMOVE_REPETITION + data = Uri.parse(habit.uriString) + }, + FLAG_UPDATE_CURRENT + ) fun showHabit(habit: Habit): PendingIntent = - androidx.core.app.TaskStackBuilder - .create(context) - .addNextIntentWithParentStack( - intentFactory.startShowHabitActivity( - context, habit)) - .getPendingIntent(0, FLAG_UPDATE_CURRENT)!! - - fun showReminder(habit: Habit, - reminderTime: Long?, - timestamp: Long): PendingIntent = - PendingIntent.getBroadcast( + androidx.core.app.TaskStackBuilder + .create(context) + .addNextIntentWithParentStack( + intentFactory.startShowHabitActivity( context, - (habit.id!! % Integer.MAX_VALUE).toInt() + 1, - Intent(context, ReminderReceiver::class.java).apply { - action = ReminderReceiver.ACTION_SHOW_REMINDER - data = Uri.parse(habit.uriString) - putExtra("timestamp", timestamp) - putExtra("reminderTime", reminderTime) - }, - FLAG_UPDATE_CURRENT) + habit + ) + ) + .getPendingIntent(0, FLAG_UPDATE_CURRENT)!! + + fun showReminder( + habit: Habit, + reminderTime: Long?, + timestamp: Long + ): PendingIntent = + PendingIntent.getBroadcast( + context, + (habit.id!! % Integer.MAX_VALUE).toInt() + 1, + Intent(context, ReminderReceiver::class.java).apply { + action = ReminderReceiver.ACTION_SHOW_REMINDER + data = Uri.parse(habit.uriString) + putExtra("timestamp", timestamp) + putExtra("reminderTime", reminderTime) + }, + FLAG_UPDATE_CURRENT + ) fun snoozeNotification(habit: Habit): PendingIntent = - PendingIntent.getBroadcast( - context, 0, - Intent(context, ReminderReceiver::class.java).apply { - data = Uri.parse(habit.uriString) - action = ReminderReceiver.ACTION_SNOOZE_REMINDER - }, - FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast( + context, + 0, + Intent(context, ReminderReceiver::class.java).apply { + data = Uri.parse(habit.uriString) + action = ReminderReceiver.ACTION_SNOOZE_REMINDER + }, + FLAG_UPDATE_CURRENT + ) fun toggleCheckmark(habit: Habit, timestamp: Long?): PendingIntent = - PendingIntent.getBroadcast( - context, 2, - Intent(context, WidgetReceiver::class.java).apply { - data = Uri.parse(habit.uriString) - action = WidgetReceiver.ACTION_TOGGLE_REPETITION - if (timestamp != null) putExtra("timestamp", timestamp) - }, - FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast( + context, + 2, + Intent(context, WidgetReceiver::class.java).apply { + data = Uri.parse(habit.uriString) + action = WidgetReceiver.ACTION_TOGGLE_REPETITION + if (timestamp != null) putExtra("timestamp", timestamp) + }, + FLAG_UPDATE_CURRENT + ) - fun setNumericalValue(widgetContext: Context, - habit: Habit, - numericalValue: Int, - timestamp: Long?): - PendingIntent = + fun setNumericalValue( + widgetContext: Context, + habit: Habit, + numericalValue: Int, + timestamp: Long? + ): + PendingIntent = getBroadcast( - widgetContext, 2, - Intent(widgetContext, WidgetReceiver::class.java).apply { - data = Uri.parse(habit.uriString) - action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE - putExtra("numericalValue", numericalValue); - if (timestamp != null) putExtra("timestamp", timestamp) - }, - FLAG_UPDATE_CURRENT) + widgetContext, + 2, + Intent(widgetContext, WidgetReceiver::class.java).apply { + data = Uri.parse(habit.uriString) + action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE + putExtra("numericalValue", numericalValue) + if (timestamp != null) putExtra("timestamp", timestamp) + }, + FLAG_UPDATE_CURRENT + ) fun updateWidgets(): PendingIntent = - PendingIntent.getBroadcast( - context, 0, - Intent(context, WidgetReceiver::class.java).apply { - action = WidgetReceiver.ACTION_UPDATE_WIDGETS_VALUE - }, - FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast( + context, + 0, + Intent(context, WidgetReceiver::class.java).apply { + action = WidgetReceiver.ACTION_UPDATE_WIDGETS_VALUE + }, + FLAG_UPDATE_CURRENT + ) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/io/AndroidLogging.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/io/AndroidLogging.kt index be89666bd..bb4b0bdba 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/io/AndroidLogging.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/io/AndroidLogging.kt @@ -19,8 +19,9 @@ package org.isoron.uhabits.io -import android.util.* -import org.isoron.uhabits.core.io.* +import android.util.Log +import org.isoron.uhabits.core.io.Logger +import org.isoron.uhabits.core.io.Logging class AndroidLogging : Logging { override fun getLogger(name: String): Logger { @@ -44,5 +45,4 @@ class AndroidLogger(val name: String) : Logger { override fun error(exception: Exception) { Log.e(name, "Exception", exception) } - -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index 8bd602294..c6021cb80 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -19,31 +19,37 @@ package org.isoron.uhabits.notifications -import android.app.* -import android.content.* -import android.graphics.* -import android.graphics.BitmapFactory.* -import android.os.* -import android.os.Build.VERSION.* -import android.util.* -import androidx.core.app.* -import androidx.core.app.NotificationCompat.* +import android.app.Activity +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.graphics.BitmapFactory.decodeResource +import android.graphics.Color +import android.os.Build +import android.os.Build.VERSION.SDK_INT +import android.util.Log +import androidx.core.app.NotificationCompat.Action +import androidx.core.app.NotificationCompat.Builder +import androidx.core.app.NotificationCompat.WearableExtender +import androidx.core.app.NotificationManagerCompat import org.isoron.uhabits.R -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.ui.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.intents.* -import javax.inject.* +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.NotificationTray +import org.isoron.uhabits.inject.AppContext +import org.isoron.uhabits.intents.PendingIntentFactory +import javax.inject.Inject @AppScope class AndroidNotificationTray @Inject constructor( - @AppContext private val context: Context, - private val pendingIntents: PendingIntentFactory, - private val preferences: Preferences, - private val ringtoneManager: RingtoneManager + @AppContext private val context: Context, + private val pendingIntents: PendingIntentFactory, + private val preferences: Preferences, + private val ringtoneManager: RingtoneManager ) : NotificationTray.SystemTray { private var active = HashSet() @@ -57,10 +63,12 @@ class AndroidNotificationTray active.remove(id) } - override fun showNotification(habit: Habit, - notificationId: Int, - timestamp: Timestamp, - reminderTime: Long) { + override fun showNotification( + habit: Habit, + notificationId: Int, + timestamp: Timestamp, + reminderTime: Long + ) { val notificationManager = NotificationManagerCompat.from(context) val notification = buildNotification(habit, reminderTime, timestamp) createAndroidNotificationChannel(context) @@ -68,37 +76,45 @@ class AndroidNotificationTray notificationManager.notify(notificationId, notification) } catch (e: RuntimeException) { // Some Xiaomi phones produce a RuntimeException if custom notification sounds are used. - Log.i("AndroidNotificationTray", - "Failed to show notification. Retrying without sound.") - val n = buildNotification(habit, - reminderTime, - timestamp, - disableSound = true) + Log.i( + "AndroidNotificationTray", + "Failed to show notification. Retrying without sound." + ) + val n = buildNotification( + habit, + reminderTime, + timestamp, + disableSound = true + ) notificationManager.notify(notificationId, n) - } active.add(notificationId) } - fun buildNotification(habit: Habit, - reminderTime: Long, - timestamp: Timestamp, - disableSound: Boolean = false): Notification { + fun buildNotification( + habit: Habit, + reminderTime: Long, + timestamp: Timestamp, + disableSound: Boolean = false + ): Notification { val addRepetitionAction = Action( - R.drawable.ic_action_check, - context.getString(R.string.yes), - pendingIntents.addCheckmark(habit, timestamp)) + R.drawable.ic_action_check, + context.getString(R.string.yes), + pendingIntents.addCheckmark(habit, timestamp) + ) val removeRepetitionAction = Action( - R.drawable.ic_action_cancel, - context.getString(R.string.no), - pendingIntents.removeRepetition(habit)) + R.drawable.ic_action_cancel, + context.getString(R.string.no), + pendingIntents.removeRepetition(habit) + ) val enterAction = Action( - R.drawable.ic_action_check, - context.getString(R.string.enter), - pendingIntents.setNumericalValue(context, habit, 0, null)) + R.drawable.ic_action_check, + context.getString(R.string.enter), + pendingIntents.setNumericalValue(context, habit, 0, null) + ) val wearableBg = decodeResource(context.resources, R.drawable.stripe) @@ -109,26 +125,26 @@ class AndroidNotificationTray val defaultText = context.getString(R.string.default_reminder_question) val builder = Builder(context, REMINDERS_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_notification) - .setContentTitle(habit.name) - .setContentText(if(habit.question.isBlank()) defaultText else habit.question) - .setContentIntent(pendingIntents.showHabit(habit)) - .setDeleteIntent(pendingIntents.dismissNotification(habit)) - .setSound(null) - .setWhen(reminderTime) - .setShowWhen(true) - .setOngoing(preferences.shouldMakeNotificationsSticky()) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle(habit.name) + .setContentText(if (habit.question.isBlank()) defaultText else habit.question) + .setContentIntent(pendingIntents.showHabit(habit)) + .setDeleteIntent(pendingIntents.dismissNotification(habit)) + .setSound(null) + .setWhen(reminderTime) + .setShowWhen(true) + .setOngoing(preferences.shouldMakeNotificationsSticky()) if (habit.isNumerical) { wearableExtender.addAction(enterAction) builder.addAction(enterAction) } else { wearableExtender - .addAction(addRepetitionAction) - .addAction(removeRepetitionAction) + .addAction(addRepetitionAction) + .addAction(removeRepetitionAction) builder - .addAction(addRepetitionAction) - .addAction(removeRepetitionAction) + .addAction(addRepetitionAction) + .addAction(removeRepetitionAction) } if (!disableSound) @@ -137,9 +153,11 @@ class AndroidNotificationTray if (preferences.shouldMakeNotificationsLed()) builder.setLights(Color.RED, 1000, 1000) - val snoozeAction = Action(R.drawable.ic_action_snooze, - context.getString(R.string.snooze), - pendingIntents.snoozeNotification(habit)) + val snoozeAction = Action( + R.drawable.ic_action_snooze, + context.getString(R.string.snooze), + pendingIntents.snoozeNotification(habit) + ) wearableExtender.addAction(snoozeAction) builder.addAction(snoozeAction) @@ -151,14 +169,15 @@ class AndroidNotificationTray private const val REMINDERS_CHANNEL_ID = "REMINDERS" fun createAndroidNotificationChannel(context: Context) { val notificationManager = context.getSystemService(Activity.NOTIFICATION_SERVICE) - as NotificationManager + as NotificationManager if (SDK_INT >= Build.VERSION_CODES.O) { - val channel = NotificationChannel(REMINDERS_CHANNEL_ID, - context.resources.getString(R.string.reminder), - NotificationManager.IMPORTANCE_DEFAULT) + val channel = NotificationChannel( + REMINDERS_CHANNEL_ID, + context.resources.getString(R.string.reminder), + NotificationManager.IMPORTANCE_DEFAULT + ) notificationManager.createNotificationChannel(channel) } } } - } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/RingtoneManager.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/RingtoneManager.kt index 30dca11f6..e45f2acaa 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/RingtoneManager.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/RingtoneManager.kt @@ -19,22 +19,25 @@ package org.isoron.uhabits.notifications -import android.content.* -import android.media.RingtoneManager.* -import android.net.* -import android.preference.* -import android.provider.* +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.media.RingtoneManager.EXTRA_RINGTONE_PICKED_URI +import android.media.RingtoneManager.getRingtone +import android.net.Uri +import android.preference.PreferenceManager +import android.provider.Settings import org.isoron.uhabits.R -import org.isoron.uhabits.core.* -import org.isoron.uhabits.inject.* -import javax.inject.* +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.inject.AppContext +import javax.inject.Inject @AppScope class RingtoneManager @Inject constructor(@AppContext private val context: Context) { val prefs: SharedPreferences = - PreferenceManager.getDefaultSharedPreferences(context) + PreferenceManager.getDefaultSharedPreferences(context) fun getName(): String? { try { @@ -54,8 +57,10 @@ class RingtoneManager fun getURI(): Uri? { var ringtoneUri: Uri? = null val defaultRingtoneUri = Settings.System.DEFAULT_NOTIFICATION_URI - val prefRingtoneUri = prefs.getString("pref_ringtone_uri", - defaultRingtoneUri.toString())!! + val prefRingtoneUri = prefs.getString( + "pref_ringtone_uri", + defaultRingtoneUri.toString() + )!! if (prefRingtoneUri.isNotEmpty()) ringtoneUri = Uri.parse(prefRingtoneUri) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt index 2a942d044..75ace43bd 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt @@ -19,22 +19,23 @@ package org.isoron.uhabits.preferences -import android.content.* -import android.preference.* +import android.content.Context +import android.content.SharedPreferences +import android.preference.PreferenceManager import org.isoron.uhabits.R -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.inject.* -import javax.inject.* +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.inject.AppContext +import javax.inject.Inject @AppScope class SharedPreferencesStorage @Inject constructor( - @AppContext context: Context + @AppContext context: Context ) : SharedPreferences.OnSharedPreferenceChangeListener, Preferences.Storage { private val sharedPrefs: SharedPreferences = - PreferenceManager.getDefaultSharedPreferences(context) + PreferenceManager.getDefaultSharedPreferences(context) private var preferences: Preferences? = null @@ -46,38 +47,40 @@ class SharedPreferencesStorage override fun clear() = sharedPrefs.edit().clear().apply() override fun getBoolean(key: String, defValue: Boolean) = - sharedPrefs.getBoolean(key, defValue) + sharedPrefs.getBoolean(key, defValue) override fun getInt(key: String, defValue: Int) = - sharedPrefs.getInt(key, defValue) + sharedPrefs.getInt(key, defValue) override fun getLong(key: String, defValue: Long) = - sharedPrefs.getLong(key, defValue) + sharedPrefs.getLong(key, defValue) override fun getString(key: String, defValue: String): String = - sharedPrefs.getString(key, defValue)!! + sharedPrefs.getString(key, defValue)!! override fun onAttached(preferences: Preferences) { this.preferences = preferences } override fun putBoolean(key: String, value: Boolean) = - sharedPrefs.edit().putBoolean(key, value).apply() + sharedPrefs.edit().putBoolean(key, value).apply() override fun putInt(key: String, value: Int) = - sharedPrefs.edit().putInt(key, value).apply() + sharedPrefs.edit().putInt(key, value).apply() override fun putLong(key: String, value: Long) = - sharedPrefs.edit().putLong(key, value).apply() + sharedPrefs.edit().putLong(key, value).apply() override fun putString(key: String, value: String) = - sharedPrefs.edit().putString(key, value).apply() + sharedPrefs.edit().putString(key, value).apply() override fun remove(key: String) = - sharedPrefs.edit().remove(key).apply() + sharedPrefs.edit().remove(key).apply() - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, - key: String) { + override fun onSharedPreferenceChanged( + sharedPreferences: SharedPreferences, + key: String + ) { val preferences = this.preferences ?: return sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) when (key) { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/AndroidNetworkManager.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/AndroidNetworkManager.kt index 4b5a2262f..1505d9fec 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/AndroidNetworkManager.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/AndroidNetworkManager.kt @@ -19,12 +19,14 @@ package org.isoron.uhabits.sync -import android.content.* -import android.net.* -import org.isoron.uhabits.core.sync.* +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkRequest +import org.isoron.uhabits.core.sync.NetworkManager class AndroidNetworkManager( - val context: Context, + val context: Context, ) : NetworkManager, ConnectivityManager.NetworkCallback() { val listeners = mutableListOf() @@ -54,4 +56,4 @@ class AndroidNetworkManager( connected = false for (l in listeners) l.onNetworkLost() } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/RemoteSyncServer.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/RemoteSyncServer.kt index 987537217..8184b130a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/RemoteSyncServer.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/sync/RemoteSyncServer.kt @@ -19,21 +19,32 @@ package org.isoron.uhabits.sync -import android.util.* -import io.ktor.client.* -import io.ktor.client.engine.android.* -import io.ktor.client.features.* -import io.ktor.client.features.json.* -import io.ktor.client.request.* -import kotlinx.coroutines.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.sync.* +import android.util.Log +import io.ktor.client.HttpClient +import io.ktor.client.engine.android.Android +import io.ktor.client.features.ClientRequestException +import io.ktor.client.features.ServerResponseException +import io.ktor.client.features.json.JsonFeature +import io.ktor.client.request.get +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.client.request.put +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.invoke +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.sync.AbstractSyncServer +import org.isoron.uhabits.core.sync.EditConflictException +import org.isoron.uhabits.core.sync.GetDataVersionResponse +import org.isoron.uhabits.core.sync.KeyNotFoundException +import org.isoron.uhabits.core.sync.RegisterReponse +import org.isoron.uhabits.core.sync.ServiceUnavailable +import org.isoron.uhabits.core.sync.SyncData class RemoteSyncServer( - private val preferences: Preferences, - private val httpClient: HttpClient = HttpClient(Android) { - install(JsonFeature) - } + private val preferences: Preferences, + private val httpClient: HttpClient = HttpClient(Android) { + install(JsonFeature) + } ) : AbstractSyncServer { override suspend fun register(): String = Dispatchers.IO { @@ -42,7 +53,7 @@ class RemoteSyncServer( Log.i("RemoteSyncServer", "POST $url") val response: RegisterReponse = httpClient.post(url) return@IO response.key - } catch(e: ServerResponseException) { + } catch (e: ServerResponseException) { throw ServiceUnavailable() } } @@ -59,8 +70,8 @@ class RemoteSyncServer( throw ServiceUnavailable() } catch (e: ClientRequestException) { Log.w("RemoteSyncServer", "ClientRequestException", e) - if(e.message!!.contains("409")) throw EditConflictException() - if(e.message!!.contains("404")) throw KeyNotFoundException() + if (e.message!!.contains("409")) throw EditConflictException() + if (e.message!!.contains("404")) throw KeyNotFoundException() throw e } } @@ -85,7 +96,7 @@ class RemoteSyncServer( Log.i("RemoteSyncServer", "GET $url") val response: GetDataVersionResponse = httpClient.get(url) return@IO response.version - } catch(e: ServerResponseException) { + } catch (e: ServerResponseException) { throw ServiceUnavailable() } catch (e: ClientRequestException) { Log.w("RemoteSyncServer", "ClientRequestException", e) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ColorUtils.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ColorUtils.kt index 0510adf6d..054f1fd6c 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ColorUtils.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ColorUtils.kt @@ -55,4 +55,4 @@ object ColorUtils { val f2 = (color2 shr channel and 0xff).toFloat() * (1.0f - amount) return (fl + f2).toInt() and 0xff shl channel } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/DateExtensions.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/DateExtensions.kt index 64f750bbe..1d12a4dd3 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/DateExtensions.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/DateExtensions.kt @@ -19,14 +19,17 @@ package org.isoron.uhabits.utils -import android.content.* +import android.content.Context import android.text.format.DateFormat -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.WeekdayList +import org.isoron.uhabits.core.utils.DateFormats import org.isoron.uhabits.core.utils.DateUtils -import java.text.* -import java.util.* +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale +import java.util.TimeZone fun String.toSimpleDataFormat(): SimpleDateFormat { val locale = Locale.getDefault() @@ -61,4 +64,4 @@ fun formatTime(context: Context, hours: Int, minutes: Int): String? { val df = DateFormat.getTimeFormat(context) df.timeZone = TimeZone.getTimeZone("UTC") return df.format(date) -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/FileUtils.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/FileUtils.kt index 2b1d1922b..c052b8683 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/FileUtils.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/FileUtils.kt @@ -20,8 +20,11 @@ package org.isoron.uhabits.utils import android.os.Environment import android.util.Log -import java.io.* - +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream +import java.io.InputStream +import java.io.OutputStream fun File.copyTo(dst: File) { val inStream = FileInputStream(this) @@ -50,7 +53,7 @@ object FileUtils { Log.e("FileUtils", "getDir: all potential parents are null or non-writable") return null } - val dir = File("${chosenDir.absolutePath}/${relativePath}/") + val dir = File("${chosenDir.absolutePath}/$relativePath/") if (!dir.exists() && !dir.mkdirs()) { Log.e("FileUtils", "getDir: chosen dir does not exist and cannot be created") return null @@ -63,4 +66,4 @@ object FileUtils { val parents = arrayOf(Environment.getExternalStorageDirectory()) return getDir(parents, relativePath) } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.kt index 477598105..be7aa8f40 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.kt @@ -18,13 +18,14 @@ */ package org.isoron.uhabits.utils -import android.content.* -import android.graphics.* -import android.util.* -import android.view.* -import android.widget.* -import android.widget.TextView.* -import androidx.core.view.* +import android.content.Context +import android.graphics.Typeface +import android.util.TypedValue +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import android.widget.TextView.OnEditorActionListener +import androidx.core.view.ViewCompat object InterfaceUtils { private var fontAwesome: Typeface? = null @@ -46,17 +47,21 @@ object InterfaceUtils { @JvmStatic fun dpToPixels(context: Context, dp: Float): Float { if (fixedResolution != null) return dp * fixedResolution!! - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - dp, - context.resources.displayMetrics) + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp, + context.resources.displayMetrics + ) } @JvmStatic fun spToPixels(context: Context, sp: Float): Float { if (fixedResolution != null) return sp * fixedResolution!! - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, - sp, - context.resources.displayMetrics) + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + sp, + context.resources.displayMetrics + ) } @JvmStatic @@ -69,8 +74,10 @@ object InterfaceUtils { return dim } - fun setupEditorAction(parent: ViewGroup, - listener: OnEditorActionListener) { + fun setupEditorAction( + parent: ViewGroup, + listener: OnEditorActionListener + ) { for (i in 0 until parent.childCount) { val child = parent.getChildAt(i) if (child is ViewGroup) setupEditorAction(child, listener) @@ -80,6 +87,6 @@ object InterfaceUtils { fun isLayoutRtl(view: View?): Boolean { return ViewCompat.getLayoutDirection(view!!) == - ViewCompat.LAYOUT_DIRECTION_RTL + ViewCompat.LAYOUT_DIRECTION_RTL } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt index f563275ee..cd9af3b59 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt @@ -3,7 +3,7 @@ package org.isoron.uhabits.utils import android.content.Context import android.graphics.Color import android.util.Log -import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.models.PaletteColor object PaletteUtils { @JvmStatic @@ -22,26 +22,26 @@ fun PaletteColor.toThemedAndroidColor(context: Context): Int { fun PaletteColor.toFixedAndroidColor(): Int { return intArrayOf( - Color.parseColor("#D32F2F"), // 0 red - Color.parseColor("#E64A19"), // 1 deep orange - Color.parseColor("#F57C00"), // 2 orange - Color.parseColor("#FF8F00"), // 3 amber - Color.parseColor("#F9A825"), // 4 yellow - Color.parseColor("#AFB42B"), // 5 lime - Color.parseColor("#7CB342"), // 6 light green - Color.parseColor("#388E3C"), // 7 green - Color.parseColor("#00897B"), // 8 teal - Color.parseColor("#00ACC1"), // 9 cyan - Color.parseColor("#039BE5"), // 10 light blue - Color.parseColor("#1976D2"), // 11 blue - Color.parseColor("#303F9F"), // 12 indigo - Color.parseColor("#5E35B1"), // 13 deep purple - Color.parseColor("#8E24AA"), // 14 purple - Color.parseColor("#D81B60"), // 15 pink - Color.parseColor("#5D4037"), // 16 brown - Color.parseColor("#303030"), // 17 dark grey - Color.parseColor("#757575"), // 18 grey - Color.parseColor("#aaaaaa") // 19 light grey + Color.parseColor("#D32F2F"), // 0 red + Color.parseColor("#E64A19"), // 1 deep orange + Color.parseColor("#F57C00"), // 2 orange + Color.parseColor("#FF8F00"), // 3 amber + Color.parseColor("#F9A825"), // 4 yellow + Color.parseColor("#AFB42B"), // 5 lime + Color.parseColor("#7CB342"), // 6 light green + Color.parseColor("#388E3C"), // 7 green + Color.parseColor("#00897B"), // 8 teal + Color.parseColor("#00ACC1"), // 9 cyan + Color.parseColor("#039BE5"), // 10 light blue + Color.parseColor("#1976D2"), // 11 blue + Color.parseColor("#303F9F"), // 12 indigo + Color.parseColor("#5E35B1"), // 13 deep purple + Color.parseColor("#8E24AA"), // 14 purple + Color.parseColor("#D81B60"), // 15 pink + Color.parseColor("#5D4037"), // 16 brown + Color.parseColor("#303030"), // 17 dark grey + Color.parseColor("#757575"), // 18 grey + Color.parseColor("#aaaaaa") // 19 light grey )[paletteIndex] } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/StyledResources.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/StyledResources.kt index 961bc9749..73639571a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/StyledResources.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/StyledResources.kt @@ -90,4 +90,4 @@ class StyledResources(private val context: Context) { fixedTheme = theme } } -} \ No newline at end of file +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt index 707dd0acd..193dd0f48 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt @@ -19,29 +19,38 @@ package org.isoron.uhabits.utils -import android.app.* -import android.content.* -import android.graphics.* -import android.graphics.drawable.* -import android.os.* -import android.view.* -import android.view.ViewGroup.LayoutParams.* -import android.widget.* -import android.widget.RelativeLayout.* -import androidx.annotation.* -import androidx.appcompat.app.* +import android.app.Activity +import android.content.ActivityNotFoundException +import android.content.Intent +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Handler +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.widget.RelativeLayout +import android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM +import android.widget.RelativeLayout.ALIGN_PARENT_TOP +import android.widget.RelativeLayout.BELOW +import android.widget.TextView +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar -import androidx.core.content.* -import com.google.android.material.snackbar.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.models.* -import java.io.* - -fun RelativeLayout.addBelow(view: View, - subject: View, - width: Int = MATCH_PARENT, - height: Int = WRAP_CONTENT, - applyCustomRules: (params: RelativeLayout.LayoutParams) -> Unit = {}) { +import androidx.core.content.FileProvider +import com.google.android.material.snackbar.Snackbar +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.PaletteColor +import java.io.File + +fun RelativeLayout.addBelow( + view: View, + subject: View, + width: Int = MATCH_PARENT, + height: Int = WRAP_CONTENT, + applyCustomRules: (params: RelativeLayout.LayoutParams) -> Unit = {} +) { view.layoutParams = RelativeLayout.LayoutParams(width, height).apply { addRule(BELOW, subject.id) @@ -51,9 +60,11 @@ fun RelativeLayout.addBelow(view: View, this.addView(view) } -fun RelativeLayout.addAtBottom(view: View, - width: Int = MATCH_PARENT, - height: Int = WRAP_CONTENT) { +fun RelativeLayout.addAtBottom( + view: View, + width: Int = MATCH_PARENT, + height: Int = WRAP_CONTENT +) { view.layoutParams = RelativeLayout.LayoutParams(width, height).apply { addRule(ALIGN_PARENT_BOTTOM) @@ -62,9 +73,11 @@ fun RelativeLayout.addAtBottom(view: View, this.addView(view) } -fun RelativeLayout.addAtTop(view: View, - width: Int = MATCH_PARENT, - height: Int = WRAP_CONTENT) { +fun RelativeLayout.addAtTop( + view: View, + width: Int = MATCH_PARENT, + height: Int = WRAP_CONTENT +) { view.layoutParams = RelativeLayout.LayoutParams(width, height).apply { addRule(ALIGN_PARENT_TOP) @@ -97,12 +110,14 @@ fun Activity.showMessage(msg: String) { fun Activity.showSendFileScreen(archiveFilename: String) { val file = File(archiveFilename) val fileUri = FileProvider.getUriForFile(this, "org.isoron.uhabits", file) - this.startActivity(Intent().apply { - action = Intent.ACTION_SEND - type = "application/zip" - putExtra(Intent.EXTRA_STREAM, fileUri) - flags = Intent.FLAG_GRANT_READ_URI_PERMISSION - }) + this.startActivity( + Intent().apply { + action = Intent.ACTION_SEND + type = "application/zip" + putExtra(Intent.EXTRA_STREAM, fileUri) + flags = Intent.FLAG_GRANT_READ_URI_PERMISSION + } + ) } fun Activity.startActivitySafely(intent: Intent) { @@ -116,32 +131,33 @@ fun Activity.startActivitySafely(intent: Intent) { fun Activity.showSendEmailScreen(@StringRes toId: Int, @StringRes subjectId: Int, content: String?) { val to = this.getString(toId) val subject = this.getString(subjectId) - this.startActivity(Intent().apply { - action = Intent.ACTION_SEND - type = "message/rfc822" - putExtra(Intent.EXTRA_EMAIL, arrayOf(to)) - putExtra(Intent.EXTRA_SUBJECT, subject) - putExtra(Intent.EXTRA_TEXT, content) - }) + this.startActivity( + Intent().apply { + action = Intent.ACTION_SEND + type = "message/rfc822" + putExtra(Intent.EXTRA_EMAIL, arrayOf(to)) + putExtra(Intent.EXTRA_SUBJECT, subject) + putExtra(Intent.EXTRA_TEXT, content) + } + ) } fun Activity.restartWithFade(cls: Class<*>?) { Handler().postDelayed( - { - finish() - overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) - startActivity(Intent(this, cls)) - }, - 500, + { + finish() + overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) + startActivity(Intent(this, cls)) + }, + 500, ) // HACK: Let the menu disappear first } - fun View.setupToolbar( - toolbar: Toolbar, - title: String, - color: PaletteColor, - displayHomeAsUpEnabled: Boolean = true, + toolbar: Toolbar, + title: String, + color: PaletteColor, + displayHomeAsUpEnabled: Boolean = true, ) { toolbar.elevation = InterfaceUtils.dpToPixels(context, 2f) val res = StyledResources(context) @@ -160,10 +176,10 @@ fun View.setupToolbar( } fun Int.toMeasureSpec(mode: Int) = - View.MeasureSpec.makeMeasureSpec(this, mode) + View.MeasureSpec.makeMeasureSpec(this, mode) fun Float.toMeasureSpec(mode: Int) = - View.MeasureSpec.makeMeasureSpec(toInt(), mode) + View.MeasureSpec.makeMeasureSpec(toInt(), mode) fun View.isRTL() = InterfaceUtils.isLayoutRtl(this) fun View.getFontAwesome() = InterfaceUtils.getFontAwesome(context)!! diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt index c09ac580c..45c78509a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt @@ -19,18 +19,19 @@ package org.isoron.uhabits.widgets -import android.app.* -import android.content.* -import android.view.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.views.* +import android.app.PendingIntent +import android.content.Context +import android.view.View +import org.isoron.uhabits.core.models.Entry +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.widgets.views.CheckmarkWidgetView open class CheckmarkWidget( - context: Context, - widgetId: Int, - protected val habit: Habit + context: Context, + widgetId: Int, + protected val habit: Habit ) : BaseWidget(context, widgetId) { override fun getOnClickPendingIntent(context: Context): PendingIntent { @@ -73,5 +74,4 @@ open class CheckmarkWidget( Entry.NO } } - } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetProvider.kt index 7d3f64378..967e0e7b1 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetProvider.kt @@ -18,7 +18,7 @@ */ package org.isoron.uhabits.widgets -import android.content.* +import android.content.Context class CheckmarkWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt index 08e8206a0..24eb8f2ad 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt @@ -19,13 +19,13 @@ package org.isoron.uhabits.widgets -import android.content.* -import android.view.* -import org.isoron.uhabits.widgets.views.* +import android.content.Context +import android.view.View +import org.isoron.uhabits.widgets.views.EmptyWidgetView class EmptyWidget( - context: Context, - widgetId: Int + context: Context, + widgetId: Int ) : BaseWidget(context, widgetId) { override fun getOnClickPendingIntent(context: Context) = null diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt index fc871a9b4..e2a0c73c0 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt @@ -19,22 +19,22 @@ package org.isoron.uhabits.widgets -import android.content.* -import android.view.* -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.views.* +import android.content.Context +import android.view.View +import org.isoron.uhabits.activities.common.views.FrequencyChart +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.widgets.views.GraphWidgetView class FrequencyWidget( - context: Context, - widgetId: Int, - private val habit: Habit, - private val firstWeekday: Int + context: Context, + widgetId: Int, + private val habit: Habit, + private val firstWeekday: Int ) : BaseWidget(context, widgetId) { override fun getOnClickPendingIntent(context: Context) = - pendingIntentFactory.showHabit(habit) + pendingIntentFactory.showHabit(habit) override fun refreshData(v: View) { val widgetView = v as GraphWidgetView @@ -49,7 +49,7 @@ class FrequencyWidget( } override fun buildView() = - GraphWidgetView(context, FrequencyChart(context)) + GraphWidgetView(context, FrequencyChart(context)) override fun getDefaultHeight() = 200 override fun getDefaultWidth() = 200 diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt index 83aedc39c..40a4ba82e 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidgetProvider.kt @@ -19,15 +19,17 @@ package org.isoron.uhabits.widgets -import android.content.* +import android.content.Context class FrequencyWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { val habits = getHabitsFromWidgetId(id) - if (habits.size == 1) return FrequencyWidget(context, - id, - habits[0], - preferences.firstWeekday) + if (habits.size == 1) return FrequencyWidget( + context, + id, + habits[0], + preferences.firstWeekday + ) else return StackWidget(context, id, StackWidgetType.FREQUENCY, habits) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt index 853420f5f..52a932339 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt @@ -19,19 +19,19 @@ package org.isoron.uhabits.widgets -import android.app.* -import android.content.* -import android.view.* -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.views.* +import android.app.PendingIntent +import android.content.Context +import android.view.View +import org.isoron.uhabits.activities.common.views.HistoryChart +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.widgets.views.GraphWidgetView class HistoryWidget( - context: Context, - id: Int, - private val habit: Habit, - private val firstWeekday: Int + context: Context, + id: Int, + private val habit: Habit, + private val firstWeekday: Int ) : BaseWidget(context, id) { override fun getOnClickPendingIntent(context: Context): PendingIntent { @@ -52,9 +52,9 @@ class HistoryWidget( } override fun buildView() = - GraphWidgetView(context, HistoryChart(context)).apply { - setTitle(habit.name) - } + GraphWidgetView(context, HistoryChart(context)).apply { + setTitle(habit.name) + } override fun getDefaultHeight() = 250 override fun getDefaultWidth() = 250 diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt index fe962ce51..9cba71154 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidgetProvider.kt @@ -18,15 +18,17 @@ */ package org.isoron.uhabits.widgets -import android.content.* +import android.content.Context class HistoryWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { val habits = getHabitsFromWidgetId(id) - if (habits.size == 1) return HistoryWidget(context, - id, - habits[0], - preferences.firstWeekday) + if (habits.size == 1) return HistoryWidget( + context, + id, + habits[0], + preferences.firstWeekday + ) else return StackWidget(context, id, StackWidgetType.HISTORY, habits) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt index a3fae10f9..edac3d118 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt @@ -19,23 +19,22 @@ package org.isoron.uhabits.widgets -import android.content.* -import android.view.* -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.activities.habits.show.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.views.* +import android.content.Context +import android.view.View +import org.isoron.uhabits.activities.common.views.ScoreChart +import org.isoron.uhabits.activities.habits.show.views.ScoreCardPresenter +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.widgets.views.GraphWidgetView class ScoreWidget( - context: Context, - id: Int, - private val habit: Habit + context: Context, + id: Int, + private val habit: Habit ) : BaseWidget(context, id) { override fun getOnClickPendingIntent(context: Context) = - pendingIntentFactory.showHabit(habit) + pendingIntentFactory.showHabit(habit) override fun refreshData(view: View) { val presenter = ScoreCardPresenter(habit, prefs.firstWeekday) @@ -52,9 +51,9 @@ class ScoreWidget( } override fun buildView() = - GraphWidgetView(context, ScoreChart(context)).apply { - setTitle(habit.name) - } + GraphWidgetView(context, ScoreChart(context)).apply { + setTitle(habit.name) + } override fun getDefaultHeight() = 300 override fun getDefaultWidth() = 300 diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidgetProvider.kt index 939e23332..61ab93184 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidgetProvider.kt @@ -18,7 +18,7 @@ */ package org.isoron.uhabits.widgets -import android.content.* +import android.content.Context class ScoreWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt index d9b2384fc..dea04b736 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt @@ -19,19 +19,20 @@ package org.isoron.uhabits.widgets -import android.appwidget.* -import android.content.* -import android.net.* -import android.view.* -import android.widget.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* +import android.appwidget.AppWidgetManager +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.view.View +import android.widget.RemoteViews +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.utils.StringUtils class StackWidget( - context: Context, - widgetId: Int, - private val widgetType: StackWidgetType, - private val habits: List + context: Context, + widgetId: Int, + private val widgetType: StackWidgetType, + private val habits: List ) : BaseWidget(context, widgetId) { override fun getOnClickPendingIntent(context: Context) = null @@ -52,8 +53,10 @@ class StackWidget( serviceIntent.data = Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)) remoteViews.setRemoteAdapter(StackWidgetType.getStackWidgetAdapterViewId(widgetType), serviceIntent) manager.notifyAppWidgetViewDataChanged(id, StackWidgetType.getStackWidgetAdapterViewId(widgetType)) - remoteViews.setEmptyView(StackWidgetType.getStackWidgetAdapterViewId(widgetType), - StackWidgetType.getStackWidgetEmptyViewId(widgetType)) + remoteViews.setEmptyView( + StackWidgetType.getStackWidgetAdapterViewId(widgetType), + StackWidgetType.getStackWidgetEmptyViewId(widgetType) + ) return remoteViews } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt index 1343f7c4b..62429da50 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt @@ -19,23 +19,23 @@ package org.isoron.uhabits.widgets -import android.content.* -import android.view.* -import android.view.ViewGroup.* -import android.view.ViewGroup.LayoutParams.* -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.views.* +import android.content.Context +import android.view.View +import android.view.ViewGroup.LayoutParams +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import org.isoron.uhabits.activities.common.views.StreakChart +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.widgets.views.GraphWidgetView class StreakWidget( - context: Context, - id: Int, - private val habit: Habit + context: Context, + id: Int, + private val habit: Habit ) : BaseWidget(context, id) { override fun getOnClickPendingIntent(context: Context) = - pendingIntentFactory.showHabit(habit) + pendingIntentFactory.showHabit(habit) override fun refreshData(view: View) { val widgetView = view as GraphWidgetView diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidgetProvider.kt index 931c924b6..7cf316800 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidgetProvider.kt @@ -18,7 +18,7 @@ */ package org.isoron.uhabits.widgets -import android.content.* +import android.content.Context class StreakWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt index 2053a7a9f..3b3f7a53d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt @@ -19,37 +19,37 @@ package org.isoron.uhabits.widgets -import android.content.* -import android.view.* -import android.view.ViewGroup.* -import android.view.ViewGroup.LayoutParams.* -import kotlinx.coroutines.* -import org.isoron.uhabits.activities.common.views.* -import org.isoron.uhabits.activities.habits.show.views.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.utils.* -import org.isoron.uhabits.widgets.views.* +import android.content.Context +import android.view.View +import android.view.ViewGroup.LayoutParams +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import kotlinx.coroutines.runBlocking +import org.isoron.uhabits.activities.common.views.TargetChart +import org.isoron.uhabits.activities.habits.show.views.TargetCardPresenter +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.widgets.views.GraphWidgetView class TargetWidget( - context: Context, - id: Int, - private val habit: Habit + context: Context, + id: Int, + private val habit: Habit ) : BaseWidget(context, id) { override fun getOnClickPendingIntent(context: Context) = - pendingIntentFactory.showHabit(habit) + pendingIntentFactory.showHabit(habit) override fun refreshData(view: View) = runBlocking { - val widgetView = view as GraphWidgetView - widgetView.setBackgroundAlpha(preferedBackgroundAlpha) - if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) - val chart = (widgetView.dataView as TargetChart) - val presenter = TargetCardPresenter(habit, prefs.firstWeekday, context.resources) - val data = presenter.present() - chart.setColor(data.color.toThemedAndroidColor(context)) - chart.setTargets(data.targets) - chart.setLabels(data.labels) - chart.setValues(data.values) + val widgetView = view as GraphWidgetView + widgetView.setBackgroundAlpha(preferedBackgroundAlpha) + if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) + val chart = (widgetView.dataView as TargetChart) + val presenter = TargetCardPresenter(habit, prefs.firstWeekday, context.resources) + val data = presenter.present() + chart.setColor(data.color.toThemedAndroidColor(context)) + chart.setTargets(data.targets) + chart.setLabels(data.labels) + chart.setValues(data.values) } override fun buildView(): View { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt index 90524c890..2ca5651f6 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt @@ -18,7 +18,7 @@ */ package org.isoron.uhabits.widgets -import android.content.* +import android.content.Context class TargetWidgetProvider : BaseWidgetProvider() { override fun getWidgetFromId(context: Context, id: Int): BaseWidget { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetDimensions.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetDimensions.kt index e017e2106..1647c4fc4 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetDimensions.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetDimensions.kt @@ -19,7 +19,9 @@ package org.isoron.uhabits.widgets -class WidgetDimensions(val portraitWidth: Int, - val portraitHeight: Int, - val landscapeWidth: Int, - val landscapeHeight: Int) \ No newline at end of file +class WidgetDimensions( + val portraitWidth: Int, + val portraitHeight: Int, + val landscapeWidth: Int, + val landscapeHeight: Int +) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt index 5a1f5a065..d49c91f21 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt @@ -19,15 +19,19 @@ package org.isoron.uhabits.widgets -import android.appwidget.* -import android.content.* -import org.isoron.uhabits.core.commands.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.core.tasks.* -import org.isoron.uhabits.core.utils.* -import org.isoron.uhabits.inject.* -import org.isoron.uhabits.intents.* -import javax.inject.* +import android.appwidget.AppWidgetManager +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import org.isoron.uhabits.core.commands.Command +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.commands.CreateRepetitionCommand +import org.isoron.uhabits.core.preferences.WidgetPreferences +import org.isoron.uhabits.core.tasks.TaskRunner +import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.AppContext +import org.isoron.uhabits.intents.IntentScheduler +import javax.inject.Inject /** * A WidgetUpdater listens to the commands being executed by the application and @@ -35,11 +39,11 @@ import javax.inject.* */ class WidgetUpdater @Inject constructor( - @AppContext private val context: Context, - private val commandRunner: CommandRunner, - private val taskRunner: TaskRunner, - private val widgetPrefs: WidgetPreferences, - private val intentScheduler: IntentScheduler + @AppContext private val context: Context, + private val commandRunner: CommandRunner, + private val taskRunner: TaskRunner, + private val widgetPrefs: WidgetPreferences, + private val intentScheduler: IntentScheduler ) : CommandRunner.Listener { override fun onCommandFinished(command: Command) { @@ -69,7 +73,7 @@ class WidgetUpdater fun scheduleStartDayWidgetUpdate() { val timestamp = DateUtils.getStartOfTomorrowWithOffset() - intentScheduler.scheduleWidgetUpdate(timestamp); + intentScheduler.scheduleWidgetUpdate(timestamp) } fun updateWidgets(modifiedHabitId: Long?) { @@ -85,7 +89,8 @@ class WidgetUpdater private fun updateWidgets(modifiedHabitId: Long?, providerClass: Class<*>) { val widgetIds = AppWidgetManager.getInstance(context).getAppWidgetIds( - ComponentName(context, providerClass)) + ComponentName(context, providerClass) + ) val modifiedWidgetIds = when (modifiedHabitId) { null -> widgetIds.toList() @@ -94,10 +99,12 @@ class WidgetUpdater } } - context.sendBroadcast(Intent(context, providerClass).apply { - action = AppWidgetManager.ACTION_APPWIDGET_UPDATE - putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, modifiedWidgetIds.toIntArray()) - }) + context.sendBroadcast( + Intent(context, providerClass).apply { + action = AppWidgetManager.ACTION_APPWIDGET_UPDATE + putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, modifiedWidgetIds.toIntArray()) + } + ) } fun updateWidgets() { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt index d78975771..ae4862952 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt @@ -19,16 +19,21 @@ package org.isoron.uhabits.widgets.activities -import android.app.* -import android.appwidget.AppWidgetManager.* -import android.content.* -import android.os.* -import android.widget.* -import android.widget.AbsListView.* -import org.isoron.uhabits.* -import org.isoron.uhabits.core.preferences.* -import org.isoron.uhabits.widgets.* -import java.util.* +import android.app.Activity +import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID +import android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID +import android.content.Intent +import android.os.Bundle +import android.widget.AbsListView.CHOICE_MODE_MULTIPLE +import android.widget.ArrayAdapter +import android.widget.Button +import android.widget.ListView +import android.widget.TextView +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.core.preferences.WidgetPreferences +import org.isoron.uhabits.widgets.WidgetUpdater +import java.util.ArrayList class BooleanHabitPickerDialog : HabitPickerDialog() { override fun shouldHideNumerical() = true @@ -71,7 +76,7 @@ open class HabitPickerDialog : Activity() { if (habitNames.isEmpty()) { setContentView(R.layout.widget_empty_activity) findViewById(R.id.message).setText(getEmptyMessage()) - return; + return } setContentView(R.layout.widget_configure_activity) @@ -79,9 +84,11 @@ open class HabitPickerDialog : Activity() { val saveButton = findViewById