about summary refs log tree commit diff
path: root/src/view/com/onboard/FeatureExplainer.web.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/onboard/FeatureExplainer.web.tsx')
-rw-r--r--src/view/com/onboard/FeatureExplainer.web.tsx203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/view/com/onboard/FeatureExplainer.web.tsx b/src/view/com/onboard/FeatureExplainer.web.tsx
new file mode 100644
index 000000000..83d460808
--- /dev/null
+++ b/src/view/com/onboard/FeatureExplainer.web.tsx
@@ -0,0 +1,203 @@
+import React, {useState} from 'react'
+import {
+  Animated,
+  Image,
+  SafeAreaView,
+  StyleSheet,
+  TouchableOpacity,
+  useWindowDimensions,
+  View,
+} from 'react-native'
+import {TabView, SceneMap, Route, TabBarProps} from 'react-native-tab-view'
+import {
+  FontAwesomeIcon,
+  FontAwesomeIconStyle,
+} from '@fortawesome/react-native-fontawesome'
+import {CenteredView} from '../util/Views.web'
+import {Text} from '../util/text/Text'
+import {useStores} from '../../../state'
+import {s, colors} from '../../lib/styles'
+import {TABS_EXPLAINER} from '../../lib/assets'
+import {TABS_ENABLED} from '../../../build-flags'
+
+const ROUTES = TABS_ENABLED
+  ? [
+      {key: 'intro', title: 'Intro'},
+      {key: 'tabs', title: 'Tabs'},
+    ]
+  : [{key: 'intro', title: 'Intro'}]
+
+const Intro = () => (
+  <View style={styles.explainer}>
+    <Text
+      style={[styles.explainerHeading, s.normal, styles.explainerHeadingIntro]}>
+      Welcome to{' '}
+      <Text style={[s.bold, s.blue3, styles.explainerHeadingBrand]}>
+        Bluesky
+      </Text>
+    </Text>
+    <Text style={[styles.explainerDesc, styles.explainerDescIntro]}>
+      This is an early beta. Your feedback is appreciated!
+    </Text>
+  </View>
+)
+
+const Tabs = () => (
+  <View style={styles.explainer}>
+    <View style={styles.explainerIcon}>
+      <View style={s.flex1} />
+      <FontAwesomeIcon
+        icon={['far', 'clone']}
+        style={[s.black as FontAwesomeIconStyle, s.mb5]}
+        size={36}
+      />
+      <View style={s.flex1} />
+    </View>
+    <Text style={styles.explainerHeading}>Tabs</Text>
+    <Text style={styles.explainerDesc}>
+      Never lose your place! Long-press to open posts and profiles in a new tab.
+    </Text>
+    <Text style={styles.explainerDesc}>
+      <Image source={TABS_EXPLAINER} style={styles.explainerImg} />
+    </Text>
+  </View>
+)
+
+const SCENE_MAP = {
+  intro: Intro,
+  tabs: Tabs,
+}
+const renderScene = SceneMap(SCENE_MAP)
+
+export const FeatureExplainer = () => {
+  const layout = useWindowDimensions()
+  const store = useStores()
+  const [index, setIndex] = useState(0)
+
+  const onPressSkip = () => store.onboard.next()
+  const onPressNext = () => {
+    if (index >= ROUTES.length - 1) {
+      store.onboard.next()
+    } else {
+      setIndex(index + 1)
+    }
+  }
+
+  const renderTabBar = (props: TabBarProps<Route>) => {
+    const inputRange = props.navigationState.routes.map((x, i) => i)
+    return (
+      <View style={styles.tabBar}>
+        <View style={s.flex1} />
+        {props.navigationState.routes.map((route, i) => {
+          const opacity = props.position.interpolate({
+            inputRange,
+            outputRange: inputRange.map(inputIndex =>
+              inputIndex === i ? 1 : 0.5,
+            ),
+          })
+
+          return (
+            <TouchableOpacity
+              key={i}
+              style={styles.tabItem}
+              onPress={() => setIndex(i)}>
+              <Animated.Text style={{opacity}}>&deg;</Animated.Text>
+            </TouchableOpacity>
+          )
+        })}
+        <View style={s.flex1} />
+      </View>
+    )
+  }
+
+  const FirstExplainer = SCENE_MAP[ROUTES[0]?.key as keyof typeof SCENE_MAP]
+  return (
+    <CenteredView style={styles.container}>
+      {ROUTES.length > 1 ? (
+        <TabView
+          navigationState={{index, routes: ROUTES}}
+          renderScene={renderScene}
+          renderTabBar={renderTabBar}
+          onIndexChange={setIndex}
+          initialLayout={{width: layout.width}}
+          tabBarPosition="bottom"
+        />
+      ) : FirstExplainer ? (
+        <FirstExplainer />
+      ) : (
+        <View />
+      )}
+      <View style={styles.footer}>
+        <TouchableOpacity onPress={onPressSkip}>
+          <Text style={styles.footerBtn}>Skip</Text>
+        </TouchableOpacity>
+        <TouchableOpacity onPress={onPressNext}>
+          <Text style={[styles.footerBtn, styles.footerBtnNext]}>Next</Text>
+        </TouchableOpacity>
+      </View>
+    </CenteredView>
+  )
+}
+
+const styles = StyleSheet.create({
+  container: {
+    height: '100%',
+    justifyContent: 'center',
+    paddingBottom: '10%',
+  },
+
+  tabBar: {
+    flexDirection: 'row',
+  },
+  tabItem: {
+    alignItems: 'center',
+    padding: 16,
+  },
+
+  explainer: {
+    paddingHorizontal: 16,
+  },
+  explainerIcon: {
+    flexDirection: 'row',
+  },
+  explainerHeading: {
+    fontSize: 42,
+    fontWeight: 'bold',
+    textAlign: 'center',
+    marginBottom: 16,
+  },
+  explainerHeadingIntro: {
+    lineHeight: 40,
+  },
+  explainerHeadingBrand: {fontSize: 56},
+  explainerDesc: {
+    fontSize: 18,
+    textAlign: 'center',
+    marginBottom: 16,
+    color: colors.gray5,
+  },
+  explainerDescIntro: {fontSize: 24},
+  explainerImg: {
+    resizeMode: 'contain',
+    maxWidth: '100%',
+    maxHeight: 330,
+  },
+
+  footer: {
+    flexDirection: 'row',
+    justifyContent: 'center',
+    paddingTop: 24,
+  },
+  footerBtn: {
+    color: colors.blue3,
+    fontSize: 19,
+    paddingHorizontal: 36,
+    paddingVertical: 8,
+  },
+  footerBtnNext: {
+    marginLeft: 10,
+    borderWidth: 1,
+    borderColor: colors.blue3,
+    borderRadius: 6,
+  },
+})