Skip to content

Commit

Permalink
Prototype for #1481
Browse files Browse the repository at this point in the history
Extract logic for calculating neighbouring periods
  • Loading branch information
mtotschnig committed Apr 25, 2024
1 parent 8fac94a commit d3d8364
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import org.totschnig.myexpenses.provider.TransactionProvider
import org.totschnig.myexpenses.provider.filter.FilterPersistence
import org.totschnig.myexpenses.provider.getEnumOrNull
import org.totschnig.myexpenses.provider.getLocalDate
import org.totschnig.myexpenses.util.GroupingInfo
import org.totschnig.myexpenses.util.GroupingNavigator
import org.totschnig.myexpenses.viewmodel.BudgetViewModel
import org.totschnig.myexpenses.viewmodel.BudgetViewModel2.Companion.aggregateNeutralPrefKey
import org.totschnig.myexpenses.viewmodel.DistributionViewModelBase
import org.totschnig.myexpenses.viewmodel.data.Budget
import org.totschnig.myexpenses.viewmodel.data.BudgetAllocation
import org.totschnig.myexpenses.viewmodel.data.BudgetProgress
Expand Down Expand Up @@ -53,7 +54,7 @@ fun budgetAllocationUri(budgetId: Long, categoryId: Long) = ContentUris.withAppe
fun budgetAllocationQueryUri(
budgetId: Long,
categoryId: Long,
groupingInfo: DistributionViewModelBase.GroupingInfo
groupingInfo: GroupingInfo
): Uri = budgetAllocationQueryUri(
budgetId,
categoryId,
Expand Down Expand Up @@ -139,24 +140,16 @@ suspend fun Repository.loadBudgetProgress(budgetId: Long): BudgetProgress? = con
end = cursor.getLocalDate(KEY_END)
),
description = budget.durationPrettyPrint()
) else with(DateInfo.load(contentResolver)) {
) else {
val dateInfo = DateInfo.load(contentResolver)
val info = GroupingNavigator.current(grouping, dateInfo)
val weekStartDay = prefHandler.weekStartAsDayOfWeek
val today = LocalDate.ofYearDay(year, day)
val today = LocalDate.ofYearDay(dateInfo.year, dateInfo.day)
val weekStart = today.with(TemporalAdjusters.previousOrSame(weekStartDay))
val year = when (grouping) {
Grouping.WEEK -> yearOfWeekStart
Grouping.MONTH -> yearOfMonthStart
else -> year
}
val second = when (grouping) {
Grouping.DAY -> day
Grouping.WEEK -> week
Grouping.MONTH -> month
else -> 0
}

BudgetPeriod(
year = year,
second = second,
year = info.year,
second = info.second,
duration = when (grouping) {
Grouping.DAY -> {
today.dayOfWeek
Expand All @@ -174,26 +167,26 @@ suspend fun Repository.loadBudgetProgress(budgetId: Long): BudgetProgress? = con

Grouping.MONTH -> with(
Grouping.getMonthRange(
yearOfMonthStart,
month,
info.year,
info.second,
prefHandler.monthStart
)
) {
BudgetDuration(this.first, this.second)
}

Grouping.YEAR -> BudgetDuration(
LocalDate.ofYearDay(year, 1),
LocalDate.of(year, 12, 31)
LocalDate.ofYearDay(info.year, 1),
LocalDate.of(info.year, 12, 31)
)

else -> throw IllegalStateException()
},
description = grouping.getDisplayTitle(
context,
year,
second,
this,
info.year,
info.second,
dateInfo,
weekStart,
true
)
Expand Down Expand Up @@ -224,7 +217,7 @@ suspend fun Repository.loadBudgetProgress(budgetId: Long): BudgetProgress? = con
BudgetProgress(
budget.title,
budget.currencyUnit,
groupingInfo.description,
groupingInfo,
allocated,
-spent,
totalDays,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.totschnig.myexpenses.util

import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.totschnig.myexpenses.model.Grouping
import org.totschnig.myexpenses.model.Grouping.DAY
import org.totschnig.myexpenses.model.Grouping.MONTH
import org.totschnig.myexpenses.model.Grouping.NONE
import org.totschnig.myexpenses.model.Grouping.WEEK
import org.totschnig.myexpenses.viewmodel.data.DateInfo
import org.totschnig.myexpenses.viewmodel.data.DateInfoExtra

@Parcelize
data class GroupingInfo(
val grouping: Grouping = NONE,
val year: Int = -1,
val second: Int = -1
) : Parcelable

object GroupingNavigator {
fun current(grouping: Grouping, dateInfo: DateInfo) = with(dateInfo) {
GroupingInfo(
grouping = grouping,
year = when (grouping) {
WEEK -> yearOfWeekStart
MONTH -> yearOfMonthStart
else -> year
},
second = when (grouping) {
DAY -> day
WEEK -> week
MONTH -> month
else -> 0
}
)
}

fun nextYear(groupingInfo: GroupingInfo) = groupingInfo.copy(year = groupingInfo.year + 1)

fun next(groupingInfo: GroupingInfo, dateInfo: DateInfoExtra): GroupingInfo {
val nextSecond = groupingInfo.second + 1
val overflow = nextSecond > dateInfo.maxValue
return groupingInfo.copy(
year = if (overflow) groupingInfo.year + 1 else groupingInfo.year,
second = if (overflow) groupingInfo.grouping.minValue else nextSecond
)
}

fun previousYear(groupingInfo: GroupingInfo) = groupingInfo.copy(year = groupingInfo.year - 1)

fun previous(groupingInfo: GroupingInfo, dateInfo: DateInfoExtra): GroupingInfo {
val nextSecond = groupingInfo.second - 1
val underflow = nextSecond < groupingInfo.grouping.minValue
return groupingInfo.copy(
year = if (underflow) groupingInfo.year - 1 else groupingInfo.year,
second = if (underflow) dateInfo.maxValue else nextSecond
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import org.totschnig.myexpenses.provider.DatabaseConstants
import org.totschnig.myexpenses.provider.DatabaseConstants.KEY_ROWID
import org.totschnig.myexpenses.provider.TransactionProvider
import org.totschnig.myexpenses.provider.filter.FilterPersistence
import org.totschnig.myexpenses.util.GroupingInfo
import org.totschnig.myexpenses.util.GroupingNavigator
import org.totschnig.myexpenses.util.crashreporting.CrashHandler
import org.totschnig.myexpenses.viewmodel.data.Budget
import org.totschnig.myexpenses.viewmodel.data.BudgetAllocation
Expand Down Expand Up @@ -191,12 +193,16 @@ class BudgetViewModel2(application: Application, savedStateHandle: SavedStateHan
)
}

private suspend fun nextGrouping() =
GroupingNavigator.next(groupingInfo!!, dateInfoExtra.filterNotNull().first())


fun rollOverClear() {
viewModelScope.launch(context = coroutineContext()) {
val budget = accountInfo.value!!
val selection =
"${DatabaseConstants.KEY_BUDGETID} = ? AND ${DatabaseConstants.KEY_YEAR} = ? AND ${DatabaseConstants.KEY_SECOND_GROUP} = ?"
val nextGrouping = groupingInfo!!.next(dateInfoExtra.filterNotNull().first())
val nextGrouping = nextGrouping()
val ops = arrayListOf(
ContentProviderOperation.newUpdate(TransactionProvider.BUDGET_ALLOCATIONS_URI)
.withSelection(
Expand Down Expand Up @@ -227,7 +233,7 @@ class BudgetViewModel2(application: Application, savedStateHandle: SavedStateHan

private suspend fun saveRollOverList(rollOverList: List<Pair<Long, Long>>) {
val budget = accountInfo.value!!
val nextGrouping = groupingInfo!!.next(dateInfoExtra.filterNotNull().first())
val nextGrouping = nextGrouping()
val ops = ArrayList<ContentProviderOperation>()
rollOverList.forEach {
val (categoryId, rollOver) = it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.totschnig.myexpenses.viewmodel

import android.app.Application
import android.os.Parcelable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.SnapshotStateList
Expand Down Expand Up @@ -29,7 +28,6 @@ import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import org.totschnig.myexpenses.R
import org.totschnig.myexpenses.db2.updateCategoryColor
import org.totschnig.myexpenses.model.Grouping
Expand All @@ -56,6 +54,8 @@ import org.totschnig.myexpenses.provider.DbUtils
import org.totschnig.myexpenses.provider.TransactionProvider
import org.totschnig.myexpenses.provider.filter.WhereFilter
import org.totschnig.myexpenses.provider.getLongIfExistsOr0
import org.totschnig.myexpenses.util.GroupingInfo
import org.totschnig.myexpenses.util.GroupingNavigator
import org.totschnig.myexpenses.viewmodel.data.Budget
import org.totschnig.myexpenses.viewmodel.data.Category
import org.totschnig.myexpenses.viewmodel.data.DateInfoExtra
Expand Down Expand Up @@ -97,52 +97,21 @@ abstract class DistributionViewModelBase<T : DistributionAccountInfo>(
groupingInfo = GroupingInfo(grouping, 0, 0)
} else {
viewModelScope.launch {
groupingInfo = with(dateInfo.first()) {
GroupingInfo(
grouping = grouping,
year = when (grouping) {
Grouping.WEEK -> yearOfWeekStart
Grouping.MONTH -> yearOfMonthStart
else -> year
},
second = when (grouping) {
Grouping.DAY -> day
Grouping.WEEK -> week
Grouping.MONTH -> month
else -> 0
}
)
}
groupingInfo = GroupingNavigator.current(grouping,dateInfo.first())
}
}
}

fun GroupingInfo.next(dateInfo: DateInfoExtra): GroupingInfo {
val nextSecond = second + 1
val overflow = nextSecond > dateInfo.maxValue
return copy(
year = if (overflow) year + 1 else year,
second = if (overflow) grouping.minValue else nextSecond
)
}

fun GroupingInfo.previous(dateInfo: DateInfoExtra): GroupingInfo {
val nextSecond = second - 1
val underflow = nextSecond < grouping.minValue
return copy(
year = if (underflow) year - 1 else year,
second = if (underflow) dateInfo.maxValue else nextSecond
)
}

fun forward() {
groupingInfo?.let { info ->
if (info.grouping == Grouping.YEAR) {
groupingInfo = info.copy(year = info.year + 1)
groupingInfo = GroupingNavigator.nextYear(info)
} else {
viewModelScope.launch {
val dateInfo = dateInfoExtra.filterNotNull().first()
groupingInfo = info.next(dateInfo)
groupingInfo = GroupingNavigator.next(
info,
dateInfoExtra.filterNotNull().first()
)
}
}
}
Expand All @@ -151,11 +120,13 @@ abstract class DistributionViewModelBase<T : DistributionAccountInfo>(
fun backward() {
groupingInfo?.let { info ->
if (info.grouping == Grouping.YEAR) {
groupingInfo = info.copy(year = info.year - 1)
groupingInfo = GroupingNavigator.previousYear(info)
} else {
viewModelScope.launch {
val dateInfo = dateInfoExtra.filterNotNull().first()
groupingInfo = info.previous(dateInfo)
groupingInfo = GroupingNavigator.previous(
info,
dateInfoExtra.filterNotNull().first()
)
}
}
}
Expand Down Expand Up @@ -375,11 +346,4 @@ abstract class DistributionViewModelBase<T : DistributionAccountInfo>(
preference[aggregateNeutralPrefKey] = aggregateNeutral
}
}

@Parcelize
data class GroupingInfo(
val grouping: Grouping = Grouping.NONE,
val year: Int = -1,
val second: Int = -1
) : Parcelable
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.totschnig.myexpenses.viewmodel.data

import org.totschnig.myexpenses.db2.BudgetPeriod
import org.totschnig.myexpenses.model.CurrencyUnit

data class BudgetProgress(
val title: String,
val currency: CurrencyUnit,
val groupInfo: String,
val groupInfo: BudgetPeriod,
val allocated: Long,
val spent: Long,
val totalDays: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import org.totschnig.myexpenses.injector
import org.totschnig.myexpenses.preference.PrefKey
import timber.log.Timber


const val WIDGET_CLICK = "org.totschnig.myexpenses.WIDGET_CLICK"
const val KEY_CLICK_ACTION = "clickAction"
const val WIDGET_CONTEXT_CHANGED = "org.totschnig.myexpenses.CONTEXT_CHANGED"
const val EXTRA_START_FROM_WIDGET = "startFromWidget"
Expand Down Expand Up @@ -51,28 +49,15 @@ abstract class AbstractListWidget(
val instance = AppWidgetManager.getInstance(context)
val appWidgetIds = intent.extras?.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS)
when (intent.action) {
WIDGET_LIST_DATA_CHANGED -> {
WIDGET_LIST_DATA_CHANGED ->
appWidgetIds?.let { instance.notifyAppWidgetViewDataChanged(it, R.id.list) }
}

WIDGET_CONTEXT_CHANGED -> {
appWidgetIds?.let { onUpdate(context, instance, it) }
}

WIDGET_CLICK -> {
handleWidgetClick(context, intent)
}
WIDGET_CONTEXT_CHANGED -> appWidgetIds?.let { onUpdate(context, instance, it) }

else -> {
super.onReceive(context, intent)
}
else -> super.onReceive(context, intent)
}
}

abstract fun handleWidgetClick(context: Context, intent: Intent)

fun clickBaseIntent(context: Context) = Intent(WIDGET_CLICK, null, context, javaClass)

override suspend fun updateWidgetDo(
context: Context,
appWidgetManager: AppWidgetManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import android.widget.RemoteViews
Expand All @@ -22,6 +23,7 @@ import javax.inject.Inject

class NoDataException(message: String) : Exception(message)

const val WIDGET_CLICK = "org.totschnig.myexpenses.WIDGET_CLICK"
const val WIDGET_LIST_DATA_CHANGED = "org.totschnig.myexpenses.LIST_DATA_CHANGED"

abstract class BaseWidget(private val protectionKey: PrefKey) : AppWidgetProvider() {
Expand All @@ -38,6 +40,16 @@ abstract class BaseWidget(private val protectionKey: PrefKey) : AppWidgetProvide
protected open fun isProtected(context: Context) = prefHandler.isProtected &&
!prefHandler.getBoolean(protectionKey, false)


abstract fun handleWidgetClick(context: Context, intent: Intent)

fun clickBaseIntent(context: Context) = Intent(WIDGET_CLICK, null, context, javaClass)

override fun onReceive(context: Context, intent: Intent) {
if (intent.action == WIDGET_CLICK) handleWidgetClick(context, intent)
else super.onReceive(context, intent)
}

override fun onAppWidgetOptionsChanged(
context: Context,
appWidgetManager: AppWidgetManager,
Expand Down
Loading

0 comments on commit d3d8364

Please sign in to comment.