From ed146a582c140b9a472298390dafbc07bd06cf60 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 21 Nov 2022 16:07:26 -0600 Subject: Add web linking and proper share controls --- src/App.native.tsx | 9 ++++ src/state/models/navigation.ts | 18 ++++++++ src/state/models/shell-ui.ts | 29 ------------ src/view/com/modals/LinkActions.tsx | 72 ----------------------------- src/view/com/modals/Modal.tsx | 18 +------- src/view/com/modals/SharePost.native.tsx | 43 ----------------- src/view/com/modals/SharePost.tsx | 57 ----------------------- src/view/com/post-thread/PostThread.tsx | 12 +---- src/view/com/post-thread/PostThreadItem.tsx | 2 - src/view/com/util/DropdownBtn.tsx | 6 ++- src/view/com/util/Link.tsx | 1 - src/view/lib/strings.ts | 9 ++++ src/view/shell/mobile/TabsSelector.tsx | 11 ++--- 13 files changed, 45 insertions(+), 242 deletions(-) delete mode 100644 src/view/com/modals/LinkActions.tsx delete mode 100644 src/view/com/modals/SharePost.native.tsx delete mode 100644 src/view/com/modals/SharePost.tsx (limited to 'src') diff --git a/src/App.native.tsx b/src/App.native.tsx index 3d3e5f1b0..65a77c3dc 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -1,5 +1,6 @@ import 'react-native-url-polyfill/auto' import React, {useState, useEffect} from 'react' +import {Linking} from 'react-native' import {RootSiblingParent} from 'react-native-root-siblings' import {GestureHandlerRootView} from 'react-native-gesture-handler' import SplashScreen from 'react-native-splash-screen' @@ -24,6 +25,14 @@ function App() { .then(store => { setRootStore(store) SplashScreen.hide() + Linking.getInitialURL().then((url: string | null) => { + if (url) { + store.nav.handleLink(url) + } + }) + Linking.addEventListener('url', ({url}) => { + store.nav.handleLink(url) + }) }) }, []) diff --git a/src/state/models/navigation.ts b/src/state/models/navigation.ts index 0ec097afc..a4d7d443b 100644 --- a/src/state/models/navigation.ts +++ b/src/state/models/navigation.ts @@ -222,6 +222,24 @@ export class NavigationModel { this.tabs.find(t => t.id === ptr[0])?.setTitle(ptr[1], title) } + handleLink(url: string) { + let path + if (url.startsWith('/')) { + path = url + } else if (url.startsWith('http')) { + try { + path = new URL(url).pathname + } catch (e) { + console.error('Invalid url', url, e) + return + } + } else { + console.error('Invalid url', url) + return + } + this.navigate(path) + } + // tab management // = diff --git a/src/state/models/shell-ui.ts b/src/state/models/shell-ui.ts index 73b1bd56e..13d720730 100644 --- a/src/state/models/shell-ui.ts +++ b/src/state/models/shell-ui.ts @@ -2,23 +2,6 @@ import {makeAutoObservable} from 'mobx' import {ProfileViewModel} from './profile-view' import * as Post from '../../third-party/api/src/client/types/app/bsky/feed/post' -export interface LinkActionsModelOpts { - newTab?: boolean -} -export class LinkActionsModel { - name = 'link-actions' - newTab: boolean - - constructor( - public href: string, - public title: string, - opts?: LinkActionsModelOpts, - ) { - makeAutoObservable(this) - this.newTab = typeof opts?.newTab === 'boolean' ? opts.newTab : true - } -} - export class ConfirmModel { name = 'confirm' @@ -31,14 +14,6 @@ export class ConfirmModel { } } -export class SharePostModel { - name = 'share-post' - - constructor(public href: string) { - makeAutoObservable(this) - } -} - export class EditProfileModel { name = 'edit-profile' @@ -85,9 +60,7 @@ export interface ComposerOpts { export class ShellUiModel { isModalActive = false activeModal: - | LinkActionsModel | ConfirmModel - | SharePostModel | EditProfileModel | CreateSceneModel | ServerInputModel @@ -101,9 +74,7 @@ export class ShellUiModel { openModal( modal: - | LinkActionsModel | ConfirmModel - | SharePostModel | EditProfileModel | CreateSceneModel | ServerInputModel, diff --git a/src/view/com/modals/LinkActions.tsx b/src/view/com/modals/LinkActions.tsx deleted file mode 100644 index deb1518ec..000000000 --- a/src/view/com/modals/LinkActions.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react' -import Toast from '../util/Toast' -import Clipboard from '@react-native-clipboard/clipboard' -import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {useStores} from '../../../state' -import {s, colors} from '../../lib/styles' - -export const snapPoints = ['30%'] - -export function Component({ - title, - href, - newTab, -}: { - title: string - href: string - newTab: boolean -}) { - const store = useStores() - - const onPressOpenNewTab = () => { - store.shell.closeModal() - store.nav.newTab(href) - } - - const onPressCopy = () => { - Clipboard.setString(href) - store.shell.closeModal() - Toast.show('Link copied', { - position: Toast.positions.TOP, - }) - } - - return ( - - {title || href} - - {newTab ? ( - - - Open in new tab - - ) : undefined} - - - Copy to clipboard - - - - ) -} - -const styles = StyleSheet.create({ - btn: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - width: '100%', - borderColor: colors.gray5, - borderWidth: 1, - borderRadius: 4, - padding: 10, - marginBottom: 10, - }, - icon: { - marginRight: 8, - }, -}) diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index 3317fef08..9d7033411 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -7,9 +7,7 @@ import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop' import * as models from '../../../state/models/shell-ui' -import * as LinkActionsModal from './LinkActions' import * as ConfirmModal from './Confirm' -import * as SharePostModal from './SharePost.native' import * as EditProfileModal from './EditProfile' import * as CreateSceneModal from './CreateScene' import * as InviteToSceneModal from './InviteToScene' @@ -41,27 +39,13 @@ export const Modal = observer(function Modal() { let snapPoints: (string | number)[] = CLOSED_SNAPPOINTS let element - if (store.shell.activeModal?.name === 'link-actions') { - snapPoints = LinkActionsModal.snapPoints - element = ( - - ) - } else if (store.shell.activeModal?.name === 'confirm') { + if (store.shell.activeModal?.name === 'confirm') { snapPoints = ConfirmModal.snapPoints element = ( ) - } else if (store.shell.activeModal?.name === 'share-post') { - snapPoints = SharePostModal.snapPoints - element = ( - - ) } else if (store.shell.activeModal?.name === 'edit-profile') { snapPoints = EditProfileModal.snapPoints element = ( diff --git a/src/view/com/modals/SharePost.native.tsx b/src/view/com/modals/SharePost.native.tsx deleted file mode 100644 index 01692fb74..000000000 --- a/src/view/com/modals/SharePost.native.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react' -import {Button, StyleSheet, Text, TouchableOpacity, View} from 'react-native' -import Toast from '../util/Toast' -import Clipboard from '@react-native-clipboard/clipboard' -import {s} from '../../lib/styles' -import {useStores} from '../../../state' - -export const snapPoints = ['30%'] - -export function Component({href}: {href: string}) { - const store = useStores() - const onPressCopy = () => { - Clipboard.setString(href) - Toast.show('Link copied', { - position: Toast.positions.TOP, - }) - store.shell.closeModal() - } - const onClose = () => store.shell.closeModal() - - return ( - - Share this post - {href} -