feat: prevent search engines from indexing Discover feed content as page descriptions
This commit is contained in:
@@ -29,6 +29,7 @@ import {FAB} from '../util/fab/FAB'
|
|||||||
import {type ListMethods} from '../util/List'
|
import {type ListMethods} from '../util/List'
|
||||||
import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn'
|
import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn'
|
||||||
import {MainScrollProvider} from '../util/MainScrollProvider'
|
import {MainScrollProvider} from '../util/MainScrollProvider'
|
||||||
|
import {NoSnippetWrapper} from '../util/NoSnippetWrapper'
|
||||||
|
|
||||||
const POLL_FREQ = 60e3 // 60sec
|
const POLL_FREQ = 60e3 // 60sec
|
||||||
|
|
||||||
@@ -132,45 +133,49 @@ export function FeedPage({
|
|||||||
|
|
||||||
const shouldPrefetch = isNative && isPageAdjacent
|
const shouldPrefetch = isNative && isPageAdjacent
|
||||||
return (
|
return (
|
||||||
<View testID={testID} {...(isDiscoverFeed && {'data-nosnippet': true})}>
|
<NoSnippetWrapper enabled={isDiscoverFeed}>
|
||||||
<MainScrollProvider>
|
<View testID={testID}>
|
||||||
<FeedFeedbackProvider value={feedFeedback}>
|
<MainScrollProvider>
|
||||||
<PostFeed
|
<FeedFeedbackProvider value={feedFeedback}>
|
||||||
testID={testID ? `${testID}-feed` : undefined}
|
<PostFeed
|
||||||
enabled={isPageFocused || shouldPrefetch}
|
testID={testID ? `${testID}-feed` : undefined}
|
||||||
feed={feed}
|
enabled={isPageFocused || shouldPrefetch}
|
||||||
feedParams={feedParams}
|
feed={feed}
|
||||||
pollInterval={POLL_FREQ}
|
feedParams={feedParams}
|
||||||
disablePoll={hasNew || !isPageFocused}
|
pollInterval={POLL_FREQ}
|
||||||
scrollElRef={scrollElRef}
|
disablePoll={hasNew || !isPageFocused}
|
||||||
onScrolledDownChange={setIsScrolledDown}
|
scrollElRef={scrollElRef}
|
||||||
onHasNew={setHasNew}
|
onScrolledDownChange={setIsScrolledDown}
|
||||||
renderEmptyState={renderEmptyState}
|
onHasNew={setHasNew}
|
||||||
renderEndOfFeed={renderEndOfFeed}
|
renderEmptyState={renderEmptyState}
|
||||||
headerOffset={headerOffset}
|
renderEndOfFeed={renderEndOfFeed}
|
||||||
savedFeedConfig={savedFeedConfig}
|
headerOffset={headerOffset}
|
||||||
isVideoFeed={isVideoFeed}
|
savedFeedConfig={savedFeedConfig}
|
||||||
|
isVideoFeed={isVideoFeed}
|
||||||
|
/>
|
||||||
|
</FeedFeedbackProvider>
|
||||||
|
</MainScrollProvider>
|
||||||
|
{(isScrolledDown || hasNew) && (
|
||||||
|
<LoadLatestBtn
|
||||||
|
onPress={onPressLoadLatest}
|
||||||
|
label={_(msg`Load new posts`)}
|
||||||
|
showIndicator={hasNew}
|
||||||
/>
|
/>
|
||||||
</FeedFeedbackProvider>
|
)}
|
||||||
</MainScrollProvider>
|
|
||||||
{(isScrolledDown || hasNew) && (
|
|
||||||
<LoadLatestBtn
|
|
||||||
onPress={onPressLoadLatest}
|
|
||||||
label={_(msg`Load new posts`)}
|
|
||||||
showIndicator={hasNew}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{hasSession && (
|
{hasSession && (
|
||||||
<FAB
|
<FAB
|
||||||
testID="composeFAB"
|
testID="composeFAB"
|
||||||
onPress={onPressCompose}
|
onPress={onPressCompose}
|
||||||
icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
|
icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={_(msg({message: `New post`, context: 'action'}))}
|
accessibilityLabel={_(
|
||||||
accessibilityHint=""
|
msg({message: `New post`, context: 'action'}),
|
||||||
/>
|
)}
|
||||||
)}
|
accessibilityHint=""
|
||||||
</View>
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</NoSnippetWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import {type ViewProps} from 'react-native'
|
||||||
|
// @ts-expect-error untyped
|
||||||
|
import {unstable_createElement} from 'react-native-web'
|
||||||
|
|
||||||
|
import {isWeb} from '#/platform/detection'
|
||||||
|
|
||||||
|
interface Props extends ViewProps {
|
||||||
|
enabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NoSnippetWrapper prevents search engines from displaying snippets of its content.
|
||||||
|
*
|
||||||
|
* If running on web and enabled, wraps children in a <div> with data-nosnippet attribute.
|
||||||
|
* Otherwise, renders children directly.
|
||||||
|
*
|
||||||
|
* @param enabled - Whether to apply the data-nosnippet attribute.
|
||||||
|
* @param viewProps - Additional props for the wrapper element.
|
||||||
|
*/
|
||||||
|
export function NoSnippetWrapper({enabled, ...viewProps}: Props) {
|
||||||
|
if (isWeb && enabled) {
|
||||||
|
return unstable_createElement('div', {
|
||||||
|
...viewProps,
|
||||||
|
'data-nosnippet': '',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{viewProps.children}</>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user