Improve Device Detection For Better Responsiveness (#1512)
* Refactor `useOnMainScroll` function to use responsive device detection - Replace static `isDesktopWeb` with `useWebMediaQueries` hook to enable dynamic device type detection. - Create `useDeviceLimits` hook to dynamically determine `DY_LIMIT_UP` and `DY_LIMIT_DOWN` based on device type. - Update dependency arrays for the `useCallback` hooks to include new dynamic variables. * Refactor styles to be responsive to device type - Create `useStyles` hook that generates styles object based on device type detected from `useWebMediaQueries`. - Replace static styles object with dynamic styles object generated from `useStyles` hook in components. - This allows `paddingLeft` values for 'ul' and 'ol' styles to adapt to device type dynamically. - This allows `maxWidth` values for 'metaItem'' styles to adapt to device type dynamically. * Remove `isDesktopWeb` in favor of `useWebMediaQueries().isDesktop` * Refactor `SplashScreen` component for responsive design * Revision based on review results * Fix isNative check --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>zio/stable
parent
2e5f73ff61
commit
2aae37d67b
|
@ -2,12 +2,18 @@ import {useState, useCallback, useRef} from 'react'
|
||||||
import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native'
|
import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native'
|
||||||
import {RootStoreModel} from 'state/index'
|
import {RootStoreModel} from 'state/index'
|
||||||
import {s} from 'lib/styles'
|
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 Y_LIMIT = 10
|
||||||
|
|
||||||
|
const useDeviceLimits = () => {
|
||||||
|
const {isDesktop} = useWebMediaQueries()
|
||||||
|
return {
|
||||||
|
dyLimitUp: isDesktop ? 30 : 10,
|
||||||
|
dyLimitDown: isDesktop ? 150 : 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type OnScrollCb = (
|
export type OnScrollCb = (
|
||||||
event: NativeSyntheticEvent<NativeScrollEvent>,
|
event: NativeSyntheticEvent<NativeScrollEvent>,
|
||||||
) => void
|
) => void
|
||||||
|
@ -18,6 +24,8 @@ export function useOnMainScroll(
|
||||||
): [OnScrollCb, boolean, ResetCb] {
|
): [OnScrollCb, boolean, ResetCb] {
|
||||||
let lastY = useRef(0)
|
let lastY = useRef(0)
|
||||||
let [isScrolledDown, setIsScrolledDown] = useState(false)
|
let [isScrolledDown, setIsScrolledDown] = useState(false)
|
||||||
|
const {dyLimitUp, dyLimitDown} = useDeviceLimits()
|
||||||
|
|
||||||
return [
|
return [
|
||||||
useCallback(
|
useCallback(
|
||||||
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
|
@ -25,15 +33,11 @@ export function useOnMainScroll(
|
||||||
const dy = y - (lastY.current || 0)
|
const dy = y - (lastY.current || 0)
|
||||||
lastY.current = y
|
lastY.current = y
|
||||||
|
|
||||||
if (
|
if (!store.shell.minimalShellMode && dy > dyLimitDown && y > Y_LIMIT) {
|
||||||
!store.shell.minimalShellMode &&
|
|
||||||
dy > DY_LIMIT_DOWN &&
|
|
||||||
y > Y_LIMIT
|
|
||||||
) {
|
|
||||||
store.shell.setMinimalShellMode(true)
|
store.shell.setMinimalShellMode(true)
|
||||||
} else if (
|
} else if (
|
||||||
store.shell.minimalShellMode &&
|
store.shell.minimalShellMode &&
|
||||||
(dy < DY_LIMIT_UP * -1 || y <= Y_LIMIT)
|
(dy < dyLimitUp * -1 || y <= Y_LIMIT)
|
||||||
) {
|
) {
|
||||||
store.shell.setMinimalShellMode(false)
|
store.shell.setMinimalShellMode(false)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +54,7 @@ export function useOnMainScroll(
|
||||||
setIsScrolledDown(false)
|
setIsScrolledDown(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[store, isScrolledDown],
|
[store.shell, dyLimitDown, dyLimitUp, isScrolledDown],
|
||||||
),
|
),
|
||||||
isScrolledDown,
|
isScrolledDown,
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
|
|
|
@ -12,7 +12,6 @@ export const isMobileWeb =
|
||||||
isWeb &&
|
isWeb &&
|
||||||
// @ts-ignore we know window exists -prf
|
// @ts-ignore we know window exists -prf
|
||||||
global.window.matchMedia(isMobileWebMediaQuery)?.matches
|
global.window.matchMedia(isMobileWebMediaQuery)?.matches
|
||||||
export const isDesktopWeb = isWeb && !isMobileWeb
|
|
||||||
|
|
||||||
export const deviceLocales = dedupArray(
|
export const deviceLocales = dedupArray(
|
||||||
getLocales?.().map?.(locale => locale.languageCode),
|
getLocales?.().map?.(locale => locale.languageCode),
|
||||||
|
|
|
@ -6,7 +6,8 @@ import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {CenteredView} from '../util/Views'
|
import {CenteredView} from '../util/Views'
|
||||||
import {isMobileWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
export const SplashScreen = ({
|
export const SplashScreen = ({
|
||||||
onPressSignin,
|
onPressSignin,
|
||||||
|
@ -16,6 +17,9 @@ export const SplashScreen = ({
|
||||||
onPressCreateAccount: () => void
|
onPressCreateAccount: () => void
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isTabletOrMobile} = useWebMediaQueries()
|
||||||
|
const styles = useStyles()
|
||||||
|
const isMobileWeb = isWeb && isTabletOrMobile
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredView style={[styles.container, pal.view]}>
|
<CenteredView style={[styles.container, pal.view]}>
|
||||||
|
@ -55,13 +59,14 @@ export const SplashScreen = ({
|
||||||
</View>
|
</View>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</View>
|
</View>
|
||||||
<Footer />
|
<Footer styles={styles} />
|
||||||
</CenteredView>
|
</CenteredView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function Footer() {
|
function Footer({styles}: {styles: ReturnType<typeof useStyles>}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.footer, pal.view, pal.border]}>
|
<View style={[styles.footer, pal.view, pal.border]}>
|
||||||
<TextLink
|
<TextLink
|
||||||
|
@ -82,78 +87,81 @@ function Footer() {
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const useStyles = () => {
|
||||||
const styles = StyleSheet.create({
|
const {isTabletOrMobile} = useWebMediaQueries()
|
||||||
container: {
|
const isMobileWeb = isWeb && isTabletOrMobile
|
||||||
height: '100%',
|
return StyleSheet.create({
|
||||||
},
|
container: {
|
||||||
containerInner: {
|
height: '100%',
|
||||||
height: '100%',
|
},
|
||||||
justifyContent: 'center',
|
containerInner: {
|
||||||
// @ts-ignore web only
|
height: '100%',
|
||||||
paddingBottom: '20vh',
|
justifyContent: 'center',
|
||||||
paddingHorizontal: 20,
|
// @ts-ignore web only
|
||||||
},
|
paddingBottom: '20vh',
|
||||||
containerInnerMobile: {
|
paddingHorizontal: 20,
|
||||||
paddingBottom: 50,
|
},
|
||||||
},
|
containerInnerMobile: {
|
||||||
title: {
|
paddingBottom: 50,
|
||||||
textAlign: 'center',
|
},
|
||||||
color: colors.blue3,
|
title: {
|
||||||
fontSize: 68,
|
textAlign: 'center',
|
||||||
fontWeight: 'bold',
|
color: colors.blue3,
|
||||||
paddingBottom: 10,
|
fontSize: 68,
|
||||||
},
|
fontWeight: 'bold',
|
||||||
titleMobile: {
|
paddingBottom: 10,
|
||||||
textAlign: 'center',
|
},
|
||||||
color: colors.blue3,
|
titleMobile: {
|
||||||
fontSize: 58,
|
textAlign: 'center',
|
||||||
fontWeight: 'bold',
|
color: colors.blue3,
|
||||||
},
|
fontSize: 58,
|
||||||
subtitle: {
|
fontWeight: 'bold',
|
||||||
textAlign: 'center',
|
},
|
||||||
color: colors.gray5,
|
subtitle: {
|
||||||
fontSize: 52,
|
textAlign: 'center',
|
||||||
fontWeight: 'bold',
|
color: colors.gray5,
|
||||||
paddingBottom: 30,
|
fontSize: 52,
|
||||||
},
|
fontWeight: 'bold',
|
||||||
subtitleMobile: {
|
paddingBottom: 30,
|
||||||
textAlign: 'center',
|
},
|
||||||
color: colors.gray5,
|
subtitleMobile: {
|
||||||
fontSize: 42,
|
textAlign: 'center',
|
||||||
fontWeight: 'bold',
|
color: colors.gray5,
|
||||||
paddingBottom: 30,
|
fontSize: 42,
|
||||||
},
|
fontWeight: 'bold',
|
||||||
btns: {
|
paddingBottom: 30,
|
||||||
flexDirection: isMobileWeb ? 'column' : 'row',
|
},
|
||||||
gap: 20,
|
btns: {
|
||||||
justifyContent: 'center',
|
flexDirection: isMobileWeb ? 'column' : 'row',
|
||||||
paddingBottom: 40,
|
gap: 20,
|
||||||
},
|
justifyContent: 'center',
|
||||||
btn: {
|
paddingBottom: 40,
|
||||||
borderRadius: 30,
|
},
|
||||||
paddingHorizontal: 24,
|
btn: {
|
||||||
paddingVertical: 12,
|
borderRadius: 30,
|
||||||
minWidth: 220,
|
paddingHorizontal: 24,
|
||||||
},
|
paddingVertical: 12,
|
||||||
btnLabel: {
|
minWidth: 220,
|
||||||
textAlign: 'center',
|
},
|
||||||
fontSize: 18,
|
btnLabel: {
|
||||||
},
|
textAlign: 'center',
|
||||||
notice: {
|
fontSize: 18,
|
||||||
paddingHorizontal: 40,
|
},
|
||||||
textAlign: 'center',
|
notice: {
|
||||||
},
|
paddingHorizontal: 40,
|
||||||
footer: {
|
textAlign: 'center',
|
||||||
position: 'absolute',
|
},
|
||||||
left: 0,
|
footer: {
|
||||||
right: 0,
|
position: 'absolute',
|
||||||
bottom: 0,
|
left: 0,
|
||||||
padding: 20,
|
right: 0,
|
||||||
borderTopWidth: 1,
|
bottom: 0,
|
||||||
flexDirection: 'row',
|
padding: 20,
|
||||||
},
|
borderTopWidth: 1,
|
||||||
footerLink: {
|
flexDirection: 'row',
|
||||||
marginRight: 20,
|
},
|
||||||
},
|
footerLink: {
|
||||||
})
|
marginRight: 20,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ import {
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {openCamera} from 'lib/media/picker'
|
import {openCamera} from 'lib/media/picker'
|
||||||
import {useCameraPermission} from 'lib/hooks/usePermissions'
|
import {useCameraPermission} from 'lib/hooks/usePermissions'
|
||||||
import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants'
|
import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants'
|
||||||
import {GalleryModel} from 'state/models/media/gallery'
|
import {GalleryModel} from 'state/models/media/gallery'
|
||||||
|
import {isMobileWeb, isNative} from 'platform/detection'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
gallery: GalleryModel
|
gallery: GalleryModel
|
||||||
|
@ -43,7 +43,8 @@ export function OpenCameraBtn({gallery}: Props) {
|
||||||
}
|
}
|
||||||
}, [gallery, track, store, requestCameraAccessIfNeeded])
|
}, [gallery, track, store, requestCameraAccessIfNeeded])
|
||||||
|
|
||||||
if (isDesktopWeb) {
|
const shouldShowCameraButton = isNative || isMobileWeb
|
||||||
|
if (!shouldShowCameraButton) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ import {
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
|
import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
|
||||||
import {GalleryModel} from 'state/models/media/gallery'
|
import {GalleryModel} from 'state/models/media/gallery'
|
||||||
import {HITSLOP_10} from 'lib/constants'
|
import {HITSLOP_10} from 'lib/constants'
|
||||||
|
import {isNative} from 'platform/detection'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
gallery: GalleryModel
|
gallery: GalleryModel
|
||||||
|
@ -23,12 +23,12 @@ export function SelectPhotoBtn({gallery}: Props) {
|
||||||
const onPressSelectPhotos = useCallback(async () => {
|
const onPressSelectPhotos = useCallback(async () => {
|
||||||
track('Composer:GalleryOpened')
|
track('Composer:GalleryOpened')
|
||||||
|
|
||||||
if (!isDesktopWeb && !(await requestPhotoAccessIfNeeded())) {
|
if (isNative && !(await requestPhotoAccessIfNeeded())) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gallery.pick()
|
gallery.pick()
|
||||||
}, [track, gallery, requestPhotoAccessIfNeeded])
|
}, [track, requestPhotoAccessIfNeeded, gallery])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {ViewHeader} from '../util/ViewHeader'
|
||||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {isNative, isDesktopWeb} from 'platform/detection'
|
import {isNative} from 'platform/detection'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
@ -78,7 +78,7 @@ export const PostThread = observer(function PostThread({
|
||||||
treeView: boolean
|
treeView: boolean
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {isTablet} = useWebMediaQueries()
|
const {isTablet, isDesktop} = useWebMediaQueries()
|
||||||
const ref = useRef<FlatList>(null)
|
const ref = useRef<FlatList>(null)
|
||||||
const hasScrolledIntoView = useRef<boolean>(false)
|
const hasScrolledIntoView = useRef<boolean>(false)
|
||||||
const [isRefreshing, setIsRefreshing] = React.useState(false)
|
const [isRefreshing, setIsRefreshing] = React.useState(false)
|
||||||
|
@ -189,7 +189,7 @@ export const PostThread = observer(function PostThread({
|
||||||
} else if (item === REPLY_PROMPT) {
|
} else if (item === REPLY_PROMPT) {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{isDesktopWeb && <ComposePrompt onPressCompose={onPressReply} />}
|
{isDesktop && <ComposePrompt onPressCompose={onPressReply} />}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
} else if (item === DELETED) {
|
} else if (item === DELETED) {
|
||||||
|
@ -261,7 +261,20 @@ export const PostThread = observer(function PostThread({
|
||||||
}
|
}
|
||||||
return <></>
|
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
|
// loading
|
||||||
|
|
|
@ -34,7 +34,6 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {formatCount} from '../util/numeric/format'
|
import {formatCount} from '../util/numeric/format'
|
||||||
import {TimeElapsed} from 'view/com/util/TimeElapsed'
|
import {TimeElapsed} from 'view/com/util/TimeElapsed'
|
||||||
import {makeProfileLink} from 'lib/routes/links'
|
import {makeProfileLink} from 'lib/routes/links'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
export const PostThreadItem = observer(function PostThreadItem({
|
export const PostThreadItem = observer(function PostThreadItem({
|
||||||
|
@ -51,6 +50,7 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const [deleted, setDeleted] = React.useState(false)
|
const [deleted, setDeleted] = React.useState(false)
|
||||||
|
const styles = useStyles()
|
||||||
const record = item.postRecord
|
const record = item.postRecord
|
||||||
const hasEngagement = item.post.likeCount || item.post.repostCount
|
const hasEngagement = item.post.likeCount || item.post.repostCount
|
||||||
|
|
||||||
|
@ -568,6 +568,7 @@ function PostOuterWrapper({
|
||||||
}>) {
|
}>) {
|
||||||
const {isMobile} = useWebMediaQueries()
|
const {isMobile} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const styles = useStyles()
|
||||||
if (treeView && item._depth > 1) {
|
if (treeView && item._depth > 1) {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
@ -636,90 +637,93 @@ function ExpandedPostDetails({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const useStyles = () => {
|
||||||
outer: {
|
const {isDesktop} = useWebMediaQueries()
|
||||||
borderTopWidth: 1,
|
return StyleSheet.create({
|
||||||
paddingLeft: 8,
|
outer: {
|
||||||
},
|
borderTopWidth: 1,
|
||||||
outerHighlighted: {
|
paddingLeft: 8,
|
||||||
paddingTop: 16,
|
},
|
||||||
paddingLeft: 8,
|
outerHighlighted: {
|
||||||
paddingRight: 8,
|
paddingTop: 16,
|
||||||
},
|
paddingLeft: 8,
|
||||||
noTopBorder: {
|
paddingRight: 8,
|
||||||
borderTopWidth: 0,
|
},
|
||||||
},
|
noTopBorder: {
|
||||||
layout: {
|
borderTopWidth: 0,
|
||||||
flexDirection: 'row',
|
},
|
||||||
gap: 10,
|
layout: {
|
||||||
paddingLeft: 8,
|
flexDirection: 'row',
|
||||||
},
|
gap: 10,
|
||||||
layoutAvi: {},
|
paddingLeft: 8,
|
||||||
layoutContent: {
|
},
|
||||||
flex: 1,
|
layoutAvi: {},
|
||||||
paddingRight: 10,
|
layoutContent: {
|
||||||
},
|
flex: 1,
|
||||||
meta: {
|
paddingRight: 10,
|
||||||
flexDirection: 'row',
|
},
|
||||||
paddingTop: 2,
|
meta: {
|
||||||
paddingBottom: 2,
|
flexDirection: 'row',
|
||||||
},
|
paddingTop: 2,
|
||||||
metaExpandedLine1: {
|
paddingBottom: 2,
|
||||||
paddingTop: 5,
|
},
|
||||||
paddingBottom: 0,
|
metaExpandedLine1: {
|
||||||
},
|
paddingTop: 5,
|
||||||
metaItem: {
|
paddingBottom: 0,
|
||||||
paddingRight: 5,
|
},
|
||||||
maxWidth: isDesktopWeb ? 380 : 220,
|
metaItem: {
|
||||||
},
|
paddingRight: 5,
|
||||||
alert: {
|
maxWidth: isDesktop ? 380 : 220,
|
||||||
marginBottom: 6,
|
},
|
||||||
},
|
alert: {
|
||||||
postTextContainer: {
|
marginBottom: 6,
|
||||||
flexDirection: 'row',
|
},
|
||||||
alignItems: 'center',
|
postTextContainer: {
|
||||||
flexWrap: 'wrap',
|
flexDirection: 'row',
|
||||||
paddingBottom: 4,
|
alignItems: 'center',
|
||||||
paddingRight: 10,
|
flexWrap: 'wrap',
|
||||||
},
|
paddingBottom: 4,
|
||||||
postTextLargeContainer: {
|
paddingRight: 10,
|
||||||
paddingHorizontal: 0,
|
},
|
||||||
paddingBottom: 10,
|
postTextLargeContainer: {
|
||||||
},
|
paddingHorizontal: 0,
|
||||||
translateLink: {
|
paddingBottom: 10,
|
||||||
marginBottom: 6,
|
},
|
||||||
},
|
translateLink: {
|
||||||
contentHider: {
|
marginBottom: 6,
|
||||||
marginBottom: 6,
|
},
|
||||||
},
|
contentHider: {
|
||||||
contentHiderChild: {
|
marginBottom: 6,
|
||||||
marginTop: 6,
|
},
|
||||||
},
|
contentHiderChild: {
|
||||||
expandedInfo: {
|
marginTop: 6,
|
||||||
flexDirection: 'row',
|
},
|
||||||
padding: 10,
|
expandedInfo: {
|
||||||
borderTopWidth: 1,
|
flexDirection: 'row',
|
||||||
borderBottomWidth: 1,
|
padding: 10,
|
||||||
marginTop: 5,
|
borderTopWidth: 1,
|
||||||
marginBottom: 15,
|
borderBottomWidth: 1,
|
||||||
},
|
marginTop: 5,
|
||||||
expandedInfoItem: {
|
marginBottom: 15,
|
||||||
marginRight: 10,
|
},
|
||||||
},
|
expandedInfoItem: {
|
||||||
loadMore: {
|
marginRight: 10,
|
||||||
flexDirection: 'row',
|
},
|
||||||
alignItems: 'center',
|
loadMore: {
|
||||||
justifyContent: 'flex-start',
|
flexDirection: 'row',
|
||||||
gap: 4,
|
alignItems: 'center',
|
||||||
paddingHorizontal: 20,
|
justifyContent: 'flex-start',
|
||||||
},
|
gap: 4,
|
||||||
replyLine: {
|
paddingHorizontal: 20,
|
||||||
width: 2,
|
},
|
||||||
marginLeft: 'auto',
|
replyLine: {
|
||||||
marginRight: 'auto',
|
width: 2,
|
||||||
},
|
marginLeft: 'auto',
|
||||||
cursor: {
|
marginRight: 'auto',
|
||||||
// @ts-ignore web only
|
},
|
||||||
cursor: 'pointer',
|
cursor: {
|
||||||
},
|
// @ts-ignore web only
|
||||||
})
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {Text} from './text/Text'
|
import {Text} from './text/Text'
|
||||||
import {TextLink} from './Link'
|
import {TextLink} from './Link'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {
|
import {
|
||||||
H1 as ExpoH1,
|
H1 as ExpoH1,
|
||||||
H2 as ExpoH2,
|
H2 as ExpoH2,
|
||||||
H3 as ExpoH3,
|
H3 as ExpoH3,
|
||||||
H4 as ExpoH4,
|
H4 as ExpoH4,
|
||||||
} from '@expo/html-elements'
|
} from '@expo/html-elements'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These utilities are used to define long documents in an html-like
|
* These utilities are used to define long documents in an html-like
|
||||||
|
@ -27,30 +27,35 @@ interface IsChildProps {
|
||||||
// | React.ReactNode
|
// | React.ReactNode
|
||||||
|
|
||||||
export function H1({children}: React.PropsWithChildren<{}>) {
|
export function H1({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const typography = useTheme().typography['title-xl']
|
const typography = useTheme().typography['title-xl']
|
||||||
return <ExpoH1 style={[typography, pal.text, styles.h1]}>{children}</ExpoH1>
|
return <ExpoH1 style={[typography, pal.text, styles.h1]}>{children}</ExpoH1>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function H2({children}: React.PropsWithChildren<{}>) {
|
export function H2({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const typography = useTheme().typography['title-lg']
|
const typography = useTheme().typography['title-lg']
|
||||||
return <ExpoH2 style={[typography, pal.text, styles.h2]}>{children}</ExpoH2>
|
return <ExpoH2 style={[typography, pal.text, styles.h2]}>{children}</ExpoH2>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function H3({children}: React.PropsWithChildren<{}>) {
|
export function H3({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const typography = useTheme().typography.title
|
const typography = useTheme().typography.title
|
||||||
return <ExpoH3 style={[typography, pal.text, styles.h3]}>{children}</ExpoH3>
|
return <ExpoH3 style={[typography, pal.text, styles.h3]}>{children}</ExpoH3>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function H4({children}: React.PropsWithChildren<{}>) {
|
export function H4({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const typography = useTheme().typography['title-sm']
|
const typography = useTheme().typography['title-sm']
|
||||||
return <ExpoH4 style={[typography, pal.text, styles.h4]}>{children}</ExpoH4>
|
return <ExpoH4 style={[typography, pal.text, styles.h4]}>{children}</ExpoH4>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function P({children}: React.PropsWithChildren<{}>) {
|
export function P({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<Text type="md" style={[pal.text, styles.p]}>
|
<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>) {
|
export function UL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
|
||||||
|
const styles = useStyles()
|
||||||
return (
|
return (
|
||||||
<View style={[styles.ul, isChild && styles.ulChild]}>
|
<View style={[styles.ul, isChild && styles.ulChild]}>
|
||||||
{markChildProps(children)}
|
{markChildProps(children)}
|
||||||
|
@ -68,6 +74,7 @@ export function UL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
|
export function OL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
|
||||||
|
const styles = useStyles()
|
||||||
return (
|
return (
|
||||||
<View style={[styles.ol, isChild && styles.olChild]}>
|
<View style={[styles.ol, isChild && styles.olChild]}>
|
||||||
{markChildProps(children)}
|
{markChildProps(children)}
|
||||||
|
@ -79,6 +86,7 @@ export function LI({
|
||||||
children,
|
children,
|
||||||
value,
|
value,
|
||||||
}: React.PropsWithChildren<{value?: string}>) {
|
}: React.PropsWithChildren<{value?: string}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<View style={styles.li}>
|
<View style={styles.li}>
|
||||||
|
@ -91,6 +99,7 @@ export function LI({
|
||||||
}
|
}
|
||||||
|
|
||||||
export function A({children, href}: React.PropsWithChildren<{href: string}>) {
|
export function A({children, href}: React.PropsWithChildren<{href: string}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<TextLink
|
<TextLink
|
||||||
|
@ -112,6 +121,7 @@ export function STRONG({children}: React.PropsWithChildren<{}>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EM({children}: React.PropsWithChildren<{}>) {
|
export function EM({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const styles = useStyles()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<Text type="md" style={[pal.text, styles.em]}>
|
<Text type="md" style={[pal.text, styles.em]}>
|
||||||
|
@ -132,58 +142,61 @@ function markChildProps(children: React.ReactNode) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const useStyles = () => {
|
||||||
h1: {
|
const {isDesktop} = useWebMediaQueries()
|
||||||
marginTop: 20,
|
return StyleSheet.create({
|
||||||
marginBottom: 10,
|
h1: {
|
||||||
letterSpacing: 0.8,
|
marginTop: 20,
|
||||||
},
|
marginBottom: 10,
|
||||||
h2: {
|
letterSpacing: 0.8,
|
||||||
marginTop: 20,
|
},
|
||||||
marginBottom: 10,
|
h2: {
|
||||||
letterSpacing: 0.8,
|
marginTop: 20,
|
||||||
},
|
marginBottom: 10,
|
||||||
h3: {
|
letterSpacing: 0.8,
|
||||||
marginTop: 0,
|
},
|
||||||
marginBottom: 10,
|
h3: {
|
||||||
},
|
marginTop: 0,
|
||||||
h4: {
|
marginBottom: 10,
|
||||||
marginTop: 0,
|
},
|
||||||
marginBottom: 10,
|
h4: {
|
||||||
fontWeight: 'bold',
|
marginTop: 0,
|
||||||
},
|
marginBottom: 10,
|
||||||
p: {
|
fontWeight: 'bold',
|
||||||
marginBottom: 10,
|
},
|
||||||
},
|
p: {
|
||||||
ul: {
|
marginBottom: 10,
|
||||||
marginBottom: 10,
|
},
|
||||||
paddingLeft: isDesktopWeb ? 18 : 4,
|
ul: {
|
||||||
},
|
marginBottom: 10,
|
||||||
ulChild: {
|
paddingLeft: isDesktop ? 18 : 4,
|
||||||
paddingTop: 10,
|
},
|
||||||
marginBottom: 0,
|
ulChild: {
|
||||||
},
|
paddingTop: 10,
|
||||||
ol: {
|
marginBottom: 0,
|
||||||
marginBottom: 10,
|
},
|
||||||
paddingLeft: isDesktopWeb ? 18 : 4,
|
ol: {
|
||||||
},
|
marginBottom: 10,
|
||||||
olChild: {
|
paddingLeft: isDesktop ? 18 : 4,
|
||||||
paddingTop: 10,
|
},
|
||||||
marginBottom: 0,
|
olChild: {
|
||||||
},
|
paddingTop: 10,
|
||||||
li: {
|
marginBottom: 0,
|
||||||
flexDirection: 'row',
|
},
|
||||||
paddingRight: 20,
|
li: {
|
||||||
marginBottom: 10,
|
flexDirection: 'row',
|
||||||
},
|
paddingRight: 20,
|
||||||
liBullet: {
|
marginBottom: 10,
|
||||||
paddingRight: 10,
|
},
|
||||||
},
|
liBullet: {
|
||||||
liText: {},
|
paddingRight: 10,
|
||||||
a: {
|
},
|
||||||
marginBottom: 10,
|
liText: {},
|
||||||
},
|
a: {
|
||||||
em: {
|
marginBottom: 10,
|
||||||
fontStyle: 'italic',
|
},
|
||||||
},
|
em: {
|
||||||
})
|
fontStyle: 'italic',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -24,10 +24,11 @@ import {NavigationProp} from 'lib/routes/types'
|
||||||
import {router} from '../../../routes'
|
import {router} from '../../../routes'
|
||||||
import {useStores, RootStoreModel} from 'state/index'
|
import {useStores, RootStoreModel} from 'state/index'
|
||||||
import {convertBskyAppUrlIfNeeded, isExternalUrl} from 'lib/strings/url-helpers'
|
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 {sanitizeUrl} from '@braintree/sanitize-url'
|
||||||
import {PressableWithHover} from './PressableWithHover'
|
import {PressableWithHover} from './PressableWithHover'
|
||||||
import FixedTouchableHighlight from '../pager/FixedTouchableHighlight'
|
import FixedTouchableHighlight from '../pager/FixedTouchableHighlight'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
type Event =
|
type Event =
|
||||||
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
||||||
|
@ -224,7 +225,9 @@ export const DesktopWebTextLink = observer(function DesktopWebTextLink({
|
||||||
lineHeight,
|
lineHeight,
|
||||||
...props
|
...props
|
||||||
}: DesktopWebTextLinkProps) {
|
}: DesktopWebTextLinkProps) {
|
||||||
if (isDesktopWeb) {
|
const {isDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
|
if (isDesktop) {
|
||||||
return (
|
return (
|
||||||
<TextLink
|
<TextLink
|
||||||
testID={testID}
|
testID={testID}
|
||||||
|
|
Loading…
Reference in New Issue