← Commit history

Cache-bust all freshened images to -v2 names (in-place /files blobs were cache-shadowing the old versions in README embeds): arch-flow, core-vs-bridge, settings, 4 toasts

John Lauer ·0166663162 ·2mo ago ·parent 160d962
8 files changed +264−7
README.md+7−7
@@ -14,7 +14,7 @@  ## How it works -![Architecture](docs/arch-flow.svg)+![Architecture](docs/arch-flow-v2.svg)  The cloud AI never touches your machine directly. It sends a verb to the **relay**; Adom Bridge, connected out to that relay from your desktop, executes it against Windows or forwards it to a bridge, and streams the result back. A co-resident sibling app (Hydrogen) can skip the relay and POST straight to the **loopback HTTP API** at `127.0.0.1`. @@ -189,7 +189,7 @@ These verbs inspect any icon you pass and return an `iconCheck` that explains, i  ## Settings -<img src="docs/settings.png" alt="Settings" width="780">+<img src="docs/settings-v2.png" alt="Settings" width="780">  Auto-connect behavior, the update channel (**prompt** / auto / off) and *restart when idle to finish updates*, the shell-approval preference, Hydrogen integration (including *exit when Hydrogen exits*), and runtime prewarming. While embedded in Hydrogen, Hydrogen-owned preferences show as *managed by Hydrogen*. @@ -209,7 +209,7 @@ Adom Bridge speaks to you through native Windows toasts via `notify_user`, under  **Basic alert.** Awareness: a build finished, a file is ready. Auto-dismisses in about 7 seconds. Add `"durationLong":true` to hold it around 25 seconds; `"level":"error"` and up do that automatically, and `"emergency"` also flashes the taskbar. -![Basic alert toast](docs/toast-basic.png)+![Basic alert toast](docs/toast-basic-v2.png)  ```bash adom-bridge-cli notify_user '{"title":"Export done","body":"gerbers.zip is ready in C:/exports."}'@@ -225,7 +225,7 @@ The response says whether the target resolved, so the AI finds out at send time  **Sticky choice with buttons that round-trip.** Stays on screen until the user clicks (no auto-dismiss). Give it an `id` you choose, then read the click back. -![Sticky toast with buttons](docs/toast-buttons.png)+![Sticky toast with buttons](docs/toast-buttons-v2.png)  ```bash adom-bridge-cli notify_user '{"id":"deploy-42","title":"Ship v2 to production?","body":"The build is green and staged.","scenario":"reminder","buttons":[{"label":"Ship it"},{"label":"Hold"}]}'@@ -233,7 +233,7 @@ adom-bridge-cli notify_user '{"id":"deploy-42","title":"Ship v2 to production?",  **Progress bar.** For a long job (a gerber export, a render). Re-fire with the SAME `id` as the job advances toward `1.0`. `body` is optional here. -![Progress bar toast](docs/toast-progress.png)+![Progress bar toast](docs/toast-progress-v2.png)  ```bash adom-bridge-cli notify_user '{"id":"job-1","title":"Exporting gerbers","progress":{"title":"myboard.kicad_pcb","value":0.6,"status":"Plotting copper layers...","valueOverride":"6 / 10 layers"}}'@@ -241,7 +241,7 @@ adom-bridge-cli notify_user '{"id":"job-1","title":"Exporting gerbers","progress  **Reply input.** The text field renders, but Windows does not return typed text over protocol activation, so it is display-only today. For a real choice, use buttons. -![Reply input toast](docs/toast-input.png)+![Reply input toast](docs/toast-input-v2.png)  ```bash adom-bridge-cli notify_user '{"title":"Quick note","body":"Leave a note for the next run.","scenario":"reminder","inputs":[{"id":"reply","type":"text","placeholder":"Type a reply..."}],"buttons":[{"label":"Send"}]}'@@ -269,7 +269,7 @@ Deep dive: [notifications](docs/notifications.md).  ## Verbs -![Core vs bridge verbs](docs/core-vs-bridge.svg)+![Core vs bridge verbs](docs/core-vs-bridge-v2.svg)  Adom Bridge core owns the generic verbs (`desktop_*`, `shell`, `ui_*`, files, `notify_user`, multi-machine). Each bridge owns its own prefix and ships its own verbs; the app relays them verbatim and stays generic. Invoke the same way on every transport, for identical JSON back: 
docs/arch-flow-v2.svgadded+161
@@ -0,0 +1,161 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 1440" font-family="'Familjen Grotesk','Satoshi',-apple-system,'Segoe UI',sans-serif">+  <defs>+    <marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">+      <path d="M0 0 L10 5 L0 10 z" fill="#2dd4bf"/>+    </marker>+    <marker id="arrUp" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">+      <path d="M0 0 L10 5 L0 10 z" fill="#64748b"/>+    </marker>+    <style>+      .box{rx:14;stroke-width:1.5}+      .h{fill:#e2e8f0;font-weight:700}+      .t{fill:#94a3b8;font-size:14px}+      .mono{font-family:'JetBrains Mono',ui-monospace,monospace;fill:#5eead4;font-size:12.5px}+      .lbl{fill:#64748b;font-size:12px;font-style:italic}+      .tier{fill:#2dd4bf;font-size:12px;font-weight:700;letter-spacing:2px}+    </style>+  </defs>++  <rect x="0" y="0" width="1120" height="1440" fill="#0b0f14"/>+  <text x="560" y="46" text-anchor="middle" class="h" font-size="26">Adom Bridge — how it works</text>+  <text x="560" y="72" text-anchor="middle" class="t">One local bridge between Adom's cloud AI and your Windows machine · v2.0.7</text>++  <!-- TIER 1: CLOUD -->+  <rect x="360" y="100" width="400" height="72" rx="14" fill="#0e1a2b" stroke="#1e3a5f"/>+  <text x="560" y="132" text-anchor="middle" class="h" font-size="16">Adom Cloud — Claude Code / AI</text>+  <text x="560" y="154" text-anchor="middle" class="t">runs in your local container: WSL2 (Windows) / Lima (macOS) via Hydrogen — Docker cloud later</text>++  <!-- arrow 1->2 -->+  <line x1="560" y1="172" x2="560" y2="212" stroke="#2dd4bf" stroke-width="2" marker-end="url(#arr)"/>+  <line x1="600" y1="212" x2="600" y2="172" stroke="#64748b" stroke-width="1.3" marker-end="url(#arrUp)"/>+  <text x="620" y="196" class="lbl">commands, files, notifications ⇅ results</text>++  <!-- TIER 2: RELAY -->+  <rect x="300" y="216" width="520" height="86" rx="14" fill="#101826" stroke="#334155"/>+  <text x="560" y="246" text-anchor="middle" class="h" font-size="16">Adom Relay  ·  Hydrogen-managed (local) or cloud (e.g. galliaApril)</text>+  <text x="560" y="268" text-anchor="middle" class="t">routes by <tspan class="mono">clientName</tspan> — one relay ⇄ many desktops</text>+  <text x="560" y="288" text-anchor="middle" class="mono">--target &lt;name&gt;  ·  --target all  ·  ambiguous_target guard</text>++  <!-- arrow 2->3 -->+  <line x1="560" y1="302" x2="560" y2="344" stroke="#2dd4bf" stroke-width="2" marker-end="url(#arr)"/>+  <text x="580" y="328" class="lbl">WebSocket wss://  (auth: clientName + token, 15s keepalive)</text>++  <!-- TIER 3: ADOM BRIDGE -->+  <rect x="40" y="348" width="1040" height="516" rx="18" fill="#0d1420" stroke="#2dd4bf" stroke-width="2"/>+  <text x="64" y="384" class="h" font-size="19">ADOM BRIDGE</text>+  <text x="235" y="384" class="t">Tauri v2 · Rust · signed · runs in your tray</text>++  <!-- INBOUND column -->+  <text x="70" y="420" class="tier">▸ WHAT CONNECTS TO BRIDGE</text>+  <g>+    <rect x="70" y="432" width="470" height="70" rx="10" fill="#111c2e" stroke="#1e3a5f"/>+    <text x="86" y="458" class="h" font-size="14">Relay WS client</text>+    <text x="86" y="480" class="t">the cloud path — ws_client.rs, auto-reconnect &lt;5s</text>+    <text x="86" y="496" class="mono">wss:// → relay → cloud AI</text>++    <rect x="70" y="510" width="470" height="70" rx="10" fill="#111c2e" stroke="#1e3a5f"/>+    <text x="86" y="536" class="h" font-size="14">Direct HTTP API</text>+    <text x="86" y="558" class="t">sibling apps (Hydrogen) + the CLI's auto-route</text>+    <text x="86" y="574" class="mono">127.0.0.1:47200  (host.docker.internal:47200 from Hydrogen's container)</text>++    <rect x="70" y="588" width="470" height="70" rx="10" fill="#111c2e" stroke="#1e3a5f"/>+    <text x="86" y="614" class="h" font-size="14">Control API — sugar routes</text>+    <text x="86" y="636" class="t">Hydrogen drives embedded mode + Bridge's auto-update</text>+    <text x="86" y="652" class="mono">POST /embedded/enter·release   /update/status·check·apply</text>++    <rect x="70" y="666" width="470" height="70" rx="10" fill="#111c2e" stroke="#1e3a5f"/>+    <text x="86" y="692" class="h" font-size="14">TCP tunnels + RDP</text>+    <text x="86" y="714" class="t">reach a cloud-only service through the laptop</text>+    <text x="86" y="730" class="mono">127.0.0.1:&lt;port&gt; ⇄ relay ⇄ upstream   ·  tunnel open|rdp</text>+  </g>++  <!-- OUTBOUND column -->+  <text x="586" y="420" class="tier">▸ WHAT BRIDGE DRIVES</text>+  <g>+    <rect x="586" y="432" width="470" height="150" rx="10" fill="#0f1d1a" stroke="#134e4a"/>+    <text x="602" y="458" class="h" font-size="14">Your Windows OS  ·  core verbs</text>+    <text x="602" y="482" class="mono">shell / run_script / wsl_exec</text>+    <text x="602" y="502" class="mono">send_files · pull_file</text>+    <text x="602" y="522" class="mono">screenshot_window · screenshot_screen</text>+    <text x="602" y="542" class="mono">ui_click · click · type · press_key (UIA + SendInput)</text>+    <text x="602" y="562" class="mono">notify_user (toasts) · tray · caption · taskbar</text>++    <rect x="586" y="590" width="470" height="68" rx="10" fill="#0f1d1a" stroke="#134e4a"/>+    <text x="602" y="616" class="h" font-size="14">Managed runtimes  ·  no UAC, no firewall</text>+    <text x="602" y="638" class="t">Bridge provisions Node + Python for bridges</text>+    <text x="602" y="654" class="mono">system-first, else portable download → ~/.adom/adom-runtimes</text>++    <rect x="586" y="666" width="470" height="70" rx="10" fill="#0f1d1a" stroke="#134e4a"/>+    <text x="602" y="692" class="h" font-size="14">Bridges  ·  spawned children</text>+    <text x="602" y="714" class="t">routed by verb prefix — HTTP on a stable internal port</text>+    <text x="602" y="730" class="mono">127.0.0.1:&lt;ephemeral&gt;  ·  ADOM_BIND_HOST=127.0.0.1</text>+  </g>++  <!-- arrow 3->4 -->+  <line x1="820" y1="736" x2="820" y2="792" stroke="#2dd4bf" stroke-width="2" marker-end="url(#arr)"/>+  <text x="840" y="770" class="lbl">spawns + supervises · stable port · auto-update from the wiki</text>++  <!-- TIER 4: BRIDGES -->+  <text x="70" y="912" class="tier">▸ BRIDGES  (each ships its own verbs; see the core-vs-bridge diagram)</text>+  <g font-size="13">+    <!-- pup -->+    <rect x="40" y="928" width="200" height="118" rx="12" fill="#101826" stroke="#334155"/>+    <text x="58" y="954" class="h">pup</text>+    <text x="58" y="974" class="t">Node · cloud-owned</text>+    <text x="58" y="996" class="t" font-size="12">drives a fresh</text>+    <text x="58" y="1012" class="t" font-size="12">automation browser</text>+    <text x="58" y="1034" class="mono" font-size="11">pup_*</text>++    <!-- kicad -->+    <rect x="256" y="928" width="200" height="118" rx="12" fill="#101826" stroke="#334155"/>+    <text x="274" y="954" class="h">KiCad</text>+    <text x="274" y="974" class="t">Python · cloud-owned</text>+    <text x="274" y="996" class="t" font-size="12">7/8/9/10 side-by-side</text>+    <text x="274" y="1012" class="t" font-size="12">EDA automation</text>+    <text x="274" y="1034" class="mono" font-size="11">kicad_*</text>++    <!-- fusion -->+    <rect x="472" y="928" width="200" height="118" rx="12" fill="#101826" stroke="#334155"/>+    <text x="490" y="954" class="h">Fusion 360</text>+    <text x="490" y="974" class="t">Python · cloud-owned</text>+    <text x="490" y="996" class="t" font-size="12">CAD + EAGLE PCB</text>+    <text x="490" y="1012" class="t" font-size="12">+ APS cloud search</text>+    <text x="490" y="1034" class="mono" font-size="11">fusion_* · aps_*</text>++    <!-- native-browser -->+    <rect x="688" y="928" width="200" height="118" rx="12" fill="#101826" stroke="#334155"/>+    <text x="706" y="954" class="h">Native browser (nb)</text>+    <text x="706" y="974" class="t">nbe extension · cloud-owned</text>+    <text x="706" y="996" class="t" font-size="12">your REAL Chrome/Edge</text>+    <text x="706" y="1012" class="t" font-size="12">— logged-in sessions</text>+    <text x="706" y="1034" class="mono" font-size="11">nbrowser_*</text>++    <!-- hd -->+    <rect x="904" y="928" width="176" height="118" rx="12" fill="#101826" stroke="#334155"/>+    <text x="922" y="954" class="h">Hydrogen</text>+    <text x="922" y="974" class="t">external-http</text>+    <text x="922" y="996" class="t" font-size="12">proxies Hydrogen's</text>+    <text x="922" y="1012" class="t" font-size="12">control API</text>+    <text x="922" y="1034" class="mono" font-size="11">hd_*</text>+  </g>+  <text x="40" y="1076" class="t" font-size="13">+ third-party bridges installed with <tspan class="mono">bridge_install {manifestUrl}</tspan> — same contract, auto-updated from their own wiki page.</text>++  <!-- ENDPOINTS LEGEND -->+  <rect x="40" y="1110" width="1040" height="290" rx="16" fill="#0d1420" stroke="#334155"/>+  <text x="64" y="1146" class="h" font-size="17">Exposed endpoints (all loopback / localhost only)</text>+  <g font-size="13">+    <text x="64" y="1182" class="mono" font-size="14">127.0.0.1:47200</text>+    <text x="330" y="1182" class="t">Direct HTTP API — <tspan class="mono" font-size="12">POST /command</tspan>, <tspan class="mono" font-size="12">GET /status</tspan>, <tspan class="mono" font-size="12">GET /ping</tspan>. Sibling apps + the CLI auto-route here.</text>+    <text x="64" y="1214" class="mono" font-size="14">127.0.0.1:47200</text>+    <text x="330" y="1214" class="t">Control sugar — <tspan class="mono" font-size="12">/embedded/enter·release</tspan>, <tspan class="mono" font-size="12">/update/status·check·apply</tspan>. Hydrogen drives these.</text>+    <text x="64" y="1246" class="mono" font-size="14">127.0.0.1:47210</text>+    <text x="330" y="1246" class="t">ad-relauncher HTTP — swap-binary-and-restart state (dev/update path).</text>+    <text x="64" y="1278" class="mono" font-size="14">127.0.0.1:&lt;stable&gt;</text>+    <text x="330" y="1278" class="t">Per-bridge HTTP — internal, persisted to <tspan class="mono" font-size="12">~/.adom/bridge-ports.json</tspan>. Callers never touch it; go through verbs.</text>+    <text x="64" y="1310" class="mono" font-size="14">127.0.0.1:&lt;dynamic&gt;</text>+    <text x="330" y="1310" class="t">Tunnel listeners — one per open tunnel; bytes pumped over the relay WS to a cloud-side upstream.</text>+    <text x="64" y="1342" class="mono" font-size="14">wss:// (outbound)</text>+    <text x="330" y="1342" class="t">Relay client — Bridge dials OUT to the cloud relay; nothing inbound from the internet. Discovery file: <tspan class="mono" font-size="12">~/.adom/direct-api-port</tspan>.</text>+    <text x="64" y="1378" class="lbl" font-size="12.5">Ports are picked ephemerally and written to discovery files — never hardcoded (Hyper-V/Docker silently reserve fixed ranges). See skills/PORTS.md.</text>+  </g>+</svg>
docs/core-vs-bridge-v2.svgadded+96
@@ -0,0 +1,96 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 900" font-family="'Familjen Grotesk','Satoshi',-apple-system,'Segoe UI',sans-serif">+  <defs>+    <marker id="a2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">+      <path d="M0 0 L10 5 L0 10 z" fill="#2dd4bf"/>+    </marker>+    <style>+      .h{fill:#e2e8f0;font-weight:700}+      .t{fill:#94a3b8;font-size:13px}+      .mono{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:12.5px}+      .tier{font-size:12px;font-weight:700;letter-spacing:2px}+    </style>+  </defs>+  <rect x="0" y="0" width="1120" height="900" fill="#0b0f14"/>+  <text x="560" y="46" text-anchor="middle" class="h" font-size="25">Core verbs vs bridge verbs — the line of demarcation</text>+  <text x="560" y="72" text-anchor="middle" class="t">Bridge OWNS + IMPLEMENTS core verbs. For bridge verbs, Bridge is a transparent RELAY — it routes by prefix and forwards args verbatim.</text>++  <!-- CORE side -->+  <rect x="40" y="100" width="480" height="710" rx="18" fill="#0f1d1a" stroke="#134e4a" stroke-width="2"/>+  <text x="64" y="138" class="tier" fill="#2dd4bf">▸ BRIDGE CORE  (Bridge implements these)</text>+  <text x="64" y="162" class="t">Built into the Tauri app. Touch the OS directly. Gated verbs need shell-approval.</text>++  <g class="mono" fill="#5eead4">+    <text x="64" y="200" class="h" font-size="14" fill="#e2e8f0">Desktop / OS</text>+    <text x="64" y="224">desktop_list_windows · screenshot_window · screenshot_screen</text>+    <text x="64" y="246">desktop_click · type · press_key · hover · cursor  (SendInput)</text>+    <text x="64" y="268">desktop_ui_click · ui_set · find_control · ui_tree  (UIA)</text>+    <text x="64" y="290">desktop_open_url · open_folder · bring_to_front · find_window</text>+    <text x="64" y="312">caption · taskbar · flash_window · display</text>++    <text x="64" y="352" class="h" font-size="14" fill="#e2e8f0">Shell / scripts  (gated)</text>+    <text x="64" y="376">shell_execute · run_script · wsl_exec · wsl_exec_async</text>+    <text x="64" y="398">wsl_recover · wsl_import · wsl_export · wsl_list</text>++    <text x="64" y="438" class="h" font-size="14" fill="#e2e8f0">Files</text>+    <text x="64" y="462">send_files · pull_file</text>++    <text x="64" y="502" class="h" font-size="14" fill="#e2e8f0">Notify / approvals</text>+    <text x="64" y="526">notify_user · notify_response · shell_auto_approve · revoke_approvals</text>++    <text x="64" y="566" class="h" font-size="14" fill="#e2e8f0">Connectivity</text>+    <text x="64" y="590">server_add · server_list · targets · tunnel (open|rdp|check)</text>++    <text x="64" y="630" class="h" font-size="14" fill="#e2e8f0">Bridge lifecycle  (Bridge manages the bridges)</text>+    <text x="64" y="654">bridge_install · bridge_list · bridge_info · bridge_kill</text>+    <text x="64" y="676">refresh_bridges · bridge_check_updates · restart_bridge · runtimes</text>++    <text x="64" y="716" class="h" font-size="14" fill="#e2e8f0">Sibling apps</text>+    <text x="64" y="740">aps_* (Autodesk cloud OAuth — Bridge-native) · timeouts · commands</text>+  </g>+  <text x="64" y="784" class="t" font-size="12">These never leave Bridge — no bridge involved. Bridge authors their result + <tspan class="mono">_hint</tspan>.</text>++  <!-- THE LINE -->+  <line x1="560" y1="110" x2="560" y2="800" stroke="#334155" stroke-width="2" stroke-dasharray="6 6"/>+  <rect x="500" y="420" width="120" height="60" rx="10" fill="#0b0f14" stroke="#2dd4bf"/>+  <text x="560" y="446" text-anchor="middle" class="h" font-size="13">route by</text>+  <text x="560" y="466" text-anchor="middle" class="mono" fill="#5eead4" font-size="13">verbPrefix</text>++  <!-- BRIDGE side -->+  <rect x="600" y="100" width="480" height="710" rx="18" fill="#101826" stroke="#334155" stroke-width="2"/>+  <text x="624" y="138" class="tier" fill="#93c5fd">▸ BRIDGE VERBS  (the bridge implements these)</text>+  <text x="624" y="162" class="t">Bridge forwards the FULL args object verbatim to the bridge over HTTP. Bridge never</text>+  <text x="624" y="180" class="t">strips, reshapes, or interprets them — the bridge validates + owns its verbs.</text>++  <g>+    <rect x="624" y="200" width="432" height="86" rx="10" fill="#0d1420" stroke="#334155"/>+    <text x="642" y="226" class="h" font-size="14">pup  ·  cloud-owned</text>+    <text x="642" y="248" class="mono" fill="#93c5fd">pup_open_window · navigate · eval · screenshot · record_*</text>+    <text x="642" y="270" class="t">→ a fresh Chrome-for-Testing (or your Edge) automation browser</text>++    <rect x="624" y="298" width="432" height="86" rx="10" fill="#0d1420" stroke="#334155"/>+    <text x="642" y="324" class="h" font-size="14">KiCad  ·  cloud-owned</text>+    <text x="642" y="346" class="mono" fill="#93c5fd">kicad_open_board · install_symbol · run_drc · export_*</text>+    <text x="642" y="368" class="t">→ KiCad 7/8/9/10 side-by-side</text>++    <rect x="624" y="396" width="432" height="86" rx="10" fill="#0d1420" stroke="#334155"/>+    <text x="642" y="422" class="h" font-size="14">Fusion 360  ·  cloud-owned</text>+    <text x="642" y="444" class="mono" fill="#93c5fd">fusion_start · import_step · export_gerbers · board_info · walk_cloud_tree</text>+    <text x="642" y="466" class="t">→ Fusion 360 CAD + EAGLE electronics</text>++    <rect x="624" y="494" width="432" height="86" rx="10" fill="#0d1420" stroke="#334155"/>+    <text x="642" y="520" class="h" font-size="14">Native browser (nb)  ·  cloud-owned (nbe extension)</text>+    <text x="642" y="542" class="mono" fill="#93c5fd">nbrowser_open · nbrowser_eval · nbrowser_status</text>+    <text x="642" y="564" class="t">→ your REAL logged-in Chrome / Edge</text>++    <rect x="624" y="592" width="432" height="70" rx="10" fill="#0d1420" stroke="#334155"/>+    <text x="642" y="618" class="h" font-size="14">Hydrogen  ·  external-http</text>+    <text x="642" y="640" class="mono" fill="#93c5fd">hd_status · hd_api · hd_launch · hd_ship</text>+    <text x="642" y="656" class="t">→ relays HD's own control API</text>++    <rect x="624" y="672" width="432" height="88" rx="10" fill="#0d1420" stroke="#334155"/>+    <text x="642" y="698" class="h" font-size="14">Third-party  ·  bridge_install</text>+    <text x="642" y="720" class="mono" fill="#93c5fd">&lt;prefix&gt;_*   (blender_* · rdp_* · anything you publish)</text>+    <text x="642" y="742" class="t">→ same contract; declares detect / timeouts / statusVerb in bridge.json</text>+  </g>+  <text x="624" y="792" class="t" font-size="12">A bridge adds/renames args with ZERO Bridge change. See skills/BRIDGE_SDK.md.</text>+</svg>
docs/settings-v2.pngadded
⋯ 1 unchanged line ⋯
docs/toast-basic-v2.pngadded
⋯ 1 unchanged line ⋯
docs/toast-buttons-v2.pngadded
⋯ 1 unchanged line ⋯
docs/toast-input-v2.pngadded
⋯ 1 unchanged line ⋯
docs/toast-progress-v2.pngadded
⋯ 1 unchanged line ⋯