Skip to content

feat(mobile): add slug suffix to inbox report deep links#2432

Open
Gilbert09 wants to merge 2 commits into
mainfrom
posthog-code/mobile-inbox-deeplink-slug
Open

feat(mobile): add slug suffix to inbox report deep links#2432
Gilbert09 wants to merge 2 commits into
mainfrom
posthog-code/mobile-inbox-deeplink-slug

Conversation

@Gilbert09
Copy link
Copy Markdown
Member

Summary

Port of the desktop PR #2298 to the mobile app: when the "Discuss this report" flow builds a link back to a report, append the slugified title as a trailing path segment so shared/copied links read like posthog://inbox/<reportId>/fix-inbox--Add-foo instead of just the UUID. The slug is purely cosmetic — receivers ignore everything past the UUID.

  • apps/mobile/src/lib/deep-links.ts

    • Adds slugifyTitle(title) mirroring buildInboxDeeplink's slug rules in apps/code/src/shared/deeplink.ts exactly (NFD-fold accented Latin, preserve URL-unreserved punctuation _ . ~, collapse colon-with-other-chars runs to --, single colon-only runs to -, strip leading/trailing hyphens).
    • Adds inboxReportShareUrl(reportId, title?) that produces the slug-suffixed posthog://inbox/<id>/<slug> custom-scheme URL (no slug when the title is empty / slugifies to empty).
    • Extends externalUrlToAppPath to strip a trailing slug from inbox custom-scheme and universal-link URLs so notification-tap navigation lands on the bare /inbox/<id> path. Mirrors the desktop receiver, which also ignores the slug.
  • apps/mobile/src/app/inbox/[id].tsxapps/mobile/src/app/inbox/[...id].tsx

    • Converts the route to a catch-all so expo-router resolves both /inbox/<id> and /inbox/<id>/<slug> to the same report screen (the OS-level deep-link entry doesn't go through externalUrlToAppPath, so route-level tolerance is the load-bearing fix).
    • Pulls reportId from the first catch-all segment and passes report.title into DiscussReportSheet.
    • _layout.tsx Stack.Screen registration updated to inbox/[...id].
  • apps/mobile/src/features/inbox/components/DiscussReportSheet.tsx

    • Accepts optional reportTitle?: string | null and builds the link via inboxReportShareUrl(reportId, reportTitle) (replacing the bare customSchemeUrl(paths.inboxReport(reportId))).
    • Still hands the resulting URL to buildDiscussReportPrompt from @posthog/shared unchanged.
  • apps/mobile/src/lib/deep-links.test.ts

    • Covers the slug rules (accented-fold, colon-run -- vs single -, URL-unreserved punctuation passthrough, punctuation-collapse, trim) mirroring apps/code/src/shared/deeplink.test.ts.
    • Covers inboxReportShareUrl (empty title, slug-empty title, colon-run convention).
    • Covers inbound path tolerance: a trailing slug segment is stripped from both posthog://inbox/<id>/<slug> and https://code.posthog.com/inbox/<id>/<slug>, including query-string preservation.

No changes to apps/code or shared-package code — buildDiscussReportPrompt from @posthog/shared is reused as-is.

Test plan

  • pnpm --filter @posthog/mobile test — 156/156 passing including the new slug + inbound-path cases.
  • pnpm --filter @posthog/mobile lint — clean.
  • Manual: tap posthog://inbox/<id> on a device → routes to the report.
  • Manual: tap posthog://inbox/<id>/some-slug on a device → routes to the same report (slug ignored).
  • Manual: tap https://code.posthog.com/inbox/<id>/some-slug (universal link) → routes to the same report.
  • Manual: open a report, hit "Discuss" → confirm the prompt embeds a posthog://inbox/<id>/<slug> URL with the slugified title.

Port of the desktop change in #2298: when the mobile "Discuss this report"
flow builds a link back to the report, append the slugified title as a
trailing path segment so shared/copied links read like
`posthog://inbox/<reportId>/fix-inbox--Add-foo` instead of just the UUID.
The slug is purely cosmetic; receivers ignore everything past the UUID.

- Add `slugifyTitle` and `inboxReportShareUrl` to `lib/deep-links.ts`,
  mirroring `buildInboxDeeplink` from `apps/code/src/shared/deeplink.ts`
  (NFD fold, colon-run `--`, URL-unreserved punctuation passthrough, etc).
- Thread `reportTitle` through `DiscussReportSheet` so the link it hands to
  `buildDiscussReportPrompt` is the slug-suffixed share URL.
- Tolerate inbound `/inbox/<id>/<slug>` two ways: convert the route to a
  catch-all (`inbox/[...id].tsx`) so expo-router matches the deeper path,
  and strip the trailing slug in `externalUrlToAppPath` so notification-tap
  navigation lands on the bare `/inbox/<id>` path.
- Unit tests cover the slug rules (accented-fold, colon-run, punctuation
  collapse, trim) and the inbound-path tolerance on both the custom-scheme
  and universal-link entry points.

Generated-By: PostHog Code
Task-Id: a37e6f21-3453-4ac4-9853-d61de0ea362a
@Gilbert09 Gilbert09 requested a review from a team May 29, 2026 10:52
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 29, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/mobile/src/lib/deep-links.test.ts:9-15
Several `it()` blocks exercise multiple independent inputs with separate `expect()` calls. The team's style guide prefers parameterised tests (`it.each`) so each input/expected pair gets its own test name and failure line when it breaks. The same pattern appears in `slugifyTitle` ("returns an empty string…" — 5 cases), `inboxReportShareUrl` ("returns just the UUID…" — 4 cases, "omits the slug…" — 2 cases), and `externalUrlToAppPath` ("ignores URLs…" — 2 cases).

```suggestion
  it.each([
    [null],
    [undefined],
    [""],
    ["   "],
    [":::"],
  ])("returns an empty string when the title is %s", (input) => {
    expect(slugifyTitle(input)).toBe("");
  });
```

Reviews (1): Last reviewed commit: "feat(mobile): add slug suffix to inbox r..." | Re-trigger Greptile

Comment thread apps/mobile/src/lib/deep-links.test.ts Outdated
Address Greptile review feedback on #2432 — convert multi-expect blocks
in `apps/mobile/src/lib/deep-links.test.ts` to `it.each` so each
input/expected pair has its own test name and failure line.

Generated-By: PostHog Code
Task-Id: a37e6f21-3453-4ac4-9853-d61de0ea362a
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.

2 participants