From 7897dd24a14e65d8ab1aa0e474a09e0628da31b7 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Thu, 14 Dec 2023 14:48:40 -0600 Subject: 🤫 (#2211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add new assets * Add splashiness * Add butter icon, spread it * Cream together eggs, sugar, and vanilla * Hi, I'd like to place and order. Yeah, none pizza with left beef, plz. * test * Refine animation * tweak * tweak * tweak * Tweak * Simplify * Cleanup * Fix android logo --------- Co-authored-by: Ansh Nanda --- src/App.native.tsx | 46 ++++--- src/Navigation.tsx | 2 - src/Splash.tsx | 154 +++++++++++++++++++++++ src/lib/assets.native.ts | 5 +- src/lib/assets.ts | 8 +- src/view/com/auth/SplashScreen.tsx | 16 ++- src/view/com/auth/SplashScreen.web.tsx | 20 +-- src/view/com/pager/FeedsTabBarMobile.tsx | 13 +- src/view/icons.ts | 201 ------------------------------- src/view/icons/Logo.tsx | 48 ++++++++ src/view/icons/Logotype.tsx | 28 +++++ src/view/icons/index.tsx | 201 +++++++++++++++++++++++++++++++ src/view/shell/index.tsx | 18 +-- 13 files changed, 493 insertions(+), 267 deletions(-) create mode 100644 src/Splash.tsx delete mode 100644 src/view/icons.ts create mode 100644 src/view/icons/Logo.tsx create mode 100644 src/view/icons/Logotype.tsx create mode 100644 src/view/icons/index.tsx (limited to 'src') diff --git a/src/App.native.tsx b/src/App.native.tsx index d11d05e70..6402b4a89 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -6,6 +6,10 @@ import {RootSiblingParent} from 'react-native-root-siblings' import * as SplashScreen from 'expo-splash-screen' import {GestureHandlerRootView} from 'react-native-gesture-handler' import {QueryClientProvider} from '@tanstack/react-query' +import { + SafeAreaProvider, + initialWindowMetrics, +} from 'react-native-safe-area-context' import 'view/icons' @@ -34,6 +38,7 @@ import { } from 'state/session' import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread' import * as persisted from '#/state/persisted' +import {Splash} from '#/Splash' SplashScreen.preventAutoHideAsync() @@ -53,27 +58,28 @@ function InnerApp() { resumeSession(account) }, [resumeSession]) - // wait for session to resume - if (isInitialLoad) return null - return ( - - - - - {/* All components should be within this provider */} - - - - - - - - - - + + + + + + + {/* All components should be within this provider */} + + + + + + + + + + + + ) } diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 24fbb0d81..252699e53 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -1,6 +1,5 @@ import * as React from 'react' import {StyleSheet} from 'react-native' -import * as SplashScreen from 'expo-splash-screen' import { NavigationContainer, createNavigationContainerRef, @@ -493,7 +492,6 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) { linking={LINKING} theme={theme} onReady={() => { - SplashScreen.hideAsync() logModuleInitTime() onReady() }}> diff --git a/src/Splash.tsx b/src/Splash.tsx new file mode 100644 index 000000000..92ed366f9 --- /dev/null +++ b/src/Splash.tsx @@ -0,0 +1,154 @@ +import React, {useCallback, useEffect} from 'react' +import {View, StyleSheet} from 'react-native' +import * as SplashScreen from 'expo-splash-screen' +import LinearGradient from 'react-native-linear-gradient' +import Animated, { + interpolate, + runOnJS, + useAnimatedStyle, + useSharedValue, + withTiming, + Easing, +} from 'react-native-reanimated' +import MaskedView from '@react-native-masked-view/masked-view' +import {useSafeAreaInsets} from 'react-native-safe-area-context' +import Svg, {Path, SvgProps} from 'react-native-svg' + +export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) { + const width = 1000 + const height = width * (67 / 64) + return ( + + + + ) +}) + +type Props = { + isReady: boolean +} + +SplashScreen.preventAutoHideAsync().catch(() => {}) + +const AnimatedLogo = Animated.createAnimatedComponent(Logo) + +export function Splash(props: React.PropsWithChildren) { + const insets = useSafeAreaInsets() + const intro = useSharedValue(0) + const outroLogo = useSharedValue(0) + const outroApp = useSharedValue(0) + const [isAnimationComplete, setIsAnimationComplete] = React.useState(false) + + const logoAnimations = useAnimatedStyle(() => { + return { + transform: [ + { + scale: interpolate(intro.value, [0, 1], [0.8, 1], 'clamp'), + }, + { + scale: interpolate( + outroLogo.value, + [0, 0.06, 0.08, 1], + [1, 0.8, 0.8, 800], + 'clamp', + ), + }, + ], + opacity: interpolate(intro.value, [0, 1], [0, 1], 'clamp'), + } + }) + + const appAnimation = useAnimatedStyle(() => { + return { + transform: [ + { + scale: interpolate( + outroApp.value, + [0, 0.7, 1], + [1.1, 1.1, 1], + 'clamp', + ), + }, + ], + opacity: interpolate(outroApp.value, [0, 0.7, 1], [0, 0, 1], 'clamp'), + } + }) + + const onFinish = useCallback(() => setIsAnimationComplete(true), []) + + useEffect(() => { + if (props.isReady) { + // hide on mount + SplashScreen.hideAsync().catch(() => {}) + + intro.value = withTiming( + 1, + {duration: 200, easing: Easing.out(Easing.cubic)}, + async () => { + outroLogo.value = withTiming( + 1, + {duration: 1200, easing: Easing.in(Easing.cubic)}, + () => { + runOnJS(onFinish)() + }, + ) + outroApp.value = withTiming( + 1, + {duration: 1200, easing: Easing.inOut(Easing.cubic)}, + () => { + runOnJS(onFinish)() + }, + ) + }, + ) + } + }, [onFinish, intro, outroLogo, outroApp, props.isReady]) + + return ( + + {!isAnimationComplete && ( + + )} + + + + + }> + {!isAnimationComplete && ( + + )} + + + {props.children} + + + + ) +} diff --git a/src/lib/assets.native.ts b/src/lib/assets.native.ts index d7ef9a05e..754bc9d2b 100644 --- a/src/lib/assets.native.ts +++ b/src/lib/assets.native.ts @@ -1,5 +1,4 @@ import {ImageRequireSource} from 'react-native' -export const DEF_AVATAR: ImageRequireSource = require('../../assets/default-avatar.jpg') -export const TABS_EXPLAINER: ImageRequireSource = require('../../assets/tabs-explainer.jpg') -export const CLOUD_SPLASH: ImageRequireSource = require('../../assets/cloud-splash.png') +export const DEF_AVATAR: ImageRequireSource = require('../../assets/default-avatar.png') +export const CLOUD_SPLASH: ImageRequireSource = require('../../assets/splash.png') diff --git a/src/lib/assets.ts b/src/lib/assets.ts index 216478762..8859607d5 100644 --- a/src/lib/assets.ts +++ b/src/lib/assets.ts @@ -1,10 +1,6 @@ import {ImageRequireSource} from 'react-native' // @ts-ignore we need to pretend -prf -export const DEF_AVATAR: ImageRequireSource = {uri: '/img/default-avatar.jpg'} +export const DEF_AVATAR: ImageRequireSource = {uri: '/img/default-avatar.png'} // @ts-ignore we need to pretend -prf -export const TABS_EXPLAINER: ImageRequireSource = { - uri: '/img/tabs-explainer.jpg', -} -// @ts-ignore we need to pretend -prf -export const CLOUD_SPLASH: ImageRequireSource = {uri: '/img/cloud-splash.png'} +export const CLOUD_SPLASH: ImageRequireSource = {uri: '/img/splash.png'} diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen.tsx index d88627f65..bb2d657ea 100644 --- a/src/view/com/auth/SplashScreen.tsx +++ b/src/view/com/auth/SplashScreen.tsx @@ -7,6 +7,8 @@ import {usePalette} from 'lib/hooks/usePalette' import {CenteredView} from '../util/Views' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {Logo} from '#/view/icons/Logo' +import {Logotype} from '#/view/icons/Logotype' export const SplashScreen = ({ onPressSignin, @@ -22,11 +24,14 @@ export const SplashScreen = ({ - - Bluesky - - - See what's next + + + + + + + + What's next? @@ -65,6 +70,7 @@ const styles = StyleSheet.create({ hero: { flex: 2, justifyContent: 'center', + alignItems: 'center', }, btns: { paddingBottom: 40, diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx index 08cf701da..4e942f66e 100644 --- a/src/view/com/auth/SplashScreen.web.tsx +++ b/src/view/com/auth/SplashScreen.web.tsx @@ -10,6 +10,8 @@ import {CenteredView} from '../util/Views' import {isWeb} from 'platform/detection' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {Trans} from '@lingui/macro' +import {Logo} from '#/view/icons/Logo' +import {Logotype} from '#/view/icons/Logotype' export const SplashScreen = ({ onDismiss, @@ -55,14 +57,15 @@ export const SplashScreen = ({ styles.containerInner, isMobileWeb && styles.containerInnerMobile, pal.border, + {alignItems: 'center'}, ]}> - - Bluesky - - - See what's next - + + + + + + }) { ) } const useStyles = () => { - const {isTabletOrMobile} = useWebMediaQueries() - const isMobileWeb = isWeb && isTabletOrMobile return StyleSheet.create({ container: { height: '100%', @@ -161,8 +162,7 @@ const useStyles = () => { paddingBottom: 30, }, btns: { - flexDirection: isMobileWeb ? 'column' : 'row', - gap: 20, + gap: 10, justifyContent: 'center', paddingBottom: 40, }, diff --git a/src/view/com/pager/FeedsTabBarMobile.tsx b/src/view/com/pager/FeedsTabBarMobile.tsx index 882b6cfc5..024f9bfab 100644 --- a/src/view/com/pager/FeedsTabBarMobile.tsx +++ b/src/view/com/pager/FeedsTabBarMobile.tsx @@ -3,12 +3,9 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native' import {TabBar} from 'view/com/pager/TabBar' import {RenderTabBarFnProps} from 'view/com/pager/Pager' import {usePalette} from 'lib/hooks/usePalette' -import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle' import {Link} from '../util/Link' -import {Text} from '../util/text/Text' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome' -import {s} from 'lib/styles' import {HITSLOP_10} from 'lib/constants' import Animated from 'react-native-reanimated' import {msg} from '@lingui/macro' @@ -21,17 +18,17 @@ import {usePinnedFeedsInfos} from '#/state/queries/feed' import {isWeb} from 'platform/detection' import {useNavigation} from '@react-navigation/native' import {NavigationProp} from 'lib/routes/types' +import {Logo} from '#/view/icons/Logo' export function FeedsTabBar( props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void}, ) { const pal = usePalette('default') - const {isSandbox, hasSession} = useSession() + const {hasSession} = useSession() const {_} = useLingui() const setDrawerOpen = useSetDrawerOpen() const navigation = useNavigation() const {feeds, hasPinnedCustom} = usePinnedFeedsInfos() - const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3) const {headerHeight} = useShellLayout() const {headerMinimalShellTransform} = useMinimalShellMode() const pinnedDisplayNames = hasSession ? feeds.map(f => f.displayName) : [] @@ -86,9 +83,9 @@ export function FeedsTabBar( /> - - {isSandbox ? 'SANDBOX' : 'Bluesky'} - + + + {hasSession && ( + {gradient && ( + + + + + + + )} + + + + ) +}) diff --git a/src/view/icons/Logotype.tsx b/src/view/icons/Logotype.tsx new file mode 100644 index 000000000..847607a3e --- /dev/null +++ b/src/view/icons/Logotype.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import Svg, {Path, SvgProps, PathProps} from 'react-native-svg' + +import {colors} from '#/lib/styles' + +const ratio = 17 / 64 + +export function Logotype({ + fill, + ...rest +}: {fill?: PathProps['fill']} & SvgProps) { + // @ts-ignore it's fiiiiine + const size = parseInt(rest.width || 32) + + return ( + + + + ) +} diff --git a/src/view/icons/index.tsx b/src/view/icons/index.tsx new file mode 100644 index 000000000..089d3f0a8 --- /dev/null +++ b/src/view/icons/index.tsx @@ -0,0 +1,201 @@ +import {library} from '@fortawesome/fontawesome-svg-core' + +import {faAddressCard} from '@fortawesome/free-regular-svg-icons' +import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown' +import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft' +import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight' +import {faAngleUp} from '@fortawesome/free-solid-svg-icons/faAngleUp' +import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft' +import {faArrowRight} from '@fortawesome/free-solid-svg-icons/faArrowRight' +import {faArrowUp} from '@fortawesome/free-solid-svg-icons/faArrowUp' +import {faArrowDown} from '@fortawesome/free-solid-svg-icons/faArrowDown' +import {faArrowRightFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowRightFromBracket' +import {faArrowUpFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowUpFromBracket' +import {faArrowUpRightFromSquare} from '@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare' +import {faArrowRotateLeft} from '@fortawesome/free-solid-svg-icons/faArrowRotateLeft' +import {faArrowTrendUp} from '@fortawesome/free-solid-svg-icons/faArrowTrendUp' +import {faArrowsRotate} from '@fortawesome/free-solid-svg-icons/faArrowsRotate' +import {faAt} from '@fortawesome/free-solid-svg-icons/faAt' +import {faBars} from '@fortawesome/free-solid-svg-icons/faBars' +import {faBan} from '@fortawesome/free-solid-svg-icons/faBan' +import {faBell} from '@fortawesome/free-solid-svg-icons/faBell' +import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell' +import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark' +import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark' +import {faCalendar as farCalendar} from '@fortawesome/free-regular-svg-icons/faCalendar' +import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera' +import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck' +import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight' +import {faCircle} from '@fortawesome/free-regular-svg-icons/faCircle' +import {faCircleCheck as farCircleCheck} from '@fortawesome/free-regular-svg-icons/faCircleCheck' +import {faCircleCheck} from '@fortawesome/free-solid-svg-icons/faCircleCheck' +import {faCircleExclamation} from '@fortawesome/free-solid-svg-icons/faCircleExclamation' +import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser' +import {faCircleDot} from '@fortawesome/free-solid-svg-icons/faCircleDot' +import {faClone} from '@fortawesome/free-solid-svg-icons/faClone' +import {faClone as farClone} from '@fortawesome/free-regular-svg-icons/faClone' +import {faComment} from '@fortawesome/free-regular-svg-icons/faComment' +import {faCommentSlash} from '@fortawesome/free-solid-svg-icons/faCommentSlash' +import {faComments} from '@fortawesome/free-regular-svg-icons/faComments' +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' +import {faEye} from '@fortawesome/free-solid-svg-icons/faEye' +import {faEyeSlash as farEyeSlash} from '@fortawesome/free-regular-svg-icons/faEyeSlash' +import {faFaceSmile} from '@fortawesome/free-regular-svg-icons/faFaceSmile' +import {faFire} from '@fortawesome/free-solid-svg-icons/faFire' +import {faFlask} from '@fortawesome/free-solid-svg-icons' +import {faFloppyDisk} from '@fortawesome/free-regular-svg-icons/faFloppyDisk' +import {faGear} from '@fortawesome/free-solid-svg-icons/faGear' +import {faGlobe} from '@fortawesome/free-solid-svg-icons/faGlobe' +import {faHand} from '@fortawesome/free-solid-svg-icons/faHand' +import {faHand as farHand} from '@fortawesome/free-regular-svg-icons/faHand' +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 {faImage as farImage} from '@fortawesome/free-regular-svg-icons/faImage' +import {faImage} from '@fortawesome/free-solid-svg-icons/faImage' +import {faInfo} from '@fortawesome/free-solid-svg-icons/faInfo' +import {faLanguage} from '@fortawesome/free-solid-svg-icons/faLanguage' +import {faLink} from '@fortawesome/free-solid-svg-icons/faLink' +import {faList} from '@fortawesome/free-solid-svg-icons/faList' +import {faListUl} from '@fortawesome/free-solid-svg-icons/faListUl' +import {faLock} from '@fortawesome/free-solid-svg-icons/faLock' +import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass' +import {faMessage} from '@fortawesome/free-regular-svg-icons/faMessage' +import {faNoteSticky} from '@fortawesome/free-solid-svg-icons/faNoteSticky' +import {faPause} from '@fortawesome/free-solid-svg-icons/faPause' +import {faPaste} from '@fortawesome/free-regular-svg-icons/faPaste' +import {faPen} from '@fortawesome/free-solid-svg-icons/faPen' +import {faPenNib} from '@fortawesome/free-solid-svg-icons/faPenNib' +import {faPenToSquare} from '@fortawesome/free-solid-svg-icons/faPenToSquare' +import {faPlay} from '@fortawesome/free-solid-svg-icons/faPlay' +import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus' +import {faQuoteLeft} from '@fortawesome/free-solid-svg-icons/faQuoteLeft' +import {faReply} from '@fortawesome/free-solid-svg-icons/faReply' +import {faRetweet} from '@fortawesome/free-solid-svg-icons/faRetweet' +import {faRss} from '@fortawesome/free-solid-svg-icons/faRss' +import {faSatelliteDish} from '@fortawesome/free-solid-svg-icons/faSatelliteDish' +import {faShare} from '@fortawesome/free-solid-svg-icons/faShare' +import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSquare' +import {faShield} from '@fortawesome/free-solid-svg-icons/faShield' +import {faSignal} from '@fortawesome/free-solid-svg-icons/faSignal' +import {faSliders} from '@fortawesome/free-solid-svg-icons/faSliders' +import {faSquare} from '@fortawesome/free-regular-svg-icons/faSquare' +import {faSquareCheck} from '@fortawesome/free-regular-svg-icons/faSquareCheck' +import {faSquarePlus} from '@fortawesome/free-regular-svg-icons/faSquarePlus' +import {faThumbtack} from '@fortawesome/free-solid-svg-icons/faThumbtack' +import {faTicket} from '@fortawesome/free-solid-svg-icons/faTicket' +import {faTrashCan} from '@fortawesome/free-regular-svg-icons/faTrashCan' +import {faUser} from '@fortawesome/free-regular-svg-icons/faUser' +import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers' +import {faUserCheck} from '@fortawesome/free-solid-svg-icons/faUserCheck' +import {faUserSlash} from '@fortawesome/free-solid-svg-icons/faUserSlash' +import {faUserPlus} from '@fortawesome/free-solid-svg-icons/faUserPlus' +import {faUserXmark} from '@fortawesome/free-solid-svg-icons/faUserXmark' +import {faUsersSlash} from '@fortawesome/free-solid-svg-icons/faUsersSlash' +import {faX} from '@fortawesome/free-solid-svg-icons/faX' +import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark' +import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown' + +library.add( + faAddressCard, + faAngleDown, + faAngleLeft, + faAngleRight, + faAngleUp, + faArrowLeft, + faArrowRight, + faArrowUp, + faArrowDown, + faArrowRightFromBracket, + faArrowUpFromBracket, + faArrowUpRightFromSquare, + faArrowRotateLeft, + faArrowTrendUp, + faArrowsRotate, + faAt, + faBan, + faBars, + faBell, + farBell, + faBookmark, + farBookmark, + farCalendar, + faCamera, + faCheck, + faChevronRight, + faCircle, + faCircleCheck, + farCircleCheck, + faCircleExclamation, + faCircleUser, + faCircleDot, + faClone, + farClone, + faComment, + faCommentSlash, + faComments, + faCompass, + faEllipsis, + faEnvelope, + faEye, + faExclamation, + farEyeSlash, + faFaceSmile, + faFire, + faFlask, + faFloppyDisk, + faGear, + faGlobe, + faHand, + farHand, + faHeart, + fasHeart, + faHouse, + faImage, + farImage, + faInfo, + faLanguage, + faLink, + faList, + faListUl, + faLock, + faMagnifyingGlass, + faMessage, + faNoteSticky, + faPaste, + faPause, + faPen, + faPenNib, + faPenToSquare, + faPlay, + faPlus, + faQuoteLeft, + faReply, + faRetweet, + faRss, + faSatelliteDish, + faShare, + faShareFromSquare, + faShield, + faSignal, + faSliders, + faSquare, + faSquareCheck, + faSquarePlus, + faUser, + faUsers, + faUserCheck, + faUserSlash, + faUserPlus, + faUserXmark, + faUsersSlash, + faThumbtack, + faTicket, + faTrashCan, + faX, + faXmark, + faChevronDown, +) diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index 18042c7ed..51c03ae3d 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -19,10 +19,6 @@ import {useTheme} from 'lib/ThemeContext' import {usePalette} from 'lib/hooks/usePalette' import {RoutesContainer, TabsNavigator} from '../../Navigation' import {isStateAtTabRoot} from 'lib/routes/helpers' -import { - SafeAreaProvider, - initialWindowMetrics, -} from 'react-native-safe-area-context' import { useIsDrawerOpen, useSetDrawerOpen, @@ -107,14 +103,12 @@ export const Shell: React.FC = function ShellImpl() { const pal = usePalette('default') const theme = useTheme() return ( - - - - - - - - + + + + + + ) } -- cgit 1.4.1