fix: Text selection toolbar still exist after navigated - #81383
Conversation
|
@ZhenjaHorbach 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] |
| @@ -272,6 +273,7 @@ function isActiveRoute(routePath: Route): boolean { | |||
| * @param options.forceReplace - If true, the navigation action will replace the current route instead of pushing a new one. | |||
| */ | |||
| function navigate(route: Route, options?: LinkToOptions) { | |||
There was a problem hiding this comment.
❌ CONSISTENCY-3 (docs)
The text selection clearing logic is duplicated across three navigation functions. Other navigation functions that trigger navigation (like dismissModalWithReport, resetToHome, goBackToHome, popToSidebar) may also need this same treatment, indicating a pattern that should be centralized.
Suggested fix: Consider creating a wrapper or helper that ensures text selection is cleared for all navigation operations, or add clearSelectedText() to all relevant navigation functions consistently. Alternatively, clear text selection at a lower level (e.g., in the navigation event listener) to avoid duplication.
Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
| @@ -699,6 +703,7 @@ function getTopmostSuperWideRHPReportID(state: NavigationState = navigationRef.g | |||
| * see the NAVIGATION.md documentation. | |||
There was a problem hiding this comment.
❌ PERF-8 (docs)
The clearSelectedText() call is placed synchronously before the isNavigationReady() promise, which means text selection is cleared immediately rather than when the modal actually dismisses. This creates a timing inconsistency - the text is cleared before navigation is ready, which differs from navigate() and goBack() where it happens at the start of the synchronous function.
Suggested fix: Consider moving clearSelectedText() inside the isNavigationReady().then() callback to ensure it executes when navigation is actually ready, maintaining consistency with the async nature of this function:
const dismissModal = ({ref = navigationRef, callback}: {ref?: NavigationRef; callback?: () => void} = {}) => {
isNavigationReady().then(() => {
clearSelectedText();
if (callback) {
const subscription = DeviceEventEmitter.addListener(CONST.MODAL_EVENTS.CLOSED, () => {
subscription.remove();
callback();
});
}
ref.dispatch({type: CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL});
});
};Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb Chrome2026-02-04.11.00.28.moviOS: HybridAppiOS: mWeb Safari2026-02-04.10.50.51.movMacOS: Chrome / Safari2026-02-04.10.52.31.mov |
|
LGTM |
|
🚧 @MariaHCD has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/MariaHCD in version: 9.3.13-1 🚀
|
|
🚀 Deployed to staging by https://github.com/MariaHCD in version: 9.3.15-0 🚀
|
|
🚀 Deployed to production by https://github.com/lakchote in version: 9.3.15-10 🚀
|
| * see the NAVIGATION.md documentation. | ||
| */ | ||
| const dismissModal = ({ref = navigationRef, callback}: {ref?: NavigationRef; callback?: () => void} = {}) => { | ||
| clearSelectedText(); |
There was a problem hiding this comment.
Checklist from #84737. Closing the suggestion list causes the composer to lose focus, we fixed it by checking the active element before clear selected text.
Explanation of Change
Fixed Issues
$#80892
PROPOSAL:#80892 (comment)
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, 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.ScrollViewcomponent to make it scrollable when more elements are added to the page.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.mov
Android: mWeb Chrome
android_ch.mov
iOS: Native
ios.mov
iOS: mWeb Safari
ios_sfr.mov
MacOS: Chrome / Safari
chorme.mov