Clean up code after conversions

pull/716/head
Quentin Hibon 5 years ago
parent 18db571507
commit 6992b5186e

@ -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,14 +287,18 @@ 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) {
ImportDataTask.SUCCESS -> {
adapter.refresh() adapter.refresh()
activity.showMessage(activity.resources.getString(R.string.habits_imported)) activity.showMessage(activity.resources.getString(R.string.habits_imported))
} else if (result == ImportDataTask.NOT_RECOGNIZED) { }
ImportDataTask.NOT_RECOGNIZED -> {
activity.showMessage(activity.resources.getString(R.string.file_not_recognized)) activity.showMessage(activity.resources.getString(R.string.file_not_recognized))
} else { }
else -> {
activity.showMessage(activity.resources.getString(R.string.could_not_import)) 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() {

Loading…
Cancel
Save