diff options
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/state/modals/index.tsx | 6 | ||||
-rw-r--r-- | src/state/persisted/schema.ts | 2 | ||||
-rw-r--r-- | src/state/preferences/in-app-browser.tsx | 79 | ||||
-rw-r--r-- | src/state/preferences/index.tsx | 5 | ||||
-rw-r--r-- | src/view/com/modals/InAppBrowserConsent.tsx | 102 | ||||
-rw-r--r-- | src/view/com/modals/LinkWarning.tsx | 6 | ||||
-rw-r--r-- | src/view/com/modals/Modal.tsx | 4 | ||||
-rw-r--r-- | src/view/com/util/Link.tsx | 12 | ||||
-rw-r--r-- | src/view/screens/Settings.tsx | 18 | ||||
-rw-r--r-- | yarn.lock | 85 |
11 files changed, 299 insertions, 22 deletions
diff --git a/package.json b/package.json index 7e63ad9a6..6572d868b 100644 --- a/package.json +++ b/package.json @@ -113,6 +113,7 @@ "expo-system-ui": "~2.9.2", "expo-task-manager": "~11.7.0", "expo-updates": "~0.24.5", + "expo-web-browser": "^12.5.0", "fast-text-encoding": "^1.0.6", "history": "^5.3.0", "js-sha256": "^0.9.0", @@ -148,7 +149,6 @@ "react-native-get-random-values": "~1.8.0", "react-native-haptic-feedback": "^1.14.0", "react-native-image-crop-picker": "^0.38.1", - "react-native-inappbrowser-reborn": "^3.6.3", "react-native-ios-context-menu": "^1.15.3", "react-native-linear-gradient": "^2.6.2", "react-native-pager-view": "6.2.2", diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index 8c32c472a..45856e108 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -187,6 +187,11 @@ export interface EmbedConsentModal { onAccept: () => void } +export interface InAppBrowserConsentModal { + name: 'in-app-browser-consent' + href: string +} + export type Modal = // Account | AddAppPasswordModal @@ -231,6 +236,7 @@ export type Modal = | ConfirmModal | LinkWarningModal | EmbedConsentModal + | InAppBrowserConsentModal const ModalContext = React.createContext<{ isModalActive: boolean diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts index 6a26cedae..a6f2ea06a 100644 --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -53,6 +53,7 @@ export const schema = z.object({ step: z.string(), }), hiddenPosts: z.array(z.string()).optional(), // should move to server + useInAppBrowser: z.boolean().optional(), }) export type Schema = z.infer<typeof schema> @@ -84,4 +85,5 @@ export const defaults: Schema = { step: 'Home', }, hiddenPosts: [], + useInAppBrowser: undefined, } diff --git a/src/state/preferences/in-app-browser.tsx b/src/state/preferences/in-app-browser.tsx new file mode 100644 index 000000000..628663af4 --- /dev/null +++ b/src/state/preferences/in-app-browser.tsx @@ -0,0 +1,79 @@ +import React from 'react' +import * as persisted from '#/state/persisted' +import {Linking} from 'react-native' +import * as WebBrowser from 'expo-web-browser' +import {isNative} from '#/platform/detection' +import {useModalControls} from '../modals' + +type StateContext = persisted.Schema['useInAppBrowser'] +type SetContext = (v: persisted.Schema['useInAppBrowser']) => void + +const stateContext = React.createContext<StateContext>( + persisted.defaults.useInAppBrowser, +) +const setContext = React.createContext<SetContext>( + (_: persisted.Schema['useInAppBrowser']) => {}, +) + +export function Provider({children}: React.PropsWithChildren<{}>) { + const [state, setState] = React.useState(persisted.get('useInAppBrowser')) + + const setStateWrapped = React.useCallback( + (inAppBrowser: persisted.Schema['useInAppBrowser']) => { + setState(inAppBrowser) + persisted.write('useInAppBrowser', inAppBrowser) + }, + [setState], + ) + + React.useEffect(() => { + return persisted.onUpdate(() => { + setState(persisted.get('useInAppBrowser')) + }) + }, [setStateWrapped]) + + return ( + <stateContext.Provider value={state}> + <setContext.Provider value={setStateWrapped}> + {children} + </setContext.Provider> + </stateContext.Provider> + ) +} + +export function useInAppBrowser() { + return React.useContext(stateContext) +} + +export function useSetInAppBrowser() { + return React.useContext(setContext) +} + +export function useOpenLink() { + const {openModal} = useModalControls() + const enabled = useInAppBrowser() + + const openLink = React.useCallback( + (url: string, override?: boolean) => { + if (isNative && !url.startsWith('mailto:')) { + if (override === undefined && enabled === undefined) { + openModal({ + name: 'in-app-browser-consent', + href: url, + }) + return + } else if (override ?? enabled) { + WebBrowser.openBrowserAsync(url, { + presentationStyle: + WebBrowser.WebBrowserPresentationStyle.FULL_SCREEN, + }) + return + } + } + Linking.openURL(url) + }, + [enabled, openModal], + ) + + return openLink +} diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx index cc2d9244c..a442b763a 100644 --- a/src/state/preferences/index.tsx +++ b/src/state/preferences/index.tsx @@ -3,6 +3,7 @@ import {Provider as LanguagesProvider} from './languages' import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required' import {Provider as HiddenPostsProvider} from '../preferences/hidden-posts' import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs' +import {Provider as InAppBrowserProvider} from './in-app-browser' export {useLanguagePrefs, useLanguagePrefsApi} from './languages' export { @@ -20,7 +21,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) { <LanguagesProvider> <AltTextRequiredProvider> <ExternalEmbedsProvider> - <HiddenPostsProvider>{children}</HiddenPostsProvider> + <HiddenPostsProvider> + <InAppBrowserProvider>{children}</InAppBrowserProvider> + </HiddenPostsProvider> </ExternalEmbedsProvider> </AltTextRequiredProvider> </LanguagesProvider> diff --git a/src/view/com/modals/InAppBrowserConsent.tsx b/src/view/com/modals/InAppBrowserConsent.tsx new file mode 100644 index 000000000..86bb46ca8 --- /dev/null +++ b/src/view/com/modals/InAppBrowserConsent.tsx @@ -0,0 +1,102 @@ +import React from 'react' +import {StyleSheet, View} from 'react-native' + +import {s} from 'lib/styles' +import {Text} from '../util/text/Text' +import {Button} from '../util/forms/Button' +import {ScrollView} from './util' +import {usePalette} from 'lib/hooks/usePalette' + +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useModalControls} from '#/state/modals' +import { + useOpenLink, + useSetInAppBrowser, +} from '#/state/preferences/in-app-browser' + +export const snapPoints = [350] + +export function Component({href}: {href: string}) { + const pal = usePalette('default') + const {closeModal} = useModalControls() + const {_} = useLingui() + const setInAppBrowser = useSetInAppBrowser() + const openLink = useOpenLink() + + const onUseIAB = React.useCallback(() => { + setInAppBrowser(true) + closeModal() + openLink(href, true) + }, [closeModal, setInAppBrowser, href, openLink]) + + const onUseLinking = React.useCallback(() => { + setInAppBrowser(false) + closeModal() + openLink(href, false) + }, [closeModal, setInAppBrowser, href, openLink]) + + return ( + <ScrollView + testID="inAppBrowserConsentModal" + style={[s.flex1, pal.view, {paddingHorizontal: 20, paddingTop: 10}]}> + <Text style={[pal.text, styles.title]}> + <Trans>How should we open this link?</Trans> + </Text> + <Text style={pal.text}> + <Trans> + Your choice will be saved, but can be changed later in settings. + </Trans> + </Text> + <View style={[styles.btnContainer]}> + <Button + testID="confirmBtn" + type="inverted" + onPress={onUseIAB} + accessibilityLabel={_(msg`Use in-app browser`)} + accessibilityHint="" + label={_(msg`Use in-app browser`)} + labelContainerStyle={{justifyContent: 'center', padding: 8}} + labelStyle={[s.f18]} + /> + <Button + testID="confirmBtn" + type="inverted" + onPress={onUseLinking} + accessibilityLabel={_(msg`Use my default browser`)} + accessibilityHint="" + label={_(msg`Use my default browser`)} + labelContainerStyle={{justifyContent: 'center', padding: 8}} + labelStyle={[s.f18]} + /> + <Button + testID="cancelBtn" + type="default" + onPress={() => { + closeModal() + }} + accessibilityLabel={_(msg`Cancel`)} + accessibilityHint="" + label="Cancel" + labelContainerStyle={{justifyContent: 'center', padding: 8}} + labelStyle={[s.f18]} + /> + </View> + </ScrollView> + ) +} + +const styles = StyleSheet.create({ + title: { + textAlign: 'center', + fontWeight: 'bold', + fontSize: 24, + marginBottom: 12, + }, + btnContainer: { + marginTop: 20, + flexDirection: 'column', + justifyContent: 'center', + rowGap: 10, + }, +}) diff --git a/src/view/com/modals/LinkWarning.tsx b/src/view/com/modals/LinkWarning.tsx index 39e6cc3e6..81fdc7285 100644 --- a/src/view/com/modals/LinkWarning.tsx +++ b/src/view/com/modals/LinkWarning.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {Linking, SafeAreaView, StyleSheet, View} from 'react-native' +import {SafeAreaView, StyleSheet, View} from 'react-native' import {ScrollView} from './util' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {Text} from '../util/text/Text' @@ -12,6 +12,7 @@ import {isPossiblyAUrl, splitApexDomain} from 'lib/strings/url-helpers' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useModalControls} from '#/state/modals' +import {useOpenLink} from '#/state/preferences/in-app-browser' export const snapPoints = ['50%'] @@ -21,10 +22,11 @@ export function Component({text, href}: {text: string; href: string}) { const {isMobile} = useWebMediaQueries() const {_} = useLingui() const potentiallyMisleading = isPossiblyAUrl(text) + const openLink = useOpenLink() const onPressVisit = () => { closeModal() - Linking.openURL(href) + openLink(href) } return ( diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index f9d211d07..7f814d971 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -39,6 +39,7 @@ import * as ChangeEmailModal from './ChangeEmail' import * as SwitchAccountModal from './SwitchAccount' import * as LinkWarningModal from './LinkWarning' import * as EmbedConsentModal from './EmbedConsent' +import * as InAppBrowserConsentModal from './InAppBrowserConsent' const DEFAULT_SNAPPOINTS = ['90%'] const HANDLE_HEIGHT = 24 @@ -180,6 +181,9 @@ export function ModalsContainer() { } else if (activeModal?.name === 'embed-consent') { snapPoints = EmbedConsentModal.snapPoints element = <EmbedConsentModal.Component {...activeModal} /> + } else if (activeModal?.name === 'in-app-browser-consent') { + snapPoints = InAppBrowserConsentModal.snapPoints + element = <InAppBrowserConsentModal.Component {...activeModal} /> } else { return null } diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx index dcbec7cb4..4f898767d 100644 --- a/src/view/com/util/Link.tsx +++ b/src/view/com/util/Link.tsx @@ -1,6 +1,5 @@ import React, {ComponentProps, memo, useMemo} from 'react' import { - Linking, GestureResponderEvent, Platform, StyleProp, @@ -31,6 +30,7 @@ import {sanitizeUrl} from '@braintree/sanitize-url' import {PressableWithHover} from './PressableWithHover' import FixedTouchableHighlight from '../pager/FixedTouchableHighlight' import {useModalControls} from '#/state/modals' +import {useOpenLink} from '#/state/preferences/in-app-browser' type Event = | React.MouseEvent<HTMLAnchorElement, MouseEvent> @@ -65,6 +65,7 @@ export const Link = memo(function Link({ const {closeModal} = useModalControls() const navigation = useNavigation<NavigationProp>() const anchorHref = asAnchor ? sanitizeUrl(href) : undefined + const openLink = useOpenLink() const onPress = React.useCallback( (e?: Event) => { @@ -74,11 +75,12 @@ export const Link = memo(function Link({ navigation, sanitizeUrl(href), navigationAction, + openLink, e, ) } }, - [closeModal, navigation, navigationAction, href], + [closeModal, navigation, navigationAction, href, openLink], ) if (noFeedback) { @@ -172,6 +174,7 @@ export const TextLink = memo(function TextLink({ const {...props} = useLinkProps({to: sanitizeUrl(href)}) const navigation = useNavigation<NavigationProp>() const {openModal, closeModal} = useModalControls() + const openLink = useOpenLink() if (warnOnMismatchingLabel && typeof text !== 'string') { console.error('Unable to detect mismatching label') @@ -200,6 +203,7 @@ export const TextLink = memo(function TextLink({ navigation, sanitizeUrl(href), navigationAction, + openLink, e, ) }, @@ -212,6 +216,7 @@ export const TextLink = memo(function TextLink({ text, warnOnMismatchingLabel, navigationAction, + openLink, ], ) const hrefAttrs = useMemo(() => { @@ -317,6 +322,7 @@ function onPressInner( navigation: NavigationProp, href: string, navigationAction: 'push' | 'replace' | 'navigate' = 'push', + openLink: (href: string) => void, e?: Event, ) { let shouldHandle = false @@ -345,7 +351,7 @@ function onPressInner( if (shouldHandle) { href = convertBskyAppUrlIfNeeded(href) if (newTab || href.startsWith('http') || href.startsWith('mailto')) { - Linking.openURL(href) + openLink(href) } else { closeModal() // close any active modals diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index c078e7a23..b4a3acbe3 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -70,6 +70,11 @@ import {useLingui} from '@lingui/react' import {useQueryClient} from '@tanstack/react-query' import {useLoggedOutViewControls} from '#/state/shell/logged-out' import {useCloseAllActiveElements} from '#/state/util' +import { + useInAppBrowser, + useSetInAppBrowser, +} from '#/state/preferences/in-app-browser' +import {isNative} from '#/platform/detection' function SettingsAccountCard({account}: {account: SessionAccount}) { const pal = usePalette('default') @@ -146,6 +151,8 @@ export function SettingsScreen({}: Props) { const setMinimalShellMode = useSetMinimalShellMode() const requireAltTextEnabled = useRequireAltTextEnabled() const setRequireAltTextEnabled = useSetRequireAltTextEnabled() + const inAppBrowserPref = useInAppBrowser() + const setUseInAppBrowser = useSetInAppBrowser() const onboardingDispatch = useOnboardingDispatch() const navigation = useNavigation<NavigationProp>() const {isMobile} = useWebMediaQueries() @@ -658,6 +665,17 @@ export function SettingsScreen({}: Props) { <Trans>Change handle</Trans> </Text> </TouchableOpacity> + {isNative && ( + <View style={[pal.view, styles.toggleCard]}> + <ToggleButton + type="default-light" + label={_(msg`Open links with in-app browser`)} + labelType="lg" + isSelected={inAppBrowserPref ?? false} + onPress={() => setUseInAppBrowser(!inAppBrowserPref)} + /> + </View> + )} <View style={styles.spacer20} /> <Text type="xl-bold" style={[pal.text, styles.heading]}> <Trans>Danger Zone</Trans> diff --git a/yarn.lock b/yarn.lock index c1db264bc..7f9de6b9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9583,6 +9583,13 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== +compare-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/compare-urls/-/compare-urls-2.0.0.tgz#9b378c4abd43980a8700fffec9afb85de4df9075" + integrity sha512-eCJcWn2OYFEIqbm70ta7LQowJOOZZqq1a2YbbFCFI1uwSvj+TWMwXVn7vPR1ceFNcAIt5RSTDbwdlX82gYLTkA== + dependencies: + normalize-url "^2.0.1" + component-type@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.1.tgz#8a47901700238e4fc32269771230226f24b415a9" @@ -10136,7 +10143,7 @@ decimal.js@^10.2.1, decimal.js@^10.4.2: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== -decode-uri-component@^0.2.2: +decode-uri-component@^0.2.0, decode-uri-component@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== @@ -11687,6 +11694,14 @@ expo-updates@~0.24.5: fbemitter "^3.0.0" resolve-from "^5.0.0" +expo-web-browser@^12.5.0: + version "12.5.0" + resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-12.5.0.tgz#69949c50ef0ef8d2889435ed9e595206cfbcf68b" + integrity sha512-3uDzP19DqcEicLOB4ZH6pGWzxlCQ8mLHSmWMmfXEBhZjooUkHUrysbzkNvQQa24ijy3uoUybX4jW0xPss594kA== + dependencies: + compare-urls "^2.0.0" + url "^0.11.0" + expo@^50.0.0-preview.7: version "50.0.0-preview.7" resolved "https://registry.yarnpkg.com/expo/-/expo-50.0.0-preview.7.tgz#d4ac7a9aad0a5e9f03a31b8794e186a1af741edc" @@ -13341,6 +13356,11 @@ is-path-inside@^3.0.2, is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -16139,6 +16159,15 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +normalize-url@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + normalize-url@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" @@ -16408,11 +16437,6 @@ open@^8.0.4, open@^8.0.9, open@^8.3.0, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -opencollective-postinstall@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" - integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== - optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -17572,6 +17596,11 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -17906,6 +17935,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0, punycode@^2.1.1: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" @@ -17933,13 +17967,22 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.5.1: +qs@^6.11.2, qs@^6.5.1: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== dependencies: side-channel "^1.0.4" +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + query-string@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" @@ -18178,14 +18221,6 @@ react-native-image-crop-picker@^0.38.1: resolved "https://registry.yarnpkg.com/react-native-image-crop-picker/-/react-native-image-crop-picker-0.38.1.tgz#5973b4a8b55835b987e6be2064de411e849ac005" integrity sha512-cF5UQnWplzHCeiCO+aiGS/0VomWaLmFf3nSsgTMPfY+8+99h8N/eHQvVdSF7RsGw50B8394wGeGyqHjjp8YRWw== -react-native-inappbrowser-reborn@^3.6.3: - version "3.7.0" - resolved "https://registry.yarnpkg.com/react-native-inappbrowser-reborn/-/react-native-inappbrowser-reborn-3.7.0.tgz#849a43c3c7da22b65147649fe596836bcb494083" - integrity sha512-Ia53jYNtFcbNaX5W3QfOmN25I7bcvuDiQmSY5zABXjy4+WI20bPc9ua09li55F8yDCjv3C99jX6vKms68mBV7g== - dependencies: - invariant "^2.2.4" - opencollective-postinstall "^2.0.3" - react-native-ios-context-menu@^1.15.3: version "1.15.3" resolved "https://registry.yarnpkg.com/react-native-ios-context-menu/-/react-native-ios-context-menu-1.15.3.tgz#c02e6a7af2df8c08d0b3e1c8f3395484b3c9c760" @@ -19454,6 +19489,13 @@ sonic-boom@^3.1.0: dependencies: atomic-sleep "^1.0.0" +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + integrity sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg== + dependencies: + is-plain-obj "^1.0.0" + source-list-map@^2.0.0, source-list-map@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" @@ -19679,6 +19721,11 @@ streamx@^2.15.0: fast-fifo "^1.1.0" queue-tick "^1.0.1" +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== + strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -20758,6 +20805,14 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +url@^0.11.0: + version "0.11.3" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.3.tgz#6f495f4b935de40ce4a0a52faee8954244f3d3ad" + integrity sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw== + dependencies: + punycode "^1.4.1" + qs "^6.11.2" + use-callback-ref@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5" |