Updates to use dynamic/responsive styles on web (#1351)
* Move most responsive queries to the hook * Fix invalid CSS value * Fixes to tablet render of post thread * Fix overflow issues on web * Fix search header on tablet * Fix QP margin in web composer * Fix: only apply double gutter once to flatlist (close #1368) * Fix styles on discover feeds header * Fix double discover links in multifeed
This commit is contained in:
parent
be8084ae10
commit
764c7cd569
63 changed files with 762 additions and 461 deletions
|
@ -7,7 +7,7 @@ import {Button} from '../com/util/forms/Button'
|
|||
import * as Toast from '../com/util/Toast'
|
||||
import {useStores} from 'state/index'
|
||||
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 {observer} from 'mobx-react-lite'
|
||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||
|
@ -23,6 +23,7 @@ export const AppPasswords = withAuthRequired(
|
|||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {screen} = useAnalytics()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
|
@ -41,7 +42,7 @@ export const AppPasswords = withAuthRequired(
|
|||
<CenteredView
|
||||
style={[
|
||||
styles.container,
|
||||
isDesktopWeb && styles.containerDesktop,
|
||||
isTabletOrDesktop && styles.containerDesktop,
|
||||
pal.view,
|
||||
pal.border,
|
||||
]}
|
||||
|
@ -53,11 +54,11 @@ export const AppPasswords = withAuthRequired(
|
|||
pressing the button below.
|
||||
</Text>
|
||||
</View>
|
||||
{!isDesktopWeb && <View style={styles.flex1} />}
|
||||
{!isTabletOrDesktop && <View style={styles.flex1} />}
|
||||
<View
|
||||
style={[
|
||||
styles.btnContainer,
|
||||
isDesktopWeb && styles.btnContainerDesktop,
|
||||
isTabletOrDesktop && styles.btnContainerDesktop,
|
||||
]}>
|
||||
<Button
|
||||
testID="appPasswordBtn"
|
||||
|
@ -77,7 +78,7 @@ export const AppPasswords = withAuthRequired(
|
|||
<CenteredView
|
||||
style={[
|
||||
styles.container,
|
||||
isDesktopWeb && styles.containerDesktop,
|
||||
isTabletOrDesktop && styles.containerDesktop,
|
||||
pal.view,
|
||||
pal.border,
|
||||
]}
|
||||
|
@ -87,7 +88,7 @@ export const AppPasswords = withAuthRequired(
|
|||
style={[
|
||||
styles.scrollContainer,
|
||||
pal.border,
|
||||
!isDesktopWeb && styles.flex1,
|
||||
!isTabletOrDesktop && styles.flex1,
|
||||
]}>
|
||||
{store.me.appPasswords.map((password, i) => (
|
||||
<AppPassword
|
||||
|
@ -97,7 +98,7 @@ export const AppPasswords = withAuthRequired(
|
|||
createdAt={password.createdAt}
|
||||
/>
|
||||
))}
|
||||
{isDesktopWeb && (
|
||||
{isTabletOrDesktop && (
|
||||
<View style={[styles.btnContainer, styles.btnContainerDesktop]}>
|
||||
<Button
|
||||
testID="appPasswordBtn"
|
||||
|
@ -110,7 +111,7 @@ export const AppPasswords = withAuthRequired(
|
|||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
{!isDesktopWeb && (
|
||||
{!isTabletOrDesktop && (
|
||||
<View style={styles.btnContainer}>
|
||||
<Button
|
||||
testID="appPasswordBtn"
|
||||
|
@ -128,6 +129,7 @@ export const AppPasswords = withAuthRequired(
|
|||
)
|
||||
|
||||
function AppPasswordsHeader() {
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const pal = usePalette('default')
|
||||
return (
|
||||
<>
|
||||
|
@ -137,7 +139,7 @@ function AppPasswordsHeader() {
|
|||
style={[
|
||||
styles.description,
|
||||
pal.text,
|
||||
isDesktopWeb && styles.descriptionDesktop,
|
||||
isTabletOrDesktop && styles.descriptionDesktop,
|
||||
]}>
|
||||
Use app passwords to login to other Bluesky clients without giving full
|
||||
access to your account or password.
|
||||
|
@ -207,11 +209,12 @@ function AppPassword({
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
containerDesktop: {
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
|
|
|
@ -22,7 +22,7 @@ import {ViewHeader} from 'view/com/util/ViewHeader'
|
|||
import {Button} from 'view/com/util/forms/Button'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
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 {shareUrl} from 'lib/sharing'
|
||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||
|
@ -122,6 +122,7 @@ export const CustomFeedScreenInner = observer(
|
|||
({route, feedOwnerDid}: Props & {feedOwnerDid: string}) => {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const {track} = useAnalytics()
|
||||
const {rkey, name: handleOrDid} = route.params
|
||||
const uri = useMemo(
|
||||
|
@ -357,7 +358,7 @@ export const CustomFeedScreenInner = observer(
|
|||
)}
|
||||
</Text>
|
||||
)}
|
||||
{isDesktopWeb && (
|
||||
{isTabletOrDesktop && (
|
||||
<View style={[styles.headerBtns, styles.headerBtnsDesktop]}>
|
||||
<Button
|
||||
type={currentFeed?.isSaved ? 'default' : 'inverted'}
|
||||
|
@ -452,7 +453,14 @@ export const CustomFeedScreenInner = observer(
|
|||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
<View style={[styles.fakeSelector, pal.border]}>
|
||||
<View
|
||||
style={[
|
||||
styles.fakeSelector,
|
||||
{
|
||||
paddingHorizontal: isTabletOrDesktop ? 16 : 6,
|
||||
},
|
||||
pal.border,
|
||||
]}>
|
||||
<View
|
||||
style={[styles.fakeSelectorItem, {borderColor: pal.colors.link}]}>
|
||||
<Text type="md-medium" style={[pal.text]}>
|
||||
|
@ -474,6 +482,7 @@ export const CustomFeedScreenInner = observer(
|
|||
rkey,
|
||||
isPinned,
|
||||
onTogglePinned,
|
||||
isTabletOrDesktop,
|
||||
])
|
||||
|
||||
const renderEmptyState = React.useCallback(() => {
|
||||
|
@ -486,7 +495,9 @@ export const CustomFeedScreenInner = observer(
|
|||
|
||||
return (
|
||||
<View style={s.hContentRegion}>
|
||||
<ViewHeader title="" renderButton={currentFeed && renderHeaderBtns} />
|
||||
{!isTabletOrDesktop && (
|
||||
<ViewHeader title="" renderButton={currentFeed && renderHeaderBtns} />
|
||||
)}
|
||||
<Feed
|
||||
scrollElRef={scrollElRef}
|
||||
feed={algoFeed}
|
||||
|
@ -495,6 +506,7 @@ export const CustomFeedScreenInner = observer(
|
|||
ListHeaderComponent={renderListHeaderComponent}
|
||||
renderEmptyState={renderEmptyState}
|
||||
extraData={[uri, isPinned]}
|
||||
style={!isTabletOrDesktop ? {flex: 1} : undefined}
|
||||
/>
|
||||
{isScrolledDown ? (
|
||||
<LoadLatestBtn
|
||||
|
@ -550,7 +562,6 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
fakeSelector: {
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: isDesktopWeb ? 16 : 6,
|
||||
},
|
||||
fakeSelectorItem: {
|
||||
paddingHorizontal: 12,
|
||||
|
|
|
@ -10,8 +10,8 @@ import {FeedsDiscoveryModel} from 'state/models/discovery/feeds'
|
|||
import {CenteredView, FlatList} from 'view/com/util/Views'
|
||||
import {CustomFeed} from 'view/com/feeds/CustomFeed'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {s} from 'lib/styles'
|
||||
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
||||
import {HeaderWithInput} from 'view/com/search/HeaderWithInput'
|
||||
|
@ -23,6 +23,7 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
|||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const feeds = React.useMemo(() => new FeedsDiscoveryModel(store), [store])
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
|
||||
// search stuff
|
||||
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)
|
||||
|
@ -74,7 +75,7 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
|||
<View style={styles.empty}>
|
||||
<Text type="lg" style={pal.textLight}>
|
||||
{feeds.isLoading
|
||||
? isDesktopWeb
|
||||
? isTabletOrDesktop
|
||||
? 'Loading...'
|
||||
: ''
|
||||
: query
|
||||
|
@ -100,23 +101,22 @@ export const DiscoverFeedsScreen = withAuthRequired(
|
|||
|
||||
return (
|
||||
<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 />
|
||||
<View style={{marginTop: isDesktopWeb ? 5 : 0, marginBottom: 4}}>
|
||||
<HeaderWithInput
|
||||
isInputFocused={isInputFocused}
|
||||
query={query}
|
||||
setIsInputFocused={setIsInputFocused}
|
||||
onChangeQuery={onChangeQuery}
|
||||
onPressClearQuery={onPressClearQuery}
|
||||
onPressCancelSearch={onPressCancelSearch}
|
||||
onSubmitQuery={onSubmitQuery}
|
||||
showMenu={false}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<HeaderWithInput
|
||||
isInputFocused={isInputFocused}
|
||||
query={query}
|
||||
setIsInputFocused={setIsInputFocused}
|
||||
onChangeQuery={onChangeQuery}
|
||||
onPressClearQuery={onPressClearQuery}
|
||||
onPressCancelSearch={onPressCancelSearch}
|
||||
onSubmitQuery={onSubmitQuery}
|
||||
showMenu={false}
|
||||
/>
|
||||
<FlatList
|
||||
style={[!isDesktopWeb && s.flex1]}
|
||||
style={[!isTabletOrDesktop && s.flex1]}
|
||||
data={feeds.feeds}
|
||||
keyExtractor={item => item.data.uri}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
|
|
|
@ -12,22 +12,23 @@ import {NativeStackScreenProps, FeedsTabNavigatorParams} from 'lib/routes/types'
|
|||
import {observer} from 'mobx-react-lite'
|
||||
import {PostsMultiFeedModel} from 'state/models/feeds/multi-feed'
|
||||
import {MultiFeed} from 'view/com/posts/MultiFeed'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useTimer} from 'lib/hooks/useTimer'
|
||||
import {useStores} from 'state/index'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||
import {ComposeIcon2, CogIcon} from 'lib/icons'
|
||||
import {s} from 'lib/styles'
|
||||
|
||||
const LOAD_NEW_PROMPT_TIME = 60e3 // 60 seconds
|
||||
const HEADER_OFFSET = isDesktopWeb ? 0 : 40
|
||||
const MOBILE_HEADER_OFFSET = 40
|
||||
|
||||
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
||||
export const FeedsScreen = withAuthRequired(
|
||||
observer<Props>(({}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const flatListRef = React.useRef<FlatList>(null)
|
||||
const multifeed = React.useMemo<PostsMultiFeedModel>(
|
||||
() => new PostsMultiFeedModel(store),
|
||||
|
@ -105,14 +106,16 @@ export const FeedsScreen = withAuthRequired(
|
|||
multifeed={multifeed}
|
||||
onScroll={onMainScroll}
|
||||
scrollEventThrottle={100}
|
||||
headerOffset={HEADER_OFFSET}
|
||||
/>
|
||||
<ViewHeader
|
||||
title="My Feeds"
|
||||
canGoBack={false}
|
||||
hideOnScroll
|
||||
renderButton={renderHeaderBtn}
|
||||
headerOffset={isMobile ? MOBILE_HEADER_OFFSET : undefined}
|
||||
/>
|
||||
{isMobile && (
|
||||
<ViewHeader
|
||||
title="My Feeds"
|
||||
canGoBack={false}
|
||||
hideOnScroll
|
||||
renderButton={renderHeaderBtn}
|
||||
/>
|
||||
)}
|
||||
{isScrolledDown || loadPromptVisible ? (
|
||||
<LoadLatestBtn
|
||||
onPress={onSoftReset}
|
||||
|
|
|
@ -19,14 +19,11 @@ import {useStores} from 'state/index'
|
|||
import {s} from 'lib/styles'
|
||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {ComposeIcon2} from 'lib/icons'
|
||||
import {isDesktopWeb, isMobileWebMediaQuery, isWeb} from 'platform/detection'
|
||||
|
||||
const HEADER_OFFSET_MOBILE = 78
|
||||
const HEADER_OFFSET_DESKTOP = 50
|
||||
const HEADER_OFFSET = isDesktopWeb
|
||||
? HEADER_OFFSET_DESKTOP
|
||||
: HEADER_OFFSET_MOBILE
|
||||
const POLL_FREQ = 30e3 // 30sec
|
||||
|
||||
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
|
||||
|
@ -158,10 +155,13 @@ const FeedPage = observer(
|
|||
renderEmptyState?: () => JSX.Element
|
||||
}) => {
|
||||
const store = useStores()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const [onMainScroll, isScrolledDown, resetMainScroll] =
|
||||
useOnMainScroll(store)
|
||||
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 {appState} = useAppState({
|
||||
onForeground: () => doPoll(true),
|
||||
|
@ -206,15 +206,9 @@ const FeedPage = observer(
|
|||
}, [isPageFocused, scrollToTop, feed])
|
||||
|
||||
// listens for resize events
|
||||
const listenForResize = React.useCallback(() => {
|
||||
// @ts-ignore we know window exists -prf
|
||||
const isMobileWeb = global.window.matchMedia(
|
||||
isMobileWebMediaQuery,
|
||||
)?.matches
|
||||
setHeaderOffset(
|
||||
isMobileWeb ? HEADER_OFFSET_MOBILE : HEADER_OFFSET_DESKTOP,
|
||||
)
|
||||
}, [])
|
||||
React.useEffect(() => {
|
||||
setHeaderOffset(isMobile ? HEADER_OFFSET_MOBILE : HEADER_OFFSET_DESKTOP)
|
||||
}, [isMobile])
|
||||
|
||||
// fires when page within screen is activated/deactivated
|
||||
// - check for latest
|
||||
|
@ -234,17 +228,10 @@ const FeedPage = observer(
|
|||
feed.update()
|
||||
}
|
||||
|
||||
if (isWeb) {
|
||||
window.addEventListener('resize', listenForResize)
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearInterval(pollInterval)
|
||||
softResetSub.remove()
|
||||
feedCleanup()
|
||||
if (isWeb) {
|
||||
isWeb && window.removeEventListener('resize', listenForResize)
|
||||
}
|
||||
}
|
||||
}, [
|
||||
store,
|
||||
|
@ -254,7 +241,6 @@ const FeedPage = observer(
|
|||
feed,
|
||||
isPageFocused,
|
||||
isScreenFocused,
|
||||
listenForResize,
|
||||
])
|
||||
|
||||
const onPressCompose = React.useCallback(() => {
|
||||
|
|
|
@ -16,7 +16,7 @@ import {Link} from '../com/util/Link'
|
|||
import {Text} from '../com/util/text/Text'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
|
||||
export const ModerationScreen = withAuthRequired(
|
||||
|
@ -24,6 +24,7 @@ export const ModerationScreen = withAuthRequired(
|
|||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {screen, track} = useAnalytics()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
|
@ -42,7 +43,7 @@ export const ModerationScreen = withAuthRequired(
|
|||
style={[
|
||||
s.hContentRegion,
|
||||
pal.border,
|
||||
isDesktopWeb ? styles.desktopContainer : pal.viewLight,
|
||||
isTabletOrDesktop ? styles.desktopContainer : pal.viewLight,
|
||||
]}
|
||||
testID="moderationScreen">
|
||||
<ViewHeader title="Moderation" showOnDesktop />
|
||||
|
|
|
@ -10,7 +10,7 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
|||
import {Text} from '../com/util/text/Text'
|
||||
import {useStores} from 'state/index'
|
||||
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 {observer} from 'mobx-react-lite'
|
||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||
|
@ -30,6 +30,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
|||
observer(({}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const {screen} = useAnalytics()
|
||||
const blockedAccounts = useMemo(
|
||||
() => new BlockedAccountsModel(store),
|
||||
|
@ -72,7 +73,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
|||
<CenteredView
|
||||
style={[
|
||||
styles.container,
|
||||
isDesktopWeb && styles.containerDesktop,
|
||||
isTabletOrDesktop && styles.containerDesktop,
|
||||
pal.view,
|
||||
pal.border,
|
||||
]}
|
||||
|
@ -83,14 +84,14 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
|||
style={[
|
||||
styles.description,
|
||||
pal.text,
|
||||
isDesktopWeb && styles.descriptionDesktop,
|
||||
isTabletOrDesktop && styles.descriptionDesktop,
|
||||
]}>
|
||||
Blocked accounts cannot reply in your threads, mention you, or
|
||||
otherwise interact with you. You will not see their content and they
|
||||
will be prevented from seeing yours.
|
||||
</Text>
|
||||
{!blockedAccounts.hasContent ? (
|
||||
<View style={[pal.border, !isDesktopWeb && styles.flex1]}>
|
||||
<View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
|
||||
<View style={[styles.empty, pal.viewLight]}>
|
||||
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
||||
You have not blocked any accounts yet. To block an account, go
|
||||
|
@ -101,7 +102,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
|||
</View>
|
||||
) : (
|
||||
<FlatList
|
||||
style={[!isDesktopWeb && styles.flex1]}
|
||||
style={[!isTabletOrDesktop && styles.flex1]}
|
||||
data={blockedAccounts.blocks}
|
||||
keyExtractor={(item: ActorDefs.ProfileView) => item.did}
|
||||
refreshControl={
|
||||
|
@ -133,11 +134,12 @@ export const ModerationBlockedAccounts = withAuthRequired(
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
containerDesktop: {
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
|
|
|
@ -15,9 +15,9 @@ import {ListsList} from 'view/com/lists/ListsList'
|
|||
import {Button} from 'view/com/util/forms/Button'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {CenteredView} from 'view/com/util/Views'
|
||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
|
||||
type Props = NativeStackScreenProps<
|
||||
CommonNavigatorParams,
|
||||
|
@ -26,6 +26,7 @@ type Props = NativeStackScreenProps<
|
|||
export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const mutelists: ListsListModel = React.useMemo(
|
||||
|
@ -89,7 +90,7 @@ export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
|||
styles.container,
|
||||
pal.view,
|
||||
pal.border,
|
||||
isDesktopWeb && styles.containerDesktop,
|
||||
isTabletOrDesktop && styles.containerDesktop,
|
||||
]}
|
||||
testID="moderationMutelistsScreen">
|
||||
<ViewHeader
|
||||
|
@ -99,7 +100,7 @@ export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
|||
/>
|
||||
<ListsList
|
||||
listsList={mutelists}
|
||||
showAddBtns={isDesktopWeb}
|
||||
showAddBtns={isTabletOrDesktop}
|
||||
renderEmptyState={renderEmptyState}
|
||||
onPressCreateNew={onPressNewMuteList}
|
||||
/>
|
||||
|
@ -110,11 +111,12 @@ export const ModerationMuteListsScreen = withAuthRequired(({}: Props) => {
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
containerDesktop: {
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
createBtn: {
|
||||
width: 40,
|
||||
|
|
|
@ -10,7 +10,7 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
|||
import {Text} from '../com/util/text/Text'
|
||||
import {useStores} from 'state/index'
|
||||
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 {observer} from 'mobx-react-lite'
|
||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||
|
@ -30,6 +30,7 @@ export const ModerationMutedAccounts = withAuthRequired(
|
|||
observer(({}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const {screen} = useAnalytics()
|
||||
const mutedAccounts = useMemo(() => new MutedAccountsModel(store), [store])
|
||||
|
||||
|
@ -69,7 +70,7 @@ export const ModerationMutedAccounts = withAuthRequired(
|
|||
<CenteredView
|
||||
style={[
|
||||
styles.container,
|
||||
isDesktopWeb && styles.containerDesktop,
|
||||
isTabletOrDesktop && styles.containerDesktop,
|
||||
pal.view,
|
||||
pal.border,
|
||||
]}
|
||||
|
@ -80,13 +81,13 @@ export const ModerationMutedAccounts = withAuthRequired(
|
|||
style={[
|
||||
styles.description,
|
||||
pal.text,
|
||||
isDesktopWeb && styles.descriptionDesktop,
|
||||
isTabletOrDesktop && styles.descriptionDesktop,
|
||||
]}>
|
||||
Muted accounts have their posts removed from your feed and from your
|
||||
notifications. Mutes are completely private.
|
||||
</Text>
|
||||
{!mutedAccounts.hasContent ? (
|
||||
<View style={[pal.border, !isDesktopWeb && styles.flex1]}>
|
||||
<View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
|
||||
<View style={[styles.empty, pal.viewLight]}>
|
||||
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
||||
You have not muted any accounts yet. To mute an account, go to
|
||||
|
@ -97,7 +98,7 @@ export const ModerationMutedAccounts = withAuthRequired(
|
|||
</View>
|
||||
) : (
|
||||
<FlatList
|
||||
style={[!isDesktopWeb && styles.flex1]}
|
||||
style={[!isTabletOrDesktop && styles.flex1]}
|
||||
data={mutedAccounts.mutes}
|
||||
keyExtractor={item => item.did}
|
||||
refreshControl={
|
||||
|
@ -129,11 +130,12 @@ export const ModerationMutedAccounts = withAuthRequired(
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
containerDesktop: {
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
|
|
|
@ -12,7 +12,7 @@ import {useStores} from 'state/index'
|
|||
import {s} from 'lib/styles'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {clamp} from 'lodash'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
|
||||
const SHELL_FOOTER_HEIGHT = 44
|
||||
|
||||
|
@ -26,6 +26,7 @@ export const PostThreadScreen = withAuthRequired(({route}: Props) => {
|
|||
() => new PostThreadModel(store, {uri}),
|
||||
[store, uri],
|
||||
)
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
|
@ -67,15 +68,15 @@ export const PostThreadScreen = withAuthRequired(({route}: Props) => {
|
|||
|
||||
return (
|
||||
<View style={s.hContentRegion}>
|
||||
<ViewHeader title="Post" />
|
||||
<View style={s.hContentRegion}>
|
||||
{isMobile && <ViewHeader title="Post" />}
|
||||
<View style={s.flex1}>
|
||||
<PostThreadComponent
|
||||
uri={uri}
|
||||
view={view}
|
||||
onPressReply={onPressReply}
|
||||
/>
|
||||
</View>
|
||||
{!isDesktopWeb && (
|
||||
{isMobile && (
|
||||
<View
|
||||
style={[
|
||||
styles.prompt,
|
||||
|
|
|
@ -6,7 +6,8 @@ import {Text} from '../com/util/text/Text'
|
|||
import {useStores} from 'state/index'
|
||||
import {s, colors} from 'lib/styles'
|
||||
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 {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
|
||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||
|
@ -50,6 +51,7 @@ type Props = NativeStackScreenProps<
|
|||
export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
|
||||
return (
|
||||
<CenteredView
|
||||
|
@ -58,10 +60,11 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
|||
pal.view,
|
||||
pal.border,
|
||||
styles.container,
|
||||
isDesktopWeb && styles.desktopContainer,
|
||||
isTabletOrDesktop && styles.desktopContainer,
|
||||
]}>
|
||||
<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]}>
|
||||
Fine-tune the content you see on your home screen.
|
||||
</Text>
|
||||
|
@ -122,7 +125,12 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
|||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<View style={[styles.btnContainer, pal.borderDark]}>
|
||||
<View
|
||||
style={[
|
||||
styles.btnContainer,
|
||||
!isTabletOrDesktop && {borderTopWidth: 1, paddingHorizontal: 20},
|
||||
pal.borderDark,
|
||||
]}>
|
||||
<TouchableOpacity
|
||||
testID="confirmBtn"
|
||||
onPress={() => {
|
||||
|
@ -130,7 +138,7 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
|||
? navigation.goBack()
|
||||
: navigation.navigate('Settings')
|
||||
}}
|
||||
style={[styles.btn, isDesktopWeb && styles.btnDesktop]}
|
||||
style={[styles.btn, isTabletOrDesktop && styles.btnDesktop]}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Confirm"
|
||||
accessibilityHint="">
|
||||
|
@ -144,15 +152,15 @@ export const PreferencesHomeFeed = observer(({navigation}: Props) => {
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingBottom: isDesktopWeb ? 40 : 90,
|
||||
paddingBottom: 90,
|
||||
},
|
||||
desktopContainer: {
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
paddingBottom: 40,
|
||||
},
|
||||
titleSection: {
|
||||
paddingBottom: 30,
|
||||
paddingTop: isDesktopWeb ? 20 : 0,
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
|
@ -184,7 +192,6 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
btnContainer: {
|
||||
paddingTop: 20,
|
||||
borderTopWidth: isDesktopWeb ? 0 : 1,
|
||||
},
|
||||
dimmed: {
|
||||
opacity: 0.3,
|
||||
|
|
|
@ -14,8 +14,8 @@ import {ListModel} from 'state/models/content/list'
|
|||
import {useStores} from 'state/index'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||
import {shareUrl} from 'lib/sharing'
|
||||
import {ListActions} from 'view/com/lists/ListActions'
|
||||
|
@ -26,6 +26,7 @@ export const ProfileListScreen = withAuthRequired(
|
|||
observer(({route}: Props) => {
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const pal = usePalette('default')
|
||||
const {name, rkey} = route.params
|
||||
|
||||
|
@ -131,7 +132,7 @@ export const ProfileListScreen = withAuthRequired(
|
|||
<CenteredView
|
||||
style={[
|
||||
styles.container,
|
||||
isDesktopWeb && styles.containerDesktop,
|
||||
isTabletOrDesktop && styles.containerDesktop,
|
||||
pal.view,
|
||||
pal.border,
|
||||
]}
|
||||
|
@ -155,10 +156,11 @@ export const ProfileListScreen = withAuthRequired(
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingBottom: isDesktopWeb ? 0 : 100,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
containerDesktop: {
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -14,11 +14,12 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {useStores} from 'state/index'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||
import {CenteredView} from 'view/com/util/Views'
|
||||
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 DraggableFlatList, {
|
||||
ShadowDecorator,
|
||||
|
@ -37,6 +38,7 @@ export const SavedFeeds = withAuthRequired(
|
|||
observer(({}: Props) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
|
||||
const {screen} = useAnalytics()
|
||||
|
||||
const savedFeeds = useMemo(() => store.me.savedFeeds, [store])
|
||||
|
@ -53,7 +55,7 @@ export const SavedFeeds = withAuthRequired(
|
|||
<View
|
||||
style={[
|
||||
pal.border,
|
||||
!isDesktopWeb && s.flex1,
|
||||
isMobile && s.flex1,
|
||||
pal.viewLight,
|
||||
styles.empty,
|
||||
]}>
|
||||
|
@ -62,7 +64,7 @@ export const SavedFeeds = withAuthRequired(
|
|||
</Text>
|
||||
</View>
|
||||
)
|
||||
}, [pal])
|
||||
}, [pal, isMobile])
|
||||
|
||||
const renderListFooterComponent = useCallback(() => {
|
||||
return (
|
||||
|
@ -116,15 +118,11 @@ export const SavedFeeds = withAuthRequired(
|
|||
style={[
|
||||
s.hContentRegion,
|
||||
pal.border,
|
||||
isDesktopWeb && styles.desktopContainer,
|
||||
isTabletOrDesktop && styles.desktopContainer,
|
||||
]}>
|
||||
<ViewHeader
|
||||
title="Edit My Feeds"
|
||||
showOnDesktop
|
||||
showBorder={!isDesktopWeb}
|
||||
/>
|
||||
<ViewHeader title="Edit My Feeds" showOnDesktop showBorder />
|
||||
<DraggableFlatList
|
||||
containerStyle={[isDesktopWeb ? s.hContentRegion : s.flex1]}
|
||||
containerStyle={[isTabletOrDesktop ? s.hContentRegion : s.flex1]}
|
||||
data={savedFeeds.all}
|
||||
keyExtractor={item => item.data.uri}
|
||||
refreshing={savedFeeds.isRefreshing}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
SearchTabNavigatorParams,
|
||||
} from 'lib/routes/types'
|
||||
import {useStores} from 'state/index'
|
||||
import {CenteredView} from 'view/com/util/Views'
|
||||
import * as Mobile from './SearchMobile'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
|
||||
|
@ -57,9 +58,9 @@ export const SearchScreen = withAuthRequired(
|
|||
|
||||
if (!isDesktop) {
|
||||
return (
|
||||
<View style={styles.scrollContainer}>
|
||||
<CenteredView style={styles.scrollContainer}>
|
||||
<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 {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {AccountData} from 'state/models/session'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
import {formatCount} from 'view/com/util/numeric/format'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
|
@ -58,6 +58,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {screen, track} = useAnalytics()
|
||||
const [isSwitching, setIsSwitching] = React.useState(false)
|
||||
const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(
|
||||
|
@ -203,7 +204,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
<ViewHeader title="Settings" />
|
||||
<ScrollView
|
||||
style={[s.hContentRegion]}
|
||||
contentContainerStyle={!isDesktopWeb && pal.viewLight}
|
||||
contentContainerStyle={isMobile && pal.viewLight}
|
||||
scrollIndicatorInsets={{right: 1}}>
|
||||
<View style={styles.spacer20} />
|
||||
{store.session.currentSession !== undefined ? (
|
||||
|
@ -508,7 +509,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
System log
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
{isDesktopWeb || __DEV__ ? (
|
||||
{__DEV__ ? (
|
||||
<ToggleButton
|
||||
type="default-light"
|
||||
label="Experiment: Use AppView Proxy"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue