(optional) In app browser (#2490)
* add expo web browser + modal * add in app browser option to settings * don't show toggle on web * Tweak browser-choice UIs --------- Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
parent
b147f7ae8a
commit
998ee29986
11 changed files with 299 additions and 22 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
79
src/state/preferences/in-app-browser.tsx
Normal file
79
src/state/preferences/in-app-browser.tsx
Normal file
|
@ -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
|
||||
}
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue