fuzzyworld

north-star / commit

some small changes, upgraded the arrow image to a higher res

cf7471ca2d5c7b8d1c01e5327b0dd0e18b0d96a6 · Pavel Safronov · 2026-03-16 00:15:21 -0700 · parents c5543782f061

some small changes, upgraded the arrow image to a higher res
 src/app.ts          |  10 +++++-----
 src/friends-sync.ts |   3 ++-
 src/image.png       | Bin 15595 -> 53827 bytes
 src/index.html      |   6 +++++-
 src/utils.ts        |   2 +-
 5 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/app.ts b/src/app.ts
index 71ee111..5a072f6 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -1,4 +1,4 @@
-import { get, ref, remove, set } from 'firebase/database';
+import { get, ref, remove, set, serverTimestamp } from 'firebase/database';
 import { getReadableTextColor, getArrowDisplayColor } from './utils';
 import { encryptJson } from './crypto';
 import { initDarkMode } from './darkmode';
@@ -71,9 +71,9 @@ const { requestWakeLock } = createWakeLockManager();
 const setCleanMode = (enabled: boolean) => {
     document.body.classList.toggle('clean-mode', enabled);
     if (cleanModeToggle instanceof HTMLButtonElement) {
-        cleanModeToggle.textContent = enabled ? 'Full' : 'Clean';
+        cleanModeToggle.textContent = enabled ? 'Back' : 'Fullscreen';
         cleanModeToggle.setAttribute('aria-pressed', String(enabled));
-        cleanModeToggle.setAttribute('aria-label', enabled ? 'Switch to full mode' : 'Switch to clean mode');
+        cleanModeToggle.setAttribute('aria-label', enabled ? 'Back to full mode' : 'Enter fullscreen mode');
     }
 };
 
@@ -141,8 +141,8 @@ const syncSelfFriend = async () => {
     const now = Date.now();
     selfFriend.timestamp = now;
     const dbRecord = roomKey
-        ? { encryptedState: await encryptJson(roomKey, selfFriend), lastSeen: now }
-        : { ...selfFriend, lastSeen: now };
+        ? { encryptedState: await encryptJson(roomKey, selfFriend), lastSeen: serverTimestamp() }
+        : { ...selfFriend, lastSeen: serverTimestamp() };
     try {
         await set(friendRef, dbRecord);
         lastLocationSyncAt = now;
diff --git a/src/friends-sync.ts b/src/friends-sync.ts
index c8fb126..d180d35 100644
--- a/src/friends-sync.ts
+++ b/src/friends-sync.ts
@@ -33,7 +33,8 @@ export function subscribeToFriends({ db, roomId, roomKey, onUpdate }) {
             const decrypted = await Promise.all(rawFriends.map(async (p) => {
                 if (p.encryptedState && roomKey) {
                     try {
-                        return await decryptJson(roomKey, p.encryptedState);
+                        const decryptedState = await decryptJson(roomKey, p.encryptedState);
+                        return { ...decryptedState, lastSeen: p.lastSeen };
                     } catch (err) {
                         console.error('Failed to decrypt friend state', p.id, err);
                         return null;
diff --git a/src/image.png b/src/image.png
index 5673c87..022472e 100644
Binary files a/src/image.png and b/src/image.png differ
diff --git a/src/index.html b/src/index.html
index e5e56d3..cbd1e99 100644
--- a/src/index.html
+++ b/src/index.html
@@ -39,7 +39,8 @@
             <input id="self-color-input" name="selfColor" type="color" />
             <button id="dark-mode-toggle" class="dark-mode-toggle" type="button"
                 aria-label="Toggle dark mode">🌙</button>
-            <button id="clean-mode-toggle" class="clean-mode-toggle" type="button" aria-pressed="false">Clean</button>
+            <button id="clean-mode-toggle" class="clean-mode-toggle" type="button"
+                aria-pressed="false">Fullscreen</button>
         </div>
         <div class="controls-row controls-row-secondary">
             <button id="calibrate-heading-link" class="friends-toggle" type="button">Compass</button>
@@ -71,6 +72,9 @@
                 icons created by Icongeek26 - Flaticon</a>
             <a href="https://www.flaticon.com/free-icons/arrow" title="arrow icons">Arrow icons created by Freepik -
                 Flaticon</a>
+            <a href="https://www.flaticon.com/free-icons/multimedia-option" title="multimedia option icons">Multimedia
+                option icons
+                created by Icongeek26 - Flaticon</a>
         </p>
     </div>
     <script src="app.ts" type="module"></script>
diff --git a/src/utils.ts b/src/utils.ts
index 113281b..d569125 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -44,7 +44,7 @@ export type PresenceThresholds = {
 };
 
 export const getFriendPresenceState = (friend, now: number, thresholds: PresenceThresholds): 'online' | 'recent-offline' | 'stale-offline' => {
-    const friendTimestamp = Number(friend.timestamp);
+    const friendTimestamp = Number(friend.lastSeen ?? friend.timestamp);
     if (!Number.isFinite(friendTimestamp)) return 'stale-offline';
     const ageMs = Math.max(0, now - friendTimestamp);
     if (ageMs <= thresholds.onlineGraceMs) return 'online';