diff --git a/src/lib/hooks/useGoogleTranslate.ts b/src/lib/hooks/useGoogleTranslate.ts index 15bec91a26..e764971cb1 100644 --- a/src/lib/hooks/useGoogleTranslate.ts +++ b/src/lib/hooks/useGoogleTranslate.ts @@ -21,12 +21,12 @@ export function useGoogleTranslate() { if (IS_ANDROID) { try { // use `getApplicationIconAsync` to determine if the translate app is installed - if ( - !(await IntentLauncher.getApplicationIconAsync( - 'com.google.android.apps.translate', - )) - ) { - throw new Error('Translate app not installed') + const installed = await IntentLauncher.getApplicationIconAsync( + 'com.google.android.apps.translate', + ) + if (!installed) { + openLink(translateUrl) + return } // TODO: this should only be called one at a time, use something like diff --git a/src/screens/Settings/BetaFeaturesSettings.tsx b/src/screens/Settings/BetaFeaturesSettings.tsx index 28f561e719..78fd356596 100644 --- a/src/screens/Settings/BetaFeaturesSettings.tsx +++ b/src/screens/Settings/BetaFeaturesSettings.tsx @@ -83,10 +83,10 @@ export function BetaFeaturesSettingsScreen({}: Props) { } catch (e) { logger.error('Failed to toggle beta features', {safeMessage: e}) Toast.show(l`Something went wrong, please try again.`, {type: 'error'}) - return - } finally { setIsPending(false) + return } + setIsPending(false) /* * The toggle already succeeded; re-evaluate feature gates against the new * attribute in-session as a best-effort follow-up. A failure here should diff --git a/src/screens/Signup/StepHandle/index.tsx b/src/screens/Signup/StepHandle/index.tsx index 06927a0552..453bc7d913 100644 --- a/src/screens/Signup/StepHandle/index.tsx +++ b/src/screens/Signup/StepHandle/index.tsx @@ -76,10 +76,11 @@ export function StepHandle() { dispatch({type: 'setIsLoading', value: true}) + const serviceDid = state.serviceDescription?.did ?? 'UNKNOWN' try { const {available: handleAvailable} = await checkHandleAvailability( createFullHandle(handle, state.userDomain), - state.serviceDescription?.did ?? 'UNKNOWN', + serviceDid, {}, ) @@ -90,6 +91,7 @@ export function StepHandle() { value: _(msg`That username is already taken`), field: 'handle', }) + dispatch({type: 'setIsLoading', value: false}) return } else { ax.metric('signup:handleAvailable', {typeahead: false}) @@ -99,9 +101,8 @@ export function StepHandle() { safeMessage: error, }) // do nothing on error, let them pass - } finally { - dispatch({type: 'setIsLoading', value: false}) } + dispatch({type: 'setIsLoading', value: false}) ax.metric('signup:nextPressed', { activeStep: state.activeStep, diff --git a/src/screens/Signup/state.ts b/src/screens/Signup/state.ts index 4c1d9cf017..9597551cc9 100644 --- a/src/screens/Signup/state.ts +++ b/src/screens/Signup/state.ts @@ -322,6 +322,7 @@ export function useSubmitSignup() { dispatch({type: 'setError', value: ''}) dispatch({type: 'setIsLoading', value: true}) + const verificationCode = state.pendingSubmit?.verificationCode try { await createAccount( { @@ -331,7 +332,7 @@ export function useSubmitSignup() { password: state.password, birthDate: state.dateOfBirth, inviteCode: state.inviteCode.trim(), - verificationCode: state.pendingSubmit?.verificationCode, + verificationCode, }, { signupDuration: Date.now() - state.signupStartTime, @@ -360,6 +361,7 @@ export function useSubmitSignup() { field: 'invite-code', }) dispatch({type: 'setStep', value: SignupStep.INFO}) + dispatch({type: 'setIsLoading', value: false}) return } @@ -384,9 +386,8 @@ export function useSubmitSignup() { safeMessage: e, }) } - } finally { - dispatch({type: 'setIsLoading', value: false}) } + dispatch({type: 'setIsLoading', value: false}) }, [l, ax, createAccount, onboardingDispatch], ) diff --git a/src/state/queries/pinned-post.ts b/src/state/queries/pinned-post.ts index b1364725ca..6bb2b12c29 100644 --- a/src/state/queries/pinned-post.ts +++ b/src/state/queries/pinned-post.ts @@ -10,6 +10,25 @@ import {updatePostShadow} from '../cache/post-shadow' import {useAppviewClient, useSession} from '../session' import {useProfileUpdateMutation} from './profile' +/** + * Out of the hook because React Compiler cannot lower a `throw` inside a `try`. + * Keeping the check in place - rather than hoisting it above the `try` - means + * the catch below still shows its toast and reverts the optimistic update. + */ +function assertSignedIn(account: unknown): asserts account { + if (!account) throw new Error('Not signed in') +} + +/** + * Out of the hook because React Compiler cannot lower an optional chain inside a + * `try` block, and `profile` only exists once the request inside it resolves. + */ +function getPinnedPostUri(profile: { + pinnedPost?: {uri: string} +}): string | undefined { + return profile.pinnedPost?.uri +} + export function usePinnedPostMutation() { const {_} = useLingui() const {currentAccount} = useSession() @@ -33,13 +52,19 @@ export function usePinnedPostMutation() { updatePostShadow(queryClient, postUri, {pinned: pinCurrentPost}) // get the currently pinned post so we can optimistically remove the pin from it - if (!currentAccount) throw new Error('Not signed in') + assertSignedIn(currentAccount) const profile = await client.call(app.bsky.actor.getProfile, { actor: currentAccount.did, }) - prevPinnedPost = profile.pinnedPost?.uri - if (prevPinnedPost && prevPinnedPost !== postUri) { - updatePostShadow(queryClient, prevPinnedPost, {pinned: false}) + prevPinnedPost = getPinnedPostUri(profile) + if (prevPinnedPost) { + /* + * Nested rather than `&&`: React Compiler cannot lower a logical + * expression in a test position inside a `try`. + */ + if (prevPinnedPost !== postUri) { + updatePostShadow(queryClient, prevPinnedPost, {pinned: false}) + } } await profileUpdateMutate({