mirror of
https://github.com/tooot-app/app
synced 2025-02-13 02:10:39 +01:00
First post tested!
This commit is contained in:
parent
8013f6b9a2
commit
188b97fbd8
@ -6,6 +6,7 @@ const client = async ({
|
|||||||
method,
|
method,
|
||||||
instance,
|
instance,
|
||||||
endpoint,
|
endpoint,
|
||||||
|
headers,
|
||||||
query,
|
query,
|
||||||
body
|
body
|
||||||
}: {
|
}: {
|
||||||
@ -13,6 +14,7 @@ const client = async ({
|
|||||||
method: 'get' | 'post' | 'delete'
|
method: 'get' | 'post' | 'delete'
|
||||||
instance: 'local' | 'remote'
|
instance: 'local' | 'remote'
|
||||||
endpoint: string
|
endpoint: string
|
||||||
|
headers?: { [key: string]: string }
|
||||||
query?: {
|
query?: {
|
||||||
[key: string]: string | number | boolean
|
[key: string]: string | number | boolean
|
||||||
}
|
}
|
||||||
@ -28,6 +30,7 @@ const client = async ({
|
|||||||
searchParams: query,
|
searchParams: query,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
...headers,
|
||||||
...(instance === 'local' && {
|
...(instance === 'local' && {
|
||||||
Authorization: `Bearer ${state.localToken}`
|
Authorization: `Bearer ${state.localToken}`
|
||||||
})
|
})
|
||||||
|
@ -1,20 +1,106 @@
|
|||||||
import React from 'react'
|
import React, { ReactNode, useReducer } from 'react'
|
||||||
import { Alert, Pressable, Text } from 'react-native'
|
import { Alert, Pressable, Text } from 'react-native'
|
||||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
|
|
||||||
import PostMain from './PostToot/PostMain'
|
import PostMain from './PostToot/PostMain'
|
||||||
|
import client from 'src/api/client'
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator()
|
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 PostToot: React.FC = () => {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
|
|
||||||
|
const [postState, postDispatch] = useReducer(postReducer, postInitialState)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator>
|
<Stack.Navigator>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='PostMain'
|
name='PostMain'
|
||||||
component={PostMain}
|
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => (
|
headerLeft: () => (
|
||||||
<Pressable
|
<Pressable
|
||||||
@ -34,12 +120,51 @@ const PostToot: React.FC = () => {
|
|||||||
),
|
),
|
||||||
headerCenter: () => <></>,
|
headerCenter: () => <></>,
|
||||||
headerRight: () => (
|
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>
|
<Text>发嘟嘟</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
{props => (
|
||||||
|
<PostMain postState={postState} postDispatch={postDispatch} />
|
||||||
|
)}
|
||||||
|
</Stack.Screen>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Dispatch } from 'react'
|
import React, { Dispatch } from 'react'
|
||||||
import { Image, Pressable } from 'react-native'
|
import { Image, Pressable } from 'react-native'
|
||||||
|
|
||||||
import { PostAction, PostState } from './PostMain'
|
import { PostAction, PostState } from '../PostToot'
|
||||||
import updateText from './updateText'
|
import updateText from './updateText'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import React, {
|
import React, { createElement, Dispatch, useCallback, useEffect } from 'react'
|
||||||
createElement,
|
|
||||||
ReactNode,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useReducer
|
|
||||||
} from 'react'
|
|
||||||
import {
|
import {
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Pressable,
|
Pressable,
|
||||||
@ -22,94 +16,14 @@ import PostSuggestions from './PostSuggestions'
|
|||||||
import PostEmojis from './PostEmojis'
|
import PostEmojis from './PostEmojis'
|
||||||
import { useQuery } from 'react-query'
|
import { useQuery } from 'react-query'
|
||||||
import { emojisFetch } from 'src/stacks/common/emojisFetch'
|
import { emojisFetch } from 'src/stacks/common/emojisFetch'
|
||||||
|
import { PostAction, PostState } from '../PostToot'
|
||||||
|
|
||||||
export type PostState = {
|
export interface Props {
|
||||||
text: {
|
postState: PostState
|
||||||
count: number
|
postDispatch: Dispatch<PostAction>
|
||||||
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 =
|
const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
|
||||||
| {
|
|
||||||
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)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Keyboard.addListener('keyboardDidShow', _keyboardDidShow)
|
Keyboard.addListener('keyboardDidShow', _keyboardDidShow)
|
||||||
Keyboard.addListener('keyboardDidHide', _keyboardDidHide)
|
Keyboard.addListener('keyboardDidHide', _keyboardDidHide)
|
||||||
|
@ -4,7 +4,7 @@ import { FlatList } from 'react-native-gesture-handler'
|
|||||||
import { useQuery } from 'react-query'
|
import { useQuery } from 'react-query'
|
||||||
|
|
||||||
import { searchFetch } from '../../common/searchFetch'
|
import { searchFetch } from '../../common/searchFetch'
|
||||||
import { PostAction, PostState } from './PostMain'
|
import { PostAction, PostState } from '../PostToot'
|
||||||
import updateText from './updateText'
|
import updateText from './updateText'
|
||||||
|
|
||||||
declare module 'react' {
|
declare module 'react' {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { PostState } from './PostMain'
|
import { PostState } from '../PostToot'
|
||||||
|
|
||||||
const updateText = ({
|
const updateText = ({
|
||||||
onChangeText,
|
onChangeText,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user