autosync toggle, configurable sync interval, 30-day session
- header Sync button now has a paired autosync toggle to its right — reads as one button with no inner seam (outer border only). Dot inside pulses once per actual sync (bursts on every backgroundSync / triggerSync / collab pollOnce via a new sync.pulse hook) so the user can see polls happen. Dot + data-autosync attribute persist the enabled state in localStorage; paused state stops both the CalDAV/relay background timer and the collab poll via a broadcast autosync.changed hook. - hover polish: Sync regains a full accent border (the missing inner edge re-appears only on its hover); the toggle fills with solid accent as hover treatment so the pair never shows a half-outline. - sync interval moved out of hardcode into a settings field under Settings → Relay: number input, 5s..3600s, default 15s (was 45s on caldav / 30s on collab). Changes broadcast via sync.interval.changed and restart both timers without reload. - session cookie lifetime raised to 30 days with matching gc_maxlifetime and SameSite=Lax (was 0 / Strict — some users got kicked to login on every reload when gc cleaned up the /tmp/sess file or a cross-link return blocked the cookie). - search button's kbd element was pushing the button ~3px taller than Sync; leading-none + tighter padding puts them on the same height. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6cd00f9660
commit
b7f450e41f
6 files changed
+222
-12
No files matched your search
@@ -1224,3 +1224,78 @@ body.anim-slow .board-card.card-pulse-local {
|
||||
.detail-stale-banner button:hover { background: var(--t-accent2); color: var(--t-bg); }
|
||||
.detail-stale-banner .detail-stale-dismiss { border-color: var(--t-border); color: var(--t-dim); padding: 3px 5px; }
|
||||
.detail-stale-banner .detail-stale-dismiss:hover { border-color: var(--t-danger); color: var(--t-danger); background: transparent; }
|
||||
|
||||
/* Sync + autosync combo: the pair reads as one button.
|
||||
- At rest: Sync has no right border, autosync has no left border —
|
||||
only the outer rectangle remains.
|
||||
- Hover Sync: the right border comes back in accent so Sync gets a
|
||||
complete outline around itself.
|
||||
- Hover autosync: no accent border at all — instead a background
|
||||
fill so the pair doesn't end up with a mismatched half-outline. */
|
||||
.header-sync-group { align-items: stretch; }
|
||||
.header-sync-group > button:first-child {
|
||||
border-right: 0 !important;
|
||||
}
|
||||
.header-sync-group > button:first-child:hover {
|
||||
border-right: 1px solid var(--t-accent) !important;
|
||||
}
|
||||
.header-sync-group > button + button {
|
||||
border-left: 0 !important;
|
||||
align-self: stretch;
|
||||
}
|
||||
#header-autosync:hover {
|
||||
background: var(--t-accent);
|
||||
border-color: var(--t-accent) !important;
|
||||
color: var(--t-bg) !important;
|
||||
}
|
||||
|
||||
/* Autosync toggle button.
|
||||
Border stays neutral in both states — the dot carries the status
|
||||
signal (accent + pulse when on, grey when off). Hover styling is
|
||||
handled by the bg-fill rule further down. */
|
||||
#header-autosync {
|
||||
border-color: var(--t-border);
|
||||
color: var(--t-muted);
|
||||
}
|
||||
|
||||
.header-autosync-dot {
|
||||
display: inline-block;
|
||||
width: 9px; height: 9px;
|
||||
border-radius: 50%;
|
||||
background: var(--t-accent);
|
||||
transition: background 0.15s, transform 0.2s;
|
||||
}
|
||||
#header-autosync[data-autosync="off"] .header-autosync-dot {
|
||||
background: var(--t-dim);
|
||||
box-shadow: none;
|
||||
}
|
||||
/* Hover: button fills with solid accent (matching the Sync button's
|
||||
hover border color). Dot switches to the app background color so it
|
||||
reads as a knockout against the fill. Pulsing keeps tracking real
|
||||
status — when a sync fires during hover the ring still animates. */
|
||||
#header-autosync:hover .header-autosync-dot {
|
||||
background: var(--t-bg);
|
||||
}
|
||||
/* Pulse shadow is accent-colored too, which would be invisible against
|
||||
the accent fill. Swap it to a bg-toned ring during hover so the
|
||||
pulse stays visible. */
|
||||
#header-autosync:hover .header-autosync-dot.pulsing {
|
||||
animation: header-autosync-pulse-on-hover 0.9s ease-out 1;
|
||||
}
|
||||
@keyframes header-autosync-pulse-on-hover {
|
||||
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--t-bg) 75%, transparent); transform: scale(1); }
|
||||
40% { transform: scale(1.4); }
|
||||
100% { box-shadow: 0 0 0 10px color-mix(in srgb, var(--t-bg) 0%, transparent); transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Burst pulse on each sync. JS adds `.pulsing` at the start of a sync
|
||||
and removes it after the animation finishes. Tuned to be visible
|
||||
against the button background — a generous ring that fades out. */
|
||||
.header-autosync-dot.pulsing {
|
||||
animation: header-autosync-pulse 0.9s ease-out 1;
|
||||
}
|
||||
@keyframes header-autosync-pulse {
|
||||
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--t-accent) 75%, transparent); transform: scale(1); }
|
||||
40% { transform: scale(1.4); }
|
||||
100% { box-shadow: 0 0 0 10px color-mix(in srgb, var(--t-accent) 0%, transparent); transform: scale(1); }
|
||||
}
|
||||
Reference in new issue
Block a user