|
|
@ -53,8 +53,8 @@ import javax.inject.Inject
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@AppScope
|
|
|
|
@AppScope
|
|
|
|
class HabitCardListCache @Inject constructor(
|
|
|
|
class HabitCardListCache @Inject constructor(
|
|
|
|
private val allHabits: HabitList,
|
|
|
|
private val habits: HabitList,
|
|
|
|
private val allHabitGroups: HabitGroupList,
|
|
|
|
private val habitGroups: HabitGroupList,
|
|
|
|
private val commandRunner: CommandRunner,
|
|
|
|
private val commandRunner: CommandRunner,
|
|
|
|
taskRunner: TaskRunner,
|
|
|
|
taskRunner: TaskRunner,
|
|
|
|
logging: Logging
|
|
|
|
logging: Logging
|
|
|
@ -68,6 +68,7 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
private val data: CacheData
|
|
|
|
private val data: CacheData
|
|
|
|
private var filteredHabits: HabitList
|
|
|
|
private var filteredHabits: HabitList
|
|
|
|
private var filteredHabitGroups: HabitGroupList
|
|
|
|
private var filteredHabitGroups: HabitGroupList
|
|
|
|
|
|
|
|
private var filteredSubHabits: MutableList<HabitList>
|
|
|
|
private val taskRunner: TaskRunner
|
|
|
|
private val taskRunner: TaskRunner
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
@ -87,12 +88,17 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun hasNoHabit(): Boolean {
|
|
|
|
fun hasNoHabit(): Boolean {
|
|
|
|
return allHabits.isEmpty
|
|
|
|
return habits.isEmpty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun hasNoHabitGroup(): Boolean {
|
|
|
|
fun hasNoHabitGroup(): Boolean {
|
|
|
|
return allHabitGroups.isEmpty
|
|
|
|
return habitGroups.isEmpty
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun hasNoSubHabits(): Boolean {
|
|
|
|
|
|
|
|
return habitGroups.all { it.habitList.isEmpty }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -103,11 +109,7 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun getHabitByPosition(position: Int): Habit? {
|
|
|
|
fun getHabitByPosition(position: Int): Habit? {
|
|
|
|
return if (position < 0 || position >= data.habits.size) {
|
|
|
|
return data.positionToHabit[position]
|
|
|
|
null
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
data.habits[position]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -118,16 +120,21 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun getHabitGroupByPosition(position: Int): HabitGroup? {
|
|
|
|
fun getHabitGroupByPosition(position: Int): HabitGroup? {
|
|
|
|
return if (position < data.habits.size || position >= data.habits.size + data.habitGroups.size) {
|
|
|
|
return data.positionToHabitGroup[position]
|
|
|
|
null
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun getUUIDByPosition(position: Int): String? {
|
|
|
|
|
|
|
|
return if (data.positionTypes[position] == STANDALONE_HABIT || data.positionTypes[position] == SUB_HABIT) {
|
|
|
|
|
|
|
|
data.positionToHabit[position]!!.uuid
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
data.habitGroups[position - data.habits.size]
|
|
|
|
data.positionToHabitGroup[position]!!.uuid
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@get:Synchronized
|
|
|
|
@get:Synchronized
|
|
|
|
val itemCount: Int
|
|
|
|
val itemCount: Int
|
|
|
|
get() = habitCount + habitGroupCount
|
|
|
|
get() = habitCount + habitGroupCount + subHabitCount
|
|
|
|
|
|
|
|
|
|
|
|
@get:Synchronized
|
|
|
|
@get:Synchronized
|
|
|
|
val habitCount: Int
|
|
|
|
val habitCount: Int
|
|
|
@ -137,15 +144,20 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
val habitGroupCount: Int
|
|
|
|
val habitGroupCount: Int
|
|
|
|
get() = data.habitGroups.size
|
|
|
|
get() = data.habitGroups.size
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@get:Synchronized
|
|
|
|
|
|
|
|
val subHabitCount: Int
|
|
|
|
|
|
|
|
get() = data.subHabits.sumOf { it.size() }
|
|
|
|
|
|
|
|
|
|
|
|
@get:Synchronized
|
|
|
|
@get:Synchronized
|
|
|
|
@set:Synchronized
|
|
|
|
@set:Synchronized
|
|
|
|
var primaryOrder: Order
|
|
|
|
var primaryOrder: Order
|
|
|
|
get() = filteredHabits.primaryOrder
|
|
|
|
get() = filteredHabits.primaryOrder
|
|
|
|
set(order) {
|
|
|
|
set(order) {
|
|
|
|
allHabits.primaryOrder = order
|
|
|
|
habits.primaryOrder = order
|
|
|
|
|
|
|
|
habitGroups.primaryOrder = order
|
|
|
|
filteredHabits.primaryOrder = order
|
|
|
|
filteredHabits.primaryOrder = order
|
|
|
|
allHabitGroups.primaryOrder = order
|
|
|
|
|
|
|
|
filteredHabitGroups.primaryOrder = order
|
|
|
|
filteredHabitGroups.primaryOrder = order
|
|
|
|
|
|
|
|
filteredSubHabits.forEach { it.primaryOrder = order }
|
|
|
|
refreshAllHabits()
|
|
|
|
refreshAllHabits()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -154,16 +166,17 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
var secondaryOrder: Order
|
|
|
|
var secondaryOrder: Order
|
|
|
|
get() = filteredHabits.secondaryOrder
|
|
|
|
get() = filteredHabits.secondaryOrder
|
|
|
|
set(order) {
|
|
|
|
set(order) {
|
|
|
|
allHabits.secondaryOrder = order
|
|
|
|
habits.secondaryOrder = order
|
|
|
|
|
|
|
|
habitGroups.secondaryOrder = order
|
|
|
|
filteredHabits.secondaryOrder = order
|
|
|
|
filteredHabits.secondaryOrder = order
|
|
|
|
allHabitGroups.secondaryOrder = order
|
|
|
|
|
|
|
|
filteredHabitGroups.secondaryOrder = order
|
|
|
|
filteredHabitGroups.secondaryOrder = order
|
|
|
|
|
|
|
|
filteredSubHabits.forEach { it.secondaryOrder = order }
|
|
|
|
refreshAllHabits()
|
|
|
|
refreshAllHabits()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun getScore(habitUUID: String): Double {
|
|
|
|
fun getScore(uuid: String): Double {
|
|
|
|
return data.scores[habitUUID]!!
|
|
|
|
return data.scores[uuid]!!
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
@ -201,42 +214,68 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun remove(uuid: String) {
|
|
|
|
fun remove(uuid: String) {
|
|
|
|
val h = data.uuidToHabit[uuid]
|
|
|
|
val type = data.positionTypes[data.uuidToPosition[uuid]!!]
|
|
|
|
if (h != null) {
|
|
|
|
if (type == STANDALONE_HABIT) {
|
|
|
|
val position = data.habits.indexOf(h)
|
|
|
|
val h = data.uuidToHabit[uuid]
|
|
|
|
data.habits.removeAt(position)
|
|
|
|
if (h != null) {
|
|
|
|
data.uuidToHabit.remove(uuid)
|
|
|
|
val position = data.habits.indexOf(h)
|
|
|
|
data.checkmarks.remove(uuid)
|
|
|
|
data.habits.removeAt(position)
|
|
|
|
data.notes.remove(uuid)
|
|
|
|
data.checkmarks.remove(uuid)
|
|
|
|
data.scores.remove(uuid)
|
|
|
|
data.notes.remove(uuid)
|
|
|
|
listener.onItemRemoved(position)
|
|
|
|
data.scores.remove(uuid)
|
|
|
|
} else {
|
|
|
|
data.decrementPositions(position + 1, data.positionTypes.size)
|
|
|
|
|
|
|
|
listener.onItemRemoved(position)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (type == SUB_HABIT) {
|
|
|
|
|
|
|
|
val h = data.uuidToHabit[uuid]
|
|
|
|
|
|
|
|
if (h != null) {
|
|
|
|
|
|
|
|
val position = data.uuidToPosition[uuid]!!
|
|
|
|
|
|
|
|
val hgrUUID = h.parentUUID
|
|
|
|
|
|
|
|
val hgr = data.uuidToHabitGroup[hgrUUID]
|
|
|
|
|
|
|
|
val hgrIdx = data.habitGroups.indexOf(hgr)
|
|
|
|
|
|
|
|
data.subHabits[hgrIdx].remove(h)
|
|
|
|
|
|
|
|
data.checkmarks.remove(uuid)
|
|
|
|
|
|
|
|
data.notes.remove(uuid)
|
|
|
|
|
|
|
|
data.scores.remove(uuid)
|
|
|
|
|
|
|
|
data.decrementPositions(position + 1, data.positionTypes.size)
|
|
|
|
|
|
|
|
listener.onItemRemoved(position)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (type == HABIT_GROUP) {
|
|
|
|
val hgr = data.uuidToHabitGroup[uuid]
|
|
|
|
val hgr = data.uuidToHabitGroup[uuid]
|
|
|
|
if (hgr != null) {
|
|
|
|
if (hgr != null) {
|
|
|
|
val position = data.habitGroups.indexOf(hgr)
|
|
|
|
val position = data.uuidToPosition[uuid]!!
|
|
|
|
data.habitGroups.removeAt(position)
|
|
|
|
val hgrIdx = data.habitGroups.indexOf(hgr)
|
|
|
|
data.uuidToHabitGroup.remove(uuid)
|
|
|
|
|
|
|
|
listener.onItemRemoved(position + data.habits.size)
|
|
|
|
for (habit in data.subHabits[hgrIdx].reversed()) {
|
|
|
|
|
|
|
|
data.checkmarks.remove(habit.uuid)
|
|
|
|
|
|
|
|
data.notes.remove(habit.uuid)
|
|
|
|
|
|
|
|
data.scores.remove(habit.uuid)
|
|
|
|
|
|
|
|
listener.onItemRemoved(data.uuidToPosition[habit.uuid]!!)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
data.subHabits.removeAt(hgrIdx)
|
|
|
|
|
|
|
|
data.habitGroups.removeAt(hgrIdx)
|
|
|
|
|
|
|
|
data.scores.remove(hgr.uuid)
|
|
|
|
|
|
|
|
data.rebuildPositions()
|
|
|
|
|
|
|
|
listener.onItemRemoved(position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun reorder(from: Int, to: Int) {
|
|
|
|
fun reorder(from: Int, to: Int) {
|
|
|
|
if (data.habits.size in (from + 1)..to || data.habits.size in (to + 1)..from) {
|
|
|
|
if (from == to) return
|
|
|
|
logger.error("reorder: from and to are in different sections")
|
|
|
|
val uuid = if (data.positionTypes[from] == STANDALONE_HABIT) {
|
|
|
|
return
|
|
|
|
data.positionToHabit[from]!!.uuid
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from < data.habits.size) {
|
|
|
|
|
|
|
|
val fromHabit = data.habits[from]
|
|
|
|
|
|
|
|
data.habits.removeAt(from)
|
|
|
|
|
|
|
|
data.habits.add(to, fromHabit)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
val fromHabitGroup = data.habitGroups[from]
|
|
|
|
data.positionToHabitGroup[from]!!.uuid
|
|
|
|
data.habitGroups.removeAt(from - data.habits.size)
|
|
|
|
}
|
|
|
|
data.habitGroups.add(to - data.habits.size, fromHabitGroup)
|
|
|
|
if (data.positionTypes[from] == STANDALONE_HABIT) {
|
|
|
|
|
|
|
|
val habit = data.positionToHabit[from]!!
|
|
|
|
|
|
|
|
data.performMove(habit, from, to)
|
|
|
|
|
|
|
|
} else if (data.positionTypes[from] == HABIT_GROUP) {
|
|
|
|
|
|
|
|
val habitGroup = data.positionToHabitGroup[from]!!
|
|
|
|
|
|
|
|
data.performMove(habitGroup, from, to)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
listener.onItemMoved(from, to)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
@ -246,8 +285,11 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
fun setFilter(matcher: HabitMatcher) {
|
|
|
|
fun setFilter(matcher: HabitMatcher) {
|
|
|
|
filteredHabits = allHabits.getFiltered(matcher)
|
|
|
|
filteredHabits = habits.getFiltered(matcher)
|
|
|
|
filteredHabitGroups = allHabitGroups.getFiltered(matcher)
|
|
|
|
filteredHabitGroups = habitGroups.getFiltered(matcher)
|
|
|
|
|
|
|
|
for (idx in filteredSubHabits.indices) {
|
|
|
|
|
|
|
|
filteredSubHabits[idx] = filteredSubHabits[idx].getFiltered(matcher)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
@ -272,6 +314,11 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
val uuidToHabitGroup: HashMap<String?, HabitGroup> = HashMap()
|
|
|
|
val uuidToHabitGroup: HashMap<String?, HabitGroup> = HashMap()
|
|
|
|
val habits: MutableList<Habit>
|
|
|
|
val habits: MutableList<Habit>
|
|
|
|
val habitGroups: MutableList<HabitGroup>
|
|
|
|
val habitGroups: MutableList<HabitGroup>
|
|
|
|
|
|
|
|
val subHabits: MutableList<HabitList>
|
|
|
|
|
|
|
|
val uuidToPosition: HashMap<String?, Int>
|
|
|
|
|
|
|
|
val positionTypes: MutableList<Int>
|
|
|
|
|
|
|
|
val positionToHabit: HashMap<Int, Habit>
|
|
|
|
|
|
|
|
val positionToHabitGroup: HashMap<Int, HabitGroup>
|
|
|
|
val checkmarks: HashMap<String?, IntArray>
|
|
|
|
val checkmarks: HashMap<String?, IntArray>
|
|
|
|
val scores: HashMap<String?, Double>
|
|
|
|
val scores: HashMap<String?, Double>
|
|
|
|
val notes: HashMap<String?, Array<String>>
|
|
|
|
val notes: HashMap<String?, Array<String>>
|
|
|
@ -327,14 +374,186 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
for (h in filteredHabits) {
|
|
|
|
for (h in filteredHabits) {
|
|
|
|
if (h.uuid == null) continue
|
|
|
|
if (h.uuid == null) continue
|
|
|
|
habits.add(h)
|
|
|
|
habits.add(h)
|
|
|
|
uuidToHabit[h.uuid] = h
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (hgr in filteredHabitGroups) {
|
|
|
|
for (hgr in filteredHabitGroups) {
|
|
|
|
if (hgr.uuid == null) continue
|
|
|
|
if (hgr.uuid == null) continue
|
|
|
|
habitGroups.add(hgr)
|
|
|
|
habitGroups.add(hgr)
|
|
|
|
|
|
|
|
val habitList = hgr.habitList
|
|
|
|
|
|
|
|
subHabits.add(habitList)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (h in habitList) {
|
|
|
|
|
|
|
|
if (h.uuid == null) continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun rebuildPositions() {
|
|
|
|
|
|
|
|
positionToHabit.clear()
|
|
|
|
|
|
|
|
positionToHabitGroup.clear()
|
|
|
|
|
|
|
|
uuidToPosition.clear()
|
|
|
|
|
|
|
|
positionTypes.clear()
|
|
|
|
|
|
|
|
var position = 0
|
|
|
|
|
|
|
|
for (h in habits) {
|
|
|
|
|
|
|
|
uuidToHabit[h.uuid] = h
|
|
|
|
|
|
|
|
uuidToPosition[h.uuid] = position
|
|
|
|
|
|
|
|
positionToHabit[position] = h
|
|
|
|
|
|
|
|
positionTypes.add(STANDALONE_HABIT)
|
|
|
|
|
|
|
|
position++
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ((idx, hgr) in habitGroups.withIndex()) {
|
|
|
|
uuidToHabitGroup[hgr.uuid] = hgr
|
|
|
|
uuidToHabitGroup[hgr.uuid] = hgr
|
|
|
|
|
|
|
|
uuidToPosition[hgr.uuid] = position
|
|
|
|
|
|
|
|
positionToHabitGroup[position] = hgr
|
|
|
|
|
|
|
|
positionTypes.add(HABIT_GROUP)
|
|
|
|
|
|
|
|
val habitList = subHabits[idx]
|
|
|
|
|
|
|
|
position++
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (h in habitList) {
|
|
|
|
|
|
|
|
uuidToHabit[h.uuid] = h
|
|
|
|
|
|
|
|
uuidToPosition[h.uuid] = position
|
|
|
|
|
|
|
|
positionToHabit[position] = h
|
|
|
|
|
|
|
|
positionTypes.add(SUB_HABIT)
|
|
|
|
|
|
|
|
position++
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun isValidInsert(habit: Habit, position: Int): Boolean {
|
|
|
|
|
|
|
|
if (habit.parentUUID == null) {
|
|
|
|
|
|
|
|
return position <= habits.size
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
val parent = uuidToHabitGroup[habit.parentUUID]
|
|
|
|
|
|
|
|
if (parent == null) {
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val parentPosition = uuidToPosition[habit.parentUUID]!!
|
|
|
|
|
|
|
|
val parentIndex = habitGroups.indexOf(parent)
|
|
|
|
|
|
|
|
val nextGroup = habitGroups.getOrNull(parentIndex + 1)
|
|
|
|
|
|
|
|
val nextGroupPosition = uuidToPosition[nextGroup?.uuid]
|
|
|
|
|
|
|
|
return (position > parentPosition && position <= positionTypes.size) && (nextGroupPosition == null || position <= nextGroupPosition)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun isValidInsert(habitGroup: HabitGroup, position: Int): Boolean {
|
|
|
|
|
|
|
|
return (position == positionTypes.size) || (positionTypes[position] == HABIT_GROUP)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun incrementPositions(from: Int, to: Int) {
|
|
|
|
|
|
|
|
for (pos in positionToHabit.keys.sortedByDescending { it }) {
|
|
|
|
|
|
|
|
if (pos in from..to) {
|
|
|
|
|
|
|
|
positionToHabit[pos + 1] = positionToHabit[pos]!!
|
|
|
|
|
|
|
|
positionToHabit.remove(pos)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pos in positionToHabitGroup.keys.sortedByDescending { it }) {
|
|
|
|
|
|
|
|
if (pos in from..to) {
|
|
|
|
|
|
|
|
positionToHabitGroup[pos + 1] = positionToHabitGroup[pos]!!
|
|
|
|
|
|
|
|
positionToHabitGroup.remove(pos)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for ((key, pos) in uuidToPosition.entries) {
|
|
|
|
|
|
|
|
if (pos in from..to) {
|
|
|
|
|
|
|
|
uuidToPosition[key] = pos + 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun decrementPositions(fromPosition: Int, toPosition: Int) {
|
|
|
|
|
|
|
|
positionTypes.removeAt(fromPosition)
|
|
|
|
|
|
|
|
for (pos in positionToHabit.keys.sortedBy { it }) {
|
|
|
|
|
|
|
|
if (pos in fromPosition..toPosition) {
|
|
|
|
|
|
|
|
positionToHabit[pos - 1] = positionToHabit[pos]!!
|
|
|
|
|
|
|
|
positionToHabit.remove(pos)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pos in positionToHabitGroup.keys.sortedBy { it }) {
|
|
|
|
|
|
|
|
if (pos in fromPosition..toPosition) {
|
|
|
|
|
|
|
|
positionToHabitGroup[pos - 1] = positionToHabitGroup[pos]!!
|
|
|
|
|
|
|
|
positionToHabitGroup.remove(pos)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for ((key, pos) in uuidToPosition.entries) {
|
|
|
|
|
|
|
|
if (pos in fromPosition..toPosition) {
|
|
|
|
|
|
|
|
uuidToPosition[key] = pos - 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun performMove(
|
|
|
|
|
|
|
|
habit: Habit,
|
|
|
|
|
|
|
|
fromPosition: Int,
|
|
|
|
|
|
|
|
toPosition: Int
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
val type = positionTypes[fromPosition]
|
|
|
|
|
|
|
|
if (type == HABIT_GROUP) return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Workaround for https://github.com/iSoron/uhabits/issues/968
|
|
|
|
|
|
|
|
val checkedToPosition = if (toPosition > positionTypes.size) {
|
|
|
|
|
|
|
|
logger.error("performMove: $toPosition for habit is strictly higher than ${habits.size}")
|
|
|
|
|
|
|
|
positionTypes.size
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
toPosition
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val verifyPosition = if (fromPosition > checkedToPosition) checkedToPosition else checkedToPosition + 1
|
|
|
|
|
|
|
|
if (!isValidInsert(habit, verifyPosition)) return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (type == STANDALONE_HABIT) {
|
|
|
|
|
|
|
|
habits.removeAt(fromPosition)
|
|
|
|
|
|
|
|
if (fromPosition < checkedToPosition) {
|
|
|
|
|
|
|
|
decrementPositions(fromPosition + 1, checkedToPosition)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
incrementPositions(toPosition, fromPosition - 1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
habits.add(checkedToPosition, habit)
|
|
|
|
|
|
|
|
positionTypes.add(checkedToPosition, STANDALONE_HABIT)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
val hgr = uuidToHabitGroup[habit.parentUUID]
|
|
|
|
|
|
|
|
val hgrIdx = habitGroups.indexOf(hgr)
|
|
|
|
|
|
|
|
val h = positionToHabit[fromPosition]!!
|
|
|
|
|
|
|
|
subHabits[hgrIdx].remove(h)
|
|
|
|
|
|
|
|
if (fromPosition < checkedToPosition) {
|
|
|
|
|
|
|
|
decrementPositions(fromPosition + 1, checkedToPosition)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
incrementPositions(toPosition, fromPosition - 1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
subHabits[hgrIdx].add(checkedToPosition - uuidToPosition[hgr!!.uuid]!! - 1, habit)
|
|
|
|
|
|
|
|
positionTypes.add(checkedToPosition, SUB_HABIT)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
positionToHabit[checkedToPosition] = habit
|
|
|
|
|
|
|
|
uuidToPosition[habit.uuid] = checkedToPosition
|
|
|
|
|
|
|
|
listener.onItemMoved(fromPosition, checkedToPosition)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
fun performMove(
|
|
|
|
|
|
|
|
habitGroup: HabitGroup,
|
|
|
|
|
|
|
|
fromPosition: Int,
|
|
|
|
|
|
|
|
toPosition: Int
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
if (positionTypes[fromPosition] != HABIT_GROUP) return
|
|
|
|
|
|
|
|
if (!isValidInsert(habitGroup, toPosition)) return
|
|
|
|
|
|
|
|
val fromIdx = habitGroups.indexOf(habitGroup)
|
|
|
|
|
|
|
|
val habitList = subHabits[fromIdx]
|
|
|
|
|
|
|
|
val toIdx = habitGroups.indexOf(positionToHabitGroup[toPosition]) - (if (fromPosition < toPosition) 1 else 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
habitGroups.removeAt(fromIdx)
|
|
|
|
|
|
|
|
subHabits.removeAt(fromIdx)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
habitGroups.add(toIdx, habitGroup)
|
|
|
|
|
|
|
|
subHabits.add(toIdx, habitList)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rebuildPositions()
|
|
|
|
|
|
|
|
listener.onItemMoved(fromPosition, toPosition)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -343,6 +562,11 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
init {
|
|
|
|
init {
|
|
|
|
habits = LinkedList()
|
|
|
|
habits = LinkedList()
|
|
|
|
habitGroups = LinkedList()
|
|
|
|
habitGroups = LinkedList()
|
|
|
|
|
|
|
|
subHabits = LinkedList()
|
|
|
|
|
|
|
|
positionTypes = LinkedList()
|
|
|
|
|
|
|
|
uuidToPosition = HashMap()
|
|
|
|
|
|
|
|
positionToHabit = HashMap()
|
|
|
|
|
|
|
|
positionToHabitGroup = HashMap()
|
|
|
|
checkmarks = HashMap()
|
|
|
|
checkmarks = HashMap()
|
|
|
|
scores = HashMap()
|
|
|
|
scores = HashMap()
|
|
|
|
notes = HashMap()
|
|
|
|
notes = HashMap()
|
|
|
@ -374,35 +598,35 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
override fun doInBackground() {
|
|
|
|
override fun doInBackground() {
|
|
|
|
newData.fetchHabits()
|
|
|
|
newData.fetchHabits()
|
|
|
|
|
|
|
|
newData.rebuildPositions()
|
|
|
|
newData.copyScoresFrom(data)
|
|
|
|
newData.copyScoresFrom(data)
|
|
|
|
newData.copyCheckmarksFrom(data)
|
|
|
|
newData.copyCheckmarksFrom(data)
|
|
|
|
newData.copyNoteIndicatorsFrom(data)
|
|
|
|
newData.copyNoteIndicatorsFrom(data)
|
|
|
|
val today = getTodayWithOffset()
|
|
|
|
val today = getTodayWithOffset()
|
|
|
|
val dateFrom = today.minus(checkmarkCount - 1)
|
|
|
|
val dateFrom = today.minus(checkmarkCount - 1)
|
|
|
|
if (runner != null) runner!!.publishProgress(this, -1)
|
|
|
|
if (runner != null) runner!!.publishProgress(this, -1)
|
|
|
|
for (position in newData.habits.indices) {
|
|
|
|
for ((position, type) in newData.positionTypes.withIndex()) {
|
|
|
|
if (isCancelled) return
|
|
|
|
if (isCancelled) return
|
|
|
|
val habit = newData.habits[position]
|
|
|
|
if (type == STANDALONE_HABIT || type == SUB_HABIT) {
|
|
|
|
if (targetUUID != null && targetUUID != habit.uuid) continue
|
|
|
|
val habit = newData.positionToHabit[position]!!
|
|
|
|
newData.scores[habit.uuid] = habit.scores[today].value
|
|
|
|
if (targetUUID != null && targetUUID != habit.uuid) continue
|
|
|
|
val list: MutableList<Int> = ArrayList()
|
|
|
|
newData.scores[habit.uuid] = habit.scores[today].value
|
|
|
|
val notes: MutableList<String> = ArrayList()
|
|
|
|
val list: MutableList<Int> = ArrayList()
|
|
|
|
for ((_, value, note) in habit.computedEntries.getByInterval(dateFrom, today)) {
|
|
|
|
val notes: MutableList<String> = ArrayList()
|
|
|
|
list.add(value)
|
|
|
|
for ((_, value, note) in habit.computedEntries.getByInterval(dateFrom, today)) {
|
|
|
|
notes.add(note)
|
|
|
|
list.add(value)
|
|
|
|
|
|
|
|
notes.add(note)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val entries = list.toTypedArray()
|
|
|
|
|
|
|
|
newData.checkmarks[habit.uuid] = ArrayUtils.toPrimitive(entries)
|
|
|
|
|
|
|
|
newData.notes[habit.uuid] = notes.toTypedArray()
|
|
|
|
|
|
|
|
runner!!.publishProgress(this, position)
|
|
|
|
|
|
|
|
} else if (type == HABIT_GROUP) {
|
|
|
|
|
|
|
|
val habitGroup = newData.positionToHabitGroup[position]!!
|
|
|
|
|
|
|
|
if (targetUUID != null && targetUUID != habitGroup.uuid) continue
|
|
|
|
|
|
|
|
newData.scores[habitGroup.uuid] = habitGroup.scores[today].value
|
|
|
|
|
|
|
|
runner!!.publishProgress(this, position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
val entries = list.toTypedArray()
|
|
|
|
|
|
|
|
newData.checkmarks[habit.uuid] = ArrayUtils.toPrimitive(entries)
|
|
|
|
|
|
|
|
newData.notes[habit.uuid] = notes.toTypedArray()
|
|
|
|
|
|
|
|
runner!!.publishProgress(this, position)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (position in newData.habitGroups.indices) {
|
|
|
|
|
|
|
|
if (isCancelled) return
|
|
|
|
|
|
|
|
val hgr = newData.habitGroups[position]
|
|
|
|
|
|
|
|
if (targetUUID != null && targetUUID != hgr.uuid) continue
|
|
|
|
|
|
|
|
newData.scores[hgr.uuid] = hgr.scores[today].value
|
|
|
|
|
|
|
|
runner!!.publishProgress(this, position + newData.habits.size)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -424,8 +648,21 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
private fun performInsert(habit: Habit, position: Int) {
|
|
|
|
private fun performInsert(habit: Habit, position: Int) {
|
|
|
|
|
|
|
|
if (!data.isValidInsert(habit, position)) return
|
|
|
|
val uuid = habit.uuid
|
|
|
|
val uuid = habit.uuid
|
|
|
|
data.habits.add(position, habit)
|
|
|
|
if (habit.parentUUID == null) {
|
|
|
|
|
|
|
|
data.habits.add(position, habit)
|
|
|
|
|
|
|
|
data.positionTypes.add(position, STANDALONE_HABIT)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// val parent = data.uuidToHabitGroup[habit.parentUUID]
|
|
|
|
|
|
|
|
// val parentIdx = data.habitGroups.indexOf(parent)
|
|
|
|
|
|
|
|
// val parentPosition = data.uuidToPosition[habit.parentUUID]!!
|
|
|
|
|
|
|
|
// data.subHabits[parentIdx].add(position - parentPosition - 1, habit)
|
|
|
|
|
|
|
|
data.positionTypes.add(position, SUB_HABIT)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
data.incrementPositions(position, data.positionTypes.size - 1)
|
|
|
|
|
|
|
|
data.positionToHabit[position] = habit
|
|
|
|
|
|
|
|
data.uuidToPosition[uuid] = position
|
|
|
|
data.uuidToHabit[uuid] = habit
|
|
|
|
data.uuidToHabit[uuid] = habit
|
|
|
|
data.scores[uuid] = newData.scores[uuid]!!
|
|
|
|
data.scores[uuid] = newData.scores[uuid]!!
|
|
|
|
data.checkmarks[uuid] = newData.checkmarks[uuid]!!
|
|
|
|
data.checkmarks[uuid] = newData.checkmarks[uuid]!!
|
|
|
@ -435,62 +672,23 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
private fun performInsert(habitGroup: HabitGroup, position: Int) {
|
|
|
|
private fun performInsert(habitGroup: HabitGroup, position: Int) {
|
|
|
|
val newPosition = if (position < data.habits.size) {
|
|
|
|
if (!data.isValidInsert(habitGroup, position)) return
|
|
|
|
data.habits.size
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
position
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val uuid = habitGroup.uuid
|
|
|
|
val uuid = habitGroup.uuid
|
|
|
|
data.habitGroups.add(newPosition - data.habits.size, habitGroup)
|
|
|
|
val prevIdx = newData.habitGroups.indexOf(habitGroup)
|
|
|
|
data.uuidToHabitGroup[uuid] = habitGroup
|
|
|
|
val habitList = newData.subHabits[prevIdx]
|
|
|
|
data.scores[uuid] = newData.scores[uuid]!!
|
|
|
|
var idx = data.habitGroups.indexOf(data.positionToHabitGroup[position])
|
|
|
|
listener.onItemInserted(newPosition)
|
|
|
|
if (idx < 0) idx = data.habitGroups.size
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
|
|
|
|
private fun performMove(
|
|
|
|
|
|
|
|
habit: Habit,
|
|
|
|
|
|
|
|
fromPosition: Int,
|
|
|
|
|
|
|
|
toPosition: Int
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
data.habits.removeAt(fromPosition)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Workaround for https://github.com/iSoron/uhabits/issues/968
|
|
|
|
data.habitGroups.add(idx, habitGroup)
|
|
|
|
val checkedToPosition = if (toPosition > data.habits.size) {
|
|
|
|
data.subHabits.add(prevIdx, habitList)
|
|
|
|
logger.error("performMove: $toPosition for habit is strictly higher than ${data.habits.size}")
|
|
|
|
data.scores[uuid] = newData.scores[uuid]!!
|
|
|
|
data.habits.size
|
|
|
|
for (h in habitList) {
|
|
|
|
} else {
|
|
|
|
data.scores[h.uuid] = newData.scores[h.uuid]!!
|
|
|
|
toPosition
|
|
|
|
data.checkmarks[h.uuid] = newData.checkmarks[h.uuid]!!
|
|
|
|
}
|
|
|
|
data.notes[h.uuid] = newData.notes[h.uuid]!!
|
|
|
|
|
|
|
|
|
|
|
|
data.habits.add(checkedToPosition, habit)
|
|
|
|
|
|
|
|
listener.onItemMoved(fromPosition, checkedToPosition)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun performMove(
|
|
|
|
|
|
|
|
habitGroup: HabitGroup,
|
|
|
|
|
|
|
|
fromPosition: Int,
|
|
|
|
|
|
|
|
toPosition: Int
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
if (fromPosition < data.habits.size || fromPosition > data.habits.size + data.habitGroups.size) {
|
|
|
|
|
|
|
|
logger.error("performMove: $fromPosition for habit group is out of bounds")
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
data.habitGroups.removeAt(fromPosition - data.habits.size)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Workaround for https://github.com/iSoron/uhabits/issues/968
|
|
|
|
|
|
|
|
val checkedToPosition = if (toPosition < data.habits.size) {
|
|
|
|
|
|
|
|
logger.error("performMove: $toPosition for habit group is strictly lower than ${data.habits.size}")
|
|
|
|
|
|
|
|
data.habits.size
|
|
|
|
|
|
|
|
} else if (toPosition > data.habits.size + data.habitGroups.size) {
|
|
|
|
|
|
|
|
logger.error("performMove: $toPosition for habit group is strictly higher than ${data.habits.size + data.habitGroups.size}")
|
|
|
|
|
|
|
|
data.habits.size + data.habitGroups.size
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
toPosition
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data.rebuildPositions()
|
|
|
|
data.habitGroups.add(checkedToPosition - data.habits.size, habitGroup)
|
|
|
|
listener.onItemInserted(position)
|
|
|
|
listener.onItemMoved(fromPosition, checkedToPosition)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
@ -500,7 +698,7 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
val newScore = newData.scores[uuid]!!
|
|
|
|
val newScore = newData.scores[uuid]!!
|
|
|
|
if (oldScore != newScore) unchanged = false
|
|
|
|
if (oldScore != newScore) unchanged = false
|
|
|
|
|
|
|
|
|
|
|
|
if (position < data.habits.size) {
|
|
|
|
if (data.positionTypes[position] != HABIT_GROUP) {
|
|
|
|
val oldCheckmarks = data.checkmarks[uuid]
|
|
|
|
val oldCheckmarks = data.checkmarks[uuid]
|
|
|
|
val newCheckmarks = newData.checkmarks[uuid]!!
|
|
|
|
val newCheckmarks = newData.checkmarks[uuid]!!
|
|
|
|
val oldNoteIndicators = data.notes[uuid]
|
|
|
|
val oldNoteIndicators = data.notes[uuid]
|
|
|
@ -519,38 +717,45 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
private fun processPosition(currentPosition: Int) {
|
|
|
|
private fun processPosition(currentPosition: Int) {
|
|
|
|
if (currentPosition < newData.habits.size) {
|
|
|
|
val type = newData.positionTypes[currentPosition]
|
|
|
|
val habit = newData.habits[currentPosition]
|
|
|
|
|
|
|
|
val uuid = habit.uuid
|
|
|
|
if (type == STANDALONE_HABIT || type == SUB_HABIT) {
|
|
|
|
val prevPosition = data.habits.indexOf(habit)
|
|
|
|
val habit = newData.positionToHabit[currentPosition]!!
|
|
|
|
|
|
|
|
val uuid = habit.uuid ?: throw NullPointerException()
|
|
|
|
|
|
|
|
val prevPosition = data.uuidToPosition[uuid] ?: -1
|
|
|
|
|
|
|
|
val newPosition = if (type == STANDALONE_HABIT) {
|
|
|
|
|
|
|
|
currentPosition
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
val hgr = data.uuidToHabitGroup[habit.parentUUID]
|
|
|
|
|
|
|
|
val hgrIdx = data.habitGroups.indexOf(hgr)
|
|
|
|
|
|
|
|
newData.subHabits[hgrIdx].indexOf(habit) + data.uuidToPosition[hgr!!.uuid]!! + 1
|
|
|
|
|
|
|
|
}
|
|
|
|
if (prevPosition < 0) {
|
|
|
|
if (prevPosition < 0) {
|
|
|
|
performInsert(habit, currentPosition)
|
|
|
|
performInsert(habit, newPosition)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (prevPosition != currentPosition) {
|
|
|
|
if (prevPosition != newPosition) {
|
|
|
|
performMove(
|
|
|
|
data.performMove(
|
|
|
|
habit,
|
|
|
|
habit,
|
|
|
|
prevPosition,
|
|
|
|
prevPosition,
|
|
|
|
currentPosition
|
|
|
|
newPosition
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uuid == null) throw NullPointerException()
|
|
|
|
|
|
|
|
performUpdate(uuid, currentPosition)
|
|
|
|
performUpdate(uuid, currentPosition)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else if (type == HABIT_GROUP) {
|
|
|
|
val habitGroup = newData.habitGroups[currentPosition - data.habits.size]
|
|
|
|
val habitGroup = newData.positionToHabitGroup[currentPosition]!!
|
|
|
|
val uuid = habitGroup.uuid
|
|
|
|
val uuid = habitGroup.uuid ?: throw NullPointerException()
|
|
|
|
val prevPosition = data.habitGroups.indexOf(habitGroup) + data.habits.size
|
|
|
|
val prevPosition = data.uuidToPosition[uuid] ?: -1
|
|
|
|
if (prevPosition < data.habits.size) {
|
|
|
|
if (prevPosition < 0) {
|
|
|
|
performInsert(habitGroup, currentPosition)
|
|
|
|
performInsert(habitGroup, currentPosition)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (prevPosition != currentPosition) {
|
|
|
|
if (prevPosition != currentPosition) {
|
|
|
|
performMove(
|
|
|
|
data.performMove(
|
|
|
|
habitGroup,
|
|
|
|
habitGroup,
|
|
|
|
prevPosition,
|
|
|
|
prevPosition,
|
|
|
|
currentPosition
|
|
|
|
currentPosition
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uuid == null) throw NullPointerException()
|
|
|
|
|
|
|
|
performUpdate(uuid, currentPosition)
|
|
|
|
performUpdate(uuid, currentPosition)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -558,27 +763,29 @@ class HabitCardListCache @Inject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
@Synchronized
|
|
|
|
private fun processRemovedHabits() {
|
|
|
|
private fun processRemovedHabits() {
|
|
|
|
val before: Set<String?> = data.uuidToHabit.keys
|
|
|
|
val before: Set<String?> = (data.uuidToHabit.keys).union(data.uuidToHabitGroup.keys)
|
|
|
|
val after: Set<String?> = newData.uuidToHabit.keys
|
|
|
|
val after: Set<String?> = (newData.uuidToHabit.keys).union(newData.uuidToHabitGroup.keys)
|
|
|
|
val removed: MutableSet<String?> = TreeSet(before)
|
|
|
|
val removed: MutableSet<String?> = TreeSet(before)
|
|
|
|
removed.removeAll(after)
|
|
|
|
removed.removeAll(after)
|
|
|
|
for (uuid in removed) remove(uuid!!)
|
|
|
|
for (uuid in removed.sortedBy { uuid -> data.uuidToPosition[uuid] }) remove(uuid!!)
|
|
|
|
processRemovedHabitGroups()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Synchronized
|
|
|
|
companion object {
|
|
|
|
private fun processRemovedHabitGroups() {
|
|
|
|
const val STANDALONE_HABIT = 0
|
|
|
|
val before: Set<String?> = data.uuidToHabitGroup.keys
|
|
|
|
const val HABIT_GROUP = 1
|
|
|
|
val after: Set<String?> = newData.uuidToHabitGroup.keys
|
|
|
|
const val SUB_HABIT = 2
|
|
|
|
val removed: MutableSet<String?> = TreeSet(before)
|
|
|
|
|
|
|
|
removed.removeAll(after)
|
|
|
|
|
|
|
|
for (uuid in removed) remove(uuid!!)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
init {
|
|
|
|
init {
|
|
|
|
filteredHabits = allHabits
|
|
|
|
filteredHabits = habits
|
|
|
|
filteredHabitGroups = allHabitGroups
|
|
|
|
filteredHabitGroups = habitGroups
|
|
|
|
|
|
|
|
filteredSubHabits = LinkedList()
|
|
|
|
|
|
|
|
for (hgr in habitGroups) {
|
|
|
|
|
|
|
|
val subList = hgr.habitList
|
|
|
|
|
|
|
|
filteredSubHabits.add(subList)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.taskRunner = taskRunner
|
|
|
|
this.taskRunner = taskRunner
|
|
|
|
listener = object : Listener {}
|
|
|
|
listener = object : Listener {}
|
|
|
|
data = CacheData()
|
|
|
|
data = CacheData()
|
|
|
|