WIP scene UIs

zio/stable
Paul Frazee 2022-10-31 12:17:58 -05:00
parent 1ab8285ad3
commit eceef67d46
9 changed files with 144 additions and 31 deletions

View File

@ -15,7 +15,7 @@ export interface ProfileUiParams {
export class ProfileUiModel {
// constants
static SELECTOR_ITEMS = ['Posts', 'Badges']
static SELECTOR_ITEMS = ['Posts', 'Scenes']
// data
profile: ProfileViewModel

View File

@ -86,14 +86,16 @@ export const ProfileHeader = observer(function ProfileHeader({
<View style={[styles.displayNameLine]}>
<Text style={styles.displayName}>{view.displayName}</Text>
</View>
<View style={styles.badgesLine}>
{
undefined /*<View style={styles.badgesLine}>
<FontAwesomeIcon icon="shield" style={s.mr5} size={12} />
<Link href="/" title="Badge TODO">
<Text style={[s.f12, s.bold]}>
Employee <Text style={[s.blue3]}>@blueskyweb.xyz</Text>
</Text>
</Link>
</View>
</View>*/
}
<View style={[styles.buttonsLine]}>
{isMe ? (
<TouchableOpacity

View File

@ -12,6 +12,8 @@ interface Layout {
width: number
}
const DEFAULT_SWIPE_GESTURE_INTERP = {value: 0}
export function Selector({
selectedIndex,
items,
@ -20,7 +22,7 @@ export function Selector({
}: {
selectedIndex: number
items: string[]
swipeGestureInterp: SharedValue<number>
swipeGestureInterp?: SharedValue<number>
onSelect?: (index: number) => void
}) {
const [itemLayouts, setItemLayouts] = useState<undefined | Layout[]>(
@ -41,26 +43,27 @@ export function Selector({
return [left, middle, right]
}, [selectedIndex, itemLayouts])
const interp = swipeGestureInterp || DEFAULT_SWIPE_GESTURE_INTERP
const underlinePos = useAnimatedStyle(() => {
const other =
swipeGestureInterp.value === 0
interp.value === 0
? currentLayouts[1]
: swipeGestureInterp.value < 0
: interp.value < 0
? currentLayouts[0]
: currentLayouts[2]
return {
left: interpolate(
Math.abs(swipeGestureInterp.value),
Math.abs(interp.value),
[0, 1],
[currentLayouts[1].x, other.x],
),
width: interpolate(
Math.abs(swipeGestureInterp.value),
Math.abs(interp.value),
[0, 1],
[currentLayouts[1].width, other.width],
),
}
}, [currentLayouts, swipeGestureInterp])
}, [currentLayouts, interp])
const onLayout = () => {
const promises = []
@ -112,7 +115,7 @@ const styles = StyleSheet.create({
backgroundColor: colors.white,
},
item: {
marginRight: 20,
marginRight: 14,
paddingHorizontal: 10,
},
itemLabel: {

View File

@ -19,6 +19,7 @@ import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faClone} from '@fortawesome/free-regular-svg-icons/faClone'
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
import {faCompass} from '@fortawesome/free-regular-svg-icons/faCompass'
import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis'
import {faEnvelope} from '@fortawesome/free-solid-svg-icons/faEnvelope'
import {faExclamation} from '@fortawesome/free-solid-svg-icons/faExclamation'
@ -69,6 +70,7 @@ export function setup() {
faCircleUser,
faClone,
faComment,
faCompass,
faEllipsis,
faEnvelope,
faExclamation,

View File

@ -33,12 +33,37 @@ export function GridIcon({style}: {style?: StyleProp<ViewStyle>}) {
export function HomeIcon({style}: {style?: StyleProp<ViewStyle>}) {
return (
<Svg viewBox="0 0 48 48" width="24" height="24" style={style}>
<Svg
viewBox="0 0 48 48"
width="24"
height="24"
stroke="currentColor"
style={style}>
<Path
strokeWidth={4}
stroke="#000"
d="M 23.951 2 C 23.631 2.011 23.323 2.124 23.072 2.322 L 8.859 13.52 C 7.055 14.941 6 17.114 6 19.41 L 6 38.5 C 6 39.864 7.136 41 8.5 41 L 18.5 41 C 19.864 41 21 39.864 21 38.5 L 21 28.5 C 21 28.205 21.205 28 21.5 28 L 26.5 28 C 26.795 28 27 28.205 27 28.5 L 27 38.5 C 27 39.864 28.136 41 29.5 41 L 39.5 41 C 40.864 41 42 39.864 42 38.5 L 42 19.41 C 42 17.114 40.945 14.941 39.141 13.52 L 24.928 2.322 C 24.65 2.103 24.304 1.989 23.951 2 Z"
/>
</Svg>
)
}
// Copyright (c) 2020 Refactoring UI Inc.
// https://github.com/tailwindlabs/heroicons/blob/master/LICENSE
export function UserGroupIcon({style}: {style?: StyleProp<ViewStyle>}) {
return (
<Svg
fill="none"
viewBox="0 0 24 24"
width="32"
height="32"
strokeWidth={1.5}
stroke="currentColor"
style={style}>
<Path
strokeLinecap="round"
strokeLinejoin="round"
d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z"
/>
</Svg>
)
}

View File

@ -43,7 +43,7 @@ export const Contacts = ({visible, params}: ScreenParams) => {
</View>
</View>
<Selector
items={['All', 'Following']}
items={['All', 'Following', 'Scenes']}
selectedIndex={0}
swipeGestureInterp={selectorInterp}
/>

View File

@ -1,6 +1,7 @@
import React, {useState, useEffect} from 'react'
import {View} from 'react-native'
import {StyleSheet, Text, View} from 'react-native'
import {Feed} from '../com/notifications/Feed'
import {colors} from '../lib/styles'
import {useStores} from '../../state'
import {NotificationsViewModel} from '../../state/models/notifications-view'
import {ScreenParams} from '../routes'
@ -35,5 +36,24 @@ export const Notifications = ({visible}: ScreenParams) => {
}
}, [visible, store])
return <View>{notesView && <Feed view={notesView} />}</View>
return (
<View>
<View style={styles.header}>
<Text style={styles.title}>Notifications</Text>
</View>
{notesView && <Feed view={notesView} />}
</View>
)
}
const styles = StyleSheet.create({
header: {
backgroundColor: colors.white,
},
title: {
fontSize: 30,
fontWeight: 'bold',
paddingHorizontal: 12,
paddingVertical: 6,
},
})

View File

@ -2,6 +2,7 @@ import React, {useEffect} from 'react'
import {observer} from 'mobx-react-lite'
import {
Image,
ImageSourcePropType,
StyleSheet,
SafeAreaView,
Text,
@ -17,7 +18,7 @@ import Animated, {
} from 'react-native-reanimated'
import {IconProp} from '@fortawesome/fontawesome-svg-core'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {HomeIcon} from '../../lib/icons'
import {HomeIcon, UserGroupIcon} from '../../lib/icons'
import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles'
import {DEF_AVATER} from '../../lib/assets'
@ -68,7 +69,9 @@ export const MainMenu = observer(
onPress={() => onNavigate(url)}>
<View style={[styles.menuItemIconWrapper]}>
{icon === 'home' ? (
<HomeIcon style={styles.menuItemIcon} size={24} />
<HomeIcon style={styles.menuItemIcon} />
) : icon === 'user-group' ? (
<UserGroupIcon style={styles.menuItemIcon} />
) : (
<FontAwesomeIcon
icon={icon}
@ -87,6 +90,32 @@ export const MainMenu = observer(
</Text>
</TouchableOpacity>
)
const MenuItemImage = ({
img,
label,
url,
count,
}: {
img: ImageSourcePropType
label: string
url: string
count?: number
}) => (
<TouchableOpacity
style={[styles.menuItem, styles.menuItemMargin]}
onPress={() => onNavigate(url)}>
<Image style={styles.menuItemImg} source={img} />
{count ? (
<View style={styles.menuItemCount}>
<Text style={styles.menuItemCountLabel}>{count}</Text>
</View>
) : undefined}
<Text style={styles.menuItemLabel} numberOfLines={1}>
{label}
</Text>
</TouchableOpacity>
)
if (!active) {
return <View />
}
@ -118,22 +147,41 @@ export const MainMenu = observer(
/>
</TouchableOpacity>
</View>
<View style={[styles.section]}>
<Animated.View style={[styles.menuItems, menuItemsAnimStyle]}>
<Animated.View style={[styles.section, menuItemsAnimStyle]}>
<View style={[styles.menuItems]}>
<MenuItem icon="home" label="Home" url="/" />
<MenuItem
icon={['far', 'circle-user']}
label="Contacts"
url="/contacts"
/>
<MenuItem
icon={['far', 'bell']}
label="Notifications"
url="/notifications"
count={store.me.notificationCount}
/>
</Animated.View>
</View>
<Text style={styles.heading}>Scenes</Text>
<View style={[styles.menuItems]}>
<MenuItem icon={['far', 'compass']} label="Discover" url="/" />
<MenuItem
icon={'user-group'}
label="Create Scene"
url="/contacts"
/>
<MenuItemImage img={DEF_AVATER} label="Galaxy Brain" url="/" />
<MenuItemImage
img={DEF_AVATER}
label="Paul's Friends"
url="/"
/>
</View>
<View style={[styles.menuItems]}>
<MenuItemImage
img={DEF_AVATER}
label="Cool People Only"
url="/"
/>
<MenuItemImage img={DEF_AVATER} label="Techsky" url="/" />
</View>
</Animated.View>
</SafeAreaView>
</Animated.View>
</>
@ -168,6 +216,13 @@ const styles = StyleSheet.create({
section: {
paddingHorizontal: 10,
},
heading: {
fontSize: 21,
fontWeight: 'bold',
paddingHorizontal: 10,
paddingTop: 6,
paddingBottom: 12,
},
profile: {
paddingVertical: 10,
@ -194,16 +249,20 @@ const styles = StyleSheet.create({
menuItems: {
flexDirection: 'row',
marginTop: 10,
marginBottom: 10,
marginBottom: 20,
},
menuItem: {
width: 80,
width: 82,
alignItems: 'center',
marginRight: 6,
},
menuItemMargin: {
marginRight: 14,
marginRight: 10,
},
menuItemImg: {
borderRadius: 30,
width: 60,
height: 60,
marginBottom: 5,
},
menuItemIconWrapper: {
borderRadius: 6,
@ -219,6 +278,7 @@ const styles = StyleSheet.create({
},
menuItemLabel: {
fontSize: 13,
textAlign: 'center',
},
menuItemCount: {
position: 'absolute',

View File

@ -388,6 +388,7 @@ const styles = StyleSheet.create({
color: colors.white,
},
ctrlIcon: {
color: colors.black,
marginLeft: 'auto',
marginRight: 'auto',
},