Skip to content

feat(tips): put the tipcard link at the root when there's no handle - #670

Merged
bmc08gt merged 1 commit into
mainfrom
feat/root-tipcard-links
Aug 27, 2026
Merged

feat(tips): put the tipcard link at the root when there's no handle#670
bmc08gt merged 1 commit into
mainfrom
feat/root-tipcard-links

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Claiming a handle used to change the shape of a user's tipcard link, not just the name in it: without one they shared flipcash.com/tip/<uuid>, with one flipcash.com/<handle>. Both forms now sit at the root, so the link a user copies before claiming a handle is the same kind of link afterwards.

URL.tipcard(for:username:) is the only place either form is built, so the change is one line there. Route.Path.parse now reads a single unmatched root segment as a uuid before falling through to the handle branch. The two forms can't collide — a uuid's dashes aren't in the handle character set and 36 characters overruns the 2-15 length — so /11111111-2222 still lands on .unknown. /tip/<uuid> keeps parsing, for links already out there.

TipCardLinkRow.displayText needed no logic change: it clips by last path component, so the row still reads flipcash.com/b0ced….

Android

code-payments/code-android-app#1340 moves the same link, and its description compares the two in detail. Worth confirming from this side: UUID(uuidString:) is as strict as the regex Android uses in place of UUID.fromString — it rejects 1-1-1-1-1, 11111111-2222, and the undashed 32-character form, so the two platforms accept the same set of links.

The tolerance difference that PR notes is real and left as is: this parser is host- and scheme-agnostic by design, so it also takes a root uuid on app.flipcash.com and under flipcash://, where Android takes the bare and www hosts only. Nothing builds those forms.

Depends on

flipcash.com/<uuid> resolving on the website. Nothing in this PR makes that page exist. The apex apple-app-site-association already ends in a /* component, so the app-opening half works as-is.

A user without a claimed handle shared `flipcash.com/tip/<uuid>` while a user
with one shared `flipcash.com/<handle>`, so claiming a handle changed the shape
of the link, not just the name in it. Both forms now sit at the root.

`Route.Path.parse` reads a single unmatched root segment as a uuid before
falling through to the handle branch. The two can't collide: a uuid's dashes
aren't in the handle character set and 36 characters overruns the 2-15 length,
so `/11111111-2222` still lands on `.unknown`. `/tip/<uuid>` keeps parsing for
links already shared.

The web side has to serve `flipcash.com/<uuid>` for the new form to resolve;
the apex `apple-app-site-association` already ends in `/*`, so the app-opening
half needs no change. Android builds this URL in its own single place and needs
the matching change.
@bmc08gt bmc08gt self-assigned this Aug 27, 2026
@bmc08gt
bmc08gt merged commit 861785e into main Aug 27, 2026
bmc08gt added a commit to code-payments/code-android-app that referenced this pull request Aug 27, 2026
…1340)

An unclaimed card shared `app.flipcash.com/tip/{uuid}` while a claimed one
shared `flipcash.com/{handle}`, so claiming a handle changed the host and the
path shape of a link its owner may already have printed or posted. Both forms
now sit at the root of the apex host: `flipcash.com/{uuid}` until there's a
handle, `flipcash.com/{handle}` after.

AppRouter's bare-host branch takes either shape. A uuid can't be mistaken for a
handle — dashes aren't in the `[a-z0-9_]{2,15}` charset and 36 characters
overruns it — so the two share the root without ambiguity, and only the handle
form needs the reserved-path list that keeps `/download` and `/privacy` with the
website. The shape test is a regex rather than `UUID.fromString`, which also
accepts `1-1-1-1-1`: an unrecognised path on this host goes back to the browser,
and claiming a looser shape would take taps away from pages the website serves.

The manifest gains a matching uuid `pathAdvancedPattern`. As with the handle
pattern, the platform ignores it below API 31 and the whole host arrives, which
is why `isProfileLink` makes the same distinction in code.

`app.flipcash.com/tip/{uuid}` still routes. Links already shared carry it;
nothing writes it any more.

Matches code-payments/code-ios-app#670, which moves the same link to the root.
@bmc08gt
bmc08gt deleted the feat/root-tipcard-links branch August 27, 2026 15:42
bmc08gt added a commit that referenced this pull request Aug 27, 2026
…ngs-sheet

* origin/main:
  feat(tips): put the tipcard link at the root when there's no handle (#670)
  chore: bump version to 2026.8.6 (#669)
  fix(you): make the version footer's toast findable in UI tests (#668)
  feat(username): find someone by their handle (#661)
  fix(onramp): restore the email AutoFill suggestion on the verify step (#663)
  fix(ui): confirm a saved name with the checkmark the rest of the app shows (#664)
  feat(you): say when the version footer unlocks beta access (#665)

# Conflicts:
#	Flipcash/Core/Navigation/AppRouter+Destination.swift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant