2020-12-11 00:29:22 +01:00
|
|
|
import React, {
|
|
|
|
createContext,
|
|
|
|
createRef,
|
|
|
|
Dispatch,
|
|
|
|
ReactNode,
|
|
|
|
RefObject,
|
|
|
|
useEffect,
|
|
|
|
useReducer,
|
|
|
|
useState
|
|
|
|
} from 'react'
|
2020-12-06 23:51:13 +01:00
|
|
|
import {
|
|
|
|
ActivityIndicator,
|
|
|
|
Alert,
|
|
|
|
Keyboard,
|
|
|
|
KeyboardAvoidingView,
|
|
|
|
StyleSheet,
|
2020-12-11 00:29:22 +01:00
|
|
|
Text,
|
|
|
|
TextInput
|
2020-12-06 23:51:13 +01:00
|
|
|
} from 'react-native'
|
2020-11-15 23:33:01 +01:00
|
|
|
import { SafeAreaView } from 'react-native-safe-area-context'
|
2020-11-08 01:10:38 +01:00
|
|
|
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
2020-11-08 19:13:46 +01:00
|
|
|
import { useNavigation } from '@react-navigation/native'
|
2020-12-06 23:51:13 +01:00
|
|
|
import sha256 from 'crypto-js/sha256'
|
2020-11-08 01:10:38 +01:00
|
|
|
|
2020-11-21 13:32:29 +01:00
|
|
|
import { store } from 'src/store'
|
2020-12-03 22:03:06 +01:00
|
|
|
import ComposeRoot from './Compose/Root'
|
2020-11-15 22:33:09 +01:00
|
|
|
import client from 'src/api/client'
|
2020-11-21 13:19:05 +01:00
|
|
|
import { getLocalAccountPreferences } from 'src/utils/slices/instancesSlice'
|
2020-12-03 01:28:56 +01:00
|
|
|
import { HeaderLeft, HeaderRight } from 'src/components/Header'
|
2020-12-06 23:51:13 +01:00
|
|
|
import { StyleConstants } from 'src/utils/styles/constants'
|
|
|
|
import { useTheme } from 'src/utils/styles/ThemeManager'
|
2020-12-07 12:31:40 +01:00
|
|
|
import formatText from './Compose/formatText'
|
2020-11-08 01:10:38 +01:00
|
|
|
|
2020-11-15 20:29:43 +01:00
|
|
|
const Stack = createNativeStackNavigator()
|
2020-11-08 01:10:38 +01:00
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
export type ComposeState = {
|
2020-12-06 23:51:13 +01:00
|
|
|
spoiler: {
|
|
|
|
active: boolean
|
|
|
|
count: number
|
|
|
|
raw: string
|
|
|
|
formatted: ReactNode
|
|
|
|
selection: { start: number; end: number }
|
|
|
|
}
|
2020-11-15 22:33:09 +01:00
|
|
|
text: {
|
|
|
|
count: number
|
|
|
|
raw: string
|
|
|
|
formatted: ReactNode
|
2020-12-06 23:51:13 +01:00
|
|
|
selection: { start: number; end: number }
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
2020-12-10 19:19:56 +01:00
|
|
|
tag?: {
|
|
|
|
type: 'url' | 'accounts' | 'hashtags'
|
|
|
|
text: string
|
|
|
|
offset: number
|
|
|
|
length: number
|
|
|
|
}
|
2020-12-04 01:17:10 +01:00
|
|
|
emoji: {
|
|
|
|
active: boolean
|
|
|
|
emojis: { title: string; data: Mastodon.Emoji[] }[] | undefined
|
|
|
|
}
|
2020-11-17 23:57:23 +01:00
|
|
|
poll: {
|
|
|
|
active: boolean
|
|
|
|
total: number
|
|
|
|
options: {
|
2020-12-06 22:32:36 +01:00
|
|
|
'0': string | undefined
|
2020-12-05 01:55:53 +01:00
|
|
|
'1': string | undefined
|
|
|
|
'2': string | undefined
|
|
|
|
'3': string | undefined
|
2020-11-17 23:57:23 +01:00
|
|
|
}
|
|
|
|
multiple: boolean
|
|
|
|
expire:
|
|
|
|
| '300'
|
|
|
|
| '1800'
|
|
|
|
| '3600'
|
|
|
|
| '21600'
|
|
|
|
| '86400'
|
|
|
|
| '259200'
|
|
|
|
| '604800'
|
|
|
|
| string
|
|
|
|
}
|
2020-12-11 00:29:22 +01:00
|
|
|
attachments: {
|
|
|
|
sensitive: boolean
|
|
|
|
uploads: (Mastodon.Attachment & { local_url?: string })[]
|
|
|
|
}
|
2020-12-10 19:19:56 +01:00
|
|
|
attachmentUploadProgress?: { progress: number; aspect?: number }
|
2020-11-19 22:45:26 +01:00
|
|
|
visibility: 'public' | 'unlisted' | 'private' | 'direct'
|
2020-12-13 01:24:25 +01:00
|
|
|
visibilityLock: boolean
|
2020-12-07 12:31:40 +01:00
|
|
|
replyToStatus?: Mastodon.Status
|
2020-12-11 00:29:22 +01:00
|
|
|
textInputFocus: {
|
|
|
|
current: 'text' | 'spoiler'
|
|
|
|
refs: { text: RefObject<TextInput>; spoiler: RefObject<TextInput> }
|
|
|
|
}
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export type PostAction =
|
|
|
|
| {
|
2020-12-06 23:51:13 +01:00
|
|
|
type: 'spoiler'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: Partial<ComposeState['spoiler']>
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
|
|
|
| {
|
2020-12-06 23:51:13 +01:00
|
|
|
type: 'text'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: Partial<ComposeState['text']>
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'tag'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: ComposeState['tag']
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
|
|
|
| {
|
2020-12-04 01:17:10 +01:00
|
|
|
type: 'emoji'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: ComposeState['emoji']
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
2020-11-17 23:57:23 +01:00
|
|
|
| {
|
|
|
|
type: 'poll'
|
2020-12-10 19:19:56 +01:00
|
|
|
payload: Partial<ComposeState['poll']>
|
2020-11-17 23:57:23 +01:00
|
|
|
}
|
2020-11-19 22:45:26 +01:00
|
|
|
| {
|
2020-12-05 01:55:53 +01:00
|
|
|
type: 'attachments'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: Partial<ComposeState['attachments']>
|
2020-11-19 22:45:26 +01:00
|
|
|
}
|
|
|
|
| {
|
2020-12-05 01:55:53 +01:00
|
|
|
type: 'attachmentUploadProgress'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: ComposeState['attachmentUploadProgress']
|
2020-11-19 22:45:26 +01:00
|
|
|
}
|
2020-12-06 16:06:38 +01:00
|
|
|
| {
|
|
|
|
type: 'attachmentEdit'
|
|
|
|
payload: Mastodon.Attachment & { local_url?: string }
|
|
|
|
}
|
2020-11-19 22:45:26 +01:00
|
|
|
| {
|
|
|
|
type: 'visibility'
|
2020-12-07 12:31:40 +01:00
|
|
|
payload: ComposeState['visibility']
|
2020-11-19 22:45:26 +01:00
|
|
|
}
|
2020-12-11 00:29:22 +01:00
|
|
|
| {
|
|
|
|
type: 'textInputFocus'
|
|
|
|
payload: Partial<ComposeState['textInputFocus']>
|
|
|
|
}
|
2020-11-15 22:33:09 +01:00
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
const composeInitialState: ComposeState = {
|
2020-12-06 23:51:13 +01:00
|
|
|
spoiler: {
|
|
|
|
active: false,
|
|
|
|
count: 0,
|
|
|
|
raw: '',
|
|
|
|
formatted: undefined,
|
|
|
|
selection: { start: 0, end: 0 }
|
|
|
|
},
|
2020-11-15 22:33:09 +01:00
|
|
|
text: {
|
2020-12-06 23:51:13 +01:00
|
|
|
count: 0,
|
2020-11-15 22:33:09 +01:00
|
|
|
raw: '',
|
2020-12-06 23:51:13 +01:00
|
|
|
formatted: undefined,
|
|
|
|
selection: { start: 0, end: 0 }
|
2020-11-15 22:33:09 +01:00
|
|
|
},
|
|
|
|
tag: undefined,
|
2020-12-04 01:17:10 +01:00
|
|
|
emoji: { active: false, emojis: undefined },
|
2020-11-17 23:57:23 +01:00
|
|
|
poll: {
|
|
|
|
active: false,
|
|
|
|
total: 2,
|
|
|
|
options: {
|
2020-12-06 23:51:13 +01:00
|
|
|
'0': undefined,
|
2020-12-05 01:55:53 +01:00
|
|
|
'1': undefined,
|
|
|
|
'2': undefined,
|
2020-12-06 23:51:13 +01:00
|
|
|
'3': undefined
|
2020-11-17 23:57:23 +01:00
|
|
|
},
|
|
|
|
multiple: false,
|
|
|
|
expire: '86400'
|
2020-11-19 22:45:26 +01:00
|
|
|
},
|
2020-12-07 00:23:26 +01:00
|
|
|
attachments: { sensitive: false, uploads: [] },
|
2020-12-05 01:55:53 +01:00
|
|
|
attachmentUploadProgress: undefined,
|
2020-11-21 00:40:55 +01:00
|
|
|
visibility:
|
|
|
|
getLocalAccountPreferences(store.getState())[
|
|
|
|
'posting:default:visibility'
|
2020-12-07 12:31:40 +01:00
|
|
|
] || 'public',
|
2020-12-13 01:24:25 +01:00
|
|
|
visibilityLock: false,
|
2020-12-11 00:29:22 +01:00
|
|
|
replyToStatus: undefined,
|
|
|
|
textInputFocus: {
|
|
|
|
current: 'text',
|
|
|
|
refs: { text: createRef(), spoiler: createRef() }
|
|
|
|
}
|
2020-11-15 22:33:09 +01:00
|
|
|
}
|
2020-12-07 12:31:40 +01:00
|
|
|
const composeExistingState = ({
|
|
|
|
type,
|
|
|
|
incomingStatus
|
|
|
|
}: {
|
2020-12-13 01:24:25 +01:00
|
|
|
type: 'reply' | 'conversation' | 'edit'
|
2020-12-07 12:31:40 +01:00
|
|
|
incomingStatus: Mastodon.Status
|
|
|
|
}): ComposeState => {
|
|
|
|
switch (type) {
|
|
|
|
case 'edit':
|
|
|
|
return {
|
|
|
|
...composeInitialState,
|
|
|
|
...(incomingStatus.spoiler_text?.length && {
|
|
|
|
spoiler: {
|
|
|
|
active: true,
|
|
|
|
count: incomingStatus.spoiler_text.length,
|
|
|
|
raw: incomingStatus.spoiler_text,
|
|
|
|
formatted: incomingStatus.spoiler_text,
|
|
|
|
selection: { start: 0, end: 0 }
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
text: {
|
|
|
|
count: incomingStatus.text!.length,
|
|
|
|
raw: incomingStatus.text!,
|
|
|
|
formatted: undefined,
|
|
|
|
selection: { start: 0, end: 0 }
|
|
|
|
},
|
|
|
|
...(incomingStatus.poll && {
|
|
|
|
poll: {
|
|
|
|
active: true,
|
|
|
|
total: incomingStatus.poll.options.length,
|
|
|
|
options: {
|
|
|
|
'0': incomingStatus.poll.options[0].title || undefined,
|
|
|
|
'1': incomingStatus.poll.options[1].title || undefined,
|
|
|
|
'2': incomingStatus.poll.options[2].title || undefined,
|
|
|
|
'3': incomingStatus.poll.options[3].title || undefined
|
|
|
|
},
|
|
|
|
multiple: incomingStatus.poll.multiple,
|
|
|
|
expire: '86400' // !!!
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
...(incomingStatus.media_attachments && {
|
|
|
|
attachments: {
|
|
|
|
sensitive: incomingStatus.sensitive,
|
|
|
|
uploads: incomingStatus.media_attachments
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
visibility: incomingStatus.visibility
|
|
|
|
}
|
|
|
|
case 'reply':
|
2020-12-13 01:24:25 +01:00
|
|
|
case 'conversation':
|
|
|
|
const actualStatus = incomingStatus.reblog || incomingStatus
|
|
|
|
const allMentions = actualStatus.mentions.map(
|
|
|
|
mention => `@${mention.acct}`
|
|
|
|
)
|
|
|
|
let replyPlaceholder = allMentions.join(' ')
|
|
|
|
if (replyPlaceholder.length === 0) {
|
|
|
|
replyPlaceholder = `@${actualStatus.account.acct} `
|
|
|
|
} else {
|
|
|
|
replyPlaceholder = replyPlaceholder + ' '
|
|
|
|
}
|
2020-12-07 12:31:40 +01:00
|
|
|
return {
|
|
|
|
...composeInitialState,
|
|
|
|
text: {
|
|
|
|
count: replyPlaceholder.length,
|
|
|
|
raw: replyPlaceholder,
|
|
|
|
formatted: undefined,
|
|
|
|
selection: { start: 0, end: 0 }
|
2020-12-10 19:19:56 +01:00
|
|
|
},
|
2020-12-13 01:24:25 +01:00
|
|
|
...(type === 'conversation' && {
|
|
|
|
visibility: 'direct',
|
|
|
|
visibilityLock: true
|
|
|
|
}),
|
2020-12-10 19:19:56 +01:00
|
|
|
replyToStatus: incomingStatus.reblog || incomingStatus
|
2020-12-07 12:31:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const postReducer = (state: ComposeState, action: PostAction): ComposeState => {
|
2020-11-15 22:33:09 +01:00
|
|
|
switch (action.type) {
|
2020-12-06 23:51:13 +01:00
|
|
|
case 'spoiler':
|
|
|
|
return { ...state, spoiler: { ...state.spoiler, ...action.payload } }
|
2020-11-15 22:33:09 +01:00
|
|
|
case 'text':
|
|
|
|
return { ...state, text: { ...state.text, ...action.payload } }
|
|
|
|
case 'tag':
|
|
|
|
return { ...state, tag: action.payload }
|
2020-12-04 01:17:10 +01:00
|
|
|
case 'emoji':
|
|
|
|
return { ...state, emoji: action.payload }
|
2020-11-17 23:57:23 +01:00
|
|
|
case 'poll':
|
2020-12-10 19:19:56 +01:00
|
|
|
return { ...state, poll: { ...state.poll, ...action.payload } }
|
2020-12-05 01:55:53 +01:00
|
|
|
case 'attachments':
|
2020-12-07 00:23:26 +01:00
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
attachments: { ...state.attachments, ...action.payload }
|
|
|
|
}
|
2020-12-05 01:55:53 +01:00
|
|
|
case 'attachmentUploadProgress':
|
|
|
|
return { ...state, attachmentUploadProgress: action.payload }
|
2020-12-06 16:06:38 +01:00
|
|
|
case 'attachmentEdit':
|
|
|
|
return {
|
|
|
|
...state,
|
2020-12-07 00:23:26 +01:00
|
|
|
attachments: {
|
|
|
|
...state.attachments,
|
|
|
|
uploads: state.attachments.uploads.map(upload =>
|
|
|
|
upload.id === action.payload.id ? action.payload : upload
|
|
|
|
)
|
|
|
|
}
|
2020-12-06 16:06:38 +01:00
|
|
|
}
|
2020-11-19 22:45:26 +01:00
|
|
|
case 'visibility':
|
|
|
|
return { ...state, visibility: action.payload }
|
2020-12-11 00:29:22 +01:00
|
|
|
case 'textInputFocus':
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
textInputFocus: { ...state.textInputFocus, ...action.payload }
|
|
|
|
}
|
2020-11-15 22:33:09 +01:00
|
|
|
default:
|
|
|
|
throw new Error('Unexpected action')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-11 00:29:22 +01:00
|
|
|
type ContextType = {
|
|
|
|
composeState: ComposeState
|
|
|
|
composeDispatch: Dispatch<PostAction>
|
|
|
|
}
|
|
|
|
export const ComposeContext = createContext<ContextType>({} as ContextType)
|
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
export interface Props {
|
|
|
|
route: {
|
|
|
|
params:
|
|
|
|
| {
|
2020-12-13 01:24:25 +01:00
|
|
|
type?: 'reply' | 'conversation' | 'edit'
|
2020-12-07 12:31:40 +01:00
|
|
|
incomingStatus: Mastodon.Status
|
|
|
|
}
|
|
|
|
| undefined
|
|
|
|
}
|
|
|
|
}
|
2020-11-08 19:13:46 +01:00
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
const Compose: React.FC<Props> = ({ route: { params } }) => {
|
|
|
|
const navigation = useNavigation()
|
|
|
|
const { theme } = useTheme()
|
2020-12-06 23:51:13 +01:00
|
|
|
|
2020-11-15 23:33:01 +01:00
|
|
|
const [hasKeyboard, setHasKeyboard] = useState(false)
|
|
|
|
useEffect(() => {
|
|
|
|
Keyboard.addListener('keyboardWillShow', _keyboardDidShow)
|
|
|
|
Keyboard.addListener('keyboardWillHide', _keyboardDidHide)
|
|
|
|
|
|
|
|
// cleanup function
|
|
|
|
return () => {
|
|
|
|
Keyboard.removeListener('keyboardWillShow', _keyboardDidShow)
|
|
|
|
Keyboard.removeListener('keyboardWillHide', _keyboardDidHide)
|
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
const _keyboardDidShow = () => {
|
|
|
|
setHasKeyboard(true)
|
|
|
|
}
|
|
|
|
const _keyboardDidHide = () => {
|
|
|
|
setHasKeyboard(false)
|
|
|
|
}
|
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
const [composeState, composeDispatch] = useReducer(
|
|
|
|
postReducer,
|
|
|
|
params?.type && params?.incomingStatus
|
|
|
|
? composeExistingState({
|
|
|
|
type: params.type,
|
|
|
|
incomingStatus: params.incomingStatus
|
|
|
|
})
|
|
|
|
: composeInitialState
|
|
|
|
)
|
|
|
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
switch (params?.type) {
|
|
|
|
case 'edit':
|
|
|
|
if (params.incomingStatus.spoiler_text) {
|
|
|
|
formatText({
|
2020-12-11 00:29:22 +01:00
|
|
|
textInput: 'spoiler',
|
2020-12-07 12:31:40 +01:00
|
|
|
composeDispatch,
|
|
|
|
content: params.incomingStatus.spoiler_text,
|
|
|
|
disableDebounce: true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
formatText({
|
2020-12-11 00:29:22 +01:00
|
|
|
textInput: 'text',
|
2020-12-07 12:31:40 +01:00
|
|
|
composeDispatch,
|
|
|
|
content: params.incomingStatus.text!,
|
|
|
|
disableDebounce: true
|
|
|
|
})
|
|
|
|
break
|
|
|
|
case 'reply':
|
2020-12-13 01:24:25 +01:00
|
|
|
case 'conversation':
|
|
|
|
const actualStatus =
|
|
|
|
params.incomingStatus.reblog || params.incomingStatus
|
|
|
|
const allMentions = actualStatus.mentions.map(
|
|
|
|
mention => `@${mention.acct}`
|
|
|
|
)
|
|
|
|
let replyPlaceholder = allMentions.join(' ')
|
|
|
|
if (replyPlaceholder.length === 0) {
|
|
|
|
replyPlaceholder = `@${actualStatus.account.acct} `
|
|
|
|
} else {
|
|
|
|
replyPlaceholder = replyPlaceholder + ' '
|
|
|
|
}
|
2020-12-07 12:31:40 +01:00
|
|
|
formatText({
|
2020-12-11 00:29:22 +01:00
|
|
|
textInput: 'text',
|
2020-12-07 12:31:40 +01:00
|
|
|
composeDispatch,
|
2020-12-13 01:24:25 +01:00
|
|
|
content: replyPlaceholder,
|
2020-12-07 12:31:40 +01:00
|
|
|
disableDebounce: true
|
|
|
|
})
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}, [params?.type])
|
2020-11-15 22:33:09 +01:00
|
|
|
|
2020-11-17 23:57:23 +01:00
|
|
|
const tootPost = async () => {
|
2020-12-06 23:51:13 +01:00
|
|
|
setIsSubmitting(true)
|
2020-12-07 12:31:40 +01:00
|
|
|
if (composeState.text.count < 0) {
|
2020-11-17 23:57:23 +01:00
|
|
|
Alert.alert('字数超限', '', [
|
|
|
|
{
|
|
|
|
text: '返回继续编辑'
|
|
|
|
}
|
|
|
|
])
|
|
|
|
} else {
|
|
|
|
const formData = new FormData()
|
2020-12-05 01:55:53 +01:00
|
|
|
|
2020-12-13 01:24:25 +01:00
|
|
|
if (params?.type === 'conversation' || params?.type === 'reply') {
|
|
|
|
formData.append('in_reply_to_id', composeState.replyToStatus!.id)
|
|
|
|
}
|
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
if (composeState.spoiler.active) {
|
|
|
|
formData.append('spoiler_text', composeState.spoiler.raw)
|
2020-12-06 23:51:13 +01:00
|
|
|
}
|
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
formData.append('status', composeState.text.raw)
|
2020-12-05 01:55:53 +01:00
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
if (composeState.poll.active) {
|
|
|
|
Object.values(composeState.poll.options)
|
2020-12-05 01:55:53 +01:00
|
|
|
.filter(e => e?.length)
|
|
|
|
.forEach(e => formData.append('poll[options][]', e!))
|
2020-12-07 12:31:40 +01:00
|
|
|
formData.append('poll[expires_in]', composeState.poll.expire)
|
|
|
|
formData.append('poll[multiple]', composeState.poll.multiple.toString())
|
2020-11-17 23:57:23 +01:00
|
|
|
}
|
2020-12-05 01:55:53 +01:00
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
if (composeState.attachments.uploads.length) {
|
|
|
|
formData.append(
|
|
|
|
'sensitive',
|
|
|
|
composeState.attachments.sensitive.toString()
|
|
|
|
)
|
|
|
|
composeState.attachments.uploads.forEach(e =>
|
2020-12-05 01:55:53 +01:00
|
|
|
formData.append('media_ids[]', e!.id)
|
2020-11-20 01:41:46 +01:00
|
|
|
)
|
|
|
|
}
|
2020-12-05 01:55:53 +01:00
|
|
|
|
2020-12-07 12:31:40 +01:00
|
|
|
formData.append('visibility', composeState.visibility)
|
2020-11-17 23:57:23 +01:00
|
|
|
|
|
|
|
client({
|
|
|
|
method: 'post',
|
|
|
|
instance: 'local',
|
2020-12-05 01:55:53 +01:00
|
|
|
url: 'statuses',
|
2020-11-17 23:57:23 +01:00
|
|
|
headers: {
|
2020-12-06 23:51:13 +01:00
|
|
|
'Idempotency-Key': sha256(
|
2020-12-07 12:31:40 +01:00
|
|
|
composeState.spoiler.raw +
|
|
|
|
composeState.text.raw +
|
|
|
|
composeState.poll.options['0'] +
|
|
|
|
composeState.poll.options['1'] +
|
|
|
|
composeState.poll.options['2'] +
|
|
|
|
composeState.poll.options['3'] +
|
|
|
|
composeState.poll.multiple +
|
|
|
|
composeState.poll.expire +
|
|
|
|
composeState.attachments.sensitive +
|
|
|
|
composeState.attachments.uploads.map(upload => upload.id) +
|
|
|
|
composeState.visibility
|
2020-12-06 23:51:13 +01:00
|
|
|
).toString()
|
2020-11-17 23:57:23 +01:00
|
|
|
},
|
|
|
|
body: formData
|
|
|
|
})
|
|
|
|
.then(
|
|
|
|
res => {
|
|
|
|
if (res.body.id) {
|
2020-12-06 23:51:13 +01:00
|
|
|
setIsSubmitting(false)
|
2020-11-17 23:57:23 +01:00
|
|
|
Alert.alert('发布成功', '', [
|
|
|
|
{
|
|
|
|
text: '好的',
|
2020-11-20 01:41:46 +01:00
|
|
|
onPress: () => {
|
|
|
|
// clear homepage cache
|
|
|
|
navigation.goBack()
|
|
|
|
}
|
2020-11-17 23:57:23 +01:00
|
|
|
}
|
|
|
|
])
|
|
|
|
} else {
|
2020-12-06 23:51:13 +01:00
|
|
|
setIsSubmitting(false)
|
2020-11-17 23:57:23 +01:00
|
|
|
Alert.alert('发布失败', '', [
|
|
|
|
{
|
|
|
|
text: '返回重试'
|
|
|
|
}
|
|
|
|
])
|
|
|
|
}
|
|
|
|
},
|
|
|
|
error => {
|
2020-12-06 23:51:13 +01:00
|
|
|
setIsSubmitting(false)
|
2020-11-17 23:57:23 +01:00
|
|
|
Alert.alert('发布失败', error.body, [
|
|
|
|
{
|
|
|
|
text: '返回重试'
|
|
|
|
}
|
|
|
|
])
|
|
|
|
}
|
|
|
|
)
|
|
|
|
.catch(() => {
|
2020-12-06 23:51:13 +01:00
|
|
|
setIsSubmitting(false)
|
2020-11-17 23:57:23 +01:00
|
|
|
Alert.alert('发布失败', '', [
|
|
|
|
{
|
|
|
|
text: '返回重试'
|
|
|
|
}
|
|
|
|
])
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-06 23:51:13 +01:00
|
|
|
const totalTextCount =
|
2020-12-07 12:31:40 +01:00
|
|
|
(composeState.spoiler.active ? composeState.spoiler.count : 0) +
|
|
|
|
composeState.text.count
|
2020-12-11 00:29:22 +01:00
|
|
|
// doesn't work
|
|
|
|
const rawCount = composeState.text.raw.length
|
2020-12-06 23:51:13 +01:00
|
|
|
|
2020-12-13 01:24:25 +01:00
|
|
|
const postButtonText = {
|
|
|
|
conversation: '回复私信',
|
|
|
|
reply: '发布回复',
|
|
|
|
edit: '发嘟嘟'
|
|
|
|
}
|
|
|
|
|
2020-11-08 01:10:38 +01:00
|
|
|
return (
|
2020-11-15 23:33:01 +01:00
|
|
|
<KeyboardAvoidingView behavior='padding' style={{ flex: 1 }}>
|
|
|
|
<SafeAreaView
|
|
|
|
style={{ flex: 1 }}
|
|
|
|
edges={hasKeyboard ? ['left', 'right'] : ['left', 'right', 'bottom']}
|
|
|
|
>
|
|
|
|
<Stack.Navigator>
|
|
|
|
<Stack.Screen
|
|
|
|
name='PostMain'
|
|
|
|
options={{
|
|
|
|
headerLeft: () => (
|
2020-12-03 01:28:56 +01:00
|
|
|
<HeaderLeft
|
2020-11-15 23:33:01 +01:00
|
|
|
onPress={() =>
|
|
|
|
Alert.alert('确认取消编辑?', '', [
|
|
|
|
{ text: '继续编辑', style: 'cancel' },
|
2020-11-15 22:33:09 +01:00
|
|
|
{
|
2020-11-15 23:33:01 +01:00
|
|
|
text: '退出编辑',
|
|
|
|
style: 'destructive',
|
2020-11-15 22:33:09 +01:00
|
|
|
onPress: () => navigation.goBack()
|
|
|
|
}
|
|
|
|
])
|
|
|
|
}
|
2020-12-03 01:28:56 +01:00
|
|
|
text='退出编辑'
|
|
|
|
/>
|
2020-11-15 23:33:01 +01:00
|
|
|
),
|
2020-12-06 23:51:13 +01:00
|
|
|
headerCenter: () => (
|
|
|
|
<Text
|
|
|
|
style={[
|
|
|
|
styles.count,
|
|
|
|
{
|
|
|
|
color:
|
|
|
|
totalTextCount > 500 ? theme.error : theme.secondary
|
|
|
|
}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
{totalTextCount} / 500
|
|
|
|
</Text>
|
|
|
|
),
|
|
|
|
headerRight: () =>
|
|
|
|
isSubmitting ? (
|
|
|
|
<ActivityIndicator />
|
|
|
|
) : (
|
|
|
|
<HeaderRight
|
|
|
|
onPress={async () => tootPost()}
|
2020-12-13 01:24:25 +01:00
|
|
|
text={params?.type ? postButtonText[params.type] : '发嘟嘟'}
|
2020-12-11 00:29:22 +01:00
|
|
|
disabled={rawCount < 1 || totalTextCount > 500}
|
2020-12-06 23:51:13 +01:00
|
|
|
/>
|
|
|
|
)
|
2020-11-15 23:33:01 +01:00
|
|
|
}}
|
|
|
|
>
|
2020-12-03 01:28:56 +01:00
|
|
|
{() => (
|
2020-12-11 00:29:22 +01:00
|
|
|
<ComposeContext.Provider
|
|
|
|
value={{ composeState, composeDispatch }}
|
|
|
|
>
|
|
|
|
<ComposeRoot />
|
|
|
|
</ComposeContext.Provider>
|
2020-11-15 23:33:01 +01:00
|
|
|
)}
|
|
|
|
</Stack.Screen>
|
|
|
|
</Stack.Navigator>
|
|
|
|
</SafeAreaView>
|
|
|
|
</KeyboardAvoidingView>
|
2020-11-08 01:10:38 +01:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-12-06 23:51:13 +01:00
|
|
|
const styles = StyleSheet.create({
|
|
|
|
count: {
|
|
|
|
textAlign: 'center',
|
|
|
|
fontSize: StyleConstants.Font.Size.M
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-12-11 00:29:22 +01:00
|
|
|
export default Compose
|