about summary refs log tree commit diff
path: root/src/state/preferences
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2024-01-12 10:19:56 -0800
committerGitHub <noreply@github.com>2024-01-12 10:19:56 -0800
commit998ee2998657e82395fe4462809c376ffbd03ed8 (patch)
tree4eb3930734b939c0cfaa36f39a84fd27ca3a831c /src/state/preferences
parentb147f7ae8a5c8c3a1ec9981132b4c6447034963f (diff)
downloadvoidsky-998ee2998657e82395fe4462809c376ffbd03ed8.tar.zst
(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>
Diffstat (limited to 'src/state/preferences')
-rw-r--r--src/state/preferences/in-app-browser.tsx79
-rw-r--r--src/state/preferences/index.tsx5
2 files changed, 83 insertions, 1 deletions
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>