Compare commits

...

12 Commits

Author SHA1 Message Date
elpatron fb9bb6754c chore: release v0.1.0.101 2026-06-02 22:29:37 +02:00
elpatron 959afd5a63 Make scrollbars wider and more visible on touch devices.
Global theme-aware scrollbar styling replaces the thin 6px event-table bar so long forms are easier to scroll on mobile.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 22:29:16 +02:00
elpatron e3ea45f717 chore: release v0.1.0.100 2026-06-02 20:55:03 +02:00
elpatron 8f57b6ff22 Remove diagnostic debug code and backend endpoint 2026-06-02 20:54:58 +02:00
elpatron 60e1b714b7 chore: release v0.1.0.99 2026-06-02 20:45:44 +02:00
elpatron 1e203bfec1 Fix Service Worker evaluation order of precacheAndRoute 2026-06-02 20:45:40 +02:00
elpatron 11420685cf chore: release v0.1.0.98 2026-06-02 20:40:46 +02:00
elpatron c674aac344 Add debug logging for push and Service Worker registration 2026-06-02 20:40:41 +02:00
elpatron 9c91a0f1fc chore: release v0.1.0.97 2026-06-02 20:35:50 +02:00
elpatron 2bcbbba626 Register Service Worker manually on startup 2026-06-02 20:35:46 +02:00
elpatron b1500f8361 chore: release v0.1.0.96 2026-06-02 20:26:41 +02:00
elpatron bc7512003e fix: retrieve Service Worker registration directly via getRegistration() to avoid ready promise hangs 2026-06-02 20:26:04 +02:00
6 changed files with 101 additions and 32 deletions
+1 -1
View File
@@ -1 +1 @@
0.1.0.96
0.1.0.102
+1 -15
View File
@@ -2647,27 +2647,13 @@ html.scheme-dark .themed-select-option.is-selected {
.events-scroll-container {
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
background: rgba(11, 12, 16, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 12px;
box-sizing: border-box;
}
/* Custom Scrollbar for events container */
.events-scroll-container::-webkit-scrollbar {
height: 6px;
}
.events-scroll-container::-webkit-scrollbar-track {
background: rgba(11, 12, 16, 0.2);
}
.events-scroll-container::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.events-scroll-container::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.2);
}
.events-table {
width: 100%;
border-collapse: collapse;
+59
View File
@@ -18,3 +18,62 @@ body {
flex-direction: column;
align-items: center;
}
/* Scrollbars — auf Touch-Geräten breiter und besser sichtbar */
:root {
--app-scrollbar-size: 10px;
}
@media (hover: none), (pointer: coarse), (max-width: 768px) {
:root {
--app-scrollbar-size: 14px;
}
}
html {
scrollbar-width: auto;
scrollbar-color: var(--app-accent-light) var(--app-surface-inset);
-webkit-overflow-scrolling: touch;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar,
*::-webkit-scrollbar {
width: var(--app-scrollbar-size);
height: var(--app-scrollbar-size);
}
html::-webkit-scrollbar-track,
body::-webkit-scrollbar-track,
*::-webkit-scrollbar-track {
background: var(--app-surface-inset);
border-radius: calc(var(--app-scrollbar-size) / 2);
}
html::-webkit-scrollbar-thumb,
body::-webkit-scrollbar-thumb,
*::-webkit-scrollbar-thumb {
background: color-mix(in srgb, var(--app-accent-light) 55%, transparent);
border-radius: calc(var(--app-scrollbar-size) / 2);
min-height: 48px;
}
html::-webkit-scrollbar-thumb:hover,
body::-webkit-scrollbar-thumb:hover,
*::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--app-accent-light) 80%, transparent);
}
@media (hover: none), (pointer: coarse), (max-width: 768px) {
html::-webkit-scrollbar-thumb,
body::-webkit-scrollbar-thumb,
*::-webkit-scrollbar-thumb {
background: color-mix(in srgb, var(--app-accent-light) 70%, transparent);
}
html::-webkit-scrollbar-thumb:active,
body::-webkit-scrollbar-thumb:active,
*::-webkit-scrollbar-thumb:active {
background: var(--app-accent-light);
}
}
+11
View File
@@ -73,6 +73,17 @@ async function bootstrap(): Promise<void> {
return
}
if ('serviceWorker' in navigator && !import.meta.env.DEV) {
navigator.serviceWorker
.register('/sw.js', { scope: '/' })
.then((reg) => {
console.log('Service Worker registered successfully with scope:', reg.scope)
})
.catch((err) => {
console.error('Service Worker registration failed:', err)
})
}
const rootEl = document.getElementById('root')
if (!rootEl) {
throw new Error('Missing #root element')
+25 -12
View File
@@ -30,6 +30,27 @@ export function getNotificationPermission(): NotificationPermission | 'unsupport
let cachedVapidKey: string | null = null
let cachedRegistration: ServiceWorkerRegistration | null = null
async function getRegistrationCompat(timeoutMs = 8000): Promise<ServiceWorkerRegistration> {
if (!('serviceWorker' in navigator)) {
throw new Error('Service Worker is not supported by your browser')
}
try {
const reg = await navigator.serviceWorker.getRegistration()
if (reg) return reg
} catch (e) {
console.warn('Failed to get service worker registration directly:', e)
}
// Fallback to waiting for ready state with a timeout
const readyPromise = navigator.serviceWorker.ready
const timeoutPromise = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Timeout waiting for Service Worker ready state')), timeoutMs)
)
return Promise.race([readyPromise, timeoutPromise])
}
export async function preloadPushService(): Promise<void> {
if (!isPushSupported()) return
try {
@@ -37,7 +58,7 @@ export async function preloadPushService(): Promise<void> {
await fetchVapidPublicKey()
}
if (!cachedRegistration) {
cachedRegistration = await navigator.serviceWorker.ready
cachedRegistration = await getRegistrationCompat()
}
} catch (err) {
console.warn('Failed to preload push service:', err)
@@ -172,14 +193,10 @@ export async function subscribeToPush(): Promise<void> {
throw new Error('Push notifications are not supported on this device')
}
// Pre-resolve registration with timeout to prevent silent hangs
// Pre-resolve registration using getRegistrationCompat to prevent ready state hangs
let registration = cachedRegistration
if (!registration) {
const readyPromise = navigator.serviceWorker.ready
const readyTimeout = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Timeout waiting for Service Worker ready state')), 8000)
)
registration = await Promise.race([readyPromise, readyTimeout])
registration = await getRegistrationCompat()
cachedRegistration = registration
}
@@ -214,11 +231,7 @@ export async function unsubscribeFromPush(): Promise<void> {
let registration = cachedRegistration
if (!registration) {
const readyPromise = navigator.serviceWorker.ready
const readyTimeout = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Timeout waiting for Service Worker ready state')), 8000)
)
registration = await Promise.race([readyPromise, readyTimeout])
registration = await getRegistrationCompat()
cachedRegistration = registration
}
+4 -4
View File
@@ -6,6 +6,10 @@ import { NetworkFirst, NetworkOnly } from 'workbox-strategies'
declare let self: ServiceWorkerGlobalScope
precacheAndRoute(self.__WB_MANIFEST)
cleanupOutdatedCaches()
clientsClaim()
const appShellFallback = createHandlerBoundToURL('/index.html')
const navigationStrategy = new NetworkFirst({
cacheName: 'app-shell',
@@ -20,10 +24,6 @@ registerRoute(({ request }) => request.mode === 'navigate', async (context) => {
}
})
precacheAndRoute(self.__WB_MANIFEST)
cleanupOutdatedCaches()
clientsClaim()
// Always fetch the live deploy version, even under an older precache.
registerRoute(({ url }) => url.pathname === '/version.json', new NetworkOnly())