Skip to content

Commit f7587b5

Browse files
committed
Merge remote-tracking branch 'origin/main' into perf/report-welcome-text
2 parents db3dedd + c70c52b commit f7587b5

199 files changed

Lines changed: 6180 additions & 3416 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
"mcp__sentry__search_events",
5353
"mcp__sentry__search_issue_events",
5454
"mcp__sentry__search_issues",
55-
"mcp__sentry__whoami"
55+
"mcp__sentry__whoami",
56+
"Bash(agent-device *)",
57+
"Bash(echo \"$(npm root -g)/agent-device/skills/agent-device\")"
5658
]
5759
},
5860
"enabledPlugins": {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
name: agent-device
3+
description: Drive iOS and Android devices for the Expensify App - testing, debugging, performance profiling, bug reproduction, and feature verification. Use when the developer needs to interact with the mobile app on a device.
4+
allowed-tools: Bash(agent-device *) Bash(npm root *)
5+
---
6+
7+
# agent-device
8+
9+
## Pre-flight
10+
11+
`agent-device` CLI version: !`agent-device --version 2>&1 || echo "NOT_INSTALLED"`
12+
13+
Canonical skill reference path (read these files directly for device automation guidance - bootstrap, exploration, verification, debugging): !`echo "$(npm root -g)/agent-device/skills/agent-device"`
14+
15+
> If the version line above shows `NOT_INSTALLED` or a command-not-found error, **STOP** and instruct the developer to install it: `npm install -g agent-device`. All device interaction depends on it.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,8 @@ modules/*/lib/
162162
.playwright-output/
163163
.playwright-mcp/
164164

165+
# agent-device
166+
agent-device-output/
167+
165168
# cspell cache
166169
.cspellcache

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ npm run web
278278
### Browser Testing
279279
Use the `/playwright-app-testing` skill to test and debug the App in a browser. Use this skill after making frontend changes to verify your work, or when the user requests testing.
280280

281+
### Mobile Device Testing
282+
Use the `/agent-device` skill to drive the App on iOS and Android (simulators or real devices) for interactive testing, performance profiling, bug reproduction, and device-specific debugging. Requires `npm install -g agent-device` - the skill's pre-flight check will surface the install instruction if missing.
283+
281284
## Architecture Decisions
282285

283286
### React Native New Architecture

Mobile-Expensify

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ For detailed setup instructions for each platform, see the following guides:
4848
* **📱 iOS Development**: [iOS Setup Instructions](contributingGuides/SETUP_IOS.md)
4949
* **🤖 Android Development**: [Android Setup Instructions](contributingGuides/SETUP_ANDROID.md)
5050

51+
**Optional AI-assisted mobile testing:** If you use Claude Code, the [`/agent-device` skill](.claude/skills/agent-device/SKILL.md) drives iOS and Android simulators or devices for interactive testing, debugging, and performance profiling. Requires `npm install -g agent-device`.
52+
5153
## General Troubleshooting
5254
1. If you are having issues with **_Getting Started_**, please reference [React Native's Documentation](https://reactnative.dev/docs/environment-setup)
5355
2. If you are running into CORS errors like (in the browser dev console)

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ android {
111111
minSdkVersion rootProject.ext.minSdkVersion
112112
targetSdkVersion rootProject.ext.targetSdkVersion
113113
multiDexEnabled rootProject.ext.multiDexEnabled
114-
versionCode 1009036102
115-
versionName "9.3.61-2"
114+
versionCode 1009036103
115+
versionName "9.3.61-3"
116116
// Supported language variants must be declared here to avoid from being removed during the compilation.
117117
// This also helps us to not include unnecessary language variants in the APK.
118118
resConfigs "en", "es"
Lines changed: 1 addition & 0 deletions
Loading

contributingGuides/NAVIGATION.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,7 @@ In Expensify, we use an extended implementation of this function because:
11411141
- In case of opening the RHP, appropriate screens should be pushed to the navigation to be displayed below the overlay. A guide on how to set up a good screen for RHP can be found [here](#how-to-set-a-correct-screen-below-the-rhp).
11421142
- When opening the settings of a specific workspace, the workspace list needs to be pushed to the state.
11431143
- When the `backTo` parameter is in the URL, we need to build a state also for the screen we want to return to. (`backTo` parameter is deprecated, more information can be found [here](#how-to-remove-backto-from-url))
1144-
- For dynamic routes, state is built from the current path and [entryScreens](#entry-screens-access-control) access control.
1144+
- For dynamic routes, when the page is refreshed the navigation state only contains the deepest screen. To make back navigation work, all intermediate dynamic screens must be inserted into the state in the correct order so the app knows which screen to return to.
11451145

11461146
Here are examples how the state is generated based on route:
11471147

@@ -1255,6 +1255,77 @@ As you can see after opening the workspace settings of the specific workspace, w
12551255

12561256
In the above example, we can see that when building a state from a link leading to a screen in RHP, screens that appear below the overlay are also built.
12571257

1258+
- `settings/profile/address/country?country=US`
1259+
1260+
```json
1261+
{
1262+
"stale": false,
1263+
"type": "stack",
1264+
"key": "stack-key-7",
1265+
"index": 1,
1266+
"routes": [
1267+
{
1268+
"name": "SettingsSplitNavigator",
1269+
"state": {
1270+
"stale": false,
1271+
"type": "stack",
1272+
"key": "stack-key-8",
1273+
"index": 1,
1274+
"routes": [
1275+
{
1276+
"name": "Settings_Root",
1277+
"key": "Settings_Root-key"
1278+
},
1279+
{
1280+
"name": "Settings_Profile",
1281+
"key": "Settings_Profile-key"
1282+
}
1283+
]
1284+
},
1285+
"key": "SettingsSplitNavigator-key"
1286+
},
1287+
{
1288+
"name": "RightModalNavigator",
1289+
"state": {
1290+
"stale": false,
1291+
"type": "stack",
1292+
"key": "stack-key-9",
1293+
"index": 0,
1294+
"routes": [
1295+
{
1296+
"name": "Settings",
1297+
"state": {
1298+
"stale": false,
1299+
"type": "stack",
1300+
"key": "stack-key-10",
1301+
"index": 1,
1302+
"routes": [
1303+
{
1304+
"name": "Settings_Address",
1305+
"path": "/settings/profile/address",
1306+
"key": "Settings_Address-key"
1307+
},
1308+
{
1309+
"name": "Dynamic_Address_Country",
1310+
"path": "/settings/profile/address/country?country=US",
1311+
"params": {
1312+
"country": "US"
1313+
},
1314+
"key": "Dynamic_Address_Country-key"
1315+
}
1316+
]
1317+
},
1318+
"key": "Settings-key"
1319+
}
1320+
]
1321+
},
1322+
"key": "RightModalNavigator-key"
1323+
}
1324+
]
1325+
}
1326+
```
1327+
Since `country` is a dynamic suffix, the `Dynamic_Address_Country` screen is layered on top of the static `Settings_Address` screen in the initial state, ensuring correct back navigation after a refresh.
1328+
12581329
## Setting the correct screen underneath RHP
12591330

12601331
RHP screens can usually be opened from a specific central screen. Of course there are cases where one RHP screen can be used in different tabs. However, most often one RHP screen has a specific central screen assigned underneath.

contributingGuides/SETUP_ANDROID.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ If you haven't done any intentional edits outside of `src/` (like adding new dep
7373
- Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
7474

7575
### Expensify Employees
76-
If you are an Expensify employee and want to point the emulator to your local VM, follow [this](https://stackoverflow.com/c/expensify/questions/7699)
76+
- To point the **Development Emulator** at your local VM, follow [these steps](https://stackoverflow.com/c/expensify/questions/7699).
77+
- You must configure the local dev email account; follow [these instructions](https://stackoverflowteams.com/c/expensify/questions/23537/23538#23538).
7778

7879
## Enabling Prebuilt React Native Artifacts
7980

0 commit comments

Comments
 (0)