implement redrafting #5

merged
opened by scanash.com targeting main
Changed files
+114 -1
src
components
PostControls
view
com
composer
+111
src/components/PostControls/PostMenu/PostMenuItems.tsx
···
import * as Clipboard from 'expo-clipboard'
import {
type AppBskyEmbedExternal,
+
type AppBskyEmbedImages,
type AppBskyEmbedRecordWithMedia,
type AppBskyEmbedVideo,
type AppBskyFeedDefs,
···
type AppBskyFeedThreadgate,
AtUri,
type RichText as RichTextAPI,
+
AppBskyEmbedRecord,
} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
···
import {Eye_Stroke2_Corner0_Rounded as Eye} from '#/components/icons/Eye'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
+
import {Pencil_Stroke2_Corner0_Rounded as Pen} from '#/components/icons/Pencil'
import {Mute_Stroke2_Corner0_Rounded as MuteIcon} from '#/components/icons/Mute'
import {Mute_Stroke2_Corner0_Rounded as Mute} from '#/components/icons/Mute'
import {PersonX_Stroke2_Corner0_Rounded as PersonX} from '#/components/icons/Person'
···
} from '#/components/moderation/ReportDialog'
import * as Prompt from '#/components/Prompt'
import {IS_INTERNAL} from '#/env'
+
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import * as bsky from '#/types/bsky'
let PostMenuItems = ({
···
const postInteractionSettingsDialogControl = useDialogControl()
const quotePostDetachConfirmControl = useDialogControl()
const hideReplyConfirmControl = useDialogControl()
+
const redraftPromptControl = useDialogControl()
const {mutateAsync: toggleReplyVisibility} =
useToggleReplyVisibilityMutation()
···
)
}
+
const {openComposer} = useOpenComposer()
+
const onRedraftPost = () => {
+
redraftPromptControl.open()
+
}
+
+
const onConfirmRedraft = () => {
+
let imageUris: {
+
uri: string
+
width: number
+
height: number
+
altText?: string
+
}[] = []
+
+
if (post.embed?.$type === 'app.bsky.embed.images#view') {
+
const embed = post.embed as AppBskyEmbedImages.View
+
imageUris = embed.images.map(img => ({
+
uri: img.fullsize,
+
width: img.aspectRatio?.width ?? 1000,
+
height: img.aspectRatio?.height ?? 1000,
+
altText: img.alt,
+
}))
+
} else if (post.embed?.$type === 'app.bsky.embed.recordWithMedia#view') {
+
const embed = post.embed as AppBskyEmbedRecordWithMedia.View
+
if (embed.media.$type === 'app.bsky.embed.images#view') {
+
const images = embed.media as AppBskyEmbedImages.View
+
imageUris = images.images.map(img => ({
+
uri: img.fullsize,
+
width: img.aspectRatio?.width ?? 1000,
+
height: img.aspectRatio?.height ?? 1000,
+
altText: img.alt,
+
}))
+
}
+
}
+
+
let quotePost: AppBskyFeedDefs.PostView | undefined
+
+
if (post.embed?.$type === 'app.bsky.embed.record#view') {
+
const embed = post.embed as AppBskyEmbedRecord.View
+
if (
+
AppBskyEmbedRecord.isViewRecord(embed.record) &&
+
AppBskyFeedPost.isRecord(embed.record.value)
+
) {
+
quotePost = {
+
uri: embed.record.uri,
+
cid: embed.record.cid,
+
author: embed.record.author,
+
record: embed.record.value,
+
indexedAt: embed.record.indexedAt,
+
} as AppBskyFeedDefs.PostView
+
}
+
} else if (post.embed?.$type === 'app.bsky.embed.recordWithMedia#view') {
+
const embed = post.embed as AppBskyEmbedRecordWithMedia.View
+
if (
+
AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
+
AppBskyFeedPost.isRecord(embed.record.record.value)
+
) {
+
const record = embed.record.record
+
quotePost = {
+
uri: record.uri,
+
cid: record.cid,
+
author: record.author,
+
record: record.value,
+
indexedAt: record.indexedAt,
+
} as AppBskyFeedDefs.PostView
+
}
+
}
+
+
let replyTo: any
+
if (record.reply) {
+
const parent = record.reply.parent || record.reply.root
+
if (parent) {
+
replyTo = {
+
uri: parent.uri,
+
cid: parent.cid,
+
}
+
}
+
}
+
+
openComposer({
+
text: record.text,
+
imageUris,
+
onPost: () => {
+
onDeletePost()
+
},
+
quote: quotePost,
+
replyTo,
+
})
+
}
+
const onToggleThreadMute = () => {
try {
if (isThreadMuted) {
···
return (
<>
+
<Prompt.Basic
+
control={redraftPromptControl}
+
title={_(msg`Redraft this post?`)}
+
description={_(
+
msg`This will delete the original post and open the composer with its content.`,
+
)}
+
onConfirm={onConfirmRedraft}
+
confirmButtonCta={_(msg`Redraft`)}
+
confirmButtonColor="primary"
+
/>
<Menu.Outer>
{isAuthor && (
<>
···
position="right"
/>
</Menu.Item>
+
<Menu.Item
+
testID="redraftPostBtn"
+
label={_(msg`Redraft`)}
+
onPress={onRedraftPost}>
+
<Menu.ItemText>{_(msg`Redraft`)}</Menu.ItemText>
+
<Menu.ItemIcon icon={Pen} position="right" />
+
</Menu.Item>
</Menu.Group>
<Menu.Divider />
</>
+3 -1
src/view/com/composer/Composer.tsx
···
keyboardShouldPersistTaps="always"
onContentSizeChange={onScrollViewContentSizeChange}
onLayout={onScrollViewLayout}>
-
{replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined}
+
{replyTo && replyTo.text && replyTo.author ? (
+
<ComposerReplyTo replyTo={replyTo} />
+
) : undefined}
{thread.posts.map((post, index) => (
<React.Fragment key={post.id}>
<ComposerPost