mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Remove DateCalculator
This commit is contained in:
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,9 +1,16 @@
|
||||
*.iml
|
||||
.gradle
|
||||
local.properties
|
||||
.idea
|
||||
*.pbxuser
|
||||
*.perspective
|
||||
*.perspectivev3
|
||||
*.swp
|
||||
*~.nib
|
||||
.DS_Store
|
||||
build
|
||||
captures
|
||||
.externalNativeBuild
|
||||
.gradle
|
||||
.idea
|
||||
build
|
||||
build/
|
||||
captures
|
||||
local.properties
|
||||
node_modules
|
||||
*xcuserdata*
|
||||
|
||||
@@ -26,7 +26,7 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:3.2.1"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,17 +42,11 @@ apply plugin:"kotlin-multiplatform"
|
||||
|
||||
kotlin {
|
||||
targets {
|
||||
def iosPreset = System.getenv('SDK_NAME')?.startsWith("iphoneos") ? presets.iosArm64 : presets.iosX64
|
||||
fromPreset(presets.jvm, 'jvm')
|
||||
|
||||
fromPreset(presets.iosX64, 'iOS') {
|
||||
fromPreset(iosPreset, 'iOS') {
|
||||
compilations.main.outputKinds('FRAMEWORK')
|
||||
}
|
||||
|
||||
// Replace the target above by the following one to produce a framework
|
||||
// which can be installed on a real iPhone:
|
||||
// fromPreset(presets.iosArm64, 'iOS') {
|
||||
// compilations.main.outputKinds('FRAMEWORK')
|
||||
// }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -31,48 +31,143 @@ enum class DayOfWeek(val index: Int) {
|
||||
SATURDAY(6),
|
||||
}
|
||||
|
||||
data class Timestamp(val unixTimeInMillis: Long)
|
||||
data class Timestamp(val millisSince1970: Long) {
|
||||
val localDate: LocalDate
|
||||
get() {
|
||||
val millisSince2000 = millisSince1970 - 946684800000
|
||||
val daysSince2000 = millisSince2000 / 86400000
|
||||
return LocalDate(daysSince2000.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
data class LocalDate(val year: Int,
|
||||
val month: Int,
|
||||
val day: Int) {
|
||||
data class LocalDate(val daysSince2000: Int) {
|
||||
|
||||
var yearCache = -1
|
||||
var monthCache = -1
|
||||
var dayCache = -1
|
||||
|
||||
init {
|
||||
if (daysSince2000 < 0)
|
||||
throw IllegalArgumentException("$daysSince2000 < 0")
|
||||
}
|
||||
|
||||
constructor(year: Int, month: Int, day: Int) :
|
||||
this(daysSince2000(year, month, day))
|
||||
|
||||
val dayOfWeek: DayOfWeek
|
||||
get() {
|
||||
return when (daysSince2000 % 7) {
|
||||
0 -> DayOfWeek.SATURDAY
|
||||
1 -> DayOfWeek.SUNDAY
|
||||
2 -> DayOfWeek.MONDAY
|
||||
3 -> DayOfWeek.TUESDAY
|
||||
4 -> DayOfWeek.WEDNESDAY
|
||||
5 -> DayOfWeek.THURSDAY
|
||||
else -> DayOfWeek.FRIDAY
|
||||
}
|
||||
}
|
||||
|
||||
val timestamp: Timestamp
|
||||
get() {
|
||||
return Timestamp(946684800000 + daysSince2000.toLong() * 86400000)
|
||||
}
|
||||
|
||||
val year: Int
|
||||
get() {
|
||||
if (yearCache < 0) updateYearMonthDayCache()
|
||||
return yearCache
|
||||
}
|
||||
|
||||
val month: Int
|
||||
get() {
|
||||
if (monthCache < 0) updateYearMonthDayCache()
|
||||
return monthCache
|
||||
}
|
||||
|
||||
val day: Int
|
||||
get() {
|
||||
if (dayCache < 0) updateYearMonthDayCache()
|
||||
return dayCache
|
||||
}
|
||||
|
||||
private fun updateYearMonthDayCache() {
|
||||
var currYear = 2000
|
||||
var currDay = 0
|
||||
|
||||
while (true) {
|
||||
val currYearLength = if (isLeapYear(currYear)) 366 else 365
|
||||
if (daysSince2000 < currDay + currYearLength) {
|
||||
yearCache = currYear
|
||||
break
|
||||
} else {
|
||||
currYear++
|
||||
currDay += currYearLength
|
||||
}
|
||||
}
|
||||
|
||||
var currMonth = 1
|
||||
val monthOffset = if (isLeapYear(currYear)) leapOffset else nonLeapOffset
|
||||
|
||||
while (true) {
|
||||
if (daysSince2000 < currDay + monthOffset[currMonth]) {
|
||||
monthCache = currMonth
|
||||
break
|
||||
} else {
|
||||
currMonth++
|
||||
}
|
||||
}
|
||||
|
||||
currDay += monthOffset[currMonth - 1]
|
||||
dayCache = daysSince2000 - currDay + 1
|
||||
|
||||
}
|
||||
|
||||
fun isOlderThan(other: LocalDate): Boolean {
|
||||
if (other.year != year) return other.year > year
|
||||
if (other.month != month) return other.month > month
|
||||
return other.day > day
|
||||
return daysSince2000 < other.daysSince2000
|
||||
}
|
||||
|
||||
fun isNewerThan(other: LocalDate): Boolean {
|
||||
if (this == other) return false
|
||||
return other.isOlderThan(this)
|
||||
return daysSince2000 > other.daysSince2000
|
||||
}
|
||||
|
||||
init {
|
||||
if ((month <= 0) or (month >= 13)) throw(IllegalArgumentException())
|
||||
if ((day <= 0) or (day >= 32)) throw(IllegalArgumentException())
|
||||
}
|
||||
fun plus(days: Int): LocalDate {
|
||||
return LocalDate(daysSince2000 + days)
|
||||
}
|
||||
|
||||
interface LocalDateCalculator {
|
||||
fun plusDays(date: LocalDate, days: Int): LocalDate
|
||||
fun dayOfWeek(date: LocalDate): DayOfWeek
|
||||
fun toTimestamp(date: LocalDate): Timestamp
|
||||
fun fromTimestamp(timestamp: Timestamp): LocalDate
|
||||
fun minus(days: Int): LocalDate {
|
||||
return LocalDate(daysSince2000 - days)
|
||||
}
|
||||
|
||||
fun LocalDateCalculator.distanceInDays(d1: LocalDate, d2: LocalDate): Int {
|
||||
val t1 = toTimestamp(d1)
|
||||
val t2 = toTimestamp(d2)
|
||||
val dayLength = 24 * 60 * 60 * 1000
|
||||
return abs((t2.unixTimeInMillis - t1.unixTimeInMillis) / dayLength).toInt()
|
||||
fun distanceTo(other: LocalDate): Int {
|
||||
return abs(daysSince2000 - other.daysSince2000)
|
||||
}
|
||||
|
||||
fun LocalDateCalculator.minusDays(date: LocalDate, days: Int): LocalDate {
|
||||
return plusDays(date, -days)
|
||||
}
|
||||
|
||||
interface LocalDateFormatter {
|
||||
fun shortWeekdayName(date: LocalDate): String
|
||||
fun shortMonthName(date: LocalDate): String
|
||||
}
|
||||
|
||||
private fun isLeapYear(year: Int): Boolean {
|
||||
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
|
||||
}
|
||||
|
||||
val leapOffset = arrayOf(0, 31, 60, 91, 121, 152, 182,
|
||||
213, 244, 274, 305, 335, 366)
|
||||
val nonLeapOffset = arrayOf(0, 31, 59, 90, 120, 151, 181,
|
||||
212, 243, 273, 304, 334, 365)
|
||||
|
||||
private fun daysSince2000(year: Int, month: Int, day: Int): Int {
|
||||
|
||||
var result = 365 * (year - 2000)
|
||||
result += ceil((year - 2000) / 4.0).toInt()
|
||||
result -= ceil((year - 2000) / 100.0).toInt()
|
||||
result += ceil((year - 2000) / 400.0).toInt()
|
||||
if (isLeapYear(year)) {
|
||||
result += leapOffset[month - 1]
|
||||
} else {
|
||||
result += nonLeapOffset[month - 1]
|
||||
}
|
||||
result += (day - 1)
|
||||
return result
|
||||
}
|
||||
@@ -30,7 +30,6 @@ class Backend(databaseName: String,
|
||||
databaseOpener: DatabaseOpener,
|
||||
fileOpener: FileOpener,
|
||||
val log: Log,
|
||||
val dateCalculator: LocalDateCalculator,
|
||||
val taskRunner: TaskRunner) {
|
||||
|
||||
val database: Database
|
||||
@@ -56,13 +55,12 @@ class Backend(databaseName: String,
|
||||
database = databaseOpener.open(dbFile)
|
||||
database.migrateTo(LOOP_DATABASE_VERSION, fileOpener, log)
|
||||
habitsRepository = HabitRepository(database)
|
||||
checkmarkRepository = CheckmarkRepository(database, dateCalculator)
|
||||
checkmarkRepository = CheckmarkRepository(database)
|
||||
taskRunner.runInBackground {
|
||||
habits.putAll(habitsRepository.findAll())
|
||||
for ((key, habit) in habits) {
|
||||
val checks = checkmarkRepository.findAll(key)
|
||||
checkmarks[habit] = CheckmarkList(habit.frequency,
|
||||
dateCalculator)
|
||||
checkmarks[habit] = CheckmarkList(habit.frequency)
|
||||
checkmarks[habit]?.setManualCheckmarks(checks)
|
||||
}
|
||||
}
|
||||
@@ -76,7 +74,7 @@ class Backend(databaseName: String,
|
||||
habit.id = id
|
||||
habit.position = habits.size
|
||||
habits[id] = habit
|
||||
checkmarks[habit] = CheckmarkList(habit.frequency, dateCalculator)
|
||||
checkmarks[habit] = CheckmarkList(habit.frequency)
|
||||
habitsRepository.insert(habit)
|
||||
mainScreenDataSource.requestData()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import kotlin.math.*
|
||||
class CalendarChart(var today: LocalDate,
|
||||
var color: Color,
|
||||
var theme: Theme,
|
||||
var dateCalculator: LocalDateCalculator,
|
||||
var dateFormatter: LocalDateFormatter) : Component {
|
||||
|
||||
var padding = 5.0
|
||||
@@ -47,19 +46,19 @@ class CalendarChart(var today: LocalDate,
|
||||
canvas.setFontSize(height * 0.06)
|
||||
|
||||
val nColumns = floor((width - 2 * padding) / squareSize).toInt() - 2
|
||||
val todayWeekday = dateCalculator.dayOfWeek(today)
|
||||
val todayWeekday = today.dayOfWeek
|
||||
val topLeftOffset = (nColumns - 1 + scrollPosition) * 7 + todayWeekday.index
|
||||
val topLeftDate = dateCalculator.minusDays(today, topLeftOffset)
|
||||
val topLeftDate = today.minus(topLeftOffset)
|
||||
|
||||
repeat(nColumns) { column ->
|
||||
val topOffset = topLeftOffset - 7 * column
|
||||
val topDate = dateCalculator.plusDays(topLeftDate, 7 * column)
|
||||
val topDate = topLeftDate.plus(7 * column)
|
||||
drawColumn(canvas, column, topDate, topOffset)
|
||||
}
|
||||
|
||||
canvas.setColor(theme.mediumContrastTextColor)
|
||||
repeat(7) { row ->
|
||||
val date = dateCalculator.plusDays(topLeftDate, row)
|
||||
val date = topLeftDate.plus(row)
|
||||
canvas.setTextAlign(TextAlign.LEFT)
|
||||
canvas.drawText(dateFormatter.shortWeekdayName(date),
|
||||
padding + nColumns * squareSize + padding,
|
||||
@@ -74,7 +73,7 @@ class CalendarChart(var today: LocalDate,
|
||||
drawHeader(canvas, column, topDate)
|
||||
repeat(7) { row ->
|
||||
val offset = topOffset - row
|
||||
val date = dateCalculator.plusDays(topDate, row)
|
||||
val date = topDate.plus(row)
|
||||
if (offset < 0) return
|
||||
drawSquare(canvas,
|
||||
padding + column * squareSize,
|
||||
|
||||
@@ -25,8 +25,7 @@ import org.isoron.platform.time.*
|
||||
class HabitListHeader(private val today: LocalDate,
|
||||
private val nButtons: Int,
|
||||
private val theme: Theme,
|
||||
private val fmt: LocalDateFormatter,
|
||||
private val calc: LocalDateCalculator) : Component {
|
||||
private val fmt: LocalDateFormatter) : Component {
|
||||
|
||||
override fun draw(canvas: Canvas) {
|
||||
val width = canvas.getWidth()
|
||||
@@ -44,7 +43,7 @@ class HabitListHeader(private val today: LocalDate,
|
||||
canvas.setFontSize(theme.smallTextSize)
|
||||
|
||||
repeat(nButtons) { index ->
|
||||
val date = calc.minusDays(today, nButtons - index - 1)
|
||||
val date = today.minus(nButtons - index - 1)
|
||||
val name = fmt.shortWeekdayName(date).toUpperCase()
|
||||
val number = date.day.toString()
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ import org.isoron.uhabits.models.Checkmark.Companion.CHECKED_AUTOMATIC
|
||||
import org.isoron.uhabits.models.Checkmark.Companion.CHECKED_MANUAL
|
||||
import org.isoron.uhabits.models.Checkmark.Companion.UNCHECKED
|
||||
|
||||
class CheckmarkList(private val frequency: Frequency,
|
||||
private val dateCalculator: LocalDateCalculator) {
|
||||
class CheckmarkList(private val frequency: Frequency) {
|
||||
|
||||
private val manualCheckmarks = mutableListOf<Checkmark>()
|
||||
private val automaticCheckmarks = mutableListOf<Checkmark>()
|
||||
@@ -39,8 +38,7 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
automaticCheckmarks.clear()
|
||||
manualCheckmarks.addAll(checks)
|
||||
automaticCheckmarks.addAll(computeAutomaticCheckmarks(checks,
|
||||
frequency,
|
||||
dateCalculator))
|
||||
frequency))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +54,7 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
|
||||
val result = mutableListOf<Int>()
|
||||
val newest = automaticCheckmarks.first().date
|
||||
val distToNewest = dateCalculator.distanceInDays(newest, date)
|
||||
val distToNewest = newest.distanceTo(date)
|
||||
|
||||
var fromIndex = 0
|
||||
val toIndex = automaticCheckmarks.size
|
||||
@@ -75,13 +73,12 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
* Computes the list of automatic checkmarks a list of manual ones.
|
||||
*/
|
||||
fun computeAutomaticCheckmarks(checks: List<Checkmark>,
|
||||
frequency: Frequency,
|
||||
calc: LocalDateCalculator
|
||||
frequency: Frequency
|
||||
): MutableList<Checkmark> {
|
||||
|
||||
val intervals = buildIntervals(checks, frequency, calc)
|
||||
snapIntervalsTogether(intervals, calc)
|
||||
return buildCheckmarksFromIntervals(checks, intervals, calc)
|
||||
val intervals = buildIntervals(checks, frequency)
|
||||
snapIntervalsTogether(intervals)
|
||||
return buildCheckmarksFromIntervals(checks, intervals)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,19 +89,17 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
* the interval, however, still falls within the interval. The length of
|
||||
* the intervals are also not modified.
|
||||
*/
|
||||
fun snapIntervalsTogether(intervals: MutableList<Interval>,
|
||||
calc: LocalDateCalculator) {
|
||||
fun snapIntervalsTogether(intervals: MutableList<Interval>) {
|
||||
|
||||
for (i in 1 until intervals.size) {
|
||||
val (begin, center, end) = intervals[i]
|
||||
val (_, _, prevEnd) = intervals[i - 1]
|
||||
|
||||
val gap = calc.distanceInDays(prevEnd, begin) - 1
|
||||
val endMinusGap = calc.minusDays(end, gap)
|
||||
if (gap <= 0 || endMinusGap.isOlderThan(center)) continue
|
||||
intervals[i] = Interval(calc.minusDays(begin, gap),
|
||||
val gap = prevEnd.distanceTo(begin) - 1
|
||||
if (gap <= 0 || end.minus(gap).isOlderThan(center)) continue
|
||||
intervals[i] = Interval(begin.minus(gap),
|
||||
center,
|
||||
calc.minusDays(end, gap))
|
||||
end.minus(gap))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +114,7 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
* receive unchecked checkmarks.
|
||||
*/
|
||||
fun buildCheckmarksFromIntervals(checks: List<Checkmark>,
|
||||
intervals: List<Interval>,
|
||||
calc: LocalDateCalculator
|
||||
intervals: List<Interval>
|
||||
): MutableList<Checkmark> {
|
||||
|
||||
if (checks.isEmpty()) throw IllegalArgumentException()
|
||||
@@ -137,25 +131,25 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
if (check.date.isNewerThan(newest)) newest = check.date
|
||||
}
|
||||
|
||||
val distance = calc.distanceInDays(oldest, newest)
|
||||
val distance = oldest.distanceTo(newest)
|
||||
val checkmarks = mutableListOf<Checkmark>()
|
||||
for (offset in 0..distance)
|
||||
checkmarks.add(Checkmark(calc.minusDays(newest, offset),
|
||||
checkmarks.add(Checkmark(newest.minus(offset),
|
||||
UNCHECKED))
|
||||
|
||||
for (interval in intervals) {
|
||||
val beginOffset = calc.distanceInDays(newest, interval.begin)
|
||||
val endOffset = calc.distanceInDays(newest, interval.end)
|
||||
val beginOffset = newest.distanceTo(interval.begin)
|
||||
val endOffset = newest.distanceTo(interval.end)
|
||||
|
||||
for (offset in endOffset..beginOffset) {
|
||||
checkmarks.set(offset,
|
||||
Checkmark(calc.minusDays(newest, offset),
|
||||
Checkmark(newest.minus(offset),
|
||||
CHECKED_AUTOMATIC))
|
||||
}
|
||||
}
|
||||
|
||||
for (check in checks) {
|
||||
val offset = calc.distanceInDays(newest, check.date)
|
||||
val offset = newest.distanceTo(check.date)
|
||||
checkmarks.set(offset, Checkmark(check.date, CHECKED_MANUAL))
|
||||
}
|
||||
|
||||
@@ -167,8 +161,7 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
* checkmarks.
|
||||
*/
|
||||
fun buildIntervals(checks: List<Checkmark>,
|
||||
frequency: Frequency,
|
||||
calc: LocalDateCalculator): MutableList<Interval> {
|
||||
frequency: Frequency): MutableList<Interval> {
|
||||
|
||||
val num = frequency.numerator
|
||||
val den = frequency.denominator
|
||||
@@ -178,10 +171,9 @@ class CheckmarkList(private val frequency: Frequency,
|
||||
val first = checks[i]
|
||||
val last = checks[i + num - 1]
|
||||
|
||||
val distance = calc.distanceInDays(first.date, last.date)
|
||||
if (distance >= den) continue
|
||||
if (first.date.distanceTo(last.date) >= den) continue
|
||||
|
||||
val end = calc.plusDays(first.date, den - 1)
|
||||
val end = first.date.plus(den - 1)
|
||||
intervals.add(Interval(first.date, last.date, end))
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ package org.isoron.uhabits.models
|
||||
import org.isoron.platform.io.*
|
||||
import org.isoron.platform.time.*
|
||||
|
||||
class CheckmarkRepository(db: Database,
|
||||
val dateCalculator: LocalDateCalculator) {
|
||||
class CheckmarkRepository(db: Database) {
|
||||
|
||||
private val findStatement = db.prepareStatement("select timestamp, value from Repetitions where habit = ? order by timestamp desc")
|
||||
private val insertStatement = db.prepareStatement("insert into Repetitions(habit, timestamp, value) values (?, ?, ?)")
|
||||
@@ -33,9 +32,8 @@ class CheckmarkRepository(db: Database,
|
||||
findStatement.bindInt(0, habitId)
|
||||
val result = mutableListOf<Checkmark>()
|
||||
while (findStatement.step() == StepResult.ROW) {
|
||||
val timestamp = Timestamp(findStatement.getLong(0))
|
||||
val date = Timestamp(findStatement.getLong(0)).localDate
|
||||
val value = findStatement.getInt(1)
|
||||
val date = dateCalculator.fromTimestamp(timestamp)
|
||||
result.add(Checkmark(date, value))
|
||||
}
|
||||
findStatement.reset()
|
||||
@@ -43,18 +41,18 @@ class CheckmarkRepository(db: Database,
|
||||
}
|
||||
|
||||
fun insert(habitId: Int, checkmark: Checkmark) {
|
||||
val timestamp = dateCalculator.toTimestamp(checkmark.date)
|
||||
val timestamp = checkmark.date.timestamp
|
||||
insertStatement.bindInt(0, habitId)
|
||||
insertStatement.bindLong(1, timestamp.unixTimeInMillis)
|
||||
insertStatement.bindLong(1, timestamp.millisSince1970)
|
||||
insertStatement.bindInt(2, checkmark.value)
|
||||
insertStatement.step()
|
||||
insertStatement.reset()
|
||||
}
|
||||
|
||||
fun delete(habitId: Int, date: LocalDate) {
|
||||
val timestamp = dateCalculator.toTimestamp(date)
|
||||
val timestamp = date.timestamp
|
||||
deleteStatement.bindInt(0, habitId)
|
||||
deleteStatement.bindLong(1, timestamp.unixTimeInMillis)
|
||||
deleteStatement.bindLong(1, timestamp.millisSince1970)
|
||||
deleteStatement.step()
|
||||
deleteStatement.reset()
|
||||
}
|
||||
|
||||
@@ -19,19 +19,20 @@
|
||||
|
||||
package org.isoron.platform.time
|
||||
|
||||
import java.lang.Math.*
|
||||
import java.util.*
|
||||
import java.util.Calendar.*
|
||||
|
||||
|
||||
fun LocalDate.toGregorianCalendar(): GregorianCalendar {
|
||||
val cal = GregorianCalendar(TimeZone.getTimeZone("GMT"))
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0)
|
||||
cal.set(Calendar.MINUTE, 0)
|
||||
cal.set(Calendar.SECOND, 0)
|
||||
cal.set(Calendar.MILLISECOND, 0)
|
||||
cal.set(Calendar.YEAR, this.year)
|
||||
cal.set(Calendar.MONTH, this.month - 1)
|
||||
cal.set(Calendar.DAY_OF_MONTH, this.day)
|
||||
val cal = GregorianCalendar()
|
||||
cal.timeZone = TimeZone.getTimeZone("GMT")
|
||||
cal.set(MILLISECOND, 0)
|
||||
cal.set(SECOND, 0)
|
||||
cal.set(MINUTE, 0)
|
||||
cal.set(HOUR_OF_DAY, 0)
|
||||
cal.set(YEAR, this.year)
|
||||
cal.set(MONTH, this.month - 1)
|
||||
cal.set(DAY_OF_MONTH, this.day)
|
||||
return cal
|
||||
}
|
||||
|
||||
@@ -56,35 +57,3 @@ class JavaLocalDateFormatter(private val locale: Locale) : LocalDateFormatter {
|
||||
return cal.getDisplayName(DAY_OF_WEEK, SHORT, locale);
|
||||
}
|
||||
}
|
||||
|
||||
class JavaLocalDateCalculator : LocalDateCalculator {
|
||||
override fun toTimestamp(date: LocalDate): Timestamp {
|
||||
val cal = date.toGregorianCalendar()
|
||||
return Timestamp(cal.timeInMillis)
|
||||
}
|
||||
|
||||
override fun fromTimestamp(timestamp: Timestamp): LocalDate {
|
||||
val cal = GregorianCalendar(TimeZone.getTimeZone("GMT"))
|
||||
cal.timeInMillis = timestamp.unixTimeInMillis
|
||||
return cal.toLocalDate()
|
||||
}
|
||||
|
||||
override fun dayOfWeek(date: LocalDate): DayOfWeek {
|
||||
val cal = date.toGregorianCalendar()
|
||||
return when (cal.get(DAY_OF_WEEK)) {
|
||||
Calendar.SATURDAY -> DayOfWeek.SATURDAY
|
||||
Calendar.SUNDAY -> DayOfWeek.SUNDAY
|
||||
Calendar.MONDAY -> DayOfWeek.MONDAY
|
||||
Calendar.TUESDAY -> DayOfWeek.TUESDAY
|
||||
Calendar.WEDNESDAY -> DayOfWeek.WEDNESDAY
|
||||
Calendar.THURSDAY -> DayOfWeek.THURSDAY
|
||||
else -> DayOfWeek.FRIDAY
|
||||
}
|
||||
}
|
||||
|
||||
override fun plusDays(date: LocalDate, days: Int): LocalDate {
|
||||
val cal = date.toGregorianCalendar()
|
||||
cal.add(Calendar.DAY_OF_MONTH, days)
|
||||
return cal.toLocalDate()
|
||||
}
|
||||
}
|
||||
@@ -23,10 +23,10 @@ import junit.framework.TestCase.*
|
||||
import org.isoron.platform.time.*
|
||||
import org.junit.*
|
||||
import java.util.*
|
||||
import java.util.Calendar.*
|
||||
|
||||
|
||||
class JavaDatesTest {
|
||||
private val calc = JavaLocalDateCalculator()
|
||||
private val d1 = LocalDate(2019, 3, 25)
|
||||
private val d2 = LocalDate(2019, 4, 4)
|
||||
private val d3 = LocalDate(2019, 5, 12)
|
||||
@@ -34,46 +34,46 @@ class JavaDatesTest {
|
||||
@Test
|
||||
fun plusMinusDays() {
|
||||
val today = LocalDate(2019, 3, 25)
|
||||
assertEquals(calc.minusDays(today, 28), LocalDate(2019, 2, 25))
|
||||
assertEquals(calc.plusDays(today, 7), LocalDate(2019, 4, 1))
|
||||
assertEquals(calc.plusDays(today, 42), LocalDate(2019, 5, 6))
|
||||
assertEquals(today.minus(28), LocalDate(2019, 2, 25))
|
||||
assertEquals(today.plus(7), LocalDate(2019, 4, 1))
|
||||
assertEquals(today.plus(42), LocalDate(2019, 5, 6))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shortMonthName() {
|
||||
var fmt = JavaLocalDateFormatter(Locale.US)
|
||||
assertEquals(fmt.shortWeekdayName(d1), "Mon")
|
||||
assertEquals(fmt.shortWeekdayName(d2), "Thu")
|
||||
assertEquals(fmt.shortWeekdayName(d3), "Sun")
|
||||
assertEquals(fmt.shortMonthName(d1), "Mar")
|
||||
assertEquals(fmt.shortMonthName(d2), "Apr")
|
||||
assertEquals(fmt.shortMonthName(d3), "May")
|
||||
assertEquals("Mon", fmt.shortWeekdayName(d1))
|
||||
assertEquals("Thu", fmt.shortWeekdayName(d2))
|
||||
assertEquals("Sun", fmt.shortWeekdayName(d3))
|
||||
assertEquals("Mar", fmt.shortMonthName(d1))
|
||||
assertEquals("Apr", fmt.shortMonthName(d2))
|
||||
assertEquals("May", fmt.shortMonthName(d3))
|
||||
|
||||
fmt = JavaLocalDateFormatter(Locale.JAPAN)
|
||||
assertEquals(fmt.shortWeekdayName(d1), "月")
|
||||
assertEquals(fmt.shortWeekdayName(d2), "木")
|
||||
assertEquals(fmt.shortWeekdayName(d3), "日")
|
||||
assertEquals(fmt.shortMonthName(d1), "3月")
|
||||
assertEquals(fmt.shortMonthName(d2), "4月")
|
||||
assertEquals(fmt.shortMonthName(d3), "5月")
|
||||
assertEquals("月", fmt.shortWeekdayName(d1))
|
||||
assertEquals("木", fmt.shortWeekdayName(d2))
|
||||
assertEquals("日", fmt.shortWeekdayName(d3))
|
||||
assertEquals("3月", fmt.shortMonthName(d1))
|
||||
assertEquals("4月", fmt.shortMonthName(d2))
|
||||
assertEquals("5月", fmt.shortMonthName(d3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun weekDay() {
|
||||
assertEquals(DayOfWeek.SUNDAY, calc.dayOfWeek(LocalDate(2015, 1, 25)))
|
||||
assertEquals(DayOfWeek.MONDAY, calc.dayOfWeek(LocalDate(2017, 7, 3)))
|
||||
assertEquals(DayOfWeek.SUNDAY, LocalDate(2015, 1, 25).dayOfWeek)
|
||||
assertEquals(DayOfWeek.MONDAY, LocalDate(2017, 7, 3).dayOfWeek)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun timestamps() {
|
||||
val timestamps = listOf(Timestamp(1555977600000),
|
||||
Timestamp(968716800000),
|
||||
Timestamp(0))
|
||||
Timestamp(946684800000))
|
||||
val dates = listOf(LocalDate(2019, 4, 23),
|
||||
LocalDate(2000, 9, 12),
|
||||
LocalDate(1970, 1, 1))
|
||||
assertEquals(timestamps, dates.map { d -> calc.toTimestamp(d) })
|
||||
assertEquals(dates, timestamps.map { t -> calc.fromTimestamp(t) })
|
||||
LocalDate(2000, 1, 1))
|
||||
assertEquals(timestamps, dates.map { d -> d.timestamp })
|
||||
assertEquals(dates, timestamps.map { t -> t.localDate })
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,10 +96,47 @@ class JavaDatesTest {
|
||||
val d2 = LocalDate(2019, 5, 30)
|
||||
val d3 = LocalDate(2019, 6, 5)
|
||||
|
||||
assertEquals(0, calc.distanceInDays(d1, d1))
|
||||
assertEquals(20, calc.distanceInDays(d1, d2))
|
||||
assertEquals(20, calc.distanceInDays(d2, d1))
|
||||
assertEquals(26, calc.distanceInDays(d1, d3))
|
||||
assertEquals(6, calc.distanceInDays(d2, d3))
|
||||
assertEquals(0, d1.distanceTo(d1))
|
||||
assertEquals(20, d1.distanceTo(d2))
|
||||
assertEquals(20, d2.distanceTo(d1))
|
||||
assertEquals(26, d1.distanceTo(d3))
|
||||
assertEquals(6, d2.distanceTo(d3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun gregorianCalendarConversion() {
|
||||
fun check(cal: GregorianCalendar, daysSince2000: Int) {
|
||||
val year = cal.get(YEAR)
|
||||
val month = cal.get(MONTH) + 1
|
||||
val day = cal.get(DAY_OF_MONTH)
|
||||
val weekday = cal.get(DAY_OF_WEEK)
|
||||
val date = LocalDate(year, month, day)
|
||||
val millisSince1970 = cal.timeInMillis
|
||||
val msg = "date=$year-$month-$day offset=$daysSince2000"
|
||||
|
||||
assertEquals(msg, daysSince2000, date.daysSince2000)
|
||||
assertEquals(msg, year, date.year)
|
||||
assertEquals(msg, month, date.month)
|
||||
assertEquals(msg, day, date.day)
|
||||
assertEquals(msg, weekday, date.dayOfWeek.index + 1)
|
||||
assertEquals(msg, millisSince1970, date.timestamp.millisSince1970)
|
||||
assertEquals(msg, date, date.timestamp.localDate)
|
||||
}
|
||||
|
||||
val cal = GregorianCalendar()
|
||||
cal.timeZone = TimeZone.getTimeZone("GMT")
|
||||
cal.set(MILLISECOND, 0)
|
||||
cal.set(SECOND, 0)
|
||||
cal.set(MINUTE, 0)
|
||||
cal.set(HOUR_OF_DAY, 0)
|
||||
cal.set(DAY_OF_MONTH, 1)
|
||||
cal.set(MONTH, 0)
|
||||
cal.set(YEAR, 2000)
|
||||
|
||||
// Check all dates from year 2000 until 2400
|
||||
for(offset in 0..146097) {
|
||||
check(cal, offset)
|
||||
cal.add(DAY_OF_YEAR, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,6 @@ open class BaseTest {
|
||||
|
||||
val databaseOpener = JavaDatabaseOpener(log)
|
||||
|
||||
val dateCalculator = JavaLocalDateCalculator()
|
||||
|
||||
val taskRunner = SequentialTaskRunner()
|
||||
|
||||
lateinit var db: Database
|
||||
|
||||
@@ -40,7 +40,6 @@ class BackendTest : BaseTest() {
|
||||
databaseOpener,
|
||||
fileOpener,
|
||||
log,
|
||||
dateCalculator,
|
||||
taskRunner)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ class CalendarChartTest : BaseViewTest() {
|
||||
val component = CalendarChart(LocalDate(2015, 1, 25),
|
||||
theme.color(4),
|
||||
theme,
|
||||
JavaLocalDateCalculator(),
|
||||
JavaLocalDateFormatter(Locale.US))
|
||||
component.series = listOf(1.0, // today
|
||||
0.2, 0.5, 0.7, 0.0, 0.3, 0.4, 0.6,
|
||||
|
||||
@@ -30,8 +30,7 @@ class HabitListHeaderTest : BaseViewTest() {
|
||||
val header = HabitListHeader(LocalDate(2019, 3, 25),
|
||||
5,
|
||||
theme,
|
||||
JavaLocalDateFormatter(Locale.US),
|
||||
JavaLocalDateCalculator())
|
||||
JavaLocalDateFormatter(Locale.US))
|
||||
assertRenders(1200, 96,
|
||||
"components/HabitListHeader/light.png",
|
||||
header)
|
||||
|
||||
@@ -32,7 +32,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
private val today = LocalDate(2019, 1, 30)
|
||||
|
||||
private fun day(offset: Int): LocalDate {
|
||||
return dateCalculator.minusDays(today, offset)
|
||||
return today.minus(offset)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -45,8 +45,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
CheckmarkList.Interval(day(18), day(18), day(12)),
|
||||
CheckmarkList.Interval(day(8), day(8), day(2)))
|
||||
val actual = CheckmarkList.buildIntervals(checks,
|
||||
Frequency.WEEKLY,
|
||||
dateCalculator)
|
||||
Frequency.WEEKLY)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@@ -60,8 +59,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
CheckmarkList.Interval(day(18), day(18), day(18)),
|
||||
CheckmarkList.Interval(day(8), day(8), day(8)))
|
||||
val actual = CheckmarkList.buildIntervals(checks,
|
||||
Frequency.DAILY,
|
||||
dateCalculator)
|
||||
Frequency.DAILY)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@@ -77,8 +75,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
CheckmarkList.Interval(day(22), day(18), day(16)),
|
||||
CheckmarkList.Interval(day(18), day(15), day(12)))
|
||||
val actual = CheckmarkList.buildIntervals(checks,
|
||||
Frequency.TWO_TIMES_PER_WEEK,
|
||||
dateCalculator)
|
||||
Frequency.TWO_TIMES_PER_WEEK)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@@ -94,7 +91,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
CheckmarkList.Interval(day(25), day(25), day(19)),
|
||||
CheckmarkList.Interval(day(18), day(16), day(12)),
|
||||
CheckmarkList.Interval(day(11), day(8), day(5)))
|
||||
CheckmarkList.snapIntervalsTogether(original, dateCalculator)
|
||||
CheckmarkList.snapIntervalsTogether(original)
|
||||
assertEquals(expected, original)
|
||||
}
|
||||
|
||||
@@ -118,8 +115,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
Checkmark(day(9), CHECKED_AUTOMATIC),
|
||||
Checkmark(day(10), CHECKED_MANUAL))
|
||||
val actual = CheckmarkList.buildCheckmarksFromIntervals(checks,
|
||||
intervals,
|
||||
dateCalculator)
|
||||
intervals)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@@ -134,8 +130,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
Checkmark(day(4), CHECKED_AUTOMATIC),
|
||||
Checkmark(day(5), CHECKED_AUTOMATIC))
|
||||
val actual = CheckmarkList.buildCheckmarksFromIntervals(reps,
|
||||
intervals,
|
||||
dateCalculator)
|
||||
intervals)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@@ -158,14 +153,13 @@ class CheckmarkListTest : BaseTest() {
|
||||
Checkmark(day(9), CHECKED_AUTOMATIC),
|
||||
Checkmark(day(10), CHECKED_MANUAL))
|
||||
val actual = CheckmarkList.computeAutomaticCheckmarks(checks,
|
||||
Frequency(1, 3),
|
||||
dateCalculator)
|
||||
Frequency(1, 3))
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetValuesUntil() {
|
||||
val list = CheckmarkList(Frequency(1, 2), dateCalculator)
|
||||
val list = CheckmarkList(Frequency(1, 2))
|
||||
list.setManualCheckmarks(listOf(Checkmark(day(4), CHECKED_MANUAL),
|
||||
Checkmark(day(7), CHECKED_MANUAL)))
|
||||
val expected = listOf(UNCHECKED,
|
||||
@@ -188,7 +182,7 @@ class CheckmarkListTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun testGetValuesUntil2() {
|
||||
val list = CheckmarkList(Frequency(1, 2), dateCalculator)
|
||||
val list = CheckmarkList(Frequency(1, 2))
|
||||
val expected = listOf<Int>()
|
||||
assertEquals(expected, list.getValuesUntil(day(0)))
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class CheckmarkRepositoryTest : BaseTest() {
|
||||
Checkmark(LocalDate(2019, 1, 25), 450),
|
||||
Checkmark(LocalDate(2019, 1, 20), 1000))
|
||||
|
||||
val repository = CheckmarkRepository(db, JavaLocalDateCalculator())
|
||||
val repository = CheckmarkRepository(db)
|
||||
|
||||
for (c in checkmarksA) repository.insert(habitA, c)
|
||||
for (c in checkmarksB) repository.insert(habitB, c)
|
||||
|
||||
@@ -26,7 +26,6 @@ import UIKit
|
||||
databaseOpener: IosDatabaseOpener(withLog: StandardLog()),
|
||||
fileOpener: IosFileOpener(),
|
||||
log: StandardLog(),
|
||||
dateCalculator: IosLocalDateCalculator(),
|
||||
taskRunner: SequentialTaskRunner())
|
||||
|
||||
func application(_ application: UIApplication,
|
||||
@@ -35,7 +34,7 @@ import UIKit
|
||||
window = UIWindow(frame: UIScreen.main.bounds)
|
||||
if let window = window {
|
||||
let nav = UINavigationController()
|
||||
nav.viewControllers = [ListHabitsController(withBackend: backend)]
|
||||
nav.viewControllers = [MainScreenController(withBackend: backend)]
|
||||
window.backgroundColor = UIColor.white
|
||||
window.rootViewController = nav
|
||||
window.makeKeyAndVisible()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class ListHabitsCell : UITableViewCell {
|
||||
class MainScreenCell : UITableViewCell {
|
||||
var ring: ComponentView
|
||||
var label = UILabel()
|
||||
var buttons: [ComponentView] = []
|
||||
@@ -48,7 +48,7 @@ class ListHabitsCell : UITableViewCell {
|
||||
label.heightAnchor.constraint(equalToConstant: size).isActive = true
|
||||
stack.addArrangedSubview(label)
|
||||
|
||||
for _ in 1...4 {
|
||||
for _ in 1...3 {
|
||||
let btn = ComponentView(frame: frame, component: nil)
|
||||
btn.backgroundColor = .white
|
||||
btn.widthAnchor.constraint(equalToConstant: size).isActive = true
|
||||
@@ -88,7 +88,7 @@ class ListHabitsCell : UITableViewCell {
|
||||
}
|
||||
}
|
||||
|
||||
class ListHabitsController: UITableViewController, MainScreenDataSourceListener {
|
||||
class MainScreenController: UITableViewController, MainScreenDataSourceListener {
|
||||
var backend: Backend
|
||||
var dataSource: MainScreenDataSource
|
||||
var data: MainScreenDataSource.Data?
|
||||
@@ -119,7 +119,7 @@ class ListHabitsController: UITableViewController, MainScreenDataSourceListener
|
||||
target: self,
|
||||
action: #selector(self.onCreateHabitClicked))
|
||||
]
|
||||
tableView.register(ListHabitsCell.self, forCellReuseIdentifier: "cell")
|
||||
tableView.register(MainScreenCell.self, forCellReuseIdentifier: "cell")
|
||||
tableView.backgroundColor = theme.headerBackgroundColor.uicolor
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ class ListHabitsController: UITableViewController, MainScreenDataSourceListener
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let row = indexPath.row
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ListHabitsCell
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MainScreenCell
|
||||
let color = theme.color(paletteIndex: data!.colors[row].index)
|
||||
cell.label.text = data!.names[row]
|
||||
cell.setColor(color)
|
||||
@@ -149,10 +149,9 @@ class ListHabitsController: UITableViewController, MainScreenDataSourceListener
|
||||
|
||||
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||
let component = HabitListHeader(today: LocalDate(year: 2019, month: 3, day: 24),
|
||||
nButtons: 4,
|
||||
nButtons: 3,
|
||||
theme: theme,
|
||||
fmt: IosLocalDateFormatter(),
|
||||
calc: IosLocalDateCalculator())
|
||||
fmt: IosLocalDateFormatter())
|
||||
return ComponentView(frame: CGRect(x: 0, y: 0, width: 100, height: CGFloat(theme.checkmarkButtonSize)),
|
||||
component: component)
|
||||
}
|
||||
@@ -47,7 +47,6 @@ class ShowHabitController : UITableViewController {
|
||||
let component = CalendarChart(today: LocalDate(year: 2019, month: 3, day: 15),
|
||||
color: color,
|
||||
theme: theme,
|
||||
dateCalculator: IosLocalDateCalculator(),
|
||||
dateFormatter: IosLocalDateFormatter())
|
||||
let cell = UITableViewCell()
|
||||
let view = ComponentView(frame: cell.frame, component: component)
|
||||
|
||||
@@ -54,35 +54,3 @@ class IosLocalDateFormatter : NSObject, LocalDateFormatter {
|
||||
return fmt.string(from: date.iosDate)
|
||||
}
|
||||
}
|
||||
|
||||
class IosLocalDateCalculator : NSObject, LocalDateCalculator {
|
||||
func toTimestamp(date: LocalDate) -> Timestamp {
|
||||
return Timestamp(unixTimeInMillis: Int64(date.iosDate.timeIntervalSince1970 * 1000))
|
||||
}
|
||||
|
||||
func fromTimestamp(timestamp: Timestamp) -> LocalDate {
|
||||
return Date.init(timeIntervalSince1970: Double(timestamp.unixTimeInMillis / 1000)).localDate
|
||||
}
|
||||
|
||||
let calendar = Calendar(identifier: .gregorian)
|
||||
|
||||
func dayOfWeek(date: LocalDate) -> DayOfWeek {
|
||||
let weekday = calendar.component(.weekday, from: date.iosDate)
|
||||
switch(weekday) {
|
||||
case 1: return DayOfWeek.sunday
|
||||
case 2: return DayOfWeek.monday
|
||||
case 3: return DayOfWeek.tuesday
|
||||
case 4: return DayOfWeek.wednesday
|
||||
case 5: return DayOfWeek.thursday
|
||||
case 6: return DayOfWeek.friday
|
||||
default: return DayOfWeek.saturday
|
||||
}
|
||||
}
|
||||
|
||||
func plusDays(date: LocalDate, days: Int32) -> LocalDate {
|
||||
let d2 = date.iosDate.addingTimeInterval(24.0 * 60 * 60 * Double(days))
|
||||
return LocalDate(year: Int32(calendar.component(.year, from: d2)),
|
||||
month: Int32(calendar.component(.month, from: d2)),
|
||||
day: Int32(calendar.component(.day, from: d2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
0057EC2B224C4CDB00C49288 /* icons in Resources */ = {isa = PBXBuildFile; fileRef = 0057EC2A224C4CDB00C49288 /* icons */; };
|
||||
00A5B42822009F590024E00C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A5B42722009F590024E00C /* AppDelegate.swift */; };
|
||||
00A5B42A22009F590024E00C /* ListHabitsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A5B42922009F590024E00C /* ListHabitsController.swift */; };
|
||||
00A5B42A22009F590024E00C /* MainScreenController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A5B42922009F590024E00C /* MainScreenController.swift */; };
|
||||
00A5B42F22009F5A0024E00C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 00A5B42E22009F5A0024E00C /* Assets.xcassets */; };
|
||||
00C0C6A52246537A003D8AF0 /* IosFilesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C0C6A122465365003D8AF0 /* IosFilesTest.swift */; };
|
||||
00C0C6A62246537E003D8AF0 /* IosDatabaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C0C6A222465365003D8AF0 /* IosDatabaseTest.swift */; };
|
||||
@@ -59,7 +59,7 @@
|
||||
0057EC2A224C4CDB00C49288 /* icons */ = {isa = PBXFileReference; lastKnownFileType = folder; path = icons; sourceTree = "<group>"; };
|
||||
00A5B42422009F590024E00C /* uhabits.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = uhabits.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
00A5B42722009F590024E00C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
00A5B42922009F590024E00C /* ListHabitsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListHabitsController.swift; sourceTree = "<group>"; };
|
||||
00A5B42922009F590024E00C /* MainScreenController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainScreenController.swift; sourceTree = "<group>"; };
|
||||
00A5B42E22009F5A0024E00C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
00A5B43322009F5A0024E00C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00A5B43822009F5A0024E00C /* uhabitsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = uhabitsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -107,7 +107,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00D48BD22200AC1600CC4527 /* EditHabitController.swift */,
|
||||
00A5B42922009F590024E00C /* ListHabitsController.swift */,
|
||||
00A5B42922009F590024E00C /* MainScreenController.swift */,
|
||||
00C0C6DE224A35FC003D8AF0 /* ShowHabitController.swift */,
|
||||
);
|
||||
path = Frontend;
|
||||
@@ -317,7 +317,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "cd ../core\n./gradlew linkDebugFrameworkIOS\n";
|
||||
shellScript = "cd ../core\n./gradlew linkIOS\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@@ -332,7 +332,7 @@
|
||||
00C0C6E0224A3602003D8AF0 /* ShowHabitController.swift in Sources */,
|
||||
00C0C6A8224654A2003D8AF0 /* IosDatabase.swift in Sources */,
|
||||
00C0C6DB2247E6B0003D8AF0 /* IosDates.swift in Sources */,
|
||||
00A5B42A22009F590024E00C /* ListHabitsController.swift in Sources */,
|
||||
00A5B42A22009F590024E00C /* MainScreenController.swift in Sources */,
|
||||
00A5B42822009F590024E00C /* AppDelegate.swift in Sources */,
|
||||
00D48BD32200AC1600CC4527 /* EditHabitController.swift in Sources */,
|
||||
);
|
||||
|
||||
Binary file not shown.
@@ -83,7 +83,8 @@
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00A5B42322009F590024E00C"
|
||||
@@ -91,7 +92,7 @@
|
||||
BlueprintName = "uhabits"
|
||||
ReferencedContainer = "container:uhabits.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
|
||||
Reference in New Issue
Block a user