mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Merge branch 'dev' into feat-1074
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
val kotlinVersion = "1.5.0"
|
val kotlinVersion = "1.5.0"
|
||||||
id("com.android.application") version ("7.0.2") apply (false)
|
id("com.android.application") version ("7.0.3") apply (false)
|
||||||
id("org.jetbrains.kotlin.android") version kotlinVersion apply (false)
|
id("org.jetbrains.kotlin.android") version kotlinVersion apply (false)
|
||||||
id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false)
|
id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false)
|
||||||
id("org.jetbrains.kotlin.android.extensions") version kotlinVersion apply (false)
|
id("org.jetbrains.kotlin.android.extensions") version kotlinVersion apply (false)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
val daggerVersion = "2.39"
|
val daggerVersion = "2.40"
|
||||||
val kotlinVersion = "1.5.31"
|
val kotlinVersion = "1.5.31"
|
||||||
val kxCoroutinesVersion = "1.5.2"
|
val kxCoroutinesVersion = "1.5.2"
|
||||||
val ktorVersion = "1.6.4"
|
val ktorVersion = "1.6.4"
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -55,6 +55,7 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
class HabitsTest : BaseUserInterfaceTest() {
|
class HabitsTest : BaseUserInterfaceTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun shouldCreateHabit() {
|
fun shouldCreateHabit() {
|
||||||
@@ -180,6 +181,8 @@ class HabitsTest : BaseUserInterfaceTest() {
|
|||||||
longPressCheckmarks("Wake up early", count = 2)
|
longPressCheckmarks("Wake up early", count = 2)
|
||||||
clickText("Wake up early")
|
clickText("Wake up early")
|
||||||
verifyShowsScreen(SHOW_HABIT)
|
verifyShowsScreen(SHOW_HABIT)
|
||||||
|
// TODO: find a better way than sleeping in tests
|
||||||
|
Thread.sleep(2001L)
|
||||||
verifyDisplaysText("10%")
|
verifyDisplaysText("10%")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +197,8 @@ class HabitsTest : BaseUserInterfaceTest() {
|
|||||||
verifyDoesNotDisplayText("Track time")
|
verifyDoesNotDisplayText("Track time")
|
||||||
verifyDisplaysText("Wake up early")
|
verifyDisplaysText("Wake up early")
|
||||||
longPressCheckmarks("Wake up early", count = 1)
|
longPressCheckmarks("Wake up early", count = 1)
|
||||||
|
// TODO: find a better way than sleeping in tests
|
||||||
|
Thread.sleep(2001L)
|
||||||
verifyDoesNotDisplayText("Wake up early")
|
verifyDoesNotDisplayText("Wake up early")
|
||||||
clickMenu(TOGGLE_COMPLETED)
|
clickMenu(TOGGLE_COMPLETED)
|
||||||
verifyDisplaysText("Track time")
|
verifyDisplaysText("Track time")
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
|
|||||||
|
|
||||||
override fun onQuestionMarksChanged() {
|
override fun onQuestionMarksChanged() {
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
menu.behavior.onPreferencesChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class ListHabitsMenu @Inject constructor(
|
|||||||
@ActivityContext context: Context,
|
@ActivityContext context: Context,
|
||||||
private val preferences: Preferences,
|
private val preferences: Preferences,
|
||||||
private val themeSwitcher: ThemeSwitcher,
|
private val themeSwitcher: ThemeSwitcher,
|
||||||
private val behavior: ListHabitsMenuBehavior
|
val behavior: ListHabitsMenuBehavior
|
||||||
) {
|
) {
|
||||||
val activity = (context as AppCompatActivity)
|
val activity = (context as AppCompatActivity)
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO
|
|||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.inject.ActivityContext
|
import org.isoron.uhabits.inject.ActivityContext
|
||||||
import org.isoron.uhabits.utils.dim
|
|
||||||
import org.isoron.uhabits.utils.drawNotesIndicator
|
import org.isoron.uhabits.utils.drawNotesIndicator
|
||||||
import org.isoron.uhabits.utils.getFontAwesome
|
import org.isoron.uhabits.utils.getFontAwesome
|
||||||
|
import org.isoron.uhabits.utils.sp
|
||||||
import org.isoron.uhabits.utils.sres
|
import org.isoron.uhabits.utils.sres
|
||||||
import org.isoron.uhabits.utils.toMeasureSpec
|
import org.isoron.uhabits.utils.toMeasureSpec
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -154,6 +154,11 @@ class CheckmarkButtonView(
|
|||||||
}
|
}
|
||||||
else -> R.string.fa_check
|
else -> R.string.fa_check
|
||||||
}
|
}
|
||||||
|
paint.textSize = when {
|
||||||
|
id == R.string.fa_question -> sp(12.0f)
|
||||||
|
value == YES_AUTO -> sp(13.0f)
|
||||||
|
else -> sp(14.0f)
|
||||||
|
}
|
||||||
if (value == YES_AUTO) {
|
if (value == YES_AUTO) {
|
||||||
paint.strokeWidth = 5f
|
paint.strokeWidth = 5f
|
||||||
paint.style = Paint.Style.STROKE
|
paint.style = Paint.Style.STROKE
|
||||||
@@ -162,11 +167,6 @@ class CheckmarkButtonView(
|
|||||||
paint.style = Paint.Style.FILL
|
paint.style = Paint.Style.FILL
|
||||||
}
|
}
|
||||||
|
|
||||||
paint.textSize = when (id) {
|
|
||||||
UNKNOWN -> dim(R.dimen.smallerTextSize)
|
|
||||||
else -> dim(R.dimen.smallTextSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
val label = resources.getString(id)
|
val label = resources.getString(id)
|
||||||
val em = paint.measureText("m")
|
val em = paint.measureText("m")
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import android.widget.TextView
|
|||||||
import org.isoron.platform.gui.toInt
|
import org.isoron.platform.gui.toInt
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.common.views.RingView
|
import org.isoron.uhabits.activities.common.views.RingView
|
||||||
|
import org.isoron.uhabits.activities.habits.list.views.HabitCardView.Companion.delay
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.models.ModelObservable
|
import org.isoron.uhabits.core.models.ModelObservable
|
||||||
import org.isoron.uhabits.core.models.Timestamp
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
@@ -150,7 +151,11 @@ class HabitCardView(
|
|||||||
checkmarkPanel = checkmarkPanelFactory.create().apply {
|
checkmarkPanel = checkmarkPanelFactory.create().apply {
|
||||||
onToggle = { timestamp, value ->
|
onToggle = { timestamp, value ->
|
||||||
triggerRipple(timestamp)
|
triggerRipple(timestamp)
|
||||||
habit?.let { behavior.onToggle(it, timestamp, value) }
|
habit?.let {
|
||||||
|
{
|
||||||
|
behavior.onToggle(it, timestamp, value)
|
||||||
|
}.delay(TOGGLE_DELAY_MILLIS)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onEdit = { timestamp ->
|
onEdit = { timestamp ->
|
||||||
triggerRipple(timestamp)
|
triggerRipple(timestamp)
|
||||||
@@ -274,4 +279,12 @@ class HabitCardView(
|
|||||||
}
|
}
|
||||||
innerFrame.setBackgroundResource(background)
|
innerFrame.setBackgroundResource(background)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TOGGLE_DELAY_MILLIS = 2000L
|
||||||
|
|
||||||
|
fun (() -> Unit).delay(delayInMillis: Long) {
|
||||||
|
Handler(Looper.getMainLooper()).postDelayed(this, delayInMillis)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,17 +23,17 @@ import android.os.Bundle
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.isoron.uhabits.HabitsApplication
|
import org.isoron.uhabits.HabitsApplication
|
||||||
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
import org.isoron.uhabits.core.models.HabitMatcherBuilder
|
import org.isoron.uhabits.core.models.HabitMatcher
|
||||||
|
|
||||||
class EditSettingActivity : AppCompatActivity() {
|
class EditSettingActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val app = applicationContext as HabitsApplication
|
val app = applicationContext as HabitsApplication
|
||||||
val habits = app.component.habitList.getFiltered(
|
val habits = app.component.habitList.getFiltered(
|
||||||
HabitMatcherBuilder()
|
HabitMatcher(
|
||||||
.setArchivedAllowed(false)
|
isArchivedAllowed = false,
|
||||||
.setCompletedAllowed(true)
|
isCompletedAllowed = true,
|
||||||
.build()
|
)
|
||||||
)
|
)
|
||||||
AndroidThemeSwitcher(this, app.component.preferences).apply()
|
AndroidThemeSwitcher(this, app.component.preferences).apply()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
2015-01-25,0.0000
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
2015-01-25,2
|
||||||
|
2015-01-24,0
|
||||||
|
2015-01-23,1
|
||||||
|
2015-01-22,2
|
||||||
|
2015-01-21,2
|
||||||
|
2015-01-20,2
|
||||||
|
2015-01-19,1
|
||||||
|
2015-01-18,1
|
||||||
|
2015-01-17,2
|
||||||
|
2015-01-16,2
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
2015-01-25,0.2557
|
||||||
|
2015-01-24,0.2226
|
||||||
|
2015-01-23,0.1991
|
||||||
|
2015-01-22,0.1746
|
||||||
|
2015-01-21,0.1379
|
||||||
|
2015-01-20,0.0995
|
||||||
|
2015-01-19,0.0706
|
||||||
|
2015-01-18,0.0515
|
||||||
|
2015-01-17,0.0315
|
||||||
|
2015-01-16,0.0107
|
||||||
|
11
uhabits-core/assets/test/csv_export/Checkmarks.csv
Normal file
11
uhabits-core/assets/test/csv_export/Checkmarks.csv
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Date,Meditate,Wake up early,
|
||||||
|
2015-01-25,-1,2,
|
||||||
|
2015-01-24,-1,0,
|
||||||
|
2015-01-23,-1,1,
|
||||||
|
2015-01-22,-1,2,
|
||||||
|
2015-01-21,-1,2,
|
||||||
|
2015-01-20,-1,2,
|
||||||
|
2015-01-19,-1,1,
|
||||||
|
2015-01-18,-1,1,
|
||||||
|
2015-01-17,-1,2,
|
||||||
|
2015-01-16,-1,2,
|
||||||
|
3
uhabits-core/assets/test/csv_export/Habits.csv
Normal file
3
uhabits-core/assets/test/csv_export/Habits.csv
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Position,Name,Question,Description,NumRepetitions,Interval,Color
|
||||||
|
001,Meditate,Did you meditate this morning?,,1,1,#FF8F00
|
||||||
|
002,Wake up early,Did you wake up before 6am?,,2,3,#00897B
|
||||||
|
11
uhabits-core/assets/test/csv_export/Scores.csv
Normal file
11
uhabits-core/assets/test/csv_export/Scores.csv
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Date,Meditate,Wake up early,
|
||||||
|
2015-01-25,0.0000,0.2557,
|
||||||
|
2015-01-24,0.0000,0.2226,
|
||||||
|
2015-01-23,0.0000,0.1991,
|
||||||
|
2015-01-22,0.0000,0.1746,
|
||||||
|
2015-01-21,0.0000,0.1379,
|
||||||
|
2015-01-20,0.0000,0.0995,
|
||||||
|
2015-01-19,0.0000,0.0706,
|
||||||
|
2015-01-18,0.0000,0.0515,
|
||||||
|
2015-01-17,0.0000,0.0315,
|
||||||
|
2015-01-16,0.0000,0.0107,
|
||||||
|
@@ -43,7 +43,7 @@ kotlin {
|
|||||||
val jvmMain by getting {
|
val jvmMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("stdlib-jdk8"))
|
implementation(kotlin("stdlib-jdk8"))
|
||||||
compileOnly("com.google.dagger:dagger:2.39")
|
compileOnly("com.google.dagger:dagger:2.40")
|
||||||
implementation("com.google.guava:guava:31.0.1-android")
|
implementation("com.google.guava:guava:31.0.1-android")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.31")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.31")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2")
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class HabitsCSVExporter(
|
|||||||
checksWriter.write(sb.toString())
|
checksWriter.write(sb.toString())
|
||||||
scoresWriter.write(sb.toString())
|
scoresWriter.write(sb.toString())
|
||||||
for (j in selectedHabits.indices) {
|
for (j in selectedHabits.indices) {
|
||||||
checksWriter.write(checkmarks[j][i].toString())
|
checksWriter.write(checkmarks[j][i].value.toString())
|
||||||
checksWriter.write(delimiter)
|
checksWriter.write(delimiter)
|
||||||
val score = String.format(Locale.US, "%.4f", scores[j][i].value)
|
val score = String.format(Locale.US, "%.4f", scores[j][i].value)
|
||||||
scoresWriter.write(score)
|
scoresWriter.write(score)
|
||||||
|
|||||||
@@ -68,17 +68,10 @@ data class Habit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFailedToday(): Boolean {
|
fun isEnteredToday(): Boolean {
|
||||||
val today = DateUtils.getTodayWithOffset()
|
val today = DateUtils.getTodayWithOffset()
|
||||||
val value = computedEntries.get(today).value
|
val value = computedEntries.get(today).value
|
||||||
return if (isNumerical) {
|
return value != Entry.UNKNOWN
|
||||||
when (targetType) {
|
|
||||||
NumericalHabitType.AT_LEAST -> value / 1000.0 < targetValue
|
|
||||||
NumericalHabitType.AT_MOST -> value / 1000.0 > targetValue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value == Entry.NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun recompute() {
|
fun recompute() {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ abstract class HabitList : Iterable<Habit> {
|
|||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
observable = ModelObservable()
|
observable = ModelObservable()
|
||||||
filter = HabitMatcherBuilder().setArchivedAllowed(true).build()
|
filter = HabitMatcher(isArchivedAllowed = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected constructor(filter: HabitMatcher) {
|
protected constructor(filter: HabitMatcher) {
|
||||||
|
|||||||
@@ -22,19 +22,21 @@ data class HabitMatcher(
|
|||||||
val isArchivedAllowed: Boolean = false,
|
val isArchivedAllowed: Boolean = false,
|
||||||
val isReminderRequired: Boolean = false,
|
val isReminderRequired: Boolean = false,
|
||||||
val isCompletedAllowed: Boolean = true,
|
val isCompletedAllowed: Boolean = true,
|
||||||
|
val isEnteredAllowed: Boolean = true,
|
||||||
) {
|
) {
|
||||||
fun matches(habit: Habit): Boolean {
|
fun matches(habit: Habit): Boolean {
|
||||||
if (!isArchivedAllowed && habit.isArchived) return false
|
if (!isArchivedAllowed && habit.isArchived) return false
|
||||||
if (isReminderRequired && !habit.hasReminder()) return false
|
if (isReminderRequired && !habit.hasReminder()) return false
|
||||||
if (!isCompletedAllowed && (habit.isCompletedToday() || habit.isFailedToday())) return false
|
if (!isCompletedAllowed && habit.isCompletedToday()) return false
|
||||||
|
if (!isEnteredAllowed && habit.isEnteredToday()) return false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val WITH_ALARM = HabitMatcherBuilder()
|
val WITH_ALARM = HabitMatcher(
|
||||||
.setArchivedAllowed(true)
|
isArchivedAllowed = true,
|
||||||
.setReminderRequired(true)
|
isReminderRequired = true,
|
||||||
.build()
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
|
||||||
*
|
|
||||||
* This file is part of Loop Habit Tracker.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.isoron.uhabits.core.models
|
|
||||||
|
|
||||||
class HabitMatcherBuilder {
|
|
||||||
private var archivedAllowed = false
|
|
||||||
private var reminderRequired = false
|
|
||||||
private var completedAllowed = true
|
|
||||||
|
|
||||||
fun build(): HabitMatcher {
|
|
||||||
return HabitMatcher(
|
|
||||||
isArchivedAllowed = archivedAllowed,
|
|
||||||
isReminderRequired = reminderRequired,
|
|
||||||
isCompletedAllowed = completedAllowed,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setArchivedAllowed(archivedAllowed: Boolean): HabitMatcherBuilder {
|
|
||||||
this.archivedAllowed = archivedAllowed
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setCompletedAllowed(completedAllowed: Boolean): HabitMatcherBuilder {
|
|
||||||
this.completedAllowed = completedAllowed
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setReminderRequired(reminderRequired: Boolean): HabitMatcherBuilder {
|
|
||||||
this.reminderRequired = reminderRequired
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ package org.isoron.uhabits.core.ui.screens.habits.list
|
|||||||
|
|
||||||
import org.isoron.uhabits.core.models.HabitList
|
import org.isoron.uhabits.core.models.HabitList
|
||||||
import org.isoron.uhabits.core.models.HabitMatcher
|
import org.isoron.uhabits.core.models.HabitMatcher
|
||||||
import org.isoron.uhabits.core.models.HabitMatcherBuilder
|
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.ui.ThemeSwitcher
|
import org.isoron.uhabits.core.ui.ThemeSwitcher
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -33,6 +32,7 @@ class ListHabitsMenuBehavior @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
private var showCompleted: Boolean
|
private var showCompleted: Boolean
|
||||||
private var showArchived: Boolean
|
private var showArchived: Boolean
|
||||||
|
|
||||||
fun onCreateHabit() {
|
fun onCreateHabit() {
|
||||||
screen.showSelectHabitTypeDialog()
|
screen.showSelectHabitTypeDialog()
|
||||||
}
|
}
|
||||||
@@ -97,13 +97,26 @@ class ListHabitsMenuBehavior @Inject constructor(
|
|||||||
screen.applyTheme()
|
screen.applyTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onPreferencesChanged() {
|
||||||
|
updateAdapterFilter()
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateAdapterFilter() {
|
private fun updateAdapterFilter() {
|
||||||
adapter.setFilter(
|
if (preferences.areQuestionMarksEnabled) {
|
||||||
HabitMatcherBuilder()
|
adapter.setFilter(
|
||||||
.setArchivedAllowed(showArchived)
|
HabitMatcher(
|
||||||
.setCompletedAllowed(showCompleted)
|
isArchivedAllowed = showArchived,
|
||||||
.build()
|
isEnteredAllowed = showCompleted,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
adapter.setFilter(
|
||||||
|
HabitMatcher(
|
||||||
|
isArchivedAllowed = showArchived,
|
||||||
|
isCompletedAllowed = showCompleted,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
adapter.refresh()
|
adapter.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ abstract class DateUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getLocalTime(): Long {
|
fun getLocalTime(utcTimeInMillis: Long? = null): Long {
|
||||||
if (fixedLocalTime != null) return fixedLocalTime as Long
|
if (fixedLocalTime != null) return fixedLocalTime as Long
|
||||||
|
|
||||||
val tz = getTimeZone()
|
val tz = getTimeZone()
|
||||||
val now = Date().time
|
val now = utcTimeInMillis ?: Date().time
|
||||||
return now + tz.getOffset(now)
|
return now + tz.getOffset(now)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ abstract class DateUtils {
|
|||||||
format: Int,
|
format: Int,
|
||||||
firstWeekDay: Int
|
firstWeekDay: Int
|
||||||
): Array<String> {
|
): Array<String> {
|
||||||
val calendar = GregorianCalendar()
|
val calendar = GregorianCalendar(getLocale())
|
||||||
calendar.set(DAY_OF_WEEK, firstWeekDay)
|
calendar.set(DAY_OF_WEEK, firstWeekDay)
|
||||||
|
|
||||||
val daysNullable = ArrayList<String>()
|
val daysNullable = ArrayList<String>()
|
||||||
@@ -149,7 +149,7 @@ abstract class DateUtils {
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getFirstWeekdayNumberAccordingToLocale(): Int {
|
fun getFirstWeekdayNumberAccordingToLocale(): Int {
|
||||||
return GregorianCalendar().firstDayOfWeek
|
return GregorianCalendar(getLocale()).firstDayOfWeek
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,13 +214,7 @@ abstract class DateUtils {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getStartOfTodayCalendarWithOffset(): GregorianCalendar = getCalendar(getStartOfTodayWithOffset())
|
fun getStartOfTodayCalendarWithOffset(): GregorianCalendar = getCalendar(getStartOfTodayWithOffset())
|
||||||
|
|
||||||
@JvmStatic
|
private fun getTimeZone(): TimeZone {
|
||||||
fun getTimeZone(): TimeZone {
|
|
||||||
return fixedTimeZone ?: TimeZone.getDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun getTimezone(): TimeZone {
|
|
||||||
return fixedTimeZone ?: TimeZone.getDefault()
|
return fixedTimeZone ?: TimeZone.getDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +230,7 @@ abstract class DateUtils {
|
|||||||
startDayMinuteOffset = minuteOffset
|
startDayMinuteOffset = minuteOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
private fun getLocale(): Locale {
|
||||||
fun getLocale(): Locale {
|
|
||||||
return fixedLocale ?: Locale.getDefault()
|
return fixedLocale ?: Locale.getDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import java.util.zip.ZipFile
|
|||||||
|
|
||||||
class HabitsCSVExporterTest : BaseUnitTest() {
|
class HabitsCSVExporterTest : BaseUnitTest() {
|
||||||
private lateinit var baseDir: File
|
private lateinit var baseDir: File
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -41,12 +42,7 @@ class HabitsCSVExporterTest : BaseUnitTest() {
|
|||||||
habitList.add(fixtures.createShortHabit())
|
habitList.add(fixtures.createShortHabit())
|
||||||
habitList.add(fixtures.createEmptyHabit())
|
habitList.add(fixtures.createEmptyHabit())
|
||||||
baseDir = Files.createTempDirectory("csv").toFile()
|
baseDir = Files.createTempDirectory("csv").toFile()
|
||||||
}
|
baseDir.deleteOnExit()
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
override fun tearDown() {
|
|
||||||
FileUtils.deleteDirectory(baseDir)
|
|
||||||
super.tearDown()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -63,14 +59,20 @@ class HabitsCSVExporterTest : BaseUnitTest() {
|
|||||||
assertAbsolutePathExists(filename)
|
assertAbsolutePathExists(filename)
|
||||||
val archive = File(filename)
|
val archive = File(filename)
|
||||||
unzip(archive)
|
unzip(archive)
|
||||||
assertPathExists("Habits.csv")
|
val filesToCheck = arrayOf(
|
||||||
assertPathExists("001 Meditate/Checkmarks.csv")
|
"001 Meditate/Checkmarks.csv",
|
||||||
assertPathExists("001 Meditate/Scores.csv")
|
"001 Meditate/Scores.csv",
|
||||||
assertPathExists("002 Wake up early")
|
"002 Wake up early/Checkmarks.csv",
|
||||||
assertPathExists("002 Wake up early/Checkmarks.csv")
|
"002 Wake up early/Scores.csv",
|
||||||
assertPathExists("002 Wake up early/Scores.csv")
|
"Checkmarks.csv",
|
||||||
assertPathExists("Checkmarks.csv")
|
"Habits.csv",
|
||||||
assertPathExists("Scores.csv")
|
"Scores.csv"
|
||||||
|
)
|
||||||
|
|
||||||
|
for (file in filesToCheck) {
|
||||||
|
assertPathExists(file)
|
||||||
|
assertFileAndReferenceAreEqual(file)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
@@ -104,4 +106,18 @@ class HabitsCSVExporterTest : BaseUnitTest() {
|
|||||||
file.exists()
|
file.exists()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun assertFileAndReferenceAreEqual(s: String) {
|
||||||
|
val assetFilename = String.format("csv_export/%s", s)
|
||||||
|
val file = File.createTempFile("asset", "")
|
||||||
|
file.deleteOnExit()
|
||||||
|
copyAssetToFile(assetFilename, file)
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
FileUtils.contentEquals(
|
||||||
|
file,
|
||||||
|
File(String.format("%s/%s", baseDir.absolutePath, s))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ class HabitListTest : BaseUnitTest() {
|
|||||||
habitsArray[1].isArchived = true
|
habitsArray[1].isArchived = true
|
||||||
habitsArray[4].isArchived = true
|
habitsArray[4].isArchived = true
|
||||||
habitsArray[7].isArchived = true
|
habitsArray[7].isArchived = true
|
||||||
activeHabits = habitList.getFiltered(HabitMatcherBuilder().build())
|
activeHabits = habitList.getFiltered(HabitMatcher())
|
||||||
reminderHabits = habitList.getFiltered(
|
reminderHabits = habitList.getFiltered(
|
||||||
HabitMatcherBuilder()
|
HabitMatcher(
|
||||||
.setArchivedAllowed(true)
|
isArchivedAllowed = true,
|
||||||
.setReminderRequired(true)
|
isReminderRequired = true,
|
||||||
.build()
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +181,10 @@ class HabitListTest : BaseUnitTest() {
|
|||||||
fun testOrder_inherit() {
|
fun testOrder_inherit() {
|
||||||
habitList.primaryOrder = HabitList.Order.BY_COLOR_ASC
|
habitList.primaryOrder = HabitList.Order.BY_COLOR_ASC
|
||||||
val filteredList = habitList.getFiltered(
|
val filteredList = habitList.getFiltered(
|
||||||
HabitMatcherBuilder()
|
HabitMatcher(
|
||||||
.setArchivedAllowed(false)
|
isArchivedAllowed = false,
|
||||||
.setCompletedAllowed(false)
|
isCompletedAllowed = false,
|
||||||
.build()
|
)
|
||||||
)
|
)
|
||||||
assertEquals(filteredList.primaryOrder, HabitList.Order.BY_COLOR_ASC)
|
assertEquals(filteredList.primaryOrder, HabitList.Order.BY_COLOR_ASC)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,12 +82,12 @@ class HabitTest : BaseUnitTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun test_isFailed() {
|
fun test_isEntered() {
|
||||||
val h = modelFactory.buildHabit()
|
val h = modelFactory.buildHabit()
|
||||||
assertFalse(h.isFailedToday())
|
assertFalse(h.isEnteredToday())
|
||||||
h.originalEntries.add(Entry(getToday(), Entry.NO))
|
h.originalEntries.add(Entry(getToday(), Entry.NO))
|
||||||
h.recompute()
|
h.recompute()
|
||||||
assertTrue(h.isFailedToday())
|
assertTrue(h.isEnteredToday())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -119,35 +119,6 @@ class HabitTest : BaseUnitTest() {
|
|||||||
assertTrue(h.isCompletedToday())
|
assertTrue(h.isCompletedToday())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@Throws(Exception::class)
|
|
||||||
fun test_isFailedNumerical() {
|
|
||||||
val h = modelFactory.buildHabit()
|
|
||||||
h.type = HabitType.NUMERICAL
|
|
||||||
h.targetType = NumericalHabitType.AT_LEAST
|
|
||||||
h.targetValue = 100.0
|
|
||||||
assertTrue(h.isFailedToday())
|
|
||||||
h.originalEntries.add(Entry(getToday(), 200000))
|
|
||||||
h.recompute()
|
|
||||||
assertFalse(h.isFailedToday())
|
|
||||||
h.originalEntries.add(Entry(getToday(), 100000))
|
|
||||||
h.recompute()
|
|
||||||
assertFalse(h.isFailedToday())
|
|
||||||
h.originalEntries.add(Entry(getToday(), 50000))
|
|
||||||
h.recompute()
|
|
||||||
assertTrue(h.isFailedToday())
|
|
||||||
h.targetType = NumericalHabitType.AT_MOST
|
|
||||||
h.originalEntries.add(Entry(getToday(), 200000))
|
|
||||||
h.recompute()
|
|
||||||
assertTrue(h.isFailedToday())
|
|
||||||
h.originalEntries.add(Entry(getToday(), 100000))
|
|
||||||
h.recompute()
|
|
||||||
assertFalse(h.isFailedToday())
|
|
||||||
h.originalEntries.add(Entry(getToday(), 50000))
|
|
||||||
h.recompute()
|
|
||||||
assertFalse(h.isFailedToday())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testURI() {
|
fun testURI() {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import org.isoron.uhabits.core.database.Database
|
|||||||
import org.isoron.uhabits.core.database.Repository
|
import org.isoron.uhabits.core.database.Repository
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.models.HabitList
|
import org.isoron.uhabits.core.models.HabitList
|
||||||
import org.isoron.uhabits.core.models.HabitMatcherBuilder
|
import org.isoron.uhabits.core.models.HabitMatcher
|
||||||
import org.isoron.uhabits.core.models.ModelObservable
|
import org.isoron.uhabits.core.models.ModelObservable
|
||||||
import org.isoron.uhabits.core.models.Reminder
|
import org.isoron.uhabits.core.models.Reminder
|
||||||
import org.isoron.uhabits.core.models.WeekdayList
|
import org.isoron.uhabits.core.models.WeekdayList
|
||||||
@@ -69,12 +69,12 @@ class SQLiteHabitListTest : BaseUnitTest() {
|
|||||||
habitsArray[4].isArchived = true
|
habitsArray[4].isArchived = true
|
||||||
habitsArray[7].isArchived = true
|
habitsArray[7].isArchived = true
|
||||||
habitList.update(habitsArray)
|
habitList.update(habitsArray)
|
||||||
activeHabits = habitList.getFiltered(HabitMatcherBuilder().build())
|
activeHabits = habitList.getFiltered(HabitMatcher())
|
||||||
reminderHabits = habitList.getFiltered(
|
reminderHabits = habitList.getFiltered(
|
||||||
HabitMatcherBuilder()
|
HabitMatcher(
|
||||||
.setArchivedAllowed(true)
|
isArchivedAllowed = true,
|
||||||
.setReminderRequired(true)
|
isReminderRequired = true,
|
||||||
.build()
|
)
|
||||||
)
|
)
|
||||||
habitList.observable.addListener(listener)
|
habitList.observable.addListener(listener)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import org.isoron.uhabits.core.utils.DateUtils.Companion.truncate
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
import java.util.GregorianCalendar
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
|
||||||
@@ -58,6 +59,129 @@ class DateUtilsTest : BaseUnitTest() {
|
|||||||
assertThat(formatted, equalTo("Thu\n31"))
|
assertThat(formatted, equalTo("Thu\n31"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetLocalTime() {
|
||||||
|
setFixedLocalTime(null)
|
||||||
|
setFixedTimeZone(TimeZone.getTimeZone("Australia/Sydney"))
|
||||||
|
val utcTestTimeInMillis = unixTime(2015, Calendar.JANUARY, 11)
|
||||||
|
val localTimeInMillis = DateUtils.getLocalTime(utcTestTimeInMillis)
|
||||||
|
val expectedUnixTimeOffsetForSydney = 11 * 60 * 60 * 1000
|
||||||
|
val expectedUnixTimeForSydney = utcTestTimeInMillis + expectedUnixTimeOffsetForSydney
|
||||||
|
assertThat(expectedUnixTimeForSydney, equalTo(localTimeInMillis))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetWeekdaySequence() {
|
||||||
|
val weekdaySequence = DateUtils.getWeekdaySequence(3)
|
||||||
|
assertThat(arrayOf(3, 4, 5, 6, 7, 1, 2), equalTo(weekdaySequence))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetFirstWeekdayNumberAccordingToLocale_germany() {
|
||||||
|
setFixedLocale(Locale.GERMANY)
|
||||||
|
val firstWeekdayNumber = DateUtils.getFirstWeekdayNumberAccordingToLocale()
|
||||||
|
assertThat(2, equalTo(firstWeekdayNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetFirstWeekdayNumberAccordingToLocale_us() {
|
||||||
|
setFixedLocale(Locale.US)
|
||||||
|
val firstWeekdayNumber = DateUtils.getFirstWeekdayNumberAccordingToLocale()
|
||||||
|
assertThat(1, equalTo(firstWeekdayNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetLongWeekdayNames_germany() {
|
||||||
|
setFixedLocale(Locale.GERMANY)
|
||||||
|
val longWeekdayNames = DateUtils.getLongWeekdayNames(Calendar.SATURDAY)
|
||||||
|
assertThat(arrayOf("Samstag", "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"), equalTo(longWeekdayNames))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetLongWeekdayNames_us() {
|
||||||
|
setFixedLocale(Locale.US)
|
||||||
|
val longWeekdayNames = DateUtils.getLongWeekdayNames(Calendar.SATURDAY)
|
||||||
|
assertThat(arrayOf("Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"), equalTo(longWeekdayNames))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetShortWeekdayNames_germany() {
|
||||||
|
setFixedLocale(Locale.GERMANY)
|
||||||
|
val longWeekdayNames = DateUtils.getShortWeekdayNames(Calendar.SATURDAY)
|
||||||
|
assertThat(arrayOf("Sa.", "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr."), equalTo(longWeekdayNames))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetShortWeekdayNames_us() {
|
||||||
|
setFixedLocale(Locale.US)
|
||||||
|
val longWeekdayNames = DateUtils.getShortWeekdayNames(Calendar.SATURDAY)
|
||||||
|
assertThat(arrayOf("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"), equalTo(longWeekdayNames))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetToday() {
|
||||||
|
setFixedLocalTime(FIXED_LOCAL_TIME)
|
||||||
|
val today = DateUtils.getToday()
|
||||||
|
assertThat(Timestamp(FIXED_LOCAL_TIME), equalTo(today))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfDay() {
|
||||||
|
val expectedStartOfDayUtc = fixedStartOfToday()
|
||||||
|
val laterInTheDayUtc = fixedStartOfTodayWithOffset(20)
|
||||||
|
val startOfDay = DateUtils.getStartOfDay(laterInTheDayUtc)
|
||||||
|
assertThat(expectedStartOfDayUtc, equalTo(startOfDay))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfToday() {
|
||||||
|
val expectedStartOfDayUtc = fixedStartOfToday()
|
||||||
|
val laterInTheDayUtc = fixedStartOfTodayWithOffset(20)
|
||||||
|
setFixedLocalTime(laterInTheDayUtc)
|
||||||
|
val startOfToday = DateUtils.getStartOfToday()
|
||||||
|
assertThat(expectedStartOfDayUtc, equalTo(startOfToday))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTomorrowWithOffset_priorToOffset() {
|
||||||
|
val priorToOffset = HOUR_OFFSET - 1
|
||||||
|
testGetStartOfTomorrowWithOffset(priorToOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTomorrowWithOffset_afterOffset() {
|
||||||
|
val afterOffset = HOUR_OFFSET + 1 - HOURS_IN_ONE_DAY
|
||||||
|
testGetStartOfTomorrowWithOffset(afterOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun testGetStartOfTomorrowWithOffset(startOfTodayOffset: Int) {
|
||||||
|
configureOffsetTest(startOfTodayOffset)
|
||||||
|
assertThat(
|
||||||
|
fixedStartOfTodayWithOffset(HOUR_OFFSET),
|
||||||
|
equalTo(DateUtils.getStartOfTomorrowWithOffset())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTodayWithOffset_priorToOffset() {
|
||||||
|
val priorToOffset = HOURS_IN_ONE_DAY + HOUR_OFFSET - 1
|
||||||
|
testGetStartOfTodayWithOffset(priorToOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTodayWithOffset_afterOffset() {
|
||||||
|
val afterOffset = HOUR_OFFSET + 1
|
||||||
|
testGetStartOfTodayWithOffset(afterOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun testGetStartOfTodayWithOffset(startOfTodayOffset: Int) {
|
||||||
|
configureOffsetTest(startOfTodayOffset)
|
||||||
|
assertThat(
|
||||||
|
fixedStartOfToday(),
|
||||||
|
equalTo(DateUtils.getStartOfTodayWithOffset())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTruncate_dayOfWeek() {
|
fun testTruncate_dayOfWeek() {
|
||||||
val field = DateUtils.TruncateField.WEEK_NUMBER
|
val field = DateUtils.TruncateField.WEEK_NUMBER
|
||||||
@@ -142,22 +266,39 @@ class DateUtilsTest : BaseUnitTest() {
|
|||||||
assertThat(truncate(field, t2, firstWeekday), equalTo(expected))
|
assertThat(truncate(field, t2, firstWeekday), equalTo(expected))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTruncate_timestamp() {
|
||||||
|
val field = DateUtils.TruncateField.YEAR
|
||||||
|
val nonTruncatedDate = unixTime(2016, Calendar.MAY, 30)
|
||||||
|
val expected = Timestamp(unixTime(2016, Calendar.JANUARY, 1))
|
||||||
|
assertThat(expected, equalTo(truncate(field, Timestamp(nonTruncatedDate), firstWeekday)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetUpcomingTimeInMillis() {
|
||||||
|
setFixedLocalTime(FIXED_LOCAL_TIME)
|
||||||
|
setFixedTimeZone(TimeZone.getTimeZone("GMT"))
|
||||||
|
val expected = unixTime(2015, Calendar.JANUARY, 25, 10, 1)
|
||||||
|
val upcomingTimeMillis = DateUtils.getUpcomingTimeInMillis(10, 1)
|
||||||
|
assertThat(expected, equalTo(upcomingTimeMillis))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testMillisecondsUntilTomorrow() {
|
fun testMillisecondsUntilTomorrow() {
|
||||||
setFixedTimeZone(TimeZone.getTimeZone("GMT"))
|
setFixedTimeZone(TimeZone.getTimeZone("GMT"))
|
||||||
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59))
|
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59))
|
||||||
assertThat(millisecondsUntilTomorrowWithOffset(), equalTo(DateUtils.MINUTE_LENGTH))
|
assertThat(millisecondsUntilTomorrowWithOffset(), equalTo(DateUtils.MINUTE_LENGTH))
|
||||||
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 20, 0))
|
setFixedLocalTime(fixedStartOfTodayWithOffset(20))
|
||||||
assertThat(
|
assertThat(
|
||||||
millisecondsUntilTomorrowWithOffset(),
|
millisecondsUntilTomorrowWithOffset(),
|
||||||
equalTo(4 * DateUtils.HOUR_LENGTH)
|
equalTo(4 * DateUtils.HOUR_LENGTH)
|
||||||
)
|
)
|
||||||
setStartDayOffset(3, 30)
|
setStartDayOffset(HOUR_OFFSET, 30)
|
||||||
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59))
|
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59))
|
||||||
assertThat(
|
assertThat(
|
||||||
millisecondsUntilTomorrowWithOffset(),
|
millisecondsUntilTomorrowWithOffset(),
|
||||||
equalTo(3 * DateUtils.HOUR_LENGTH + 31 * DateUtils.MINUTE_LENGTH)
|
equalTo(HOUR_OFFSET * DateUtils.HOUR_LENGTH + 31 * DateUtils.MINUTE_LENGTH)
|
||||||
)
|
)
|
||||||
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 2, 1, 0))
|
setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 2, 1, 0))
|
||||||
assertThat(
|
assertThat(
|
||||||
@@ -166,6 +307,52 @@ class DateUtilsTest : BaseUnitTest() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTodayCalendar() {
|
||||||
|
setFixedLocalTime(FIXED_LOCAL_TIME)
|
||||||
|
setFixedLocale(Locale.GERMANY)
|
||||||
|
val expectedStartOfDay = unixTime(2015, Calendar.JANUARY, 25, 0, 0)
|
||||||
|
val expectedCalendar = GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.GERMANY)
|
||||||
|
expectedCalendar.timeInMillis = expectedStartOfDay
|
||||||
|
val startOfTodayCalendar = DateUtils.getStartOfTodayCalendar()
|
||||||
|
assertThat(expectedCalendar, equalTo(startOfTodayCalendar))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTodayCalendarWithOffset_priorToOffset() {
|
||||||
|
val priorToOffset = HOUR_OFFSET - 1
|
||||||
|
testGetStartOfTodayCalendarWithOffset(priorToOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetStartOfTodayCalendarWithOffset_afterOffset() {
|
||||||
|
val afterOffset = HOUR_OFFSET + 1
|
||||||
|
testGetStartOfTodayCalendarWithOffset(afterOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun testGetStartOfTodayCalendarWithOffset(startOfTodayOffset: Int) {
|
||||||
|
configureOffsetTest(startOfTodayOffset)
|
||||||
|
setFixedLocale(Locale.GERMANY)
|
||||||
|
val expectedCalendar = GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.GERMANY)
|
||||||
|
expectedCalendar.timeInMillis = fixedStartOfToday()
|
||||||
|
assertThat(
|
||||||
|
expectedCalendar,
|
||||||
|
equalTo(DateUtils.getStartOfTodayCalendar())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureOffsetTest(startOfTodayOffset: Int) {
|
||||||
|
setStartDayOffset(HOUR_OFFSET, 0)
|
||||||
|
setFixedTimeZone(TimeZone.getTimeZone("GMT"))
|
||||||
|
setFixedLocalTime(fixedStartOfTodayWithOffset(startOfTodayOffset))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fixedStartOfToday() = fixedStartOfTodayWithOffset(0)
|
||||||
|
|
||||||
|
private fun fixedStartOfTodayWithOffset(hourOffset: Int): Long {
|
||||||
|
return unixTime(2017, Calendar.JANUARY, 1, hourOffset, 0)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testGetTodayWithOffset() {
|
fun testGetTodayWithOffset() {
|
||||||
@@ -469,4 +656,9 @@ class DateUtilsTest : BaseUnitTest() {
|
|||||||
unixTime(2018, Calendar.APRIL, 1, 18, 0)
|
unixTime(2018, Calendar.APRIL, 1, 18, 0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val HOUR_OFFSET = 3
|
||||||
|
const val HOURS_IN_ONE_DAY = 24
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.isoron.uhabits.core.utils
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.BaseUnitTest
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class FileExtensionsTest : BaseUnitTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsSQLite3File() {
|
||||||
|
val file = File.createTempFile("asset", "")
|
||||||
|
copyAssetToFile("loop.db", file)
|
||||||
|
val isSqlite3File = file.isSQLite3File()
|
||||||
|
assertTrue(isSqlite3File)
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,19 +0,0 @@
|
|||||||
HabitName,HabitDescription,HabitCategory,CalendarDate,Value,CommentText
|
|
||||||
Breed dragons,with love and fire,Diet & Food,2016-03-18,1,
|
|
||||||
Breed dragons,with love and fire,Diet & Food,2016-03-19,1,
|
|
||||||
Breed dragons,with love and fire,Diet & Food,2016-03-21,1,
|
|
||||||
Reduce sleep,only 2 hours per day,Time Management,2016-03-15,1,
|
|
||||||
Reduce sleep,only 2 hours per day,Time Management,2016-03-16,1,
|
|
||||||
Reduce sleep,only 2 hours per day,Time Management,2016-03-17,1,
|
|
||||||
Reduce sleep,only 2 hours per day,Time Management,2016-03-21,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-15,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-16,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-18,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-21,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-15,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-16,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-18,1,
|
|
||||||
No-arms pushup,Become like water my friend!,Fitness,2016-03-21,1,
|
|
||||||
Grow spiritually,"transcend ego, practice compassion, smile and breath",Meditation,2016-03-15,1,
|
|
||||||
Grow spiritually,"transcend ego, practice compassion, smile and breath",Meditation,2016-03-17,1,
|
|
||||||
Grow spiritually,"transcend ego, practice compassion, smile and breath",Meditation,2016-03-21,1,
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -22,7 +22,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|||||||
plugins {
|
plugins {
|
||||||
application
|
application
|
||||||
id("kotlin")
|
id("kotlin")
|
||||||
id("com.github.johnrengelman.shadow") version "7.0.0"
|
id("com.github.johnrengelman.shadow") version "7.1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user