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 | // Draws the app's icons from the g1t mark (packages/theme/mark.svg): |
| 2 | // `npm run icons -w @g1t/mobile` after the mark or the background changes. | |
| 3 | // | |
| 4 | // - icon.png: the store and iOS icon, the mark on g1t's background. | |
| 5 | // - android-icon-foreground.png: the adaptive icon's mark, inside the | |
| 6 | // middle 66% Android keeps whatever the launcher's mask. | |
| 7 | // - android-icon-monochrome.png: the same in white, for themed icons. | |
| 8 | // - splash-icon.png: the mark alone, on the splash screen's background. | |
| 9 | import { readFile } from "node:fs/promises"; | |
| 10 | import { fileURLToPath } from "node:url"; | |
| 11 | import sharp from "sharp"; | |
| 12 | ||
| 13 | const here = (path) => fileURLToPath(new URL(path, import.meta.url)); | |
| 14 | const mark = await readFile(here("../../../packages/theme/mark.svg"), "utf8"); | |
| 15 | const BACKGROUND = "#0f0f11"; | |
| 16 | ||
| 17 | /** The mark at `scale` of a `size` square, recoloured, on `background` or nothing. */ | |
| 18 | async function draw(file, { size, scale, color, background }) { | |
| 19 | const inner = Math.round(size * scale); | |
| 20 | const svg = Buffer.from(mark.replace(/#b6a8ff/g, color ?? "#b6a8ff").replace("<svg ", `<svg width="${inner}" height="${inner}" `)); | |
| 21 | const glyph = await sharp(svg, { density: 72 * (inner / 80) }).resize(inner, inner).png().toBuffer(); | |
| 22 | await sharp({ create: { width: size, height: size, channels: 4, background: background ?? { r: 0, g: 0, b: 0, alpha: 0 } } }) | |
| 23 | .composite([{ input: glyph, gravity: "centre" }]) | |
| 24 | .png() | |
| 25 | .toFile(here(`../assets/images/${file}`)); | |
| 26 | } | |
| 27 | ||
| 28 | await draw("icon.png", { size: 1024, scale: 0.62, background: BACKGROUND }); | |
| 29 | await draw("android-icon-foreground.png", { size: 1024, scale: 0.46 }); | |
| 30 | await draw("android-icon-monochrome.png", { size: 1024, scale: 0.46, color: "#ffffff" }); | |
| 31 | await draw("splash-icon.png", { size: 512, scale: 0.9 }); | |
| 32 | console.log("Drew icon.png, android-icon-foreground.png, android-icon-monochrome.png and splash-icon.png."); |