about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/index.ts2
-rw-r--r--src/view/shell/mobile/index.tsx33
-rw-r--r--src/view/shell/mobile/location-menu.tsx183
3 files changed, 214 insertions, 4 deletions
diff --git a/src/view/index.ts b/src/view/index.ts
index 89db506d0..9fcebcc3b 100644
--- a/src/view/index.ts
+++ b/src/view/index.ts
@@ -12,6 +12,7 @@ import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
 import {faClone} from '@fortawesome/free-regular-svg-icons/faClone'
 import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
 import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis'
+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'
@@ -39,6 +40,7 @@ export function setup() {
     faClone,
     faComment,
     faEllipsis,
+    faGear,
     faHeart,
     fasHeart,
     faHouse,
diff --git a/src/view/shell/mobile/index.tsx b/src/view/shell/mobile/index.tsx
index 4dd5cf349..68387883b 100644
--- a/src/view/shell/mobile/index.tsx
+++ b/src/view/shell/mobile/index.tsx
@@ -1,4 +1,4 @@
-import React, {useRef} from 'react'
+import React, {useState, useRef} from 'react'
 import {observer} from 'mobx-react-lite'
 import {
   GestureResponderEvent,
@@ -16,16 +16,25 @@ 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 {createBackMenu, createForwardMenu} from './history-menu'
 import {colors} from '../../lib/styles'
 import {AVIS} from '../../lib/assets'
 
 const locationIconNeedsNudgeUp = (icon: IconProp) => icon === 'house'
 
-const Location = ({icon, title}: {icon: IconProp; title?: string}) => {
+const Location = ({
+  icon,
+  title,
+  onPress,
+}: {
+  icon: IconProp
+  title?: string
+  onPress?: (event: GestureResponderEvent) => void
+}) => {
   const nudgeUp = locationIconNeedsNudgeUp(icon)
   return (
-    <TouchableOpacity style={styles.location}>
+    <TouchableOpacity style={styles.location} onPress={onPress}>
       {title ? (
         <FontAwesomeIcon
           size={12}
@@ -84,8 +93,16 @@ const Btn = ({
 export const MobileShell: React.FC = observer(() => {
   const stores = useStores()
   const tabSelectorRef = useRef<{open: () => void}>()
+  const [isLocationMenuActive, setLocationMenuActive] = useState(false)
   const screenRenderDesc = constructScreenRenderDesc(stores.nav)
 
+  const onPressLocation = () => setLocationMenuActive(true)
+  const onNavigateLocationMenu = (url: string) => {
+    setLocationMenuActive(false)
+    stores.nav.navigate(url)
+  }
+  const onDismissLocationMenu = () => setLocationMenuActive(false)
+
   const onPressBack = () => stores.nav.tab.goBack()
   const onPressForward = () => stores.nav.tab.goForward()
   const onPressHome = () => stores.nav.navigate('/')
@@ -102,10 +119,11 @@ export const MobileShell: React.FC = observer(() => {
   return (
     <View style={styles.outerContainer}>
       <View style={styles.topBar}>
-        <Image style={styles.avi} source={AVIS['carla.com']} />
+        <Image style={styles.avi} source={AVIS['alice.com']} />
         <Location
           icon={screenRenderDesc.icon}
           title={stores.nav.tab.current.title}
+          onPress={onPressLocation}
         />
         <TouchableOpacity style={styles.topBarBtn}>
           <FontAwesomeIcon icon="ellipsis" />
@@ -148,6 +166,13 @@ export const MobileShell: React.FC = observer(() => {
         onChangeTab={onChangeTab}
         onCloseTab={onCloseTab}
       />
+      {isLocationMenuActive && (
+        <LocationMenu
+          url={stores.nav.tab.current.url}
+          onNavigate={onNavigateLocationMenu}
+          onDismiss={onDismissLocationMenu}
+        />
+      )}
     </View>
   )
 })
diff --git a/src/view/shell/mobile/location-menu.tsx b/src/view/shell/mobile/location-menu.tsx
new file mode 100644
index 000000000..77d09a226
--- /dev/null
+++ b/src/view/shell/mobile/location-menu.tsx
@@ -0,0 +1,183 @@
+import React, {useState, useRef} from 'react'
+import {
+  SafeAreaView,
+  StyleSheet,
+  Text,
+  TextInput,
+  TouchableOpacity,
+  TouchableWithoutFeedback,
+  View,
+} from 'react-native'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {IconProp} from '@fortawesome/fontawesome-svg-core'
+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},
+      })
+    }
+  }
+
+  const FatMenuItem = ({
+    icon,
+    label,
+    url,
+    color,
+  }: {
+    icon: IconProp
+    label: string
+    url: string
+    color: string
+  }) => (
+    <TouchableOpacity
+      style={styles.fatMenuItem}
+      onPress={() => onNavigate(url)}>
+      <View style={[styles.fatMenuItemIconWrapper, {backgroundColor: color}]}>
+        <FontAwesomeIcon icon={icon} style={styles.fatMenuItemIcon} size={24} />
+      </View>
+      <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="/" color={colors.red3} />
+          <FatMenuItem
+            icon="bell"
+            label="Notifications"
+            url="/notifications"
+            color={colors.pink3}
+          />
+          <FatMenuItem
+            icon={['far', 'user']}
+            label="My Profile"
+            url="/"
+            color={colors.purple3}
+          />
+          <FatMenuItem
+            icon="gear"
+            label="Settings"
+            url="/"
+            color={colors.blue3}
+          />
+        </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,
+  },
+  fatMenuItems: {
+    flexDirection: 'row',
+    marginBottom: 20,
+  },
+  fatMenuItem: {
+    width: 90,
+    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,
+  },
+})