Skip to content

Commit cfa0814

Browse files
committed
Merge branch 'main' of https://github.com/aimane-chnaif/Expensify into feature-84764-2
2 parents 5b1ebb4 + 3bf3971 commit cfa0814

52 files changed

Lines changed: 631 additions & 163 deletions

Some content is hidden

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

Mobile-Expensify

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 1009033900
115-
versionName "9.3.39-0"
114+
versionCode 1009033901
115+
versionName "9.3.39-1"
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"

ios/NewExpensify/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
</dict>
4545
</array>
4646
<key>CFBundleVersion</key>
47-
<string>9.3.39.0</string>
47+
<string>9.3.39.1</string>
4848
<key>FullStory</key>
4949
<dict>
5050
<key>OrgId</key>

ios/NotificationServiceExtension/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<key>CFBundleShortVersionString</key>
1414
<string>9.3.39</string>
1515
<key>CFBundleVersion</key>
16-
<string>9.3.39.0</string>
16+
<string>9.3.39.1</string>
1717
<key>NSExtension</key>
1818
<dict>
1919
<key>NSExtensionPointIdentifier</key>

ios/ShareViewController/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<key>CFBundleShortVersionString</key>
1414
<string>9.3.39</string>
1515
<key>CFBundleVersion</key>
16-
<string>9.3.39.0</string>
16+
<string>9.3.39.1</string>
1717
<key>NSExtension</key>
1818
<dict>
1919
<key>NSExtensionAttributes</key>

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "new.expensify",
3-
"version": "9.3.39-0",
3+
"version": "9.3.39-1",
44
"author": "Expensify, Inc.",
55
"homepage": "https://new.expensify.com",
66
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
@@ -124,7 +124,7 @@
124124
"date-fns-tz": "^3.2.0",
125125
"dom-serializer": "^0.2.2",
126126
"domhandler": "^5.0.3",
127-
"expensify-common": "2.0.171",
127+
"expensify-common": "2.0.173",
128128
"expo": "54.0.22",
129129
"expo-asset": "12.0.8",
130130
"expo-audio": "1.1.1",

src/CONST/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1755,7 +1755,6 @@ const CONST = {
17551755
SHOW_HOVER_PREVIEW_DELAY: 270,
17561756
SHOW_HOVER_PREVIEW_ANIMATION_DURATION: 250,
17571757
ACTIVITY_INDICATOR_TIMEOUT: 10000,
1758-
GET_INITIAL_URL_TIMEOUT: 10000,
17591758
MIN_SMOOTH_SCROLL_EVENT_THROTTLE: 16,
17601759
},
17611760
TELEMETRY: {

src/DeepLinkHandler.tsx

Lines changed: 14 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ type DeepLinkHandlerProps = {
2525
*/
2626
function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
2727
const linkingChangeListener = useRef<NativeEventSubscription | null>(null);
28-
const initialUrlProcessed = useRef(false);
2928

3029
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
3130
const [, sessionMetadata] = useOnyx(ONYXKEYS.SESSION);
@@ -38,57 +37,24 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
3837
if (isLoadingOnyxValue(sessionMetadata)) {
3938
return;
4039
}
40+
// If the app is opened from a deep link, get the reportID (if exists) from the deep link and navigate to the chat report
41+
Linking.getInitialURL().then((url) => {
42+
onInitialUrl(url as Route);
4143

42-
// Guard against stale closures: when deps change and the effect re-runs, the previous
43-
// getInitialURL() promise may still be in-flight. Without this guard, its .then() would
44-
// fire with stale conciergeReportID/introSelected values, causing a duplicate
45-
// openReportFromDeepLink() call.
46-
let cancelled = false;
47-
48-
// If the app is opened from a deep link, get the reportID (if exists) from the deep link and navigate to the chat report.
49-
// We race against a timeout to prevent permanently blocking NavigationRoot if getInitialURL() never resolves
50-
// (e.g. in HybridApp when OldDot fails to send the URL via native bridge).
51-
Promise.race([
52-
Linking.getInitialURL(),
53-
new Promise<null>((resolve) => {
54-
setTimeout(() => resolve(null), CONST.TIMING.GET_INITIAL_URL_TIMEOUT);
55-
}),
56-
])
57-
.then((url) => {
58-
if (cancelled) {
59-
return;
44+
if (url) {
45+
if (conciergeReportID === undefined) {
46+
Log.info('[Deep link] conciergeReportID is undefined when processing initial URL', false, {url});
6047
}
61-
62-
initialUrlProcessed.current = true;
63-
onInitialUrl(url as Route);
64-
65-
if (url) {
66-
if (conciergeReportID === undefined) {
67-
Log.info('[Deep link] conciergeReportID is undefined when processing initial URL', false, {url});
68-
}
69-
if (introSelected === undefined) {
70-
Log.info('[Deep link] introSelected is undefined when processing initial URL', false, {url});
71-
}
72-
// Use hasAuthToken() for the latest auth state at call time, since the isAuthenticated
73-
// closure value may be stale on cold start (useOnyx reports 'loaded' before storage completes).
74-
const isCurrentlyAuthenticated = hasAuthToken();
75-
openReportFromDeepLink(url, allReports, isCurrentlyAuthenticated, conciergeReportID, introSelected, betas);
76-
} else {
77-
Report.doneCheckingPublicRoom();
48+
if (introSelected === undefined) {
49+
Log.info('[Deep link] introSelected is undefined when processing initial URL', false, {url});
7850
}
79-
80-
endSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.DEEP_LINK);
81-
})
82-
.catch(() => {
83-
if (cancelled) {
84-
return;
85-
}
86-
87-
initialUrlProcessed.current = true;
88-
onInitialUrl(null);
51+
openReportFromDeepLink(url, allReports, isAuthenticated, conciergeReportID, introSelected, betas);
52+
} else {
8953
Report.doneCheckingPublicRoom();
90-
endSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.DEEP_LINK);
91-
});
54+
}
55+
56+
endSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.DEEP_LINK);
57+
});
9258

9359
// Open chat report from a deep link (only mobile native)
9460
linkingChangeListener.current = Linking.addEventListener('url', (state) => {
@@ -103,25 +69,11 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
10369
});
10470

10571
return () => {
106-
cancelled = true;
10772
linkingChangeListener.current?.remove();
10873
};
10974
// eslint-disable-next-line react-hooks/exhaustive-deps -- we only want this effect to re-run when conciergeReportID changes
11075
}, [sessionMetadata?.status, conciergeReportID, introSelected, betas]);
11176

112-
// Safety net: if getInitialURL() resolves before the session loads, hasAuthToken() may return false
113-
// for an authenticated user, causing openReportFromDeepLink to take the wrong path. Once isAuthenticated
114-
// settles to true, unblock the UI. The initialUrlProcessed guard ensures this doesn't fire before URL
115-
// resolution. In the common case (isAuthenticated settles first), this is a no-op because
116-
// openReportFromDeepLink's own doneCheckingPublicRoom() call handles it.
117-
useEffect(() => {
118-
if (!isAuthenticated || !initialUrlProcessed.current) {
119-
return;
120-
}
121-
122-
Report.doneCheckingPublicRoom();
123-
}, [isAuthenticated]);
124-
12577
return null;
12678
}
12779

src/Expensify.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ function Expensify() {
6565
const {preferredLocale} = useLocalize();
6666
const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector});
6767
const [lastRoute] = useOnyx(ONYXKEYS.LAST_ROUTE);
68-
const [isCheckingPublicRoom = true] = useOnyx(ONYXKEYS.RAM_ONLY_IS_CHECKING_PUBLIC_ROOM);
69-
const [updateAvailable] = useOnyx(ONYXKEYS.RAM_ONLY_UPDATE_AVAILABLE);
70-
const [updateRequired] = useOnyx(ONYXKEYS.RAM_ONLY_UPDATE_REQUIRED);
68+
const [isCheckingPublicRoom = true] = useOnyx(ONYXKEYS.IS_CHECKING_PUBLIC_ROOM, {initWithStoredValues: false});
69+
const [updateAvailable] = useOnyx(ONYXKEYS.UPDATE_AVAILABLE, {initWithStoredValues: false});
70+
const [updateRequired] = useOnyx(ONYXKEYS.UPDATE_REQUIRED, {initWithStoredValues: false});
7171
const [lastVisitedPath] = useOnyx(ONYXKEYS.LAST_VISITED_PATH);
7272

7373
useDebugShortcut();
@@ -81,7 +81,7 @@ function Expensify() {
8181

8282
const bootsplashSpan = useRef<Sentry.Span>(null);
8383

84-
const [initialUrl, setInitialUrl] = useState<Route | null | undefined>(undefined);
84+
const [initialUrl, setInitialUrl] = useState<Route | null>(null);
8585
const {setIsAuthenticatedAtStartup} = useInitialURLActions();
8686

8787
useEffect(() => {
@@ -302,7 +302,7 @@ function Expensify() {
302302
<FullstoryInitHandler />
303303
<DeepLinkHandler onInitialUrl={setInitialUrl} />
304304
<AppleAuthWrapper />
305-
{hasAttemptedToOpenPublicRoom && initialUrl !== undefined && (
305+
{hasAttemptedToOpenPublicRoom && (
306306
<NavigationRoot
307307
onReady={setNavigationReady}
308308
authenticated={isAuthenticated}

0 commit comments

Comments
 (0)