From 3d7779ae832eb1dadbf90d9bf9ef15fa18a5cfb0 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Thu, 7 May 2026 18:52:51 +0200 Subject: [PATCH] fix(mobile): Zoom blocken, Long-Press, KW-Bubble, Swipe-Nav, Safe-Area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Viewport: maximum-scale=1, user-scalable=no — kein Pinch-Zoom mehr - Profil-Dropdown öffnet wieder: overflow:hidden auf .topbar-right in der Mobile-Media-Query entfernt (hatte das absolut positionierte Dropdown abgeschnitten) - Long-Press auf Kalenderzellen markiert keinen Text mehr: user-select/touch-callout/tap-highlight in der ganzen Mobile-UI aus - Long-Press auf Avatar zeigt nicht "Bild speichern": -webkit-touch-callout:none + pointer-events:none auf - Kalenderwochen erscheinen als kleine Bubble oben links in jeder Zeile statt als eigene 38px-Spalte - Status-Bar-Overlap im Settings-Modal behoben: safe-area-inset-top auf .settings-page-header und Modal-Header in der Mobile-Media-Query - Swipe links/rechts auf #view-container navigiert prev/next (≥60 px, überwiegend horizontal, < 700 ms) - Version v3 → v4 (auch SW-Cache) --- frontend/css/app.css | 60 ++++++++++++++++++++++++++++++++++++++++- frontend/index.html | 10 +++---- frontend/js/calendar.js | 28 +++++++++++++++++++ frontend/js/version.js | 2 +- frontend/sw.js | 2 +- 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/frontend/css/app.css b/frontend/css/app.css index bbca5fb..213afb0 100644 --- a/frontend/css/app.css +++ b/frontend/css/app.css @@ -1270,7 +1270,7 @@ a { color: var(--primary); text-decoration: none; } } .topbar-right { min-width: 0; - overflow: hidden; + /* no overflow:hidden — would clip the user dropdown on tap */ } .view-switcher { overflow-x: auto; @@ -1346,6 +1346,64 @@ a { color: var(--primary); text-decoration: none; } /* ── Misc safety: prevent overflow on flex topbar items ──── */ .main-view { width: 100%; min-width: 0; } #view-container { max-width: 100%; overflow-x: hidden; } + + /* ── Long-press / text-selection / image-save fixes ──────── */ + /* Calendar UI shouldn't be selectable on touch — long-press + should reach our handlers, not trigger iOS text selection. */ + .topbar, .sidebar, .main-view, + .month-view, .month-row, .month-col, .cell-day, .month-events-overlay, .month-span-event, + .week-view, .day-view, .week-day-col, .week-day-header, .week-allday-row, + .quarter-view, .agenda-view, + .view-switcher, .view-btn, .btn, .icon-btn, .user-avatar, .user-dropdown, .dropdown-item { + -webkit-user-select: none; + user-select: none; + -webkit-touch-callout: none; + -webkit-tap-highlight-color: transparent; + } + /* Faster taps, no double-tap zoom on interactive elements */ + .icon-btn, .btn, .view-btn, .user-avatar, .month-col, .week-day-col, .dropdown-item, + .sidebar-copyright, .impressum-link, .modal-close, [data-modal] { + touch-action: manipulation; + } + /* Avatar long-press: don't show "Save Image" — taps reach parent */ + .user-avatar img { + -webkit-touch-callout: none; + pointer-events: none; + } + + /* ── Calendar weeks (KW) shown as a small bubble, not a column ── */ + .month-header { + grid-template-columns: repeat(7, 1fr) !important; + } + .month-kw-header { display: none !important; } + .month-row-right { + margin-left: 0 !important; + } + .month-kw-cell { + position: absolute; + left: 3px; top: 3px; + width: auto; height: auto; + bottom: auto; + padding: 1px 7px; + background: var(--bg-active); + border: none !important; + border-radius: 10px; + font-size: 10px; font-weight: 600; + color: var(--text-2); + z-index: 5; + display: inline-flex; + align-items: center; + } + + /* ── Status-bar safe area inside full-screen modals (PWA) ── */ + .modal-card .modal-header, + .settings-page-header { + padding-top: calc(16px + env(safe-area-inset-top, 0px)); + } + .modal-footer, + .settings-page-body { + padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); + } } /* iOS notch / home-indicator safe areas (PWA standalone) */ diff --git a/frontend/index.html b/frontend/index.html index 69bce84..9efd076 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,9 +2,9 @@ - + - Calendarr v3 + Calendarr v4 @@ -77,7 +77,7 @@ - + @@ -179,7 +179,7 @@
- + @@ -841,7 +841,7 @@ scarriffleservices@gmail.com

diff --git a/frontend/js/calendar.js b/frontend/js/calendar.js index 1135044..464aeda 100644 --- a/frontend/js/calendar.js +++ b/frontend/js/calendar.js @@ -76,6 +76,7 @@ export async function initCalendar() { bindHAAccountModal(); bindSettingsModal(); bindProfileModal(); + bindSwipeNavigation(); handleHAOAuthReturn(); } @@ -755,6 +756,33 @@ function renderCalendarList() { }); } +// ── Swipe navigation (mobile) ───────────────────────────── +function bindSwipeNavigation() { + const container = document.getElementById('view-container'); + if (!container) return; + let startX = 0, startY = 0, startT = 0, active = false; + container.addEventListener('touchstart', e => { + if (e.touches.length !== 1) { active = false; return; } + startX = e.touches[0].clientX; + startY = e.touches[0].clientY; + startT = Date.now(); + active = true; + }, { passive: true }); + container.addEventListener('touchend', e => { + if (!active) return; + active = false; + const t = e.changedTouches[0]; + const dx = t.clientX - startX; + const dy = t.clientY - startY; + const dt = Date.now() - startT; + // Horizontal swipe: ≥ 60px, mostly horizontal, faster than 700ms + if (Math.abs(dx) > 60 && Math.abs(dx) > Math.abs(dy) * 1.5 && dt < 700) { + navigate(dx < 0 ? 1 : -1); + fetchAndRender(); + } + }, { passive: true }); +} + // ── Navigation ──────────────────────────────────────────── function navigate(dir) { const d = state.currentDate; diff --git a/frontend/js/version.js b/frontend/js/version.js index b54d089..9f06a98 100644 --- a/frontend/js/version.js +++ b/frontend/js/version.js @@ -1,2 +1,2 @@ // Increment APP_VERSION with every code change -export const APP_VERSION = 'v3'; +export const APP_VERSION = 'v4'; diff --git a/frontend/sw.js b/frontend/sw.js index 81d23ad..0213bb1 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,7 +1,7 @@ // Calendarr Service Worker // Cache-first for static assets, network-first for /api/* (graceful offline) -const CACHE_VERSION = 'calendarr-v3'; +const CACHE_VERSION = 'calendarr-v4'; const STATIC_ASSETS = [ '/', '/index.html',