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 multifeedzio/stable
parent
be8084ae10
commit
764c7cd569
|
@ -2,13 +2,19 @@ import {useMediaQuery} from 'react-responsive'
|
||||||
import {isNative} from 'platform/detection'
|
import {isNative} from 'platform/detection'
|
||||||
|
|
||||||
export function useWebMediaQueries() {
|
export function useWebMediaQueries() {
|
||||||
const isDesktop = useMediaQuery({
|
const isDesktop = useMediaQuery({minWidth: 1300})
|
||||||
query: '(min-width: 1224px)',
|
const isTablet = useMediaQuery({minWidth: 800, maxWidth: 1300})
|
||||||
})
|
const isMobile = useMediaQuery({maxWidth: 800})
|
||||||
const isTabletOrMobile = useMediaQuery({query: '(max-width: 1224px)'})
|
const isTabletOrMobile = isMobile || isTablet
|
||||||
const isMobile = useMediaQuery({query: '(max-width: 800px)'})
|
const isTabletOrDesktop = isDesktop || isTablet
|
||||||
if (isNative) {
|
if (isNative) {
|
||||||
return {isMobile: true, isTabletOrMobile: true, isDesktop: false}
|
return {
|
||||||
|
isMobile: true,
|
||||||
|
isTablet: false,
|
||||||
|
isTabletOrMobile: true,
|
||||||
|
isTabletOrDesktop: false,
|
||||||
|
isDesktop: false,
|
||||||
}
|
}
|
||||||
return {isMobile, isTabletOrMobile, isDesktop}
|
}
|
||||||
|
return {isMobile, isTablet, isTabletOrMobile, isTabletOrDesktop, isDesktop}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const isAndroid = Platform.OS === 'android'
|
||||||
export const isNative = isIOS || isAndroid
|
export const isNative = isIOS || isAndroid
|
||||||
export const devicePlatform = isIOS ? 'ios' : isAndroid ? 'android' : 'web'
|
export const devicePlatform = isIOS ? 'ios' : isAndroid ? 'android' : 'web'
|
||||||
export const isWeb = !isNative
|
export const isWeb = !isNative
|
||||||
export const isMobileWebMediaQuery = 'only screen and (max-width: 1230px)'
|
export const isMobileWebMediaQuery = 'only screen and (max-width: 1300px)'
|
||||||
export const isMobileWeb =
|
export const isMobileWeb =
|
||||||
isWeb &&
|
isWeb &&
|
||||||
// @ts-ignore we know window exists -prf
|
// @ts-ignore we know window exists -prf
|
||||||
|
|
|
@ -111,7 +111,8 @@ export class PostsMultiFeedModel {
|
||||||
uri: makeProfileLink(feedInfo.data.creator, 'feed', urip.rkey),
|
uri: makeProfileLink(feedInfo.data.creator, 'feed', urip.rkey),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (!this.hasMore) {
|
if (!this.hasMore && this.hasContent) {
|
||||||
|
// only show if hasContent to avoid double discover-feed links
|
||||||
items.push({_reactKey: '__footer__', type: 'footer'})
|
items.push({_reactKey: '__footer__', type: 'footer'})
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
|
|
|
@ -16,9 +16,7 @@ type Props = {
|
||||||
|
|
||||||
export const WelcomeDesktop = observer(({next}: Props) => {
|
export const WelcomeDesktop = observer(({next}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const horizontal = useMediaQuery({
|
const horizontal = useMediaQuery({minWidth: 1300})
|
||||||
query: '(min-width: 1230px)',
|
|
||||||
})
|
|
||||||
const title = (
|
const title = (
|
||||||
<>
|
<>
|
||||||
<Text
|
<Text
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {Button} from 'view/com/util/forms/Button'
|
import {Button} from 'view/com/util/forms/Button'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
next: () => void
|
next: () => void
|
||||||
|
@ -95,7 +94,7 @@ export const WelcomeMobile = observer(({next, skip}: Props) => {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
marginBottom: isDesktopWeb ? 30 : 60,
|
marginBottom: 60,
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
},
|
},
|
||||||
|
|
|
@ -37,9 +37,10 @@ import {toShortUrl} from 'lib/strings/url-helpers'
|
||||||
import {SelectPhotoBtn} from './photos/SelectPhotoBtn'
|
import {SelectPhotoBtn} from './photos/SelectPhotoBtn'
|
||||||
import {OpenCameraBtn} from './photos/OpenCameraBtn'
|
import {OpenCameraBtn} from './photos/OpenCameraBtn'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import QuoteEmbed from '../util/post-embeds/QuoteEmbed'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {useExternalLinkFetch} from './useExternalLinkFetch'
|
import {useExternalLinkFetch} from './useExternalLinkFetch'
|
||||||
import {isDesktopWeb, isAndroid, isIOS} from 'platform/detection'
|
import {isWeb, isNative, isAndroid, isIOS} from 'platform/detection'
|
||||||
|
import QuoteEmbed from '../util/post-embeds/QuoteEmbed'
|
||||||
import {GalleryModel} from 'state/models/media/gallery'
|
import {GalleryModel} from 'state/models/media/gallery'
|
||||||
import {Gallery} from './photos/Gallery'
|
import {Gallery} from './photos/Gallery'
|
||||||
import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
|
import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
|
||||||
|
@ -61,6 +62,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isDesktop, isMobile} = useWebMediaQueries()
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const textInput = useRef<TextInputRef>(null)
|
const textInput = useRef<TextInputRef>(null)
|
||||||
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
||||||
|
@ -99,9 +101,9 @@ export const ComposePost = observer(function ComposePost({
|
||||||
() => ({
|
() => ({
|
||||||
paddingBottom:
|
paddingBottom:
|
||||||
isAndroid || (isIOS && !isKeyboardVisible) ? insets.bottom : 0,
|
isAndroid || (isIOS && !isKeyboardVisible) ? insets.bottom : 0,
|
||||||
paddingTop: isAndroid ? insets.top : isDesktopWeb ? 0 : 15,
|
paddingTop: isAndroid ? insets.top : isMobile ? 15 : 0,
|
||||||
}),
|
}),
|
||||||
[insets, isKeyboardVisible],
|
[insets, isKeyboardVisible, isMobile],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onPressCancel = useCallback(() => {
|
const onPressCancel = useCallback(() => {
|
||||||
|
@ -143,7 +145,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
[onPressCancel],
|
[onPressCancel],
|
||||||
)
|
)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDesktopWeb) {
|
if (isWeb) {
|
||||||
window.addEventListener('keydown', onEscape)
|
window.addEventListener('keydown', onEscape)
|
||||||
return () => window.removeEventListener('keydown', onEscape)
|
return () => window.removeEventListener('keydown', onEscape)
|
||||||
}
|
}
|
||||||
|
@ -240,7 +242,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
style={styles.outer}>
|
style={styles.outer}>
|
||||||
<View style={[s.flex1, viewStyles]} aria-modal accessibilityViewIsModal>
|
<View style={[s.flex1, viewStyles]} aria-modal accessibilityViewIsModal>
|
||||||
<View style={styles.topbar}>
|
<View style={[styles.topbar, isDesktop && styles.topbarDesktop]}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="composerDiscardButton"
|
testID="composerDiscardButton"
|
||||||
onPress={onPressCancel}
|
onPress={onPressCancel}
|
||||||
|
@ -334,7 +336,12 @@ export const ComposePost = observer(function ComposePost({
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
|
||||||
<View style={[pal.border, styles.textInputLayout]}>
|
<View
|
||||||
|
style={[
|
||||||
|
pal.border,
|
||||||
|
styles.textInputLayout,
|
||||||
|
isNative && styles.textInputLayoutMobile,
|
||||||
|
]}>
|
||||||
<UserAvatar avatar={store.me.avatar} size={50} />
|
<UserAvatar avatar={store.me.avatar} size={50} />
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={textInput}
|
ref={textInput}
|
||||||
|
@ -362,7 +369,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{quote ? (
|
{quote ? (
|
||||||
<View style={s.mt5}>
|
<View style={[s.mt5, isWeb && s.mb10]}>
|
||||||
<QuoteEmbed quote={quote} />
|
<QuoteEmbed quote={quote} />
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
@ -395,7 +402,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
<OpenCameraBtn gallery={gallery} />
|
<OpenCameraBtn gallery={gallery} />
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
{isDesktopWeb ? <EmojiPickerButton /> : null}
|
{isDesktop ? <EmojiPickerButton /> : null}
|
||||||
<View style={s.flex1} />
|
<View style={s.flex1} />
|
||||||
<SelectLangBtn />
|
<SelectLangBtn />
|
||||||
<CharProgress count={graphemeLength} />
|
<CharProgress count={graphemeLength} />
|
||||||
|
@ -414,11 +421,14 @@ const styles = StyleSheet.create({
|
||||||
topbar: {
|
topbar: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingTop: isDesktopWeb ? 10 : undefined,
|
paddingBottom: 4,
|
||||||
paddingBottom: isDesktopWeb ? 10 : 4,
|
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
height: 55,
|
height: 55,
|
||||||
},
|
},
|
||||||
|
topbarDesktop: {
|
||||||
|
paddingTop: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
postBtn: {
|
postBtn: {
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
|
@ -465,11 +475,13 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 15,
|
paddingHorizontal: 15,
|
||||||
},
|
},
|
||||||
textInputLayout: {
|
textInputLayout: {
|
||||||
flex: isDesktopWeb ? undefined : 1,
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
paddingTop: 16,
|
paddingTop: 16,
|
||||||
},
|
},
|
||||||
|
textInputLayoutMobile: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
replyToLayout: {
|
replyToLayout: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
|
|
|
@ -4,11 +4,12 @@ import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
|
export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isDesktop} = useWebMediaQueries()
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="replyPromptBtn"
|
testID="replyPromptBtn"
|
||||||
|
@ -22,7 +23,7 @@ export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
|
||||||
type="xl"
|
type="xl"
|
||||||
style={[
|
style={[
|
||||||
pal.text,
|
pal.text,
|
||||||
isDesktopWeb ? styles.labelDesktopWeb : styles.labelMobile,
|
isDesktop ? styles.labelDesktopWeb : styles.labelMobile,
|
||||||
]}>
|
]}>
|
||||||
Write your reply
|
Write your reply
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -7,10 +7,10 @@ import {s, colors} from 'lib/styles'
|
||||||
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {openAltTextModal} from 'lib/media/alt-text'
|
import {openAltTextModal} from 'lib/media/alt-text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
gallery: GalleryModel
|
gallery: GalleryModel
|
||||||
|
@ -19,13 +19,14 @@ interface Props {
|
||||||
export const Gallery = observer(function ({gallery}: Props) {
|
export const Gallery = observer(function ({gallery}: Props) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
let side: number
|
let side: number
|
||||||
|
|
||||||
if (gallery.size === 1) {
|
if (gallery.size === 1) {
|
||||||
side = 250
|
side = 250
|
||||||
} else {
|
} else {
|
||||||
side = (isDesktopWeb ? 560 : 350) / gallery.size
|
side = (isMobile ? 350 : 560) / gallery.size
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageStyle = {
|
const imageStyle = {
|
||||||
|
@ -33,14 +34,14 @@ export const Gallery = observer(function ({gallery}: Props) {
|
||||||
width: side,
|
width: side,
|
||||||
}
|
}
|
||||||
|
|
||||||
const isOverflow = !isDesktopWeb && gallery.size > 2
|
const isOverflow = isMobile && gallery.size > 2
|
||||||
|
|
||||||
const altTextControlStyle = isOverflow
|
const altTextControlStyle = isOverflow
|
||||||
? {
|
? {
|
||||||
left: 4,
|
left: 4,
|
||||||
bottom: 4,
|
bottom: 4,
|
||||||
}
|
}
|
||||||
: isDesktopWeb && gallery.size < 3
|
: !isMobile && gallery.size < 3
|
||||||
? {
|
? {
|
||||||
left: 8,
|
left: 8,
|
||||||
top: 8,
|
top: 8,
|
||||||
|
@ -60,7 +61,7 @@ export const Gallery = observer(function ({gallery}: Props) {
|
||||||
right: 4,
|
right: 4,
|
||||||
gap: 4,
|
gap: 4,
|
||||||
}
|
}
|
||||||
: isDesktopWeb && gallery.size < 3
|
: !isMobile && gallery.size < 3
|
||||||
? {
|
? {
|
||||||
top: 8,
|
top: 8,
|
||||||
right: 8,
|
right: 8,
|
||||||
|
|
|
@ -22,9 +22,9 @@ import {TextLink} from '../util/Link'
|
||||||
import {ListModel} from 'state/models/content/list'
|
import {ListModel} from 'state/models/content/list'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {ListActions} from './ListActions'
|
import {ListActions} from './ListActions'
|
||||||
import {makeProfileLink} from 'lib/routes/links'
|
import {makeProfileLink} from 'lib/routes/links'
|
||||||
import {sanitizeHandle} from 'lib/strings/handles'
|
import {sanitizeHandle} from 'lib/strings/handles'
|
||||||
|
@ -283,6 +283,7 @@ const ListHeader = observer(
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isDesktop} = useWebMediaQueries()
|
||||||
const descriptionRT = React.useMemo(
|
const descriptionRT = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
list?.description &&
|
list?.description &&
|
||||||
|
@ -318,7 +319,7 @@ const ListHeader = observer(
|
||||||
richText={descriptionRT}
|
richText={descriptionRT}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isDesktopWeb && (
|
{isDesktop && (
|
||||||
<ListActions
|
<ListActions
|
||||||
isOwner={isOwner}
|
isOwner={isOwner}
|
||||||
muted={list.viewer?.muted}
|
muted={list.viewer?.muted}
|
||||||
|
@ -334,7 +335,8 @@ const ListHeader = observer(
|
||||||
<UserAvatar type="list" avatar={list.avatar} size={64} />
|
<UserAvatar type="list" avatar={list.avatar} size={64} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.fakeSelector, pal.border]}>
|
<View
|
||||||
|
style={{flexDirection: 'row', paddingHorizontal: isDesktop ? 16 : 6}}>
|
||||||
<View
|
<View
|
||||||
style={[styles.fakeSelectorItem, {borderColor: pal.colors.link}]}>
|
style={[styles.fakeSelectorItem, {borderColor: pal.colors.link}]}>
|
||||||
<Text type="md-medium" style={[pal.text]}>
|
<Text type="md-medium" style={[pal.text]}>
|
||||||
|
@ -365,10 +367,6 @@ const styles = StyleSheet.create({
|
||||||
gap: 8,
|
gap: 8,
|
||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
},
|
},
|
||||||
fakeSelector: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
paddingHorizontal: isDesktopWeb ? 16 : 6,
|
|
||||||
},
|
|
||||||
fakeSelectorItem: {
|
fakeSelectorItem: {
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
paddingBottom: 8,
|
paddingBottom: 8,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {Button} from '../util/forms/Button'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isNative} from 'platform/detection'
|
||||||
import {
|
import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
|
@ -205,7 +205,7 @@ export function Component({}: {}) {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 50,
|
paddingBottom: isNative ? 50 : 0,
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
},
|
},
|
||||||
textInputWrapper: {
|
textInputWrapper: {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {useTheme} from 'lib/ThemeContext'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import LinearGradient from 'react-native-linear-gradient'
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isDesktopWeb, isAndroid} from 'platform/detection'
|
import {isAndroid, isWeb} from 'platform/detection'
|
||||||
import {ImageModel} from 'state/models/media/image'
|
import {ImageModel} from 'state/models/media/image'
|
||||||
|
|
||||||
export const snapPoints = ['fullscreen']
|
export const snapPoints = ['fullscreen']
|
||||||
|
@ -35,7 +35,7 @@ export function Component({image}: Props) {
|
||||||
const windim = useWindowDimensions()
|
const windim = useWindowDimensions()
|
||||||
|
|
||||||
const imageStyles = useMemo<ImageStyle>(() => {
|
const imageStyles = useMemo<ImageStyle>(() => {
|
||||||
const maxWidth = isDesktopWeb ? 450 : windim.width
|
const maxWidth = isWeb ? 450 : windim.width
|
||||||
if (image.height > image.width) {
|
if (image.height > image.width) {
|
||||||
return {
|
return {
|
||||||
resizeMode: 'contain',
|
resizeMode: 'contain',
|
||||||
|
@ -137,12 +137,12 @@ const styles = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
paddingVertical: isDesktopWeb ? 0 : 18,
|
paddingVertical: isWeb ? 0 : 18,
|
||||||
},
|
},
|
||||||
scrollContainer: {
|
scrollContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
paddingHorizontal: isDesktopWeb ? 0 : 12,
|
paddingHorizontal: isWeb ? 0 : 12,
|
||||||
},
|
},
|
||||||
scrollInner: {
|
scrollInner: {
|
||||||
gap: 12,
|
gap: 12,
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {s, colors} from 'lib/styles'
|
||||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||||
import {cleanError} from 'lib/strings/errors'
|
import {cleanError} from 'lib/strings/errors'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
import type {ConfirmModal} from 'state/models/ui/shell'
|
import type {ConfirmModal} from 'state/models/ui/shell'
|
||||||
|
|
||||||
export const snapPoints = ['50%']
|
export const snapPoints = ['50%']
|
||||||
|
@ -96,7 +96,7 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
padding: 10,
|
padding: 10,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 60,
|
paddingBottom: isWeb ? 0 : 60,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -11,13 +11,15 @@ import {TextLink} from '../util/Link'
|
||||||
import {ToggleButton} from '../util/forms/ToggleButton'
|
import {ToggleButton} from '../util/forms/ToggleButton'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {CONFIGURABLE_LABEL_GROUPS} from 'lib/labeling/const'
|
import {CONFIGURABLE_LABEL_GROUPS} from 'lib/labeling/const'
|
||||||
import {isDesktopWeb, isIOS} from 'platform/detection'
|
import {isIOS} from 'platform/detection'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import * as Toast from '../util/Toast'
|
import * as Toast from '../util/Toast'
|
||||||
|
|
||||||
export const snapPoints = ['90%']
|
export const snapPoints = ['90%']
|
||||||
|
|
||||||
export const Component = observer(({}: {}) => {
|
export const Component = observer(({}: {}) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -88,9 +90,14 @@ export const Component = observer(({}: {}) => {
|
||||||
<ContentLabelPref group="hate" />
|
<ContentLabelPref group="hate" />
|
||||||
<ContentLabelPref group="spam" />
|
<ContentLabelPref group="spam" />
|
||||||
<ContentLabelPref group="impersonation" />
|
<ContentLabelPref group="impersonation" />
|
||||||
<View style={styles.bottomSpacer} />
|
<View style={{height: isMobile ? 60 : 0}} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<View style={[styles.btnContainer, pal.borderDark]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.btnContainer,
|
||||||
|
isMobile && styles.btnContainerMobile,
|
||||||
|
pal.borderDark,
|
||||||
|
]}>
|
||||||
<Pressable
|
<Pressable
|
||||||
testID="sendReportBtn"
|
testID="sendReportBtn"
|
||||||
onPress={onPressDone}
|
onPress={onPressDone}
|
||||||
|
@ -259,14 +266,13 @@ const styles = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
},
|
},
|
||||||
bottomSpacer: {
|
|
||||||
height: isDesktopWeb ? 0 : 60,
|
|
||||||
},
|
|
||||||
btnContainer: {
|
btnContainer: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 40,
|
},
|
||||||
borderTopWidth: isDesktopWeb ? 0 : 1,
|
btnContainerMobile: {
|
||||||
|
paddingBottom: 40,
|
||||||
|
borderTopWidth: 1,
|
||||||
},
|
},
|
||||||
|
|
||||||
contentLabelPref: {
|
contentLabelPref: {
|
||||||
|
|
|
@ -22,8 +22,8 @@ import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
const MAX_NAME = 64 // todo
|
const MAX_NAME = 64 // todo
|
||||||
const MAX_DESCRIPTION = 300 // todo
|
const MAX_DESCRIPTION = 300 // todo
|
||||||
|
@ -38,6 +38,7 @@ export function Component({
|
||||||
list?: ListModel
|
list?: ListModel
|
||||||
}) {
|
}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [error, setError] = useState<string>('')
|
const [error, setError] = useState<string>('')
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
@ -130,7 +131,12 @@ export function Component({
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView behavior="height">
|
<KeyboardAvoidingView behavior="height">
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={[pal.view, styles.container]}
|
style={[
|
||||||
|
pal.view,
|
||||||
|
{
|
||||||
|
paddingHorizontal: isMobile ? 16 : 0,
|
||||||
|
},
|
||||||
|
]}
|
||||||
testID="createOrEditMuteListModal">
|
testID="createOrEditMuteListModal">
|
||||||
<Text style={[styles.title, pal.text]}>
|
<Text style={[styles.title, pal.text]}>
|
||||||
{list ? 'Edit Mute List' : 'New Mute List'}
|
{list ? 'Edit Mute List' : 'New Mute List'}
|
||||||
|
@ -226,9 +232,6 @@ export function Component({
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
|
||||||
paddingHorizontal: isDesktopWeb ? 0 : 16,
|
|
||||||
},
|
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
|
|
|
@ -13,10 +13,10 @@ import {useStores} from 'state/index'
|
||||||
import {s, colors, gradients} from 'lib/styles'
|
import {s, colors, gradients} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||||
import {cleanError} from 'lib/strings/errors'
|
import {cleanError} from 'lib/strings/errors'
|
||||||
import {resetToTab} from '../../../Navigation'
|
import {resetToTab} from '../../../Navigation'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
export const snapPoints = ['60%']
|
export const snapPoints = ['60%']
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export function Component({}: {}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false)
|
const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false)
|
||||||
const [confirmCode, setConfirmCode] = React.useState<string>('')
|
const [confirmCode, setConfirmCode] = React.useState<string>('')
|
||||||
const [password, setPassword] = React.useState<string>('')
|
const [password, setPassword] = React.useState<string>('')
|
||||||
|
@ -78,7 +79,7 @@ export function Component({}: {}) {
|
||||||
type="title-xl"
|
type="title-xl"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={[
|
style={[
|
||||||
isDesktopWeb ? styles.titleDesktop : styles.titleMobile,
|
isMobile ? styles.titleMobile : styles.titleDesktop,
|
||||||
pal.text,
|
pal.text,
|
||||||
s.bold,
|
s.bold,
|
||||||
]}>
|
]}>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {useTheme} from 'lib/ThemeContext'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import LinearGradient from 'react-native-linear-gradient'
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import ImageEditor, {Position} from 'react-avatar-editor'
|
import ImageEditor, {Position} from 'react-avatar-editor'
|
||||||
import {TextInput} from './util'
|
import {TextInput} from './util'
|
||||||
import {enforceLen} from 'lib/strings/helpers'
|
import {enforceLen} from 'lib/strings/helpers'
|
||||||
|
@ -18,7 +19,6 @@ import {Slider} from '@miblanchard/react-native-slider'
|
||||||
import {MaterialIcons} from '@expo/vector-icons'
|
import {MaterialIcons} from '@expo/vector-icons'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {getKeys} from 'lib/type-assertions'
|
import {getKeys} from 'lib/type-assertions'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
export const snapPoints = ['80%']
|
export const snapPoints = ['80%']
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ export const Component = observer(function ({image, gallery}: Props) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const windowDimensions = useWindowDimensions()
|
const windowDimensions = useWindowDimensions()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
aspectRatio,
|
aspectRatio,
|
||||||
|
@ -174,19 +175,28 @@ export const Component = observer(function ({image, gallery}: Props) {
|
||||||
|
|
||||||
const computedWidth =
|
const computedWidth =
|
||||||
windowDimensions.width > 500 ? 410 : windowDimensions.width - 80
|
windowDimensions.width > 500 ? 410 : windowDimensions.width - 80
|
||||||
const sideLength = isDesktopWeb ? 300 : computedWidth
|
const sideLength = isMobile ? computedWidth : 300
|
||||||
|
|
||||||
const dimensions = image.getResizedDimensions(aspectRatio, sideLength)
|
const dimensions = image.getResizedDimensions(aspectRatio, sideLength)
|
||||||
const imgContainerStyles = {width: sideLength, height: sideLength}
|
const imgContainerStyles = {width: sideLength, height: sideLength}
|
||||||
|
|
||||||
const imgControlStyles = {
|
const imgControlStyles = {
|
||||||
alignItems: 'center' as const,
|
alignItems: 'center' as const,
|
||||||
flexDirection: isDesktopWeb ? ('row' as const) : ('column' as const),
|
flexDirection: isMobile ? ('column' as const) : ('row' as const),
|
||||||
gap: isDesktopWeb ? 5 : 0,
|
gap: isMobile ? 0 : 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID="editImageModal" style={[pal.view, styles.container, s.flex1]}>
|
<View
|
||||||
|
testID="editImageModal"
|
||||||
|
style={[
|
||||||
|
pal.view,
|
||||||
|
styles.container,
|
||||||
|
s.flex1,
|
||||||
|
{
|
||||||
|
paddingHorizontal: isMobile ? 16 : undefined,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
<Text style={[styles.title, pal.text]}>Edit image</Text>
|
<Text style={[styles.title, pal.text]}>Edit image</Text>
|
||||||
<View style={[styles.gap18, s.flexRow]}>
|
<View style={[styles.gap18, s.flexRow]}>
|
||||||
<View>
|
<View>
|
||||||
|
@ -213,7 +223,7 @@ export const Component = observer(function ({image, gallery}: Props) {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
{isDesktopWeb ? (
|
{!isMobile ? (
|
||||||
<Text type="sm-bold" style={pal.text}>
|
<Text type="sm-bold" style={pal.text}>
|
||||||
Ratios
|
Ratios
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -248,7 +258,7 @@ export const Component = observer(function ({image, gallery}: Props) {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</View>
|
</View>
|
||||||
{isDesktopWeb ? (
|
{!isMobile ? (
|
||||||
<Text type="sm-bold" style={[pal.text, styles.subsection]}>
|
<Text type="sm-bold" style={[pal.text, styles.subsection]}>
|
||||||
Transformations
|
Transformations
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -282,7 +292,14 @@ export const Component = observer(function ({image, gallery}: Props) {
|
||||||
</Text>
|
</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
testID="altTextImageInput"
|
testID="altTextImageInput"
|
||||||
style={[styles.textArea, pal.border, pal.text]}
|
style={[
|
||||||
|
styles.textArea,
|
||||||
|
pal.border,
|
||||||
|
pal.text,
|
||||||
|
{
|
||||||
|
maxHeight: isMobile ? 50 : undefined,
|
||||||
|
},
|
||||||
|
]}
|
||||||
keyboardAppearance={theme.colorScheme}
|
keyboardAppearance={theme.colorScheme}
|
||||||
multiline
|
multiline
|
||||||
value={altText}
|
value={altText}
|
||||||
|
@ -317,7 +334,6 @@ export const Component = observer(function ({image, gallery}: Props) {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
gap: 18,
|
gap: 18,
|
||||||
paddingHorizontal: isDesktopWeb ? undefined : 16,
|
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
|
@ -369,7 +385,6 @@ const styles = StyleSheet.create({
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
height: 100,
|
height: 100,
|
||||||
textAlignVertical: 'top',
|
textAlignVertical: 'top',
|
||||||
maxHeight: isDesktopWeb ? undefined : 50,
|
|
||||||
},
|
},
|
||||||
bottomSection: {
|
bottomSection: {
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as Toast from '../util/Toast'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {ScrollView} from './util'
|
import {ScrollView} from './util'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
|
|
||||||
export const snapPoints = ['70%']
|
export const snapPoints = ['70%']
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ const InviteCode = observer(
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 50,
|
paddingBottom: isWeb ? 0 : 50,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
import {sanitizeHandle} from 'lib/strings/handles'
|
import {sanitizeHandle} from 'lib/strings/handles'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb, isAndroid} from 'platform/detection'
|
import {isWeb, isAndroid} from 'platform/detection'
|
||||||
import isEqual from 'lodash.isequal'
|
import isEqual from 'lodash.isequal'
|
||||||
|
|
||||||
export const snapPoints = ['fullscreen']
|
export const snapPoints = ['fullscreen']
|
||||||
|
@ -231,7 +231,7 @@ export const Component = observer(
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
paddingHorizontal: isDesktopWeb ? 0 : 16,
|
paddingHorizontal: isWeb ? 0 : 16,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {TouchableWithoutFeedback, StyleSheet, View} from 'react-native'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import type {Modal as ModalIface} from 'state/models/ui/shell'
|
import type {Modal as ModalIface} from 'state/models/ui/shell'
|
||||||
import {isMobileWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
import * as ConfirmModal from './Confirm'
|
import * as ConfirmModal from './Confirm'
|
||||||
import * as EditProfileModal from './EditProfile'
|
import * as EditProfileModal from './EditProfile'
|
||||||
|
@ -47,6 +47,7 @@ export const ModalsContainer = observer(function ModalsContainer() {
|
||||||
function Modal({modal}: {modal: ModalIface}) {
|
function Modal({modal}: {modal: ModalIface}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
if (!store.shell.isModalActive) {
|
if (!store.shell.isModalActive) {
|
||||||
return null
|
return null
|
||||||
|
@ -119,7 +120,7 @@ function Modal({modal}: {modal: ModalIface}) {
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
isMobileWeb && styles.containerMobile,
|
isMobile && styles.containerMobile,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
]}>
|
]}>
|
||||||
|
|
|
@ -2,11 +2,12 @@ import React from 'react'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {StyleSheet, View} from 'react-native'
|
||||||
import {ModerationUI} from '@atproto/api'
|
import {ModerationUI} from '@atproto/api'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import {TextLink} from '../util/Link'
|
import {TextLink} from '../util/Link'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
import {listUriToHref} from 'lib/strings/url-helpers'
|
import {listUriToHref} from 'lib/strings/url-helpers'
|
||||||
import {Button} from '../util/forms/Button'
|
import {Button} from '../util/forms/Button'
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ export function Component({
|
||||||
moderation: ModerationUI
|
moderation: ModerationUI
|
||||||
}) {
|
}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
|
||||||
let name
|
let name
|
||||||
|
@ -64,7 +66,15 @@ export function Component({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID="moderationDetailsModal" style={[styles.container, pal.view]}>
|
<View
|
||||||
|
testID="moderationDetailsModal"
|
||||||
|
style={[
|
||||||
|
styles.container,
|
||||||
|
{
|
||||||
|
paddingHorizontal: isMobile ? 14 : 0,
|
||||||
|
},
|
||||||
|
pal.view,
|
||||||
|
]}>
|
||||||
<Text type="title-xl" style={[pal.text, styles.title]}>
|
<Text type="title-xl" style={[pal.text, styles.title]}>
|
||||||
{name}
|
{name}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -87,7 +97,6 @@ export function Component({
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingHorizontal: isDesktopWeb ? 0 : 14,
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
@ -99,7 +108,7 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
btn: {
|
btn: {
|
||||||
paddingVertical: 14,
|
paddingVertical: 14,
|
||||||
marginTop: isDesktopWeb ? 40 : 0,
|
marginTop: isWeb ? 40 : 0,
|
||||||
marginBottom: isDesktopWeb ? 0 : 40,
|
marginBottom: isWeb ? 0 : 40,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {Text} from '../util/text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
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 {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
import {Button} from '../util/forms/Button'
|
import {Button} from '../util/forms/Button'
|
||||||
import {SelectableBtn} from '../util/forms/SelectableBtn'
|
import {SelectableBtn} from '../util/forms/SelectableBtn'
|
||||||
import {ScrollView} from 'view/com/modals/util'
|
import {ScrollView} from 'view/com/modals/util'
|
||||||
|
@ -25,6 +26,7 @@ export const Component = observer(function Component({
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [selected, setSelected] = useState(labels)
|
const [selected, setSelected] = useState(labels)
|
||||||
|
|
||||||
const toggleAdultLabel = (label: string) => {
|
const toggleAdultLabel = (label: string) => {
|
||||||
|
@ -54,7 +56,12 @@ export const Component = observer(function Component({
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={[styles.section, pal.border, {borderBottomWidth: 1}]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.section,
|
||||||
|
pal.border,
|
||||||
|
{borderBottomWidth: 1, paddingHorizontal: isMobile ? 20 : 0},
|
||||||
|
]}>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
@ -152,11 +159,11 @@ export const Component = observer(function Component({
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 40,
|
paddingBottom: isWeb ? 0 : 40,
|
||||||
},
|
},
|
||||||
titleSection: {
|
titleSection: {
|
||||||
paddingTop: isDesktopWeb ? 0 : 4,
|
paddingTop: isWeb ? 0 : 4,
|
||||||
paddingBottom: isDesktopWeb ? 14 : 10,
|
paddingBottom: isWeb ? 14 : 10,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
@ -170,7 +177,6 @@ const styles = StyleSheet.create({
|
||||||
section: {
|
section: {
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
paddingVertical: 20,
|
paddingVertical: 20,
|
||||||
paddingHorizontal: isDesktopWeb ? 0 : 20,
|
|
||||||
},
|
},
|
||||||
adultExplainer: {
|
adultExplainer: {
|
||||||
paddingLeft: 5,
|
paddingLeft: 5,
|
||||||
|
|
|
@ -2,8 +2,8 @@ import React from 'react'
|
||||||
import {StyleSheet, Text, View, Pressable} from 'react-native'
|
import {StyleSheet, Text, View, Pressable} from 'react-native'
|
||||||
import LinearGradient from 'react-native-linear-gradient'
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {s, colors, gradients} from 'lib/styles'
|
import {s, colors, gradients} from 'lib/styles'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
export const ConfirmLanguagesButton = ({
|
export const ConfirmLanguagesButton = ({
|
||||||
onPress,
|
onPress,
|
||||||
|
@ -13,8 +13,17 @@ export const ConfirmLanguagesButton = ({
|
||||||
extraText?: string
|
extraText?: string
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
return (
|
return (
|
||||||
<View style={[styles.btnContainer, pal.borderDark]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.btnContainer,
|
||||||
|
pal.borderDark,
|
||||||
|
isMobile && {
|
||||||
|
paddingBottom: 40,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
<Pressable
|
<Pressable
|
||||||
testID="confirmContentLanguagesBtn"
|
testID="confirmContentLanguagesBtn"
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
|
@ -37,8 +46,6 @@ const styles = StyleSheet.create({
|
||||||
btnContainer: {
|
btnContainer: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 40,
|
|
||||||
borderTopWidth: isDesktopWeb ? 0 : 1,
|
|
||||||
},
|
},
|
||||||
btn: {
|
btn: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
|
@ -4,7 +4,8 @@ import {ScrollView} from '../util'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb, deviceLocales} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
import {deviceLocales} from 'platform/detection'
|
||||||
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
||||||
import {LanguageToggle} from './LanguageToggle'
|
import {LanguageToggle} from './LanguageToggle'
|
||||||
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||||
|
@ -14,6 +15,7 @@ export const snapPoints = ['100%']
|
||||||
export function Component({}: {}) {
|
export function Component({}: {}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const onPressDone = React.useCallback(() => {
|
const onPressDone = React.useCallback(() => {
|
||||||
store.shell.closeModal()
|
store.shell.closeModal()
|
||||||
}, [store])
|
}, [store])
|
||||||
|
@ -47,7 +49,19 @@ export function Component({}: {}) {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID="contentLanguagesModal" style={[pal.view, styles.container]}>
|
<View
|
||||||
|
testID="contentLanguagesModal"
|
||||||
|
style={[
|
||||||
|
pal.view,
|
||||||
|
styles.container,
|
||||||
|
isMobile
|
||||||
|
? {
|
||||||
|
paddingTop: 20,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
maxHeight: '90vh',
|
||||||
|
},
|
||||||
|
]}>
|
||||||
<Text style={[pal.text, styles.title]}>Content Languages</Text>
|
<Text style={[pal.text, styles.title]}>Content Languages</Text>
|
||||||
<Text style={[pal.text, styles.description]}>
|
<Text style={[pal.text, styles.description]}>
|
||||||
Which languages would you like to see in your algorithmic feeds?
|
Which languages would you like to see in your algorithmic feeds?
|
||||||
|
@ -67,7 +81,11 @@ export function Component({}: {}) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<View style={styles.bottomSpacer} />
|
<View
|
||||||
|
style={{
|
||||||
|
height: isMobile ? 60 : 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<ConfirmLanguagesButton onPress={onPressDone} />
|
<ConfirmLanguagesButton onPress={onPressDone} />
|
||||||
</View>
|
</View>
|
||||||
|
@ -77,7 +95,6 @@ export function Component({}: {}) {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: 20,
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
@ -94,7 +111,4 @@ const styles = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
},
|
},
|
||||||
bottomSpacer: {
|
|
||||||
height: isDesktopWeb ? 0 : 60,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {ScrollView} from '../util'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb, deviceLocales} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
import {deviceLocales} from 'platform/detection'
|
||||||
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
||||||
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||||
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||||
|
@ -15,6 +16,7 @@ export const snapPoints = ['100%']
|
||||||
export const Component = observer(() => {
|
export const Component = observer(() => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const onPressDone = React.useCallback(() => {
|
const onPressDone = React.useCallback(() => {
|
||||||
store.shell.closeModal()
|
store.shell.closeModal()
|
||||||
}, [store])
|
}, [store])
|
||||||
|
@ -48,7 +50,19 @@ export const Component = observer(() => {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID="postLanguagesModal" style={[pal.view, styles.container]}>
|
<View
|
||||||
|
testID="postLanguagesModal"
|
||||||
|
style={[
|
||||||
|
pal.view,
|
||||||
|
styles.container,
|
||||||
|
isMobile
|
||||||
|
? {
|
||||||
|
paddingTop: 20,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
maxHeight: '90vh',
|
||||||
|
},
|
||||||
|
]}>
|
||||||
<Text style={[pal.text, styles.title]}>Post Languages</Text>
|
<Text style={[pal.text, styles.title]}>Post Languages</Text>
|
||||||
<Text style={[pal.text, styles.description]}>
|
<Text style={[pal.text, styles.description]}>
|
||||||
Which languages are used in this post?
|
Which languages are used in this post?
|
||||||
|
@ -80,7 +94,11 @@ export const Component = observer(() => {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<View style={styles.bottomSpacer} />
|
<View
|
||||||
|
style={{
|
||||||
|
height: isMobile ? 60 : 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<ConfirmLanguagesButton onPress={onPressDone} />
|
<ConfirmLanguagesButton onPress={onPressDone} />
|
||||||
</View>
|
</View>
|
||||||
|
@ -90,7 +108,6 @@ export const Component = observer(() => {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: 20,
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
@ -107,9 +124,6 @@ const styles = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
},
|
},
|
||||||
bottomSpacer: {
|
|
||||||
height: isDesktopWeb ? 0 : 60,
|
|
||||||
},
|
|
||||||
languageToggle: {
|
languageToggle: {
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
|
|
|
@ -5,9 +5,9 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {CharProgress} from '../../composer/char-progress/CharProgress'
|
import {CharProgress} from '../../composer/char-progress/CharProgress'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {SendReportButton} from './SendReportButton'
|
import {SendReportButton} from './SendReportButton'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
export function InputIssueDetails({
|
export function InputIssueDetails({
|
||||||
details,
|
details,
|
||||||
|
@ -23,9 +23,13 @@ export function InputIssueDetails({
|
||||||
isProcessing: boolean
|
isProcessing: boolean
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.detailsContainer]}>
|
<View
|
||||||
|
style={{
|
||||||
|
marginTop: isMobile ? 12 : 0,
|
||||||
|
}}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="addDetailsBtn"
|
testID="addDetailsBtn"
|
||||||
style={[s.mb10, styles.backBtn]}
|
style={[s.mb10, styles.backBtn]}
|
||||||
|
@ -63,9 +67,6 @@ export function InputIssueDetails({
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
detailsContainer: {
|
|
||||||
marginTop: isDesktopWeb ? 0 : 12,
|
|
||||||
},
|
|
||||||
backBtn: {
|
backBtn: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {Linking, StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||||
import {ScrollView} from 'react-native-gesture-handler'
|
import {ScrollView} from 'react-native-gesture-handler'
|
||||||
import {AtUri} from '@atproto/api'
|
import {AtUri} from '@atproto/api'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import * as Toast from '../../util/Toast'
|
import * as Toast from '../../util/Toast'
|
||||||
|
@ -37,6 +38,7 @@ type ReportComponentProps =
|
||||||
export function Component(content: ReportComponentProps) {
|
export function Component(content: ReportComponentProps) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [isProcessing, setIsProcessing] = useState(false)
|
const [isProcessing, setIsProcessing] = useState(false)
|
||||||
const [showDetailsInput, setShowDetailsInput] = useState(false)
|
const [showDetailsInput, setShowDetailsInput] = useState(false)
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
|
@ -87,7 +89,13 @@ export function Component(content: ReportComponentProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView testID="reportModal" style={[s.flex1, pal.view]}>
|
<ScrollView testID="reportModal" style={[s.flex1, pal.view]}>
|
||||||
<View style={styles.container}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.container,
|
||||||
|
isMobile && {
|
||||||
|
paddingBottom: 40,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
{showDetailsInput ? (
|
{showDetailsInput ? (
|
||||||
<InputIssueDetails
|
<InputIssueDetails
|
||||||
details={details}
|
details={details}
|
||||||
|
@ -153,16 +161,14 @@ const SelectIssue = ({
|
||||||
<Text style={[pal.textLight, styles.description]}>
|
<Text style={[pal.textLight, styles.description]}>
|
||||||
What is the issue with this {collectionName}?
|
What is the issue with this {collectionName}?
|
||||||
</Text>
|
</Text>
|
||||||
|
<View style={{marginBottom: 10}}>
|
||||||
<ReportReasonOptions
|
<ReportReasonOptions
|
||||||
atUri={atUri}
|
atUri={atUri}
|
||||||
selectedIssue={issue}
|
selectedIssue={issue}
|
||||||
onSelectIssue={onSelectIssue}
|
onSelectIssue={onSelectIssue}
|
||||||
/>
|
/>
|
||||||
{error ? (
|
|
||||||
<View style={s.mt10}>
|
|
||||||
<ErrorMessage message={error} />
|
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
{error ? <ErrorMessage message={error} /> : undefined}
|
||||||
{/* If no atUri is present, the report would be for account in which case, we allow sending without specifying a reason */}
|
{/* If no atUri is present, the report would be for account in which case, we allow sending without specifying a reason */}
|
||||||
{issue || !atUri ? (
|
{issue || !atUri ? (
|
||||||
<>
|
<>
|
||||||
|
@ -188,7 +194,6 @@ const SelectIssue = ({
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
paddingBottom: 40,
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -13,8 +13,8 @@ export const FeedsTabBar = observer(
|
||||||
(
|
(
|
||||||
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
||||||
) => {
|
) => {
|
||||||
const {isDesktop} = useWebMediaQueries()
|
const {isMobile} = useWebMediaQueries()
|
||||||
if (!isDesktop) {
|
if (isMobile) {
|
||||||
return <FeedsTabBarMobile {...props} />
|
return <FeedsTabBarMobile {...props} />
|
||||||
} else {
|
} else {
|
||||||
return <FeedsTabBarDesktop {...props} />
|
return <FeedsTabBarDesktop {...props} />
|
||||||
|
|
|
@ -3,7 +3,8 @@ import {StyleSheet, View, ScrollView, LayoutChangeEvent} from 'react-native'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import {PressableWithHover} from '../util/PressableWithHover'
|
import {PressableWithHover} from '../util/PressableWithHover'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb, isMobileWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
import {DraggableScrollView} from './DraggableScrollView'
|
import {DraggableScrollView} from './DraggableScrollView'
|
||||||
|
|
||||||
export interface TabBarProps {
|
export interface TabBarProps {
|
||||||
|
@ -30,6 +31,7 @@ export function TabBar({
|
||||||
() => ({borderBottomColor: indicatorColor || pal.colors.link}),
|
() => ({borderBottomColor: indicatorColor || pal.colors.link}),
|
||||||
[indicatorColor, pal],
|
[indicatorColor, pal],
|
||||||
)
|
)
|
||||||
|
const {isDesktop, isTablet} = useWebMediaQueries()
|
||||||
|
|
||||||
// scrolls to the selected item when the page changes
|
// scrolls to the selected item when the page changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -61,6 +63,7 @@ export function TabBar({
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const styles = isDesktop || isTablet ? desktopStyles : mobileStyles
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={[pal.view, styles.outer]}>
|
<View testID={testID} style={[pal.view, styles.outer]}>
|
||||||
<DraggableScrollView
|
<DraggableScrollView
|
||||||
|
@ -78,7 +81,7 @@ export function TabBar({
|
||||||
hoverStyle={pal.viewLight}
|
hoverStyle={pal.viewLight}
|
||||||
onPress={() => onPressItem(i)}>
|
onPress={() => onPressItem(i)}>
|
||||||
<Text
|
<Text
|
||||||
type={isDesktopWeb ? 'xl-bold' : 'lg-bold'}
|
type={isDesktop || isTablet ? 'xl-bold' : 'lg-bold'}
|
||||||
testID={testID ? `${testID}-${item}` : undefined}
|
testID={testID ? `${testID}-${item}` : undefined}
|
||||||
style={selected ? pal.text : pal.textLight}>
|
style={selected ? pal.text : pal.textLight}>
|
||||||
{item}
|
{item}
|
||||||
|
@ -91,8 +94,7 @@ export function TabBar({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = isDesktopWeb
|
const desktopStyles = StyleSheet.create({
|
||||||
? StyleSheet.create({
|
|
||||||
outer: {
|
outer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
width: 598,
|
width: 598,
|
||||||
|
@ -111,8 +113,9 @@ const styles = isDesktopWeb
|
||||||
borderBottomColor: 'transparent',
|
borderBottomColor: 'transparent',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
: StyleSheet.create({
|
|
||||||
|
const mobileStyles = StyleSheet.create({
|
||||||
outer: {
|
outer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
@ -120,17 +123,17 @@ const styles = isDesktopWeb
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
},
|
},
|
||||||
contentContainer: {
|
contentContainer: {
|
||||||
columnGap: isMobileWeb ? 0 : 20,
|
columnGap: isWeb ? 0 : 20,
|
||||||
marginLeft: isMobileWeb ? 0 : 18,
|
marginLeft: isWeb ? 0 : 18,
|
||||||
paddingRight: isMobileWeb ? 0 : 36,
|
paddingRight: isWeb ? 0 : 36,
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
paddingBottom: 10,
|
paddingBottom: 10,
|
||||||
paddingHorizontal: isMobileWeb ? 8 : 0,
|
paddingHorizontal: isWeb ? 8 : 0,
|
||||||
borderBottomWidth: 3,
|
borderBottomWidth: 3,
|
||||||
borderBottomColor: 'transparent',
|
borderBottomColor: 'transparent',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,18 +18,24 @@ import {
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {PostThreadItem} from './PostThreadItem'
|
import {PostThreadItem} from './PostThreadItem'
|
||||||
import {ComposePrompt} from '../composer/Prompt'
|
import {ComposePrompt} from '../composer/Prompt'
|
||||||
|
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 {isIOS, isDesktopWeb, isMobileWeb} from 'platform/detection'
|
import {isIOS, isDesktopWeb} 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'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
|
|
||||||
const MAINTAIN_VISIBLE_CONTENT_POSITION = {minIndexForVisible: 0}
|
const MAINTAIN_VISIBLE_CONTENT_POSITION = {minIndexForVisible: 0}
|
||||||
|
|
||||||
|
const TOP_COMPONENT = {
|
||||||
|
_reactKey: '__top_component__',
|
||||||
|
_isHighlightedPost: false,
|
||||||
|
}
|
||||||
const PARENT_SPINNER = {
|
const PARENT_SPINNER = {
|
||||||
_reactKey: '__parent_spinner__',
|
_reactKey: '__parent_spinner__',
|
||||||
_isHighlightedPost: false,
|
_isHighlightedPost: false,
|
||||||
|
@ -47,6 +53,7 @@ const BOTTOM_COMPONENT = {
|
||||||
}
|
}
|
||||||
type YieldedItem =
|
type YieldedItem =
|
||||||
| PostThreadItemModel
|
| PostThreadItemModel
|
||||||
|
| typeof TOP_COMPONENT
|
||||||
| typeof PARENT_SPINNER
|
| typeof PARENT_SPINNER
|
||||||
| typeof REPLY_PROMPT
|
| typeof REPLY_PROMPT
|
||||||
| typeof DELETED
|
| typeof DELETED
|
||||||
|
@ -63,13 +70,14 @@ export const PostThread = observer(function PostThread({
|
||||||
onPressReply: () => void
|
onPressReply: () => void
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isTablet} = 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)
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const posts = React.useMemo(() => {
|
const posts = React.useMemo(() => {
|
||||||
if (view.thread) {
|
if (view.thread) {
|
||||||
const arr = Array.from(flattenThread(view.thread))
|
const arr = [TOP_COMPONENT].concat(Array.from(flattenThread(view.thread)))
|
||||||
if (view.isLoadingFromCache) {
|
if (view.isLoadingFromCache) {
|
||||||
if (view.thread?.postRecord?.reply) {
|
if (view.thread?.postRecord?.reply) {
|
||||||
arr.unshift(PARENT_SPINNER)
|
arr.unshift(PARENT_SPINNER)
|
||||||
|
@ -158,7 +166,9 @@ export const PostThread = observer(function PostThread({
|
||||||
|
|
||||||
const renderItem = React.useCallback(
|
const renderItem = React.useCallback(
|
||||||
({item, index}: {item: YieldedItem; index: number}) => {
|
({item, index}: {item: YieldedItem; index: number}) => {
|
||||||
if (item === PARENT_SPINNER) {
|
if (item === TOP_COMPONENT) {
|
||||||
|
return isTablet ? <ViewHeader title="Post" /> : null
|
||||||
|
} else if (item === PARENT_SPINNER) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.parentSpinner}>
|
<View style={styles.parentSpinner}>
|
||||||
<ActivityIndicator />
|
<ActivityIndicator />
|
||||||
|
@ -186,19 +196,8 @@ export const PostThread = observer(function PostThread({
|
||||||
// HACK
|
// HACK
|
||||||
// due to some complexities with how flatlist works, this is the easiest way
|
// due to some complexities with how flatlist works, this is the easiest way
|
||||||
// I could find to get a border positioned directly under the last item
|
// I could find to get a border positioned directly under the last item
|
||||||
// -
|
|
||||||
// addendum -- it's also the best way to get mobile web to add padding
|
|
||||||
// at the bottom of the thread since paddingbottom is ignored. yikes.
|
|
||||||
// -prf
|
// -prf
|
||||||
return (
|
return <View style={[pal.border, styles.bottomSpacer]} />
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
styles.bottomBorder,
|
|
||||||
pal.border,
|
|
||||||
isMobileWeb && styles.bottomSpacer,
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
} else if (item === CHILD_SPINNER) {
|
} else if (item === CHILD_SPINNER) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.childSpinner}>
|
<View style={styles.childSpinner}>
|
||||||
|
@ -219,7 +218,7 @@ export const PostThread = observer(function PostThread({
|
||||||
}
|
}
|
||||||
return <></>
|
return <></>
|
||||||
},
|
},
|
||||||
[onRefresh, onPressReply, pal, posts],
|
[onRefresh, onPressReply, pal, posts, isTablet],
|
||||||
)
|
)
|
||||||
|
|
||||||
// loading
|
// loading
|
||||||
|
@ -331,7 +330,6 @@ export const PostThread = observer(function PostThread({
|
||||||
}
|
}
|
||||||
onScrollToIndexFailed={onScrollToIndexFailed}
|
onScrollToIndexFailed={onScrollToIndexFailed}
|
||||||
style={s.hContentRegion}
|
style={s.hContentRegion}
|
||||||
contentContainerStyle={styles.contentContainerExtra}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -384,13 +382,8 @@ const styles = StyleSheet.create({
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
},
|
},
|
||||||
childSpinner: {},
|
childSpinner: {},
|
||||||
bottomBorder: {
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
},
|
|
||||||
bottomSpacer: {
|
bottomSpacer: {
|
||||||
height: 400,
|
height: 400,
|
||||||
},
|
borderTopWidth: 1,
|
||||||
contentContainerExtra: {
|
|
||||||
paddingBottom: 500,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {s} from 'lib/styles'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {CogIcon} from 'lib/icons'
|
import {CogIcon} from 'lib/icons'
|
||||||
|
|
||||||
export const MultiFeed = observer(function Feed({
|
export const MultiFeed = observer(function Feed({
|
||||||
|
@ -48,6 +48,7 @@ export const MultiFeed = observer(function Feed({
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const [isRefreshing, setIsRefreshing] = React.useState(false)
|
const [isRefreshing, setIsRefreshing] = React.useState(false)
|
||||||
|
|
||||||
|
@ -80,8 +81,9 @@ export const MultiFeed = observer(function Feed({
|
||||||
const renderItem = React.useCallback(
|
const renderItem = React.useCallback(
|
||||||
({item}: {item: MultiFeedItem}) => {
|
({item}: {item: MultiFeedItem}) => {
|
||||||
if (item.type === 'header') {
|
if (item.type === 'header') {
|
||||||
if (isDesktopWeb) {
|
if (!isMobile) {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<View style={[pal.view, pal.border, styles.headerDesktop]}>
|
<View style={[pal.view, pal.border, styles.headerDesktop]}>
|
||||||
<Text type="2xl-bold" style={pal.text}>
|
<Text type="2xl-bold" style={pal.text}>
|
||||||
My Feeds
|
My Feeds
|
||||||
|
@ -90,9 +92,16 @@ export const MultiFeed = observer(function Feed({
|
||||||
<CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
|
<CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
|
||||||
</Link>
|
</Link>
|
||||||
</View>
|
</View>
|
||||||
|
<DiscoverLink />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return <View style={[styles.header, pal.border]} />
|
return (
|
||||||
|
<>
|
||||||
|
<View style={[styles.header, pal.border]} />
|
||||||
|
<DiscoverLink />
|
||||||
|
</>
|
||||||
|
)
|
||||||
} else if (item.type === 'feed-header') {
|
} else if (item.type === 'feed-header') {
|
||||||
return (
|
return (
|
||||||
<View style={styles.feedHeader}>
|
<View style={styles.feedHeader}>
|
||||||
|
@ -124,18 +133,11 @@ export const MultiFeed = observer(function Feed({
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
} else if (item.type === 'footer') {
|
} else if (item.type === 'footer') {
|
||||||
return (
|
return <DiscoverLink />
|
||||||
<Link style={[styles.footerLink, pal.viewLight]} href="/search/feeds">
|
|
||||||
<FontAwesomeIcon icon="search" size={18} color={pal.colors.text} />
|
|
||||||
<Text type="xl-medium" style={pal.text}>
|
|
||||||
Discover new feeds
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
[pal],
|
[pal, isMobile],
|
||||||
)
|
)
|
||||||
|
|
||||||
const ListFooter = React.useCallback(
|
const ListFooter = React.useCallback(
|
||||||
|
@ -150,17 +152,6 @@ export const MultiFeed = observer(function Feed({
|
||||||
[multifeed.isLoading, isRefreshing, pal],
|
[multifeed.isLoading, isRefreshing, pal],
|
||||||
)
|
)
|
||||||
|
|
||||||
const ListHeader = React.useCallback(() => {
|
|
||||||
return (
|
|
||||||
<Link style={[styles.footerLink, pal.viewLight]} href="/search/feeds">
|
|
||||||
<FontAwesomeIcon icon="search" size={18} color={pal.colors.text} />
|
|
||||||
<Text type="xl-medium" style={pal.text}>
|
|
||||||
Discover new feeds
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}, [pal])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={style}>
|
<View testID={testID} style={style}>
|
||||||
{multifeed.items.length > 0 && (
|
{multifeed.items.length > 0 && (
|
||||||
|
@ -171,7 +162,6 @@ export const MultiFeed = observer(function Feed({
|
||||||
keyExtractor={item => item._reactKey}
|
keyExtractor={item => item._reactKey}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
ListFooterComponent={ListFooter}
|
ListFooterComponent={ListFooter}
|
||||||
ListHeaderComponent={ListHeader}
|
|
||||||
refreshControl={
|
refreshControl={
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
refreshing={isRefreshing}
|
refreshing={isRefreshing}
|
||||||
|
@ -199,6 +189,18 @@ export const MultiFeed = observer(function Feed({
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function DiscoverLink() {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
return (
|
||||||
|
<Link style={[styles.discoverLink, pal.viewLight]} href="/search/feeds">
|
||||||
|
<FontAwesomeIcon icon="search" size={18} color={pal.colors.text} />
|
||||||
|
<Text type="xl-medium" style={pal.text}>
|
||||||
|
Discover new feeds
|
||||||
|
</Text>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
@ -237,7 +239,7 @@ const styles = StyleSheet.create({
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
},
|
},
|
||||||
footerLink: {
|
discoverLink: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
|
|
@ -27,8 +27,9 @@ import {UserBanner} from '../util/UserBanner'
|
||||||
import {ProfileHeaderAlerts} from '../util/moderation/ProfileHeaderAlerts'
|
import {ProfileHeaderAlerts} from '../util/moderation/ProfileHeaderAlerts'
|
||||||
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 {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {isDesktopWeb, isNative} from 'platform/detection'
|
import {isNative} from 'platform/detection'
|
||||||
import {FollowState} from 'state/models/cache/my-follows'
|
import {FollowState} from 'state/models/cache/my-follows'
|
||||||
import {shareUrl} from 'lib/sharing'
|
import {shareUrl} from 'lib/sharing'
|
||||||
import {formatCount} from '../util/numeric/format'
|
import {formatCount} from '../util/numeric/format'
|
||||||
|
@ -108,6 +109,7 @@ const ProfileHeaderLoaded = observer(
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const invalidHandle = isInvalidHandle(view.handle)
|
const invalidHandle = isInvalidHandle(view.handle)
|
||||||
|
const {isDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
const onPressBack = React.useCallback(() => {
|
const onPressBack = React.useCallback(() => {
|
||||||
navigation.goBack()
|
navigation.goBack()
|
||||||
|
@ -510,7 +512,7 @@ const ProfileHeaderLoaded = observer(
|
||||||
)}
|
)}
|
||||||
<ProfileHeaderAlerts moderation={view.moderation} />
|
<ProfileHeaderAlerts moderation={view.moderation} />
|
||||||
</View>
|
</View>
|
||||||
{!isDesktopWeb && !hideBackButton && (
|
{!isDesktop && !hideBackButton && (
|
||||||
<TouchableWithoutFeedback
|
<TouchableWithoutFeedback
|
||||||
onPress={onPressBack}
|
onPress={onPressBack}
|
||||||
hitSlop={BACK_HITSLOP}
|
hitSlop={BACK_HITSLOP}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {useTheme} from 'lib/ThemeContext'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {HITSLOP_10} from 'lib/constants'
|
import {HITSLOP_10} from 'lib/constants'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -37,6 +38,7 @@ export function HeaderWithInput({
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const textInput = React.useRef<TextInput>(null)
|
const textInput = React.useRef<TextInput>(null)
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
const onPressMenu = React.useCallback(() => {
|
const onPressMenu = React.useCallback(() => {
|
||||||
track('ViewHeader:MenuButtonClicked')
|
track('ViewHeader:MenuButtonClicked')
|
||||||
|
@ -49,8 +51,14 @@ export function HeaderWithInput({
|
||||||
}, [onPressCancelSearch, textInput])
|
}, [onPressCancelSearch, textInput])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[pal.view, pal.border, styles.header]}>
|
<View
|
||||||
{showMenu ? (
|
style={[
|
||||||
|
pal.view,
|
||||||
|
pal.border,
|
||||||
|
styles.header,
|
||||||
|
!isMobile && styles.headerDesktop,
|
||||||
|
]}>
|
||||||
|
{showMenu && isMobile ? (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="viewHeaderBackOrMenuBtn"
|
testID="viewHeaderBackOrMenuBtn"
|
||||||
onPress={onPressMenu}
|
onPress={onPressMenu}
|
||||||
|
@ -85,7 +93,7 @@ export function HeaderWithInput({
|
||||||
onBlur={() => setIsInputFocused(false)}
|
onBlur={() => setIsInputFocused(false)}
|
||||||
onChangeText={onChangeQuery}
|
onChangeText={onChangeQuery}
|
||||||
onSubmitEditing={onSubmitQuery}
|
onSubmitEditing={onSubmitQuery}
|
||||||
autoFocus={true}
|
autoFocus={isMobile}
|
||||||
accessibilityRole="search"
|
accessibilityRole="search"
|
||||||
accessibilityLabel="Search"
|
accessibilityLabel="Search"
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
|
@ -127,6 +135,11 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
paddingVertical: 4,
|
paddingVertical: 4,
|
||||||
},
|
},
|
||||||
|
headerDesktop: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderTopWidth: 0,
|
||||||
|
paddingVertical: 10,
|
||||||
|
},
|
||||||
headerMenuBtn: {
|
headerMenuBtn: {
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
|
|
|
@ -13,13 +13,14 @@ import {
|
||||||
} from 'view/com/util/LoadingPlaceholder'
|
} from 'view/com/util/LoadingPlaceholder'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
const SECTIONS = ['Posts', 'Users']
|
const SECTIONS = ['Posts', 'Users']
|
||||||
|
|
||||||
export const SearchResults = observer(({model}: {model: SearchUIModel}) => {
|
export const SearchResults = observer(({model}: {model: SearchUIModel}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
const renderTabBar = React.useCallback(
|
const renderTabBar = React.useCallback(
|
||||||
(props: RenderTabBarFnProps) => {
|
(props: RenderTabBarFnProps) => {
|
||||||
|
@ -39,10 +40,16 @@ export const SearchResults = observer(({model}: {model: SearchUIModel}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pager renderTabBar={renderTabBar} tabBarPosition="top" initialPage={0}>
|
<Pager renderTabBar={renderTabBar} tabBarPosition="top" initialPage={0}>
|
||||||
<View style={[styles.results]}>
|
<View
|
||||||
|
style={{
|
||||||
|
paddingTop: isMobile ? 42 : 50,
|
||||||
|
}}>
|
||||||
<PostResults key="0" model={model} />
|
<PostResults key="0" model={model} />
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.results]}>
|
<View
|
||||||
|
style={{
|
||||||
|
paddingTop: isMobile ? 42 : 50,
|
||||||
|
}}>
|
||||||
<Profiles key="1" model={model} />
|
<Profiles key="1" model={model} />
|
||||||
</View>
|
</View>
|
||||||
</Pager>
|
</Pager>
|
||||||
|
@ -128,7 +135,4 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 16,
|
||||||
},
|
},
|
||||||
results: {
|
|
||||||
paddingTop: isDesktopWeb ? 50 : 42,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,9 +8,9 @@ import {Text} from './text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20}
|
const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ export const ViewHeader = observer(function ({
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
|
const {isDesktop, isTablet} = useWebMediaQueries()
|
||||||
|
|
||||||
const onPressBack = React.useCallback(() => {
|
const onPressBack = React.useCallback(() => {
|
||||||
if (navigation.canGoBack()) {
|
if (navigation.canGoBack()) {
|
||||||
|
@ -49,7 +50,7 @@ export const ViewHeader = observer(function ({
|
||||||
store.shell.openDrawer()
|
store.shell.openDrawer()
|
||||||
}, [track, store])
|
}, [track, store])
|
||||||
|
|
||||||
if (isDesktopWeb) {
|
if (isDesktop) {
|
||||||
if (showOnDesktop) {
|
if (showOnDesktop) {
|
||||||
return (
|
return (
|
||||||
<DesktopWebHeader
|
<DesktopWebHeader
|
||||||
|
@ -84,13 +85,13 @@ export const ViewHeader = observer(function ({
|
||||||
icon="angle-left"
|
icon="angle-left"
|
||||||
style={[styles.backIcon, pal.text]}
|
style={[styles.backIcon, pal.text]}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : !isTablet ? (
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
size={18}
|
size={18}
|
||||||
icon="bars"
|
icon="bars"
|
||||||
style={[styles.backIcon, pal.textLight]}
|
style={[styles.backIcon, pal.textLight]}
|
||||||
/>
|
/>
|
||||||
)}
|
) : null}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
) : null}
|
) : null}
|
||||||
<View style={styles.titleContainer} pointerEvents="none">
|
<View style={styles.titleContainer} pointerEvents="none">
|
||||||
|
@ -122,6 +123,7 @@ function DesktopWebHeader({
|
||||||
<CenteredView
|
<CenteredView
|
||||||
style={[
|
style={[
|
||||||
styles.header,
|
styles.header,
|
||||||
|
styles.headerFixed,
|
||||||
styles.desktopHeader,
|
styles.desktopHeader,
|
||||||
pal.border,
|
pal.border,
|
||||||
{
|
{
|
||||||
|
@ -178,6 +180,7 @@ const Container = observer(
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.header,
|
styles.header,
|
||||||
|
styles.headerFixed,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
showBorder && styles.border,
|
showBorder && styles.border,
|
||||||
|
@ -190,9 +193,9 @@ const Container = observer(
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
styles.header,
|
styles.header,
|
||||||
|
styles.headerFloating,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
styles.headerFloating,
|
|
||||||
transform,
|
transform,
|
||||||
showBorder && styles.border,
|
showBorder && styles.border,
|
||||||
]}>
|
]}>
|
||||||
|
@ -208,6 +211,12 @@ const styles = StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
paddingVertical: 6,
|
paddingVertical: 6,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
headerFixed: {
|
||||||
|
maxWidth: 600,
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
},
|
},
|
||||||
headerFloating: {
|
headerFloating: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|
|
@ -24,6 +24,7 @@ import {
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {addStyle} from 'lib/styles'
|
import {addStyle} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
interface AddedProps {
|
interface AddedProps {
|
||||||
desktopFixedHeight?: boolean
|
desktopFixedHeight?: boolean
|
||||||
|
@ -48,6 +49,7 @@ export const FlatList = React.forwardRef(function <ItemT>(
|
||||||
ref: React.Ref<RNFlatList>,
|
ref: React.Ref<RNFlatList>,
|
||||||
) {
|
) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
contentContainerStyle = addStyle(
|
contentContainerStyle = addStyle(
|
||||||
contentContainerStyle,
|
contentContainerStyle,
|
||||||
styles.containerScroll,
|
styles.containerScroll,
|
||||||
|
@ -67,6 +69,12 @@ export const FlatList = React.forwardRef(function <ItemT>(
|
||||||
}
|
}
|
||||||
if (desktopFixedHeight) {
|
if (desktopFixedHeight) {
|
||||||
style = addStyle(style, styles.fixedHeight)
|
style = addStyle(style, styles.fixedHeight)
|
||||||
|
if (!isMobile) {
|
||||||
|
contentContainerStyle = addStyle(
|
||||||
|
contentContainerStyle,
|
||||||
|
styles.stableGutters,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<RNFlatList
|
<RNFlatList
|
||||||
|
@ -126,6 +134,9 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
fixedHeight: {
|
fixedHeight: {
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
|
},
|
||||||
|
stableGutters: {
|
||||||
|
// @ts-ignore web only -prf
|
||||||
scrollbarGutter: 'stable both-edges',
|
scrollbarGutter: 'stable both-edges',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,8 @@ import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {gradients} from 'lib/styles'
|
import {gradients} from 'lib/styles'
|
||||||
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isMobileWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
|
|
||||||
export interface FABProps
|
export interface FABProps
|
||||||
extends ComponentProps<typeof TouchableWithoutFeedback> {
|
extends ComponentProps<typeof TouchableWithoutFeedback> {
|
||||||
|
@ -14,6 +15,7 @@ export interface FABProps
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FABInner = observer(({testID, icon, ...props}: FABProps) => {
|
export const FABInner = observer(({testID, icon, ...props}: FABProps) => {
|
||||||
|
const {isTablet} = useWebMediaQueries()
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const interp = useAnimatedValue(0)
|
const interp = useAnimatedValue(0)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -24,18 +26,33 @@ export const FABInner = observer(({testID, icon, ...props}: FABProps) => {
|
||||||
isInteraction: false,
|
isInteraction: false,
|
||||||
}).start()
|
}).start()
|
||||||
}, [interp, store.shell.minimalShellMode])
|
}, [interp, store.shell.minimalShellMode])
|
||||||
const transform = {
|
const transform = isTablet
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
transform: [{translateY: Animated.multiply(interp, 60)}],
|
transform: [{translateY: Animated.multiply(interp, 60)}],
|
||||||
}
|
}
|
||||||
|
const size = isTablet ? styles.sizeLarge : styles.sizeRegular
|
||||||
return (
|
return (
|
||||||
<TouchableWithoutFeedback testID={testID} {...props}>
|
<TouchableWithoutFeedback testID={testID} {...props}>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[styles.outer, isMobileWeb && styles.mobileWebOuter, transform]}>
|
style={[
|
||||||
|
styles.outer,
|
||||||
|
size,
|
||||||
|
isWeb && isTablet
|
||||||
|
? {
|
||||||
|
right: 50,
|
||||||
|
bottom: 50,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
bottom: 114,
|
||||||
|
},
|
||||||
|
transform,
|
||||||
|
]}>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||||
start={{x: 0, y: 0}}
|
start={{x: 0, y: 0}}
|
||||||
end={{x: 1, y: 1}}
|
end={{x: 1, y: 1}}
|
||||||
style={styles.inner}>
|
style={[styles.inner, size]}>
|
||||||
{icon}
|
{icon}
|
||||||
</LinearGradient>
|
</LinearGradient>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
@ -44,22 +61,23 @@ export const FABInner = observer(({testID, icon, ...props}: FABProps) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
sizeRegular: {
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
borderRadius: 30,
|
||||||
|
},
|
||||||
|
sizeLarge: {
|
||||||
|
width: 70,
|
||||||
|
height: 70,
|
||||||
|
borderRadius: 35,
|
||||||
|
},
|
||||||
outer: {
|
outer: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
right: 24,
|
right: 24,
|
||||||
bottom: 94,
|
bottom: 94,
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
borderRadius: 30,
|
|
||||||
},
|
|
||||||
mobileWebOuter: {
|
|
||||||
bottom: 114,
|
|
||||||
},
|
},
|
||||||
inner: {
|
inner: {
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
borderRadius: 30,
|
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||||
import {Pressable, ViewStyle, StyleProp, StyleSheet} from 'react-native'
|
import {Pressable, ViewStyle, StyleProp, StyleSheet} from 'react-native'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
interface SelectableBtnProps {
|
interface SelectableBtnProps {
|
||||||
testID?: string
|
testID?: string
|
||||||
|
@ -28,12 +28,16 @@ export function SelectableBtn({
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const palPrimary = usePalette('inverted')
|
const palPrimary = usePalette('inverted')
|
||||||
const needsWidthStyles = !style || !('width' in style || 'flex' in style)
|
const needsWidthStyles = !style || !('width' in style || 'flex' in style)
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={testID}
|
testID={testID}
|
||||||
style={[
|
style={[
|
||||||
styles.btn,
|
styles.btn,
|
||||||
needsWidthStyles && styles.btnWidth,
|
needsWidthStyles && {
|
||||||
|
flex: isMobile ? 1 : undefined,
|
||||||
|
width: !isMobile ? 100 : undefined,
|
||||||
|
},
|
||||||
left && styles.btnLeft,
|
left && styles.btnLeft,
|
||||||
right && styles.btnRight,
|
right && styles.btnRight,
|
||||||
pal.border,
|
pal.border,
|
||||||
|
@ -58,10 +62,6 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
},
|
},
|
||||||
btnWidth: {
|
|
||||||
flex: isDesktopWeb ? undefined : 1,
|
|
||||||
width: isDesktopWeb ? 100 : undefined,
|
|
||||||
},
|
|
||||||
btnLeft: {
|
btnLeft: {
|
||||||
borderTopLeftRadius: 8,
|
borderTopLeftRadius: 8,
|
||||||
borderBottomLeftRadius: 8,
|
borderBottomLeftRadius: 8,
|
||||||
|
|
|
@ -2,18 +2,18 @@ import React from 'react'
|
||||||
import MediaQuery from 'react-responsive'
|
import MediaQuery from 'react-responsive'
|
||||||
|
|
||||||
export const Desktop = ({children}: React.PropsWithChildren<{}>) => (
|
export const Desktop = ({children}: React.PropsWithChildren<{}>) => (
|
||||||
<MediaQuery minWidth={1224}>{children}</MediaQuery>
|
<MediaQuery minWidth={1300}>{children}</MediaQuery>
|
||||||
)
|
)
|
||||||
export const TabletOrDesktop = ({children}: React.PropsWithChildren<{}>) => (
|
export const TabletOrDesktop = ({children}: React.PropsWithChildren<{}>) => (
|
||||||
<MediaQuery minWidth={800}>{children}</MediaQuery>
|
<MediaQuery minWidth={800}>{children}</MediaQuery>
|
||||||
)
|
)
|
||||||
export const Tablet = ({children}: React.PropsWithChildren<{}>) => (
|
export const Tablet = ({children}: React.PropsWithChildren<{}>) => (
|
||||||
<MediaQuery minWidth={800} maxWidth={1224}>
|
<MediaQuery minWidth={800} maxWidth={1300}>
|
||||||
{children}
|
{children}
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
)
|
)
|
||||||
export const TabletOrMobile = ({children}: React.PropsWithChildren<{}>) => (
|
export const TabletOrMobile = ({children}: React.PropsWithChildren<{}>) => (
|
||||||
<MediaQuery maxWidth={1224}>{children}</MediaQuery>
|
<MediaQuery maxWidth={1300}>{children}</MediaQuery>
|
||||||
)
|
)
|
||||||
export const Mobile = ({children}: React.PropsWithChildren<{}>) => (
|
export const Mobile = ({children}: React.PropsWithChildren<{}>) => (
|
||||||
<MediaQuery maxWidth={800}>{children}</MediaQuery>
|
<MediaQuery maxWidth={800}>{children}</MediaQuery>
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {StyleSheet, TouchableOpacity} from 'react-native'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {LoadLatestBtn as LoadLatestBtnMobile} from './LoadLatestBtnMobile'
|
import {LoadLatestBtn as LoadLatestBtnMobile} from './LoadLatestBtnMobile'
|
||||||
import {isMobileWeb} from 'platform/detection'
|
|
||||||
import {HITSLOP_20} from 'lib/constants'
|
import {HITSLOP_20} from 'lib/constants'
|
||||||
|
|
||||||
export const LoadLatestBtn = ({
|
export const LoadLatestBtn = ({
|
||||||
|
@ -19,7 +19,8 @@ export const LoadLatestBtn = ({
|
||||||
minimalShellMode?: boolean
|
minimalShellMode?: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
if (isMobileWeb) {
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
if (isMobile) {
|
||||||
return (
|
return (
|
||||||
<LoadLatestBtnMobile
|
<LoadLatestBtnMobile
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {ModerationUI} from '@atproto/api'
|
import {ModerationUI} from '@atproto/api'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {ShieldExclamation} from 'lib/icons'
|
import {ShieldExclamation} from 'lib/icons'
|
||||||
import {describeModerationCause} from 'lib/moderation'
|
import {describeModerationCause} from 'lib/moderation'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
export function ContentHider({
|
export function ContentHider({
|
||||||
testID,
|
testID,
|
||||||
|
@ -24,6 +24,7 @@ export function ContentHider({
|
||||||
}>) {
|
}>) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [override, setOverride] = React.useState(false)
|
const [override, setOverride] = React.useState(false)
|
||||||
|
|
||||||
if (!moderation.blur || (ignoreMute && moderation.cause?.type === 'muted')) {
|
if (!moderation.blur || (ignoreMute && moderation.cause?.type === 'muted')) {
|
||||||
|
@ -54,6 +55,7 @@ export function ContentHider({
|
||||||
accessibilityLabel=""
|
accessibilityLabel=""
|
||||||
style={[
|
style={[
|
||||||
styles.cover,
|
styles.cover,
|
||||||
|
{paddingRight: isMobile ? 22 : 18},
|
||||||
moderation.noOverride
|
moderation.noOverride
|
||||||
? {borderWidth: 1, borderColor: pal.colors.borderDark}
|
? {borderWidth: 1, borderColor: pal.colors.borderDark}
|
||||||
: pal.viewLight,
|
: pal.viewLight,
|
||||||
|
@ -96,7 +98,6 @@ const styles = StyleSheet.create({
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
paddingVertical: 14,
|
paddingVertical: 14,
|
||||||
paddingLeft: 14,
|
paddingLeft: 14,
|
||||||
paddingRight: isDesktopWeb ? 18 : 22,
|
|
||||||
},
|
},
|
||||||
showBtn: {
|
showBtn: {
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
|
|
|
@ -2,13 +2,13 @@ import React, {ComponentProps} from 'react'
|
||||||
import {StyleSheet, Pressable, View} from 'react-native'
|
import {StyleSheet, Pressable, View} from 'react-native'
|
||||||
import {ModerationUI} from '@atproto/api'
|
import {ModerationUI} from '@atproto/api'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {Link} from '../Link'
|
import {Link} from '../Link'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {addStyle} from 'lib/styles'
|
import {addStyle} from 'lib/styles'
|
||||||
import {describeModerationCause} from 'lib/moderation'
|
import {describeModerationCause} from 'lib/moderation'
|
||||||
import {ShieldExclamation} from 'lib/icons'
|
import {ShieldExclamation} from 'lib/icons'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
interface Props extends ComponentProps<typeof Link> {
|
interface Props extends ComponentProps<typeof Link> {
|
||||||
// testID?: string
|
// testID?: string
|
||||||
|
@ -27,6 +27,7 @@ export function PostHider({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [override, setOverride] = React.useState(false)
|
const [override, setOverride] = React.useState(false)
|
||||||
|
|
||||||
if (!moderation.blur) {
|
if (!moderation.blur) {
|
||||||
|
@ -55,7 +56,11 @@ export function PostHider({
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityHint={override ? 'Hide the content' : 'Show the content'}
|
accessibilityHint={override ? 'Hide the content' : 'Show the content'}
|
||||||
accessibilityLabel=""
|
accessibilityLabel=""
|
||||||
style={[styles.description, pal.viewLight]}>
|
style={[
|
||||||
|
styles.description,
|
||||||
|
{paddingRight: isMobile ? 22 : 18},
|
||||||
|
pal.viewLight,
|
||||||
|
]}>
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
store.shell.openModal({
|
store.shell.openModal({
|
||||||
|
@ -100,7 +105,6 @@ const styles = StyleSheet.create({
|
||||||
gap: 4,
|
gap: 4,
|
||||||
paddingVertical: 14,
|
paddingVertical: 14,
|
||||||
paddingLeft: 18,
|
paddingLeft: 18,
|
||||||
paddingRight: isDesktopWeb ? 18 : 22,
|
|
||||||
marginTop: 1,
|
marginTop: 1,
|
||||||
},
|
},
|
||||||
showBtn: {
|
showBtn: {
|
||||||
|
|
|
@ -13,10 +13,10 @@ import {
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
import {ModerationUI} from '@atproto/api'
|
import {ModerationUI} from '@atproto/api'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {Button} from '../forms/Button'
|
import {Button} from '../forms/Button'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {describeModerationCause} from 'lib/moderation'
|
import {describeModerationCause} from 'lib/moderation'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ export function ScreenHider({
|
||||||
const palInverted = usePalette('inverted')
|
const palInverted = usePalette('inverted')
|
||||||
const [override, setOverride] = React.useState(false)
|
const [override, setOverride] = React.useState(false)
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
if (!moderation.blur || override) {
|
if (!moderation.blur || override) {
|
||||||
return (
|
return (
|
||||||
|
@ -85,7 +86,7 @@ export function ScreenHider({
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
</Text>
|
</Text>
|
||||||
{!isDesktopWeb && <View style={styles.spacer} />}
|
{isMobile && <View style={styles.spacer} />}
|
||||||
<View style={styles.btnContainer}>
|
<View style={styles.btnContainer}>
|
||||||
<Button
|
<Button
|
||||||
type="inverted"
|
type="inverted"
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {Image} from 'expo-image'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {StyleSheet, View} from 'react-native'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {AppBskyEmbedExternal} from '@atproto/api'
|
import {AppBskyEmbedExternal} from '@atproto/api'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {toNiceDomain} from 'lib/strings/url-helpers'
|
import {toNiceDomain} from 'lib/strings/url-helpers'
|
||||||
|
|
||||||
export const ExternalLinkEmbed = ({
|
export const ExternalLinkEmbed = ({
|
||||||
|
@ -15,55 +15,16 @@ export const ExternalLinkEmbed = ({
|
||||||
imageChild?: React.ReactNode
|
imageChild?: React.ReactNode
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
return (
|
return (
|
||||||
<View style={styles.extContainer}>
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: isMobile ? 'column' : 'row',
|
||||||
|
}}>
|
||||||
{link.thumb ? (
|
{link.thumb ? (
|
||||||
<View style={styles.extImageContainer}>
|
<View
|
||||||
<Image
|
style={
|
||||||
style={styles.extImage}
|
!isMobile
|
||||||
source={{uri: link.thumb}}
|
|
||||||
accessibilityIgnoresInvertColors
|
|
||||||
/>
|
|
||||||
{imageChild}
|
|
||||||
</View>
|
|
||||||
) : undefined}
|
|
||||||
<View style={styles.extInner}>
|
|
||||||
<Text
|
|
||||||
type="sm"
|
|
||||||
numberOfLines={1}
|
|
||||||
style={[pal.textLight, styles.extUri]}>
|
|
||||||
{toNiceDomain(link.uri)}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
type="lg-bold"
|
|
||||||
numberOfLines={isDesktopWeb ? 2 : 4}
|
|
||||||
style={[pal.text]}>
|
|
||||||
{link.title || link.uri}
|
|
||||||
</Text>
|
|
||||||
{link.description ? (
|
|
||||||
<Text
|
|
||||||
type="md"
|
|
||||||
numberOfLines={isDesktopWeb ? 2 : 4}
|
|
||||||
style={[pal.text, styles.extDescription]}>
|
|
||||||
{link.description}
|
|
||||||
</Text>
|
|
||||||
) : undefined}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
borderTopLeftRadius: 6,
|
||||||
borderBottomLeftRadius: 6,
|
borderBottomLeftRadius: 6,
|
||||||
|
@ -77,7 +38,49 @@ const styles = StyleSheet.create({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: 200,
|
height: 200,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
},
|
}
|
||||||
|
}>
|
||||||
|
<Image
|
||||||
|
style={styles.extImage}
|
||||||
|
source={{uri: link.thumb}}
|
||||||
|
accessibilityIgnoresInvertColors
|
||||||
|
/>
|
||||||
|
{imageChild}
|
||||||
|
</View>
|
||||||
|
) : undefined}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: isMobile ? 10 : 14,
|
||||||
|
paddingTop: 8,
|
||||||
|
paddingBottom: 10,
|
||||||
|
flex: !isMobile ? 1 : undefined,
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
type="sm"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={[pal.textLight, styles.extUri]}>
|
||||||
|
{toNiceDomain(link.uri)}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
type="lg-bold"
|
||||||
|
numberOfLines={isMobile ? 4 : 2}
|
||||||
|
style={[pal.text]}>
|
||||||
|
{link.title || link.uri}
|
||||||
|
</Text>
|
||||||
|
{link.description ? (
|
||||||
|
<Text
|
||||||
|
type="md"
|
||||||
|
numberOfLines={isMobile ? 4 : 2}
|
||||||
|
style={[pal.text, styles.extDescription]}>
|
||||||
|
{link.description}
|
||||||
|
</Text>
|
||||||
|
) : undefined}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
extImage: {
|
extImage: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: 200,
|
height: 200,
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
|
||||||
import {ImagesLightbox} from 'state/models/ui/shell'
|
import {ImagesLightbox} from 'state/models/ui/shell'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {YoutubeEmbed} from './YoutubeEmbed'
|
import {YoutubeEmbed} from './YoutubeEmbed'
|
||||||
import {ExternalLinkEmbed} from './ExternalLinkEmbed'
|
import {ExternalLinkEmbed} from './ExternalLinkEmbed'
|
||||||
import {getYoutubeVideoId} from 'lib/strings/url-helpers'
|
import {getYoutubeVideoId} from 'lib/strings/url-helpers'
|
||||||
|
@ -29,7 +30,6 @@ import {MaybeQuoteEmbed} from './QuoteEmbed'
|
||||||
import {AutoSizedImage} from '../images/AutoSizedImage'
|
import {AutoSizedImage} from '../images/AutoSizedImage'
|
||||||
import {CustomFeedEmbed} from './CustomFeedEmbed'
|
import {CustomFeedEmbed} from './CustomFeedEmbed'
|
||||||
import {ListEmbed} from './ListEmbed'
|
import {ListEmbed} from './ListEmbed'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {isCauseALabelOnUri} from 'lib/moderation'
|
import {isCauseALabelOnUri} from 'lib/moderation'
|
||||||
|
|
||||||
type Embed =
|
type Embed =
|
||||||
|
@ -50,6 +50,7 @@ export function PostEmbeds({
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
// quote post with media
|
// quote post with media
|
||||||
// =
|
// =
|
||||||
|
@ -111,7 +112,10 @@ export function PostEmbeds({
|
||||||
uri={thumb}
|
uri={thumb}
|
||||||
onPress={() => openLightbox(0)}
|
onPress={() => openLightbox(0)}
|
||||||
onPressIn={() => onPressIn(0)}
|
onPressIn={() => onPressIn(0)}
|
||||||
style={styles.singleImage}>
|
style={[
|
||||||
|
styles.singleImage,
|
||||||
|
isMobile && styles.singleImageMobile,
|
||||||
|
]}>
|
||||||
{alt === '' ? null : (
|
{alt === '' ? null : (
|
||||||
<View style={styles.altContainer}>
|
<View style={styles.altContainer}>
|
||||||
<Text style={styles.alt} accessible={false}>
|
<Text style={styles.alt} accessible={false}>
|
||||||
|
@ -130,7 +134,11 @@ export function PostEmbeds({
|
||||||
images={embed.images}
|
images={embed.images}
|
||||||
onPress={openLightbox}
|
onPress={openLightbox}
|
||||||
onPressIn={onPressIn}
|
onPressIn={onPressIn}
|
||||||
style={embed.images.length === 1 ? styles.singleImage : undefined}
|
style={
|
||||||
|
embed.images.length === 1
|
||||||
|
? [styles.singleImage, isMobile && styles.singleImageMobile]
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -169,7 +177,10 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
singleImage: {
|
singleImage: {
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
maxHeight: isDesktopWeb ? 1000 : 500,
|
maxHeight: 1000,
|
||||||
|
},
|
||||||
|
singleImageMobile: {
|
||||||
|
maxHeight: 500,
|
||||||
},
|
},
|
||||||
extOuter: {
|
extOuter: {
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {Button} from '../com/util/forms/Button'
|
||||||
import * as Toast from '../com/util/Toast'
|
import * as Toast from '../com/util/Toast'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
|
@ -23,6 +23,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
|
@ -41,7 +42,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
<CenteredView
|
<CenteredView
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
isDesktopWeb && styles.containerDesktop,
|
isTabletOrDesktop && styles.containerDesktop,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
]}
|
]}
|
||||||
|
@ -53,11 +54,11 @@ export const AppPasswords = withAuthRequired(
|
||||||
pressing the button below.
|
pressing the button below.
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
{!isDesktopWeb && <View style={styles.flex1} />}
|
{!isTabletOrDesktop && <View style={styles.flex1} />}
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.btnContainer,
|
styles.btnContainer,
|
||||||
isDesktopWeb && styles.btnContainerDesktop,
|
isTabletOrDesktop && styles.btnContainerDesktop,
|
||||||
]}>
|
]}>
|
||||||
<Button
|
<Button
|
||||||
testID="appPasswordBtn"
|
testID="appPasswordBtn"
|
||||||
|
@ -77,7 +78,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
<CenteredView
|
<CenteredView
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
isDesktopWeb && styles.containerDesktop,
|
isTabletOrDesktop && styles.containerDesktop,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
]}
|
]}
|
||||||
|
@ -87,7 +88,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
style={[
|
style={[
|
||||||
styles.scrollContainer,
|
styles.scrollContainer,
|
||||||
pal.border,
|
pal.border,
|
||||||
!isDesktopWeb && styles.flex1,
|
!isTabletOrDesktop && styles.flex1,
|
||||||
]}>
|
]}>
|
||||||
{store.me.appPasswords.map((password, i) => (
|
{store.me.appPasswords.map((password, i) => (
|
||||||
<AppPassword
|
<AppPassword
|
||||||
|
@ -97,7 +98,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
createdAt={password.createdAt}
|
createdAt={password.createdAt}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{isDesktopWeb && (
|
{isTabletOrDesktop && (
|
||||||
<View style={[styles.btnContainer, styles.btnContainerDesktop]}>
|
<View style={[styles.btnContainer, styles.btnContainerDesktop]}>
|
||||||
<Button
|
<Button
|
||||||
testID="appPasswordBtn"
|
testID="appPasswordBtn"
|
||||||
|
@ -110,7 +111,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
{!isDesktopWeb && (
|
{!isTabletOrDesktop && (
|
||||||
<View style={styles.btnContainer}>
|
<View style={styles.btnContainer}>
|
||||||
<Button
|
<Button
|
||||||
testID="appPasswordBtn"
|
testID="appPasswordBtn"
|
||||||
|
@ -128,6 +129,7 @@ export const AppPasswords = withAuthRequired(
|
||||||
)
|
)
|
||||||
|
|
||||||
function AppPasswordsHeader() {
|
function AppPasswordsHeader() {
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -137,7 +139,7 @@ function AppPasswordsHeader() {
|
||||||
style={[
|
style={[
|
||||||
styles.description,
|
styles.description,
|
||||||
pal.text,
|
pal.text,
|
||||||
isDesktopWeb && styles.descriptionDesktop,
|
isTabletOrDesktop && styles.descriptionDesktop,
|
||||||
]}>
|
]}>
|
||||||
Use app passwords to login to other Bluesky clients without giving full
|
Use app passwords to login to other Bluesky clients without giving full
|
||||||
access to your account or password.
|
access to your account or password.
|
||||||
|
@ -207,11 +209,12 @@ function AppPassword({
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
paddingBottom: 100,
|
||||||
},
|
},
|
||||||
containerDesktop: {
|
containerDesktop: {
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||||
import {Button} from 'view/com/util/forms/Button'
|
import {Button} from 'view/com/util/forms/Button'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import * as Toast from 'view/com/util/Toast'
|
import * as Toast from 'view/com/util/Toast'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||||
import {shareUrl} from 'lib/sharing'
|
import {shareUrl} from 'lib/sharing'
|
||||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||||
|
@ -122,6 +122,7 @@ export const CustomFeedScreenInner = observer(
|
||||||
({route, feedOwnerDid}: Props & {feedOwnerDid: string}) => {
|
({route, feedOwnerDid}: Props & {feedOwnerDid: string}) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const {rkey, name: handleOrDid} = route.params
|
const {rkey, name: handleOrDid} = route.params
|
||||||
const uri = useMemo(
|
const uri = useMemo(
|
||||||
|
@ -357,7 +358,7 @@ export const CustomFeedScreenInner = observer(
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
{isDesktopWeb && (
|
{isTabletOrDesktop && (
|
||||||
<View style={[styles.headerBtns, styles.headerBtnsDesktop]}>
|
<View style={[styles.headerBtns, styles.headerBtnsDesktop]}>
|
||||||
<Button
|
<Button
|
||||||
type={currentFeed?.isSaved ? 'default' : 'inverted'}
|
type={currentFeed?.isSaved ? 'default' : 'inverted'}
|
||||||
|
@ -452,7 +453,14 @@ export const CustomFeedScreenInner = observer(
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.fakeSelector, pal.border]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.fakeSelector,
|
||||||
|
{
|
||||||
|
paddingHorizontal: isTabletOrDesktop ? 16 : 6,
|
||||||
|
},
|
||||||
|
pal.border,
|
||||||
|
]}>
|
||||||
<View
|
<View
|
||||||
style={[styles.fakeSelectorItem, {borderColor: pal.colors.link}]}>
|
style={[styles.fakeSelectorItem, {borderColor: pal.colors.link}]}>
|
||||||
<Text type="md-medium" style={[pal.text]}>
|
<Text type="md-medium" style={[pal.text]}>
|
||||||
|
@ -474,6 +482,7 @@ export const CustomFeedScreenInner = observer(
|
||||||
rkey,
|
rkey,
|
||||||
isPinned,
|
isPinned,
|
||||||
onTogglePinned,
|
onTogglePinned,
|
||||||
|
isTabletOrDesktop,
|
||||||
])
|
])
|
||||||
|
|
||||||
const renderEmptyState = React.useCallback(() => {
|
const renderEmptyState = React.useCallback(() => {
|
||||||
|
@ -486,7 +495,9 @@ export const CustomFeedScreenInner = observer(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={s.hContentRegion}>
|
<View style={s.hContentRegion}>
|
||||||
|
{!isTabletOrDesktop && (
|
||||||
<ViewHeader title="" renderButton={currentFeed && renderHeaderBtns} />
|
<ViewHeader title="" renderButton={currentFeed && renderHeaderBtns} />
|
||||||
|
)}
|
||||||
<Feed
|
<Feed
|
||||||
scrollElRef={scrollElRef}
|
scrollElRef={scrollElRef}
|
||||||
feed={algoFeed}
|
feed={algoFeed}
|
||||||
|
@ -495,6 +506,7 @@ export const CustomFeedScreenInner = observer(
|
||||||
ListHeaderComponent={renderListHeaderComponent}
|
ListHeaderComponent={renderListHeaderComponent}
|
||||||
renderEmptyState={renderEmptyState}
|
renderEmptyState={renderEmptyState}
|
||||||
extraData={[uri, isPinned]}
|
extraData={[uri, isPinned]}
|
||||||
|
style={!isTabletOrDesktop ? {flex: 1} : undefined}
|
||||||
/>
|
/>
|
||||||
{isScrolledDown ? (
|
{isScrolledDown ? (
|
||||||
<LoadLatestBtn
|
<LoadLatestBtn
|
||||||
|
@ -550,7 +562,6 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
fakeSelector: {
|
fakeSelector: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
paddingHorizontal: isDesktopWeb ? 16 : 6,
|
|
||||||
},
|
},
|
||||||
fakeSelectorItem: {
|
fakeSelectorItem: {
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
|
|
|
@ -10,8 +10,8 @@ import {FeedsDiscoveryModel} from 'state/models/discovery/feeds'
|
||||||
import {CenteredView, FlatList} from 'view/com/util/Views'
|
import {CenteredView, FlatList} from 'view/com/util/Views'
|
||||||
import {CustomFeed} from 'view/com/feeds/CustomFeed'
|
import {CustomFeed} from 'view/com/feeds/CustomFeed'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
||||||
import {HeaderWithInput} from 'view/com/search/HeaderWithInput'
|
import {HeaderWithInput} from 'view/com/search/HeaderWithInput'
|
||||||
|
@ -23,6 +23,7 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const feeds = React.useMemo(() => new FeedsDiscoveryModel(store), [store])
|
const feeds = React.useMemo(() => new FeedsDiscoveryModel(store), [store])
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
// search stuff
|
// search stuff
|
||||||
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)
|
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)
|
||||||
|
@ -74,7 +75,7 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
||||||
<View style={styles.empty}>
|
<View style={styles.empty}>
|
||||||
<Text type="lg" style={pal.textLight}>
|
<Text type="lg" style={pal.textLight}>
|
||||||
{feeds.isLoading
|
{feeds.isLoading
|
||||||
? isDesktopWeb
|
? isTabletOrDesktop
|
||||||
? 'Loading...'
|
? 'Loading...'
|
||||||
: ''
|
: ''
|
||||||
: query
|
: query
|
||||||
|
@ -100,9 +101,10 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredView style={[styles.container, pal.view]}>
|
<CenteredView style={[styles.container, pal.view]}>
|
||||||
<View style={[isDesktopWeb && styles.containerDesktop, pal.border]}>
|
<View
|
||||||
|
style={[isTabletOrDesktop && styles.containerDesktop, pal.border]}>
|
||||||
<ViewHeader title="Discover Feeds" showOnDesktop />
|
<ViewHeader title="Discover Feeds" showOnDesktop />
|
||||||
<View style={{marginTop: isDesktopWeb ? 5 : 0, marginBottom: 4}}>
|
</View>
|
||||||
<HeaderWithInput
|
<HeaderWithInput
|
||||||
isInputFocused={isInputFocused}
|
isInputFocused={isInputFocused}
|
||||||
query={query}
|
query={query}
|
||||||
|
@ -113,10 +115,8 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
||||||
onSubmitQuery={onSubmitQuery}
|
onSubmitQuery={onSubmitQuery}
|
||||||
showMenu={false}
|
showMenu={false}
|
||||||
/>
|
/>
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<FlatList
|
<FlatList
|
||||||
style={[!isDesktopWeb && s.flex1]}
|
style={[!isTabletOrDesktop && s.flex1]}
|
||||||
data={feeds.feeds}
|
data={feeds.feeds}
|
||||||
keyExtractor={item => item.data.uri}
|
keyExtractor={item => item.data.uri}
|
||||||
contentContainerStyle={styles.contentContainer}
|
contentContainerStyle={styles.contentContainer}
|
||||||
|
|
|
@ -12,22 +12,23 @@ import {NativeStackScreenProps, FeedsTabNavigatorParams} from 'lib/routes/types'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {PostsMultiFeedModel} from 'state/models/feeds/multi-feed'
|
import {PostsMultiFeedModel} from 'state/models/feeds/multi-feed'
|
||||||
import {MultiFeed} from 'view/com/posts/MultiFeed'
|
import {MultiFeed} from 'view/com/posts/MultiFeed'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTimer} from 'lib/hooks/useTimer'
|
import {useTimer} from 'lib/hooks/useTimer'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||||
import {ComposeIcon2, CogIcon} from 'lib/icons'
|
import {ComposeIcon2, CogIcon} from 'lib/icons'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
|
|
||||||
const LOAD_NEW_PROMPT_TIME = 60e3 // 60 seconds
|
const LOAD_NEW_PROMPT_TIME = 60e3 // 60 seconds
|
||||||
const HEADER_OFFSET = isDesktopWeb ? 0 : 40
|
const MOBILE_HEADER_OFFSET = 40
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
||||||
export const FeedsScreen = withAuthRequired(
|
export const FeedsScreen = withAuthRequired(
|
||||||
observer<Props>(({}: Props) => {
|
observer<Props>(({}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const flatListRef = React.useRef<FlatList>(null)
|
const flatListRef = React.useRef<FlatList>(null)
|
||||||
const multifeed = React.useMemo<PostsMultiFeedModel>(
|
const multifeed = React.useMemo<PostsMultiFeedModel>(
|
||||||
() => new PostsMultiFeedModel(store),
|
() => new PostsMultiFeedModel(store),
|
||||||
|
@ -105,14 +106,16 @@ export const FeedsScreen = withAuthRequired(
|
||||||
multifeed={multifeed}
|
multifeed={multifeed}
|
||||||
onScroll={onMainScroll}
|
onScroll={onMainScroll}
|
||||||
scrollEventThrottle={100}
|
scrollEventThrottle={100}
|
||||||
headerOffset={HEADER_OFFSET}
|
headerOffset={isMobile ? MOBILE_HEADER_OFFSET : undefined}
|
||||||
/>
|
/>
|
||||||
|
{isMobile && (
|
||||||
<ViewHeader
|
<ViewHeader
|
||||||
title="My Feeds"
|
title="My Feeds"
|
||||||
canGoBack={false}
|
canGoBack={false}
|
||||||
hideOnScroll
|
hideOnScroll
|
||||||
renderButton={renderHeaderBtn}
|
renderButton={renderHeaderBtn}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
{isScrolledDown || loadPromptVisible ? (
|
{isScrolledDown || loadPromptVisible ? (
|
||||||
<LoadLatestBtn
|
<LoadLatestBtn
|
||||||
onPress={onSoftReset}
|
onPress={onSoftReset}
|
||||||
|
|
|
@ -19,14 +19,11 @@ import {useStores} from 'state/index'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {ComposeIcon2} from 'lib/icons'
|
import {ComposeIcon2} from 'lib/icons'
|
||||||
import {isDesktopWeb, isMobileWebMediaQuery, isWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
const HEADER_OFFSET_MOBILE = 78
|
const HEADER_OFFSET_MOBILE = 78
|
||||||
const HEADER_OFFSET_DESKTOP = 50
|
const HEADER_OFFSET_DESKTOP = 50
|
||||||
const HEADER_OFFSET = isDesktopWeb
|
|
||||||
? HEADER_OFFSET_DESKTOP
|
|
||||||
: HEADER_OFFSET_MOBILE
|
|
||||||
const POLL_FREQ = 30e3 // 30sec
|
const POLL_FREQ = 30e3 // 30sec
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
|
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
|
||||||
|
@ -158,10 +155,13 @@ const FeedPage = observer(
|
||||||
renderEmptyState?: () => JSX.Element
|
renderEmptyState?: () => JSX.Element
|
||||||
}) => {
|
}) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const [onMainScroll, isScrolledDown, resetMainScroll] =
|
const [onMainScroll, isScrolledDown, resetMainScroll] =
|
||||||
useOnMainScroll(store)
|
useOnMainScroll(store)
|
||||||
const {screen, track} = useAnalytics()
|
const {screen, track} = useAnalytics()
|
||||||
const [headerOffset, setHeaderOffset] = React.useState(HEADER_OFFSET)
|
const [headerOffset, setHeaderOffset] = React.useState(
|
||||||
|
isMobile ? HEADER_OFFSET_MOBILE : HEADER_OFFSET_DESKTOP,
|
||||||
|
)
|
||||||
const scrollElRef = React.useRef<FlatList>(null)
|
const scrollElRef = React.useRef<FlatList>(null)
|
||||||
const {appState} = useAppState({
|
const {appState} = useAppState({
|
||||||
onForeground: () => doPoll(true),
|
onForeground: () => doPoll(true),
|
||||||
|
@ -206,15 +206,9 @@ const FeedPage = observer(
|
||||||
}, [isPageFocused, scrollToTop, feed])
|
}, [isPageFocused, scrollToTop, feed])
|
||||||
|
|
||||||
// listens for resize events
|
// listens for resize events
|
||||||
const listenForResize = React.useCallback(() => {
|
React.useEffect(() => {
|
||||||
// @ts-ignore we know window exists -prf
|
setHeaderOffset(isMobile ? HEADER_OFFSET_MOBILE : HEADER_OFFSET_DESKTOP)
|
||||||
const isMobileWeb = global.window.matchMedia(
|
}, [isMobile])
|
||||||
isMobileWebMediaQuery,
|
|
||||||
)?.matches
|
|
||||||
setHeaderOffset(
|
|
||||||
isMobileWeb ? HEADER_OFFSET_MOBILE : HEADER_OFFSET_DESKTOP,
|
|
||||||
)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// fires when page within screen is activated/deactivated
|
// fires when page within screen is activated/deactivated
|
||||||
// - check for latest
|
// - check for latest
|
||||||
|
@ -234,17 +228,10 @@ const FeedPage = observer(
|
||||||
feed.update()
|
feed.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWeb) {
|
|
||||||
window.addEventListener('resize', listenForResize)
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(pollInterval)
|
clearInterval(pollInterval)
|
||||||
softResetSub.remove()
|
softResetSub.remove()
|
||||||
feedCleanup()
|
feedCleanup()
|
||||||
if (isWeb) {
|
|
||||||
isWeb && window.removeEventListener('resize', listenForResize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
store,
|
store,
|
||||||
|
@ -254,7 +241,6 @@ const FeedPage = observer(
|
||||||
feed,
|
feed,
|
||||||
isPageFocused,
|
isPageFocused,
|
||||||
isScreenFocused,
|
isScreenFocused,
|
||||||
listenForResize,
|
|
||||||
])
|
])
|
||||||
|
|
||||||
const onPressCompose = React.useCallback(() => {
|
const onPressCompose = React.useCallback(() => {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {Link} from '../com/util/Link'
|
||||||
import {Text} from '../com/util/text/Text'
|
import {Text} from '../com/util/text/Text'
|
||||||
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 {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
|
||||||
export const ModerationScreen = withAuthRequired(
|
export const ModerationScreen = withAuthRequired(
|
||||||
|
@ -24,6 +24,7 @@ export const ModerationScreen = withAuthRequired(
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const {screen, track} = useAnalytics()
|
const {screen, track} = useAnalytics()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
|
@ -42,7 +43,7 @@ export const ModerationScreen = withAuthRequired(
|
||||||
style={[
|
style={[
|
||||||
s.hContentRegion,
|
s.hContentRegion,
|
||||||
pal.border,
|
pal.border,
|
||||||
isDesktopWeb ? styles.desktopContainer : pal.viewLight,
|
isTabletOrDesktop ? styles.desktopContainer : pal.viewLight,
|
||||||
]}
|
]}
|
||||||
testID="moderationScreen">
|
testID="moderationScreen">
|
||||||
<ViewHeader title="Moderation" showOnDesktop />
|
<ViewHeader title="Moderation" showOnDesktop />
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||||
import {Text} from '../com/util/text/Text'
|
import {Text} from '../com/util/text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
|
@ -30,6 +30,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
||||||
observer(({}: Props) => {
|
observer(({}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
const blockedAccounts = useMemo(
|
const blockedAccounts = useMemo(
|
||||||
() => new BlockedAccountsModel(store),
|
() => new BlockedAccountsModel(store),
|
||||||
|
@ -72,7 +73,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
||||||
<CenteredView
|
<CenteredView
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
isDesktopWeb && styles.containerDesktop,
|
isTabletOrDesktop && styles.containerDesktop,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
]}
|
]}
|
||||||
|
@ -83,14 +84,14 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
||||||
style={[
|
style={[
|
||||||
styles.description,
|
styles.description,
|
||||||
pal.text,
|
pal.text,
|
||||||
isDesktopWeb && styles.descriptionDesktop,
|
isTabletOrDesktop && styles.descriptionDesktop,
|
||||||
]}>
|
]}>
|
||||||
Blocked accounts cannot reply in your threads, mention you, or
|
Blocked accounts cannot reply in your threads, mention you, or
|
||||||
otherwise interact with you. You will not see their content and they
|
otherwise interact with you. You will not see their content and they
|
||||||
will be prevented from seeing yours.
|
will be prevented from seeing yours.
|
||||||
</Text>
|
</Text>
|
||||||
{!blockedAccounts.hasContent ? (
|
{!blockedAccounts.hasContent ? (
|
||||||
<View style={[pal.border, !isDesktopWeb && styles.flex1]}>
|
<View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
|
||||||
<View style={[styles.empty, pal.viewLight]}>
|
<View style={[styles.empty, pal.viewLight]}>
|
||||||
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
||||||
You have not blocked any accounts yet. To block an account, go
|
You have not blocked any accounts yet. To block an account, go
|
||||||
|
@ -101,7 +102,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<FlatList
|
<FlatList
|
||||||
style={[!isDesktopWeb && styles.flex1]}
|
style={[!isTabletOrDesktop && styles.flex1]}
|
||||||
data={blockedAccounts.blocks}
|
data={blockedAccounts.blocks}
|
||||||
keyExtractor={(item: ActorDefs.ProfileView) => item.did}
|
keyExtractor={(item: ActorDefs.ProfileView) => item.did}
|
||||||
refreshControl={
|
refreshControl={
|
||||||
|
@ -133,11 +134,12 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
paddingBottom: 100,
|
||||||
},
|
},
|
||||||
containerDesktop: {
|
containerDesktop: {
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -15,9 +15,9 @@ import {ListsList} from 'view/com/lists/ListsList'
|
||||||
import {Button} from 'view/com/util/forms/Button'
|
import {Button} from 'view/com/util/forms/Button'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {CenteredView} from 'view/com/util/Views'
|
import {CenteredView} from 'view/com/util/Views'
|
||||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<
|
type Props = NativeStackScreenProps<
|
||||||
CommonNavigatorParams,
|
CommonNavigatorParams,
|
||||||
|
@ -26,6 +26,7 @@ type Props = NativeStackScreenProps<
|
||||||
export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
const mutelists: ListsListModel = React.useMemo(
|
const mutelists: ListsListModel = React.useMemo(
|
||||||
|
@ -89,7 +90,7 @@ export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
||||||
styles.container,
|
styles.container,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
isDesktopWeb && styles.containerDesktop,
|
isTabletOrDesktop && styles.containerDesktop,
|
||||||
]}
|
]}
|
||||||
testID="moderationMutelistsScreen">
|
testID="moderationMutelistsScreen">
|
||||||
<ViewHeader
|
<ViewHeader
|
||||||
|
@ -99,7 +100,7 @@ export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
||||||
/>
|
/>
|
||||||
<ListsList
|
<ListsList
|
||||||
listsList={mutelists}
|
listsList={mutelists}
|
||||||
showAddBtns={isDesktopWeb}
|
showAddBtns={isTabletOrDesktop}
|
||||||
renderEmptyState={renderEmptyState}
|
renderEmptyState={renderEmptyState}
|
||||||
onPressCreateNew={onPressNewMuteList}
|
onPressCreateNew={onPressNewMuteList}
|
||||||
/>
|
/>
|
||||||
|
@ -110,11 +111,12 @@ export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
paddingBottom: 100,
|
||||||
},
|
},
|
||||||
containerDesktop: {
|
containerDesktop: {
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
createBtn: {
|
createBtn: {
|
||||||
width: 40,
|
width: 40,
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||||
import {Text} from '../com/util/text/Text'
|
import {Text} from '../com/util/text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
|
@ -30,6 +30,7 @@ export const ModerationMutedAccounts = withAuthRequired(
|
||||||
observer(({}: Props) => {
|
observer(({}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
const mutedAccounts = useMemo(() => new MutedAccountsModel(store), [store])
|
const mutedAccounts = useMemo(() => new MutedAccountsModel(store), [store])
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ export const ModerationMutedAccounts = withAuthRequired(
|
||||||
<CenteredView
|
<CenteredView
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
isDesktopWeb && styles.containerDesktop,
|
isTabletOrDesktop && styles.containerDesktop,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
]}
|
]}
|
||||||
|
@ -80,13 +81,13 @@ export const ModerationMutedAccounts = withAuthRequired(
|
||||||
style={[
|
style={[
|
||||||
styles.description,
|
styles.description,
|
||||||
pal.text,
|
pal.text,
|
||||||
isDesktopWeb && styles.descriptionDesktop,
|
isTabletOrDesktop && styles.descriptionDesktop,
|
||||||
]}>
|
]}>
|
||||||
Muted accounts have their posts removed from your feed and from your
|
Muted accounts have their posts removed from your feed and from your
|
||||||
notifications. Mutes are completely private.
|
notifications. Mutes are completely private.
|
||||||
</Text>
|
</Text>
|
||||||
{!mutedAccounts.hasContent ? (
|
{!mutedAccounts.hasContent ? (
|
||||||
<View style={[pal.border, !isDesktopWeb && styles.flex1]}>
|
<View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
|
||||||
<View style={[styles.empty, pal.viewLight]}>
|
<View style={[styles.empty, pal.viewLight]}>
|
||||||
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
||||||
You have not muted any accounts yet. To mute an account, go to
|
You have not muted any accounts yet. To mute an account, go to
|
||||||
|
@ -97,7 +98,7 @@ export const ModerationMutedAccounts = withAuthRequired(
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<FlatList
|
<FlatList
|
||||||
style={[!isDesktopWeb && styles.flex1]}
|
style={[!isTabletOrDesktop && styles.flex1]}
|
||||||
data={mutedAccounts.mutes}
|
data={mutedAccounts.mutes}
|
||||||
keyExtractor={item => item.did}
|
keyExtractor={item => item.did}
|
||||||
refreshControl={
|
refreshControl={
|
||||||
|
@ -129,11 +130,12 @@ export const ModerationMutedAccounts = withAuthRequired(
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
paddingBottom: 100,
|
||||||
},
|
},
|
||||||
containerDesktop: {
|
containerDesktop: {
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {useStores} from 'state/index'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {clamp} from 'lodash'
|
import {clamp} from 'lodash'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
const SHELL_FOOTER_HEIGHT = 44
|
const SHELL_FOOTER_HEIGHT = 44
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ export const PostThreadScreen = withAuthRequired(({route}: Props) => {
|
||||||
() => new PostThreadModel(store, {uri}),
|
() => new PostThreadModel(store, {uri}),
|
||||||
[store, uri],
|
[store, uri],
|
||||||
)
|
)
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
|
@ -67,15 +68,15 @@ export const PostThreadScreen = withAuthRequired(({route}: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={s.hContentRegion}>
|
<View style={s.hContentRegion}>
|
||||||
<ViewHeader title="Post" />
|
{isMobile && <ViewHeader title="Post" />}
|
||||||
<View style={s.hContentRegion}>
|
<View style={s.flex1}>
|
||||||
<PostThreadComponent
|
<PostThreadComponent
|
||||||
uri={uri}
|
uri={uri}
|
||||||
view={view}
|
view={view}
|
||||||
onPressReply={onPressReply}
|
onPressReply={onPressReply}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
{!isDesktopWeb && (
|
{isMobile && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.prompt,
|
styles.prompt,
|
||||||
|
|
|
@ -6,7 +6,8 @@ import {Text} from '../com/util/text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
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 {isWeb, isDesktopWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||||
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
|
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
|
||||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||||
|
@ -50,6 +51,7 @@ type Props = NativeStackScreenProps<
|
||||||
export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredView
|
<CenteredView
|
||||||
|
@ -58,10 +60,11 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
styles.container,
|
styles.container,
|
||||||
isDesktopWeb && styles.desktopContainer,
|
isTabletOrDesktop && styles.desktopContainer,
|
||||||
]}>
|
]}>
|
||||||
<ViewHeader title="Home Feed Preferences" showOnDesktop />
|
<ViewHeader title="Home Feed Preferences" showOnDesktop />
|
||||||
<View style={styles.titleSection}>
|
<View
|
||||||
|
style={[styles.titleSection, isTabletOrDesktop && {paddingTop: 20}]}>
|
||||||
<Text type="xl" style={[pal.textLight, styles.description]}>
|
<Text type="xl" style={[pal.textLight, styles.description]}>
|
||||||
Fine-tune the content you see on your home screen.
|
Fine-tune the content you see on your home screen.
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -122,7 +125,12 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<View style={[styles.btnContainer, pal.borderDark]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.btnContainer,
|
||||||
|
!isTabletOrDesktop && {borderTopWidth: 1, paddingHorizontal: 20},
|
||||||
|
pal.borderDark,
|
||||||
|
]}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="confirmBtn"
|
testID="confirmBtn"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
@ -130,7 +138,7 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
||||||
? navigation.goBack()
|
? navigation.goBack()
|
||||||
: navigation.navigate('Settings')
|
: navigation.navigate('Settings')
|
||||||
}}
|
}}
|
||||||
style={[styles.btn, isDesktopWeb && styles.btnDesktop]}
|
style={[styles.btn, isTabletOrDesktop && styles.btnDesktop]}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel="Confirm"
|
accessibilityLabel="Confirm"
|
||||||
accessibilityHint="">
|
accessibilityHint="">
|
||||||
|
@ -144,15 +152,15 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 40 : 90,
|
paddingBottom: 90,
|
||||||
},
|
},
|
||||||
desktopContainer: {
|
desktopContainer: {
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
|
paddingBottom: 40,
|
||||||
},
|
},
|
||||||
titleSection: {
|
titleSection: {
|
||||||
paddingBottom: 30,
|
paddingBottom: 30,
|
||||||
paddingTop: isDesktopWeb ? 20 : 0,
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
@ -184,7 +192,6 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
btnContainer: {
|
btnContainer: {
|
||||||
paddingTop: 20,
|
paddingTop: 20,
|
||||||
borderTopWidth: isDesktopWeb ? 0 : 1,
|
|
||||||
},
|
},
|
||||||
dimmed: {
|
dimmed: {
|
||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
|
|
|
@ -14,8 +14,8 @@ import {ListModel} from 'state/models/content/list'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
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 {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||||
import {shareUrl} from 'lib/sharing'
|
import {shareUrl} from 'lib/sharing'
|
||||||
import {ListActions} from 'view/com/lists/ListActions'
|
import {ListActions} from 'view/com/lists/ListActions'
|
||||||
|
@ -26,6 +26,7 @@ export const ProfileListScreen = withAuthRequired(
|
||||||
observer(({route}: Props) => {
|
observer(({route}: Props) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {name, rkey} = route.params
|
const {name, rkey} = route.params
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ export const ProfileListScreen = withAuthRequired(
|
||||||
<CenteredView
|
<CenteredView
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
isDesktopWeb && styles.containerDesktop,
|
isTabletOrDesktop && styles.containerDesktop,
|
||||||
pal.view,
|
pal.view,
|
||||||
pal.border,
|
pal.border,
|
||||||
]}
|
]}
|
||||||
|
@ -155,10 +156,11 @@ export const ProfileListScreen = withAuthRequired(
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
paddingBottom: 100,
|
||||||
},
|
},
|
||||||
containerDesktop: {
|
containerDesktop: {
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,11 +14,12 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||||
import {CenteredView} from 'view/com/util/Views'
|
import {CenteredView} from 'view/com/util/Views'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {isDesktopWeb, isWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import DraggableFlatList, {
|
import DraggableFlatList, {
|
||||||
ShadowDecorator,
|
ShadowDecorator,
|
||||||
|
@ -37,6 +38,7 @@ export const SavedFeeds = withAuthRequired(
|
||||||
observer(({}: Props) => {
|
observer(({}: Props) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
|
|
||||||
const savedFeeds = useMemo(() => store.me.savedFeeds, [store])
|
const savedFeeds = useMemo(() => store.me.savedFeeds, [store])
|
||||||
|
@ -53,7 +55,7 @@ export const SavedFeeds = withAuthRequired(
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
pal.border,
|
pal.border,
|
||||||
!isDesktopWeb && s.flex1,
|
isMobile && s.flex1,
|
||||||
pal.viewLight,
|
pal.viewLight,
|
||||||
styles.empty,
|
styles.empty,
|
||||||
]}>
|
]}>
|
||||||
|
@ -62,7 +64,7 @@ export const SavedFeeds = withAuthRequired(
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}, [pal])
|
}, [pal, isMobile])
|
||||||
|
|
||||||
const renderListFooterComponent = useCallback(() => {
|
const renderListFooterComponent = useCallback(() => {
|
||||||
return (
|
return (
|
||||||
|
@ -116,15 +118,11 @@ export const SavedFeeds = withAuthRequired(
|
||||||
style={[
|
style={[
|
||||||
s.hContentRegion,
|
s.hContentRegion,
|
||||||
pal.border,
|
pal.border,
|
||||||
isDesktopWeb && styles.desktopContainer,
|
isTabletOrDesktop && styles.desktopContainer,
|
||||||
]}>
|
]}>
|
||||||
<ViewHeader
|
<ViewHeader title="Edit My Feeds" showOnDesktop showBorder />
|
||||||
title="Edit My Feeds"
|
|
||||||
showOnDesktop
|
|
||||||
showBorder={!isDesktopWeb}
|
|
||||||
/>
|
|
||||||
<DraggableFlatList
|
<DraggableFlatList
|
||||||
containerStyle={[isDesktopWeb ? s.hContentRegion : s.flex1]}
|
containerStyle={[isTabletOrDesktop ? s.hContentRegion : s.flex1]}
|
||||||
data={savedFeeds.all}
|
data={savedFeeds.all}
|
||||||
keyExtractor={item => item.data.uri}
|
keyExtractor={item => item.data.uri}
|
||||||
refreshing={savedFeeds.isRefreshing}
|
refreshing={savedFeeds.isRefreshing}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
SearchTabNavigatorParams,
|
SearchTabNavigatorParams,
|
||||||
} from 'lib/routes/types'
|
} from 'lib/routes/types'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {CenteredView} from 'view/com/util/Views'
|
||||||
import * as Mobile from './SearchMobile'
|
import * as Mobile from './SearchMobile'
|
||||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
|
@ -57,9 +58,9 @@ export const SearchScreen = withAuthRequired(
|
||||||
|
|
||||||
if (!isDesktop) {
|
if (!isDesktop) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.scrollContainer}>
|
<CenteredView style={styles.scrollContainer}>
|
||||||
<Mobile.SearchScreen navigation={navigation} route={route} />
|
<Mobile.SearchScreen navigation={navigation} route={route} />
|
||||||
</View>
|
</CenteredView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||||
import {SelectableBtn} from 'view/com/util/forms/SelectableBtn'
|
import {SelectableBtn} from 'view/com/util/forms/SelectableBtn'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {AccountData} from 'state/models/session'
|
import {AccountData} from 'state/models/session'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
|
||||||
import {pluralize} from 'lib/strings/helpers'
|
import {pluralize} from 'lib/strings/helpers'
|
||||||
import {formatCount} from 'view/com/util/numeric/format'
|
import {formatCount} from 'view/com/util/numeric/format'
|
||||||
import Clipboard from '@react-native-clipboard/clipboard'
|
import Clipboard from '@react-native-clipboard/clipboard'
|
||||||
|
@ -58,6 +58,7 @@ export const SettingsScreen = withAuthRequired(
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
const {screen, track} = useAnalytics()
|
const {screen, track} = useAnalytics()
|
||||||
const [isSwitching, setIsSwitching] = React.useState(false)
|
const [isSwitching, setIsSwitching] = React.useState(false)
|
||||||
const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(
|
const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(
|
||||||
|
@ -203,7 +204,7 @@ export const SettingsScreen = withAuthRequired(
|
||||||
<ViewHeader title="Settings" />
|
<ViewHeader title="Settings" />
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={[s.hContentRegion]}
|
style={[s.hContentRegion]}
|
||||||
contentContainerStyle={!isDesktopWeb && pal.viewLight}
|
contentContainerStyle={isMobile && pal.viewLight}
|
||||||
scrollIndicatorInsets={{right: 1}}>
|
scrollIndicatorInsets={{right: 1}}>
|
||||||
<View style={styles.spacer20} />
|
<View style={styles.spacer20} />
|
||||||
{store.session.currentSession !== undefined ? (
|
{store.session.currentSession !== undefined ? (
|
||||||
|
@ -508,7 +509,7 @@ export const SettingsScreen = withAuthRequired(
|
||||||
System log
|
System log
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{isDesktopWeb || __DEV__ ? (
|
{__DEV__ ? (
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
type="default-light"
|
type="default-light"
|
||||||
label="Experiment: Use AppView Proxy"
|
label="Experiment: Use AppView Proxy"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {StyleSheet, View} from 'react-native'
|
||||||
import {ComposePost} from '../com/composer/Composer'
|
import {ComposePost} from '../com/composer/Composer'
|
||||||
import {ComposerOpts} from 'state/models/ui/shell'
|
import {ComposerOpts} from 'state/models/ui/shell'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {isMobileWeb} from 'platform/detection'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
|
|
||||||
const BOTTOM_BAR_HEIGHT = 61
|
const BOTTOM_BAR_HEIGHT = 61
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ export const Composer = observer(
|
||||||
mention?: ComposerOpts['mention']
|
mention?: ComposerOpts['mention']
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isMobile} = useWebMediaQueries()
|
||||||
|
|
||||||
// rendering
|
// rendering
|
||||||
// =
|
// =
|
||||||
|
@ -36,7 +37,13 @@ export const Composer = observer(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.mask} aria-modal accessibilityViewIsModal>
|
<View style={styles.mask} aria-modal accessibilityViewIsModal>
|
||||||
<View style={[styles.container, pal.view, pal.border]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.container,
|
||||||
|
isMobile && styles.containerMobile,
|
||||||
|
pal.view,
|
||||||
|
pal.border,
|
||||||
|
]}>
|
||||||
<ComposePost
|
<ComposePost
|
||||||
replyTo={replyTo}
|
replyTo={replyTo}
|
||||||
quote={quote}
|
quote={quote}
|
||||||
|
@ -66,11 +73,14 @@ const styles = StyleSheet.create({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
paddingVertical: 0,
|
paddingVertical: 0,
|
||||||
paddingHorizontal: 2,
|
paddingHorizontal: 2,
|
||||||
borderRadius: isMobileWeb ? 0 : 8,
|
borderRadius: 8,
|
||||||
marginBottom: isMobileWeb ? BOTTOM_BAR_HEIGHT : 0,
|
marginBottom: 0,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
maxHeight: isMobileWeb
|
maxHeight: 'calc(100% - (40px * 2))',
|
||||||
? `calc(100% - ${BOTTOM_BAR_HEIGHT}px)`
|
},
|
||||||
: 'calc(100% - (40px * 2))',
|
containerMobile: {
|
||||||
|
borderRadius: 0,
|
||||||
|
marginBottom: BOTTOM_BAR_HEIGHT,
|
||||||
|
maxHeight: `calc(100% - ${BOTTOM_BAR_HEIGHT}px)`,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {Link} from 'view/com/util/Link'
|
||||||
import {LoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
|
import {LoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {
|
import {
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
|
@ -41,18 +42,28 @@ import {makeProfileLink} from 'lib/routes/links'
|
||||||
|
|
||||||
const ProfileCard = observer(() => {
|
const ProfileCard = observer(() => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isDesktop} = useWebMediaQueries()
|
||||||
|
const size = isDesktop ? 64 : 48
|
||||||
return store.me.handle ? (
|
return store.me.handle ? (
|
||||||
<Link href={makeProfileLink(store.me)} style={styles.profileCard} asAnchor>
|
<Link
|
||||||
<UserAvatar avatar={store.me.avatar} size={64} />
|
href={makeProfileLink(store.me)}
|
||||||
|
style={[styles.profileCard, !isDesktop && styles.profileCardTablet]}
|
||||||
|
asAnchor>
|
||||||
|
<UserAvatar avatar={store.me.avatar} size={size} />
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<View style={styles.profileCard}>
|
<View style={[styles.profileCard, !isDesktop && styles.profileCardTablet]}>
|
||||||
<LoadingPlaceholder width={64} height={64} style={{borderRadius: 64}} />
|
<LoadingPlaceholder
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
style={{borderRadius: size}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
function BackBtn() {
|
function BackBtn() {
|
||||||
|
const {isTablet} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const shouldShow = useNavigationState(state => !isStateAtTabRoot(state))
|
const shouldShow = useNavigationState(state => !isStateAtTabRoot(state))
|
||||||
|
@ -65,7 +76,7 @@ function BackBtn() {
|
||||||
}
|
}
|
||||||
}, [navigation])
|
}, [navigation])
|
||||||
|
|
||||||
if (!shouldShow) {
|
if (!shouldShow || isTablet) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -96,6 +107,7 @@ const NavItem = observer(
|
||||||
({count, href, icon, iconFilled, label}: NavItemProps) => {
|
({count, href, icon, iconFilled, label}: NavItemProps) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const {isDesktop, isTablet} = useWebMediaQueries()
|
||||||
const [pathName] = React.useMemo(() => router.matchPath(href), [href])
|
const [pathName] = React.useMemo(() => router.matchPath(href), [href])
|
||||||
const currentRouteInfo = useNavigationState(state => {
|
const currentRouteInfo = useNavigationState(state => {
|
||||||
if (!state) {
|
if (!state) {
|
||||||
|
@ -137,17 +149,28 @@ const NavItem = observer(
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={label}
|
accessibilityLabel={label}
|
||||||
accessibilityHint="">
|
accessibilityHint="">
|
||||||
<View style={[styles.navItemIconWrapper]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.navItemIconWrapper,
|
||||||
|
isTablet && styles.navItemIconWrapperTablet,
|
||||||
|
]}>
|
||||||
{isCurrent ? iconFilled : icon}
|
{isCurrent ? iconFilled : icon}
|
||||||
{typeof count === 'string' && count ? (
|
{typeof count === 'string' && count ? (
|
||||||
<Text type="button" style={styles.navItemCount}>
|
<Text
|
||||||
|
type="button"
|
||||||
|
style={[
|
||||||
|
styles.navItemCount,
|
||||||
|
isTablet && styles.navItemCountTablet,
|
||||||
|
]}>
|
||||||
{count}
|
{count}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
|
{isDesktop && (
|
||||||
<Text type="title" style={[isCurrent ? s.bold : s.normal, pal.text]}>
|
<Text type="title" style={[isCurrent ? s.bold : s.normal, pal.text]}>
|
||||||
{label}
|
{label}
|
||||||
</Text>
|
</Text>
|
||||||
|
)}
|
||||||
</PressableWithHover>
|
</PressableWithHover>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -156,6 +179,7 @@ const NavItem = observer(
|
||||||
function ComposeBtn() {
|
function ComposeBtn() {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const {getState} = useNavigation()
|
const {getState} = useNavigation()
|
||||||
|
const {isTablet} = useWebMediaQueries()
|
||||||
|
|
||||||
const getProfileHandle = () => {
|
const getProfileHandle = () => {
|
||||||
const {routes} = getState()
|
const {routes} = getState()
|
||||||
|
@ -172,6 +196,9 @@ function ComposeBtn() {
|
||||||
const onPressCompose = () =>
|
const onPressCompose = () =>
|
||||||
store.shell.openComposer({mention: getProfileHandle()})
|
store.shell.openComposer({mention: getProfileHandle()})
|
||||||
|
|
||||||
|
if (isTablet) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.newPostBtn]}
|
style={[styles.newPostBtn]}
|
||||||
|
@ -196,28 +223,43 @@ function ComposeBtn() {
|
||||||
export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {isDesktop, isTablet} = useWebMediaQueries()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.leftNav, pal.view]}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.leftNav,
|
||||||
|
isTablet && styles.leftNavTablet,
|
||||||
|
pal.view,
|
||||||
|
pal.border,
|
||||||
|
]}>
|
||||||
{store.session.hasSession && <ProfileCard />}
|
{store.session.hasSession && <ProfileCard />}
|
||||||
<BackBtn />
|
<BackBtn />
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/"
|
href="/"
|
||||||
icon={<HomeIcon size={24} style={pal.text} />}
|
icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<HomeIconSolid strokeWidth={4} size={24} style={pal.text} />
|
<HomeIconSolid
|
||||||
|
strokeWidth={4}
|
||||||
|
size={isDesktop ? 24 : 28}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
label="Home"
|
label="Home"
|
||||||
/>
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/search"
|
href="/search"
|
||||||
icon={
|
icon={
|
||||||
<MagnifyingGlassIcon2 strokeWidth={2} size={24} style={pal.text} />
|
<MagnifyingGlassIcon2
|
||||||
|
strokeWidth={2}
|
||||||
|
size={isDesktop ? 24 : 26}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<MagnifyingGlassIcon2Solid
|
<MagnifyingGlassIcon2Solid
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
size={24}
|
size={isDesktop ? 24 : 26}
|
||||||
style={pal.text}
|
style={pal.text}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -229,14 +271,14 @@ export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
||||||
<SatelliteDishIcon
|
<SatelliteDishIcon
|
||||||
strokeWidth={1.75}
|
strokeWidth={1.75}
|
||||||
style={pal.text as FontAwesomeIconStyle}
|
style={pal.text as FontAwesomeIconStyle}
|
||||||
size={24}
|
size={isDesktop ? 24 : 28}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<SatelliteDishIconSolid
|
<SatelliteDishIconSolid
|
||||||
strokeWidth={1.75}
|
strokeWidth={1.75}
|
||||||
style={pal.text as FontAwesomeIconStyle}
|
style={pal.text as FontAwesomeIconStyle}
|
||||||
size={24}
|
size={isDesktop ? 24 : 28}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="My Feeds"
|
label="My Feeds"
|
||||||
|
@ -244,9 +286,19 @@ export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/notifications"
|
href="/notifications"
|
||||||
count={store.me.notifications.unreadCountLabel}
|
count={store.me.notifications.unreadCountLabel}
|
||||||
icon={<BellIcon strokeWidth={2} size={24} style={pal.text} />}
|
icon={
|
||||||
|
<BellIcon
|
||||||
|
strokeWidth={2}
|
||||||
|
size={isDesktop ? 24 : 26}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
|
}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<BellIconSolid strokeWidth={1.5} size={24} style={pal.text} />
|
<BellIconSolid
|
||||||
|
strokeWidth={1.5}
|
||||||
|
size={isDesktop ? 24 : 26}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
label="Notifications"
|
label="Notifications"
|
||||||
/>
|
/>
|
||||||
|
@ -256,14 +308,14 @@ export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
||||||
<HandIcon
|
<HandIcon
|
||||||
strokeWidth={5.5}
|
strokeWidth={5.5}
|
||||||
style={pal.text as FontAwesomeIconStyle}
|
style={pal.text as FontAwesomeIconStyle}
|
||||||
size={24}
|
size={isDesktop ? 24 : 27}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon="hand"
|
icon="hand"
|
||||||
style={pal.text as FontAwesomeIconStyle}
|
style={pal.text as FontAwesomeIconStyle}
|
||||||
size={20}
|
size={isDesktop ? 20 : 26}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="Moderation"
|
label="Moderation"
|
||||||
|
@ -271,18 +323,38 @@ export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
||||||
{store.session.hasSession && (
|
{store.session.hasSession && (
|
||||||
<NavItem
|
<NavItem
|
||||||
href={makeProfileLink(store.me)}
|
href={makeProfileLink(store.me)}
|
||||||
icon={<UserIcon strokeWidth={1.75} size={28} style={pal.text} />}
|
icon={
|
||||||
|
<UserIcon
|
||||||
|
strokeWidth={1.75}
|
||||||
|
size={isDesktop ? 28 : 30}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
|
}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<UserIconSolid strokeWidth={1.75} size={28} style={pal.text} />
|
<UserIconSolid
|
||||||
|
strokeWidth={1.75}
|
||||||
|
size={isDesktop ? 28 : 30}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
label="Profile"
|
label="Profile"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<NavItem
|
<NavItem
|
||||||
href="/settings"
|
href="/settings"
|
||||||
icon={<CogIcon strokeWidth={1.75} size={28} style={pal.text} />}
|
icon={
|
||||||
|
<CogIcon
|
||||||
|
strokeWidth={1.75}
|
||||||
|
size={isDesktop ? 28 : 32}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
|
}
|
||||||
iconFilled={
|
iconFilled={
|
||||||
<CogIconSolid strokeWidth={1.5} size={28} style={pal.text} />
|
<CogIconSolid
|
||||||
|
strokeWidth={1.5}
|
||||||
|
size={isDesktop ? 28 : 32}
|
||||||
|
style={pal.text}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
label="Settings"
|
label="Settings"
|
||||||
/>
|
/>
|
||||||
|
@ -300,12 +372,24 @@ const styles = StyleSheet.create({
|
||||||
maxHeight: 'calc(100vh - 10px)',
|
maxHeight: 'calc(100vh - 10px)',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
},
|
},
|
||||||
|
leftNavTablet: {
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 'auto',
|
||||||
|
borderRightWidth: 1,
|
||||||
|
height: '100%',
|
||||||
|
width: 76,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
|
||||||
profileCard: {
|
profileCard: {
|
||||||
marginVertical: 10,
|
marginVertical: 10,
|
||||||
width: 90,
|
width: 90,
|
||||||
paddingLeft: 12,
|
paddingLeft: 12,
|
||||||
},
|
},
|
||||||
|
profileCardTablet: {
|
||||||
|
width: 70,
|
||||||
|
},
|
||||||
|
|
||||||
backBtn: {
|
backBtn: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -330,6 +414,10 @@ const styles = StyleSheet.create({
|
||||||
height: 28,
|
height: 28,
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
},
|
},
|
||||||
|
navItemIconWrapperTablet: {
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
},
|
||||||
navItemCount: {
|
navItemCount: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
|
@ -341,6 +429,10 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 4,
|
paddingHorizontal: 4,
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
},
|
},
|
||||||
|
navItemCountTablet: {
|
||||||
|
left: 18,
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
|
||||||
newPostBtn: {
|
newPostBtn: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
@ -354,10 +446,9 @@ const styles = StyleSheet.create({
|
||||||
marginLeft: 12,
|
marginLeft: 12,
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
|
gap: 8,
|
||||||
},
|
},
|
||||||
newPostBtnIconWrapper: {
|
newPostBtnIconWrapper: {},
|
||||||
marginRight: 8,
|
|
||||||
},
|
|
||||||
newPostBtnLabel: {
|
newPostBtnLabel: {
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {TextLink} from 'view/com/util/Link'
|
||||||
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
|
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {pluralize} from 'lib/strings/helpers'
|
import {pluralize} from 'lib/strings/helpers'
|
||||||
import {formatCount} from 'view/com/util/numeric/format'
|
import {formatCount} from 'view/com/util/numeric/format'
|
||||||
|
|
||||||
|
@ -17,6 +18,11 @@ export const DesktopRightNav = observer(function DesktopRightNav() {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const palError = usePalette('error')
|
const palError = usePalette('error')
|
||||||
|
|
||||||
|
const {isTablet} = useWebMediaQueries()
|
||||||
|
if (isTablet) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.rightNav, pal.view]}>
|
<View style={[styles.rightNav, pal.view]}>
|
||||||
{store.session.hasSession && <DesktopSearch />}
|
{store.session.hasSession && <DesktopSearch />}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {NavigationProp} from 'lib/routes/types'
|
||||||
|
|
||||||
const ShellInner = observer(() => {
|
const ShellInner = observer(() => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const {isDesktop} = useWebMediaQueries()
|
const {isDesktop, isMobile} = useWebMediaQueries()
|
||||||
const navigator = useNavigation<NavigationProp>()
|
const navigator = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -28,11 +28,11 @@ const ShellInner = observer(() => {
|
||||||
})
|
})
|
||||||
}, [navigator, store.shell])
|
}, [navigator, store.shell])
|
||||||
|
|
||||||
const showBottomBar = !isDesktop && !store.onboarding.isActive
|
const showBottomBar = isMobile && !store.onboarding.isActive
|
||||||
const showSideNavs =
|
const showSideNavs =
|
||||||
isDesktop && store.session.hasSession && !store.onboarding.isActive
|
!isMobile && store.session.hasSession && !store.onboarding.isActive
|
||||||
return (
|
return (
|
||||||
<>
|
<View style={[s.hContentRegion, {overflow: 'hidden'}]}>
|
||||||
<View style={s.hContentRegion}>
|
<View style={s.hContentRegion}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<FlatNavigator />
|
<FlatNavigator />
|
||||||
|
@ -67,7 +67,7 @@ const ShellInner = observer(() => {
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
</>
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue