Add alerts to embeds (#1138)
* Add alerts to embeds * Add images to the mock data * Fix typeszio/stable
parent
e51dbefd0a
commit
bbe9861eef
|
@ -144,7 +144,7 @@ async function main() {
|
||||||
await server.mocker.labelProfile('porn', 'porn-profile')
|
await server.mocker.labelProfile('porn', 'porn-profile')
|
||||||
await server.mocker.labelPost(
|
await server.mocker.labelPost(
|
||||||
'porn',
|
'porn',
|
||||||
await server.mocker.createPost('porn-posts', 'porn post'),
|
await server.mocker.createImagePost('porn-posts', 'porn post'),
|
||||||
)
|
)
|
||||||
await server.mocker.labelPost(
|
await server.mocker.labelPost(
|
||||||
'porn',
|
'porn',
|
||||||
|
@ -167,7 +167,7 @@ async function main() {
|
||||||
await server.mocker.labelProfile('nudity', 'nudity-profile')
|
await server.mocker.labelProfile('nudity', 'nudity-profile')
|
||||||
await server.mocker.labelPost(
|
await server.mocker.labelPost(
|
||||||
'nudity',
|
'nudity',
|
||||||
await server.mocker.createPost('nudity-posts', 'nudity post'),
|
await server.mocker.createImagePost('nudity-posts', 'nudity post'),
|
||||||
)
|
)
|
||||||
await server.mocker.labelPost(
|
await server.mocker.labelPost(
|
||||||
'nudity',
|
'nudity',
|
||||||
|
|
|
@ -29,13 +29,13 @@ export async function createServer(
|
||||||
plc: {port: port2},
|
plc: {port: port2},
|
||||||
})
|
})
|
||||||
|
|
||||||
const profilePic = fs.readFileSync(
|
const pic = fs.readFileSync(
|
||||||
path.join(__dirname, '..', 'assets', 'default-avatar.jpg'),
|
path.join(__dirname, '..', 'assets', 'default-avatar.jpg'),
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pdsUrl,
|
pdsUrl,
|
||||||
mocker: new Mocker(pds, pdsUrl, profilePic),
|
mocker: new Mocker(pds, pdsUrl, pic),
|
||||||
async close() {
|
async close() {
|
||||||
await pds.server.destroy()
|
await pds.server.destroy()
|
||||||
await plc.server.destroy()
|
await plc.server.destroy()
|
||||||
|
@ -50,7 +50,7 @@ class Mocker {
|
||||||
constructor(
|
constructor(
|
||||||
public pds: DevEnvTestPDS,
|
public pds: DevEnvTestPDS,
|
||||||
public service: string,
|
public service: string,
|
||||||
public profilePic: Uint8Array,
|
public pic: Uint8Array,
|
||||||
) {
|
) {
|
||||||
this.agent = new BskyAgent({service})
|
this.agent = new BskyAgent({service})
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ class Mocker {
|
||||||
password: 'hunter2',
|
password: 'hunter2',
|
||||||
})
|
})
|
||||||
await agent.upsertProfile(async () => {
|
await agent.upsertProfile(async () => {
|
||||||
const blob = await agent.uploadBlob(this.profilePic, {
|
const blob = await agent.uploadBlob(this.pic, {
|
||||||
encoding: 'image/jpeg',
|
encoding: 'image/jpeg',
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
|
@ -151,6 +151,25 @@ class Mocker {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createImagePost(user: string, text: string) {
|
||||||
|
const agent = this.users[user]?.agent
|
||||||
|
if (!agent) {
|
||||||
|
throw new Error(`Not a user: ${user}`)
|
||||||
|
}
|
||||||
|
const blob = await agent.uploadBlob(this.pic, {
|
||||||
|
encoding: 'image/jpeg',
|
||||||
|
})
|
||||||
|
return await agent.post({
|
||||||
|
text,
|
||||||
|
langs: ['en'],
|
||||||
|
embed: {
|
||||||
|
$type: 'app.bsky.embed.images',
|
||||||
|
images: [{image: blob.data.blob, alt: ''}],
|
||||||
|
},
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async createQuotePost(
|
async createQuotePost(
|
||||||
user: string,
|
user: string,
|
||||||
text: string,
|
text: string,
|
||||||
|
|
|
@ -75,3 +75,13 @@ export function getProfileModerationCauses(
|
||||||
return true
|
return true
|
||||||
}) as ModerationCause[]
|
}) as ModerationCause[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCauseALabelOnUri(
|
||||||
|
cause: ModerationCause | undefined,
|
||||||
|
uri: string,
|
||||||
|
): boolean {
|
||||||
|
if (cause?.type !== 'label') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return cause.label.uri === uri
|
||||||
|
}
|
||||||
|
|
|
@ -269,7 +269,10 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{item.post.embed && (
|
{item.post.embed && (
|
||||||
<ContentHider moderation={item.moderation.embed} style={s.mb10}>
|
<ContentHider moderation={item.moderation.embed} style={s.mb10}>
|
||||||
<PostEmbeds embed={item.post.embed} />
|
<PostEmbeds
|
||||||
|
embed={item.post.embed}
|
||||||
|
moderation={item.moderation.embed}
|
||||||
|
/>
|
||||||
</ContentHider>
|
</ContentHider>
|
||||||
)}
|
)}
|
||||||
</ContentHider>
|
</ContentHider>
|
||||||
|
@ -428,7 +431,10 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{item.post.embed && (
|
{item.post.embed && (
|
||||||
<ContentHider style={s.mb10} moderation={item.moderation.embed}>
|
<ContentHider style={s.mb10} moderation={item.moderation.embed}>
|
||||||
<PostEmbeds embed={item.post.embed} />
|
<PostEmbeds
|
||||||
|
embed={item.post.embed}
|
||||||
|
moderation={item.moderation.embed}
|
||||||
|
/>
|
||||||
</ContentHider>
|
</ContentHider>
|
||||||
)}
|
)}
|
||||||
{needsTranslation && (
|
{needsTranslation && (
|
||||||
|
|
|
@ -267,7 +267,10 @@ const PostLoaded = observer(
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{item.post.embed ? (
|
{item.post.embed ? (
|
||||||
<ContentHider moderation={item.moderation.embed} style={s.mb10}>
|
<ContentHider moderation={item.moderation.embed} style={s.mb10}>
|
||||||
<PostEmbeds embed={item.post.embed} />
|
<PostEmbeds
|
||||||
|
embed={item.post.embed}
|
||||||
|
moderation={item.moderation.embed}
|
||||||
|
/>
|
||||||
</ContentHider>
|
</ContentHider>
|
||||||
) : null}
|
) : null}
|
||||||
{needsTranslation && (
|
{needsTranslation && (
|
||||||
|
|
|
@ -293,7 +293,10 @@ export const FeedItem = observer(function ({
|
||||||
<ContentHider
|
<ContentHider
|
||||||
moderation={item.moderation.embed}
|
moderation={item.moderation.embed}
|
||||||
style={styles.embed}>
|
style={styles.embed}>
|
||||||
<PostEmbeds embed={item.post.embed} />
|
<PostEmbeds
|
||||||
|
embed={item.post.embed}
|
||||||
|
moderation={item.moderation.embed}
|
||||||
|
/>
|
||||||
</ContentHider>
|
</ContentHider>
|
||||||
) : null}
|
) : null}
|
||||||
{needsTranslation && (
|
{needsTranslation && (
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
AppBskyEmbedImages,
|
AppBskyEmbedImages,
|
||||||
AppBskyEmbedRecordWithMedia,
|
AppBskyEmbedRecordWithMedia,
|
||||||
|
ModerationUI,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {AtUri} from '@atproto/api'
|
import {AtUri} from '@atproto/api'
|
||||||
import {PostMeta} from '../PostMeta'
|
import {PostMeta} from '../PostMeta'
|
||||||
|
@ -13,14 +14,17 @@ import {Text} from '../text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {ComposerOptsQuote} from 'state/models/ui/shell'
|
import {ComposerOptsQuote} from 'state/models/ui/shell'
|
||||||
import {PostEmbeds} from '.'
|
import {PostEmbeds} from '.'
|
||||||
|
import {PostAlerts} from '../moderation/PostAlerts'
|
||||||
import {makeProfileLink} from 'lib/routes/links'
|
import {makeProfileLink} from 'lib/routes/links'
|
||||||
import {InfoCircleIcon} from 'lib/icons'
|
import {InfoCircleIcon} from 'lib/icons'
|
||||||
|
|
||||||
export function MaybeQuoteEmbed({
|
export function MaybeQuoteEmbed({
|
||||||
embed,
|
embed,
|
||||||
|
moderation,
|
||||||
style,
|
style,
|
||||||
}: {
|
}: {
|
||||||
embed: AppBskyEmbedRecord.View
|
embed: AppBskyEmbedRecord.View
|
||||||
|
moderation: ModerationUI
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -39,6 +43,7 @@ export function MaybeQuoteEmbed({
|
||||||
text: embed.record.value.text,
|
text: embed.record.value.text,
|
||||||
embeds: embed.record.embeds,
|
embeds: embed.record.embeds,
|
||||||
}}
|
}}
|
||||||
|
moderation={moderation}
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -66,9 +71,11 @@ export function MaybeQuoteEmbed({
|
||||||
|
|
||||||
export function QuoteEmbed({
|
export function QuoteEmbed({
|
||||||
quote,
|
quote,
|
||||||
|
moderation,
|
||||||
style,
|
style,
|
||||||
}: {
|
}: {
|
||||||
quote: ComposerOptsQuote
|
quote: ComposerOptsQuote
|
||||||
|
moderation?: ModerationUI
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -100,16 +107,19 @@ export function QuoteEmbed({
|
||||||
postHref={itemHref}
|
postHref={itemHref}
|
||||||
timestamp={quote.indexedAt}
|
timestamp={quote.indexedAt}
|
||||||
/>
|
/>
|
||||||
|
{moderation ? (
|
||||||
|
<PostAlerts moderation={moderation} style={styles.alert} />
|
||||||
|
) : null}
|
||||||
{!isEmpty ? (
|
{!isEmpty ? (
|
||||||
<Text type="post-text" style={pal.text} numberOfLines={6}>
|
<Text type="post-text" style={pal.text} numberOfLines={6}>
|
||||||
{quote.text}
|
{quote.text}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
{AppBskyEmbedImages.isView(imagesEmbed) && (
|
{AppBskyEmbedImages.isView(imagesEmbed) && (
|
||||||
<PostEmbeds embed={imagesEmbed} />
|
<PostEmbeds embed={imagesEmbed} moderation={{}} />
|
||||||
)}
|
)}
|
||||||
{AppBskyEmbedRecordWithMedia.isView(imagesEmbed) && (
|
{AppBskyEmbedRecordWithMedia.isView(imagesEmbed) && (
|
||||||
<PostEmbeds embed={imagesEmbed.media} />
|
<PostEmbeds embed={imagesEmbed.media} moderation={{}} />
|
||||||
)}
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
|
@ -140,4 +150,7 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
},
|
},
|
||||||
|
alert: {
|
||||||
|
marginBottom: 6,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
AppBskyEmbedRecordWithMedia,
|
AppBskyEmbedRecordWithMedia,
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyGraphDefs,
|
AppBskyGraphDefs,
|
||||||
|
ModerationUI,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {Link} from '../Link'
|
import {Link} from '../Link'
|
||||||
import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
|
import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
|
||||||
|
@ -28,6 +29,7 @@ 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 {isDesktopWeb} from 'platform/detection'
|
||||||
|
import {isCauseALabelOnUri} from 'lib/moderation'
|
||||||
|
|
||||||
type Embed =
|
type Embed =
|
||||||
| AppBskyEmbedRecord.View
|
| AppBskyEmbedRecord.View
|
||||||
|
@ -38,9 +40,11 @@ type Embed =
|
||||||
|
|
||||||
export function PostEmbeds({
|
export function PostEmbeds({
|
||||||
embed,
|
embed,
|
||||||
|
moderation,
|
||||||
style,
|
style,
|
||||||
}: {
|
}: {
|
||||||
embed?: Embed
|
embed?: Embed
|
||||||
|
moderation: ModerationUI
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -49,10 +53,15 @@ export function PostEmbeds({
|
||||||
// quote post with media
|
// quote post with media
|
||||||
// =
|
// =
|
||||||
if (AppBskyEmbedRecordWithMedia.isView(embed)) {
|
if (AppBskyEmbedRecordWithMedia.isView(embed)) {
|
||||||
|
const isModOnQuote =
|
||||||
|
AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
|
||||||
|
isCauseALabelOnUri(moderation.cause, embed.record.record.uri)
|
||||||
|
const mediaModeration = isModOnQuote ? {} : moderation
|
||||||
|
const quoteModeration = isModOnQuote ? moderation : {}
|
||||||
return (
|
return (
|
||||||
<View style={[styles.stackContainer, style]}>
|
<View style={[styles.stackContainer, style]}>
|
||||||
<PostEmbeds embed={embed.media} />
|
<PostEmbeds embed={embed.media} moderation={mediaModeration} />
|
||||||
<MaybeQuoteEmbed embed={embed.record} />
|
<MaybeQuoteEmbed embed={embed.record} moderation={quoteModeration} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +80,9 @@ export function PostEmbeds({
|
||||||
|
|
||||||
// quote post
|
// quote post
|
||||||
// =
|
// =
|
||||||
return <MaybeQuoteEmbed embed={embed} style={style} />
|
return (
|
||||||
|
<MaybeQuoteEmbed embed={embed} style={style} moderation={moderation} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// image embed
|
// image embed
|
||||||
|
|
Loading…
Reference in New Issue