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