diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-09-05 10:42:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-05 10:42:19 -0700 |
commit | 764c7cd5694a41c98d8543b68d7791fa90db4291 (patch) | |
tree | 8a11af0aa0e898cf7fb57ab0354f9fb5d28f004e /src/view/com/util | |
parent | be8084ae103064d5680485f25e202c763957f2b4 (diff) | |
download | voidsky-764c7cd5694a41c98d8543b68d7791fa90db4291.tar.zst |
Updates to use dynamic/responsive styles on web (#1351)
* Move most responsive queries to the hook * Fix invalid CSS value * Fixes to tablet render of post thread * Fix overflow issues on web * Fix search header on tablet * Fix QP margin in web composer * Fix: only apply double gutter once to flatlist (close #1368) * Fix styles on discover feeds header * Fix double discover links in multifeed
Diffstat (limited to 'src/view/com/util')
-rw-r--r-- | src/view/com/util/ViewHeader.tsx | 19 | ||||
-rw-r--r-- | src/view/com/util/Views.web.tsx | 11 | ||||
-rw-r--r-- | src/view/com/util/fab/FABInner.tsx | 48 | ||||
-rw-r--r-- | src/view/com/util/forms/SelectableBtn.tsx | 12 | ||||
-rw-r--r-- | src/view/com/util/layouts/Breakpoints.web.tsx | 6 | ||||
-rw-r--r-- | src/view/com/util/load-latest/LoadLatestBtn.web.tsx | 5 | ||||
-rw-r--r-- | src/view/com/util/moderation/ContentHider.tsx | 5 | ||||
-rw-r--r-- | src/view/com/util/moderation/PostHider.tsx | 10 | ||||
-rw-r--r-- | src/view/com/util/moderation/ScreenHider.tsx | 5 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/ExternalLinkEmbed.tsx | 63 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/index.tsx | 19 |
11 files changed, 131 insertions, 72 deletions
diff --git a/src/view/com/util/ViewHeader.tsx b/src/view/com/util/ViewHeader.tsx index 7482db8eb..91cdb08c7 100644 --- a/src/view/com/util/ViewHeader.tsx +++ b/src/view/com/util/ViewHeader.tsx @@ -8,9 +8,9 @@ import {Text} from './text/Text' import {useStores} from 'state/index' import {usePalette} from 'lib/hooks/usePalette' import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useAnalytics} from 'lib/analytics/analytics' import {NavigationProp} from 'lib/routes/types' -import {isDesktopWeb} from 'platform/detection' const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20} @@ -35,6 +35,7 @@ export const ViewHeader = observer(function ({ const store = useStores() const navigation = useNavigation<NavigationProp>() const {track} = useAnalytics() + const {isDesktop, isTablet} = useWebMediaQueries() const onPressBack = React.useCallback(() => { if (navigation.canGoBack()) { @@ -49,7 +50,7 @@ export const ViewHeader = observer(function ({ store.shell.openDrawer() }, [track, store]) - if (isDesktopWeb) { + if (isDesktop) { if (showOnDesktop) { return ( <DesktopWebHeader @@ -84,13 +85,13 @@ export const ViewHeader = observer(function ({ icon="angle-left" style={[styles.backIcon, pal.text]} /> - ) : ( + ) : !isTablet ? ( <FontAwesomeIcon size={18} icon="bars" style={[styles.backIcon, pal.textLight]} /> - )} + ) : null} </TouchableOpacity> ) : null} <View style={styles.titleContainer} pointerEvents="none"> @@ -122,6 +123,7 @@ function DesktopWebHeader({ <CenteredView style={[ styles.header, + styles.headerFixed, styles.desktopHeader, pal.border, { @@ -178,6 +180,7 @@ const Container = observer( <View style={[ styles.header, + styles.headerFixed, pal.view, pal.border, showBorder && styles.border, @@ -190,9 +193,9 @@ const Container = observer( <Animated.View style={[ styles.header, + styles.headerFloating, pal.view, pal.border, - styles.headerFloating, transform, showBorder && styles.border, ]}> @@ -208,6 +211,12 @@ const styles = StyleSheet.create({ alignItems: 'center', paddingHorizontal: 12, paddingVertical: 6, + width: '100%', + }, + headerFixed: { + maxWidth: 600, + marginLeft: 'auto', + marginRight: 'auto', }, headerFloating: { position: 'absolute', diff --git a/src/view/com/util/Views.web.tsx b/src/view/com/util/Views.web.tsx index 3313492e1..58a367f20 100644 --- a/src/view/com/util/Views.web.tsx +++ b/src/view/com/util/Views.web.tsx @@ -24,6 +24,7 @@ import { } from 'react-native' import {addStyle} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' interface AddedProps { desktopFixedHeight?: boolean @@ -48,6 +49,7 @@ export const FlatList = React.forwardRef(function <ItemT>( ref: React.Ref<RNFlatList>, ) { const pal = usePalette('default') + const {isMobile} = useWebMediaQueries() contentContainerStyle = addStyle( contentContainerStyle, styles.containerScroll, @@ -67,6 +69,12 @@ export const FlatList = React.forwardRef(function <ItemT>( } if (desktopFixedHeight) { style = addStyle(style, styles.fixedHeight) + if (!isMobile) { + contentContainerStyle = addStyle( + contentContainerStyle, + styles.stableGutters, + ) + } } return ( <RNFlatList @@ -126,6 +134,9 @@ const styles = StyleSheet.create({ }, fixedHeight: { height: '100vh', + }, + stableGutters: { + // @ts-ignore web only -prf scrollbarGutter: 'stable both-edges', }, }) diff --git a/src/view/com/util/fab/FABInner.tsx b/src/view/com/util/fab/FABInner.tsx index 76824e575..afd172c82 100644 --- a/src/view/com/util/fab/FABInner.tsx +++ b/src/view/com/util/fab/FABInner.tsx @@ -5,7 +5,8 @@ import LinearGradient from 'react-native-linear-gradient' import {gradients} from 'lib/styles' import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' import {useStores} from 'state/index' -import {isMobileWeb} from 'platform/detection' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' +import {isWeb} from 'platform/detection' export interface FABProps extends ComponentProps<typeof TouchableWithoutFeedback> { @@ -14,6 +15,7 @@ export interface FABProps } export const FABInner = observer(({testID, icon, ...props}: FABProps) => { + const {isTablet} = useWebMediaQueries() const store = useStores() const interp = useAnimatedValue(0) React.useEffect(() => { @@ -24,18 +26,33 @@ export const FABInner = observer(({testID, icon, ...props}: FABProps) => { isInteraction: false, }).start() }, [interp, store.shell.minimalShellMode]) - const transform = { - transform: [{translateY: Animated.multiply(interp, 60)}], - } + const transform = isTablet + ? undefined + : { + transform: [{translateY: Animated.multiply(interp, 60)}], + } + const size = isTablet ? styles.sizeLarge : styles.sizeRegular return ( <TouchableWithoutFeedback testID={testID} {...props}> <Animated.View - style={[styles.outer, isMobileWeb && styles.mobileWebOuter, transform]}> + style={[ + styles.outer, + size, + isWeb && isTablet + ? { + right: 50, + bottom: 50, + } + : { + bottom: 114, + }, + transform, + ]}> <LinearGradient colors={[gradients.blueLight.start, gradients.blueLight.end]} start={{x: 0, y: 0}} end={{x: 1, y: 1}} - style={styles.inner}> + style={[styles.inner, size]}> {icon} </LinearGradient> </Animated.View> @@ -44,22 +61,23 @@ export const FABInner = observer(({testID, icon, ...props}: FABProps) => { }) const styles = StyleSheet.create({ + sizeRegular: { + width: 60, + height: 60, + borderRadius: 30, + }, + sizeLarge: { + width: 70, + height: 70, + borderRadius: 35, + }, outer: { position: 'absolute', zIndex: 1, right: 24, bottom: 94, - width: 60, - height: 60, - borderRadius: 30, - }, - mobileWebOuter: { - bottom: 114, }, inner: { - width: 60, - height: 60, - borderRadius: 30, justifyContent: 'center', alignItems: 'center', }, diff --git a/src/view/com/util/forms/SelectableBtn.tsx b/src/view/com/util/forms/SelectableBtn.tsx index 4b494264e..f09d063a1 100644 --- a/src/view/com/util/forms/SelectableBtn.tsx +++ b/src/view/com/util/forms/SelectableBtn.tsx @@ -2,7 +2,7 @@ import React from 'react' import {Pressable, ViewStyle, StyleProp, StyleSheet} from 'react-native' import {Text} from '../text/Text' import {usePalette} from 'lib/hooks/usePalette' -import {isDesktopWeb} from 'platform/detection' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' interface SelectableBtnProps { testID?: string @@ -28,12 +28,16 @@ export function SelectableBtn({ const pal = usePalette('default') const palPrimary = usePalette('inverted') const needsWidthStyles = !style || !('width' in style || 'flex' in style) + const {isMobile} = useWebMediaQueries() return ( <Pressable testID={testID} style={[ styles.btn, - needsWidthStyles && styles.btnWidth, + needsWidthStyles && { + flex: isMobile ? 1 : undefined, + width: !isMobile ? 100 : undefined, + }, left && styles.btnLeft, right && styles.btnRight, pal.border, @@ -58,10 +62,6 @@ const styles = StyleSheet.create({ paddingHorizontal: 10, paddingVertical: 10, }, - btnWidth: { - flex: isDesktopWeb ? undefined : 1, - width: isDesktopWeb ? 100 : undefined, - }, btnLeft: { borderTopLeftRadius: 8, borderBottomLeftRadius: 8, diff --git a/src/view/com/util/layouts/Breakpoints.web.tsx b/src/view/com/util/layouts/Breakpoints.web.tsx index 7031a1735..5cf73df0c 100644 --- a/src/view/com/util/layouts/Breakpoints.web.tsx +++ b/src/view/com/util/layouts/Breakpoints.web.tsx @@ -2,18 +2,18 @@ import React from 'react' import MediaQuery from 'react-responsive' export const Desktop = ({children}: React.PropsWithChildren<{}>) => ( - <MediaQuery minWidth={1224}>{children}</MediaQuery> + <MediaQuery minWidth={1300}>{children}</MediaQuery> ) export const TabletOrDesktop = ({children}: React.PropsWithChildren<{}>) => ( <MediaQuery minWidth={800}>{children}</MediaQuery> ) export const Tablet = ({children}: React.PropsWithChildren<{}>) => ( - <MediaQuery minWidth={800} maxWidth={1224}> + <MediaQuery minWidth={800} maxWidth={1300}> {children} </MediaQuery> ) export const TabletOrMobile = ({children}: React.PropsWithChildren<{}>) => ( - <MediaQuery maxWidth={1224}>{children}</MediaQuery> + <MediaQuery maxWidth={1300}>{children}</MediaQuery> ) export const Mobile = ({children}: React.PropsWithChildren<{}>) => ( <MediaQuery maxWidth={800}>{children}</MediaQuery> diff --git a/src/view/com/util/load-latest/LoadLatestBtn.web.tsx b/src/view/com/util/load-latest/LoadLatestBtn.web.tsx index c90e5dfb1..c9576e56b 100644 --- a/src/view/com/util/load-latest/LoadLatestBtn.web.tsx +++ b/src/view/com/util/load-latest/LoadLatestBtn.web.tsx @@ -3,8 +3,8 @@ import {StyleSheet, TouchableOpacity} from 'react-native' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {Text} from '../text/Text' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {LoadLatestBtn as LoadLatestBtnMobile} from './LoadLatestBtnMobile' -import {isMobileWeb} from 'platform/detection' import {HITSLOP_20} from 'lib/constants' export const LoadLatestBtn = ({ @@ -19,7 +19,8 @@ export const LoadLatestBtn = ({ minimalShellMode?: boolean }) => { const pal = usePalette('default') - if (isMobileWeb) { + const {isMobile} = useWebMediaQueries() + if (isMobile) { return ( <LoadLatestBtnMobile onPress={onPress} diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx index 853f7840c..6cf1cefd0 100644 --- a/src/view/com/util/moderation/ContentHider.tsx +++ b/src/view/com/util/moderation/ContentHider.tsx @@ -1,12 +1,12 @@ import React from 'react' import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {ModerationUI} from '@atproto/api' import {Text} from '../text/Text' import {ShieldExclamation} from 'lib/icons' import {describeModerationCause} from 'lib/moderation' import {useStores} from 'state/index' -import {isDesktopWeb} from 'platform/detection' export function ContentHider({ testID, @@ -24,6 +24,7 @@ export function ContentHider({ }>) { const store = useStores() const pal = usePalette('default') + const {isMobile} = useWebMediaQueries() const [override, setOverride] = React.useState(false) if (!moderation.blur || (ignoreMute && moderation.cause?.type === 'muted')) { @@ -54,6 +55,7 @@ export function ContentHider({ accessibilityLabel="" style={[ styles.cover, + {paddingRight: isMobile ? 22 : 18}, moderation.noOverride ? {borderWidth: 1, borderColor: pal.colors.borderDark} : pal.viewLight, @@ -96,7 +98,6 @@ const styles = StyleSheet.create({ marginTop: 4, paddingVertical: 14, paddingLeft: 14, - paddingRight: isDesktopWeb ? 18 : 22, }, showBtn: { marginLeft: 'auto', diff --git a/src/view/com/util/moderation/PostHider.tsx b/src/view/com/util/moderation/PostHider.tsx index 2a52561d4..443885dfa 100644 --- a/src/view/com/util/moderation/PostHider.tsx +++ b/src/view/com/util/moderation/PostHider.tsx @@ -2,13 +2,13 @@ import React, {ComponentProps} from 'react' import {StyleSheet, Pressable, View} from 'react-native' import {ModerationUI} from '@atproto/api' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {Link} from '../Link' import {Text} from '../text/Text' import {addStyle} from 'lib/styles' import {describeModerationCause} from 'lib/moderation' import {ShieldExclamation} from 'lib/icons' import {useStores} from 'state/index' -import {isDesktopWeb} from 'platform/detection' interface Props extends ComponentProps<typeof Link> { // testID?: string @@ -27,6 +27,7 @@ export function PostHider({ }: Props) { const store = useStores() const pal = usePalette('default') + const {isMobile} = useWebMediaQueries() const [override, setOverride] = React.useState(false) if (!moderation.blur) { @@ -55,7 +56,11 @@ export function PostHider({ accessibilityRole="button" accessibilityHint={override ? 'Hide the content' : 'Show the content'} accessibilityLabel="" - style={[styles.description, pal.viewLight]}> + style={[ + styles.description, + {paddingRight: isMobile ? 22 : 18}, + pal.viewLight, + ]}> <Pressable onPress={() => { store.shell.openModal({ @@ -100,7 +105,6 @@ const styles = StyleSheet.create({ gap: 4, paddingVertical: 14, paddingLeft: 18, - paddingRight: isDesktopWeb ? 18 : 22, marginTop: 1, }, showBtn: { diff --git a/src/view/com/util/moderation/ScreenHider.tsx b/src/view/com/util/moderation/ScreenHider.tsx index b76b1101c..0224b9fee 100644 --- a/src/view/com/util/moderation/ScreenHider.tsx +++ b/src/view/com/util/moderation/ScreenHider.tsx @@ -13,10 +13,10 @@ import { import {useNavigation} from '@react-navigation/native' import {ModerationUI} from '@atproto/api' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {NavigationProp} from 'lib/routes/types' import {Text} from '../text/Text' import {Button} from '../forms/Button' -import {isDesktopWeb} from 'platform/detection' import {describeModerationCause} from 'lib/moderation' import {useStores} from 'state/index' @@ -39,6 +39,7 @@ export function ScreenHider({ const palInverted = usePalette('inverted') const [override, setOverride] = React.useState(false) const navigation = useNavigation<NavigationProp>() + const {isMobile} = useWebMediaQueries() if (!moderation.blur || override) { return ( @@ -85,7 +86,7 @@ export function ScreenHider({ </Text> </TouchableWithoutFeedback> </Text> - {!isDesktopWeb && <View style={styles.spacer} />} + {isMobile && <View style={styles.spacer} />} <View style={styles.btnContainer}> <Button type="inverted" diff --git a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx index 81f1ca560..d5bb38fb2 100644 --- a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx +++ b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx @@ -3,8 +3,8 @@ import {Image} from 'expo-image' import {Text} from '../text/Text' import {StyleSheet, View} from 'react-native' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {AppBskyEmbedExternal} from '@atproto/api' -import {isDesktopWeb} from 'platform/detection' import {toNiceDomain} from 'lib/strings/url-helpers' export const ExternalLinkEmbed = ({ @@ -15,10 +15,31 @@ export const ExternalLinkEmbed = ({ imageChild?: React.ReactNode }) => { const pal = usePalette('default') + const {isMobile} = useWebMediaQueries() return ( - <View style={styles.extContainer}> + <View + style={{ + flexDirection: isMobile ? 'column' : 'row', + }}> {link.thumb ? ( - <View style={styles.extImageContainer}> + <View + style={ + !isMobile + ? { + borderTopLeftRadius: 6, + borderBottomLeftRadius: 6, + width: 120, + aspectRatio: 1, + overflow: 'hidden', + } + : { + borderTopLeftRadius: 6, + borderTopRightRadius: 6, + width: '100%', + height: 200, + overflow: 'hidden', + } + }> <Image style={styles.extImage} source={{uri: link.thumb}} @@ -27,7 +48,13 @@ export const ExternalLinkEmbed = ({ {imageChild} </View> ) : undefined} - <View style={styles.extInner}> + <View + style={{ + paddingHorizontal: isMobile ? 10 : 14, + paddingTop: 8, + paddingBottom: 10, + flex: !isMobile ? 1 : undefined, + }}> <Text type="sm" numberOfLines={1} @@ -36,14 +63,14 @@ export const ExternalLinkEmbed = ({ </Text> <Text type="lg-bold" - numberOfLines={isDesktopWeb ? 2 : 4} + numberOfLines={isMobile ? 4 : 2} style={[pal.text]}> {link.title || link.uri} </Text> {link.description ? ( <Text type="md" - numberOfLines={isDesktopWeb ? 2 : 4} + numberOfLines={isMobile ? 4 : 2} style={[pal.text, styles.extDescription]}> {link.description} </Text> @@ -54,30 +81,6 @@ export const ExternalLinkEmbed = ({ } const styles = StyleSheet.create({ - extContainer: { - flexDirection: isDesktopWeb ? 'row' : 'column', - }, - extInner: { - paddingHorizontal: isDesktopWeb ? 14 : 10, - paddingTop: 8, - paddingBottom: 10, - flex: isDesktopWeb ? 1 : undefined, - }, - extImageContainer: isDesktopWeb - ? { - borderTopLeftRadius: 6, - borderBottomLeftRadius: 6, - width: 120, - aspectRatio: 1, - overflow: 'hidden', - } - : { - borderTopLeftRadius: 6, - borderTopRightRadius: 6, - width: '100%', - height: 200, - overflow: 'hidden', - }, extImage: { width: '100%', height: 200, diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx index bf2365f18..ce6da4a1b 100644 --- a/src/view/com/util/post-embeds/index.tsx +++ b/src/view/com/util/post-embeds/index.tsx @@ -22,6 +22,7 @@ import {ImageLayoutGrid} from '../images/ImageLayoutGrid' import {ImagesLightbox} from 'state/models/ui/shell' import {useStores} from 'state/index' import {usePalette} from 'lib/hooks/usePalette' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {YoutubeEmbed} from './YoutubeEmbed' import {ExternalLinkEmbed} from './ExternalLinkEmbed' import {getYoutubeVideoId} from 'lib/strings/url-helpers' @@ -29,7 +30,6 @@ import {MaybeQuoteEmbed} from './QuoteEmbed' import {AutoSizedImage} from '../images/AutoSizedImage' import {CustomFeedEmbed} from './CustomFeedEmbed' import {ListEmbed} from './ListEmbed' -import {isDesktopWeb} from 'platform/detection' import {isCauseALabelOnUri} from 'lib/moderation' type Embed = @@ -50,6 +50,7 @@ export function PostEmbeds({ }) { const pal = usePalette('default') const store = useStores() + const {isMobile} = useWebMediaQueries() // quote post with media // = @@ -111,7 +112,10 @@ export function PostEmbeds({ uri={thumb} onPress={() => openLightbox(0)} onPressIn={() => onPressIn(0)} - style={styles.singleImage}> + style={[ + styles.singleImage, + isMobile && styles.singleImageMobile, + ]}> {alt === '' ? null : ( <View style={styles.altContainer}> <Text style={styles.alt} accessible={false}> @@ -130,7 +134,11 @@ export function PostEmbeds({ images={embed.images} onPress={openLightbox} onPressIn={onPressIn} - style={embed.images.length === 1 ? styles.singleImage : undefined} + style={ + embed.images.length === 1 + ? [styles.singleImage, isMobile && styles.singleImageMobile] + : undefined + } /> </View> ) @@ -169,7 +177,10 @@ const styles = StyleSheet.create({ }, singleImage: { borderRadius: 8, - maxHeight: isDesktopWeb ? 1000 : 500, + maxHeight: 1000, + }, + singleImageMobile: { + maxHeight: 500, }, extOuter: { borderWidth: 1, |