diff --git a/frontend/js/calendar.js b/frontend/js/calendar.js index 88a7ac5..99c31bc 100644 --- a/frontend/js/calendar.js +++ b/frontend/js/calendar.js @@ -1209,9 +1209,14 @@ function bindSwipeNavigation() { function navigate(dir) { const d = state.currentDate; if (state.currentView === 'month') { - // Buttons jump 4 weeks (one screenful) - state.currentDate = new Date(d); - state.currentDate.setDate(d.getDate() + dir * 28); + if (state.settings && state.settings.month_view_paged) { + // Paged mode: jump a whole calendar month. + state.currentDate = new Date(d.getFullYear(), d.getMonth() + dir, Math.min(d.getDate(), 28)); + } else { + // Scroll mode: buttons jump 4 weeks (one screenful of the rolling grid). + state.currentDate = new Date(d); + state.currentDate.setDate(d.getDate() + dir * 28); + } } else if (state.currentView === 'week') { state.currentDate = new Date(d); state.currentDate.setDate(d.getDate() + dir * 7); @@ -1335,6 +1340,8 @@ function bindTopbar() { _wheelLast = now; const dir = e.deltaY > 0 ? 1 : -1; if (state.currentView === 'month') { + // Paged mode: no scroll navigation — only buttons / horizontal swipe. + if (state.settings && state.settings.month_view_paged) return; state.currentDate = new Date(state.currentDate); state.currentDate.setDate(state.currentDate.getDate() + dir * 7); fetchAndRender(); @@ -3463,11 +3470,13 @@ function wireSettingRow(def) { function readAppearanceTable() { const out = {}; const numKeys = new Set(['hour_height', 'default_event_duration_minutes']); + const boolKeys = new Set(['month_view_paged']); SETTING_GROUPS.forEach(g => g.rows.forEach(def => { if (def.type === 'select') { const el = document.querySelector(`[data-skey="${def.key}"]`); let v = el ? el.value : state.settings[def.key]; if (numKeys.has(def.key)) v = Number(v); + else if (boolKeys.has(def.key)) v = (String(v) === 'true'); out[def.key] = v; } else if (def.type === 'toggle') { const el = document.querySelector(`[data-vtoggle="${def.key}"]`); diff --git a/frontend/js/i18n.js b/frontend/js/i18n.js index b4bcdd6..c0615ed 100644 --- a/frontend/js/i18n.js +++ b/frontend/js/i18n.js @@ -92,6 +92,9 @@ const translations = { settings_week_start: 'Erster Wochentag', week_start_monday: 'Montag', week_start_sunday: 'Sonntag', settings_dim_past: 'Vergangene Termine ausgrauen', + settings_month_mode: 'Monatswechsel', + settings_month_mode_scroll: 'Fortlaufend scrollen (Woche)', + settings_month_mode_paged: 'Seitenweise blättern (Monat)', settings_default_duration: 'Standard-Termindauer', settings_privacy: 'Privatsphäre', settings_private_visibility: 'Private Termine für Gruppenmitglieder', @@ -446,6 +449,9 @@ const translations = { settings_week_start: 'First day of week', week_start_monday: 'Monday', week_start_sunday: 'Sunday', settings_dim_past: 'Dim past events', + settings_month_mode: 'Month switching', + settings_month_mode_scroll: 'Continuous scroll (week)', + settings_month_mode_paged: 'Page by page (month)', settings_default_duration: 'Default event duration', settings_privacy: 'Privacy', settings_private_visibility: 'Private events for group members', diff --git a/frontend/js/settings-sync.js b/frontend/js/settings-sync.js index 1810c07..c3084f6 100644 --- a/frontend/js/settings-sync.js +++ b/frontend/js/settings-sync.js @@ -34,6 +34,9 @@ export const SETTING_GROUPS = [ { v: 'monday', tk: 'week_start_monday' }, { v: 'sunday', tk: 'week_start_sunday' }, ] }, { key: 'dim_past_events', labelKey: 'settings_dim_past', type: 'toggle' }, + { key: 'month_view_paged', labelKey: 'settings_month_mode', type: 'select', opts: [ + { v: false, tk: 'settings_month_mode_scroll' }, { v: true, tk: 'settings_month_mode_paged' }, + ] }, { key: 'hour_height', labelKey: 'settings_hour_height', type: 'select', opts: [ { v: 28, tk: 'hour_compact' }, { v: 44, tk: 'hour_normal' }, { v: 60, tk: 'hour_comfort' }, { v: 80, tk: 'hour_large' }, diff --git a/frontend/sw.js b/frontend/sw.js index 5d758d4..eb66cbf 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -7,7 +7,7 @@ // the entry HTML / version files). New releases take effect on the next // reload, no manual SW unregister required. -const CACHE_VERSION = 'calendarr-v29'; +const CACHE_VERSION = 'calendarr-v30'; const OFFLINE_SHELL = ['/', '/index.html']; self.addEventListener('install', event => {