fixes: timeAgo utc parse, reload clears unread, sync-event debug
- detail banner timeAgo: SQLite timestamps are UTC without tz marker, JS was parsing them as local. Fixed by appending Z when absent — same pattern chat uses. "2h ago" for a 30s-old update is gone. - banner Reload button now re-fires detail.opened so the collab-buckets plugin clears the red dot on the board card and calls mark-card-seen. Dismiss (×) still leaves the dot — that's the acknowledgement that nothing was actually read. - instrument /api/relay/poll with a sync_debug field so the JS can console.debug what happened on the sync-events sub-request (status, count, error body). Helps diagnose "no toast" reports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
1966f8f4c0
commit
4a668b7fc4
5 files changed
+26
-4
No files matched your search
+1
-1
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
define('APP_NAME', 'hyprcrd');
|
||||
define('APP_VERSION', '1.8.0');
|
||||
define('APP_VERSION', '1.8.1');
|
||||
|
||||
// Database path — writable directory, outside webroot
|
||||
// DB_PATH / UPLOAD_DIR can be pre-defined by the Electron router for app isolation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hyprcrd",
|
||||
"version": "1.8.0",
|
||||
"version": "1.8.1",
|
||||
"description": "hyprcrd — self-hosted card manager",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
+8
-1
@@ -961,6 +961,7 @@ if (str_starts_with($route, '/api/')) {
|
||||
// them. GET /api/sync-events on the relay auto-marks fetched events.
|
||||
// Best-effort — older relays won't have the endpoint.
|
||||
$syncEvents = [];
|
||||
$syncDebug = ['requested' => true];
|
||||
$sch = curl_init(rtrim($relayUrl, '/') . '/api/sync-events');
|
||||
curl_setopt_array($sch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
@@ -970,14 +971,20 @@ if (str_starts_with($route, '/api/')) {
|
||||
$sResp = curl_exec($sch);
|
||||
$sStatus = curl_getinfo($sch, CURLINFO_HTTP_CODE);
|
||||
curl_close($sch);
|
||||
$syncDebug['status'] = $sStatus;
|
||||
if ($sStatus === 200) {
|
||||
$decoded = json_decode($sResp, true);
|
||||
if (is_array($decoded) && isset($decoded['events'])) {
|
||||
$syncEvents = $decoded['events'];
|
||||
$syncDebug['count'] = count($syncEvents);
|
||||
} else {
|
||||
$syncDebug['parse_error'] = substr((string)$sResp, 0, 200);
|
||||
}
|
||||
} else {
|
||||
$syncDebug['body'] = substr((string)$sResp, 0, 200);
|
||||
}
|
||||
|
||||
echo json_encode(['ok' => true, 'pulled' => $pulled, 'sync_events' => $syncEvents]); exit;
|
||||
echo json_encode(['ok' => true, 'pulled' => $pulled, 'sync_events' => $syncEvents, 'sync_debug' => $syncDebug]); exit;
|
||||
}
|
||||
|
||||
// List relay tenants (for the recipient picker)
|
||||
|
||||
@@ -340,6 +340,9 @@ function showSyncEventToast(ev) {
|
||||
}
|
||||
|
||||
function drainSyncEvents(relayRes) {
|
||||
if (relayRes?.sync_debug) {
|
||||
console.debug('[sync-events]', relayRes.sync_debug);
|
||||
}
|
||||
const events = Array.isArray(relayRes?.sync_events) ? relayRes.sync_events : [];
|
||||
for (const ev of events) showSyncEventToast(ev);
|
||||
}
|
||||
|
||||
@@ -116,6 +116,10 @@ function showStaleBanner(fresh) {
|
||||
state.viewingCard = current;
|
||||
renderSidebar(current);
|
||||
showContent(current);
|
||||
// Treat the reload as an explicit "I've now seen the new version"
|
||||
// — re-fire detail.opened so collab-buckets clears the red dot
|
||||
// on the board card and persists mark-card-seen to the backend.
|
||||
window.hyprcrd?.hooks?.emit?.('detail.opened', { id: current.id });
|
||||
}
|
||||
dismissStaleBanner();
|
||||
});
|
||||
@@ -123,7 +127,15 @@ function showStaleBanner(fresh) {
|
||||
}
|
||||
|
||||
function timeAgo(iso) {
|
||||
const t = new Date(iso).getTime();
|
||||
if (!iso) return '';
|
||||
// SQLite stores CURRENT_TIMESTAMP as UTC without a tz marker
|
||||
// ("2026-04-14 12:34:56"). Without an explicit Z, JS parses it as
|
||||
// local time — off by the tz offset (2h on CEST, hence "2h ago"
|
||||
// for a 30-second-old update).
|
||||
const normalized = String(iso).includes('T') || /[Zz]|[+-]\d\d:?\d\d$/.test(iso)
|
||||
? iso
|
||||
: iso.replace(' ', 'T') + 'Z';
|
||||
const t = new Date(normalized).getTime();
|
||||
if (!isFinite(t)) return '';
|
||||
const s = Math.max(0, (Date.now() - t) / 1000);
|
||||
if (s < 60) return `${Math.floor(s)}s ago`;
|
||||
|
||||
Reference in new issue
Block a user