Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
64dc0a8
Migrate nym shim binding generation from zingolib
dorianvp Jul 31, 2026
5aa621e
chore: draft changes for nym integration from zingolib
dorianvp Aug 1, 2026
d1b66f3
chore: ui fixes
dorianvp Aug 2, 2026
f22576f
chore: ios perf fixes
dorianvp Aug 4, 2026
b4ae844
chore: update Orchard mentions to Ironwood
dorianvp Aug 4, 2026
380d9dd
chore: nym toggle feedback
dorianvp Aug 4, 2026
5f20f34
fix: animation status bar continuity
dorianvp Aug 4, 2026
1a61a83
chore: fix NYM edge cases
dorianvp Aug 6, 2026
58d4532
fix: animations, network states, and icons
dorianvp Aug 6, 2026
c7918b1
fix: iOS podfile min 16
juanky201271 Aug 7, 2026
8c1b389
fix: Android quickstart & script improvement
juanky201271 Aug 7, 2026
bcbb2a5
Merge branch 'dev' into migrate-nym-bindgen
juanky201271 Aug 7, 2026
828e33a
fix: update receiver types and onload nym config
dorianvp Aug 10, 2026
ff9fb8b
Merge branch 'dev' into migrate-nym-bindgen
dorianvp Aug 10, 2026
9ac4ba7
fix: some ADR and eslint config issues
dorianvp Aug 10, 2026
602d94d
fix: move nym to network section
dorianvp Aug 10, 2026
ee3c0d6
fix: value transfer types when sending
dorianvp Aug 10, 2026
f7f05aa
chore: re-enable private migration
dorianvp Aug 10, 2026
1b6ba3e
chore: route the private path through nym too
dorianvp Aug 10, 2026
0d84ddf
chore: use latest zingolib
dorianvp Aug 10, 2026
b817395
fix: broad visual fixes & new colors
dorianvp Aug 11, 2026
5bd8fc4
test: setup storybook
dorianvp Aug 11, 2026
dc15e7c
feat(visual): deploy review site to Cloudflare Pages + Current tab
dorianvp Aug 11, 2026
ca7e479
docs: add readmes and instructions for Cloudflare-related topics
dorianvp Aug 11, 2026
7c509a9
chore: add more components & some UI fixes
dorianvp Aug 11, 2026
f906743
fix: visual ci issues
dorianvp Aug 11, 2026
6de02fc
chore(cloudflare): delete-on-merge
dorianvp Aug 11, 2026
51f8d37
chore: local-only visualizer
dorianvp Aug 11, 2026
635d20b
refactor: rename components/Components to components/ui
dorianvp Aug 11, 2026
b516412
refactor: split shared UI into ui/primitives and ui/widgets
dorianvp Aug 11, 2026
f93d357
refactor: rename components/ to screens/ and gather runtime into app/
dorianvp Aug 12, 2026
feafe73
chore: apply aliases
dorianvp Aug 12, 2026
c9bdea3
fix: storybook imports
dorianvp Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
37 changes: 37 additions & 0 deletions .github/CLOUDFLARE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Cloudflare Pages deploy

The workflows send the web Storybook and the pull request reports to Cloudflare
Pages. `deploy-storybook.yaml` sends the Storybook. `visual-review.yaml` sends
each report.

## Setup

Do these steps one time.

1. Make the Pages project:

```
npx wrangler pages project create zingo-visual --production-branch=production
```

2. Get the account ID from the Cloudflare dashboard. Or run `npx wrangler whoami`.

3. Make an API token. Give the token the `Cloudflare Pages: Edit` permission.

4. Add two secrets to the GitHub repository:

- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`

## Links

- The `dev` build: `https://zingo-visual.pages.dev`
- Each pull request: `https://pr-<number>.zingo-visual.pages.dev`

## Notes

- Keep the token secret. Do not put the token in a file.
- A fork pull request cannot read the secrets. The deploy step stops, but you
still get the report as an artifact.
- When a pull request closes, a workflow deletes all its preview deployments.
- To make the pages private, use Cloudflare Access.
49 changes: 49 additions & 0 deletions .github/workflows/deploy-storybook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Deploy Storybook

# On every push to dev, publishes the interactive web Storybook to the
# Cloudflare Pages production URL — a stable link for browsing the current
# components. Per-PR reports are preview deploys of the same project.

on:
push:
branches: [dev]
paths:
- 'components/**'
- 'app/theme/**'
- 'app/AppState/**'
- '.storybook-web/**'
- 'assets/**'

permissions:
contents: read

concurrency:
group: deploy-storybook
cancel-in-progress: true

jobs:
deploy:
name: Deploy Storybook
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7

- uses: actions/setup-node@v4
with:
node-version: 22.18.0
cache: yarn

- run: yarn

- run: yarn build-storybook

- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: >-
pages deploy storybook-static
--project-name=zingo-visual
--branch=production
66 changes: 66 additions & 0 deletions .github/workflows/visual-review-cleanup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Visual review cleanup

# When a PR closes (merged or not), delete every Cloudflare Pages preview
# deployment on its pr-<n> branch — all per-commit deploys, latest included.

on:
pull_request:
types: [closed]

permissions:
contents: read

concurrency:
group: visual-review-cleanup-${{ github.event.number }}
cancel-in-progress: false

jobs:
cleanup:
name: Delete PR previews
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Delete Cloudflare Pages deployments for this PR
env:
CF_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
PROJECT: zingo-visual
BRANCH: pr-${{ github.event.number }}
run: |
set -euo pipefail
api="https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${PROJECT}/deployments"
auth="Authorization: Bearer ${CF_API_TOKEN}"

# Collect matching ids across all pages first; deleting mid-paginate
# shifts the list and skips entries.
ids=""
page=1
while :; do
resp=$(curl -sS -H "$auth" "${api}?page=${page}&per_page=25")
if [ "$(echo "$resp" | jq -r '.success')" != "true" ]; then
echo "::error::Cloudflare list failed: $(echo "$resp" | jq -c '.errors')"
exit 1
fi
[ "$(echo "$resp" | jq '.result | length')" -eq 0 ] && break
match=$(echo "$resp" | jq -r --arg b "$BRANCH" \
'.result[] | select(.deployment_trigger.metadata.branch == $b) | .id')
ids="${ids} ${match}"
page=$((page + 1))
done

deleted=0
failed=0
for id in $ids; do
code=$(curl -sS -o /dev/null -w '%{http_code}' -X DELETE \
-H "$auth" "${api}/${id}?force=true")
if [ "$code" = "200" ]; then
deleted=$((deleted + 1))
else
echo "::warning::delete ${id} returned HTTP ${code}"
failed=$((failed + 1))
fi
done

echo "Deleted ${deleted} preview deployment(s) for ${BRANCH} (${failed} failed)."
[ "$failed" -eq 0 ]
157 changes: 157 additions & 0 deletions .github/workflows/visual-review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Visual review

# Builds this PR and its base branch on the same runner, captures both with
# the web Storybook harness, and diffs head vs base — no committed baseline.
# The report (visual/ci) is uploaded as an artifact and the result posted to
# the PR. The check fails when a component or animation changed.

on:
pull_request:
paths:
- 'screens/**'
- 'ui/**'
- 'app/theme/**'
- 'app/AppState/**'
- '.storybook-web/**'
- 'visual/**'
- 'assets/**'

permissions:
contents: read
pull-requests: write

# Cancel a superseded run when the PR gets a new push.
concurrency:
group: visual-review-${{ github.ref }}
cancel-in-progress: true

jobs:
visual-review:
name: Visual review
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout PR head
uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22.18.0
cache: yarn

- run: yarn

- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('yarn.lock') }}

- name: Install Playwright Chromium
run: yarn playwright install --with-deps chromium

- name: Capture PR head
run: VISUAL_OUT=visual/ci/head yarn visual:snapshot

# Base uses its own checked-out harness (works once this lands on the
# base branch). Until then — or on any base hiccup — this is a clean
# no-op and the diff below treats every story as new.
- name: Capture base (${{ github.base_ref }})
continue-on-error: true
run: |
git fetch origin "$BASE" --depth=1
git worktree add "$RUNNER_TEMP/base" "origin/$BASE"
ln -s "$GITHUB_WORKSPACE/node_modules" "$RUNNER_TEMP/base/node_modules"
if grep -q '"visual:snapshot"' "$RUNNER_TEMP/base/package.json"; then
( cd "$RUNNER_TEMP/base" \
&& VISUAL_OUT="$GITHUB_WORKSPACE/visual/ci/base" yarn visual:snapshot ) \
|| echo "::warning::base capture failed — every story reads as new"
else
echo "::notice::base branch has no visual harness yet — every story reads as new"
fi
env:
BASE: ${{ github.base_ref }}

# The head build is still in storybook-static (base built in its own
# worktree). Ship it alongside the report so the Current tab embeds it.
- name: Assemble Current view
run: cp -r storybook-static visual/ci/storybook

- name: Diff head vs base
id: diff
continue-on-error: true
run: >-
VISUAL_CURRENT=visual/ci/head
VISUAL_BASELINE=visual/ci/base
VISUAL_REPORT=visual/ci/index.html
VISUAL_STORYBOOK=storybook/index.html
yarn tsx visual/diff.mts

- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: visual-review
path: visual/ci

# Fork PRs can't read secrets, so this fails there (artifact still up).
- name: Deploy report to Cloudflare Pages
id: deploy
if: always()
continue-on-error: true
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: >-
pages deploy visual/ci
--project-name=zingo-visual
--branch=pr-${{ github.event.number }}

# Fork PRs get a read-only token, so commenting will fail there — don't
# let that red the run. The artifact is still uploaded.
- name: Comment result
if: always()
continue-on-error: true
uses: actions/github-script@v7
with:
script: |
const changed = '${{ steps.diff.outcome }}' !== 'success';
const deployed = '${{ steps.deploy.outcome }}' === 'success';
// Stable per-PR alias; always points at this PR's latest deploy.
const url = `https://pr-${context.issue.number}.zingo-visual.pages.dev`;
const link = deployed
? `**[Open the review page](${url})** — Current, Animations, and Image diffs tabs.`
: `Download the **visual-review** artifact from [this run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) and open \`index.html\`.`;
const marker = '<!-- visual-review -->';
const body = [
marker,
`### Visual review — ${changed ? '⚠️ changes detected' : '✅ no changes'}`,
'',
`Head vs \`${context.payload.pull_request.base.ref}\`. ${link}`,
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner, repo: context.repo.repo,
comment_id: existing.id, body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: context.issue.number, body,
});
}

- name: Gate
if: steps.diff.outcome != 'success'
run: |
echo "Visual changes detected — open the visual-review artifact."
exit 1
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
#
.DS_Store

# Secrets
.env
.env.*
!.env.example

# Xcode
#
build/
Expand Down Expand Up @@ -30,9 +35,11 @@ android/app/beta/release/
*.aab
*.apk
ios/Zingolib.xcframework/
ios/NymHost.xcframework/
ios/zingo.swift
rust/lib/Generated/zingo.swift
rust/lib/Generated/zingoFFI.h
rust/nym-host/Generated/
rust/lib/Generated/zingoFFI.modulemap

# Android/IntelliJ
Expand Down Expand Up @@ -99,5 +106,25 @@ buck-out/

# Claude Code
.claude/

# Wayfinder Agent Skill
.wayfinder

# Jest coverage output
coverage/

# Storybook web static build
storybook-static/

# Visual regression (review artifacts. baselines are committed)
visual/__current__/
visual/__baseline__/
visual/__diff__/
visual/__video__/
visual/report.html
visual/report.json
visual/index.html
visual/styled.html
visual/ci/
test-results/
playwright-report/
Loading
Loading