mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Clean up code after conversions
This commit is contained in:
@@ -201,7 +201,7 @@ abstract class BaseAndroidTest : TestCase() {
|
|||||||
Thread.sleep(1000)
|
Thread.sleep(1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var savedCalendar: GregorianCalendar? = null
|
private lateinit var savedCalendar: GregorianCalendar
|
||||||
fun saveSystemTime() {
|
fun saveSystemTime() {
|
||||||
savedCalendar = GregorianCalendar()
|
savedCalendar = GregorianCalendar()
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ abstract class BaseAndroidTest : TestCase() {
|
|||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun restoreSystemTime() {
|
fun restoreSystemTime() {
|
||||||
if (savedCalendar == null) throw NullPointerException()
|
if (savedCalendar == null) throw NullPointerException()
|
||||||
setSystemTime(savedCalendar!!)
|
setSystemTime(savedCalendar)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -40,15 +40,13 @@ class HabitFixtures(private val modelFactory: ModelFactory, private val habitLis
|
|||||||
100000, 0, 100000
|
100000, 0, 100000
|
||||||
)
|
)
|
||||||
|
|
||||||
@JvmOverloads
|
fun createEmptyHabit(): Habit {
|
||||||
fun createEmptyHabit(id: Long? = null): Habit {
|
|
||||||
val habit = modelFactory.buildHabit()
|
val habit = modelFactory.buildHabit()
|
||||||
habit.name = "Meditate"
|
habit.name = "Meditate"
|
||||||
habit.question = "Did you meditate this morning?"
|
habit.question = "Did you meditate this morning?"
|
||||||
habit.description = "This is a test description"
|
habit.description = "This is a test description"
|
||||||
habit.color = PaletteColor(5)
|
habit.color = PaletteColor(5)
|
||||||
habit.frequency = DAILY
|
habit.frequency = DAILY
|
||||||
habit.id = id
|
|
||||||
habitList.add(habit)
|
habitList.add(habit)
|
||||||
return habit
|
return habit
|
||||||
}
|
}
|
||||||
@@ -101,13 +99,14 @@ class HabitFixtures(private val modelFactory: ModelFactory, private val habitLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createLongNumericalHabit(): Habit {
|
fun createLongNumericalHabit(): Habit {
|
||||||
val habit = modelFactory.buildHabit()
|
val habit = modelFactory.buildHabit().apply {
|
||||||
habit.name = "Read"
|
name = "Read"
|
||||||
habit.question = "How many pages did you walk today?"
|
question = "How many pages did you walk today?"
|
||||||
habit.type = NUMBER_HABIT
|
type = NUMBER_HABIT
|
||||||
habit.targetType = AT_LEAST
|
targetType = AT_LEAST
|
||||||
habit.targetValue = 200.0
|
targetValue = 200.0
|
||||||
habit.unit = "pages"
|
unit = "pages"
|
||||||
|
}
|
||||||
habitList.add(habit)
|
habitList.add(habit)
|
||||||
var timestamp: Timestamp = getToday()
|
var timestamp: Timestamp = getToday()
|
||||||
for (value in LONG_NUMERICAL_HABIT_ENTRIES) {
|
for (value in LONG_NUMERICAL_HABIT_ENTRIES) {
|
||||||
@@ -119,10 +118,11 @@ class HabitFixtures(private val modelFactory: ModelFactory, private val habitLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createShortHabit(): Habit {
|
fun createShortHabit(): Habit {
|
||||||
val habit = modelFactory.buildHabit()
|
val habit = modelFactory.buildHabit().apply {
|
||||||
habit.name = "Wake up early"
|
name = "Wake up early"
|
||||||
habit.question = "Did you wake up before 6am?"
|
question = "Did you wake up before 6am?"
|
||||||
habit.frequency = Frequency(2, 3)
|
frequency = Frequency(2, 3)
|
||||||
|
}
|
||||||
habitList.add(habit)
|
habitList.add(habit)
|
||||||
var timestamp: Timestamp = getToday()
|
var timestamp: Timestamp = getToday()
|
||||||
for (c in LONG_HABIT_ENTRIES) {
|
for (c in LONG_HABIT_ENTRIES) {
|
||||||
|
|||||||
@@ -29,19 +29,17 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class FrequencyChartTest : BaseViewTest() {
|
class FrequencyChartTest : BaseViewTest() {
|
||||||
private var view: FrequencyChart? = null
|
private lateinit var view: FrequencyChart
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
fixtures.purgeHabits(habitList)
|
fixtures.purgeHabits(habitList)
|
||||||
val habit = fixtures.createLongHabit()
|
val habit = fixtures.createLongHabit()
|
||||||
view = FrequencyChart(targetContext)
|
view = FrequencyChart(targetContext).apply {
|
||||||
view!!.setFrequency(
|
setFrequency(habit.originalEntries.computeWeekdayFrequency(habit.isNumerical))
|
||||||
habit.originalEntries.computeWeekdayFrequency(
|
setColor(habit.color.toFixedAndroidColor())
|
||||||
habit.isNumerical
|
}
|
||||||
)
|
|
||||||
)
|
|
||||||
view!!.setColor(habit.color.toFixedAndroidColor())
|
|
||||||
measureView(view, dpToPixels(300), dpToPixels(100))
|
measureView(view, dpToPixels(300), dpToPixels(100))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +52,8 @@ class FrequencyChartTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withDataOffset() {
|
fun testRender_withDataOffset() {
|
||||||
view!!.onScroll(null, null, -dpToPixels(150), 0f)
|
view.onScroll(null, null, -dpToPixels(150), 0f)
|
||||||
view!!.invalidate()
|
view.invalidate()
|
||||||
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ class FrequencyChartTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withTransparentBackground() {
|
fun testRender_withTransparentBackground() {
|
||||||
view!!.setIsBackgroundTransparent(true)
|
view.setIsBackgroundTransparent(true)
|
||||||
assertRenders(view, BASE_PATH + "renderTransparent.png")
|
assertRenders(view, BASE_PATH + "renderTransparent.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,16 +31,18 @@ import java.io.IOException
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class RingViewTest : BaseViewTest() {
|
class RingViewTest : BaseViewTest() {
|
||||||
private var view: RingView? = null
|
private lateinit var view: RingView
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
view = RingView(targetContext)
|
view = RingView(targetContext).apply {
|
||||||
view!!.setPercentage(0.6f)
|
setPercentage(0.6f)
|
||||||
view!!.setText("60%")
|
setText("60%")
|
||||||
view!!.setColor(getAndroidTestColor(0))
|
setColor(getAndroidTestColor(0))
|
||||||
view!!.setBackgroundColor(Color.WHITE)
|
setBackgroundColor(Color.WHITE)
|
||||||
view!!.setThickness(dpToPixels(3))
|
setThickness(dpToPixels(3))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -53,8 +55,8 @@ class RingViewTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun testRender_withDifferentParams() {
|
fun testRender_withDifferentParams() {
|
||||||
view!!.setPercentage(0.25f)
|
view.setPercentage(0.25f)
|
||||||
view!!.setColor(getAndroidTestColor(5))
|
view.setColor(getAndroidTestColor(5))
|
||||||
measureView(view, dpToPixels(200), dpToPixels(200))
|
measureView(view, dpToPixels(200), dpToPixels(200))
|
||||||
assertRenders(view, BASE_PATH + "renderDifferentParams.png")
|
assertRenders(view, BASE_PATH + "renderDifferentParams.png")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,17 +32,18 @@ import org.junit.runner.RunWith
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
class ScoreChartTest : BaseViewTest() {
|
class ScoreChartTest : BaseViewTest() {
|
||||||
private lateinit var habit: Habit
|
private lateinit var habit: Habit
|
||||||
private var view: ScoreChart? = null
|
private lateinit var view: ScoreChart
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
fixtures.purgeHabits(habitList)
|
fixtures.purgeHabits(habitList)
|
||||||
habit = fixtures.createLongHabit()
|
habit = fixtures.createLongHabit()
|
||||||
val (scores, bucketSize, _, color) = buildState(habit, prefs.firstWeekdayInt, 0)
|
val (scores, bucketSize, _, color) = buildState(habit, prefs.firstWeekdayInt, 0)
|
||||||
view = ScoreChart(targetContext)
|
view = ScoreChart(targetContext).apply {
|
||||||
view!!.setScores(scores.toMutableList())
|
setScores(scores.toMutableList())
|
||||||
view!!.setColor(color.toFixedAndroidColor())
|
setColor(color.toFixedAndroidColor())
|
||||||
view!!.setBucketSize(bucketSize)
|
setBucketSize(bucketSize)
|
||||||
|
}
|
||||||
measureView(view, dpToPixels(300), dpToPixels(200))
|
measureView(view, dpToPixels(300), dpToPixels(200))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,8 +56,8 @@ class ScoreChartTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withDataOffset() {
|
fun testRender_withDataOffset() {
|
||||||
view!!.onScroll(null, null, -dpToPixels(150), 0f)
|
view.onScroll(null, null, -dpToPixels(150), 0f)
|
||||||
view!!.invalidate()
|
view.invalidate()
|
||||||
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,20 +72,20 @@ class ScoreChartTest : BaseViewTest() {
|
|||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withMonthlyBucket() {
|
fun testRender_withMonthlyBucket() {
|
||||||
val (scores, bucketSize) = buildState(
|
val (scores, bucketSize) = buildState(
|
||||||
habit!!,
|
habit,
|
||||||
prefs.firstWeekdayInt,
|
prefs.firstWeekdayInt,
|
||||||
2
|
2
|
||||||
)
|
)
|
||||||
view!!.setScores(scores.toMutableList())
|
view.setScores(scores.toMutableList())
|
||||||
view!!.setBucketSize(bucketSize)
|
view.setBucketSize(bucketSize)
|
||||||
view!!.invalidate()
|
view.invalidate()
|
||||||
assertRenders(view, BASE_PATH + "renderMonthly.png")
|
assertRenders(view, BASE_PATH + "renderMonthly.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withTransparentBackground() {
|
fun testRender_withTransparentBackground() {
|
||||||
view!!.setIsTransparencyEnabled(true)
|
view.setIsTransparencyEnabled(true)
|
||||||
assertRenders(view, BASE_PATH + "renderTransparent.png")
|
assertRenders(view, BASE_PATH + "renderTransparent.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,13 +93,13 @@ class ScoreChartTest : BaseViewTest() {
|
|||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withYearlyBucket() {
|
fun testRender_withYearlyBucket() {
|
||||||
val (scores, bucketSize) = buildState(
|
val (scores, bucketSize) = buildState(
|
||||||
habit!!,
|
habit,
|
||||||
prefs.firstWeekdayInt,
|
prefs.firstWeekdayInt,
|
||||||
4
|
4
|
||||||
)
|
)
|
||||||
view!!.setScores(scores.toMutableList())
|
view.setScores(scores.toMutableList())
|
||||||
view!!.setBucketSize(bucketSize)
|
view.setBucketSize(bucketSize)
|
||||||
view!!.invalidate()
|
view.invalidate()
|
||||||
assertRenders(view, BASE_PATH + "renderYearly.png")
|
assertRenders(view, BASE_PATH + "renderYearly.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,15 +29,16 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class StreakChartTest : BaseViewTest() {
|
class StreakChartTest : BaseViewTest() {
|
||||||
private var view: StreakChart? = null
|
private lateinit var view: StreakChart
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
fixtures.purgeHabits(habitList)
|
fixtures.purgeHabits(habitList)
|
||||||
val (color, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, streaks) = fixtures.createLongHabit()
|
val habit = fixtures.createLongHabit()
|
||||||
view = StreakChart(targetContext)
|
view = StreakChart(targetContext).apply {
|
||||||
view!!.setColor(color.toFixedAndroidColor())
|
setColor(habit.color.toFixedAndroidColor())
|
||||||
view!!.setStreaks(streaks.getBest(5))
|
setStreaks(habit.streaks.getBest(5))
|
||||||
|
}
|
||||||
measureView(view, dpToPixels(300), dpToPixels(100))
|
measureView(view, dpToPixels(300), dpToPixels(100))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ class StreakChartTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withTransparentBackground() {
|
fun testRender_withTransparentBackground() {
|
||||||
view!!.setIsBackgroundTransparent(true)
|
view.setIsBackgroundTransparent(true)
|
||||||
assertRenders(view, BASE_PATH + "renderTransparent.png")
|
assertRenders(view, BASE_PATH + "renderTransparent.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,44 +22,44 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import com.nhaarman.mockitokotlin2.doReturn
|
import com.nhaarman.mockitokotlin2.doReturn
|
||||||
import com.nhaarman.mockitokotlin2.mock
|
import com.nhaarman.mockitokotlin2.mock
|
||||||
|
import com.nhaarman.mockitokotlin2.verify
|
||||||
|
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.Mockito
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class HeaderViewTest : BaseViewTest() {
|
class HeaderViewTest : BaseViewTest() {
|
||||||
private var view: HeaderView? = null
|
private lateinit var view: HeaderView
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
prefs = mock()
|
prefs = mock()
|
||||||
view = HeaderView(targetContext, prefs, mock())
|
view = HeaderView(targetContext, prefs, mock())
|
||||||
view!!.buttonCount = 5
|
view.buttonCount = 5
|
||||||
measureView(view, dpToPixels(600), dpToPixels(48))
|
measureView(view, dpToPixels(600), dpToPixels(48))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testRender() {
|
fun testRender() {
|
||||||
Mockito.`when`(prefs.isCheckmarkSequenceReversed).thenReturn(false)
|
whenever(prefs.isCheckmarkSequenceReversed).thenReturn(false)
|
||||||
assertRenders(view, PATH + "render.png")
|
assertRenders(view, PATH + "render.png")
|
||||||
Mockito.verify(prefs).isCheckmarkSequenceReversed
|
verify(prefs).isCheckmarkSequenceReversed
|
||||||
Mockito.verifyNoMoreInteractions(prefs)
|
verifyNoMoreInteractions(prefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testRender_reverse() {
|
fun testRender_reverse() {
|
||||||
doReturn(true).whenever(prefs).isCheckmarkSequenceReversed
|
doReturn(true).whenever(prefs).isCheckmarkSequenceReversed
|
||||||
// Mockito.`when`(prefs.isCheckmarkSequenceReversed).thenReturn(true)
|
|
||||||
assertRenders(view, PATH + "render_reverse.png")
|
assertRenders(view, PATH + "render_reverse.png")
|
||||||
Mockito.verify(prefs).isCheckmarkSequenceReversed
|
verify(prefs).isCheckmarkSequenceReversed
|
||||||
Mockito.verifyNoMoreInteractions(prefs)
|
verifyNoMoreInteractions(prefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ class HintViewTest : BaseViewTest() {
|
|||||||
val text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
val text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
doReturn(true).whenever(list).shouldShow()
|
doReturn(true).whenever(list).shouldShow()
|
||||||
doReturn(text).whenever(list).pop()
|
doReturn(text).whenever(list).pop()
|
||||||
// Mockito.`when`(list.shouldShow()).thenReturn(true)
|
|
||||||
// Mockito.`when`(list.pop()).thenReturn(text)
|
|
||||||
view.showNext()
|
view.showNext()
|
||||||
skipAnimation(view)
|
skipAnimation(view)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ import org.junit.Test
|
|||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
class AndroidDatabaseTest : BaseAndroidTest() {
|
class AndroidDatabaseTest : BaseAndroidTest() {
|
||||||
private var db: AndroidDatabase? = null
|
private lateinit var db: AndroidDatabase
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
db = AndroidDatabase(SQLiteDatabase.create(null), null)
|
db = AndroidDatabase(SQLiteDatabase.create(null), null)
|
||||||
db!!.execute("create table test(color int, name string)")
|
db.execute("create table test(color int, name string)")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -40,8 +40,8 @@ class AndroidDatabaseTest : BaseAndroidTest() {
|
|||||||
val map = HashMap<String, Any?>()
|
val map = HashMap<String, Any?>()
|
||||||
map["name"] = "asd"
|
map["name"] = "asd"
|
||||||
map["color"] = null
|
map["color"] = null
|
||||||
db!!.insert("test", map)
|
db.insert("test", map)
|
||||||
val c: Cursor = db!!.query("select * from test")
|
val c: Cursor = db.query("select * from test")
|
||||||
c.moveToNext()
|
c.moveToNext()
|
||||||
assertNull(c.getInt(0))
|
assertNull(c.getInt(0))
|
||||||
MatcherAssert.assertThat(c.getString(1), IsEqual.equalTo("asd"))
|
MatcherAssert.assertThat(c.getString(1), IsEqual.equalTo("asd"))
|
||||||
|
|||||||
@@ -38,10 +38,11 @@ class TargetWidgetTest : BaseViewTest() {
|
|||||||
super.setUp()
|
super.setUp()
|
||||||
setTheme(R.style.WidgetTheme)
|
setTheme(R.style.WidgetTheme)
|
||||||
prefs.widgetOpacity = 255
|
prefs.widgetOpacity = 255
|
||||||
habit = fixtures.createLongNumericalHabit()
|
habit = fixtures.createLongNumericalHabit().apply {
|
||||||
habit.color = PaletteColor(11)
|
color = PaletteColor(11)
|
||||||
habit.frequency = Frequency.WEEKLY
|
frequency = Frequency.WEEKLY
|
||||||
habit.recompute()
|
recompute()
|
||||||
|
}
|
||||||
val widget = TargetWidget(targetContext, 0, habit)
|
val widget = TargetWidget(targetContext, 0, habit)
|
||||||
view = convertToView(widget, 400, 400)
|
view = convertToView(widget, 400, 400)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,25 +32,24 @@ import java.io.IOException
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class CheckmarkWidgetViewTest : BaseViewTest() {
|
class CheckmarkWidgetViewTest : BaseViewTest() {
|
||||||
private var view: CheckmarkWidgetView? = null
|
private lateinit var view: CheckmarkWidgetView
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
setTheme(R.style.WidgetTheme)
|
setTheme(R.style.WidgetTheme)
|
||||||
val habit = fixtures.createShortHabit()
|
val habit = fixtures.createShortHabit()
|
||||||
val name = habit.name
|
|
||||||
val computedEntries = habit.computedEntries
|
val computedEntries = habit.computedEntries
|
||||||
val scores = habit.scores
|
val scores = habit.scores
|
||||||
val today = getTodayWithOffset()
|
val today = getTodayWithOffset()
|
||||||
view = CheckmarkWidgetView(targetContext)
|
|
||||||
val score = scores[today].value
|
val score = scores[today].value
|
||||||
val percentage = score.toFloat()
|
view = CheckmarkWidgetView(targetContext).apply {
|
||||||
view!!.activeColor = getAndroidTestColor(0)
|
activeColor = getAndroidTestColor(0)
|
||||||
view!!.entryState = computedEntries.get(today).value
|
entryState = computedEntries.get(today).value
|
||||||
view!!.entryValue = computedEntries.get(today).value
|
entryValue = computedEntries.get(today).value
|
||||||
view!!.percentage = percentage
|
percentage = score.toFloat()
|
||||||
view!!.name = name
|
name = habit.name
|
||||||
view!!.refresh()
|
}
|
||||||
|
view.refresh()
|
||||||
measureView(view, dpToPixels(100), dpToPixels(200))
|
measureView(view, dpToPixels(100), dpToPixels(200))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import android.os.Parcelable.ClassLoaderCreator
|
|||||||
import androidx.customview.view.AbsSavedState
|
import androidx.customview.view.AbsSavedState
|
||||||
|
|
||||||
class BundleSavedState : AbsSavedState {
|
class BundleSavedState : AbsSavedState {
|
||||||
val bundle: Bundle?
|
@JvmField val bundle: Bundle?
|
||||||
|
|
||||||
constructor(superState: Parcelable?, bundle: Bundle?) : super(superState!!) {
|
constructor(superState: Parcelable?, bundle: Bundle?) : super(superState!!) {
|
||||||
this.bundle = bundle
|
this.bundle = bundle
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ import java.util.GregorianCalendar
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class FrequencyChart : ScrollableChart {
|
class FrequencyChart : ScrollableChart {
|
||||||
private var pGrid: Paint? = null
|
private var pGrid: Paint? = null
|
||||||
@@ -90,8 +93,8 @@ class FrequencyChart : ScrollableChart {
|
|||||||
|
|
||||||
private fun getMaxFreq(frequency: HashMap<Timestamp, Array<Int>>): Int {
|
private fun getMaxFreq(frequency: HashMap<Timestamp, Array<Int>>): Int {
|
||||||
var maxValue = 1
|
var maxValue = 1
|
||||||
for (values in frequency.values) for (value in values) maxValue = Math.max(
|
for (values in frequency.values) for (value in values) maxValue = max(
|
||||||
value!!,
|
value,
|
||||||
maxValue
|
maxValue
|
||||||
)
|
)
|
||||||
return maxValue
|
return maxValue
|
||||||
@@ -102,7 +105,7 @@ class FrequencyChart : ScrollableChart {
|
|||||||
initColors()
|
initColors()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun initPaints() {
|
private fun initPaints() {
|
||||||
pText = Paint()
|
pText = Paint()
|
||||||
pText!!.isAntiAlias = true
|
pText!!.isAntiAlias = true
|
||||||
pGraph = Paint()
|
pGraph = Paint()
|
||||||
@@ -155,7 +158,7 @@ class FrequencyChart : ScrollableChart {
|
|||||||
pGrid!!.strokeWidth = baseSize * 0.05f
|
pGrid!!.strokeWidth = baseSize * 0.05f
|
||||||
em = pText!!.fontSpacing
|
em = pText!!.fontSpacing
|
||||||
columnWidth = baseSize.toFloat()
|
columnWidth = baseSize.toFloat()
|
||||||
columnWidth = Math.max(columnWidth, maxMonthWidth * 1.2f)
|
columnWidth = max(columnWidth, maxMonthWidth * 1.2f)
|
||||||
columnHeight = 8 * baseSize
|
columnHeight = 8 * baseSize
|
||||||
nColumns = (width / columnWidth).toInt()
|
nColumns = (width / columnWidth).toInt()
|
||||||
internalPaddingTop = 0
|
internalPaddingTop = 0
|
||||||
@@ -225,20 +228,20 @@ class FrequencyChart : ScrollableChart {
|
|||||||
// the real mark radius is scaled down by a factor depending on the maximal frequency
|
// the real mark radius is scaled down by a factor depending on the maximal frequency
|
||||||
val scale = 1.0f / maxFreq * value!!
|
val scale = 1.0f / maxFreq * value!!
|
||||||
val radius = maxRadius * scale
|
val radius = maxRadius * scale
|
||||||
val colorIndex = Math.min(colors.size - 1, Math.round((colors.size - 1) * scale))
|
val colorIndex = min((colors.size - 1), ((colors.size - 1) * scale).roundToInt())
|
||||||
pGraph!!.color = colors[colorIndex]
|
pGraph!!.color = colors[colorIndex]
|
||||||
canvas.drawCircle(rect.centerX(), rect.centerY(), radius, pGraph!!)
|
canvas.drawCircle(rect.centerX(), rect.centerY(), radius, pGraph!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val maxMonthWidth: Float
|
private val maxMonthWidth: Float
|
||||||
private get() {
|
get() {
|
||||||
var maxMonthWidth = 0f
|
var maxMonthWidth = 0f
|
||||||
val day: GregorianCalendar =
|
val day: GregorianCalendar =
|
||||||
getStartOfTodayCalendarWithOffset()
|
getStartOfTodayCalendarWithOffset()
|
||||||
for (i in 0..11) {
|
for (i in 0..11) {
|
||||||
day[Calendar.MONTH] = i
|
day[Calendar.MONTH] = i
|
||||||
val monthWidth = pText!!.measureText(dfMonth!!.format(day.time))
|
val monthWidth = pText!!.measureText(dfMonth!!.format(day.time))
|
||||||
maxMonthWidth = Math.max(maxMonthWidth, monthWidth)
|
maxMonthWidth = max(maxMonthWidth, monthWidth)
|
||||||
}
|
}
|
||||||
return maxMonthWidth
|
return maxMonthWidth
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
|
|||||||
import org.isoron.uhabits.utils.InterfaceUtils.spToPixels
|
import org.isoron.uhabits.utils.InterfaceUtils.spToPixels
|
||||||
import org.isoron.uhabits.utils.PaletteUtils.getAndroidTestColor
|
import org.isoron.uhabits.utils.PaletteUtils.getAndroidTestColor
|
||||||
import org.isoron.uhabits.utils.StyledResources
|
import org.isoron.uhabits.utils.StyledResources
|
||||||
|
import kotlin.math.min
|
||||||
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
class RingView : View {
|
class RingView : View {
|
||||||
private var color: Int
|
private var color: Int
|
||||||
@@ -140,7 +142,7 @@ class RingView : View {
|
|||||||
}
|
}
|
||||||
pRing!!.color = color
|
pRing!!.color = color
|
||||||
rect!![0f, 0f, diameter.toFloat()] = diameter.toFloat()
|
rect!![0f, 0f, diameter.toFloat()] = diameter.toFloat()
|
||||||
val angle = 360 * Math.round(percentage / precision) * precision
|
val angle = 360 * (percentage / precision).roundToLong() * precision
|
||||||
activeCanvas!!.drawArc(rect!!, -90f, angle, true, pRing!!)
|
activeCanvas!!.drawArc(rect!!, -90f, angle, true, pRing!!)
|
||||||
pRing!!.color = inactiveColor!!
|
pRing!!.color = inactiveColor!!
|
||||||
activeCanvas.drawArc(rect!!, angle - 90, 360 - angle, true, pRing!!)
|
activeCanvas.drawArc(rect!!, angle - 90, 360 - angle, true, pRing!!)
|
||||||
@@ -167,7 +169,7 @@ class RingView : View {
|
|||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||||
val width = MeasureSpec.getSize(widthMeasureSpec)
|
val width = MeasureSpec.getSize(widthMeasureSpec)
|
||||||
val height = MeasureSpec.getSize(heightMeasureSpec)
|
val height = MeasureSpec.getSize(heightMeasureSpec)
|
||||||
diameter = Math.min(height, width)
|
diameter = min(height, width)
|
||||||
pRing!!.textSize = textSize
|
pRing!!.textSize = textSize
|
||||||
em = pRing!!.measureText("M")
|
em = pRing!!.measureText("M")
|
||||||
setMeasuredDimension(diameter, diameter)
|
setMeasuredDimension(diameter, diameter)
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ import java.util.GregorianCalendar
|
|||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class ScoreChart : ScrollableChart {
|
class ScoreChart : ScrollableChart {
|
||||||
private var pGrid: Paint? = null
|
private var pGrid: Paint? = null
|
||||||
@@ -89,7 +91,7 @@ class ScoreChart : ScrollableChart {
|
|||||||
for (i in 1..99) {
|
for (i in 1..99) {
|
||||||
val step = 0.1
|
val step = 0.1
|
||||||
var current = previous + random.nextDouble() * step * 2 - step
|
var current = previous + random.nextDouble() * step * 2 - step
|
||||||
current = Math.max(0.0, Math.min(1.0, current))
|
current = max(0.0, min(1.0, current))
|
||||||
newScores.add(Score(timestamp.minus(i), current))
|
newScores.add(Score(timestamp.minus(i), current))
|
||||||
previous = current
|
previous = current
|
||||||
}
|
}
|
||||||
@@ -178,14 +180,14 @@ class ScoreChart : ScrollableChart {
|
|||||||
if (height < 9) height = 200
|
if (height < 9) height = 200
|
||||||
val maxTextSize = getDimension(context, R.dimen.tinyTextSize)
|
val maxTextSize = getDimension(context, R.dimen.tinyTextSize)
|
||||||
val textSize = height * 0.06f
|
val textSize = height * 0.06f
|
||||||
pText!!.textSize = Math.min(textSize, maxTextSize)
|
pText!!.textSize = min(textSize, maxTextSize)
|
||||||
em = pText!!.fontSpacing
|
em = pText!!.fontSpacing
|
||||||
val footerHeight = (3 * em).toInt()
|
val footerHeight = (3 * em).toInt()
|
||||||
internalPaddingTop = em.toInt()
|
internalPaddingTop = em.toInt()
|
||||||
baseSize = (height - footerHeight - internalPaddingTop) / 8
|
baseSize = (height - footerHeight - internalPaddingTop) / 8
|
||||||
columnWidth = baseSize.toFloat()
|
columnWidth = baseSize.toFloat()
|
||||||
columnWidth = Math.max(columnWidth, maxDayWidth * 1.5f)
|
columnWidth = max(columnWidth, maxDayWidth * 1.5f)
|
||||||
columnWidth = Math.max(columnWidth, maxMonthWidth * 1.2f)
|
columnWidth = max(columnWidth, maxMonthWidth * 1.2f)
|
||||||
nColumns = (width / columnWidth).toInt()
|
nColumns = (width / columnWidth).toInt()
|
||||||
columnWidth = width.toFloat() / nColumns
|
columnWidth = width.toFloat() / nColumns
|
||||||
setScrollerBucketSize(columnWidth.toInt())
|
setScrollerBucketSize(columnWidth.toInt())
|
||||||
@@ -193,7 +195,7 @@ class ScoreChart : ScrollableChart {
|
|||||||
val minStrokeWidth = dpToPixels(context, 1f)
|
val minStrokeWidth = dpToPixels(context, 1f)
|
||||||
pGraph!!.textSize = baseSize * 0.5f
|
pGraph!!.textSize = baseSize * 0.5f
|
||||||
pGraph!!.strokeWidth = baseSize * 0.1f
|
pGraph!!.strokeWidth = baseSize * 0.1f
|
||||||
pGrid!!.strokeWidth = Math.min(minStrokeWidth, baseSize * 0.05f)
|
pGrid!!.strokeWidth = min(minStrokeWidth, baseSize * 0.05f)
|
||||||
if (isTransparencyEnabled) initCache(width, height)
|
if (isTransparencyEnabled) initCache(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +300,7 @@ class ScoreChart : ScrollableChart {
|
|||||||
for (i in 0..27) {
|
for (i in 0..27) {
|
||||||
day[Calendar.DAY_OF_MONTH] = i
|
day[Calendar.DAY_OF_MONTH] = i
|
||||||
val monthWidth = pText!!.measureText(dfMonth!!.format(day.time))
|
val monthWidth = pText!!.measureText(dfMonth!!.format(day.time))
|
||||||
maxDayWidth = Math.max(maxDayWidth, monthWidth)
|
maxDayWidth = max(maxDayWidth, monthWidth)
|
||||||
}
|
}
|
||||||
return maxDayWidth
|
return maxDayWidth
|
||||||
}
|
}
|
||||||
@@ -310,7 +312,7 @@ class ScoreChart : ScrollableChart {
|
|||||||
for (i in 0..11) {
|
for (i in 0..11) {
|
||||||
day[Calendar.MONTH] = i
|
day[Calendar.MONTH] = i
|
||||||
val monthWidth = pText!!.measureText(dfMonth!!.format(day.time))
|
val monthWidth = pText!!.measureText(dfMonth!!.format(day.time))
|
||||||
maxMonthWidth = Math.max(maxMonthWidth, monthWidth)
|
maxMonthWidth = max(maxMonthWidth, monthWidth)
|
||||||
}
|
}
|
||||||
return maxMonthWidth
|
return maxMonthWidth
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ import android.view.GestureDetector
|
|||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Scroller
|
import android.widget.Scroller
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
abstract class ScrollableChart : View, GestureDetector.OnGestureListener, AnimatorUpdateListener {
|
abstract class ScrollableChart : View, GestureDetector.OnGestureListener, AnimatorUpdateListener {
|
||||||
var dataOffset = 0
|
var dataOffset = 0
|
||||||
@@ -91,37 +94,37 @@ abstract class ScrollableChart : View, GestureDetector.OnGestureListener, Animat
|
|||||||
super.onRestoreInstanceState(state)
|
super.onRestoreInstanceState(state)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val bss = state
|
val x = state.bundle!!.getInt("x")
|
||||||
val x = bss.bundle!!.getInt("x")
|
val y = state.bundle.getInt("y")
|
||||||
val y = bss.bundle.getInt("y")
|
direction = state.bundle.getInt("direction")
|
||||||
direction = bss.bundle.getInt("direction")
|
dataOffset = state.bundle.getInt("dataOffset")
|
||||||
dataOffset = bss.bundle.getInt("dataOffset")
|
maxDataOffset = state.bundle.getInt("maxDataOffset")
|
||||||
maxDataOffset = bss.bundle.getInt("maxDataOffset")
|
|
||||||
scroller!!.startScroll(0, 0, x, y, 0)
|
scroller!!.startScroll(0, 0, x, y, 0)
|
||||||
scroller!!.computeScrollOffset()
|
scroller!!.computeScrollOffset()
|
||||||
super.onRestoreInstanceState(bss.superState)
|
super.onRestoreInstanceState(state.superState)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun onSaveInstanceState(): Parcelable? {
|
public override fun onSaveInstanceState(): Parcelable? {
|
||||||
val superState = super.onSaveInstanceState()
|
val superState = super.onSaveInstanceState()
|
||||||
val bundle = Bundle()
|
val bundle = Bundle().apply {
|
||||||
bundle.putInt("x", scroller!!.currX)
|
putInt("x", scroller!!.currX)
|
||||||
bundle.putInt("y", scroller!!.currY)
|
putInt("y", scroller!!.currY)
|
||||||
bundle.putInt("dataOffset", dataOffset)
|
putInt("dataOffset", dataOffset)
|
||||||
bundle.putInt("direction", direction)
|
putInt("direction", direction)
|
||||||
bundle.putInt("maxDataOffset", maxDataOffset)
|
putInt("maxDataOffset", maxDataOffset)
|
||||||
|
}
|
||||||
return BundleSavedState(superState, bundle)
|
return BundleSavedState(superState, bundle)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, dx: Float, dy: Float): Boolean {
|
override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, dx: Float, dy: Float): Boolean {
|
||||||
var dx = dx
|
var dx = dx
|
||||||
if (scrollerBucketSize == 0) return false
|
if (scrollerBucketSize == 0) return false
|
||||||
if (Math.abs(dx) > Math.abs(dy)) {
|
if (abs(dx) > abs(dy)) {
|
||||||
val parent = parent
|
val parent = parent
|
||||||
parent?.requestDisallowInterceptTouchEvent(true)
|
parent?.requestDisallowInterceptTouchEvent(true)
|
||||||
}
|
}
|
||||||
dx = -direction * dx
|
dx *= -direction
|
||||||
dx = Math.min(dx, (maxX - scroller!!.currX).toFloat())
|
dx = min(dx, (maxX - scroller!!.currX).toFloat())
|
||||||
scroller!!.startScroll(
|
scroller!!.startScroll(
|
||||||
scroller!!.currX,
|
scroller!!.currX,
|
||||||
scroller!!.currY,
|
scroller!!.currY,
|
||||||
@@ -151,7 +154,7 @@ abstract class ScrollableChart : View, GestureDetector.OnGestureListener, Animat
|
|||||||
override fun onLongPress(e: MotionEvent) {}
|
override fun onLongPress(e: MotionEvent) {}
|
||||||
fun setMaxDataOffset(maxDataOffset: Int) {
|
fun setMaxDataOffset(maxDataOffset: Int) {
|
||||||
this.maxDataOffset = maxDataOffset
|
this.maxDataOffset = maxDataOffset
|
||||||
dataOffset = Math.min(dataOffset, maxDataOffset)
|
dataOffset = min(dataOffset, maxDataOffset)
|
||||||
scrollController!!.onDataOffsetChanged(dataOffset)
|
scrollController!!.onDataOffsetChanged(dataOffset)
|
||||||
postInvalidate()
|
postInvalidate()
|
||||||
}
|
}
|
||||||
@@ -181,8 +184,8 @@ abstract class ScrollableChart : View, GestureDetector.OnGestureListener, Animat
|
|||||||
|
|
||||||
private fun updateDataOffset() {
|
private fun updateDataOffset() {
|
||||||
var newDataOffset = scroller!!.currX / scrollerBucketSize
|
var newDataOffset = scroller!!.currX / scrollerBucketSize
|
||||||
newDataOffset = Math.max(0, newDataOffset)
|
newDataOffset = max(0, newDataOffset)
|
||||||
newDataOffset = Math.min(maxDataOffset, newDataOffset)
|
newDataOffset = min(maxDataOffset, newDataOffset)
|
||||||
if (newDataOffset != dataOffset) {
|
if (newDataOffset != dataOffset) {
|
||||||
dataOffset = newDataOffset
|
dataOffset = newDataOffset
|
||||||
scrollController!!.onDataOffsetChanged(dataOffset)
|
scrollController!!.onDataOffsetChanged(dataOffset)
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ import java.text.DateFormat
|
|||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
import kotlin.math.floor
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class StreakChart : View {
|
class StreakChart : View {
|
||||||
private var paint: Paint? = null
|
private var paint: Paint? = null
|
||||||
@@ -72,7 +75,7 @@ class StreakChart : View {
|
|||||||
* @return max number of visible streaks
|
* @return max number of visible streaks
|
||||||
*/
|
*/
|
||||||
val maxStreakCount: Int
|
val maxStreakCount: Int
|
||||||
get() = Math.floor((measuredHeight / baseSize).toDouble()).toInt()
|
get() = floor((measuredHeight / baseSize).toDouble()).toInt()
|
||||||
|
|
||||||
fun populateWithRandomData() {
|
fun populateWithRandomData() {
|
||||||
var start: Timestamp = getToday()
|
var start: Timestamp = getToday()
|
||||||
@@ -105,7 +108,7 @@ class StreakChart : View {
|
|||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
override fun onDraw(canvas: Canvas) {
|
||||||
super.onDraw(canvas)
|
super.onDraw(canvas)
|
||||||
if (streaks!!.size == 0) return
|
if (streaks!!.isEmpty()) return
|
||||||
rect!![0f, 0f, internalWidth.toFloat()] = baseSize.toFloat()
|
rect!![0f, 0f, internalWidth.toFloat()] = baseSize.toFloat()
|
||||||
for (s in streaks!!) {
|
for (s in streaks!!) {
|
||||||
drawRow(canvas, s, rect)
|
drawRow(canvas, s, rect)
|
||||||
@@ -137,7 +140,7 @@ class StreakChart : View {
|
|||||||
val minTextSize = getDimension(context, R.dimen.tinyTextSize)
|
val minTextSize = getDimension(context, R.dimen.tinyTextSize)
|
||||||
val maxTextSize = getDimension(context, R.dimen.regularTextSize)
|
val maxTextSize = getDimension(context, R.dimen.regularTextSize)
|
||||||
val textSize = baseSize * 0.5f
|
val textSize = baseSize * 0.5f
|
||||||
paint!!.textSize = Math.max(Math.min(textSize, maxTextSize), minTextSize)
|
paint!!.textSize = max(min(textSize, maxTextSize), minTextSize)
|
||||||
em = paint!!.fontSpacing
|
em = paint!!.fontSpacing
|
||||||
textMargin = 0.5f * em
|
textMargin = 0.5f * em
|
||||||
updateMaxMinLengths()
|
updateMaxMinLengths()
|
||||||
@@ -149,8 +152,8 @@ class StreakChart : View {
|
|||||||
var availableWidth = internalWidth - 2 * maxLabelWidth
|
var availableWidth = internalWidth - 2 * maxLabelWidth
|
||||||
if (shouldShowLabels) availableWidth -= 2 * textMargin
|
if (shouldShowLabels) availableWidth -= 2 * textMargin
|
||||||
var barWidth = percentage * availableWidth
|
var barWidth = percentage * availableWidth
|
||||||
val minBarWidth = paint!!.measureText(java.lang.Long.toString(streak.length.toLong())) + em
|
val minBarWidth = paint!!.measureText(streak.length.toLong().toString()) + em
|
||||||
barWidth = Math.max(barWidth, minBarWidth)
|
barWidth = max(barWidth, minBarWidth)
|
||||||
val gap = (internalWidth - barWidth) / 2
|
val gap = (internalWidth - barWidth) / 2
|
||||||
val paddingTopBottom = baseSize * 0.05f
|
val paddingTopBottom = baseSize * 0.05f
|
||||||
paint!!.color = percentageToColor(percentage)
|
paint!!.color = percentageToColor(percentage)
|
||||||
@@ -168,7 +171,7 @@ class StreakChart : View {
|
|||||||
paint!!.color = percentageToTextColor(percentage)
|
paint!!.color = percentageToTextColor(percentage)
|
||||||
paint!!.textAlign = Paint.Align.CENTER
|
paint!!.textAlign = Paint.Align.CENTER
|
||||||
canvas.drawText(
|
canvas.drawText(
|
||||||
java.lang.Long.toString(streak.length.toLong()),
|
streak.length.toLong().toString(),
|
||||||
rect.centerX(),
|
rect.centerX(),
|
||||||
yOffset,
|
yOffset,
|
||||||
paint!!
|
paint!!
|
||||||
@@ -189,7 +192,7 @@ class StreakChart : View {
|
|||||||
initColors()
|
initColors()
|
||||||
streaks = emptyList()
|
streaks = emptyList()
|
||||||
val newDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM)
|
val newDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM)
|
||||||
if (!isInEditMode) newDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"))
|
if (!isInEditMode) newDateFormat.timeZone = TimeZone.getTimeZone("GMT")
|
||||||
dateFormat = newDateFormat
|
dateFormat = newDateFormat
|
||||||
rect = RectF()
|
rect = RectF()
|
||||||
baseSize = resources.getDimensionPixelSize(R.dimen.baseSize)
|
baseSize = resources.getDimensionPixelSize(R.dimen.baseSize)
|
||||||
@@ -232,11 +235,11 @@ class StreakChart : View {
|
|||||||
minLength = Long.MAX_VALUE
|
minLength = Long.MAX_VALUE
|
||||||
shouldShowLabels = true
|
shouldShowLabels = true
|
||||||
for (s in streaks!!) {
|
for (s in streaks!!) {
|
||||||
maxLength = Math.max(maxLength, s.length.toLong())
|
maxLength = max(maxLength, s.length.toLong())
|
||||||
minLength = Math.min(minLength, s.length.toLong())
|
minLength = min(minLength, s.length.toLong())
|
||||||
val lw1 = paint!!.measureText(dateFormat!!.format(s.start.toJavaDate()))
|
val lw1 = paint!!.measureText(dateFormat!!.format(s.start.toJavaDate()))
|
||||||
val lw2 = paint!!.measureText(dateFormat!!.format(s.end.toJavaDate()))
|
val lw2 = paint!!.measureText(dateFormat!!.format(s.end.toJavaDate()))
|
||||||
maxLabelWidth = Math.max(maxLabelWidth, Math.max(lw1, lw2))
|
maxLabelWidth = max(maxLabelWidth, max(lw1, lw2))
|
||||||
}
|
}
|
||||||
if (internalWidth - 2 * maxLabelWidth < internalWidth * 0.25f) {
|
if (internalWidth - 2 * maxLabelWidth < internalWidth * 0.25f) {
|
||||||
maxLabelWidth = 0f
|
maxLabelWidth = 0f
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import org.isoron.uhabits.activities.habits.list.views.toShortString
|
|||||||
import org.isoron.uhabits.utils.InterfaceUtils.dpToPixels
|
import org.isoron.uhabits.utils.InterfaceUtils.dpToPixels
|
||||||
import org.isoron.uhabits.utils.InterfaceUtils.getDimension
|
import org.isoron.uhabits.utils.InterfaceUtils.getDimension
|
||||||
import org.isoron.uhabits.utils.StyledResources
|
import org.isoron.uhabits.utils.StyledResources
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class TargetChart : View {
|
class TargetChart : View {
|
||||||
private var paint: Paint? = null
|
private var paint: Paint? = null
|
||||||
@@ -62,12 +64,12 @@ class TargetChart : View {
|
|||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
override fun onDraw(canvas: Canvas) {
|
||||||
super.onDraw(canvas)
|
super.onDraw(canvas)
|
||||||
if (labels.size == 0) return
|
if (labels.isEmpty()) return
|
||||||
maxLabelSize = 0f
|
maxLabelSize = 0f
|
||||||
for (label in labels) {
|
for (label in labels) {
|
||||||
paint!!.textSize = tinyTextSize
|
paint!!.textSize = tinyTextSize
|
||||||
val len = paint!!.measureText(label)
|
val len = paint!!.measureText(label)
|
||||||
maxLabelSize = Math.max(maxLabelSize, len)
|
maxLabelSize = max(maxLabelSize, len)
|
||||||
}
|
}
|
||||||
val marginTop = (height - baseSize * labels.size) / 2.0f
|
val marginTop = (height - baseSize * labels.size) / 2.0f
|
||||||
rect[0f, marginTop, width.toFloat()] = marginTop + baseSize
|
rect[0f, marginTop, width.toFloat()] = marginTop + baseSize
|
||||||
@@ -86,7 +88,7 @@ class TargetChart : View {
|
|||||||
val params = layoutParams
|
val params = layoutParams
|
||||||
if (params != null && params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
if (params != null && params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||||
height = MeasureSpec.getSize(heightSpec)
|
height = MeasureSpec.getSize(heightSpec)
|
||||||
if (labels.size > 0) baseSize = height / labels.size
|
if (labels.isNotEmpty()) baseSize = height / labels.size
|
||||||
}
|
}
|
||||||
heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
|
heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
|
||||||
widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY)
|
widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY)
|
||||||
@@ -116,7 +118,7 @@ class TargetChart : View {
|
|||||||
rect.bottom - baseSize * 0.05f
|
rect.bottom - baseSize * 0.05f
|
||||||
canvas.drawRoundRect(barRect, round, round, paint!!)
|
canvas.drawRoundRect(barRect, round, round, paint!!)
|
||||||
var percentage = (values[row] / targets[row]).toFloat()
|
var percentage = (values[row] / targets[row]).toFloat()
|
||||||
percentage = Math.min(1.0f, percentage)
|
percentage = min(1.0f, percentage)
|
||||||
|
|
||||||
// Draw completed box
|
// Draw completed box
|
||||||
var completedWidth = percentage * barRect.width()
|
var completedWidth = percentage * barRect.width()
|
||||||
|
|||||||
@@ -173,8 +173,8 @@ class ListHabitsScreen
|
|||||||
ConfirmDeleteDialog(activity, callback, quantity).show()
|
ConfirmDeleteDialog(activity, callback, quantity).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEditHabitsScreen(habits: List<Habit>) {
|
override fun showEditHabitsScreen(selected: List<Habit>) {
|
||||||
val intent = intentFactory.startEditActivity(activity, habits[0])
|
val intent = intentFactory.startEditActivity(activity, selected[0])
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +183,8 @@ class ListHabitsScreen
|
|||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showHabitScreen(habit: Habit) {
|
override fun showHabitScreen(h: Habit) {
|
||||||
val intent = intentFactory.startShowHabitActivity(activity, habit)
|
val intent = intentFactory.startShowHabitActivity(activity, h)
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ class ListHabitsScreen
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showSendBugReportToDeveloperScreen(log: String?) {
|
override fun showSendBugReportToDeveloperScreen(log: String) {
|
||||||
val to = R.string.bugReportTo
|
val to = R.string.bugReportTo
|
||||||
val subject = R.string.bugReportSubject
|
val subject = R.string.bugReportSubject
|
||||||
activity.showSendEmailScreen(to, subject, log)
|
activity.showSendEmailScreen(to, subject, log)
|
||||||
@@ -287,13 +287,17 @@ class ListHabitsScreen
|
|||||||
private fun onImportData(file: File, onFinished: () -> Unit) {
|
private fun onImportData(file: File, onFinished: () -> Unit) {
|
||||||
taskRunner.execute(
|
taskRunner.execute(
|
||||||
importTaskFactory.create(file) { result ->
|
importTaskFactory.create(file) { result ->
|
||||||
if (result == ImportDataTask.SUCCESS) {
|
when (result) {
|
||||||
adapter.refresh()
|
ImportDataTask.SUCCESS -> {
|
||||||
activity.showMessage(activity.resources.getString(R.string.habits_imported))
|
adapter.refresh()
|
||||||
} else if (result == ImportDataTask.NOT_RECOGNIZED) {
|
activity.showMessage(activity.resources.getString(R.string.habits_imported))
|
||||||
activity.showMessage(activity.resources.getString(R.string.file_not_recognized))
|
}
|
||||||
} else {
|
ImportDataTask.NOT_RECOGNIZED -> {
|
||||||
activity.showMessage(activity.resources.getString(R.string.could_not_import))
|
activity.showMessage(activity.resources.getString(R.string.file_not_recognized))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
activity.showMessage(activity.resources.getString(R.string.could_not_import))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onFinished()
|
onFinished()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,10 +90,6 @@ class HabitCardListAdapter @Inject constructor(
|
|||||||
return getItem(position)!!.id!!
|
return getItem(position)!!.id!!
|
||||||
}
|
}
|
||||||
|
|
||||||
// override fun getSelected(): List<Habit> {
|
|
||||||
// return LinkedList(selected)
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether list of selected items is empty.
|
* Returns whether list of selected items is empty.
|
||||||
*
|
*
|
||||||
@@ -158,8 +154,8 @@ class HabitCardListAdapter @Inject constructor(
|
|||||||
observable.notifyListeners()
|
observable.notifyListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemMoved(fromPosition: Int, toPosition: Int) {
|
override fun onItemMoved(oldPosition: Int, newPosition: Int) {
|
||||||
notifyItemMoved(fromPosition, toPosition)
|
notifyItemMoved(oldPosition, newPosition)
|
||||||
observable.notifyListeners()
|
observable.notifyListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,8 +205,8 @@ class HabitCardListAdapter @Inject constructor(
|
|||||||
cache.refreshAllHabits()
|
cache.refreshAllHabits()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setFilter(matcher: HabitMatcher?) {
|
override fun setFilter(matcher: HabitMatcher) {
|
||||||
if (matcher != null) cache.setFilter(matcher)
|
cache.setFilter(matcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -92,9 +92,7 @@ class HabitCardView(
|
|||||||
var score
|
var score
|
||||||
get() = scoreRing.getPercentage().toDouble()
|
get() = scoreRing.getPercentage().toDouble()
|
||||||
set(value) {
|
set(value) {
|
||||||
// scoreRing.percentage = value.toFloat()
|
|
||||||
scoreRing.setPercentage(value.toFloat())
|
scoreRing.setPercentage(value.toFloat())
|
||||||
// scoreRing.precision = 1.0f / 16
|
|
||||||
scoreRing.setPrecision(1.0f / 16)
|
scoreRing.setPrecision(1.0f / 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +226,6 @@ class HabitCardView(
|
|||||||
}
|
}
|
||||||
scoreRing.apply {
|
scoreRing.apply {
|
||||||
setColor(c)
|
setColor(c)
|
||||||
// color = c
|
|
||||||
}
|
}
|
||||||
checkmarkPanel.apply {
|
checkmarkPanel.apply {
|
||||||
color = c
|
color = c
|
||||||
|
|||||||
@@ -49,9 +49,7 @@ class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(con
|
|||||||
binding.monthDiffLabel.text = formatPercentageDiff(state.scoreMonthDiff)
|
binding.monthDiffLabel.text = formatPercentageDiff(state.scoreMonthDiff)
|
||||||
binding.scoreLabel.setTextColor(androidColor)
|
binding.scoreLabel.setTextColor(androidColor)
|
||||||
binding.scoreLabel.text = String.format("%.0f%%", state.scoreToday * 100)
|
binding.scoreLabel.text = String.format("%.0f%%", state.scoreToday * 100)
|
||||||
// binding.scoreRing.color = androidColor
|
|
||||||
binding.scoreRing.setColor(androidColor)
|
binding.scoreRing.setColor(androidColor)
|
||||||
// binding.scoreRing.percentage = state.scoreToday
|
|
||||||
binding.scoreRing.setPercentage(state.scoreToday)
|
binding.scoreRing.setPercentage(state.scoreToday)
|
||||||
|
|
||||||
binding.title.setTextColor(androidColor)
|
binding.title.setTextColor(androidColor)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class IntentScheduler
|
|||||||
return schedule(updateTime, intent, RTC)
|
return schedule(updateTime, intent, RTC)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log(componentName: String?, msg: String?) {
|
override fun log(componentName: String, msg: String) {
|
||||||
Log.d(componentName, msg)
|
Log.d(componentName, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ class AndroidNotificationTray
|
|||||||
) : NotificationTray.SystemTray {
|
) : NotificationTray.SystemTray {
|
||||||
private var active = HashSet<Int>()
|
private var active = HashSet<Int>()
|
||||||
|
|
||||||
override fun log(msg: String?) {
|
override fun log(msg: String) {
|
||||||
Log.d("AndroidNotificationTray", msg)
|
Log.d("AndroidNotificationTray", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeNotification(id: Int) {
|
override fun removeNotification(notificationId: Int) {
|
||||||
val manager = NotificationManagerCompat.from(context)
|
val manager = NotificationManagerCompat.from(context)
|
||||||
manager.cancel(id)
|
manager.cancel(notificationId)
|
||||||
active.remove(id)
|
active.remove(notificationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showNotification(
|
override fun showNotification(
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener {
|
|||||||
private var dialog: AlertDialog? = null
|
private var dialog: AlertDialog? = null
|
||||||
override fun onCreate(bundle: Bundle?) {
|
override fun onCreate(bundle: Bundle?) {
|
||||||
super.onCreate(bundle)
|
super.onCreate(bundle)
|
||||||
|
val intent = intent
|
||||||
if (intent == null) finish()
|
if (intent == null) finish()
|
||||||
if (intent.data == null) finish()
|
if (intent.data == null) finish()
|
||||||
val app = applicationContext as HabitsApplication
|
val app = applicationContext as HabitsApplication
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import org.isoron.uhabits.core.preferences.WidgetPreferences
|
|||||||
import org.isoron.uhabits.intents.PendingIntentFactory
|
import org.isoron.uhabits.intents.PendingIntentFactory
|
||||||
|
|
||||||
abstract class BaseWidget(val context: Context, val id: Int) {
|
abstract class BaseWidget(val context: Context, val id: Int) {
|
||||||
protected val widgetPrefs: WidgetPreferences
|
private val widgetPrefs: WidgetPreferences
|
||||||
protected val prefs: Preferences
|
protected val prefs: Preferences
|
||||||
protected val pendingIntentFactory: PendingIntentFactory
|
protected val pendingIntentFactory: PendingIntentFactory
|
||||||
protected val commandRunner: CommandRunner
|
protected val commandRunner: CommandRunner
|
||||||
@@ -120,9 +120,9 @@ abstract class BaseWidget(val context: Context, val id: Int) {
|
|||||||
return remoteViews
|
return remoteViews
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun measureView(view: View, width: Int, height: Int) {
|
private fun measureView(view: View, w: Int, h: Int) {
|
||||||
var width = width
|
var width = w
|
||||||
var height = height
|
var height = h
|
||||||
val inflater = LayoutInflater.from(context)
|
val inflater = LayoutInflater.from(context)
|
||||||
val entireView = inflater.inflate(R.layout.widget_wrapper, null)
|
val entireView = inflater.inflate(R.layout.widget_wrapper, null)
|
||||||
var specWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY)
|
var specWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY)
|
||||||
@@ -144,7 +144,7 @@ abstract class BaseWidget(val context: Context, val id: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected val preferedBackgroundAlpha: Int
|
protected val preferedBackgroundAlpha: Int
|
||||||
protected get() = prefs.widgetOpacity
|
get() = prefs.widgetOpacity
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val app = context.applicationContext as HabitsApplication
|
val app = context.applicationContext as HabitsApplication
|
||||||
|
|||||||
@@ -83,10 +83,8 @@ class CheckmarkWidgetView : HabitWidgetView {
|
|||||||
setShadowAlpha(0x00)
|
setShadowAlpha(0x00)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ring.percentage = percentage
|
|
||||||
ring.setPercentage(percentage)
|
ring.setPercentage(percentage)
|
||||||
ring.setColor(fgColor)
|
ring.setColor(fgColor)
|
||||||
// ring.color = fgColor
|
|
||||||
ring.setBackgroundColor(bgColor)
|
ring.setBackgroundColor(bgColor)
|
||||||
ring.setText(text)
|
ring.setText(text)
|
||||||
label.text = name
|
label.text = name
|
||||||
|
|||||||
@@ -101,20 +101,6 @@ abstract class HabitList : Iterable<Habit> {
|
|||||||
abstract var primaryOrder: Order
|
abstract var primaryOrder: Order
|
||||||
abstract var secondaryOrder: Order
|
abstract var secondaryOrder: Order
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Changes the order of the elements on the list.
|
|
||||||
// *
|
|
||||||
// * @param order the new order criterion
|
|
||||||
// */
|
|
||||||
// abstract fun setPrimaryOrder(order: Order)
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Changes the previous order of the elements on the list.
|
|
||||||
// *
|
|
||||||
// * @param order the new order criterion
|
|
||||||
// */
|
|
||||||
// abstract fun setSecondaryOrder(order: Order)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of the given habit in the list, or -1 if the list does
|
* Returns the index of the given habit in the list, or -1 if the list does
|
||||||
* not contain the habit.
|
* not contain the habit.
|
||||||
@@ -172,7 +158,7 @@ abstract class HabitList : Iterable<Habit> {
|
|||||||
*
|
*
|
||||||
* @param habits the list of habits that have been modified.
|
* @param habits the list of habits that have been modified.
|
||||||
*/
|
*/
|
||||||
abstract fun update(habits: List<Habit?>?)
|
abstract fun update(habits: List<Habit>)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the list that a certain habit has been modified.
|
* Notifies the list that a certain habit has been modified.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import java.util.TimeZone
|
|||||||
class Timestamp(unixTime: Long) : Comparable<Timestamp> {
|
class Timestamp(unixTime: Long) : Comparable<Timestamp> {
|
||||||
val unixTime: Long
|
val unixTime: Long
|
||||||
|
|
||||||
constructor(cal: GregorianCalendar) : this(cal.timeInMillis) {}
|
constructor(cal: GregorianCalendar) : this(cal.timeInMillis)
|
||||||
|
|
||||||
fun toLocalDate(): LocalDate {
|
fun toLocalDate(): LocalDate {
|
||||||
val millisSince2000 = unixTime - 946684800000L
|
val millisSince2000 = unixTime - 946684800000L
|
||||||
|
|||||||
@@ -119,16 +119,12 @@ class MemoryHabitList : HabitList {
|
|||||||
|
|
||||||
private fun getComparatorByOrder(order: Order): Comparator<Habit> {
|
private fun getComparatorByOrder(order: Order): Comparator<Habit> {
|
||||||
val nameComparatorAsc = Comparator<Habit> { habit1, habit2 ->
|
val nameComparatorAsc = Comparator<Habit> { habit1, habit2 ->
|
||||||
habit1.name.compareTo(
|
habit1.name.compareTo(habit2.name)
|
||||||
habit2.name
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
val nameComparatorDesc =
|
val nameComparatorDesc =
|
||||||
Comparator { h1: Habit, h2: Habit -> nameComparatorAsc.compare(h2, h1) }
|
Comparator { h1: Habit, h2: Habit -> nameComparatorAsc.compare(h2, h1) }
|
||||||
val colorComparatorAsc = Comparator<Habit> { (color1), (color2) ->
|
val colorComparatorAsc = Comparator<Habit> { (color1), (color2) ->
|
||||||
color1.compareTo(
|
color1.compareTo(color2)
|
||||||
color2
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
val colorComparatorDesc =
|
val colorComparatorDesc =
|
||||||
Comparator { h1: Habit, h2: Habit -> colorComparatorAsc.compare(h2, h1) }
|
Comparator { h1: Habit, h2: Habit -> colorComparatorAsc.compare(h2, h1) }
|
||||||
@@ -140,9 +136,7 @@ class MemoryHabitList : HabitList {
|
|||||||
val scoreComparatorAsc =
|
val scoreComparatorAsc =
|
||||||
Comparator { h1: Habit, h2: Habit -> scoreComparatorDesc.compare(h2, h1) }
|
Comparator { h1: Habit, h2: Habit -> scoreComparatorDesc.compare(h2, h1) }
|
||||||
val positionComparator =
|
val positionComparator =
|
||||||
Comparator<Habit> { habit1, habit2 ->
|
Comparator<Habit> { habit1, habit2 -> habit1.position.compareTo(habit2.position) }
|
||||||
habit1.position.compareTo(habit2.position)
|
|
||||||
}
|
|
||||||
val statusComparatorDesc = Comparator { h1: Habit, h2: Habit ->
|
val statusComparatorDesc = Comparator { h1: Habit, h2: Habit ->
|
||||||
if (h1.isCompletedToday() != h2.isCompletedToday()) {
|
if (h1.isCompletedToday() != h2.isCompletedToday()) {
|
||||||
return@Comparator if (h1.isCompletedToday()) -1 else 1
|
return@Comparator if (h1.isCompletedToday()) -1 else 1
|
||||||
@@ -206,7 +200,7 @@ class MemoryHabitList : HabitList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun update(habits: List<Habit?>?) {
|
override fun update(habits: List<Habit>) {
|
||||||
resort()
|
resort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import javax.inject.Inject
|
|||||||
* Implementation of a [HabitList] that is backed by SQLite.
|
* Implementation of a [HabitList] that is backed by SQLite.
|
||||||
*/
|
*/
|
||||||
class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory) : HabitList() {
|
class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory) : HabitList() {
|
||||||
private val repository: Repository<HabitRecord>
|
private val repository: Repository<HabitRecord> = modelFactory.buildHabitListRepository()
|
||||||
private val list: MemoryHabitList = MemoryHabitList()
|
private val list: MemoryHabitList = MemoryHabitList()
|
||||||
private var loaded = false
|
private var loaded = false
|
||||||
private fun loadRecords() {
|
private fun loadRecords() {
|
||||||
@@ -197,13 +197,11 @@ class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun update(habits: List<Habit?>?) {
|
override fun update(habits: List<Habit>) {
|
||||||
loadRecords()
|
loadRecords()
|
||||||
list.update(habits)
|
list.update(habits)
|
||||||
for (h in habits!!) {
|
for (h in habits) {
|
||||||
val record = repository.find(
|
val record = repository.find(h.id!!) ?: continue
|
||||||
h!!.id!!
|
|
||||||
) ?: continue
|
|
||||||
record.copyFrom(h)
|
record.copyFrom(h)
|
||||||
repository.save(record)
|
repository.save(record)
|
||||||
}
|
}
|
||||||
@@ -219,8 +217,4 @@ class SQLiteHabitList @Inject constructor(private val modelFactory: ModelFactory
|
|||||||
fun reload() {
|
fun reload() {
|
||||||
loaded = false
|
loaded = false
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
repository = modelFactory.buildHabitListRepository()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,11 +47,6 @@ class EntryRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun toEntry(): Entry {
|
fun toEntry(): Entry {
|
||||||
return Entry(
|
return Entry(Timestamp(timestamp!!), value!!)
|
||||||
Timestamp(
|
|
||||||
timestamp!!
|
|
||||||
),
|
|
||||||
value!!
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,8 +85,9 @@ class HabitRecord {
|
|||||||
|
|
||||||
@field:Column
|
@field:Column
|
||||||
var uuid: String? = null
|
var uuid: String? = null
|
||||||
fun copyFrom(model: Habit?) {
|
|
||||||
id = model!!.id
|
fun copyFrom(model: Habit) {
|
||||||
|
id = model.id
|
||||||
name = model.name
|
name = model.name
|
||||||
description = model.description
|
description = model.description
|
||||||
highlight = 0
|
highlight = 0
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class ReminderScheduler @Inject constructor(
|
|||||||
): SchedulerResult
|
): SchedulerResult
|
||||||
|
|
||||||
fun scheduleWidgetUpdate(updateTime: Long): SchedulerResult?
|
fun scheduleWidgetUpdate(updateTime: Long): SchedulerResult?
|
||||||
fun log(componentName: String?, msg: String?)
|
fun log(componentName: String, msg: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SchedulerResult {
|
enum class SchedulerResult {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class NotificationTray @Inject constructor(
|
|||||||
private val preferences: Preferences,
|
private val preferences: Preferences,
|
||||||
private val systemTray: SystemTray
|
private val systemTray: SystemTray
|
||||||
) : CommandRunner.Listener, Preferences.Listener {
|
) : CommandRunner.Listener, Preferences.Listener {
|
||||||
private val active: HashMap<Habit, NotificationData>
|
private val active: HashMap<Habit, NotificationData> = HashMap()
|
||||||
fun cancel(habit: Habit) {
|
fun cancel(habit: Habit) {
|
||||||
val notificationId = getNotificationId(habit)
|
val notificationId = getNotificationId(habit)
|
||||||
systemTray.removeNotification(notificationId)
|
systemTray.removeNotification(notificationId)
|
||||||
@@ -86,8 +86,7 @@ class NotificationTray @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun reshowAll() {
|
private fun reshowAll() {
|
||||||
for (habit in active.keys) {
|
for ((habit, data) in active.entries) {
|
||||||
val data = active[habit]!!
|
|
||||||
taskRunner.execute(ShowNotificationTask(habit, data))
|
taskRunner.execute(ShowNotificationTask(habit, data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,15 +100,15 @@ class NotificationTray @Inject constructor(
|
|||||||
reminderTime: Long
|
reminderTime: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
fun log(msg: String?)
|
fun log(msg: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NotificationData(val timestamp: Timestamp, val reminderTime: Long)
|
internal class NotificationData(val timestamp: Timestamp, val reminderTime: Long)
|
||||||
private inner class ShowNotificationTask(private val habit: Habit, data: NotificationData) :
|
private inner class ShowNotificationTask(private val habit: Habit, data: NotificationData) :
|
||||||
Task {
|
Task {
|
||||||
var todayValue = 0
|
var todayValue = 0
|
||||||
private val timestamp: Timestamp
|
private val timestamp: Timestamp = data.timestamp
|
||||||
private val reminderTime: Long
|
private val reminderTime: Long = data.reminderTime
|
||||||
override fun doInBackground() {
|
override fun doInBackground() {
|
||||||
val today = getTodayWithOffset()
|
val today = getTodayWithOffset()
|
||||||
todayValue = habit.computedEntries.get(today).value
|
todayValue = habit.computedEntries.get(today).value
|
||||||
@@ -172,18 +171,9 @@ class NotificationTray @Inject constructor(
|
|||||||
val weekday = timestamp.weekday
|
val weekday = timestamp.weekday
|
||||||
return reminderDays[weekday]
|
return reminderDays[weekday]
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
timestamp = data.timestamp
|
|
||||||
reminderTime = data.reminderTime
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val REMINDERS_CHANNEL_ID = "REMINDERS"
|
const val REMINDERS_CHANNEL_ID = "REMINDERS"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
active = HashMap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class HabitCardListCache @Inject constructor(
|
|||||||
private val data: CacheData
|
private val data: CacheData
|
||||||
private var filteredHabits: HabitList
|
private var filteredHabits: HabitList
|
||||||
private val taskRunner: TaskRunner
|
private val taskRunner: TaskRunner
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun cancelTasks() {
|
fun cancelTasks() {
|
||||||
currentFetchTask?.cancel()
|
currentFetchTask?.cancel()
|
||||||
@@ -195,6 +196,7 @@ class HabitCardListCache @Inject constructor(
|
|||||||
val habits: MutableList<Habit>
|
val habits: MutableList<Habit>
|
||||||
val checkmarks: HashMap<Long?, IntArray>
|
val checkmarks: HashMap<Long?, IntArray>
|
||||||
val scores: HashMap<Long?, Double>
|
val scores: HashMap<Long?, Double>
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun copyCheckmarksFrom(oldData: CacheData) {
|
fun copyCheckmarksFrom(oldData: CacheData) {
|
||||||
val empty = IntArray(checkmarkCount)
|
val empty = IntArray(checkmarkCount)
|
||||||
@@ -263,18 +265,14 @@ class HabitCardListCache @Inject constructor(
|
|||||||
if (runner != null) runner!!.publishProgress(this, -1)
|
if (runner != null) runner!!.publishProgress(this, -1)
|
||||||
for (position in newData.habits.indices) {
|
for (position in newData.habits.indices) {
|
||||||
if (isCancelled) return
|
if (isCancelled) return
|
||||||
val (_, _, _, id, _, _, _, _, _, _, _, _, _, _, computedEntries, _, scores) = newData.habits[position]
|
val habit = newData.habits[position]
|
||||||
if (targetId != null && targetId != id) continue
|
if (targetId != null && targetId != habit.id) continue
|
||||||
newData.scores[id] = scores[today].value
|
newData.scores[habit.id] = habit.scores[today].value
|
||||||
val list: MutableList<Int> = ArrayList()
|
val list: MutableList<Int> = ArrayList()
|
||||||
for (
|
for ((_, value) in habit.computedEntries.getByInterval(dateFrom, today))
|
||||||
(_, value) in computedEntries
|
|
||||||
.getByInterval(dateFrom, today)
|
|
||||||
) {
|
|
||||||
list.add(value)
|
list.add(value)
|
||||||
}
|
|
||||||
val entries = list.toTypedArray()
|
val entries = list.toTypedArray()
|
||||||
newData.checkmarks[id] = ArrayUtils.toPrimitive(entries)
|
newData.checkmarks[habit.id] = ArrayUtils.toPrimitive(entries)
|
||||||
runner!!.publishProgress(this, position)
|
runner!!.publishProgress(this, position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.io.File
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
open class ListHabitsBehavior @Inject constructor(
|
open class ListHabitsBehavior @Inject constructor(
|
||||||
private val habitList: HabitList,
|
private val habitList: HabitList,
|
||||||
@@ -51,14 +52,11 @@ open class ListHabitsBehavior @Inject constructor(
|
|||||||
val oldValue = entries.get(timestamp!!).value.toDouble()
|
val oldValue = entries.get(timestamp!!).value.toDouble()
|
||||||
screen.showNumberPicker(
|
screen.showNumberPicker(
|
||||||
oldValue / 1000,
|
oldValue / 1000,
|
||||||
habit.unit,
|
habit.unit
|
||||||
{ newValue: Double ->
|
) { newValue: Double ->
|
||||||
val value = Math.round(newValue * 1000).toDouble()
|
val value = (newValue * 1000).roundToInt()
|
||||||
commandRunner.run(
|
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value))
|
||||||
CreateRepetitionCommand(habitList, habit, timestamp, value.toInt())
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onExportCSV() {
|
fun onExportCSV() {
|
||||||
@@ -154,7 +152,7 @@ open class ListHabitsBehavior @Inject constructor(
|
|||||||
callback: NumberPickerCallback
|
callback: NumberPickerCallback
|
||||||
)
|
)
|
||||||
|
|
||||||
fun showSendBugReportToDeveloperScreen(log: String?)
|
fun showSendBugReportToDeveloperScreen(log: String)
|
||||||
fun showSendFileScreen(filename: String)
|
fun showSendFileScreen(filename: String)
|
||||||
fun showConfirmInstallSyncKey(callback: OnConfirmedCallback)
|
fun showConfirmInstallSyncKey(callback: OnConfirmedCallback)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,10 +109,7 @@ class ListHabitsMenuBehavior @Inject constructor(
|
|||||||
|
|
||||||
interface Adapter {
|
interface Adapter {
|
||||||
fun refresh()
|
fun refresh()
|
||||||
fun setFilter(matcher: HabitMatcher?)
|
fun setFilter(matcher: HabitMatcher)
|
||||||
// fun setSecondaryOrder(order: HabitList.Order)
|
|
||||||
// fun setPrimaryOrder(order: HabitList.Order)
|
|
||||||
// fun getPrimaryOrder(): HabitList.Order
|
|
||||||
var primaryOrder: HabitList.Order
|
var primaryOrder: HabitList.Order
|
||||||
var secondaryOrder: HabitList.Order
|
var secondaryOrder: HabitList.Order
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,19 +51,15 @@ class ListHabitsSelectionMenuBehavior @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onArchiveHabits() {
|
fun onArchiveHabits() {
|
||||||
commandRunner.run(
|
commandRunner.run(ArchiveHabitsCommand(habitList, adapter.selected))
|
||||||
ArchiveHabitsCommand(habitList, adapter.selected)
|
|
||||||
)
|
|
||||||
adapter.clearSelection()
|
adapter.clearSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onChangeColor() {
|
fun onChangeColor() {
|
||||||
val selected = adapter.selected
|
val selected = adapter.selected
|
||||||
val (color) = selected[0]
|
val (color) = selected[0]
|
||||||
screen.showColorPicker(color) { selectedColor: PaletteColor? ->
|
screen.showColorPicker(color) { selectedColor: PaletteColor ->
|
||||||
commandRunner.run(
|
commandRunner.run(ChangeHabitColorCommand(habitList, selected, selectedColor))
|
||||||
ChangeHabitColorCommand(habitList, selected, selectedColor!!)
|
|
||||||
)
|
|
||||||
adapter.clearSelection()
|
adapter.clearSelection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,9 +69,7 @@ class ListHabitsSelectionMenuBehavior @Inject constructor(
|
|||||||
screen.showDeleteConfirmationScreen(
|
screen.showDeleteConfirmationScreen(
|
||||||
{
|
{
|
||||||
adapter.performRemove(selected)
|
adapter.performRemove(selected)
|
||||||
commandRunner.run(
|
commandRunner.run(DeleteHabitsCommand(habitList, selected))
|
||||||
DeleteHabitsCommand(habitList, selected)
|
|
||||||
)
|
|
||||||
adapter.clearSelection()
|
adapter.clearSelection()
|
||||||
},
|
},
|
||||||
selected.size
|
selected.size
|
||||||
@@ -88,9 +82,7 @@ class ListHabitsSelectionMenuBehavior @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onUnarchiveHabits() {
|
fun onUnarchiveHabits() {
|
||||||
commandRunner.run(
|
commandRunner.run(UnarchiveHabitsCommand(habitList, adapter.selected))
|
||||||
UnarchiveHabitsCommand(habitList, adapter.selected)
|
|
||||||
)
|
|
||||||
adapter.clearSelection()
|
adapter.clearSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,16 +29,16 @@ import org.junit.Before
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class RepositoryTest : BaseUnitTest() {
|
class RepositoryTest : BaseUnitTest() {
|
||||||
private var repository: Repository<ThingRecord>? = null
|
private lateinit var repository: Repository<ThingRecord>
|
||||||
private var db: Database? = null
|
private lateinit var db: Database
|
||||||
@Before
|
@Before
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
db = buildMemoryDatabase()
|
db = buildMemoryDatabase()
|
||||||
repository = Repository(ThingRecord::class.java, db!!)
|
repository = Repository(ThingRecord::class.java, db)
|
||||||
db!!.execute("drop table if exists tests")
|
db.execute("drop table if exists tests")
|
||||||
db!!.execute(
|
db.execute(
|
||||||
"create table tests(" +
|
"create table tests(" +
|
||||||
"id integer not null primary key autoincrement, " +
|
"id integer not null primary key autoincrement, " +
|
||||||
"color_number integer not null, score float not null, " +
|
"color_number integer not null, score float not null, " +
|
||||||
@@ -49,11 +49,11 @@ class RepositoryTest : BaseUnitTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testFind() {
|
fun testFind() {
|
||||||
db!!.execute(
|
db.execute(
|
||||||
"insert into tests(id, color_number, name, score) " +
|
"insert into tests(id, color_number, name, score) " +
|
||||||
"values (10, 20, 'hello', 8.0)"
|
"values (10, 20, 'hello', 8.0)"
|
||||||
)
|
)
|
||||||
val record = repository!!.find(10L)
|
val record = repository.find(10L)
|
||||||
Assert.assertNotNull(record)
|
Assert.assertNotNull(record)
|
||||||
MatcherAssert.assertThat(record!!.id, IsEqual.equalTo(10L))
|
MatcherAssert.assertThat(record!!.id, IsEqual.equalTo(10L))
|
||||||
MatcherAssert.assertThat(record.color, IsEqual.equalTo(20))
|
MatcherAssert.assertThat(record.color, IsEqual.equalTo(20))
|
||||||
@@ -64,38 +64,30 @@ class RepositoryTest : BaseUnitTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testSave_withId() {
|
fun testSave_withId() {
|
||||||
val record = ThingRecord()
|
val record = ThingRecord().apply {
|
||||||
record.id = 50L
|
id = 50L
|
||||||
record.color = 10
|
color = 10
|
||||||
record.name = "hello"
|
name = "hello"
|
||||||
record.score = 5.0
|
score = 5.0
|
||||||
repository!!.save(record)
|
}
|
||||||
MatcherAssert.assertThat(
|
repository.save(record)
|
||||||
record,
|
MatcherAssert.assertThat(record, IsEqual.equalTo(repository.find(50L)))
|
||||||
IsEqual.equalTo(
|
|
||||||
repository!!.find(50L)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
record.name = "world"
|
record.name = "world"
|
||||||
record.score = 128.0
|
record.score = 128.0
|
||||||
repository!!.save(record)
|
repository.save(record)
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(record, IsEqual.equalTo(repository.find(50L)))
|
||||||
record,
|
|
||||||
IsEqual.equalTo(
|
|
||||||
repository!!.find(50L)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testSave_withNull() {
|
fun testSave_withNull() {
|
||||||
val record = ThingRecord()
|
val record = ThingRecord().apply {
|
||||||
record.color = 50
|
color = 50
|
||||||
record.name = null
|
name = null
|
||||||
record.score = 12.0
|
score = 12.0
|
||||||
repository!!.save(record)
|
}
|
||||||
val retrieved = repository!!.find(record.id!!)
|
repository.save(record)
|
||||||
|
val retrieved = repository.find(record.id!!)
|
||||||
Assert.assertNotNull(retrieved)
|
Assert.assertNotNull(retrieved)
|
||||||
Assert.assertNull(retrieved!!.name)
|
Assert.assertNull(retrieved!!.name)
|
||||||
MatcherAssert.assertThat(record, IsEqual.equalTo(retrieved))
|
MatcherAssert.assertThat(record, IsEqual.equalTo(retrieved))
|
||||||
@@ -104,16 +96,18 @@ class RepositoryTest : BaseUnitTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testSave_withoutId() {
|
fun testSave_withoutId() {
|
||||||
val r1 = ThingRecord()
|
val r1 = ThingRecord().apply {
|
||||||
r1.color = 10
|
color = 10
|
||||||
r1.name = "hello"
|
name = "hello"
|
||||||
r1.score = 16.0
|
score = 16.0
|
||||||
repository!!.save(r1)
|
}
|
||||||
val r2 = ThingRecord()
|
repository.save(r1)
|
||||||
r2.color = 20
|
val r2 = ThingRecord().apply {
|
||||||
r2.name = "world"
|
color = 20
|
||||||
r2.score = 2.0
|
name = "world"
|
||||||
repository!!.save(r2)
|
score = 2.0
|
||||||
|
}
|
||||||
|
repository.save(r2)
|
||||||
MatcherAssert.assertThat(r1.id, IsEqual.equalTo(1L))
|
MatcherAssert.assertThat(r1.id, IsEqual.equalTo(1L))
|
||||||
MatcherAssert.assertThat(r2.id, IsEqual.equalTo(2L))
|
MatcherAssert.assertThat(r2.id, IsEqual.equalTo(2L))
|
||||||
}
|
}
|
||||||
@@ -121,40 +115,27 @@ class RepositoryTest : BaseUnitTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testRemove() {
|
fun testRemove() {
|
||||||
val rec1 = ThingRecord()
|
val rec1 = ThingRecord().apply {
|
||||||
rec1.color = 10
|
color = 10
|
||||||
rec1.name = "hello"
|
name = "hello"
|
||||||
rec1.score = 16.0
|
score = 16.0
|
||||||
repository!!.save(rec1)
|
}
|
||||||
val rec2 = ThingRecord()
|
repository.save(rec1)
|
||||||
rec2.color = 20
|
val rec2 = ThingRecord().apply {
|
||||||
rec2.name = "world"
|
color = 20
|
||||||
rec2.score = 32.0
|
name = "world"
|
||||||
repository!!.save(rec2)
|
score = 32.0
|
||||||
|
}
|
||||||
|
repository.save(rec2)
|
||||||
val id = rec1.id!!
|
val id = rec1.id!!
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(rec1, IsEqual.equalTo(repository.find(id)))
|
||||||
rec1,
|
MatcherAssert.assertThat(rec2, IsEqual.equalTo(repository.find(rec2.id!!)))
|
||||||
IsEqual.equalTo(
|
repository.remove(rec1)
|
||||||
repository!!.find(id)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
MatcherAssert.assertThat(
|
|
||||||
rec2,
|
|
||||||
IsEqual.equalTo(
|
|
||||||
repository!!.find(rec2.id!!)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
repository!!.remove(rec1)
|
|
||||||
MatcherAssert.assertThat(rec1.id, IsEqual.equalTo(null))
|
MatcherAssert.assertThat(rec1.id, IsEqual.equalTo(null))
|
||||||
Assert.assertNull(repository!!.find(id))
|
Assert.assertNull(repository.find(id))
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(rec2, IsEqual.equalTo(repository.find(rec2.id!!)))
|
||||||
rec2,
|
repository.remove(rec1) // should have no effect
|
||||||
IsEqual.equalTo(
|
Assert.assertNull(repository.find(id))
|
||||||
repository!!.find(rec2.id!!)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
repository!!.remove(rec1) // should have no effect
|
|
||||||
Assert.assertNull(repository!!.find(id))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table(name = "tests")
|
@Table(name = "tests")
|
||||||
|
|||||||
@@ -381,5 +381,5 @@ class EntryListTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun day(offset: Int) = DateUtils.getToday().minus(offset)!!
|
fun day(offset: Int) = DateUtils.getToday().minus(offset)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.junit.Test
|
|||||||
class HabitRecordTest : BaseUnitTest() {
|
class HabitRecordTest : BaseUnitTest() {
|
||||||
@Test
|
@Test
|
||||||
fun testCopyRestore1() {
|
fun testCopyRestore1() {
|
||||||
val original = modelFactory.buildHabit().apply() {
|
val original = modelFactory.buildHabit().apply {
|
||||||
name = "Hello world"
|
name = "Hello world"
|
||||||
question = "Did you greet the world today?"
|
question = "Did you greet the world today?"
|
||||||
color = PaletteColor(1)
|
color = PaletteColor(1)
|
||||||
@@ -50,7 +50,7 @@ class HabitRecordTest : BaseUnitTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCopyRestore2() {
|
fun testCopyRestore2() {
|
||||||
val original = modelFactory.buildHabit().apply() {
|
val original = modelFactory.buildHabit().apply {
|
||||||
name = "Hello world"
|
name = "Hello world"
|
||||||
question = "Did you greet the world today?"
|
question = "Did you greet the world today?"
|
||||||
color = PaletteColor(5)
|
color = PaletteColor(5)
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.sync.app
|
package org.isoron.uhabits.sync.app
|
||||||
|
|
||||||
|
import com.nhaarman.mockitokotlin2.mock
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import org.isoron.uhabits.sync.server.*
|
import org.isoron.uhabits.sync.server.*
|
||||||
import org.mockito.Mockito.*
|
|
||||||
|
|
||||||
open class BaseApplicationTest {
|
open class BaseApplicationTest {
|
||||||
|
|
||||||
protected val server: AbstractSyncServer = mock(AbstractSyncServer::class.java)
|
protected val server: AbstractSyncServer = mock()
|
||||||
|
|
||||||
protected fun app(): Application.() -> Unit = {
|
protected fun app(): Application.() -> Unit = {
|
||||||
SyncApplication(server).apply {
|
SyncApplication(server).apply {
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.sync.app
|
package org.isoron.uhabits.sync.app
|
||||||
|
|
||||||
|
import com.nhaarman.mockitokotlin2.verify
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.testing.*
|
import io.ktor.server.testing.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.isoron.uhabits.sync.*
|
import org.isoron.uhabits.sync.*
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.Mockito.*
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class StorageModuleTest : BaseApplicationTest() {
|
class StorageModuleTest : BaseApplicationTest() {
|
||||||
|
|||||||
Reference in New Issue
Block a user