mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 17:18:52 -06:00
Reformat all Kotlin files with ktlint; add check to build script
This commit is contained in:
@@ -2,6 +2,9 @@ buildscript {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -9,6 +12,7 @@ buildscript {
|
|||||||
classpath "com.neenbedankt.gradle.plugins:android-apt:1.8"
|
classpath "com.neenbedankt.gradle.plugins:android-apt:1.8"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION"
|
||||||
classpath "org.ajoberstar:grgit:1.5.0"
|
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/" }
|
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
apply plugin: "org.jlleitschuh.gradle.ktlint"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ run_adb_as_root() {
|
|||||||
$ADB root
|
$ADB root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lint() {
|
||||||
|
log_info "Running ktlint..."
|
||||||
|
$GRADLE ktlintCheck || fail
|
||||||
|
}
|
||||||
|
|
||||||
build_apk() {
|
build_apk() {
|
||||||
log_info "Removing old APKs..."
|
log_info "Removing old APKs..."
|
||||||
rm -vf build/*.apk
|
rm -vf build/*.apk
|
||||||
@@ -258,6 +263,7 @@ case "$1" in
|
|||||||
build)
|
build)
|
||||||
shift; parse_opts $*
|
shift; parse_opts $*
|
||||||
|
|
||||||
|
lint
|
||||||
build_apk
|
build_apk
|
||||||
build_instrumentation_apk
|
build_instrumentation_apk
|
||||||
run_jvm_tests
|
run_jvm_tests
|
||||||
|
|||||||
@@ -19,12 +19,22 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits
|
package org.isoron.uhabits
|
||||||
|
|
||||||
import dagger.*
|
import dagger.Component
|
||||||
import org.isoron.uhabits.activities.habits.list.*
|
import dagger.Module
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import dagger.Provides
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.activities.habits.list.ListHabitsModule
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.activities.habits.list.views.CheckmarkButtonViewFactory
|
||||||
import org.mockito.Mockito.*
|
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
|
@Module
|
||||||
class TestModule {
|
class TestModule {
|
||||||
@@ -32,13 +42,16 @@ class TestModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
@Component(modules = arrayOf(
|
@Component(
|
||||||
|
modules = arrayOf(
|
||||||
ActivityContextModule::class,
|
ActivityContextModule::class,
|
||||||
HabitsActivityModule::class,
|
HabitsActivityModule::class,
|
||||||
ListHabitsModule::class,
|
ListHabitsModule::class,
|
||||||
HabitModule::class,
|
HabitModule::class,
|
||||||
TestModule::class
|
TestModule::class
|
||||||
), dependencies = arrayOf(HabitsApplicationComponent::class))
|
),
|
||||||
|
dependencies = arrayOf(HabitsApplicationComponent::class)
|
||||||
|
)
|
||||||
interface HabitsActivityTestComponent {
|
interface HabitsActivityTestComponent {
|
||||||
fun getCheckmarkPanelViewFactory(): CheckmarkPanelViewFactory
|
fun getCheckmarkPanelViewFactory(): CheckmarkPanelViewFactory
|
||||||
fun getHabitCardViewFactory(): HabitCardViewFactory
|
fun getHabitCardViewFactory(): HabitCardViewFactory
|
||||||
|
|||||||
@@ -19,11 +19,20 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.acceptance
|
package org.isoron.uhabits.acceptance
|
||||||
|
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.LargeTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||||
import org.isoron.uhabits.acceptance.steps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText
|
||||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
|
||||||
import org.junit.*
|
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
|
@LargeTest
|
||||||
class BackupTest : BaseUserInterfaceTest() {
|
class BackupTest : BaseUserInterfaceTest() {
|
||||||
|
|||||||
@@ -19,10 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.acceptance.steps
|
package org.isoron.uhabits.acceptance.steps
|
||||||
|
|
||||||
import androidx.test.uiautomator.*
|
import androidx.test.uiautomator.UiSelector
|
||||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText
|
||||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.device
|
||||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*
|
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 BACKUP_FOLDER = "/sdcard/Android/data/org.isoron.uhabits/files/Backups/"
|
||||||
const val DOWNLOAD_FOLDER = "/sdcard/Download/"
|
const val DOWNLOAD_FOLDER = "/sdcard/Download/"
|
||||||
|
|||||||
@@ -20,12 +20,13 @@
|
|||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Entry
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.utils.PaletteUtils
|
||||||
import org.junit.*
|
import org.junit.Before
|
||||||
import org.junit.runner.*
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
|||||||
@@ -19,18 +19,20 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.hamcrest.CoreMatchers.*
|
import org.hamcrest.CoreMatchers.equalTo
|
||||||
import org.hamcrest.MatcherAssert.*
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.core.models.*
|
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.NO
|
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_AUTO
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import org.junit.*
|
import org.isoron.uhabits.utils.PaletteUtils
|
||||||
import org.junit.runner.*
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -44,13 +46,15 @@ class EntryPanelViewTest : BaseViewTest() {
|
|||||||
super.setUp()
|
super.setUp()
|
||||||
prefs.isCheckmarkSequenceReversed = false
|
prefs.isCheckmarkSequenceReversed = false
|
||||||
|
|
||||||
val checkmarks = intArrayOf(YES_MANUAL,
|
val checkmarks = intArrayOf(
|
||||||
|
YES_MANUAL,
|
||||||
YES_MANUAL,
|
YES_MANUAL,
|
||||||
YES_AUTO,
|
YES_AUTO,
|
||||||
NO,
|
NO,
|
||||||
NO,
|
NO,
|
||||||
NO,
|
NO,
|
||||||
YES_MANUAL)
|
YES_MANUAL
|
||||||
|
)
|
||||||
|
|
||||||
view = component.getCheckmarkPanelViewFactory().create().apply {
|
view = component.getCheckmarkPanelViewFactory().create().apply {
|
||||||
values = checkmarks
|
values = checkmarks
|
||||||
|
|||||||
@@ -19,22 +19,24 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.junit.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.junit.runner.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class HabitCardViewTest : BaseViewTest() {
|
class HabitCardViewTest : BaseViewTest() {
|
||||||
|
|
||||||
val PATH = "habits/list/HabitCardView"
|
val PATH = "habits/list/HabitCardView"
|
||||||
lateinit private var view: HabitCardView
|
private lateinit var view: HabitCardView
|
||||||
lateinit private var habit1: Habit
|
private lateinit var habit1: Habit
|
||||||
lateinit private var habit2: Habit
|
private lateinit var habit2: Habit
|
||||||
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
|
|||||||
@@ -20,14 +20,14 @@
|
|||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import androidx.test.runner.*
|
import org.hamcrest.CoreMatchers.equalTo
|
||||||
import org.hamcrest.CoreMatchers.*
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
import org.hamcrest.MatcherAssert.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.utils.PaletteUtils
|
||||||
import org.isoron.uhabits.utils.*
|
import org.junit.Before
|
||||||
import org.junit.*
|
import org.junit.Test
|
||||||
import org.junit.runner.*
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
|||||||
@@ -20,15 +20,16 @@
|
|||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import androidx.test.runner.*
|
import org.hamcrest.CoreMatchers.equalTo
|
||||||
import org.hamcrest.CoreMatchers.*
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
import org.hamcrest.MatcherAssert.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.utils.PaletteUtils
|
||||||
import org.isoron.uhabits.utils.*
|
import org.junit.After
|
||||||
import org.junit.*
|
import org.junit.Before
|
||||||
import org.junit.runner.*
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -42,8 +43,14 @@ class NumberPanelViewTest : BaseViewTest() {
|
|||||||
super.setUp()
|
super.setUp()
|
||||||
prefs.isCheckmarkSequenceReversed = false
|
prefs.isCheckmarkSequenceReversed = false
|
||||||
|
|
||||||
val checkmarks = doubleArrayOf(1400.0, 5300.0, 0.0,
|
val checkmarks = doubleArrayOf(
|
||||||
14600.0, 2500.0, 45000.0)
|
1400.0,
|
||||||
|
5300.0,
|
||||||
|
0.0,
|
||||||
|
14600.0,
|
||||||
|
2500.0,
|
||||||
|
45000.0
|
||||||
|
)
|
||||||
|
|
||||||
view = component.getNumberPanelViewFactory().create().apply {
|
view = component.getNumberPanelViewFactory().create().apply {
|
||||||
values = checkmarks
|
values = checkmarks
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.test.ext.junit.runners.*
|
import android.view.View
|
||||||
import androidx.test.filters.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.isoron.uhabits.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.junit.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.runner.*
|
import org.isoron.uhabits.R
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.test.ext.junit.runners.*
|
import android.view.View
|
||||||
import androidx.test.filters.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.isoron.uhabits.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.junit.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.runner.*
|
import org.isoron.uhabits.R
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -39,9 +42,13 @@ class HistoryCardTest : BaseViewTest() {
|
|||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById<View>(R.id.historyCard) as HistoryCard
|
.findViewById<View>(R.id.historyCard) as HistoryCard
|
||||||
view.update(HistoryCardPresenter(habit = habit,
|
view.update(
|
||||||
|
HistoryCardPresenter(
|
||||||
|
habit = habit,
|
||||||
firstWeekday = 1,
|
firstWeekday = 1,
|
||||||
isSkipEnabled = false).present())
|
isSkipEnabled = false
|
||||||
|
).present()
|
||||||
|
)
|
||||||
measureView(view, 800f, 600f)
|
measureView(view, 800f, 600f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,15 +18,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.view.View.*
|
import android.view.View.GONE
|
||||||
import androidx.test.ext.junit.runners.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.hamcrest.Matchers.*
|
import org.hamcrest.Matchers.equalTo
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.*
|
import org.isoron.uhabits.R
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.assertThat
|
||||||
import org.junit.runner.*
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
|||||||
@@ -18,13 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.test.ext.junit.runners.*
|
import android.view.View
|
||||||
import androidx.test.filters.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.isoron.uhabits.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.*
|
import org.isoron.uhabits.R
|
||||||
import org.junit.runner.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -39,13 +42,15 @@ class OverviewCardViewTest : BaseViewTest() {
|
|||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById<View>(R.id.overviewCard) as OverviewCardView
|
.findViewById<View>(R.id.overviewCard) as OverviewCardView
|
||||||
view.update(OverviewCardViewModel(
|
view.update(
|
||||||
|
OverviewCardViewModel(
|
||||||
scoreToday = 0.74f,
|
scoreToday = 0.74f,
|
||||||
scoreMonthDiff = 0.23f,
|
scoreMonthDiff = 0.23f,
|
||||||
scoreYearDiff = 0.74f,
|
scoreYearDiff = 0.74f,
|
||||||
totalCount = 44,
|
totalCount = 44,
|
||||||
color = PaletteColor(7),
|
color = PaletteColor(7),
|
||||||
))
|
)
|
||||||
|
)
|
||||||
measureView(view, 800f, 300f)
|
measureView(view, 800f, 300f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.test.ext.junit.runners.*
|
import android.view.View
|
||||||
import androidx.test.filters.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.isoron.uhabits.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.junit.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.runner.*
|
import org.isoron.uhabits.R
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
|||||||
@@ -18,17 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.test.ext.junit.runners.*
|
import android.view.View
|
||||||
import org.junit.runner.RunWith
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.activities.habits.show.views.StreakCardView
|
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.habits.show.views.StreakCardViewTest
|
import org.junit.Before
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.junit.Test
|
||||||
import org.junit.*
|
import org.junit.runner.RunWith
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -44,10 +42,12 @@ class StreakCardViewTest : BaseViewTest() {
|
|||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById<View>(R.id.streakCard) as StreakCardView
|
.findViewById<View>(R.id.streakCard) as StreakCardView
|
||||||
view.update(StreakCardViewModel(
|
view.update(
|
||||||
|
StreakCardViewModel(
|
||||||
bestStreaks = habit.streaks.getBest(10),
|
bestStreaks = habit.streaks.getBest(10),
|
||||||
color = habit.color,
|
color = habit.color,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
measureView(view, 800f, 600f)
|
measureView(view, 800f, 600f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.test.ext.junit.runners.*
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.R
|
||||||
import org.junit.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.junit.runner.*
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@@ -39,14 +41,16 @@ class SubtitleCardViewTest : BaseViewTest() {
|
|||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById(R.id.subtitleCard)
|
.findViewById(R.id.subtitleCard)
|
||||||
view.update(SubtitleCardViewModel(
|
view.update(
|
||||||
|
SubtitleCardViewModel(
|
||||||
color = PaletteColor(7),
|
color = PaletteColor(7),
|
||||||
frequencyText = "3 times in 7 days",
|
frequencyText = "3 times in 7 days",
|
||||||
isNumerical = false,
|
isNumerical = false,
|
||||||
question = "Did you meditate this morning?",
|
question = "Did you meditate this morning?",
|
||||||
reminderText = "8:30 AM",
|
reminderText = "8:30 AM",
|
||||||
targetText = "",
|
targetText = "",
|
||||||
))
|
)
|
||||||
|
)
|
||||||
measureView(view, 800f, 200f)
|
measureView(view, 800f, 200f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.database
|
package org.isoron.uhabits.database
|
||||||
|
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.AndroidDirFinder
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.BaseAndroidTest
|
||||||
import org.junit.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import java.io.*
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
|
||||||
class AutoBackupTest : BaseAndroidTest() {
|
class AutoBackupTest : BaseAndroidTest() {
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -18,18 +18,27 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.intents
|
package org.isoron.uhabits.intents
|
||||||
|
|
||||||
import android.content.ContentUris.*
|
import android.content.ContentUris.parseId
|
||||||
import androidx.test.ext.junit.runners.*
|
import androidx.test.filters.MediumTest
|
||||||
import androidx.test.filters.*
|
import org.hamcrest.Matchers.equalTo
|
||||||
import org.hamcrest.Matchers.*
|
import org.isoron.uhabits.BaseAndroidTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.core.reminders.ReminderScheduler.SchedulerResult.OK
|
||||||
import org.isoron.uhabits.core.reminders.ReminderScheduler.SchedulerResult.*
|
import org.isoron.uhabits.receivers.ReminderReceiver
|
||||||
import org.isoron.uhabits.receivers.*
|
import org.isoron.uhabits.receivers.WidgetReceiver
|
||||||
import org.junit.*
|
import org.junit.After
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.assertThat
|
||||||
import org.junit.runner.*
|
import org.junit.Before
|
||||||
import java.util.*
|
import org.junit.Test
|
||||||
import java.util.Calendar.*
|
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() {
|
class IntentSchedulerTest : BaseAndroidTest() {
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,23 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.regression
|
package org.isoron.uhabits.regression
|
||||||
|
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.LargeTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.EDIT_HABIT
|
||||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.LIST_HABITS
|
||||||
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.SELECT_HABIT_TYPE
|
||||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText
|
||||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
|
||||||
import org.junit.*
|
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
|
@LargeTest
|
||||||
class ListHabitsRegressionTest : BaseUserInterfaceTest() {
|
class ListHabitsRegressionTest : BaseUserInterfaceTest() {
|
||||||
|
|||||||
@@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.regression
|
package org.isoron.uhabits.regression
|
||||||
|
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.LargeTest
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.*
|
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
|
||||||
import org.isoron.uhabits.activities.about.*
|
import org.isoron.uhabits.activities.about.AboutActivity
|
||||||
import org.junit.*
|
import org.junit.Test
|
||||||
import java.lang.Thread.*
|
import java.lang.Thread.sleep
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
class SavedStateTest : BaseUserInterfaceTest() {
|
class SavedStateTest : BaseUserInterfaceTest() {
|
||||||
|
|||||||
@@ -19,18 +19,29 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.sync
|
package org.isoron.uhabits.sync
|
||||||
|
|
||||||
import androidx.test.filters.*
|
import androidx.test.filters.MediumTest
|
||||||
import com.fasterxml.jackson.databind.*
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.ktor.client.*
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.engine.mock.*
|
import io.ktor.client.engine.mock.MockEngine
|
||||||
import io.ktor.client.features.json.*
|
import io.ktor.client.engine.mock.MockRequestHandleScope
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.engine.mock.respond
|
||||||
import io.ktor.http.*
|
import io.ktor.client.engine.mock.respondError
|
||||||
import junit.framework.Assert.*
|
import io.ktor.client.engine.mock.respondOk
|
||||||
import kotlinx.coroutines.*
|
import io.ktor.client.features.json.JsonFeature
|
||||||
import org.isoron.uhabits.*
|
import io.ktor.client.request.HttpRequestData
|
||||||
import org.isoron.uhabits.core.sync.*
|
import io.ktor.client.request.HttpResponseData
|
||||||
import org.junit.*
|
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
|
@MediumTest
|
||||||
class RemoteSyncServerTest : BaseAndroidTest() {
|
class RemoteSyncServerTest : BaseAndroidTest() {
|
||||||
@@ -115,10 +126,12 @@ class RemoteSyncServerTest : BaseAndroidTest() {
|
|||||||
return@runBlocking
|
return@runBlocking
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun server(expectedPath: String,
|
private fun server(
|
||||||
|
expectedPath: String,
|
||||||
action: MockRequestHandleScope.(HttpRequestData) -> HttpResponseData
|
action: MockRequestHandleScope.(HttpRequestData) -> HttpResponseData
|
||||||
): AbstractSyncServer {
|
): AbstractSyncServer {
|
||||||
return RemoteSyncServer(httpClient = HttpClient(MockEngine) {
|
return RemoteSyncServer(
|
||||||
|
httpClient = HttpClient(MockEngine) {
|
||||||
install(JsonFeature)
|
install(JsonFeature)
|
||||||
engine {
|
engine {
|
||||||
addHandler { request ->
|
addHandler { request ->
|
||||||
@@ -128,10 +141,14 @@ class RemoteSyncServerTest : BaseAndroidTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, preferences = prefs)
|
},
|
||||||
|
preferences = prefs
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MockRequestHandleScope.respondWithJson(content: Any) =
|
private fun MockRequestHandleScope.respondWithJson(content: Any) =
|
||||||
respond(mapper.writeValueAsBytes(content),
|
respond(
|
||||||
headers = headersOf("Content-Type" to listOf("application/json")))
|
mapper.writeValueAsBytes(content),
|
||||||
|
headers = headersOf("Content-Type" to listOf("application/json"))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -18,14 +18,21 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits
|
package org.isoron.uhabits
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.os.*
|
import android.os.Build
|
||||||
import android.view.*
|
import android.os.Environment
|
||||||
import org.isoron.uhabits.inject.*
|
import android.view.WindowManager
|
||||||
import java.io.*
|
import org.isoron.uhabits.inject.AppContext
|
||||||
import java.text.*
|
import java.io.BufferedReader
|
||||||
import java.util.*
|
import java.io.File
|
||||||
import javax.inject.*
|
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) {
|
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?
|
var line: String?
|
||||||
while (true) {
|
while (true) {
|
||||||
line = bufferedReader.readLine()
|
line = bufferedReader.readLine()
|
||||||
if (line == null) break;
|
if (line == null) break
|
||||||
log.addLast(line)
|
log.addLast(line)
|
||||||
if (log.size > maxLineCount) log.removeFirst()
|
if (log.size > maxLineCount) log.removeFirst()
|
||||||
}
|
}
|
||||||
@@ -106,5 +113,4 @@ open class AndroidBugReporter @Inject constructor(@AppContext private val contex
|
|||||||
appendln()
|
appendln()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ package org.isoron.uhabits
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.AppContext
|
||||||
import org.isoron.uhabits.utils.FileUtils
|
import org.isoron.uhabits.utils.FileUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits
|
package org.isoron.uhabits
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
|
|
||||||
class BaseExceptionHandler(private val activity: Activity) : Thread.UncaughtExceptionHandler {
|
class BaseExceptionHandler(private val activity: Activity) : Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
|||||||
@@ -19,16 +19,19 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits
|
package org.isoron.uhabits
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Application
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import org.isoron.uhabits.core.database.*
|
import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException
|
||||||
import org.isoron.uhabits.core.reminders.*
|
import org.isoron.uhabits.core.reminders.ReminderScheduler
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.ui.NotificationTray
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.AppContextModule
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.inject.DaggerHabitsApplicationComponent
|
||||||
import org.isoron.uhabits.widgets.*
|
import org.isoron.uhabits.inject.HabitsApplicationComponent
|
||||||
import java.io.*
|
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.
|
* The Android application for Loop Habit Tracker.
|
||||||
|
|||||||
@@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits
|
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.
|
* An Android BackupAgentHelper customized for this application.
|
||||||
|
|||||||
@@ -21,12 +21,13 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits
|
package org.isoron.uhabits
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.database.sqlite.*
|
import android.database.sqlite.SQLiteDatabase
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper
|
||||||
import org.isoron.uhabits.core.database.*
|
import org.isoron.uhabits.core.database.MigrationHelper
|
||||||
import org.isoron.uhabits.database.*
|
import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException
|
||||||
import java.io.*
|
import org.isoron.uhabits.database.AndroidDatabase
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class HabitsDatabaseOpener(
|
class HabitsDatabaseOpener(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -45,18 +46,22 @@ class HabitsDatabaseOpener(
|
|||||||
db.disableWriteAheadLogging()
|
db.disableWriteAheadLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUpgrade(db: SQLiteDatabase,
|
override fun onUpgrade(
|
||||||
|
db: SQLiteDatabase,
|
||||||
oldVersion: Int,
|
oldVersion: Int,
|
||||||
newVersion: Int) {
|
newVersion: Int
|
||||||
|
) {
|
||||||
db.disableWriteAheadLogging()
|
db.disableWriteAheadLogging()
|
||||||
if (db.version < 8) throw UnsupportedDatabaseVersionException()
|
if (db.version < 8) throw UnsupportedDatabaseVersionException()
|
||||||
val helper = MigrationHelper(AndroidDatabase(db, File(databaseFilename)))
|
val helper = MigrationHelper(AndroidDatabase(db, File(databaseFilename)))
|
||||||
helper.migrateTo(newVersion)
|
helper.migrateTo(newVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDowngrade(db: SQLiteDatabase,
|
override fun onDowngrade(
|
||||||
|
db: SQLiteDatabase,
|
||||||
oldVersion: Int,
|
oldVersion: Int,
|
||||||
newVersion: Int) {
|
newVersion: Int
|
||||||
|
) {
|
||||||
throw UnsupportedDatabaseVersionException()
|
throw UnsupportedDatabaseVersionException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities
|
package org.isoron.uhabits.activities
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.content.res.Configuration.*
|
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
|
||||||
import android.os.Build.VERSION.*
|
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
import androidx.core.content.*
|
import android.os.Build.VERSION.SDK_INT
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.ui.ThemeSwitcher
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
|
import org.isoron.uhabits.inject.ActivityScope
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
class AndroidThemeSwitcher
|
class AndroidThemeSwitcher
|
||||||
@@ -37,12 +39,12 @@ constructor(
|
|||||||
) : ThemeSwitcher(preferences) {
|
) : ThemeSwitcher(preferences) {
|
||||||
|
|
||||||
override fun getSystemTheme(): Int {
|
override fun getSystemTheme(): Int {
|
||||||
if (SDK_INT < 29) return THEME_LIGHT;
|
if (SDK_INT < 29) return THEME_LIGHT
|
||||||
val uiMode = context.resources.configuration.uiMode
|
val uiMode = context.resources.configuration.uiMode
|
||||||
return if ((uiMode and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES) {
|
return if ((uiMode and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES) {
|
||||||
THEME_DARK;
|
THEME_DARK
|
||||||
} else {
|
} else {
|
||||||
THEME_LIGHT;
|
THEME_LIGHT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities
|
package org.isoron.uhabits.activities
|
||||||
|
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.AndroidDirFinder
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.*
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior
|
||||||
import java.io.*
|
import java.io.File
|
||||||
import javax.inject.*
|
import javax.inject.Inject
|
||||||
|
|
||||||
class HabitsDirFinder @Inject
|
class HabitsDirFinder @Inject
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.about
|
package org.isoron.uhabits.activities.about
|
||||||
|
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.activities.*
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity that allows the user to see information about the app itself.
|
* Activity that allows the user to see information about the app itself.
|
||||||
@@ -31,9 +31,11 @@ class AboutActivity : AppCompatActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val app = application as HabitsApplication
|
val app = application as HabitsApplication
|
||||||
val screen = AboutScreen(this,
|
val screen = AboutScreen(
|
||||||
|
this,
|
||||||
app.component.intentFactory,
|
app.component.intentFactory,
|
||||||
app.component.preferences)
|
app.component.preferences
|
||||||
|
)
|
||||||
AndroidThemeSwitcher(this, app.component.preferences).apply()
|
AndroidThemeSwitcher(this, app.component.preferences).apply()
|
||||||
setContentView(AboutView(this, screen))
|
setContentView(AboutView(this, screen))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.about
|
package org.isoron.uhabits.activities.about
|
||||||
|
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.intents.*
|
import org.isoron.uhabits.intents.IntentFactory
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.utils.showMessage
|
||||||
|
import org.isoron.uhabits.utils.startActivitySafely
|
||||||
|
|
||||||
class AboutScreen(
|
class AboutScreen(
|
||||||
private val activity: AboutActivity,
|
private val activity: AboutActivity,
|
||||||
|
|||||||
@@ -18,14 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.about
|
package org.isoron.uhabits.activities.about
|
||||||
|
|
||||||
import android.annotation.*
|
import android.annotation.SuppressLint
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.FrameLayout
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.BuildConfig
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.databinding.AboutBinding
|
||||||
|
import org.isoron.uhabits.utils.setupToolbar
|
||||||
|
|
||||||
@SuppressLint("ViewConstructor")
|
@SuppressLint("ViewConstructor")
|
||||||
class AboutView(
|
class AboutView(
|
||||||
|
|||||||
@@ -19,18 +19,20 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.common.dialogs
|
package org.isoron.uhabits.activities.common.dialogs
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Dialog
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.util.*
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.view.View
|
||||||
import androidx.appcompat.app.*
|
import android.widget.EditText
|
||||||
|
import android.widget.RadioButton
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatDialogFragment
|
||||||
import kotlinx.android.synthetic.main.frequency_picker_dialog.view.*
|
import kotlinx.android.synthetic.main.frequency_picker_dialog.view.*
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.R
|
||||||
|
|
||||||
|
class FrequencyPickerDialog(
|
||||||
class FrequencyPickerDialog(var freqNumerator: Int,
|
var freqNumerator: Int,
|
||||||
var freqDenominator: Int
|
var freqDenominator: Int
|
||||||
) : AppCompatDialogFragment() {
|
) : AppCompatDialogFragment() {
|
||||||
|
|
||||||
|
|||||||
@@ -19,26 +19,31 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.common.dialogs
|
package org.isoron.uhabits.activities.common.dialogs
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import androidx.appcompat.app.*
|
import android.content.DialogInterface
|
||||||
import android.text.*
|
import android.text.InputFilter
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.view.WindowManager.LayoutParams.*
|
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
|
||||||
import android.view.inputmethod.*
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.*
|
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.R
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.utils.InterfaceUtils
|
||||||
import javax.inject.*
|
import javax.inject.Inject
|
||||||
|
|
||||||
class NumberPickerFactory
|
class NumberPickerFactory
|
||||||
@Inject constructor(
|
@Inject constructor(
|
||||||
@ActivityContext private val context: Context
|
@ActivityContext private val context: Context
|
||||||
) {
|
) {
|
||||||
fun create(value: Double,
|
fun create(
|
||||||
|
value: Double,
|
||||||
unit: String,
|
unit: String,
|
||||||
callback: ListHabitsBehavior.NumberPickerCallback): AlertDialog {
|
callback: ListHabitsBehavior.NumberPickerCallback
|
||||||
|
): AlertDialog {
|
||||||
|
|
||||||
val inflater = LayoutInflater.from(context)
|
val inflater = LayoutInflater.from(context)
|
||||||
val view = inflater.inflate(R.layout.number_picker_dialog, null)
|
val view = inflater.inflate(R.layout.number_picker_dialog, null)
|
||||||
@@ -80,11 +85,14 @@ class NumberPickerFactory
|
|||||||
dialog.window?.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
dialog.window?.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
InterfaceUtils.setupEditorAction(picker, TextView.OnEditorActionListener { _, actionId, _ ->
|
InterfaceUtils.setupEditorAction(
|
||||||
|
picker,
|
||||||
|
TextView.OnEditorActionListener { _, actionId, _ ->
|
||||||
if (actionId == EditorInfo.IME_ACTION_DONE)
|
if (actionId == EditorInfo.IME_ACTION_DONE)
|
||||||
dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick()
|
dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick()
|
||||||
false
|
false
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return dialog
|
return dialog
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.common.views
|
package org.isoron.uhabits.activities.common.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.ProgressBar
|
||||||
import org.isoron.uhabits.core.tasks.*
|
import org.isoron.uhabits.core.tasks.Task
|
||||||
|
import org.isoron.uhabits.core.tasks.TaskRunner
|
||||||
|
|
||||||
class TaskProgressBar(
|
class TaskProgressBar(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -31,7 +32,8 @@ class TaskProgressBar(
|
|||||||
context,
|
context,
|
||||||
null,
|
null,
|
||||||
android.R.attr.progressBarStyleHorizontal
|
android.R.attr.progressBarStyleHorizontal
|
||||||
), TaskRunner.Listener {
|
),
|
||||||
|
TaskRunner.Listener {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
visibility = View.GONE
|
visibility = View.GONE
|
||||||
|
|||||||
@@ -19,25 +19,38 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit
|
package org.isoron.uhabits.activities.habits.edit
|
||||||
|
|
||||||
import android.annotation.*
|
import android.annotation.SuppressLint
|
||||||
import android.content.res.*
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.*
|
import android.graphics.Color
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.text.format.*
|
import android.text.format.DateFormat
|
||||||
import android.view.*
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.ArrayAdapter
|
||||||
import androidx.appcompat.app.*
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.android.datetimepicker.time.*
|
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 kotlinx.android.synthetic.main.activity_edit_habit.*
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.activities.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
import org.isoron.uhabits.core.commands.*
|
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.common.dialogs.FrequencyPickerDialog
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.activities.common.dialogs.WeekdayPickerDialog
|
||||||
import org.isoron.uhabits.utils.*
|
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() {
|
class EditHabitActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@@ -159,7 +172,8 @@ class EditHabitActivity : AppCompatActivity() {
|
|||||||
val currentHour = if (reminderHour >= 0) reminderHour else 8
|
val currentHour = if (reminderHour >= 0) reminderHour else 8
|
||||||
val currentMin = if (reminderMin >= 0) reminderMin else 0
|
val currentMin = if (reminderMin >= 0) reminderMin else 0
|
||||||
val is24HourMode = DateFormat.is24HourFormat(this)
|
val is24HourMode = DateFormat.is24HourFormat(this)
|
||||||
val dialog = TimePickerDialog.newInstance(object : TimePickerDialog.OnTimeSetListener {
|
val dialog = TimePickerDialog.newInstance(
|
||||||
|
object : TimePickerDialog.OnTimeSetListener {
|
||||||
override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) {
|
override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) {
|
||||||
reminderHour = hourOfDay
|
reminderHour = hourOfDay
|
||||||
reminderMin = minute
|
reminderMin = minute
|
||||||
@@ -172,7 +186,12 @@ class EditHabitActivity : AppCompatActivity() {
|
|||||||
reminderDays = WeekdayList.EVERY_DAY
|
reminderDays = WeekdayList.EVERY_DAY
|
||||||
populateReminder()
|
populateReminder()
|
||||||
}
|
}
|
||||||
}, currentHour, currentMin, is24HourMode, androidColor)
|
},
|
||||||
|
currentHour,
|
||||||
|
currentMin,
|
||||||
|
is24HourMode,
|
||||||
|
androidColor
|
||||||
|
)
|
||||||
dialog.show(supportFragmentManager, "timePicker")
|
dialog.show(supportFragmentManager, "timePicker")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,12 +247,14 @@ class EditHabitActivity : AppCompatActivity() {
|
|||||||
EditHabitCommand(
|
EditHabitCommand(
|
||||||
component.habitList,
|
component.habitList,
|
||||||
habitId,
|
habitId,
|
||||||
habit)
|
habit
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
CreateHabitCommand(
|
CreateHabitCommand(
|
||||||
component.modelFactory,
|
component.modelFactory,
|
||||||
component.habitList,
|
component.habitList,
|
||||||
habit)
|
habit
|
||||||
|
)
|
||||||
}
|
}
|
||||||
component.commandRunner.run(command)
|
component.commandRunner.run(command)
|
||||||
finish()
|
finish()
|
||||||
|
|||||||
@@ -19,20 +19,24 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.edit
|
package org.isoron.uhabits.activities.habits.edit
|
||||||
|
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.appcompat.app.*
|
import android.view.View
|
||||||
import org.isoron.uhabits.*
|
import android.view.ViewGroup
|
||||||
import org.isoron.uhabits.core.models.*
|
import androidx.appcompat.app.AppCompatDialogFragment
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.intents.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.databinding.SelectHabitTypeBinding
|
||||||
|
import org.isoron.uhabits.intents.IntentFactory
|
||||||
|
|
||||||
class HabitTypeDialog : AppCompatDialogFragment() {
|
class HabitTypeDialog : AppCompatDialogFragment() {
|
||||||
override fun getTheme() = R.style.Translucent
|
override fun getTheme() = R.style.Translucent
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater,
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?): View? {
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
val binding = SelectHabitTypeBinding.inflate(inflater, container, false)
|
val binding = SelectHabitTypeBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
binding.buttonYesNo.setOnClickListener {
|
binding.buttonYesNo.setOnClickListener {
|
||||||
|
|||||||
@@ -19,22 +19,26 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list
|
package org.isoron.uhabits.activities.habits.list
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Intent
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
import androidx.appcompat.app.*
|
import android.view.MenuItem
|
||||||
import kotlinx.coroutines.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import org.isoron.uhabits.activities.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import kotlinx.coroutines.launch
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.BaseExceptionHandler
|
||||||
import org.isoron.uhabits.core.sync.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.core.tasks.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
|
||||||
import org.isoron.uhabits.core.ui.ThemeSwitcher.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.sync.SyncManager
|
||||||
import org.isoron.uhabits.database.*
|
import org.isoron.uhabits.core.tasks.TaskRunner
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.ui.ThemeSwitcher.THEME_DARK
|
||||||
import org.isoron.uhabits.utils.*
|
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() {
|
class ListHabitsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,18 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list
|
package org.isoron.uhabits.activities.habits.list
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
import androidx.appcompat.app.*
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.ui.ThemeSwitcher
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsMenuBehavior
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.inject.ActivityScope
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
class ListHabitsMenu @Inject constructor(
|
class ListHabitsMenu @Inject constructor(
|
||||||
|
|||||||
@@ -19,14 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list
|
package org.isoron.uhabits.activities.habits.list
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import dagger.*
|
import dagger.Binds
|
||||||
import org.isoron.uhabits.*
|
import dagger.Module
|
||||||
import org.isoron.uhabits.activities.*
|
import org.isoron.uhabits.AndroidBugReporter
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import org.isoron.uhabits.activities.HabitsDirFinder
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
import javax.inject.*
|
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
|
class BugReporterProxy
|
||||||
@Inject constructor(
|
@Inject constructor(
|
||||||
|
|||||||
@@ -19,21 +19,38 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list
|
package org.isoron.uhabits.activities.habits.list
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.ViewGroup.LayoutParams.*
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.widget.*
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.RelativeLayout
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.common.views.*
|
import org.isoron.uhabits.activities.common.views.ScrollableChart
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import org.isoron.uhabits.activities.common.views.TaskProgressBar
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.habits.list.views.EmptyListView
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
|
||||||
import org.isoron.uhabits.core.tasks.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListView
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListViewFactory
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.activities.habits.list.views.HeaderView
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.activities.habits.list.views.HintView
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.models.ModelObservable
|
||||||
import java.lang.Math.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import javax.inject.*
|
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
|
const val MAX_CHECKMARK_COUNT = 60
|
||||||
|
|
||||||
@@ -86,11 +103,13 @@ class ListHabitsRootView @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupControllers() {
|
private fun setupControllers() {
|
||||||
header.setScrollController(object : ScrollableChart.ScrollController {
|
header.setScrollController(
|
||||||
|
object : ScrollableChart.ScrollController {
|
||||||
override fun onDataOffsetChanged(newDataOffset: Int) {
|
override fun onDataOffsetChanged(newDataOffset: Int) {
|
||||||
listView.dataOffset = newDataOffset
|
listView.dataOffset = newDataOffset
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
|
|||||||
@@ -19,29 +19,58 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list
|
package org.isoron.uhabits.activities.habits.list
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.content.Intent
|
||||||
import androidx.annotation.*
|
import android.util.Log
|
||||||
import androidx.appcompat.app.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import dagger.*
|
import dagger.Lazy
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*
|
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
|
||||||
import org.isoron.uhabits.activities.habits.edit.*
|
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialogFactory
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import org.isoron.uhabits.activities.common.dialogs.ConfirmSyncKeyDialogFactory
|
||||||
import org.isoron.uhabits.core.commands.*
|
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.habits.edit.HabitTypeDialog
|
||||||
import org.isoron.uhabits.core.tasks.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.commands.ArchiveHabitsCommand
|
||||||
import org.isoron.uhabits.core.ui.callbacks.*
|
import org.isoron.uhabits.core.commands.ChangeHabitColorCommand
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.commands.Command
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.*
|
import org.isoron.uhabits.core.commands.CommandRunner
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.commands.CreateHabitCommand
|
||||||
import org.isoron.uhabits.intents.*
|
import org.isoron.uhabits.core.commands.DeleteHabitsCommand
|
||||||
import org.isoron.uhabits.tasks.*
|
import org.isoron.uhabits.core.commands.EditHabitCommand
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand
|
||||||
import java.io.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import javax.inject.*
|
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_IMPORT_DATA = 101
|
||||||
const val RESULT_EXPORT_CSV = 102
|
const val RESULT_EXPORT_CSV = 102
|
||||||
@@ -172,7 +201,9 @@ class ListHabitsScreen
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showMessage(m: ListHabitsBehavior.Message) {
|
override fun showMessage(m: ListHabitsBehavior.Message) {
|
||||||
activity.showMessage(activity.resources.getString(when (m) {
|
activity.showMessage(
|
||||||
|
activity.resources.getString(
|
||||||
|
when (m) {
|
||||||
COULD_NOT_EXPORT -> R.string.could_not_export
|
COULD_NOT_EXPORT -> R.string.could_not_export
|
||||||
IMPORT_SUCCESSFUL -> R.string.habits_imported
|
IMPORT_SUCCESSFUL -> R.string.habits_imported
|
||||||
IMPORT_FAILED -> R.string.could_not_import
|
IMPORT_FAILED -> R.string.could_not_import
|
||||||
@@ -181,7 +212,9 @@ class ListHabitsScreen
|
|||||||
FILE_NOT_RECOGNIZED -> R.string.file_not_recognized
|
FILE_NOT_RECOGNIZED -> R.string.file_not_recognized
|
||||||
SYNC_ENABLED -> R.string.sync_enabled
|
SYNC_ENABLED -> R.string.sync_enabled
|
||||||
SYNC_KEY_ALREADY_INSTALLED -> R.string.sync_key_already_installed
|
SYNC_KEY_ALREADY_INSTALLED -> R.string.sync_key_already_installed
|
||||||
}))
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showSendBugReportToDeveloperScreen(log: String) {
|
override fun showSendBugReportToDeveloperScreen(log: String) {
|
||||||
@@ -199,16 +232,20 @@ class ListHabitsScreen
|
|||||||
activity.startActivityForResult(intent, REQUEST_SETTINGS)
|
activity.startActivityForResult(intent, REQUEST_SETTINGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showColorPicker(defaultColor: PaletteColor,
|
override fun showColorPicker(
|
||||||
callback: OnColorPickedCallback) {
|
defaultColor: PaletteColor,
|
||||||
|
callback: OnColorPickedCallback
|
||||||
|
) {
|
||||||
val picker = colorPickerFactory.create(defaultColor)
|
val picker = colorPickerFactory.create(defaultColor)
|
||||||
picker.setListener(callback)
|
picker.setListener(callback)
|
||||||
picker.show(activity.supportFragmentManager, "picker")
|
picker.show(activity.supportFragmentManager, "picker")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showNumberPicker(value: Double,
|
override fun showNumberPicker(
|
||||||
|
value: Double,
|
||||||
unit: String,
|
unit: String,
|
||||||
callback: ListHabitsBehavior.NumberPickerCallback) {
|
callback: ListHabitsBehavior.NumberPickerCallback
|
||||||
|
) {
|
||||||
numberPickerFactory.create(value, unit, callback).show()
|
numberPickerFactory.create(value, unit, callback).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,33 +256,42 @@ class ListHabitsScreen
|
|||||||
private fun getExecuteString(command: Command): String? {
|
private fun getExecuteString(command: Command): String? {
|
||||||
when (command) {
|
when (command) {
|
||||||
is ArchiveHabitsCommand -> {
|
is ArchiveHabitsCommand -> {
|
||||||
return activity.resources.getQuantityString(R.plurals.toast_habits_archived,
|
return activity.resources.getQuantityString(
|
||||||
command.selected.size)
|
R.plurals.toast_habits_archived,
|
||||||
|
command.selected.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is ChangeHabitColorCommand -> {
|
is ChangeHabitColorCommand -> {
|
||||||
return activity.resources.getQuantityString(R.plurals.toast_habits_changed,
|
return activity.resources.getQuantityString(
|
||||||
command.selected.size)
|
R.plurals.toast_habits_changed,
|
||||||
|
command.selected.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is CreateHabitCommand -> {
|
is CreateHabitCommand -> {
|
||||||
return activity.resources.getString(R.string.toast_habit_created)
|
return activity.resources.getString(R.string.toast_habit_created)
|
||||||
}
|
}
|
||||||
is DeleteHabitsCommand -> {
|
is DeleteHabitsCommand -> {
|
||||||
return activity.resources.getQuantityString(R.plurals.toast_habits_deleted,
|
return activity.resources.getQuantityString(
|
||||||
command.selected.size)
|
R.plurals.toast_habits_deleted,
|
||||||
|
command.selected.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is EditHabitCommand -> {
|
is EditHabitCommand -> {
|
||||||
return activity.resources.getQuantityString(R.plurals.toast_habits_changed, 1)
|
return activity.resources.getQuantityString(R.plurals.toast_habits_changed, 1)
|
||||||
}
|
}
|
||||||
is UnarchiveHabitsCommand -> {
|
is UnarchiveHabitsCommand -> {
|
||||||
return activity.resources.getQuantityString(R.plurals.toast_habits_unarchived,
|
return activity.resources.getQuantityString(
|
||||||
command.selected.size)
|
R.plurals.toast_habits_unarchived,
|
||||||
|
command.selected.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> return null
|
else -> return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onImportData(file: File, onFinished: () -> Unit) {
|
private fun onImportData(file: File, onFinished: () -> Unit) {
|
||||||
taskRunner.execute(importTaskFactory.create(file) { result ->
|
taskRunner.execute(
|
||||||
|
importTaskFactory.create(file) { result ->
|
||||||
if (result == ImportDataTask.SUCCESS) {
|
if (result == ImportDataTask.SUCCESS) {
|
||||||
adapter.refresh()
|
adapter.refresh()
|
||||||
activity.showMessage(activity.resources.getString(R.string.habits_imported))
|
activity.showMessage(activity.resources.getString(R.string.habits_imported))
|
||||||
@@ -255,13 +301,16 @@ class ListHabitsScreen
|
|||||||
activity.showMessage(activity.resources.getString(R.string.could_not_import))
|
activity.showMessage(activity.resources.getString(R.string.could_not_import))
|
||||||
}
|
}
|
||||||
onFinished()
|
onFinished()
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onExportDB() {
|
private fun onExportDB() {
|
||||||
taskRunner.execute(exportDBFactory.create { filename ->
|
taskRunner.execute(
|
||||||
|
exportDBFactory.create { filename ->
|
||||||
if (filename != null) activity.showSendFileScreen(filename)
|
if (filename != null) activity.showSendFileScreen(filename)
|
||||||
else activity.showMessage(activity.resources.getString(R.string.could_not_export))
|
else activity.showMessage(activity.resources.getString(R.string.could_not_export))
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,20 +19,23 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list
|
package org.isoron.uhabits.activities.habits.list
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
import androidx.appcompat.app.*
|
import android.view.MenuItem
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import dagger.*
|
import dagger.Lazy
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
|
||||||
import org.isoron.uhabits.core.commands.*
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardListController
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.commands.CommandRunner
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.ui.NotificationTray
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsSelectionMenuBehavior
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
|
import org.isoron.uhabits.inject.ActivityScope
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
class ListHabitsSelectionMenu @Inject constructor(
|
class ListHabitsSelectionMenu @Inject constructor(
|
||||||
|
|||||||
@@ -19,13 +19,14 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.View
|
||||||
import android.view.View.MeasureSpec.*
|
import android.view.View.MeasureSpec.EXACTLY
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.utils.dim
|
||||||
|
import org.isoron.uhabits.utils.toMeasureSpec
|
||||||
|
|
||||||
abstract class ButtonPanelView<T : View>(
|
abstract class ButtonPanelView<T : View>(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -79,8 +80,10 @@ abstract class ButtonPanelView<T : View>(
|
|||||||
val buttonWidth = dim(R.dimen.checkmarkWidth)
|
val buttonWidth = dim(R.dimen.checkmarkWidth)
|
||||||
val buttonHeight = dim(R.dimen.checkmarkHeight)
|
val buttonHeight = dim(R.dimen.checkmarkHeight)
|
||||||
val width = (buttonWidth * buttonCount)
|
val width = (buttonWidth * buttonCount)
|
||||||
super.onMeasure(width.toMeasureSpec(EXACTLY),
|
super.onMeasure(
|
||||||
buttonHeight.toMeasureSpec(EXACTLY))
|
width.toMeasureSpec(EXACTLY),
|
||||||
|
buttonHeight.toMeasureSpec(EXACTLY)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun setupButtons()
|
protected abstract fun setupButtons()
|
||||||
|
|||||||
@@ -19,21 +19,30 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.graphics.*
|
import android.graphics.Canvas
|
||||||
import android.text.*
|
import android.graphics.Color
|
||||||
import android.view.*
|
import android.graphics.Paint
|
||||||
import android.view.View.MeasureSpec.*
|
import android.graphics.RectF
|
||||||
import com.google.auto.factory.*
|
import android.text.TextPaint
|
||||||
import org.isoron.uhabits.*
|
import android.view.HapticFeedbackConstants
|
||||||
import org.isoron.uhabits.core.models.*
|
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.NO
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.SKIP
|
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.UNKNOWN
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
import org.isoron.uhabits.utils.*
|
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
|
@AutoFactory
|
||||||
class CheckmarkButtonView(
|
class CheckmarkButtonView(
|
||||||
@@ -93,8 +102,10 @@ class CheckmarkButtonView(
|
|||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
val height = resources.getDimensionPixelSize(R.dimen.checkmarkHeight)
|
val height = resources.getDimensionPixelSize(R.dimen.checkmarkHeight)
|
||||||
val width = resources.getDimensionPixelSize(R.dimen.checkmarkWidth)
|
val width = resources.getDimensionPixelSize(R.dimen.checkmarkWidth)
|
||||||
super.onMeasure(width.toMeasureSpec(EXACTLY),
|
super.onMeasure(
|
||||||
height.toMeasureSpec(EXACTLY))
|
width.toMeasureSpec(EXACTLY),
|
||||||
|
height.toMeasureSpec(EXACTLY)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class Drawer {
|
private inner class Drawer {
|
||||||
|
|||||||
@@ -19,13 +19,14 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import com.google.auto.factory.*
|
import com.google.auto.factory.AutoFactory
|
||||||
import org.isoron.uhabits.core.models.*
|
import com.google.auto.factory.Provided
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
|
import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
|
|
||||||
@AutoFactory
|
@AutoFactory
|
||||||
class CheckmarkPanelView(
|
class CheckmarkPanelView(
|
||||||
|
|||||||
@@ -19,13 +19,19 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.Gravity.CENTER
|
||||||
import android.view.Gravity.*
|
import android.view.View
|
||||||
import android.view.ViewGroup.LayoutParams.*
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.widget.*
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
import org.isoron.uhabits.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.utils.*
|
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) {
|
class EmptyListView(context: Context) : LinearLayout(context) {
|
||||||
init {
|
init {
|
||||||
@@ -33,19 +39,27 @@ class EmptyListView(context: Context) : LinearLayout(context) {
|
|||||||
gravity = CENTER
|
gravity = CENTER
|
||||||
visibility = View.GONE
|
visibility = View.GONE
|
||||||
|
|
||||||
addView(TextView(context).apply {
|
addView(
|
||||||
|
TextView(context).apply {
|
||||||
text = str(R.string.fa_star_half_o)
|
text = str(R.string.fa_star_half_o)
|
||||||
typeface = getFontAwesome()
|
typeface = getFontAwesome()
|
||||||
textSize = sp(40.0f)
|
textSize = sp(40.0f)
|
||||||
gravity = CENTER
|
gravity = CENTER
|
||||||
setTextColor(sres.getColor(R.attr.mediumContrastTextColor))
|
setTextColor(sres.getColor(R.attr.mediumContrastTextColor))
|
||||||
}, MATCH_PARENT, WRAP_CONTENT)
|
},
|
||||||
|
MATCH_PARENT,
|
||||||
|
WRAP_CONTENT
|
||||||
|
)
|
||||||
|
|
||||||
addView(TextView(context).apply {
|
addView(
|
||||||
|
TextView(context).apply {
|
||||||
text = str(R.string.no_habits_found)
|
text = str(R.string.no_habits_found)
|
||||||
gravity = CENTER
|
gravity = CENTER
|
||||||
setPadding(0, dp(20.0f).toInt(), 0, 0)
|
setPadding(0, dp(20.0f).toInt(), 0, 0)
|
||||||
setTextColor(sres.getColor(R.attr.mediumContrastTextColor))
|
setTextColor(sres.getColor(R.attr.mediumContrastTextColor))
|
||||||
}, MATCH_PARENT, WRAP_CONTENT)
|
},
|
||||||
|
MATCH_PARENT,
|
||||||
|
WRAP_CONTENT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,12 +19,13 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import dagger.*
|
import dagger.Lazy
|
||||||
import org.isoron.uhabits.activities.habits.list.*
|
import org.isoron.uhabits.activities.habits.list.ListHabitsSelectionMenu
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.models.ModelObservable
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.inject.ActivityScope
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller responsible for receiving and processing the events generated by a
|
* Controller responsible for receiving and processing the events generated by a
|
||||||
|
|||||||
@@ -19,17 +19,26 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import androidx.recyclerview.widget.*
|
import android.os.Parcelable
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper.*
|
import android.view.GestureDetector
|
||||||
import android.view.*
|
import android.view.MotionEvent
|
||||||
import com.google.auto.factory.*
|
import android.view.View
|
||||||
import dagger.*
|
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.R
|
||||||
import org.isoron.uhabits.activities.common.views.*
|
import org.isoron.uhabits.activities.common.views.BundleSavedState
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
|
|
||||||
@AutoFactory
|
@AutoFactory
|
||||||
class HabitCardListView(
|
class HabitCardListView(
|
||||||
@@ -65,11 +74,13 @@ class HabitCardListView(
|
|||||||
return cardViewFactory.create()
|
return cardViewFactory.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bindCardView(holder: HabitCardViewHolder,
|
fun bindCardView(
|
||||||
|
holder: HabitCardViewHolder,
|
||||||
habit: Habit,
|
habit: Habit,
|
||||||
score: Double,
|
score: Double,
|
||||||
checkmarks: IntArray,
|
checkmarks: IntArray,
|
||||||
selected: Boolean): View {
|
selected: Boolean
|
||||||
|
): View {
|
||||||
val cardView = holder.itemView as HabitCardView
|
val cardView = holder.itemView as HabitCardView
|
||||||
cardView.habit = habit
|
cardView.habit = habit
|
||||||
cardView.isSelected = selected
|
cardView.isSelected = selected
|
||||||
@@ -149,20 +160,26 @@ class HabitCardListView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class TouchHelperCallback : ItemTouchHelper.Callback() {
|
inner class TouchHelperCallback : ItemTouchHelper.Callback() {
|
||||||
override fun getMovementFlags(recyclerView: RecyclerView,
|
override fun getMovementFlags(
|
||||||
viewHolder: RecyclerView.ViewHolder): Int {
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder
|
||||||
|
): Int {
|
||||||
return makeMovementFlags(UP or DOWN, START or END)
|
return makeMovementFlags(UP or DOWN, START or END)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMove(recyclerView: RecyclerView,
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
from: RecyclerView.ViewHolder,
|
from: RecyclerView.ViewHolder,
|
||||||
to: RecyclerView.ViewHolder): Boolean {
|
to: RecyclerView.ViewHolder
|
||||||
|
): Boolean {
|
||||||
controller.get().drop(from.adapterPosition, to.adapterPosition)
|
controller.get().drop(from.adapterPosition, to.adapterPosition)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder,
|
override fun onSwiped(
|
||||||
direction: Int) {
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
direction: Int
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isItemViewSwipeEnabled() = false
|
override fun isItemViewSwipeEnabled() = false
|
||||||
|
|||||||
@@ -19,22 +19,34 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.os.*
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import android.os.Build.VERSION.*
|
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||||
import android.os.Build.VERSION_CODES.*
|
import android.os.Build.VERSION_CODES.M
|
||||||
import android.text.*
|
import android.os.Handler
|
||||||
import android.view.*
|
import android.os.Looper
|
||||||
import android.view.ViewGroup.LayoutParams.*
|
import android.text.Layout
|
||||||
import android.widget.*
|
import android.text.TextUtils
|
||||||
import com.google.auto.factory.*
|
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.R
|
||||||
import org.isoron.uhabits.activities.common.views.*
|
import org.isoron.uhabits.activities.common.views.RingView
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.models.ModelObservable
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
import org.isoron.uhabits.utils.*
|
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
|
@AutoFactory
|
||||||
class HabitCardView(
|
class HabitCardView(
|
||||||
@@ -228,8 +240,10 @@ class HabitCardView(
|
|||||||
private fun triggerRipple(x: Float, y: Float) {
|
private fun triggerRipple(x: Float, y: Float) {
|
||||||
val background = innerFrame.background
|
val background = innerFrame.background
|
||||||
if (SDK_INT >= LOLLIPOP) background.setHotspot(x, y)
|
if (SDK_INT >= LOLLIPOP) background.setHotspot(x, y)
|
||||||
background.state = intArrayOf(android.R.attr.state_pressed,
|
background.state = intArrayOf(
|
||||||
android.R.attr.state_enabled)
|
android.R.attr.state_pressed,
|
||||||
|
android.R.attr.state_enabled
|
||||||
|
)
|
||||||
Handler().postDelayed({ background.state = intArrayOf() }, 25)
|
Handler().postDelayed({ background.state = intArrayOf() }, 25)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import androidx.appcompat.widget.*
|
import android.view.View
|
||||||
import android.view.*
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
||||||
class HabitCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
|
class HabitCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
|
||||||
|
|||||||
@@ -19,19 +19,28 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.graphics.*
|
import android.graphics.Canvas
|
||||||
import android.os.Build.VERSION.*
|
import android.graphics.Color
|
||||||
import android.os.Build.VERSION_CODES.*
|
import android.graphics.Paint
|
||||||
import android.text.*
|
import android.graphics.RectF
|
||||||
import android.view.View.MeasureSpec.*
|
import android.graphics.Typeface
|
||||||
import org.isoron.uhabits.*
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import org.isoron.uhabits.activities.common.views.*
|
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import android.text.TextPaint
|
||||||
import org.isoron.uhabits.core.utils.*
|
import android.view.View.MeasureSpec.EXACTLY
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.activities.common.views.ScrollableChart
|
||||||
import java.util.*
|
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(
|
class HeaderView(
|
||||||
context: Context,
|
context: Context,
|
||||||
@@ -121,8 +130,12 @@ class HeaderView(
|
|||||||
if (isReversed) rect.offset(-(index + 1) * width, 0f)
|
if (isReversed) rect.offset(-(index + 1) * width, 0f)
|
||||||
else rect.offset((index - buttonCount) * width, 0f)
|
else rect.offset((index - buttonCount) * width, 0f)
|
||||||
|
|
||||||
if (isRTL()) rect.set(canvas.width - rect.right, rect.top,
|
if (isRTL()) rect.set(
|
||||||
canvas.width - rect.left, rect.bottom)
|
canvas.width - rect.right,
|
||||||
|
rect.top,
|
||||||
|
canvas.width - rect.left,
|
||||||
|
rect.bottom
|
||||||
|
)
|
||||||
|
|
||||||
val y1 = rect.centerY() - 0.25 * em
|
val y1 = rect.centerY() - 0.25 * em
|
||||||
val y2 = rect.centerY() + 1.25 * em
|
val y2 = rect.centerY() + 1.25 * em
|
||||||
|
|||||||
@@ -19,16 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.animation.*
|
import android.animation.AnimatorListenerAdapter
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.graphics.*
|
import android.graphics.Color.WHITE
|
||||||
import android.graphics.Color.*
|
import android.graphics.Typeface
|
||||||
import android.view.*
|
import android.view.View
|
||||||
import android.view.ViewGroup.LayoutParams.*
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.*
|
import android.widget.TextView
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.HintList
|
||||||
|
import org.isoron.uhabits.utils.dp
|
||||||
|
|
||||||
class HintView(
|
class HintView(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|||||||
@@ -19,18 +19,25 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.graphics.*
|
import android.graphics.Canvas
|
||||||
import android.text.*
|
import android.graphics.Paint
|
||||||
import android.view.*
|
import android.graphics.RectF
|
||||||
import android.view.View.*
|
import android.graphics.Typeface
|
||||||
import com.google.auto.factory.*
|
import android.text.TextPaint
|
||||||
import org.isoron.uhabits.*
|
import android.view.View
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import android.view.View.OnClickListener
|
||||||
import org.isoron.uhabits.inject.*
|
import android.view.View.OnLongClickListener
|
||||||
import org.isoron.uhabits.utils.*
|
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 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 BOLD_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.BOLD)
|
||||||
private val NORMAL_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.NORMAL)
|
private val NORMAL_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.NORMAL)
|
||||||
|
|||||||
@@ -19,12 +19,13 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import com.google.auto.factory.*
|
import com.google.auto.factory.AutoFactory
|
||||||
import org.isoron.uhabits.core.models.*
|
import com.google.auto.factory.Provided
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
|
|
||||||
@AutoFactory
|
@AutoFactory
|
||||||
class NumberPanelView(
|
class NumberPanelView(
|
||||||
|
|||||||
@@ -19,11 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list.views
|
package org.isoron.uhabits.activities.habits.list.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.View
|
||||||
import android.view.View.MeasureSpec.*
|
import android.view.View.MeasureSpec.EXACTLY
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.utils.dp
|
||||||
|
import org.isoron.uhabits.utils.toMeasureSpec
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
class ShadowView(context: Context) : View(context) {
|
class ShadowView(context: Context) : View(context) {
|
||||||
@@ -33,7 +34,9 @@ class ShadowView(context: Context) : View(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
super.onMeasure(widthMeasureSpec,
|
super.onMeasure(
|
||||||
dp(2.0f).toInt().toMeasureSpec(EXACTLY))
|
widthMeasureSpec,
|
||||||
|
dp(2.0f).toInt().toMeasureSpec(EXACTLY)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,17 +18,25 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
import android.content.*
|
import android.content.ContentUris
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
import androidx.appcompat.app.*
|
import android.view.MenuItem
|
||||||
import kotlinx.coroutines.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import org.isoron.uhabits.activities.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*
|
import kotlinx.coroutines.launch
|
||||||
import org.isoron.uhabits.core.commands.*
|
import org.isoron.uhabits.AndroidDirFinder
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.intents.*
|
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 {
|
class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
||||||
|
|
||||||
@@ -125,4 +133,3 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.show
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
import org.isoron.uhabits.*
|
import android.view.MenuItem
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior
|
||||||
|
|
||||||
class ShowHabitMenu(
|
class ShowHabitMenu(
|
||||||
val activity: ShowHabitActivity,
|
val activity: ShowHabitActivity,
|
||||||
|
|||||||
@@ -19,16 +19,20 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.show
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*
|
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialogFactory
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.common.dialogs.HistoryEditorDialog
|
||||||
import org.isoron.uhabits.core.ui.callbacks.*
|
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.*
|
import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback
|
||||||
import org.isoron.uhabits.intents.*
|
import org.isoron.uhabits.core.ui.callbacks.OnToggleCheckmarkListener
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
import org.isoron.uhabits.widgets.*
|
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(
|
class ShowHabitScreen(
|
||||||
val activity: ShowHabitActivity,
|
val activity: ShowHabitActivity,
|
||||||
@@ -40,7 +44,7 @@ class ShowHabitScreen(
|
|||||||
) : ShowHabitBehavior.Screen, ShowHabitMenuBehavior.Screen {
|
) : ShowHabitBehavior.Screen, ShowHabitMenuBehavior.Screen {
|
||||||
|
|
||||||
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();
|
numberPickerFactory.create(value, unit, callback).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateWidgets() {
|
override fun updateWidgets() {
|
||||||
|
|||||||
@@ -19,14 +19,32 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.show
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.FrameLayout
|
||||||
import org.isoron.uhabits.activities.habits.show.views.*
|
import org.isoron.uhabits.activities.habits.show.views.BarCardPresenter
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.habits.show.views.BarCardViewModel
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.activities.habits.show.views.FrequencyCardPresenter
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.activities.habits.show.views.FrequencyCardViewModel
|
||||||
import org.isoron.uhabits.utils.*
|
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(
|
data class ShowHabitViewModel(
|
||||||
val title: String = "",
|
val title: String = "",
|
||||||
|
|||||||
@@ -18,15 +18,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
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.activities.habits.show.views.ScoreCardPresenter.Companion.getTruncateField
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Entry
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
import org.isoron.uhabits.databinding.ShowHabitBarBinding
|
||||||
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
data class BarCardViewModel(
|
data class BarCardViewModel(
|
||||||
val entries: List<Entry>,
|
val entries: List<Entry>,
|
||||||
|
|||||||
@@ -18,14 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import java.util.*
|
import org.isoron.uhabits.databinding.ShowHabitFrequencyBinding
|
||||||
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
data class FrequencyCardViewModel(
|
data class FrequencyCardViewModel(
|
||||||
val frequency: HashMap<Timestamp, Array<Int>>,
|
val frequency: HashMap<Timestamp, Array<Int>>,
|
||||||
|
|||||||
@@ -18,13 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.databinding.ShowHabitHistoryBinding
|
||||||
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
data class HistoryCardViewModel(
|
data class HistoryCardViewModel(
|
||||||
val entries: IntArray,
|
val entries: IntArray,
|
||||||
@@ -54,7 +55,6 @@ class HistoryCard(context: Context, attrs: AttributeSet) : LinearLayout(context,
|
|||||||
if (data.isNumerical) {
|
if (data.isNumerical) {
|
||||||
binding.historyChart.setNumerical(true)
|
binding.historyChart.setNumerical(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.databinding.ShowHabitNotesBinding
|
||||||
|
|
||||||
data class NotesCardViewModel(val description: String)
|
data class NotesCardViewModel(val description: String)
|
||||||
|
|
||||||
|
|||||||
@@ -18,17 +18,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
import org.isoron.uhabits.*
|
import kotlinx.coroutines.invoke
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
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(
|
data class OverviewCardViewModel(
|
||||||
val color: PaletteColor,
|
val color: PaletteColor,
|
||||||
@@ -43,8 +46,11 @@ class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(con
|
|||||||
private val binding = ShowHabitOverviewBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ShowHabitOverviewBinding.inflate(LayoutInflater.from(context), this)
|
||||||
|
|
||||||
private fun formatPercentageDiff(percentageDiff: Float): String {
|
private fun formatPercentageDiff(percentageDiff: Float): String {
|
||||||
return String.format("%s%.0f%%", if (percentageDiff >= 0) "+" else "\u2212",
|
return String.format(
|
||||||
Math.abs(percentageDiff) * 100)
|
"%s%.0f%%",
|
||||||
|
if (percentageDiff >= 0) "+" else "\u2212",
|
||||||
|
Math.abs(percentageDiff) * 100
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(data: OverviewCardViewModel) {
|
fun update(data: OverviewCardViewModel) {
|
||||||
|
|||||||
@@ -18,15 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.view.View
|
||||||
import org.isoron.uhabits.core.models.*
|
import android.widget.AdapterView
|
||||||
import org.isoron.uhabits.core.utils.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
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(
|
data class ScoreCardViewModel(
|
||||||
val scores: List<Score>,
|
val scores: List<Score>,
|
||||||
@@ -86,9 +94,12 @@ class ScoreCardPresenter(
|
|||||||
val scores = habit.scores.getByInterval(oldest, today).groupBy {
|
val scores = habit.scores.getByInterval(oldest, today).groupBy {
|
||||||
DateUtils.truncate(field, it.timestamp, firstWeekday)
|
DateUtils.truncate(field, it.timestamp, firstWeekday)
|
||||||
}.map { (timestamp, scores) ->
|
}.map { (timestamp, scores) ->
|
||||||
Score(timestamp, scores.map {
|
Score(
|
||||||
|
timestamp,
|
||||||
|
scores.map {
|
||||||
it.value
|
it.value
|
||||||
}.average())
|
}.average()
|
||||||
|
)
|
||||||
}.sortedBy {
|
}.sortedBy {
|
||||||
it.timestamp
|
it.timestamp
|
||||||
}.reversed()
|
}.reversed()
|
||||||
|
|||||||
@@ -18,14 +18,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
import org.isoron.uhabits.core.models.*
|
import kotlinx.coroutines.invoke
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.utils.*
|
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(
|
data class StreakCardViewModel(
|
||||||
val color: PaletteColor,
|
val color: PaletteColor,
|
||||||
|
|||||||
@@ -18,18 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.annotation.*
|
import android.annotation.SuppressLint
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.content.res.*
|
import android.content.res.Resources
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.view.View
|
||||||
import org.isoron.uhabits.*
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.habits.list.views.toShortString
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.Frequency
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import java.util.*
|
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(
|
data class SubtitleCardViewModel(
|
||||||
val color: PaletteColor,
|
val color: PaletteColor,
|
||||||
|
|||||||
@@ -18,18 +18,21 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.content.res.*
|
import android.content.res.Resources
|
||||||
import android.util.*
|
import android.util.AttributeSet
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.*
|
import android.widget.LinearLayout
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
import org.isoron.uhabits.*
|
import kotlinx.coroutines.invoke
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import java.util.*
|
import org.isoron.uhabits.databinding.ShowHabitTargetBinding
|
||||||
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
data class TargetCardViewModel(
|
data class TargetCardViewModel(
|
||||||
val color: PaletteColor,
|
val color: PaletteColor,
|
||||||
|
|||||||
@@ -19,11 +19,10 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.intro
|
package org.isoron.uhabits.activities.intro
|
||||||
|
|
||||||
import android.graphics.*
|
import android.graphics.Color
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
|
import com.github.paolorotolo.appintro.AppIntro2
|
||||||
import com.github.paolorotolo.appintro.*
|
import com.github.paolorotolo.appintro.AppIntroFragment
|
||||||
|
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,17 +33,32 @@ class IntroActivity : AppIntro2() {
|
|||||||
override fun init(savedInstanceState: Bundle?) {
|
override fun init(savedInstanceState: Bundle?) {
|
||||||
showStatusBar(false)
|
showStatusBar(false)
|
||||||
|
|
||||||
addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_1),
|
addSlide(
|
||||||
getString(R.string.intro_description_1), R.drawable.intro_icon_1,
|
AppIntroFragment.newInstance(
|
||||||
Color.parseColor("#194673")))
|
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),
|
addSlide(
|
||||||
getString(R.string.intro_description_2), R.drawable.intro_icon_2,
|
AppIntroFragment.newInstance(
|
||||||
Color.parseColor("#ffa726")))
|
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),
|
addSlide(
|
||||||
getString(R.string.intro_description_4), R.drawable.intro_icon_4,
|
AppIntroFragment.newInstance(
|
||||||
Color.parseColor("#9575cd")))
|
getString(R.string.intro_title_4),
|
||||||
|
getString(R.string.intro_description_4),
|
||||||
|
R.drawable.intro_icon_4,
|
||||||
|
Color.parseColor("#9575cd")
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNextPressed() {}
|
override fun onNextPressed() {}
|
||||||
|
|||||||
@@ -18,14 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.settings
|
package org.isoron.uhabits.activities.settings
|
||||||
|
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import androidx.appcompat.app.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.activities.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
import org.isoron.uhabits.databinding.*
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.databinding.SettingsActivityBinding
|
||||||
|
import org.isoron.uhabits.utils.setupToolbar
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
class SettingsActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|||||||
@@ -19,25 +19,31 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.sync
|
package org.isoron.uhabits.activities.sync
|
||||||
|
|
||||||
import android.content.*
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.graphics.*
|
import android.content.Context
|
||||||
import android.os.*
|
import android.graphics.Bitmap
|
||||||
import android.text.*
|
import android.graphics.Color
|
||||||
import android.view.*
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.*
|
import android.text.Html
|
||||||
import com.google.zxing.*
|
import android.view.View
|
||||||
import com.google.zxing.qrcode.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import kotlinx.coroutines.*
|
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.utils.InterfaceUtils.getFontAwesome
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.utils.setupToolbar
|
||||||
import org.isoron.uhabits.activities.*
|
import org.isoron.uhabits.utils.showMessage
|
||||||
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.*
|
|
||||||
|
|
||||||
|
|
||||||
class SyncActivity : AppCompatActivity(), SyncBehavior.Screen {
|
class SyncActivity : AppCompatActivity(), SyncBehavior.Screen {
|
||||||
|
|
||||||
@@ -100,7 +106,6 @@ class SyncActivity : AppCompatActivity(), SyncBehavior.Screen {
|
|||||||
binding.progress.visibility = View.GONE
|
binding.progress.visibility = View.GONE
|
||||||
binding.qrCode.visibility = View.VISIBLE
|
binding.qrCode.visibility = View.VISIBLE
|
||||||
binding.qrCode.setImageBitmap(generateQR(msg))
|
binding.qrCode.setImageBitmap(generateQR(msg))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun showLoadingScreen() {
|
override suspend fun showLoadingScreen() {
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.automation
|
package org.isoron.uhabits.automation
|
||||||
|
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.*
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.activities.*
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.HabitMatcherBuilder
|
||||||
|
|
||||||
class EditSettingActivity : AppCompatActivity() {
|
class EditSettingActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -33,7 +33,8 @@ class EditSettingActivity : AppCompatActivity() {
|
|||||||
HabitMatcherBuilder()
|
HabitMatcherBuilder()
|
||||||
.setArchivedAllowed(false)
|
.setArchivedAllowed(false)
|
||||||
.setCompletedAllowed(true)
|
.setCompletedAllowed(true)
|
||||||
.build())
|
.build()
|
||||||
|
)
|
||||||
AndroidThemeSwitcher(this, app.component.preferences).apply()
|
AndroidThemeSwitcher(this, app.component.preferences).apply()
|
||||||
|
|
||||||
val args = SettingUtils.parseIntent(this.intent, habits)
|
val args = SettingUtils.parseIntent(this.intent, habits)
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.automation
|
package org.isoron.uhabits.automation
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.Intent
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
|
||||||
class EditSettingController(private val activity: Activity) {
|
class EditSettingController(private val activity: Activity) {
|
||||||
|
|
||||||
@@ -36,10 +36,13 @@ class EditSettingController(private val activity: Activity) {
|
|||||||
bundle.putInt("action", action)
|
bundle.putInt("action", action)
|
||||||
bundle.putLong("habit", habit.id!!)
|
bundle.putLong("habit", habit.id!!)
|
||||||
|
|
||||||
activity.setResult(Activity.RESULT_OK, Intent().apply {
|
activity.setResult(
|
||||||
|
Activity.RESULT_OK,
|
||||||
|
Intent().apply {
|
||||||
putExtra(EXTRA_STRING_BLURB, blurb)
|
putExtra(EXTRA_STRING_BLURB, blurb)
|
||||||
putExtra(EXTRA_BUNDLE, bundle)
|
putExtra(EXTRA_BUNDLE, bundle)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
activity.finish()
|
activity.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,16 +19,22 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.automation
|
package org.isoron.uhabits.automation
|
||||||
|
|
||||||
import android.R.layout.*
|
import android.R.layout.simple_spinner_dropdown_item
|
||||||
import android.annotation.*
|
import android.R.layout.simple_spinner_item
|
||||||
import android.content.*
|
import android.annotation.SuppressLint
|
||||||
import android.view.*
|
import android.content.Context
|
||||||
import android.widget.*
|
import android.view.LayoutInflater
|
||||||
import org.isoron.uhabits.*
|
import android.view.View
|
||||||
import org.isoron.uhabits.core.models.*
|
import android.widget.AdapterView
|
||||||
import org.isoron.uhabits.databinding.*
|
import android.widget.ArrayAdapter
|
||||||
import org.isoron.uhabits.utils.*
|
import android.widget.FrameLayout
|
||||||
import java.util.*
|
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")
|
@SuppressLint("ViewConstructor")
|
||||||
class EditSettingRootView(
|
class EditSettingRootView(
|
||||||
|
|||||||
@@ -19,14 +19,16 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.automation
|
package org.isoron.uhabits.automation
|
||||||
|
|
||||||
import android.content.*
|
import android.content.BroadcastReceiver
|
||||||
import dagger.*
|
import android.content.Context
|
||||||
import org.isoron.uhabits.*
|
import android.content.Intent
|
||||||
import org.isoron.uhabits.core.models.*
|
import dagger.Component
|
||||||
import org.isoron.uhabits.core.ui.widgets.*
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.HabitList
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.ui.widgets.WidgetBehavior
|
||||||
import org.isoron.uhabits.receivers.*
|
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_CHECK = 0
|
||||||
const val ACTION_UNCHECK = 1
|
const val ACTION_UNCHECK = 1
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.database
|
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 {
|
class AndroidCursor(private val cursor: android.database.Cursor) : Cursor {
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.database
|
package org.isoron.uhabits.database
|
||||||
|
|
||||||
import android.content.*
|
import android.content.ContentValues
|
||||||
import android.database.sqlite.*
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import org.isoron.uhabits.core.database.*
|
import org.isoron.uhabits.core.database.Database
|
||||||
import java.io.*
|
import java.io.File
|
||||||
|
|
||||||
class AndroidDatabase(
|
class AndroidDatabase(
|
||||||
private val db: SQLiteDatabase,
|
private val db: SQLiteDatabase,
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.database
|
package org.isoron.uhabits.database
|
||||||
|
|
||||||
import android.database.sqlite.*
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import org.isoron.uhabits.core.database.*
|
import org.isoron.uhabits.core.database.DatabaseOpener
|
||||||
import java.io.*
|
import java.io.File
|
||||||
import javax.inject.*
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AndroidDatabaseOpener @Inject constructor() : DatabaseOpener {
|
class AndroidDatabaseOpener @Inject constructor() : DatabaseOpener {
|
||||||
override fun open(file: File): AndroidDatabase {
|
override fun open(file: File): AndroidDatabase {
|
||||||
@@ -32,6 +32,7 @@ class AndroidDatabaseOpener @Inject constructor() : DatabaseOpener {
|
|||||||
null,
|
null,
|
||||||
SQLiteDatabase.OPEN_READWRITE,
|
SQLiteDatabase.OPEN_READWRITE,
|
||||||
),
|
),
|
||||||
file = file)
|
file = file
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.database
|
package org.isoron.uhabits.database
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.util.*
|
import android.util.Log
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.AndroidDirFinder
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.utils.DatabaseUtils
|
||||||
import java.io.*
|
import java.io.File
|
||||||
|
|
||||||
class AutoBackup(private val context: Context) {
|
class AutoBackup(private val context: Context) {
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class AutoBackup(private val context: Context) {
|
|||||||
fun run(keep: Int = 5) {
|
fun run(keep: Int = 5) {
|
||||||
Log.i("AutoBackup", "Starting automatic backups...")
|
Log.i("AutoBackup", "Starting automatic backups...")
|
||||||
val files = listBackupFiles()
|
val files = listBackupFiles()
|
||||||
var newestTimestamp = 0L;
|
var newestTimestamp = 0L
|
||||||
if (files.isNotEmpty()) {
|
if (files.isNotEmpty()) {
|
||||||
newestTimestamp = files.last().lastModified()
|
newestTimestamp = files.last().lastModified()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.inject
|
package org.isoron.uhabits.inject
|
||||||
|
|
||||||
import javax.inject.*
|
import javax.inject.Qualifier
|
||||||
|
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.inject
|
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 used by objects that live as long as the activity is alive.
|
||||||
|
|||||||
@@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.inject
|
package org.isoron.uhabits.inject
|
||||||
|
|
||||||
import dagger.*
|
import dagger.Module
|
||||||
import org.isoron.uhabits.core.models.*
|
import dagger.Provides
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
class HabitModule(private val habit: Habit) {
|
class HabitModule(private val habit: Habit) {
|
||||||
|
|||||||
@@ -19,20 +19,27 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.inject
|
package org.isoron.uhabits.inject
|
||||||
|
|
||||||
import dagger.*
|
import dagger.Component
|
||||||
import org.isoron.uhabits.activities.common.dialogs.*
|
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
|
||||||
import org.isoron.uhabits.activities.habits.list.*
|
import org.isoron.uhabits.activities.habits.list.ListHabitsMenu
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*
|
import org.isoron.uhabits.activities.habits.list.ListHabitsModule
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.activities.habits.list.ListHabitsRootView
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.*
|
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
|
@ActivityScope
|
||||||
@Component(modules = arrayOf(
|
@Component(
|
||||||
|
modules = arrayOf(
|
||||||
ActivityContextModule::class,
|
ActivityContextModule::class,
|
||||||
HabitsActivityModule::class,
|
HabitsActivityModule::class,
|
||||||
ListHabitsModule::class,
|
ListHabitsModule::class,
|
||||||
HabitModule::class
|
HabitModule::class
|
||||||
), dependencies = arrayOf(HabitsApplicationComponent::class))
|
),
|
||||||
|
dependencies = arrayOf(HabitsApplicationComponent::class)
|
||||||
|
)
|
||||||
interface HabitsActivityComponent {
|
interface HabitsActivityComponent {
|
||||||
val colorPickerDialogFactory: ColorPickerDialogFactory
|
val colorPickerDialogFactory: ColorPickerDialogFactory
|
||||||
val habitCardListAdapter: HabitCardListAdapter
|
val habitCardListAdapter: HabitCardListAdapter
|
||||||
|
|||||||
@@ -19,11 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.inject
|
package org.isoron.uhabits.inject
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import dagger.*
|
import dagger.Module
|
||||||
import org.isoron.uhabits.activities.*
|
import dagger.Provides
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
|
import org.isoron.uhabits.core.ui.ThemeSwitcher
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
class HabitsActivityModule {
|
class HabitsActivityModule {
|
||||||
|
|||||||
@@ -19,28 +19,35 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.inject
|
package org.isoron.uhabits.inject
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import dagger.*
|
import dagger.Module
|
||||||
import org.isoron.uhabits.core.*
|
import dagger.Provides
|
||||||
import org.isoron.uhabits.core.commands.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.core.database.*
|
import org.isoron.uhabits.core.commands.CommandRunner
|
||||||
import org.isoron.uhabits.core.io.*
|
import org.isoron.uhabits.core.database.Database
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.database.DatabaseOpener
|
||||||
import org.isoron.uhabits.core.models.sqlite.*
|
import org.isoron.uhabits.core.io.Logging
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.models.HabitList
|
||||||
import org.isoron.uhabits.core.reminders.*
|
import org.isoron.uhabits.core.models.ModelFactory
|
||||||
import org.isoron.uhabits.core.sync.*
|
import org.isoron.uhabits.core.models.sqlite.SQLModelFactory
|
||||||
import org.isoron.uhabits.core.tasks.*
|
import org.isoron.uhabits.core.models.sqlite.SQLiteHabitList
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.database.*
|
import org.isoron.uhabits.core.preferences.WidgetPreferences
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.reminders.ReminderScheduler
|
||||||
import org.isoron.uhabits.intents.*
|
import org.isoron.uhabits.core.sync.AbstractSyncServer
|
||||||
import org.isoron.uhabits.io.*
|
import org.isoron.uhabits.core.sync.NetworkManager
|
||||||
import org.isoron.uhabits.notifications.*
|
import org.isoron.uhabits.core.tasks.TaskRunner
|
||||||
import org.isoron.uhabits.preferences.*
|
import org.isoron.uhabits.core.ui.NotificationTray
|
||||||
import org.isoron.uhabits.sync.*
|
import org.isoron.uhabits.database.AndroidDatabase
|
||||||
import org.isoron.uhabits.utils.*
|
import org.isoron.uhabits.database.AndroidDatabaseOpener
|
||||||
import java.io.*
|
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
|
@Module
|
||||||
class HabitsModule(dbFile: File) {
|
class HabitsModule(dbFile: File) {
|
||||||
@@ -125,4 +132,3 @@ class HabitsModule(dbFile: File) {
|
|||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,17 +19,18 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.intents
|
package org.isoron.uhabits.intents
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.net.*
|
import android.content.Intent
|
||||||
import org.isoron.uhabits.*
|
import android.net.Uri
|
||||||
import org.isoron.uhabits.activities.about.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.habits.edit.*
|
import org.isoron.uhabits.activities.about.AboutActivity
|
||||||
import org.isoron.uhabits.activities.habits.show.*
|
import org.isoron.uhabits.activities.habits.edit.EditHabitActivity
|
||||||
import org.isoron.uhabits.activities.intro.*
|
import org.isoron.uhabits.activities.habits.show.ShowHabitActivity
|
||||||
import org.isoron.uhabits.activities.settings.*
|
import org.isoron.uhabits.activities.intro.IntroActivity
|
||||||
import org.isoron.uhabits.activities.sync.*
|
import org.isoron.uhabits.activities.settings.SettingsActivity
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.activities.sync.SyncActivity
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class IntentFactory
|
class IntentFactory
|
||||||
@Inject constructor() {
|
@Inject constructor() {
|
||||||
|
|||||||
@@ -19,13 +19,15 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.intents
|
package org.isoron.uhabits.intents
|
||||||
|
|
||||||
import android.content.*
|
import android.content.ContentUris.parseId
|
||||||
import android.content.ContentUris.*
|
import android.content.Intent
|
||||||
import android.net.*
|
import android.net.Uri
|
||||||
import org.isoron.uhabits.core.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.HabitList
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AppScope
|
@AppScope
|
||||||
class IntentParser
|
class IntentParser
|
||||||
@@ -37,13 +39,13 @@ class IntentParser
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun copyIntentData(source: Intent, destination: Intent) {
|
fun copyIntentData(source: Intent, destination: Intent) {
|
||||||
destination.data = source.data;
|
destination.data = source.data
|
||||||
destination.putExtra("timestamp", source.getLongExtra("timestamp", DateUtils.getTodayWithOffset().unixTime))
|
destination.putExtra("timestamp", source.getLongExtra("timestamp", DateUtils.getTodayWithOffset().unixTime))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseHabit(uri: Uri): Habit {
|
private fun parseHabit(uri: Uri): Habit {
|
||||||
val habit = habits.getById(parseId(uri)) ?:
|
val habit = habits.getById(parseId(uri))
|
||||||
throw IllegalArgumentException("habit not found")
|
?: throw IllegalArgumentException("habit not found")
|
||||||
return habit
|
return habit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,20 +19,23 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.intents
|
package org.isoron.uhabits.intents
|
||||||
|
|
||||||
import android.app.*
|
import android.app.AlarmManager
|
||||||
import android.app.AlarmManager.*
|
import android.app.AlarmManager.RTC
|
||||||
import android.content.*
|
import android.app.AlarmManager.RTC_WAKEUP
|
||||||
import android.content.Context.*
|
import android.app.PendingIntent
|
||||||
import android.os.Build.VERSION.*
|
import android.content.Context
|
||||||
import android.os.Build.VERSION_CODES.*
|
import android.content.Context.ALARM_SERVICE
|
||||||
import android.util.*
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import org.isoron.uhabits.core.*
|
import android.os.Build.VERSION_CODES.M
|
||||||
import org.isoron.uhabits.core.models.*
|
import android.util.Log
|
||||||
import org.isoron.uhabits.core.reminders.ReminderScheduler.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.reminders.ReminderScheduler.SchedulerResult
|
||||||
import java.util.*
|
import org.isoron.uhabits.core.reminders.ReminderScheduler.SystemScheduler
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.core.utils.DateFormats
|
||||||
|
import org.isoron.uhabits.inject.AppContext
|
||||||
|
import java.util.Date
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AppScope
|
@AppScope
|
||||||
class IntentScheduler
|
class IntentScheduler
|
||||||
@@ -48,8 +51,10 @@ class IntentScheduler
|
|||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
Log.d("IntentScheduler", "timestamp=$timestamp now=$now")
|
Log.d("IntentScheduler", "timestamp=$timestamp now=$now")
|
||||||
if (timestamp < now) {
|
if (timestamp < now) {
|
||||||
Log.e("IntentScheduler",
|
Log.e(
|
||||||
"Ignoring attempt to schedule intent in the past.")
|
"IntentScheduler",
|
||||||
|
"Ignoring attempt to schedule intent in the past."
|
||||||
|
)
|
||||||
return SchedulerResult.IGNORED
|
return SchedulerResult.IGNORED
|
||||||
}
|
}
|
||||||
if (SDK_INT >= M)
|
if (SDK_INT >= M)
|
||||||
@@ -59,9 +64,11 @@ class IntentScheduler
|
|||||||
return SchedulerResult.OK
|
return SchedulerResult.OK
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun scheduleShowReminder(reminderTime: Long,
|
override fun scheduleShowReminder(
|
||||||
|
reminderTime: Long,
|
||||||
habit: Habit,
|
habit: Habit,
|
||||||
timestamp: Long): SchedulerResult {
|
timestamp: Long
|
||||||
|
): SchedulerResult {
|
||||||
val intent = pendingIntents.showReminder(habit, reminderTime, timestamp)
|
val intent = pendingIntents.showReminder(habit, reminderTime, timestamp)
|
||||||
logReminderScheduled(habit, reminderTime)
|
logReminderScheduled(habit, reminderTime)
|
||||||
return schedule(reminderTime, intent, RTC_WAKEUP)
|
return schedule(reminderTime, intent, RTC_WAKEUP)
|
||||||
@@ -81,7 +88,9 @@ class IntentScheduler
|
|||||||
val name = habit.name.substring(0, min)
|
val name = habit.name.substring(0, min)
|
||||||
val df = DateFormats.getBackupDateFormat()
|
val df = DateFormats.getBackupDateFormat()
|
||||||
val time = df.format(Date(reminderTime))
|
val time = df.format(Date(reminderTime))
|
||||||
Log.i("ReminderHelper",
|
Log.i(
|
||||||
String.format("Setting alarm (%s): %s", time, name))
|
"ReminderHelper",
|
||||||
|
String.format("Setting alarm (%s): %s", time, name)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,61 +19,77 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.intents
|
package org.isoron.uhabits.intents
|
||||||
|
|
||||||
import android.app.*
|
import android.app.PendingIntent
|
||||||
import android.app.PendingIntent.*
|
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
import android.content.*
|
import android.app.PendingIntent.getBroadcast
|
||||||
import android.net.*
|
import android.content.Context
|
||||||
import org.isoron.uhabits.core.*
|
import android.content.Intent
|
||||||
import org.isoron.uhabits.core.models.*
|
import android.net.Uri
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.receivers.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import javax.inject.*
|
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
|
@AppScope
|
||||||
class PendingIntentFactory
|
class PendingIntentFactory
|
||||||
@Inject constructor(
|
@Inject constructor(
|
||||||
@AppContext private val context: Context,
|
@AppContext private val context: Context,
|
||||||
private val intentFactory: IntentFactory) {
|
private val intentFactory: IntentFactory
|
||||||
|
) {
|
||||||
|
|
||||||
fun addCheckmark(habit: Habit, timestamp: Timestamp?): PendingIntent =
|
fun addCheckmark(habit: Habit, timestamp: Timestamp?): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context, 1,
|
context,
|
||||||
|
1,
|
||||||
Intent(context, WidgetReceiver::class.java).apply {
|
Intent(context, WidgetReceiver::class.java).apply {
|
||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
action = WidgetReceiver.ACTION_ADD_REPETITION
|
action = WidgetReceiver.ACTION_ADD_REPETITION
|
||||||
if (timestamp != null) putExtra("timestamp", timestamp.unixTime)
|
if (timestamp != null) putExtra("timestamp", timestamp.unixTime)
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun dismissNotification(habit: Habit): PendingIntent =
|
fun dismissNotification(habit: Habit): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context, 0,
|
context,
|
||||||
|
0,
|
||||||
Intent(context, ReminderReceiver::class.java).apply {
|
Intent(context, ReminderReceiver::class.java).apply {
|
||||||
action = WidgetReceiver.ACTION_DISMISS_REMINDER
|
action = WidgetReceiver.ACTION_DISMISS_REMINDER
|
||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun removeRepetition(habit: Habit): PendingIntent =
|
fun removeRepetition(habit: Habit): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context, 3,
|
context,
|
||||||
|
3,
|
||||||
Intent(context, WidgetReceiver::class.java).apply {
|
Intent(context, WidgetReceiver::class.java).apply {
|
||||||
action = WidgetReceiver.ACTION_REMOVE_REPETITION
|
action = WidgetReceiver.ACTION_REMOVE_REPETITION
|
||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun showHabit(habit: Habit): PendingIntent =
|
fun showHabit(habit: Habit): PendingIntent =
|
||||||
androidx.core.app.TaskStackBuilder
|
androidx.core.app.TaskStackBuilder
|
||||||
.create(context)
|
.create(context)
|
||||||
.addNextIntentWithParentStack(
|
.addNextIntentWithParentStack(
|
||||||
intentFactory.startShowHabitActivity(
|
intentFactory.startShowHabitActivity(
|
||||||
context, habit))
|
context,
|
||||||
|
habit
|
||||||
|
)
|
||||||
|
)
|
||||||
.getPendingIntent(0, FLAG_UPDATE_CURRENT)!!
|
.getPendingIntent(0, FLAG_UPDATE_CURRENT)!!
|
||||||
|
|
||||||
fun showReminder(habit: Habit,
|
fun showReminder(
|
||||||
|
habit: Habit,
|
||||||
reminderTime: Long?,
|
reminderTime: Long?,
|
||||||
timestamp: Long): PendingIntent =
|
timestamp: Long
|
||||||
|
): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
(habit.id!! % Integer.MAX_VALUE).toInt() + 1,
|
(habit.id!! % Integer.MAX_VALUE).toInt() + 1,
|
||||||
@@ -83,47 +99,58 @@ class PendingIntentFactory
|
|||||||
putExtra("timestamp", timestamp)
|
putExtra("timestamp", timestamp)
|
||||||
putExtra("reminderTime", reminderTime)
|
putExtra("reminderTime", reminderTime)
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun snoozeNotification(habit: Habit): PendingIntent =
|
fun snoozeNotification(habit: Habit): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context, 0,
|
context,
|
||||||
|
0,
|
||||||
Intent(context, ReminderReceiver::class.java).apply {
|
Intent(context, ReminderReceiver::class.java).apply {
|
||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
action = ReminderReceiver.ACTION_SNOOZE_REMINDER
|
action = ReminderReceiver.ACTION_SNOOZE_REMINDER
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun toggleCheckmark(habit: Habit, timestamp: Long?): PendingIntent =
|
fun toggleCheckmark(habit: Habit, timestamp: Long?): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context, 2,
|
context,
|
||||||
|
2,
|
||||||
Intent(context, WidgetReceiver::class.java).apply {
|
Intent(context, WidgetReceiver::class.java).apply {
|
||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
action = WidgetReceiver.ACTION_TOGGLE_REPETITION
|
action = WidgetReceiver.ACTION_TOGGLE_REPETITION
|
||||||
if (timestamp != null) putExtra("timestamp", timestamp)
|
if (timestamp != null) putExtra("timestamp", timestamp)
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun setNumericalValue(widgetContext: Context,
|
fun setNumericalValue(
|
||||||
|
widgetContext: Context,
|
||||||
habit: Habit,
|
habit: Habit,
|
||||||
numericalValue: Int,
|
numericalValue: Int,
|
||||||
timestamp: Long?):
|
timestamp: Long?
|
||||||
|
):
|
||||||
PendingIntent =
|
PendingIntent =
|
||||||
getBroadcast(
|
getBroadcast(
|
||||||
widgetContext, 2,
|
widgetContext,
|
||||||
|
2,
|
||||||
Intent(widgetContext, WidgetReceiver::class.java).apply {
|
Intent(widgetContext, WidgetReceiver::class.java).apply {
|
||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE
|
action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE
|
||||||
putExtra("numericalValue", numericalValue);
|
putExtra("numericalValue", numericalValue)
|
||||||
if (timestamp != null) putExtra("timestamp", timestamp)
|
if (timestamp != null) putExtra("timestamp", timestamp)
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
|
||||||
fun updateWidgets(): PendingIntent =
|
fun updateWidgets(): PendingIntent =
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context, 0,
|
context,
|
||||||
|
0,
|
||||||
Intent(context, WidgetReceiver::class.java).apply {
|
Intent(context, WidgetReceiver::class.java).apply {
|
||||||
action = WidgetReceiver.ACTION_UPDATE_WIDGETS_VALUE
|
action = WidgetReceiver.ACTION_UPDATE_WIDGETS_VALUE
|
||||||
},
|
},
|
||||||
FLAG_UPDATE_CURRENT)
|
FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.io
|
package org.isoron.uhabits.io
|
||||||
|
|
||||||
import android.util.*
|
import android.util.Log
|
||||||
import org.isoron.uhabits.core.io.*
|
import org.isoron.uhabits.core.io.Logger
|
||||||
|
import org.isoron.uhabits.core.io.Logging
|
||||||
|
|
||||||
class AndroidLogging : Logging {
|
class AndroidLogging : Logging {
|
||||||
override fun getLogger(name: String): Logger {
|
override fun getLogger(name: String): Logger {
|
||||||
@@ -44,5 +45,4 @@ class AndroidLogger(val name: String) : Logger {
|
|||||||
override fun error(exception: Exception) {
|
override fun error(exception: Exception) {
|
||||||
Log.e(name, "Exception", exception)
|
Log.e(name, "Exception", exception)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,23 +19,29 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.notifications
|
package org.isoron.uhabits.notifications
|
||||||
|
|
||||||
import android.app.*
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.app.Notification
|
||||||
import android.graphics.*
|
import android.app.NotificationChannel
|
||||||
import android.graphics.BitmapFactory.*
|
import android.app.NotificationManager
|
||||||
import android.os.*
|
import android.content.Context
|
||||||
import android.os.Build.VERSION.*
|
import android.graphics.BitmapFactory.decodeResource
|
||||||
import android.util.*
|
import android.graphics.Color
|
||||||
import androidx.core.app.*
|
import android.os.Build
|
||||||
import androidx.core.app.NotificationCompat.*
|
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.R
|
||||||
import org.isoron.uhabits.core.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
import org.isoron.uhabits.core.ui.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.core.ui.NotificationTray
|
||||||
import org.isoron.uhabits.intents.*
|
import org.isoron.uhabits.inject.AppContext
|
||||||
import javax.inject.*
|
import org.isoron.uhabits.intents.PendingIntentFactory
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AppScope
|
@AppScope
|
||||||
class AndroidNotificationTray
|
class AndroidNotificationTray
|
||||||
@@ -57,10 +63,12 @@ class AndroidNotificationTray
|
|||||||
active.remove(id)
|
active.remove(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showNotification(habit: Habit,
|
override fun showNotification(
|
||||||
|
habit: Habit,
|
||||||
notificationId: Int,
|
notificationId: Int,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
reminderTime: Long) {
|
reminderTime: Long
|
||||||
|
) {
|
||||||
val notificationManager = NotificationManagerCompat.from(context)
|
val notificationManager = NotificationManagerCompat.from(context)
|
||||||
val notification = buildNotification(habit, reminderTime, timestamp)
|
val notification = buildNotification(habit, reminderTime, timestamp)
|
||||||
createAndroidNotificationChannel(context)
|
createAndroidNotificationChannel(context)
|
||||||
@@ -68,37 +76,45 @@ class AndroidNotificationTray
|
|||||||
notificationManager.notify(notificationId, notification)
|
notificationManager.notify(notificationId, notification)
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
// Some Xiaomi phones produce a RuntimeException if custom notification sounds are used.
|
// Some Xiaomi phones produce a RuntimeException if custom notification sounds are used.
|
||||||
Log.i("AndroidNotificationTray",
|
Log.i(
|
||||||
"Failed to show notification. Retrying without sound.")
|
"AndroidNotificationTray",
|
||||||
val n = buildNotification(habit,
|
"Failed to show notification. Retrying without sound."
|
||||||
|
)
|
||||||
|
val n = buildNotification(
|
||||||
|
habit,
|
||||||
reminderTime,
|
reminderTime,
|
||||||
timestamp,
|
timestamp,
|
||||||
disableSound = true)
|
disableSound = true
|
||||||
|
)
|
||||||
notificationManager.notify(notificationId, n)
|
notificationManager.notify(notificationId, n)
|
||||||
|
|
||||||
}
|
}
|
||||||
active.add(notificationId)
|
active.add(notificationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildNotification(habit: Habit,
|
fun buildNotification(
|
||||||
|
habit: Habit,
|
||||||
reminderTime: Long,
|
reminderTime: Long,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
disableSound: Boolean = false): Notification {
|
disableSound: Boolean = false
|
||||||
|
): Notification {
|
||||||
|
|
||||||
val addRepetitionAction = Action(
|
val addRepetitionAction = Action(
|
||||||
R.drawable.ic_action_check,
|
R.drawable.ic_action_check,
|
||||||
context.getString(R.string.yes),
|
context.getString(R.string.yes),
|
||||||
pendingIntents.addCheckmark(habit, timestamp))
|
pendingIntents.addCheckmark(habit, timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
val removeRepetitionAction = Action(
|
val removeRepetitionAction = Action(
|
||||||
R.drawable.ic_action_cancel,
|
R.drawable.ic_action_cancel,
|
||||||
context.getString(R.string.no),
|
context.getString(R.string.no),
|
||||||
pendingIntents.removeRepetition(habit))
|
pendingIntents.removeRepetition(habit)
|
||||||
|
)
|
||||||
|
|
||||||
val enterAction = Action(
|
val enterAction = Action(
|
||||||
R.drawable.ic_action_check,
|
R.drawable.ic_action_check,
|
||||||
context.getString(R.string.enter),
|
context.getString(R.string.enter),
|
||||||
pendingIntents.setNumericalValue(context, habit, 0, null))
|
pendingIntents.setNumericalValue(context, habit, 0, null)
|
||||||
|
)
|
||||||
|
|
||||||
val wearableBg = decodeResource(context.resources, R.drawable.stripe)
|
val wearableBg = decodeResource(context.resources, R.drawable.stripe)
|
||||||
|
|
||||||
@@ -137,9 +153,11 @@ class AndroidNotificationTray
|
|||||||
if (preferences.shouldMakeNotificationsLed())
|
if (preferences.shouldMakeNotificationsLed())
|
||||||
builder.setLights(Color.RED, 1000, 1000)
|
builder.setLights(Color.RED, 1000, 1000)
|
||||||
|
|
||||||
val snoozeAction = Action(R.drawable.ic_action_snooze,
|
val snoozeAction = Action(
|
||||||
|
R.drawable.ic_action_snooze,
|
||||||
context.getString(R.string.snooze),
|
context.getString(R.string.snooze),
|
||||||
pendingIntents.snoozeNotification(habit))
|
pendingIntents.snoozeNotification(habit)
|
||||||
|
)
|
||||||
wearableExtender.addAction(snoozeAction)
|
wearableExtender.addAction(snoozeAction)
|
||||||
builder.addAction(snoozeAction)
|
builder.addAction(snoozeAction)
|
||||||
|
|
||||||
@@ -153,12 +171,13 @@ class AndroidNotificationTray
|
|||||||
val notificationManager = context.getSystemService(Activity.NOTIFICATION_SERVICE)
|
val notificationManager = context.getSystemService(Activity.NOTIFICATION_SERVICE)
|
||||||
as NotificationManager
|
as NotificationManager
|
||||||
if (SDK_INT >= Build.VERSION_CODES.O) {
|
if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val channel = NotificationChannel(REMINDERS_CHANNEL_ID,
|
val channel = NotificationChannel(
|
||||||
|
REMINDERS_CHANNEL_ID,
|
||||||
context.resources.getString(R.string.reminder),
|
context.resources.getString(R.string.reminder),
|
||||||
NotificationManager.IMPORTANCE_DEFAULT)
|
NotificationManager.IMPORTANCE_DEFAULT
|
||||||
|
)
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager.createNotificationChannel(channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,18 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.notifications
|
package org.isoron.uhabits.notifications
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.media.RingtoneManager.*
|
import android.content.Intent
|
||||||
import android.net.*
|
import android.content.SharedPreferences
|
||||||
import android.preference.*
|
import android.media.RingtoneManager.EXTRA_RINGTONE_PICKED_URI
|
||||||
import android.provider.*
|
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.R
|
||||||
import org.isoron.uhabits.core.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.AppContext
|
||||||
import javax.inject.*
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AppScope
|
@AppScope
|
||||||
class RingtoneManager
|
class RingtoneManager
|
||||||
@@ -54,8 +57,10 @@ class RingtoneManager
|
|||||||
fun getURI(): Uri? {
|
fun getURI(): Uri? {
|
||||||
var ringtoneUri: Uri? = null
|
var ringtoneUri: Uri? = null
|
||||||
val defaultRingtoneUri = Settings.System.DEFAULT_NOTIFICATION_URI
|
val defaultRingtoneUri = Settings.System.DEFAULT_NOTIFICATION_URI
|
||||||
val prefRingtoneUri = prefs.getString("pref_ringtone_uri",
|
val prefRingtoneUri = prefs.getString(
|
||||||
defaultRingtoneUri.toString())!!
|
"pref_ringtone_uri",
|
||||||
|
defaultRingtoneUri.toString()
|
||||||
|
)!!
|
||||||
if (prefRingtoneUri.isNotEmpty())
|
if (prefRingtoneUri.isNotEmpty())
|
||||||
ringtoneUri = Uri.parse(prefRingtoneUri)
|
ringtoneUri = Uri.parse(prefRingtoneUri)
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,14 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.preferences
|
package org.isoron.uhabits.preferences
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.preference.*
|
import android.content.SharedPreferences
|
||||||
|
import android.preference.PreferenceManager
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.*
|
import org.isoron.uhabits.core.AppScope
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.inject.*
|
import org.isoron.uhabits.inject.AppContext
|
||||||
import javax.inject.*
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AppScope
|
@AppScope
|
||||||
class SharedPreferencesStorage
|
class SharedPreferencesStorage
|
||||||
@@ -76,8 +77,10 @@ class SharedPreferencesStorage
|
|||||||
override fun remove(key: String) =
|
override fun remove(key: String) =
|
||||||
sharedPrefs.edit().remove(key).apply()
|
sharedPrefs.edit().remove(key).apply()
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences,
|
override fun onSharedPreferenceChanged(
|
||||||
key: String) {
|
sharedPreferences: SharedPreferences,
|
||||||
|
key: String
|
||||||
|
) {
|
||||||
val preferences = this.preferences ?: return
|
val preferences = this.preferences ?: return
|
||||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||||
when (key) {
|
when (key) {
|
||||||
|
|||||||
@@ -19,9 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.sync
|
package org.isoron.uhabits.sync
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.net.*
|
import android.net.ConnectivityManager
|
||||||
import org.isoron.uhabits.core.sync.*
|
import android.net.Network
|
||||||
|
import android.net.NetworkRequest
|
||||||
|
import org.isoron.uhabits.core.sync.NetworkManager
|
||||||
|
|
||||||
class AndroidNetworkManager(
|
class AndroidNetworkManager(
|
||||||
val context: Context,
|
val context: Context,
|
||||||
|
|||||||
@@ -19,15 +19,26 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.sync
|
package org.isoron.uhabits.sync
|
||||||
|
|
||||||
import android.util.*
|
import android.util.Log
|
||||||
import io.ktor.client.*
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.engine.android.*
|
import io.ktor.client.engine.android.Android
|
||||||
import io.ktor.client.features.*
|
import io.ktor.client.features.ClientRequestException
|
||||||
import io.ktor.client.features.json.*
|
import io.ktor.client.features.ServerResponseException
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.features.json.JsonFeature
|
||||||
import kotlinx.coroutines.*
|
import io.ktor.client.request.get
|
||||||
import org.isoron.uhabits.core.preferences.*
|
import io.ktor.client.request.header
|
||||||
import org.isoron.uhabits.core.sync.*
|
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(
|
class RemoteSyncServer(
|
||||||
private val preferences: Preferences,
|
private val preferences: Preferences,
|
||||||
|
|||||||
@@ -19,14 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.utils
|
package org.isoron.uhabits.utils
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import org.isoron.uhabits.*
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.*
|
import org.isoron.uhabits.core.models.WeekdayList
|
||||||
import org.isoron.uhabits.core.utils.*
|
import org.isoron.uhabits.core.utils.DateFormats
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import java.text.*
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Calendar
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
fun String.toSimpleDataFormat(): SimpleDateFormat {
|
fun String.toSimpleDataFormat(): SimpleDateFormat {
|
||||||
val locale = Locale.getDefault()
|
val locale = Locale.getDefault()
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ package org.isoron.uhabits.utils
|
|||||||
|
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.util.Log
|
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) {
|
fun File.copyTo(dst: File) {
|
||||||
val inStream = FileInputStream(this)
|
val inStream = FileInputStream(this)
|
||||||
@@ -50,7 +53,7 @@ object FileUtils {
|
|||||||
Log.e("FileUtils", "getDir: all potential parents are null or non-writable")
|
Log.e("FileUtils", "getDir: all potential parents are null or non-writable")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val dir = File("${chosenDir.absolutePath}/${relativePath}/")
|
val dir = File("${chosenDir.absolutePath}/$relativePath/")
|
||||||
if (!dir.exists() && !dir.mkdirs()) {
|
if (!dir.exists() && !dir.mkdirs()) {
|
||||||
Log.e("FileUtils", "getDir: chosen dir does not exist and cannot be created")
|
Log.e("FileUtils", "getDir: chosen dir does not exist and cannot be created")
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -18,13 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.utils
|
package org.isoron.uhabits.utils
|
||||||
|
|
||||||
import android.content.*
|
import android.content.Context
|
||||||
import android.graphics.*
|
import android.graphics.Typeface
|
||||||
import android.util.*
|
import android.util.TypedValue
|
||||||
import android.view.*
|
import android.view.View
|
||||||
import android.widget.*
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView.*
|
import android.widget.TextView
|
||||||
import androidx.core.view.*
|
import android.widget.TextView.OnEditorActionListener
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
|
||||||
object InterfaceUtils {
|
object InterfaceUtils {
|
||||||
private var fontAwesome: Typeface? = null
|
private var fontAwesome: Typeface? = null
|
||||||
@@ -46,17 +47,21 @@ object InterfaceUtils {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun dpToPixels(context: Context, dp: Float): Float {
|
fun dpToPixels(context: Context, dp: Float): Float {
|
||||||
if (fixedResolution != null) return dp * fixedResolution!!
|
if (fixedResolution != null) return dp * fixedResolution!!
|
||||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
return TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
dp,
|
dp,
|
||||||
context.resources.displayMetrics)
|
context.resources.displayMetrics
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun spToPixels(context: Context, sp: Float): Float {
|
fun spToPixels(context: Context, sp: Float): Float {
|
||||||
if (fixedResolution != null) return sp * fixedResolution!!
|
if (fixedResolution != null) return sp * fixedResolution!!
|
||||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
|
return TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
sp,
|
sp,
|
||||||
context.resources.displayMetrics)
|
context.resources.displayMetrics
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -69,8 +74,10 @@ object InterfaceUtils {
|
|||||||
return dim
|
return dim
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupEditorAction(parent: ViewGroup,
|
fun setupEditorAction(
|
||||||
listener: OnEditorActionListener) {
|
parent: ViewGroup,
|
||||||
|
listener: OnEditorActionListener
|
||||||
|
) {
|
||||||
for (i in 0 until parent.childCount) {
|
for (i in 0 until parent.childCount) {
|
||||||
val child = parent.getChildAt(i)
|
val child = parent.getChildAt(i)
|
||||||
if (child is ViewGroup) setupEditorAction(child, listener)
|
if (child is ViewGroup) setupEditorAction(child, listener)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user