diff options
-rw-r--r-- | src/view/index.ts | 8 | ||||
-rw-r--r-- | src/view/shell/mobile/index.tsx | 17 | ||||
-rw-r--r-- | src/view/shell/mobile/location-menu.tsx | 217 | ||||
-rw-r--r-- | src/view/shell/mobile/location-navigator.tsx | 176 |
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, + }, +}) |