Repository navigation
Wildcard deeplinks - #99347
Wildcard deeplinks#99347war-in wants to merge 9 commits into
Conversation
|
@MelvinBot review |
|
🤖 Review: looks safe to ship, with one verification gap to close. The wildcard change is sound. The one real risk with collapsing the allowlists to Key findings
Please verify before merging
Config correctness notes
|
|
🚧 Julesssss has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
I verified it works correctly on Android, unable to test on iOS Screen_Recording_20260825_114729_Expensify.Adhoc.mp4 |
|
Regarding Melvin's review
This one is fine; we want to open all links in the app |
|
@aimane-chnaif Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
# Conflicts: # .well-known/apple-app-site-association
|
Discussed this one with @Julesssss and we can thoroughly test Android before the rollout, but iOS will probably have to be tested on staging/prod (we need to deploy AASA file first) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d06f18ba43
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
JmillsExpensify
left a comment
There was a problem hiding this comment.
Product experience is largely the same. LGTM
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari |
|
|
|
NewDot opens some of its own links outside the app on purpose, and on native some of those go through
On 1. New Expensify links meant to open in the browser reopen the app (production Android HybridApp)Code path: Repro steps (Android HybridApp):
Expected (main): The browser opens and downloads the file. bug.movVariant: Send 2. The PDS/FSG "Download" button opens the app instead of the PDF (production Android HybridApp)Code path: Repro steps:
Expected: The PDF opens in the browser. 3. The "Expensify web app" link on the Unsupported device screen loops back into the app (production Android HybridApp)Code path: Repro steps:
Expected: new.expensify.com opens in the browser. |
|
|
|
@Julesssss what do you think about those? |
|
Sorry forgot to send my draft yesterday..
#99347 (comment) Sorry for delay. A) AI feedback I am not sure if this is a problem and whether that URL should do anything. It doesn't on prod as far as I can tell. If we can exclude these on either mobile platform great, but I don't think it's a blocker. B) New Expensify links meant to open in the browser reopen the app
Not the best example, as this is an odd case. But for C) The PDS/FSG "Download" button opens the app instead of the PDF Yeah that one seems problematic. Especially for some of the banking flows for which we are providing terms and conditions. @war-in any ideas how to resolve this one? D) The "Expensify web app" link on the Unsupported device screen loops back into the app
Are they able to workaround by navigating manually on browser? If so and there is no special URL speeding up their auth process I think it could be okay. Possibly fixed along with changes we'll make to resolve the above issues. |
|
I like the web view idea a lot! But the real problem is that Android doesn't allow for easy opt-outs from deeplinks, so we need to find another solution or simply give up on the wildcard idea I'll try to dig into this again 🤞 |
|
Ok, I think I found a way iOS is simple, we can exclude some paths, but Android supports such a feature since Android 15. @Julesssss could you verify in Google Play console how many Android devices are under v14? Sentry shows that this is ~20%, but this is from the traces and crashes, so that number can be inflated |
|
@Julesssss what do you think about preserving the current behaviour (from main) for Android <15 users? I think that would be the cleanest approach without any workarounds 🤔 |
Yeah that should be okay. So I know we can use conditions to wrap by Android version, but does this require some other method? I can't remember but assume some OS linking into the app might be done prior to out SDK version checks. |
Yeah, it'd definitely be too late. But we can use |
|
@Julesssss all changes are in this and ME PRs so please let me know if that approach works for you 🙏 |
|
🚧 Julesssss has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
@aimane-chnaif could you review? 🙏 |
|
🚧 Julesssss has triggered a test Expensify/App build. You can view the workflow run here. |
Please also review the linked Mobile-Expensify PR too |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|

Explanation of Change
Replaces the hand-maintained NewDot deeplink path allowlists with a wildcard, so every
new.expensify.com/staging.new.expensify.compath opens the app and new routes need no native change. iOS: AASA components collapsed to{"/": "*"}. Android:pathPrefixentries replaced by host-only<data>, mirrored in Mobile-Expensify. Expensify Classic links unchanged.Fixed Issues
$ #99412
PROPOSAL:
MOBILE-EXPENSIFY: https://github.com/Expensify/Mobile-Expensify/pull/14073 needs to be merged simultaneously
Tests
Note on iOS: the AASA is fetched from the server, so the wildcard only takes effect once this branch's
.well-known/apple-app-site-associationis deployed tonew.expensify.com/staging.new.expensify.com. To test before deploy, append?mode=developerto theapplinks:entries in the entitlements and enable Settings > Developer > Associated Domains Development on the device.Android — previously unlisted NewDot path opens the app (standalone + HybridApp)
https://new.expensify.com/workspace/<policyID>/members.https://new.expensify.com/r/<reportID>.https://new.expensify.com/some-unsupported-pathNot foundpageAndroid — Expensify Classic links are unchanged (HybridApp)
https://www.expensify.com/inbox.https://www.expensify.com/expensify-classic/hubs/getting-started/, a Classic path that is not in the OldDot allowlist.iOS — universal links resolve to the app (standalone + HybridApp)
https://new.expensify.com/settings/profilelink in Notes or Messages and long-press it.https://new.expensify.com/workspace/<policyID>/members.https://www.expensify.com/inbox.www.expensify.comserves its own AASA which this PR does not change.Offline tests
N/A — the change only touches native link-matching configuration and does not involve API calls or Onyx data.
QA Steps
Same as tests, but Android only
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari