First post tested!

This commit is contained in:
Zhiyuan Zheng 2020-11-15 22:33:09 +01:00
parent 8013f6b9a2
commit 188b97fbd8
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
6 changed files with 141 additions and 99 deletions

View File

@ -6,6 +6,7 @@ const client = async ({
method,
instance,
endpoint,
headers,
query,
body
}: {
@ -13,6 +14,7 @@ const client = async ({
method: 'get' | 'post' | 'delete'
instance: 'local' | 'remote'
endpoint: string
headers?: { [key: string]: string }
query?: {
[key: string]: string | number | boolean
}
@ -28,6 +30,7 @@ const client = async ({
searchParams: query,
headers: {
'Content-Type': 'application/json',
...headers,
...(instance === 'local' && {
Authorization: `Bearer ${state.localToken}`
})

View File

@ -1,20 +1,106 @@
import React from 'react'
import React, { ReactNode, useReducer } from 'react'
import { Alert, Pressable, Text } from 'react-native'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { useNavigation } from '@react-navigation/native'
import PostMain from './PostToot/PostMain'
import client from 'src/api/client'
const Stack = createNativeStackNavigator()
export type PostState = {
text: {
count: number
raw: string
formatted: ReactNode
}
selection: { start: number; end: number }
overlay: null | 'suggestions' | 'emojis'
tag:
| {
type: 'url' | 'accounts' | 'hashtags'
text: string
offset: number
}
| undefined
emojis: mastodon.Emoji[] | undefined
height: {
view: number
editor: number
keyboard: number
}
}
export type PostAction =
| {
type: 'text'
payload: Partial<PostState['text']>
}
| {
type: 'selection'
payload: PostState['selection']
}
| {
type: 'overlay'
payload: PostState['overlay']
}
| {
type: 'tag'
payload: PostState['tag']
}
| {
type: 'emojis'
payload: PostState['emojis']
}
| {
type: 'height'
payload: Partial<PostState['height']>
}
const postInitialState: PostState = {
text: {
count: 0,
raw: '',
formatted: undefined
},
selection: { start: 0, end: 0 },
overlay: null,
tag: undefined,
emojis: undefined,
height: {
view: 0,
editor: 0,
keyboard: 0
}
}
const postReducer = (state: PostState, action: PostAction): PostState => {
switch (action.type) {
case 'text':
return { ...state, text: { ...state.text, ...action.payload } }
case 'selection':
return { ...state, selection: action.payload }
case 'overlay':
return { ...state, overlay: action.payload }
case 'tag':
return { ...state, tag: action.payload }
case 'emojis':
return { ...state, emojis: action.payload }
case 'height':
return { ...state, height: { ...state.height, ...action.payload } }
default:
throw new Error('Unexpected action')
}
}
const PostToot: React.FC = () => {
const navigation = useNavigation()
const [postState, postDispatch] = useReducer(postReducer, postInitialState)
return (
<Stack.Navigator>
<Stack.Screen
name='PostMain'
component={PostMain}
options={{
headerLeft: () => (
<Pressable
@ -34,12 +120,51 @@ const PostToot: React.FC = () => {
),
headerCenter: () => <></>,
headerRight: () => (
<Pressable>
<Pressable
onPress={async () => {
if (postState.text.count < 0) {
Alert.alert('字数超限', '', [
{
text: '返回继续编辑'
}
])
} else {
const res = await client({
method: 'post',
instance: 'local',
endpoint: 'statuses',
headers: {
'Idempotency-Key':
Date.now().toString() + Math.random().toString()
},
query: { status: postState.text.raw }
})
if (res.body.id) {
Alert.alert('发布成功', '', [
{
text: '好的',
onPress: () => navigation.goBack()
}
])
} else {
Alert.alert('发布失败', '', [
{
text: '返回重试'
}
])
}
}
}}
>
<Text></Text>
</Pressable>
)
}}
/>
>
{props => (
<PostMain postState={postState} postDispatch={postDispatch} />
)}
</Stack.Screen>
</Stack.Navigator>
)
}

View File

@ -1,7 +1,7 @@
import React, { Dispatch } from 'react'
import { Image, Pressable } from 'react-native'
import { PostAction, PostState } from './PostMain'
import { PostAction, PostState } from '../PostToot'
import updateText from './updateText'
export interface Props {

View File

@ -1,10 +1,4 @@
import React, {
createElement,
ReactNode,
useCallback,
useEffect,
useReducer
} from 'react'
import React, { createElement, Dispatch, useCallback, useEffect } from 'react'
import {
Keyboard,
Pressable,
@ -22,94 +16,14 @@ import PostSuggestions from './PostSuggestions'
import PostEmojis from './PostEmojis'
import { useQuery } from 'react-query'
import { emojisFetch } from 'src/stacks/common/emojisFetch'
import { PostAction, PostState } from '../PostToot'
export type PostState = {
text: {
count: number
raw: string
formatted: ReactNode
}
selection: { start: number; end: number }
overlay: null | 'suggestions' | 'emojis'
tag:
| {
type: 'url' | 'accounts' | 'hashtags'
text: string
offset: number
}
| undefined
emojis: mastodon.Emoji[] | undefined
height: {
view: number
editor: number
keyboard: number
}
export interface Props {
postState: PostState
postDispatch: Dispatch<PostAction>
}
export type PostAction =
| {
type: 'text'
payload: Partial<PostState['text']>
}
| {
type: 'selection'
payload: PostState['selection']
}
| {
type: 'overlay'
payload: PostState['overlay']
}
| {
type: 'tag'
payload: PostState['tag']
}
| {
type: 'emojis'
payload: PostState['emojis']
}
| {
type: 'height'
payload: Partial<PostState['height']>
}
const postInitialState: PostState = {
text: {
count: 0,
raw: '',
formatted: undefined
},
selection: { start: 0, end: 0 },
overlay: null,
tag: undefined,
emojis: undefined,
height: {
view: 0,
editor: 0,
keyboard: 0
}
}
const postReducer = (state: PostState, action: PostAction): PostState => {
switch (action.type) {
case 'text':
return { ...state, text: { ...state.text, ...action.payload } }
case 'selection':
return { ...state, selection: action.payload }
case 'overlay':
return { ...state, overlay: action.payload }
case 'tag':
return { ...state, tag: action.payload }
case 'emojis':
return { ...state, emojis: action.payload }
case 'height':
return { ...state, height: { ...state.height, ...action.payload } }
default:
throw new Error('Unexpected action')
}
}
const PostMain = () => {
const [postState, postDispatch] = useReducer(postReducer, postInitialState)
const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
useEffect(() => {
Keyboard.addListener('keyboardDidShow', _keyboardDidShow)
Keyboard.addListener('keyboardDidHide', _keyboardDidHide)

View File

@ -4,7 +4,7 @@ import { FlatList } from 'react-native-gesture-handler'
import { useQuery } from 'react-query'
import { searchFetch } from '../../common/searchFetch'
import { PostAction, PostState } from './PostMain'
import { PostAction, PostState } from '../PostToot'
import updateText from './updateText'
declare module 'react' {

View File

@ -1,4 +1,4 @@
import { PostState } from './PostMain'
import { PostState } from '../PostToot'
const updateText = ({
onChangeText,