Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 9s
Renovate / renovate (push) Successful in 1m28s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Successful in 18m17s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Successful in 1m31s
Beta — Codeberg pre-release / detect (push) Successful in 5s
Beta — Codeberg pre-release / beta (push) Skipped
Stable 2.23.0 after four betas. It adds long-press select, move, resize and drafting in the timeline, tap-to-call phone numbers, formatted HTML descriptions, scrolling back in the agenda, events from shared text, the option to open the editor on tap, the black theme, Liberapay and more haptics. It also fixes the daylight saving and recurring-move bugs. CHANGELOG.md has the full list, and every store locale has its own What's New. I merged main into the release branch to pick up Liberapay (#430) and Weblate #421. The Czech and Japanese string conflicts were lines added at the end of each file on both sides, so I kept main's. Closes #116, closes #141, closes #153, closes #178, closes #181, closes #271, closes #306, closes #339, closes #367, closes #387, closes #413 Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de> Co-authored-by: Tritra002 <tritratrulala002@outlook.com> Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/433
81 lines
3.2 KiB
Kotlin
81 lines
3.2 KiB
Kotlin
package de.jeanlucmakiola.calendula.ui
|
|
|
|
import androidx.lifecycle.ViewModel
|
|
import androidx.lifecycle.viewModelScope
|
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
import de.jeanlucmakiola.calendula.data.prefs.SettingsPrefs
|
|
import de.jeanlucmakiola.calendula.data.time.TodaySource
|
|
import de.jeanlucmakiola.calendula.data.time.currentDate
|
|
import de.jeanlucmakiola.calendula.ui.common.CalendarView
|
|
import de.jeanlucmakiola.calendula.ui.common.IMPLEMENTED_VIEWS
|
|
import de.jeanlucmakiola.floret.android.stateWhileSubscribed
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
import kotlinx.coroutines.flow.map
|
|
import kotlinx.coroutines.flow.first
|
|
import kotlinx.datetime.LocalDate
|
|
import javax.inject.Inject
|
|
|
|
/**
|
|
* Supplies [CalendarHost] with the user's default startup view (M1). Held as a
|
|
* nullable [StateFlow] so the host can wait for DataStore's first emission before
|
|
* seeding its view back stack — rendering nothing for that first frame rather
|
|
* than flashing the old hard-coded Week view and then correcting it.
|
|
*/
|
|
@HiltViewModel
|
|
class CalendarHostViewModel @Inject constructor(
|
|
prefs: SettingsPrefs,
|
|
todaySource: TodaySource,
|
|
) : ViewModel() {
|
|
|
|
/** Today, kept current across midnight so the shared focus can follow it (#373). */
|
|
val today: StateFlow<LocalDate> = todaySource.today.stateWhileSubscribed(
|
|
scope = viewModelScope,
|
|
initialValue = currentDate(),
|
|
)
|
|
|
|
val defaultView: StateFlow<CalendarView?> = prefs.defaultView.stateWhileSubscribed(
|
|
scope = viewModelScope,
|
|
initialValue = null,
|
|
)
|
|
|
|
/** Views the top-bar quick-switch pill cycles through, in the user's order (#24). */
|
|
val quickSwitchViews: StateFlow<List<CalendarView>> = prefs.quickSwitchConfig
|
|
.map { it.cycle }
|
|
.stateWhileSubscribed(
|
|
scope = viewModelScope,
|
|
initialValue = IMPLEMENTED_VIEWS,
|
|
)
|
|
|
|
/** Order of the views in the navigation drawer (#24); every view always shown. */
|
|
val drawerViewOrder: StateFlow<List<CalendarView>> = prefs.drawerViewOrder
|
|
.stateWhileSubscribed(
|
|
scope = viewModelScope,
|
|
initialValue = IMPLEMENTED_VIEWS,
|
|
)
|
|
|
|
/** Whether each view's jump-to-today control lives in the top bar, not the FAB (#60). */
|
|
val todayButtonInToolbar: StateFlow<Boolean> = prefs.todayButtonInToolbar
|
|
.stateWhileSubscribed(
|
|
scope = viewModelScope,
|
|
initialValue = false,
|
|
)
|
|
|
|
/**
|
|
* Whether events may be dragged to another slot to reschedule them (#68, #173).
|
|
* Off until the stored value arrives, even though the preference itself defaults
|
|
* on: the wrong guess costs an enabled user a gesture for the few frames a cold
|
|
* start takes to read DataStore, but re-arms the one thing a disabled user
|
|
* switched off to be rid of.
|
|
*/
|
|
val dragToReschedule: StateFlow<Boolean> = prefs.dragToReschedule
|
|
.stateWhileSubscribed(
|
|
scope = viewModelScope,
|
|
initialValue = false,
|
|
)
|
|
|
|
private val tapOpensEditorPref = prefs.tapOpensEditor
|
|
|
|
/** Whether tapping an event opens the edit form rather than the detail screen (#178). */
|
|
suspend fun tapOpensEditor(): Boolean = tapOpensEditorPref.first()
|
|
}
|