Add a setting to turn drag-to-reschedule off (#173)
Drag to move is on by default; turning it off drops the move scope, so no event block registers a drag gesture at all.
This commit is contained in:
@@ -301,6 +301,19 @@ class SettingsPrefs @Inject constructor(
|
|||||||
store.edit { it[TODAY_BUTTON_IN_TOOLBAR_KEY] = enabled }
|
store.edit { it[TODAY_BUTTON_IN_TOOLBAR_KEY] = enabled }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether events can be dragged to another slot in the calendar views (#68,
|
||||||
|
* #173). Defaults to ON. Off means no block registers a drag gesture at all;
|
||||||
|
* rescheduling then goes through the edit form.
|
||||||
|
*/
|
||||||
|
val dragToReschedule: Flow<Boolean> = store.data.map { prefs ->
|
||||||
|
prefs[DRAG_TO_RESCHEDULE_KEY] ?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setDragToReschedule(enabled: Boolean) {
|
||||||
|
store.edit { it[DRAG_TO_RESCHEDULE_KEY] = enabled }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How far ahead the in-app Agenda screen shows events (v2.11). Defaults to
|
* How far ahead the in-app Agenda screen shows events (v2.11). Defaults to
|
||||||
* [AgendaRange.Month] — a month of upcoming events. Independent of the
|
* [AgendaRange.Month] — a month of upcoming events. Independent of the
|
||||||
@@ -945,6 +958,7 @@ class SettingsPrefs @Inject constructor(
|
|||||||
internal val MONTH_VIEW_STYLE_KEY = stringPreferencesKey("month_view_style")
|
internal val MONTH_VIEW_STYLE_KEY = stringPreferencesKey("month_view_style")
|
||||||
internal val TIMELINE_SCALE_KEY = stringPreferencesKey("timeline_scale")
|
internal val TIMELINE_SCALE_KEY = stringPreferencesKey("timeline_scale")
|
||||||
internal val TODAY_BUTTON_IN_TOOLBAR_KEY = booleanPreferencesKey("today_button_in_toolbar")
|
internal val TODAY_BUTTON_IN_TOOLBAR_KEY = booleanPreferencesKey("today_button_in_toolbar")
|
||||||
|
internal val DRAG_TO_RESCHEDULE_KEY = booleanPreferencesKey("drag_to_reschedule")
|
||||||
internal val DEFAULT_VIEW_KEY = stringPreferencesKey("default_view")
|
internal val DEFAULT_VIEW_KEY = stringPreferencesKey("default_view")
|
||||||
internal val QUICK_SWITCH_VIEWS_KEY = stringPreferencesKey("quick_switch_views")
|
internal val QUICK_SWITCH_VIEWS_KEY = stringPreferencesKey("quick_switch_views")
|
||||||
internal val DRAWER_VIEW_ORDER_KEY = stringPreferencesKey("drawer_view_order")
|
internal val DRAWER_VIEW_ORDER_KEY = stringPreferencesKey("drawer_view_order")
|
||||||
|
|||||||
@@ -312,6 +312,9 @@ fun CalendarHost(
|
|||||||
heldEditKey = key
|
heldEditKey = key
|
||||||
editKey = key
|
editKey = key
|
||||||
}
|
}
|
||||||
|
// Off by preference (#173) means no scope at all: every block then registers
|
||||||
|
// no drag gesture, and the edit form stays the way to reschedule.
|
||||||
|
val dragToReschedule = viewModel.dragToReschedule.collectAsStateWithLifecycle().value
|
||||||
val moveScope = remember(movableCalendarIds, reschedule) {
|
val moveScope = remember(movableCalendarIds, reschedule) {
|
||||||
EventMoveScope(
|
EventMoveScope(
|
||||||
movableCalendarIds = movableCalendarIds,
|
movableCalendarIds = movableCalendarIds,
|
||||||
@@ -339,7 +342,7 @@ fun CalendarHost(
|
|||||||
// navigation, so it fades through rather than sliding — paging *within* a
|
// navigation, so it fades through rather than sliding — paging *within* a
|
||||||
// view keeps the directional slide. AnimatedContent keyed on the view type.
|
// view keeps the directional slide. AnimatedContent keyed on the view type.
|
||||||
val viewSwitch = fadeThrough()
|
val viewSwitch = fadeThrough()
|
||||||
CompositionLocalProvider(LocalEventMove provides moveScope) {
|
CompositionLocalProvider(LocalEventMove provides moveScope.takeIf { dragToReschedule }) {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
targetState = view,
|
targetState = view,
|
||||||
transitionSpec = { viewSwitch },
|
transitionSpec = { viewSwitch },
|
||||||
|
|||||||
@@ -53,4 +53,12 @@ class CalendarHostViewModel @Inject constructor(
|
|||||||
started = SharingStarted.WhileSubscribed(5_000L),
|
started = SharingStarted.WhileSubscribed(5_000L),
|
||||||
initialValue = false,
|
initialValue = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** Whether events may be dragged to another slot to reschedule them (#68, #173). */
|
||||||
|
val dragToReschedule: StateFlow<Boolean> = prefs.dragToReschedule
|
||||||
|
.stateIn(
|
||||||
|
scope = viewModelScope,
|
||||||
|
started = SharingStarted.WhileSubscribed(5_000L),
|
||||||
|
initialValue = true,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ data class SettingsUiState(
|
|||||||
val showWeekNumbers: Boolean = false,
|
val showWeekNumbers: Boolean = false,
|
||||||
/** Whether the jump-to-today control sits in the top bar instead of the FAB (#60). */
|
/** Whether the jump-to-today control sits in the top bar instead of the FAB (#60). */
|
||||||
val todayButtonInToolbar: Boolean = false,
|
val todayButtonInToolbar: Boolean = false,
|
||||||
|
/** Whether events can be dragged to another slot to reschedule them (#68, #173). */
|
||||||
|
val dragToReschedule: Boolean = true,
|
||||||
/** How far ahead the in-app Agenda screen shows events (v2.11). */
|
/** How far ahead the in-app Agenda screen shows events (v2.11). */
|
||||||
val agendaScreenRange: AgendaRange = AgendaRange.Month,
|
val agendaScreenRange: AgendaRange = AgendaRange.Month,
|
||||||
/** How far ahead the agenda widget shows events (v2.11). */
|
/** How far ahead the agenda widget shows events (v2.11). */
|
||||||
|
|||||||
@@ -145,9 +145,15 @@ class SettingsViewModel @Inject constructor(
|
|||||||
prefs.showWeekNumbers,
|
prefs.showWeekNumbers,
|
||||||
prefs.agendaShowToday,
|
prefs.agendaShowToday,
|
||||||
prefs.softenCalendarColors,
|
prefs.softenCalendarColors,
|
||||||
prefs.todayButtonInToolbar,
|
combine(
|
||||||
) { hourLines, weekNumbers, showToday, soften, todayInToolbar ->
|
prefs.todayButtonInToolbar,
|
||||||
DisplayToggles(hourLines, weekNumbers, showToday, soften, todayInToolbar)
|
prefs.dragToReschedule,
|
||||||
|
::Pair,
|
||||||
|
),
|
||||||
|
) { hourLines, weekNumbers, showToday, soften, (todayInToolbar, dragToMove) ->
|
||||||
|
DisplayToggles(
|
||||||
|
hourLines, weekNumbers, showToday, soften, todayInToolbar, dragToMove,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
) { view, screenRange, widgetRange, timeFormat, toggles ->
|
) { view, screenRange, widgetRange, timeFormat, toggles ->
|
||||||
ViewSettings(
|
ViewSettings(
|
||||||
@@ -157,6 +163,7 @@ class SettingsViewModel @Inject constructor(
|
|||||||
agendaShowToday = toggles.agendaShowToday,
|
agendaShowToday = toggles.agendaShowToday,
|
||||||
softenColors = toggles.softenColors,
|
softenColors = toggles.softenColors,
|
||||||
todayButtonInToolbar = toggles.todayButtonInToolbar,
|
todayButtonInToolbar = toggles.todayButtonInToolbar,
|
||||||
|
dragToReschedule = toggles.dragToReschedule,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
combine(
|
combine(
|
||||||
@@ -189,6 +196,7 @@ class SettingsViewModel @Inject constructor(
|
|||||||
agendaShowToday = views.agendaShowToday,
|
agendaShowToday = views.agendaShowToday,
|
||||||
softenColors = views.softenColors,
|
softenColors = views.softenColors,
|
||||||
todayButtonInToolbar = views.todayButtonInToolbar,
|
todayButtonInToolbar = views.todayButtonInToolbar,
|
||||||
|
dragToReschedule = views.dragToReschedule,
|
||||||
agendaShowRangeBar = misc.showRangeBar,
|
agendaShowRangeBar = misc.showRangeBar,
|
||||||
autofocusEventTitle = misc.autofocusEventTitle,
|
autofocusEventTitle = misc.autofocusEventTitle,
|
||||||
pastEventDisplay = misc.pastEventDisplay,
|
pastEventDisplay = misc.pastEventDisplay,
|
||||||
@@ -289,6 +297,7 @@ class SettingsViewModel @Inject constructor(
|
|||||||
val agendaShowToday: Boolean,
|
val agendaShowToday: Boolean,
|
||||||
val softenColors: Boolean,
|
val softenColors: Boolean,
|
||||||
val todayButtonInToolbar: Boolean,
|
val todayButtonInToolbar: Boolean,
|
||||||
|
val dragToReschedule: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class DisplayToggles(
|
private data class DisplayToggles(
|
||||||
@@ -297,6 +306,7 @@ class SettingsViewModel @Inject constructor(
|
|||||||
val agendaShowToday: Boolean,
|
val agendaShowToday: Boolean,
|
||||||
val softenColors: Boolean,
|
val softenColors: Boolean,
|
||||||
val todayButtonInToolbar: Boolean,
|
val todayButtonInToolbar: Boolean,
|
||||||
|
val dragToReschedule: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class MiscSettings(
|
private data class MiscSettings(
|
||||||
@@ -534,6 +544,10 @@ class SettingsViewModel @Inject constructor(
|
|||||||
viewModelScope.launch { prefs.setTodayButtonInToolbar(enabled) }
|
viewModelScope.launch { prefs.setTodayButtonInToolbar(enabled) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setDragToReschedule(enabled: Boolean) {
|
||||||
|
viewModelScope.launch { prefs.setDragToReschedule(enabled) }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch the launcher label (#44). The card highlights at once, then settles
|
* Switch the launcher label (#44). The card highlights at once, then settles
|
||||||
* on what the component state reports; the writes are binder round-trips and
|
* on what the component state reports; the writes are binder round-trips and
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ internal fun ViewsScreen(
|
|||||||
GroupedRow(
|
GroupedRow(
|
||||||
title = stringResource(R.string.settings_dim_completed),
|
title = stringResource(R.string.settings_dim_completed),
|
||||||
summary = stringResource(R.string.settings_dim_completed_summary),
|
summary = stringResource(R.string.settings_dim_completed_summary),
|
||||||
position = Position.Bottom,
|
position = Position.Middle,
|
||||||
trailing = {
|
trailing = {
|
||||||
Switch(
|
Switch(
|
||||||
checked = state.dimCompletedEvents,
|
checked = state.dimCompletedEvents,
|
||||||
@@ -123,6 +123,18 @@ internal fun ViewsScreen(
|
|||||||
},
|
},
|
||||||
onClick = { viewModel.setDimCompletedEvents(!state.dimCompletedEvents) },
|
onClick = { viewModel.setDimCompletedEvents(!state.dimCompletedEvents) },
|
||||||
)
|
)
|
||||||
|
GroupedRow(
|
||||||
|
title = stringResource(R.string.settings_drag_to_reschedule),
|
||||||
|
summary = stringResource(R.string.settings_drag_to_reschedule_summary),
|
||||||
|
position = Position.Bottom,
|
||||||
|
trailing = {
|
||||||
|
Switch(
|
||||||
|
checked = state.dragToReschedule,
|
||||||
|
onCheckedChange = viewModel::setDragToReschedule,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = { viewModel.setDragToReschedule(!state.dragToReschedule) },
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
SectionHeader(stringResource(R.string.settings_month_header))
|
SectionHeader(stringResource(R.string.settings_month_header))
|
||||||
|
|||||||
@@ -439,6 +439,8 @@
|
|||||||
<string name="timeline_scale_custom_summary">The height you pinched the timeline to</string>
|
<string name="timeline_scale_custom_summary">The height you pinched the timeline to</string>
|
||||||
<string name="settings_dim_completed">Dim completed events</string>
|
<string name="settings_dim_completed">Dim completed events</string>
|
||||||
<string name="settings_dim_completed_summary">Fade events that have already ended in month and week view</string>
|
<string name="settings_dim_completed_summary">Fade events that have already ended in month and week view</string>
|
||||||
|
<string name="settings_drag_to_reschedule">Drag to reschedule</string>
|
||||||
|
<string name="settings_drag_to_reschedule_summary">Move an event by dragging it to another day or time</string>
|
||||||
<string name="settings_past_events">Past events</string>
|
<string name="settings_past_events">Past events</string>
|
||||||
<string name="settings_past_events_show">Show</string>
|
<string name="settings_past_events_show">Show</string>
|
||||||
<string name="settings_past_events_dim">Dim</string>
|
<string name="settings_past_events_dim">Dim</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user