Skip to content
20 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

The phone app's scaffolding, in apps/mobile: Expo SDK 57 with Expo Router, Android first, with Chat, Code and Customize. It signs in with g1t's own OAuth 2.1 (PKCE, a client id that encodes "g1t for Android" and g1t://oauth/callback, so nothing is registered), keeps the server and credentials in the phone's keystore, refreshes the 30-day token a minute early and shares the single-use refresh between requests. A personal access token is the other way in, and a self-hosted g1t the other server.1/** "now", "5m", "3h", "2d", or a date, for lists. */
2export function ago(iso: string, now = Date.now()): string {
3 const then = Date.parse(iso);
4 if (Number.isNaN(then)) return "";
5 const seconds = Math.max(0, Math.round((now - then) / 1000));
6 if (seconds < 60) return "now";
7 const minutes = Math.round(seconds / 60);
8 if (minutes < 60) return `${minutes}m`;
9 const hours = Math.round(minutes / 60);
10 if (hours < 24) return `${hours}h`;
11 const days = Math.round(hours / 24);
12 if (days < 7) return `${days}d`;
13 return new Date(then).toLocaleDateString(undefined, { month: "short", day: "numeric" });
14}
15
16/** A message's time of day: "14:05". */
17export function clock(iso: string): string {
18 const date = new Date(iso);
19 return Number.isNaN(date.getTime()) ? "" : date.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" });
20}