diff options
-rw-r--r-- | src/lib/hooks/useOnMainScroll.ts | 24 | ||||
-rw-r--r-- | src/platform/detection.ts | 1 | ||||
-rw-r--r-- | src/view/com/auth/SplashScreen.web.tsx | 164 | ||||
-rw-r--r-- | src/view/com/composer/photos/OpenCameraBtn.tsx | 5 | ||||
-rw-r--r-- | src/view/com/composer/photos/SelectPhotoBtn.tsx | 6 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThread.tsx | 21 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 180 | ||||
-rw-r--r-- | src/view/com/util/Html.tsx | 125 | ||||
-rw-r--r-- | src/view/com/util/Link.tsx | 7 |
9 files changed, 289 insertions, 244 deletions
diff --git a/src/lib/hooks/useOnMainScroll.ts b/src/lib/hooks/useOnMainScroll.ts index 507a28cee..250ef3a36 100644 --- a/src/lib/hooks/useOnMainScroll.ts +++ b/src/lib/hooks/useOnMainScroll.ts @@ -2,12 +2,18 @@ import {useState, useCallback, useRef} from 'react' import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native' import {RootStoreModel} from 'state/index' import {s} from 'lib/styles' -import {isDesktopWeb} from 'platform/detection' +import {useWebMediaQueries} from './useWebMediaQueries' -const DY_LIMIT_UP = isDesktopWeb ? 30 : 10 -const DY_LIMIT_DOWN = isDesktopWeb ? 150 : 10 const Y_LIMIT = 10 +const useDeviceLimits = () => { + const {isDesktop} = useWebMediaQueries() + return { + dyLimitUp: isDesktop ? 30 : 10, + dyLimitDown: isDesktop ? 150 : 10, + } +} + export type OnScrollCb = ( event: NativeSyntheticEvent<NativeScrollEvent>, ) => void @@ -18,6 +24,8 @@ export function useOnMainScroll( ): [OnScrollCb, boolean, ResetCb] { let lastY = useRef(0) let [isScrolledDown, setIsScrolledDown] = useState(false) + const {dyLimitUp, dyLimitDown} = useDeviceLimits() + return [ useCallback( (event: NativeSyntheticEvent<NativeScrollEvent>) => { @@ -25,15 +33,11 @@ export function useOnMainScroll( const dy = y - (lastY.current || 0) lastY.current = y - if ( - !store.shell.minimalShellMode && - dy > DY_LIMIT_DOWN && - y > Y_LIMIT - ) { + if (!store.shell.minimalShellMode && dy > dyLimitDown && y > Y_LIMIT) { store.shell.setMinimalShellMode(true) } else if ( store.shell.minimalShellMode && - (dy < DY_LIMIT_UP * -1 || y <= Y_LIMIT) + (dy < dyLimitUp * -1 || y <= Y_LIMIT) ) { store.shell.setMinimalShellMode(false) } @@ -50,7 +54,7 @@ export function useOnMainScroll( setIsScrolledDown(false) } }, - [store, isScrolledDown], + [store.shell, dyLimitDown, dyLimitUp, isScrolledDown], ), isScrolledDown, useCallback(() => { diff --git a/src/platform/detection.ts b/src/platform/detection.ts index d414b008c..f4f7be240 100644 --- a/src/platform/detection.ts +++ b/src/platform/detection.ts @@ -12,7 +12,6 @@ export const isMobileWeb = isWeb && // @ts-ignore we know window exists -prf global.window.matchMedia(isMobileWebMediaQuery)?.matches -export const isDesktopWeb = isWeb && !isMobileWeb export const deviceLocales = dedupArray( getLocales?.().map?.(locale => locale.languageCode), diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx index 3c949bb9a..cef9618ef 100644 --- a/src/view/com/auth/SplashScreen.web.tsx +++ b/src/view/com/auth/SplashScreen.web.tsx @@ -6,7 +6,8 @@ import {ErrorBoundary} from 'view/com/util/ErrorBoundary' import {s, colors} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' import {CenteredView} from '../util/Views' -import {isMobileWeb} from 'platform/detection' +import {isWeb} from 'platform/detection' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' export const SplashScreen = ({ onPressSignin, @@ -16,6 +17,9 @@ export const SplashScreen = ({ onPressCreateAccount: () => void }) => { const pal = usePalette('default') + const {isTabletOrMobile} = useWebMediaQueries() + const styles = useStyles() + const isMobileWeb = isWeb && isTabletOrMobile return ( <CenteredView style={[styles.container, pal.view]}> @@ -55,13 +59,14 @@ export const SplashScreen = ({ </View> </ErrorBoundary> </View> - <Footer /> + <Footer styles={styles} /> </CenteredView> ) } -function Footer() { +function Footer({styles}: {styles: ReturnType<typeof useStyles>}) { const pal = usePalette('default') + return ( <View style={[styles.footer, pal.view, pal.border]}> <TextLink @@ -82,78 +87,81 @@ function Footer() { </View> ) } - -const styles = StyleSheet.create({ - container: { - height: '100%', - }, - containerInner: { - height: '100%', - justifyContent: 'center', - // @ts-ignore web only - paddingBottom: '20vh', - paddingHorizontal: 20, - }, - containerInnerMobile: { - paddingBottom: 50, - }, - title: { - textAlign: 'center', - color: colors.blue3, - fontSize: 68, - fontWeight: 'bold', - paddingBottom: 10, - }, - titleMobile: { - textAlign: 'center', - color: colors.blue3, - fontSize: 58, - fontWeight: 'bold', - }, - subtitle: { - textAlign: 'center', - color: colors.gray5, - fontSize: 52, - fontWeight: 'bold', - paddingBottom: 30, - }, - subtitleMobile: { - textAlign: 'center', - color: colors.gray5, - fontSize: 42, - fontWeight: 'bold', - paddingBottom: 30, - }, - btns: { - flexDirection: isMobileWeb ? 'column' : 'row', - gap: 20, - justifyContent: 'center', - paddingBottom: 40, - }, - btn: { - borderRadius: 30, - paddingHorizontal: 24, - paddingVertical: 12, - minWidth: 220, - }, - btnLabel: { - textAlign: 'center', - fontSize: 18, - }, - notice: { - paddingHorizontal: 40, - textAlign: 'center', - }, - footer: { - position: 'absolute', - left: 0, - right: 0, - bottom: 0, - padding: 20, - borderTopWidth: 1, - flexDirection: 'row', - }, - footerLink: { - marginRight: 20, - }, -}) +const useStyles = () => { + const {isTabletOrMobile} = useWebMediaQueries() + const isMobileWeb = isWeb && isTabletOrMobile + return StyleSheet.create({ + container: { + height: '100%', + }, + containerInner: { + height: '100%', + justifyContent: 'center', + // @ts-ignore web only + paddingBottom: '20vh', + paddingHorizontal: 20, + }, + containerInnerMobile: { + paddingBottom: 50, + }, + title: { + textAlign: 'center', + color: colors.blue3, + fontSize: 68, + fontWeight: 'bold', + paddingBottom: 10, + }, + titleMobile: { + textAlign: 'center', + color: colors.blue3, + fontSize: 58, + fontWeight: 'bold', + }, + subtitle: { + textAlign: 'center', + color: colors.gray5, + fontSize: 52, + fontWeight: 'bold', + paddingBottom: 30, + }, + subtitleMobile: { + textAlign: 'center', + color: colors.gray5, + fontSize: 42, + fontWeight: 'bold', + paddingBottom: 30, + }, + btns: { + flexDirection: isMobileWeb ? 'column' : 'row', + gap: 20, + justifyContent: 'center', + paddingBottom: 40, + }, + btn: { + borderRadius: 30, + paddingHorizontal: 24, + paddingVertical: 12, + minWidth: 220, + }, + btnLabel: { + textAlign: 'center', + fontSize: 18, + }, + notice: { + paddingHorizontal: 40, + textAlign: 'center', + }, + footer: { + position: 'absolute', + left: 0, + right: 0, + bottom: 0, + padding: 20, + borderTopWidth: 1, + flexDirection: 'row', + }, + footerLink: { + marginRight: 20, + }, + }) +} diff --git a/src/view/com/composer/photos/OpenCameraBtn.tsx b/src/view/com/composer/photos/OpenCameraBtn.tsx index d58b17c58..a6917b36d 100644 --- a/src/view/com/composer/photos/OpenCameraBtn.tsx +++ b/src/view/com/composer/photos/OpenCameraBtn.tsx @@ -7,11 +7,11 @@ import { import {usePalette} from 'lib/hooks/usePalette' import {useAnalytics} from 'lib/analytics/analytics' import {useStores} from 'state/index' -import {isDesktopWeb} from 'platform/detection' import {openCamera} from 'lib/media/picker' import {useCameraPermission} from 'lib/hooks/usePermissions' import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants' import {GalleryModel} from 'state/models/media/gallery' +import {isMobileWeb, isNative} from 'platform/detection' type Props = { gallery: GalleryModel @@ -43,7 +43,8 @@ export function OpenCameraBtn({gallery}: Props) { } }, [gallery, track, store, requestCameraAccessIfNeeded]) - if (isDesktopWeb) { + const shouldShowCameraButton = isNative || isMobileWeb + if (!shouldShowCameraButton) { return null } diff --git a/src/view/com/composer/photos/SelectPhotoBtn.tsx b/src/view/com/composer/photos/SelectPhotoBtn.tsx index 081456f75..a6826eb98 100644 --- a/src/view/com/composer/photos/SelectPhotoBtn.tsx +++ b/src/view/com/composer/photos/SelectPhotoBtn.tsx @@ -6,10 +6,10 @@ import { } from '@fortawesome/react-native-fontawesome' import {usePalette} from 'lib/hooks/usePalette' import {useAnalytics} from 'lib/analytics/analytics' -import {isDesktopWeb} from 'platform/detection' import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions' import {GalleryModel} from 'state/models/media/gallery' import {HITSLOP_10} from 'lib/constants' +import {isNative} from 'platform/detection' type Props = { gallery: GalleryModel @@ -23,12 +23,12 @@ export function SelectPhotoBtn({gallery}: Props) { const onPressSelectPhotos = useCallback(async () => { track('Composer:GalleryOpened') - if (!isDesktopWeb && !(await requestPhotoAccessIfNeeded())) { + if (isNative && !(await requestPhotoAccessIfNeeded())) { return } gallery.pick() - }, [track, gallery, requestPhotoAccessIfNeeded]) + }, [track, requestPhotoAccessIfNeeded, gallery]) return ( <TouchableOpacity diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx index 3c5d3a88d..7f6e9ca19 100644 --- a/src/view/com/post-thread/PostThread.tsx +++ b/src/view/com/post-thread/PostThread.tsx @@ -23,7 +23,7 @@ import {ViewHeader} from '../util/ViewHeader' import {ErrorMessage} from '../util/error/ErrorMessage' import {Text} from '../util/text/Text' import {s} from 'lib/styles' -import {isNative, isDesktopWeb} from 'platform/detection' +import {isNative} from 'platform/detection' import {usePalette} from 'lib/hooks/usePalette' import {useSetTitle} from 'lib/hooks/useSetTitle' import {useNavigation} from '@react-navigation/native' @@ -78,7 +78,7 @@ export const PostThread = observer(function PostThread({ treeView: boolean }) { const pal = usePalette('default') - const {isTablet} = useWebMediaQueries() + const {isTablet, isDesktop} = useWebMediaQueries() const ref = useRef<FlatList>(null) const hasScrolledIntoView = useRef<boolean>(false) const [isRefreshing, setIsRefreshing] = React.useState(false) @@ -189,7 +189,7 @@ export const PostThread = observer(function PostThread({ } else if (item === REPLY_PROMPT) { return ( <View> - {isDesktopWeb && <ComposePrompt onPressCompose={onPressReply} />} + {isDesktop && <ComposePrompt onPressCompose={onPressReply} />} </View> ) } else if (item === DELETED) { @@ -261,7 +261,20 @@ export const PostThread = observer(function PostThread({ } return <></> }, - [onRefresh, onPressReply, pal, posts, isTablet, treeView], + [ + isTablet, + isDesktop, + onPressReply, + pal.border, + pal.viewLight, + pal.textLight, + pal.view, + pal.text, + pal.colors.border, + posts, + onRefresh, + treeView, + ], ) // loading diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 788ce96ad..75d756d61 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -34,7 +34,6 @@ import {usePalette} from 'lib/hooks/usePalette' import {formatCount} from '../util/numeric/format' import {TimeElapsed} from 'view/com/util/TimeElapsed' import {makeProfileLink} from 'lib/routes/links' -import {isDesktopWeb} from 'platform/detection' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' export const PostThreadItem = observer(function PostThreadItem({ @@ -51,6 +50,7 @@ export const PostThreadItem = observer(function PostThreadItem({ const pal = usePalette('default') const store = useStores() const [deleted, setDeleted] = React.useState(false) + const styles = useStyles() const record = item.postRecord const hasEngagement = item.post.likeCount || item.post.repostCount @@ -568,6 +568,7 @@ function PostOuterWrapper({ }>) { const {isMobile} = useWebMediaQueries() const pal = usePalette('default') + const styles = useStyles() if (treeView && item._depth > 1) { return ( <View @@ -636,90 +637,93 @@ function ExpandedPostDetails({ ) } -const styles = StyleSheet.create({ - outer: { - borderTopWidth: 1, - paddingLeft: 8, - }, - outerHighlighted: { - paddingTop: 16, - paddingLeft: 8, - paddingRight: 8, - }, - noTopBorder: { - borderTopWidth: 0, - }, - layout: { - flexDirection: 'row', - gap: 10, - paddingLeft: 8, - }, - layoutAvi: {}, - layoutContent: { - flex: 1, - paddingRight: 10, - }, - meta: { - flexDirection: 'row', - paddingTop: 2, - paddingBottom: 2, - }, - metaExpandedLine1: { - paddingTop: 5, - paddingBottom: 0, - }, - metaItem: { - paddingRight: 5, - maxWidth: isDesktopWeb ? 380 : 220, - }, - alert: { - marginBottom: 6, - }, - postTextContainer: { - flexDirection: 'row', - alignItems: 'center', - flexWrap: 'wrap', - paddingBottom: 4, - paddingRight: 10, - }, - postTextLargeContainer: { - paddingHorizontal: 0, - paddingBottom: 10, - }, - translateLink: { - marginBottom: 6, - }, - contentHider: { - marginBottom: 6, - }, - contentHiderChild: { - marginTop: 6, - }, - expandedInfo: { - flexDirection: 'row', - padding: 10, - borderTopWidth: 1, - borderBottomWidth: 1, - marginTop: 5, - marginBottom: 15, - }, - expandedInfoItem: { - marginRight: 10, - }, - loadMore: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-start', - gap: 4, - paddingHorizontal: 20, - }, - replyLine: { - width: 2, - marginLeft: 'auto', - marginRight: 'auto', - }, - cursor: { - // @ts-ignore web only - cursor: 'pointer', - }, -}) +const useStyles = () => { + const {isDesktop} = useWebMediaQueries() + return StyleSheet.create({ + outer: { + borderTopWidth: 1, + paddingLeft: 8, + }, + outerHighlighted: { + paddingTop: 16, + paddingLeft: 8, + paddingRight: 8, + }, + noTopBorder: { + borderTopWidth: 0, + }, + layout: { + flexDirection: 'row', + gap: 10, + paddingLeft: 8, + }, + layoutAvi: {}, + layoutContent: { + flex: 1, + paddingRight: 10, + }, + meta: { + flexDirection: 'row', + paddingTop: 2, + paddingBottom: 2, + }, + metaExpandedLine1: { + paddingTop: 5, + paddingBottom: 0, + }, + metaItem: { + paddingRight: 5, + maxWidth: isDesktop ? 380 : 220, + }, + alert: { + marginBottom: 6, + }, + postTextContainer: { + flexDirection: 'row', + alignItems: 'center', + flexWrap: 'wrap', + paddingBottom: 4, + paddingRight: 10, + }, + postTextLargeContainer: { + paddingHorizontal: 0, + paddingBottom: 10, + }, + translateLink: { + marginBottom: 6, + }, + contentHider: { + marginBottom: 6, + }, + contentHiderChild: { + marginTop: 6, + }, + expandedInfo: { + flexDirection: 'row', + padding: 10, + borderTopWidth: 1, + borderBottomWidth: 1, + marginTop: 5, + marginBottom: 15, + }, + expandedInfoItem: { + marginRight: 10, + }, + loadMore: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-start', + gap: 4, + paddingHorizontal: 20, + }, + replyLine: { + width: 2, + marginLeft: 'auto', + marginRight: 'auto', + }, + cursor: { + // @ts-ignore web only + cursor: 'pointer', + }, + }) +} diff --git a/src/view/com/util/Html.tsx b/src/view/com/util/Html.tsx index 6179a726e..1590955a2 100644 --- a/src/view/com/util/Html.tsx +++ b/src/view/com/util/Html.tsx @@ -4,13 +4,13 @@ import {usePalette} from 'lib/hooks/usePalette' import {useTheme} from 'lib/ThemeContext' import {Text} from './text/Text' import {TextLink} from './Link' -import {isDesktopWeb} from 'platform/detection' import { H1 as ExpoH1, H2 as ExpoH2, H3 as ExpoH3, H4 as ExpoH4, } from '@expo/html-elements' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' /** * These utilities are used to define long documents in an html-like @@ -27,30 +27,35 @@ interface IsChildProps { // | React.ReactNode export function H1({children}: React.PropsWithChildren<{}>) { + const styles = useStyles() const pal = usePalette('default') const typography = useTheme().typography['title-xl'] return <ExpoH1 style={[typography, pal.text, styles.h1]}>{children}</ExpoH1> } export function H2({children}: React.PropsWithChildren<{}>) { + const styles = useStyles() const pal = usePalette('default') const typography = useTheme().typography['title-lg'] return <ExpoH2 style={[typography, pal.text, styles.h2]}>{children}</ExpoH2> } export function H3({children}: React.PropsWithChildren<{}>) { + const styles = useStyles() const pal = usePalette('default') const typography = useTheme().typography.title return <ExpoH3 style={[typography, pal.text, styles.h3]}>{children}</ExpoH3> } export function H4({children}: React.PropsWithChildren<{}>) { + const styles = useStyles() const pal = usePalette('default') const typography = useTheme().typography['title-sm'] return <ExpoH4 style={[typography, pal.text, styles.h4]}>{children}</ExpoH4> } export function P({children}: React.PropsWithChildren<{}>) { + const styles = useStyles() const pal = usePalette('default') return ( <Text type="md" style={[pal.text, styles.p]}> @@ -60,6 +65,7 @@ export function P({children}: React.PropsWithChildren<{}>) { } export function UL({children, isChild}: React.PropsWithChildren<IsChildProps>) { + const styles = useStyles() return ( <View style={[styles.ul, isChild && styles.ulChild]}> {markChildProps(children)} @@ -68,6 +74,7 @@ export function UL({children, isChild}: React.PropsWithChildren<IsChildProps>) { } export function OL({children, isChild}: React.PropsWithChildren<IsChildProps>) { + const styles = useStyles() return ( <View style={[styles.ol, isChild && styles.olChild]}> {markChildProps(children)} @@ -79,6 +86,7 @@ export function LI({ children, value, }: React.PropsWithChildren<{value?: string}>) { + const styles = useStyles() const pal = usePalette('default') return ( <View style={styles.li}> @@ -91,6 +99,7 @@ export function LI({ } export function A({children, href}: React.PropsWithChildren<{href: string}>) { + const styles = useStyles() const pal = usePalette('default') return ( <TextLink @@ -112,6 +121,7 @@ export function STRONG({children}: React.PropsWithChildren<{}>) { } export function EM({children}: React.PropsWithChildren<{}>) { + const styles = useStyles() const pal = usePalette('default') return ( <Text type="md" style={[pal.text, styles.em]}> @@ -132,58 +142,61 @@ function markChildProps(children: React.ReactNode) { }) } -const styles = StyleSheet.create({ - h1: { - marginTop: 20, - marginBottom: 10, - letterSpacing: 0.8, - }, - h2: { - marginTop: 20, - marginBottom: 10, - letterSpacing: 0.8, - }, - h3: { - marginTop: 0, - marginBottom: 10, - }, - h4: { - marginTop: 0, - marginBottom: 10, - fontWeight: 'bold', - }, - p: { - marginBottom: 10, - }, - ul: { - marginBottom: 10, - paddingLeft: isDesktopWeb ? 18 : 4, - }, - ulChild: { - paddingTop: 10, - marginBottom: 0, - }, - ol: { - marginBottom: 10, - paddingLeft: isDesktopWeb ? 18 : 4, - }, - olChild: { - paddingTop: 10, - marginBottom: 0, - }, - li: { - flexDirection: 'row', - paddingRight: 20, - marginBottom: 10, - }, - liBullet: { - paddingRight: 10, - }, - liText: {}, - a: { - marginBottom: 10, - }, - em: { - fontStyle: 'italic', - }, -}) +const useStyles = () => { + const {isDesktop} = useWebMediaQueries() + return StyleSheet.create({ + h1: { + marginTop: 20, + marginBottom: 10, + letterSpacing: 0.8, + }, + h2: { + marginTop: 20, + marginBottom: 10, + letterSpacing: 0.8, + }, + h3: { + marginTop: 0, + marginBottom: 10, + }, + h4: { + marginTop: 0, + marginBottom: 10, + fontWeight: 'bold', + }, + p: { + marginBottom: 10, + }, + ul: { + marginBottom: 10, + paddingLeft: isDesktop ? 18 : 4, + }, + ulChild: { + paddingTop: 10, + marginBottom: 0, + }, + ol: { + marginBottom: 10, + paddingLeft: isDesktop ? 18 : 4, + }, + olChild: { + paddingTop: 10, + marginBottom: 0, + }, + li: { + flexDirection: 'row', + paddingRight: 20, + marginBottom: 10, + }, + liBullet: { + paddingRight: 10, + }, + liText: {}, + a: { + marginBottom: 10, + }, + em: { + fontStyle: 'italic', + }, + }) +} diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx index 8734cf32f..d11bae6ba 100644 --- a/src/view/com/util/Link.tsx +++ b/src/view/com/util/Link.tsx @@ -24,10 +24,11 @@ import {NavigationProp} from 'lib/routes/types' import {router} from '../../../routes' import {useStores, RootStoreModel} from 'state/index' import {convertBskyAppUrlIfNeeded, isExternalUrl} from 'lib/strings/url-helpers' -import {isAndroid, isDesktopWeb} from 'platform/detection' +import {isAndroid} from 'platform/detection' import {sanitizeUrl} from '@braintree/sanitize-url' import {PressableWithHover} from './PressableWithHover' import FixedTouchableHighlight from '../pager/FixedTouchableHighlight' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' type Event = | React.MouseEvent<HTMLAnchorElement, MouseEvent> @@ -224,7 +225,9 @@ export const DesktopWebTextLink = observer(function DesktopWebTextLink({ lineHeight, ...props }: DesktopWebTextLinkProps) { - if (isDesktopWeb) { + const {isDesktop} = useWebMediaQueries() + + if (isDesktop) { return ( <TextLink testID={testID} |