1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Basic editing works

This commit is contained in:
Zhiyuan Zheng
2022-04-30 17:44:39 +02:00
parent 95ec76f411
commit d4f91a5756
17 changed files with 220 additions and 71 deletions

View File

@@ -14,6 +14,8 @@ import { useTheme } from '@utils/styles/ThemeManager'
import apiInstance from '@api/instance'
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
import { RootStackParamList } from '@utils/navigation/navigators'
import { useSelector } from 'react-redux'
import { checkInstanceFeature } from '@utils/slices/instancesSlice'
export interface Props {
navigation: NativeStackNavigationProp<RootStackParamList, 'Screen-Actions'>
@@ -59,22 +61,89 @@ const ActionsStatus: React.FC<Props> = ({
}
})
const canEditPost = useSelector(checkInstanceFeature('edit_post'))
return (
<MenuContainer>
<MenuHeader heading={t('shared.header.actions.status.heading')} />
{canEditPost ? (
<MenuRow
onPress={async () => {
analytics('timeline_shared_headeractions_status_edit_press', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({
method: 'get',
url: `statuses/${status.in_reply_to_id}`
}).then(res => res.body)
}
apiInstance<{
id: Mastodon.Status['id']
text: NonNullable<Mastodon.Status['text']>
spoiler_text: Mastodon.Status['spoiler_text']
}>({
method: 'get',
url: `statuses/${status.id}/source`
}).then(res => {
dismiss()
navigation.navigate('Screen-Compose', {
type: 'edit',
incomingStatus: {
...status,
text: res.body.text,
spoiler_text: res.body.spoiler_text
},
...(replyToStatus && { replyToStatus }),
queryKey,
rootQueryKey
})
})
}}
iconFront='Edit3'
title={t('shared.header.actions.status.edit.button')}
/>
) : null}
<MenuRow
onPress={() => {
analytics('timeline_shared_headeractions_status_delete_press', {
page: queryKey && queryKey[1].page
})
dismiss()
mutation.mutate({
type: 'deleteItem',
source: 'statuses',
queryKey,
rootQueryKey,
id: status.id
})
Alert.alert(
t('shared.header.actions.status.delete.alert.title'),
t('shared.header.actions.status.delete.alert.message'),
[
{
text: t(
'shared.header.actions.status.delete.alert.buttons.cancel'
),
style: 'cancel'
},
{
text: t(
'shared.header.actions.status.delete.alert.buttons.confirm'
),
style: 'destructive',
onPress: async () => {
analytics(
'timeline_shared_headeractions_status_delete_confirm',
{
page: queryKey && queryKey[1].page
}
)
dismiss()
mutation.mutate({
type: 'deleteItem',
source: 'statuses',
queryKey,
rootQueryKey,
id: status.id
})
}
}
]
)
}}
iconFront='Trash'
title={t('shared.header.actions.status.delete.button')}
@@ -85,18 +154,18 @@ const ActionsStatus: React.FC<Props> = ({
page: queryKey && queryKey[1].page
})
Alert.alert(
t('shared.header.actions.status.edit.alert.title'),
t('shared.header.actions.status.edit.alert.message'),
t('shared.header.actions.status.deleteEdit.alert.title'),
t('shared.header.actions.status.deleteEdit.alert.message'),
[
{
text: t(
'shared.header.actions.status.edit.alert.buttons.cancel'
'shared.header.actions.status.deleteEdit.alert.buttons.cancel'
),
style: 'cancel'
},
{
text: t(
'shared.header.actions.status.edit.alert.buttons.confirm'
'shared.header.actions.status.deleteEdit.alert.buttons.confirm'
),
style: 'destructive',
onPress: async () => {
@@ -106,7 +175,7 @@ const ActionsStatus: React.FC<Props> = ({
page: queryKey && queryKey[1].page
}
)
let replyToStatus: Mastodon.Status
let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({
method: 'get',
@@ -122,10 +191,9 @@ const ActionsStatus: React.FC<Props> = ({
})
.then(res => {
dismiss()
// @ts-ignore
navigation.navigate('Screen-Compose', {
type: 'edit',
incomingStatus: res.body,
type: 'deleteEdit',
incomingStatus: res.body as Mastodon.Status,
...(replyToStatus && { replyToStatus }),
queryKey
})
@@ -136,7 +204,7 @@ const ActionsStatus: React.FC<Props> = ({
)
}}
iconFront='Edit'
title={t('shared.header.actions.status.edit.button')}
title={t('shared.header.actions.status.deleteEdit.button')}
/>
<MenuRow
onPress={() => {

View File

@@ -1,11 +1,14 @@
import analytics from '@components/analytics'
import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header'
import { HeaderLeft, HeaderRight } from '@components/Header'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import haptics from '@root/components/haptics'
import formatText from '@screens/Compose/formatText'
import ComposeRoot from '@screens/Compose/Root'
import { RootStackScreenProps } from '@utils/navigation/navigators'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import {
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { updateStoreReview } from '@utils/slices/contextsSlice'
import {
getInstanceAccount,
@@ -133,6 +136,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
useEffect(() => {
switch (params?.type) {
case 'edit':
case 'deleteEdit':
if (params.incomingStatus.spoiler_text) {
formatText({
textInput: 'spoiler',
@@ -268,6 +272,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
}
return false
}, [totalTextCount, composeState.attachments.uploads, composeState.text.raw])
const mutateTimeline = useTimelineMutation({ onMutate: true })
const headerRight = useCallback(
() => (
<HeaderRight
@@ -282,7 +287,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
composeDispatch({ type: 'posting', payload: true })
composePost(params, composeState)
.then(() => {
.then(res => {
haptics('Success')
if (
Platform.OS === 'ios' &&
@@ -300,6 +305,15 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
switch (params?.type) {
case 'edit':
console.log('firing mutation')
mutateTimeline.mutate({
type: 'editItem',
queryKey: params.queryKey,
rootQueryKey: params.rootQueryKey,
status: res.body
})
break
case 'deleteEdit':
case 'reply':
if (params?.queryKey && params.queryKey[1].page === 'Toot') {
queryClient.invalidateQueries(params.queryKey)

View File

@@ -39,6 +39,7 @@ const composeParseState = (
): ComposeState => {
switch (params.type) {
case 'edit':
case 'deleteEdit':
return {
...composeInitialState,
dirty: true,

View File

@@ -51,8 +51,11 @@ const composePost = async (
formData.append('visibility', composeState.visibility)
return apiInstance<Mastodon.Status>({
method: 'post',
url: 'statuses',
method: params?.type === 'edit' ? 'put' : 'post',
url:
params?.type === 'edit'
? `statuses/${params.incomingStatus.id}`
: 'statuses',
headers: {
'Idempotency-Key': await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
@@ -67,7 +70,9 @@ const composePost = async (
composeState.attachments.sensitive +
composeState.attachments.uploads.map(upload => upload.remote?.id) +
composeState.visibility +
(params?.type === 'edit' ? Math.random() : '')
(params?.type === 'edit' || params?.type === 'deleteEdit'
? Math.random()
: '')
)
},
body: formData