M1-03: Design pass — static UI on sample data #3
Labels
No labels
area/agent
area/capture
area/editor
area/geo
area/security
area/sync
area/transcription
area/ui
area/vault
area/voice-memos
blocked
milestone/M1
milestone/M2
milestone/M3
milestone/M4
needs-decision
needs-hardware
p0
p1
p2
type/bug
type/enhancement
type/feature
type/idea
type/infrastructure
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Stash/stash-ios#3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
First visual pass, in code, with default SwiftUI mechanics. No audio anywhere —
every value on screen is sample data.
Wes's instruction: "let's just go ahead and throw together an initial design pass in code
using default swiftui mechanics and then i can talk you through tweaks and take screenshots."
There is deliberately no Figma/Penpot step — SwiftUI has no drag-and-drop builder, Xcode
Previews render against real iOS primitives, and any intermediate mockup would be a
lower-fidelity picture of something Previews shows for real.
Screens
states Wes described: a cloud with a line through it (not synced), a cloud with circular
arrows (syncing), a cloud with a checkmark (synced). In M1 everything is permanently "not
synced" — the states exist so the design is right, not because anything syncs yet.
a stop button.
not here; it controls something that does not exist until M3.)
Design constraints
~/Projects/_archive/stash-saas— the archived v2 app is kept for exactly this.
Done when
Wes has it on his phone, takes screenshots, and directs tweaks from there. Expect iteration
on this issue rather than one clean pass.
Milestone 1 of the Stash v3 rebuild, scoped 2026-08-06. M1 is a functioning iOS app on Wes's
phone with no sync at all — the entire goal is recording voice memos reliably and getting
them off the device by hand. Sync arrives in M3.
Working agreement for every issue in this repo: feature branch, tested before the PR opens
(on-device where the label says so), then Wes reviews the PR and we walk the code together.
Docs update in the same commit. A PR that takes more than 20 minutes to review is too big —
say so and split it.
Branch
m1-03-design-pass, one commit. Screenshots below — this is the pass to talk tweaks against.What's there
Memo list is the root view. Each row is title, relative date, duration, and the sync icon. The three states use the symbols you described and they're all stock:
icloud.slash(cloud with a line through it),arrow.triangle.2.circlepath.icloud(cloud with circular arrows),checkmark.icloud(cloud with a checkmark). Every sample memo isnotSynced, which is the only honest state in M1 — the other two exist in the type so the row is designed against the states it will really have rather than redesigned when sync lands.Empty state is
ContentUnavailableView, the stock one, so it matches every other app on the phone. Reachable in the running app by swiping every row away.Recording bar pins with
safeAreaInsetrather than overlaying, so the last row can still scroll clear of it. Level meter, live elapsed timer, red stop button. Tapping Record shows it; nothing is recorded and no audio session is touched.Settings is a
Formwith the version and a footer. The VTT-first/audio-first preference is deliberately not there — it controls something that doesn't exist until M3, and a switch that changes nothing is worse than no switch.Titles are the date-stamped default names the app will generate on its own, since M1 has no naming UI. All synthetic — this repo is public.
What I validated
Clean lint (
--strict, 0 violations, 7 files) and BUILD SUCCEEDED on the iPhone 17 Pro Max simulator. Installed, launched, confirmed alive rather than launch-and-crash. Screenshotted all four screens plus dark mode; dark and light are entirely system-managed, no per-mode colours anywhere.One layout bug found and fixed in the process: the recording bar's material was hugging its content instead of spanning the width, so the bar rendered as a floating box in the middle of the screen. The screenshot below is after the fix.
The three states that need a tap — recording, empty, settings — were captured by temporarily patching the initial state, building, and reverting. The reverted tree is what's committed and what built last.
What I did not validate
Not on your phone. No signing identity here, and none belongs in a public repo, so this is simulator-only. Getting it on the device is your step, and it's the part of "done when" I can't do.
Not checked: Dynamic Type at large sizes, landscape, iPad, or VoiceOver actually reading the rows — the accessibility labels are written but I have not run VoiceOver over them.
The level meter is the one hand-drawn control. It's driven by a sine wave, not a microphone, and
TimelineView(.animation)redraws it at display refresh — fine for a stub, worth revisiting when it's showing real levels.Leaving this open — you said to expect iteration here rather than one clean pass.
Memo list
Empty state
Active recording
Settings stub
Memo list, dark
Verified on hardware —
wes-iphone, iPhone 17 Pro. Wes confirmed the screens look right on the device.Nothing signing-related was added to the repository. The team identifier is passed on the command line, not written into
project.yml, because this repo is public.git statuswas clean afterwards.Team identifier, read off the existing certificate rather than guessed — it is the OU:
Checked for a leftover install first. Wes had deleted the old app; this confirms the bundle ID was actually free rather than assuming it:
Build, install, launch:
-allowProvisioningUpdatesis what lets Xcode mintiOS Team Provisioning Profile: today.wes.stashwithout a visit to the UI. Signing identity resolved toApple Development: Wes Kennedy (LW2SXU4UH5), BUILD SUCCEEDED.Confirmed it was still running rather than launch-and-crash, which is the part a successful launch does not tell you:
Worth knowing: this is a development build, so the profile expires and the app will stop launching after a while. Re-running the three commands above fixes it.
PR is open. Leaving this issue open — you said to expect iteration on the design rather than one clean pass, and the device pass has not changed that.