Merge remote-tracking branch 'origin/main' into hailey/verify-email-dialog-alf
This commit is contained in:
@@ -42,7 +42,7 @@ class ViewController: UIViewController, WKScriptMessageHandler, WKNavigationDele
|
|||||||
let payload = try? JSONDecoder().decode(WebViewActionPayload.self, from: data) else {
|
let payload = try? JSONDecoder().decode(WebViewActionPayload.self, from: data) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch payload.action {
|
switch payload.action {
|
||||||
case .present:
|
case .present:
|
||||||
guard let url = self.starterPackUrl else {
|
guard let url = self.starterPackUrl else {
|
||||||
@@ -66,23 +66,51 @@ class ViewController: UIViewController, WKScriptMessageHandler, WKNavigationDele
|
|||||||
guard let url = navigationAction.request.url else {
|
guard let url = navigationAction.request.url else {
|
||||||
return .allow
|
return .allow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the previous one to compare later, but only set starterPackUrl when we find the right one
|
// Store the previous one to compare later, but only set starterPackUrl when we find the right one
|
||||||
prevUrl = url
|
prevUrl = url
|
||||||
// pathComponents starts with "/" as the first component, then each path name. so...
|
// pathComponents starts with "/" as the first component, then each path name. so...
|
||||||
// ["/", "start", "name", "rkey"]
|
// ["/", "start", "name", "rkey"]
|
||||||
if url.pathComponents.count == 4,
|
if isStarterPackUrl(url){
|
||||||
url.pathComponents[1] == "start" {
|
|
||||||
self.starterPackUrl = url
|
self.starterPackUrl = url
|
||||||
}
|
}
|
||||||
|
|
||||||
return .allow
|
return .allow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStarterPackUrl(_ url: URL) -> Bool {
|
||||||
|
var host: String?
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
host = url.host()
|
||||||
|
} else {
|
||||||
|
host = url.host
|
||||||
|
}
|
||||||
|
|
||||||
|
switch host {
|
||||||
|
case "bsky.app":
|
||||||
|
if url.pathComponents.count == 4,
|
||||||
|
(url.pathComponents[1] == "start" || url.pathComponents[1] == "starter-pack") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
case "go.bsky.app":
|
||||||
|
if url.pathComponents.count == 2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleURL(url: URL) {
|
func handleURL(url: URL) {
|
||||||
let urlString = "\(url.absoluteString)?clip=true"
|
if isStarterPackUrl(url) {
|
||||||
if let url = URL(string: urlString) {
|
let urlString = "\(url.absoluteString)?clip=true"
|
||||||
self.webView?.load(URLRequest(url: url))
|
if let url = URL(string: urlString) {
|
||||||
|
self.webView?.load(URLRequest(url: url))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.webView?.load(URLRequest(url: URL(string: "https://bsky.app/?splash=true&clip=true")!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,18 +153,18 @@ export function Outer({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Context.Provider value={context}>
|
<BottomSheet
|
||||||
<BottomSheet
|
ref={ref}
|
||||||
ref={ref}
|
cornerRadius={20}
|
||||||
cornerRadius={20}
|
backgroundColor={t.atoms.bg.backgroundColor}
|
||||||
backgroundColor={t.atoms.bg.backgroundColor}
|
{...nativeOptions}
|
||||||
{...nativeOptions}
|
onSnapPointChange={onSnapPointChange}
|
||||||
onSnapPointChange={onSnapPointChange}
|
onStateChange={onStateChange}
|
||||||
onStateChange={onStateChange}
|
disableDrag={disableDrag}>
|
||||||
disableDrag={disableDrag}>
|
<Context.Provider value={context}>
|
||||||
<View testID={testID}>{children}</View>
|
<View testID={testID}>{children}</View>
|
||||||
</BottomSheet>
|
</Context.Provider>
|
||||||
</Context.Provider>
|
</BottomSheet>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import type {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
|
|
||||||
import {ViewStyleProp} from '#/alf'
|
import {ViewStyleProp} from '#/alf'
|
||||||
import {PortalComponent} from '#/components/Portal'
|
|
||||||
import {BottomSheetViewProps} from '../../../modules/bottom-sheet'
|
import {BottomSheetViewProps} from '../../../modules/bottom-sheet'
|
||||||
import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types'
|
import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types'
|
||||||
|
|
||||||
@@ -61,7 +60,6 @@ export type DialogOuterProps = {
|
|||||||
nativeOptions?: Omit<BottomSheetViewProps, 'children'>
|
nativeOptions?: Omit<BottomSheetViewProps, 'children'>
|
||||||
webOptions?: {}
|
webOptions?: {}
|
||||||
testID?: string
|
testID?: string
|
||||||
Portal?: PortalComponent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DialogInnerPropsBase<T> = React.PropsWithChildren<ViewStyleProp> & T
|
type DialogInnerPropsBase<T> = React.PropsWithChildren<ViewStyleProp> & T
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import {
|
|||||||
ItemTextProps,
|
ItemTextProps,
|
||||||
TriggerProps,
|
TriggerProps,
|
||||||
} from '#/components/Menu/types'
|
} from '#/components/Menu/types'
|
||||||
import {PortalComponent} from '#/components/Portal'
|
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -78,11 +77,9 @@ export function Trigger({children, label}: TriggerProps) {
|
|||||||
export function Outer({
|
export function Outer({
|
||||||
children,
|
children,
|
||||||
showCancel,
|
showCancel,
|
||||||
Portal,
|
|
||||||
}: React.PropsWithChildren<{
|
}: React.PropsWithChildren<{
|
||||||
showCancel?: boolean
|
showCancel?: boolean
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
Portal?: PortalComponent
|
|
||||||
}>) {
|
}>) {
|
||||||
const context = React.useContext(Context)
|
const context = React.useContext(Context)
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -90,8 +87,7 @@ export function Outer({
|
|||||||
return (
|
return (
|
||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
control={context.control}
|
control={context.control}
|
||||||
nativeOptions={{preventExpansion: true}}
|
nativeOptions={{preventExpansion: true}}>
|
||||||
Portal={Portal}>
|
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
{/* Re-wrap with context since Dialogs are portal-ed to root */}
|
{/* Re-wrap with context since Dialogs are portal-ed to root */}
|
||||||
<Context.Provider value={context}>
|
<Context.Provider value={context}>
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ type ComponentMap = {
|
|||||||
[id: string]: Component
|
[id: string]: Component
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PortalComponent = ({children}: {children?: React.ReactNode}) => null
|
|
||||||
|
|
||||||
export function createPortalGroup() {
|
export function createPortalGroup() {
|
||||||
const Context = React.createContext<ContextType>({
|
const Context = React.createContext<ContextType>({
|
||||||
outlet: null,
|
outlet: null,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {Button, ButtonColor, ButtonText} from '#/components/Button'
|
import {Button, ButtonColor, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {PortalComponent} from '#/components/Portal'
|
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {BottomSheetViewProps} from '../../modules/bottom-sheet'
|
import {BottomSheetViewProps} from '../../modules/bottom-sheet'
|
||||||
|
|
||||||
@@ -27,12 +26,10 @@ export function Outer({
|
|||||||
children,
|
children,
|
||||||
control,
|
control,
|
||||||
testID,
|
testID,
|
||||||
Portal,
|
|
||||||
nativeOptions,
|
nativeOptions,
|
||||||
}: React.PropsWithChildren<{
|
}: React.PropsWithChildren<{
|
||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
testID?: string
|
testID?: string
|
||||||
Portal?: PortalComponent
|
|
||||||
nativeOptions?: Omit<BottomSheetViewProps, 'children'>
|
nativeOptions?: Omit<BottomSheetViewProps, 'children'>
|
||||||
}>) {
|
}>) {
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
@@ -48,7 +45,6 @@ export function Outer({
|
|||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
control={control}
|
control={control}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
Portal={Portal}
|
|
||||||
nativeOptions={{preventExpansion: true, ...nativeOptions}}>
|
nativeOptions={{preventExpansion: true, ...nativeOptions}}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<Context.Provider value={context}>
|
<Context.Provider value={context}>
|
||||||
@@ -190,7 +186,6 @@ export function Basic({
|
|||||||
onConfirm,
|
onConfirm,
|
||||||
confirmButtonColor,
|
confirmButtonColor,
|
||||||
showCancel = true,
|
showCancel = true,
|
||||||
Portal,
|
|
||||||
}: React.PropsWithChildren<{
|
}: React.PropsWithChildren<{
|
||||||
control: Dialog.DialogOuterProps['control']
|
control: Dialog.DialogOuterProps['control']
|
||||||
title: string
|
title: string
|
||||||
@@ -207,10 +202,9 @@ export function Basic({
|
|||||||
onConfirm: (e: GestureResponderEvent) => void
|
onConfirm: (e: GestureResponderEvent) => void
|
||||||
confirmButtonColor?: ButtonColor
|
confirmButtonColor?: ButtonColor
|
||||||
showCancel?: boolean
|
showCancel?: boolean
|
||||||
Portal?: PortalComponent
|
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<Outer control={control} testID="confirmModal" Portal={Portal}>
|
<Outer control={control} testID="confirmModal">
|
||||||
<TitleText>{title}</TitleText>
|
<TitleText>{title}</TitleText>
|
||||||
<DescriptionText>{description}</DescriptionText>
|
<DescriptionText>{description}</DescriptionText>
|
||||||
<Actions>
|
<Actions>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function ReportDialogInner(props: ReportDialogProps) {
|
|||||||
isLoading: isLabelerLoading,
|
isLoading: isLabelerLoading,
|
||||||
data: labelers,
|
data: labelers,
|
||||||
error,
|
error,
|
||||||
} = useMyLabelersQuery()
|
} = useMyLabelersQuery({excludeNonConfigurableLabelers: true})
|
||||||
const isLoading = useDelayedLoading(500, isLabelerLoading)
|
const isLoading = useDelayedLoading(500, isLabelerLoading)
|
||||||
|
|
||||||
const ref = React.useRef<ScrollView>(null)
|
const ref = React.useRef<ScrollView>(null)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ interface AppClipMessage {
|
|||||||
jsonToStore?: string
|
jsonToStore?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function postAppClipMessage(message: AppClipMessage) {
|
export function postAppClipMessage(message: AppClipMessage) {
|
||||||
// @ts-expect-error safari webview only
|
// @ts-expect-error safari webview only
|
||||||
window.webkit.messageHandlers.onMessage.postMessage(JSON.stringify(message))
|
window.webkit.messageHandlers.onMessage.postMessage(JSON.stringify(message))
|
||||||
}
|
}
|
||||||
@@ -356,7 +356,7 @@ function LandingScreenLoaded({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function AppClipOverlay({
|
export function AppClipOverlay({
|
||||||
visible,
|
visible,
|
||||||
setIsVisible,
|
setIsVisible,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
DEFAULT_LABEL_SETTINGS,
|
|
||||||
BskyAgent,
|
BskyAgent,
|
||||||
|
DEFAULT_LABEL_SETTINGS,
|
||||||
interpretLabelValueDefinitions,
|
interpretLabelValueDefinitions,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {usePreferencesQuery} from './index'
|
import {isNonConfigurableModerationAuthority} from '#/state/session/additional-moderation-authorities'
|
||||||
import {useLabelersDetailedInfoQuery} from '../labeler'
|
import {useLabelersDetailedInfoQuery} from '../labeler'
|
||||||
|
import {usePreferencesQuery} from './index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* More strict than our default settings for logged in users.
|
* More strict than our default settings for logged in users.
|
||||||
@@ -16,15 +17,22 @@ export const DEFAULT_LOGGED_OUT_LABEL_PREFERENCES: typeof DEFAULT_LABEL_SETTINGS
|
|||||||
Object.entries(DEFAULT_LABEL_SETTINGS).map(([key, _pref]) => [key, 'hide']),
|
Object.entries(DEFAULT_LABEL_SETTINGS).map(([key, _pref]) => [key, 'hide']),
|
||||||
)
|
)
|
||||||
|
|
||||||
export function useMyLabelersQuery() {
|
export function useMyLabelersQuery({
|
||||||
|
excludeNonConfigurableLabelers = false,
|
||||||
|
}: {
|
||||||
|
excludeNonConfigurableLabelers?: boolean
|
||||||
|
} = {}) {
|
||||||
const prefs = usePreferencesQuery()
|
const prefs = usePreferencesQuery()
|
||||||
const dids = Array.from(
|
let dids = Array.from(
|
||||||
new Set(
|
new Set(
|
||||||
BskyAgent.appLabelers.concat(
|
BskyAgent.appLabelers.concat(
|
||||||
prefs.data?.moderationPrefs.labelers.map(l => l.did) || [],
|
prefs.data?.moderationPrefs.labelers.map(l => l.did) || [],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
if (excludeNonConfigurableLabelers) {
|
||||||
|
dids = dids.filter(did => !isNonConfigurableModerationAuthority(did))
|
||||||
|
}
|
||||||
const labelers = useLabelersDetailedInfoQuery({dids})
|
const labelers = useLabelersDetailedInfoQuery({dids})
|
||||||
const isLoading = prefs.isLoading || labelers.isLoading
|
const isLoading = prefs.isLoading || labelers.isLoading
|
||||||
const error = prefs.error || labelers.error
|
const error = prefs.error || labelers.error
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ import {useKawaiiMode} from '#/state/preferences/kawaii'
|
|||||||
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
||||||
import {Logo} from '#/view/icons/Logo'
|
import {Logo} from '#/view/icons/Logo'
|
||||||
import {Logotype} from '#/view/icons/Logotype'
|
import {Logotype} from '#/view/icons/Logotype'
|
||||||
|
import {
|
||||||
|
AppClipOverlay,
|
||||||
|
postAppClipMessage,
|
||||||
|
} from '#/screens/StarterPack/StarterPackLandingScreen'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {AppLanguageDropdown} from '#/components/AppLanguageDropdown'
|
import {AppLanguageDropdown} from '#/components/AppLanguageDropdown'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
@@ -28,6 +32,18 @@ export const SplashScreen = ({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {isTabletOrMobile: isMobileWeb} = useWebMediaQueries()
|
const {isTabletOrMobile: isMobileWeb} = useWebMediaQueries()
|
||||||
|
const [showClipOverlay, setShowClipOverlay] = React.useState(false)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const getParams = new URLSearchParams(window.location.search)
|
||||||
|
const clip = getParams.get('clip')
|
||||||
|
if (clip === 'true') {
|
||||||
|
setShowClipOverlay(true)
|
||||||
|
postAppClipMessage({
|
||||||
|
action: 'present',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const kawaii = useKawaiiMode()
|
const kawaii = useKawaiiMode()
|
||||||
|
|
||||||
@@ -119,6 +135,10 @@ export const SplashScreen = ({
|
|||||||
</View>
|
</View>
|
||||||
<Footer />
|
<Footer />
|
||||||
</CenteredView>
|
</CenteredView>
|
||||||
|
<AppClipOverlay
|
||||||
|
visible={showClipOverlay}
|
||||||
|
setIsVisible={setShowClipOverlay}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
|
|||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
import {PortalComponent} from '#/components/Portal'
|
|
||||||
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
||||||
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
|
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
|
||||||
|
|
||||||
@@ -51,7 +50,6 @@ interface UserAvatarProps extends BaseUserAvatarProps {
|
|||||||
|
|
||||||
interface EditableUserAvatarProps extends BaseUserAvatarProps {
|
interface EditableUserAvatarProps extends BaseUserAvatarProps {
|
||||||
onSelectNewAvatar: (img: RNImage | null) => void
|
onSelectNewAvatar: (img: RNImage | null) => void
|
||||||
Portal?: PortalComponent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
|
interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
|
||||||
@@ -268,7 +266,6 @@ let EditableUserAvatar = ({
|
|||||||
size,
|
size,
|
||||||
avatar,
|
avatar,
|
||||||
onSelectNewAvatar,
|
onSelectNewAvatar,
|
||||||
Portal,
|
|
||||||
}: EditableUserAvatarProps): React.ReactNode => {
|
}: EditableUserAvatarProps): React.ReactNode => {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
@@ -366,7 +363,7 @@ let EditableUserAvatar = ({
|
|||||||
</Pressable>
|
</Pressable>
|
||||||
)}
|
)}
|
||||||
</Menu.Trigger>
|
</Menu.Trigger>
|
||||||
<Menu.Outer showCancel Portal={Portal}>
|
<Menu.Outer showCancel>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
{isNative && (
|
{isNative && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import {
|
|||||||
import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
|
import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
|
||||||
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
|
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
import {PortalComponent} from '#/components/Portal'
|
|
||||||
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
|
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
|
||||||
|
|
||||||
export function UserBanner({
|
export function UserBanner({
|
||||||
@@ -33,13 +32,11 @@ export function UserBanner({
|
|||||||
banner,
|
banner,
|
||||||
moderation,
|
moderation,
|
||||||
onSelectNewBanner,
|
onSelectNewBanner,
|
||||||
Portal,
|
|
||||||
}: {
|
}: {
|
||||||
type?: 'labeler' | 'default'
|
type?: 'labeler' | 'default'
|
||||||
banner?: string | null
|
banner?: string | null
|
||||||
moderation?: ModerationUI
|
moderation?: ModerationUI
|
||||||
onSelectNewBanner?: (img: RNImage | null) => void
|
onSelectNewBanner?: (img: RNImage | null) => void
|
||||||
Portal?: PortalComponent
|
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
@@ -118,7 +115,7 @@ export function UserBanner({
|
|||||||
</Pressable>
|
</Pressable>
|
||||||
)}
|
)}
|
||||||
</Menu.Trigger>
|
</Menu.Trigger>
|
||||||
<Menu.Outer showCancel Portal={Portal}>
|
<Menu.Outer showCancel>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
{isNative && (
|
{isNative && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
|
|||||||
@@ -4,8 +4,15 @@ import {useFocusEffect} from '@react-navigation/native'
|
|||||||
|
|
||||||
import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
|
import {useOTAUpdates} from '#/lib/hooks/useOTAUpdates'
|
||||||
import {useSetTitle} from '#/lib/hooks/useSetTitle'
|
import {useSetTitle} from '#/lib/hooks/useSetTitle'
|
||||||
|
import {useRequestNotificationsPermission} from '#/lib/notifications/notifications'
|
||||||
|
import {
|
||||||
|
HomeTabNavigatorParams,
|
||||||
|
NativeStackScreenProps,
|
||||||
|
} from '#/lib/routes/types'
|
||||||
import {logEvent, LogEvents} from '#/lib/statsig/statsig'
|
import {logEvent, LogEvents} from '#/lib/statsig/statsig'
|
||||||
|
import {isWeb} from '#/platform/detection'
|
||||||
import {emitSoftReset} from '#/state/events'
|
import {emitSoftReset} from '#/state/events'
|
||||||
import {SavedFeedSourceInfo, usePinnedFeedsInfos} from '#/state/queries/feed'
|
import {SavedFeedSourceInfo, usePinnedFeedsInfos} from '#/state/queries/feed'
|
||||||
import {FeedParams} from '#/state/queries/post-feed'
|
import {FeedParams} from '#/state/queries/post-feed'
|
||||||
@@ -13,26 +20,34 @@ import {usePreferencesQuery} from '#/state/queries/preferences'
|
|||||||
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell'
|
import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell'
|
||||||
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
|
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
|
||||||
import {useOTAUpdates} from 'lib/hooks/useOTAUpdates'
|
import {FeedPage} from '#/view/com/feeds/FeedPage'
|
||||||
import {useRequestNotificationsPermission} from 'lib/notifications/notifications'
|
import {Pager, PagerRef, RenderTabBarFnProps} from '#/view/com/pager/Pager'
|
||||||
import {HomeTabNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
|
import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState'
|
||||||
import {FeedPage} from 'view/com/feeds/FeedPage'
|
import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState'
|
||||||
import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
|
import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed'
|
||||||
import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
|
|
||||||
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
|
|
||||||
import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
|
|
||||||
import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
||||||
import {HomeHeader} from '../com/home/HomeHeader'
|
import {HomeHeader} from '../com/home/HomeHeader'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home' | 'Start'>
|
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home' | 'Start'>
|
||||||
export function HomeScreen(props: Props) {
|
export function HomeScreen(props: Props) {
|
||||||
|
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||||
const {data: preferences} = usePreferencesQuery()
|
const {data: preferences} = usePreferencesQuery()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const {data: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} =
|
const {data: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} =
|
||||||
usePinnedFeedsInfos()
|
usePinnedFeedsInfos()
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
if (isWeb && !currentAccount) {
|
||||||
|
const getParams = new URLSearchParams(window.location.search)
|
||||||
|
const splash = getParams.get('splash')
|
||||||
|
if (splash === 'true') {
|
||||||
|
setShowLoggedOut(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const params = props.route.params
|
const params = props.route.params
|
||||||
if (
|
if (
|
||||||
currentAccount &&
|
currentAccount &&
|
||||||
@@ -45,7 +60,13 @@ export function HomeScreen(props: Props) {
|
|||||||
name: params.name,
|
name: params.name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [currentAccount, props.navigation, props.route.name, props.route.params])
|
}, [
|
||||||
|
currentAccount,
|
||||||
|
props.navigation,
|
||||||
|
props.route.name,
|
||||||
|
props.route.params,
|
||||||
|
setShowLoggedOut,
|
||||||
|
])
|
||||||
|
|
||||||
if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) {
|
if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user