about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/view/index.ts8
-rw-r--r--src/view/shell/mobile/index.tsx17
-rw-r--r--src/view/shell/mobile/location-menu.tsx217
-rw-r--r--src/view/shell/mobile/location-navigator.tsx176
4 files changed, 255 insertions, 163 deletions
diff --git a/src/view/index.ts b/src/view/index.ts
index 9fcebcc3b..3dcadf676 100644
--- a/src/view/index.ts
+++ b/src/view/index.ts
@@ -3,6 +3,8 @@ import {library} from '@fortawesome/fontawesome-svg-core'
 import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft'
 import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight'
 import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft'
+import {faArrowUpFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowUpFromBracket'
+import {faArrowUpRightFromSquare} from '@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare'
 import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
 import {faBell} from '@fortawesome/free-solid-svg-icons/faBell'
 import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell'
@@ -16,10 +18,12 @@ import {faGear} from '@fortawesome/free-solid-svg-icons/faGear'
 import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
 import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart'
 import {faHouse} from '@fortawesome/free-solid-svg-icons/faHouse'
+import {faLink} from '@fortawesome/free-solid-svg-icons/faLink'
 import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass'
 import {faMessage} from '@fortawesome/free-regular-svg-icons/faMessage'
 import {faPenNib} from '@fortawesome/free-solid-svg-icons/faPenNib'
 import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus'
+import {faShare} from '@fortawesome/free-solid-svg-icons/faShare'
 import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSquare'
 import {faRetweet} from '@fortawesome/free-solid-svg-icons/faRetweet'
 import {faUser} from '@fortawesome/free-regular-svg-icons/faUser'
@@ -31,6 +35,8 @@ export function setup() {
     faAngleLeft,
     faAngleRight,
     faArrowLeft,
+    faArrowUpFromBracket,
+    faArrowUpRightFromSquare,
     faBars,
     faBell,
     farBell,
@@ -44,11 +50,13 @@ export function setup() {
     faHeart,
     fasHeart,
     faHouse,
+    faLink,
     faMagnifyingGlass,
     faMessage,
     faPenNib,
     faPlus,
     faRetweet,
+    faShare,
     faShareFromSquare,
     faUser,
     faUsers,
diff --git a/src/view/shell/mobile/index.tsx b/src/view/shell/mobile/index.tsx
index 3d35efa1a..8ce2e63d7 100644
--- a/src/view/shell/mobile/index.tsx
+++ b/src/view/shell/mobile/index.tsx
@@ -16,9 +16,10 @@ import {useStores} from '../../../state'
 import {NavigationModel} from '../../../state/models/navigation'
 import {match, MatchResult} from '../../routes'
 import {TabsSelectorModal} from './tabs-selector'
-import {LocationMenu} from './location-menu'
+import {LocationNavigator} from './location-navigator'
 import {createBackMenu, createForwardMenu} from './history-menu'
 import {createAccountsMenu} from './accounts-menu'
+import {createLocationMenu} from './location-menu'
 import {colors} from '../../lib/styles'
 import {AVIS} from '../../lib/assets'
 
@@ -99,11 +100,13 @@ export const MobileShell: React.FC = observer(() => {
 
   const onPressAvi = () => createAccountsMenu()
   const onPressLocation = () => setLocationMenuActive(true)
-  const onNavigateLocationMenu = (url: string) => {
+  const onPressEllipsis = () => createLocationMenu()
+
+  const onNavigateLocation = (url: string) => {
     setLocationMenuActive(false)
     stores.nav.navigate(url)
   }
-  const onDismissLocationMenu = () => setLocationMenuActive(false)
+  const onDismissLocationNavigator = () => setLocationMenuActive(false)
 
   const onPressBack = () => stores.nav.tab.goBack()
   const onPressForward = () => stores.nav.tab.goForward()
@@ -129,7 +132,7 @@ export const MobileShell: React.FC = observer(() => {
           title={stores.nav.tab.current.title}
           onPress={onPressLocation}
         />
-        <TouchableOpacity style={styles.topBarBtn}>
+        <TouchableOpacity style={styles.topBarBtn} onPress={onPressEllipsis}>
           <FontAwesomeIcon icon="ellipsis" />
         </TouchableOpacity>
       </View>
@@ -171,10 +174,10 @@ export const MobileShell: React.FC = observer(() => {
         onCloseTab={onCloseTab}
       />
       {isLocationMenuActive && (
-        <LocationMenu
+        <LocationNavigator
           url={stores.nav.tab.current.url}
-          onNavigate={onNavigateLocationMenu}
-          onDismiss={onDismissLocationMenu}
+          onNavigate={onNavigateLocation}
+          onDismiss={onDismissLocationNavigator}
         />
       )}
     </View>
diff --git a/src/view/shell/mobile/location-menu.tsx b/src/view/shell/mobile/location-menu.tsx
index 5e3e7eb77..b5f4d8036 100644
--- a/src/view/shell/mobile/location-menu.tsx
+++ b/src/view/shell/mobile/location-menu.tsx
@@ -1,176 +1,81 @@
-import React, {useState, useRef} from 'react'
-import {StyleSheet, Text, TextInput, TouchableOpacity, View} from 'react-native'
-import LinearGradient from 'react-native-linear-gradient'
+import React from 'react'
+import {
+  StyleSheet,
+  Text,
+  TouchableOpacity,
+  TouchableWithoutFeedback,
+  View,
+} from 'react-native'
+import RootSiblings from 'react-native-root-siblings'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {IconProp} from '@fortawesome/fontawesome-svg-core'
-import {s, gradients, colors} from '../../lib/styles'
+import {s, colors} from '../../lib/styles'
 
-export function LocationMenu({
-  url,
-  onNavigate,
-  onDismiss,
-}: {
-  url: string
-  onNavigate: (url: string) => void
-  onDismiss: () => void
-}) {
-  const [searchText, onChangeSearchText] = useState(url !== '/' ? url : '')
-  const inputRef = useRef<TextInput | null>(null)
-
-  const onFocusSearchText = () => {
-    if (inputRef.current && searchText.length) {
-      // select the text on focus
-      inputRef.current.setNativeProps({
-        selection: {start: 0, end: searchText.length},
-      })
-    }
+export function createLocationMenu(): RootSiblings {
+  const onPressItem = (_index: number) => {
+    sibling.destroy()
   }
-
-  const FatMenuItem = ({
-    icon,
-    label,
-    url,
-    gradient,
-  }: {
-    icon: IconProp
-    label: string
-    url: string
-    gradient: keyof typeof gradients
-  }) => (
-    <TouchableOpacity
-      style={styles.fatMenuItem}
-      onPress={() => onNavigate(url)}>
-      <LinearGradient
-        style={[styles.fatMenuItemIconWrapper]}
-        colors={[gradients[gradient].start, gradients[gradient].end]}
-        start={{x: 0, y: 0}}
-        end={{x: 1, y: 1}}>
-        <FontAwesomeIcon icon={icon} style={styles.fatMenuItemIcon} size={24} />
-      </LinearGradient>
-      <Text style={styles.fatMenuItemLabel}>{label}</Text>
-    </TouchableOpacity>
-  )
-
-  const ThinMenuItem = ({label, url}: {label: string; url: string}) => (
-    <TouchableOpacity
-      style={styles.thinMenuItem}
-      onPress={() => onNavigate(url)}>
-      <Text style={styles.thinMenuItemLabel}>{label}</Text>
-    </TouchableOpacity>
-  )
-
-  return (
-    <View style={styles.menu}>
-      <View style={styles.searchContainer}>
-        <FontAwesomeIcon
-          icon="magnifying-glass"
-          size={18}
-          style={styles.searchIcon}
-        />
-        <TextInput
-          autoFocus
-          ref={inputRef}
-          value={searchText}
-          style={styles.searchInput}
-          onChangeText={onChangeSearchText}
-          onFocus={onFocusSearchText}
-        />
-        <TouchableOpacity onPress={() => onDismiss()}>
-          <Text style={[s.blue3, s.f15]}>Cancel</Text>
-        </TouchableOpacity>
-      </View>
-      <View style={styles.menuItemsContainer}>
-        <View style={styles.fatMenuItems}>
-          <FatMenuItem icon="house" label="Feed" url="/" gradient="primary" />
-          <FatMenuItem
-            icon="bell"
-            label="Notifications"
-            url="/notifications"
-            gradient="purple"
-          />
-          <FatMenuItem
-            icon={['far', 'user']}
-            label="My Profile"
-            url="/"
-            gradient="blue"
-          />
-          <FatMenuItem icon="gear" label="Settings" url="/" gradient="blue" />
-        </View>
-        <View style={styles.thinMenuItems}>
-          <ThinMenuItem label="Send us feedback" url="/" />
-          <ThinMenuItem label="Get help..." url="/" />
-          <ThinMenuItem label="Settings" url="/" />
+  const onOuterPress = () => sibling.destroy()
+  const sibling = new RootSiblings(
+    (
+      <>
+        <TouchableWithoutFeedback onPress={onOuterPress}>
+          <View style={styles.bg} />
+        </TouchableWithoutFeedback>
+        <View style={[styles.menu]}>
+          <TouchableOpacity
+            style={[styles.menuItem]}
+            onPress={() => onPressItem(0)}>
+            <FontAwesomeIcon style={styles.icon} icon="share" />
+            <Text style={styles.label}>Share</Text>
+          </TouchableOpacity>
+          <TouchableOpacity
+            style={[styles.menuItem, styles.menuItemBorder]}
+            onPress={() => onPressItem(0)}>
+            <FontAwesomeIcon style={styles.icon} icon="link" />
+            <Text style={styles.label}>Copy Link</Text>
+          </TouchableOpacity>
         </View>
-      </View>
-    </View>
+      </>
+    ),
   )
+  return sibling
 }
 
 const styles = StyleSheet.create({
-  menu: {
+  bg: {
     position: 'absolute',
-    left: 0,
     top: 0,
-    width: '100%',
-    height: '100%',
+    right: 0,
+    bottom: 0,
+    left: 0,
+    backgroundColor: '#000',
+    opacity: 0.1,
+  },
+  menu: {
+    position: 'absolute',
+    right: 4,
+    top: 70,
     backgroundColor: '#fff',
+    borderRadius: 14,
     opacity: 1,
+    paddingVertical: 2,
   },
-  searchContainer: {
+  menuItem: {
     flexDirection: 'row',
-    backgroundColor: colors.gray1,
-    borderBottomWidth: 1,
-    borderColor: colors.gray2,
-    paddingHorizontal: 16,
-    paddingTop: 48,
-    paddingBottom: 8,
-  },
-  searchIcon: {
-    color: colors.gray5,
-    marginRight: 8,
-  },
-  searchInput: {
-    flex: 1,
-  },
-  menuItemsContainer: {
-    paddingVertical: 30,
-    paddingHorizontal: 8,
-  },
-  fatMenuItems: {
-    flexDirection: 'row',
-    marginBottom: 20,
-  },
-  fatMenuItem: {
-    width: 86,
-    alignItems: 'center',
-    marginRight: 6,
-  },
-  fatMenuItemIconWrapper: {
-    borderRadius: 6,
-    width: 50,
-    height: 50,
-    justifyContent: 'center',
     alignItems: 'center',
-    marginBottom: 5,
-    shadowColor: '#000',
-    shadowOpacity: 0.2,
-    shadowOffset: {width: 0, height: 2},
-    shadowRadius: 2,
+    paddingVertical: 8,
+    paddingLeft: 10,
+    paddingRight: 30,
   },
-  fatMenuItemIcon: {
-    color: colors.white,
+  menuItemBorder: {
+    borderTopWidth: 1,
+    borderTopColor: colors.gray1,
   },
-  fatMenuItemLabel: {
-    fontSize: 12,
-  },
-  thinMenuItems: {
-    paddingHorizontal: 18,
-  },
-  thinMenuItem: {
-    paddingVertical: 4,
+  icon: {
+    marginLeft: 6,
+    marginRight: 8,
   },
-  thinMenuItemLabel: {
-    color: colors.blue3,
-    fontSize: 16,
+  label: {
+    fontSize: 15,
   },
 })
diff --git a/src/view/shell/mobile/location-navigator.tsx b/src/view/shell/mobile/location-navigator.tsx
new file mode 100644
index 000000000..28ca23101
--- /dev/null
+++ b/src/view/shell/mobile/location-navigator.tsx
@@ -0,0 +1,176 @@
+import React, {useState, useRef} from 'react'
+import {StyleSheet, Text, TextInput, TouchableOpacity, View} from 'react-native'
+import LinearGradient from 'react-native-linear-gradient'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {IconProp} from '@fortawesome/fontawesome-svg-core'
+import {s, gradients, colors} from '../../lib/styles'
+
+export function LocationNavigator({
+  url,
+  onNavigate,
+  onDismiss,
+}: {
+  url: string
+  onNavigate: (url: string) => void
+  onDismiss: () => void
+}) {
+  const [searchText, onChangeSearchText] = useState(url !== '/' ? url : '')
+  const inputRef = useRef<TextInput | null>(null)
+
+  const onFocusSearchText = () => {
+    if (inputRef.current && searchText.length) {
+      // select the text on focus
+      inputRef.current.setNativeProps({
+        selection: {start: 0, end: searchText.length},
+      })
+    }
+  }
+
+  const FatMenuItem = ({
+    icon,
+    label,
+    url,
+    gradient,
+  }: {
+    icon: IconProp
+    label: string
+    url: string
+    gradient: keyof typeof gradients
+  }) => (
+    <TouchableOpacity
+      style={styles.fatMenuItem}
+      onPress={() => onNavigate(url)}>
+      <LinearGradient
+        style={[styles.fatMenuItemIconWrapper]}
+        colors={[gradients[gradient].start, gradients[gradient].end]}
+        start={{x: 0, y: 0}}
+        end={{x: 1, y: 1}}>
+        <FontAwesomeIcon icon={icon} style={styles.fatMenuItemIcon} size={24} />
+      </LinearGradient>
+      <Text style={styles.fatMenuItemLabel}>{label}</Text>
+    </TouchableOpacity>
+  )
+
+  const ThinMenuItem = ({label, url}: {label: string; url: string}) => (
+    <TouchableOpacity
+      style={styles.thinMenuItem}
+      onPress={() => onNavigate(url)}>
+      <Text style={styles.thinMenuItemLabel}>{label}</Text>
+    </TouchableOpacity>
+  )
+
+  return (
+    <View style={styles.menu}>
+      <View style={styles.searchContainer}>
+        <FontAwesomeIcon
+          icon="magnifying-glass"
+          size={18}
+          style={styles.searchIcon}
+        />
+        <TextInput
+          autoFocus
+          ref={inputRef}
+          value={searchText}
+          style={styles.searchInput}
+          onChangeText={onChangeSearchText}
+          onFocus={onFocusSearchText}
+        />
+        <TouchableOpacity onPress={() => onDismiss()}>
+          <Text style={[s.blue3, s.f15]}>Cancel</Text>
+        </TouchableOpacity>
+      </View>
+      <View style={styles.menuItemsContainer}>
+        <View style={styles.fatMenuItems}>
+          <FatMenuItem icon="house" label="Feed" url="/" gradient="primary" />
+          <FatMenuItem
+            icon="bell"
+            label="Notifications"
+            url="/notifications"
+            gradient="purple"
+          />
+          <FatMenuItem
+            icon={['far', 'user']}
+            label="My Profile"
+            url="/"
+            gradient="blue"
+          />
+          <FatMenuItem icon="gear" label="Settings" url="/" gradient="blue" />
+        </View>
+        <View style={styles.thinMenuItems}>
+          <ThinMenuItem label="Send us feedback" url="/" />
+          <ThinMenuItem label="Get help..." url="/" />
+          <ThinMenuItem label="Settings" url="/" />
+        </View>
+      </View>
+    </View>
+  )
+}
+
+const styles = StyleSheet.create({
+  menu: {
+    position: 'absolute',
+    left: 0,
+    top: 0,
+    width: '100%',
+    height: '100%',
+    backgroundColor: '#fff',
+    opacity: 1,
+  },
+  searchContainer: {
+    flexDirection: 'row',
+    backgroundColor: colors.gray1,
+    borderBottomWidth: 1,
+    borderColor: colors.gray2,
+    paddingHorizontal: 16,
+    paddingTop: 48,
+    paddingBottom: 8,
+  },
+  searchIcon: {
+    color: colors.gray5,
+    marginRight: 8,
+  },
+  searchInput: {
+    flex: 1,
+  },
+  menuItemsContainer: {
+    paddingVertical: 30,
+    paddingHorizontal: 8,
+  },
+  fatMenuItems: {
+    flexDirection: 'row',
+    marginBottom: 20,
+  },
+  fatMenuItem: {
+    width: 86,
+    alignItems: 'center',
+    marginRight: 6,
+  },
+  fatMenuItemIconWrapper: {
+    borderRadius: 6,
+    width: 50,
+    height: 50,
+    justifyContent: 'center',
+    alignItems: 'center',
+    marginBottom: 5,
+    shadowColor: '#000',
+    shadowOpacity: 0.2,
+    shadowOffset: {width: 0, height: 2},
+    shadowRadius: 2,
+  },
+  fatMenuItemIcon: {
+    color: colors.white,
+  },
+  fatMenuItemLabel: {
+    fontSize: 12,
+  },
+  thinMenuItems: {
+    paddingHorizontal: 18,
+  },
+  thinMenuItem: {
+    paddingVertical: 4,
+  },
+  thinMenuItemLabel: {
+    color: colors.blue3,
+    fontSize: 16,
+  },
+})