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

Support max_toot_chars

See this commit of how to supply this value in API response. `instance_serializer.rb`

2bf275ba3b
This commit is contained in:
Zhiyuan Zheng
2021-02-05 13:45:02 +01:00
parent 29f2bf7457
commit 700b9ad433
6 changed files with 46 additions and 15 deletions

View File

@ -290,6 +290,9 @@ declare namespace Mastodon {
// Others // Others
thumbnail?: string thumbnail?: string
contact_account?: Account contact_account?: Account
// Custom
max_toot_chars?: number
} }
type Mention = { type Mention = {

View File

@ -149,7 +149,7 @@ const ComponentInstance: React.FC<Props> = ({
<InstanceAuth <InstanceAuth
key={Math.random()} key={Math.random()}
instanceDomain={instanceDomain} instanceDomain={instanceDomain}
instanceUri={instanceQuery.data.uri} instance={instanceQuery.data}
appData={{ appData={{
clientId: appsQuery.data.client_id, clientId: appsQuery.data.client_id,
clientSecret: appsQuery.data.client_secret clientSecret: appsQuery.data.client_secret

View File

@ -8,13 +8,13 @@ import { useDispatch } from 'react-redux'
export interface Props { export interface Props {
instanceDomain: string instanceDomain: string
// Domain can be different than uri // Domain can be different than uri
instanceUri: Mastodon.Instance['uri'] instance: Mastodon.Instance
appData: InstanceLocal['appData'] appData: InstanceLocal['appData']
goBack?: boolean goBack?: boolean
} }
const InstanceAuth = React.memo( const InstanceAuth = React.memo(
({ instanceDomain, instanceUri, appData, goBack }: Props) => { ({ instanceDomain, instance, appData, goBack }: Props) => {
const redirectUri = AuthSession.makeRedirectUri({ const redirectUri = AuthSession.makeRedirectUri({
native: 'tooot://instance-auth', native: 'tooot://instance-auth',
useProxy: false useProxy: false
@ -65,7 +65,8 @@ const InstanceAuth = React.memo(
localAddInstance({ localAddInstance({
url: instanceDomain, url: instanceDomain,
token: accessToken, token: accessToken,
uri: instanceUri, uri: instance.uri,
max_toot_chars: instance.max_toot_chars,
appData appData
}) })
) )

View File

@ -7,7 +7,10 @@ import formatText from '@screens/Compose/formatText'
import ComposeRoot from '@screens/Compose/Root' import ComposeRoot from '@screens/Compose/Root'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { updateStoreReview } from '@utils/slices/contextsSlice' import { updateStoreReview } from '@utils/slices/contextsSlice'
import { getLocalAccount } from '@utils/slices/instancesSlice' import {
getLocalAccount,
getLocalMaxTootChar
} from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect, useReducer, useState } from 'react' import React, { useCallback, useEffect, useReducer, useState } from 'react'
@ -23,7 +26,7 @@ import {
import { SafeAreaView } from 'react-native-safe-area-context' import { SafeAreaView } from 'react-native-safe-area-context'
import { createNativeStackNavigator } from 'react-native-screens/native-stack' import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { useQueryClient } from 'react-query' import { useQueryClient } from 'react-query'
import { useDispatch } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import * as Sentry from 'sentry-expo' import * as Sentry from 'sentry-expo'
import ComposeEditAttachment from './Compose/EditAttachment' import ComposeEditAttachment from './Compose/EditAttachment'
import ComposeContext from './Compose/utils/createContext' import ComposeContext from './Compose/utils/createContext'
@ -110,6 +113,7 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
} }
}, [params?.type]) }, [params?.type])
const maxTootChars = useSelector(getLocalMaxTootChar)
const totalTextCount = const totalTextCount =
(composeState.spoiler.active ? composeState.spoiler.count : 0) + (composeState.spoiler.active ? composeState.spoiler.count : 0) +
composeState.text.count composeState.text.count
@ -160,14 +164,14 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
style={[ style={[
styles.count, styles.count,
{ {
color: totalTextCount > 500 ? theme.red : theme.secondary color: totalTextCount > maxTootChars ? theme.red : theme.secondary
} }
]} ]}
> >
{totalTextCount} / 500 {totalTextCount} / {maxTootChars}
</Text> </Text>
), ),
[totalTextCount] [totalTextCount, maxTootChars]
) )
const dispatch = useDispatch() const dispatch = useDispatch()
const headerRight = useCallback( const headerRight = useCallback(
@ -217,14 +221,14 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
loading={composeState.posting} loading={composeState.posting}
disabled={ disabled={
composeState.text.raw.length < 1 || composeState.text.raw.length < 1 ||
totalTextCount > 500 || totalTextCount > maxTootChars ||
(composeState.attachments.uploads.length > 0 && (composeState.attachments.uploads.length > 0 &&
composeState.attachments.uploads.filter(upload => upload.uploading) composeState.attachments.uploads.filter(upload => upload.uploading)
.length > 0) .length > 0)
} }
/> />
), ),
[totalTextCount, composeState] [totalTextCount, maxTootChars, composeState]
) )
return ( return (

View File

@ -6,9 +6,9 @@ import {
getDefaultMiddleware getDefaultMiddleware
} from '@reduxjs/toolkit' } from '@reduxjs/toolkit'
import contextsSlice from '@utils/slices/contextsSlice' import contextsSlice from '@utils/slices/contextsSlice'
import instancesSlice from '@utils/slices/instancesSlice' import instancesSlice, { InstancesState } from '@utils/slices/instancesSlice'
import settingsSlice from '@utils/slices/settingsSlice' import settingsSlice from '@utils/slices/settingsSlice'
import { persistReducer, persistStore } from 'redux-persist' import { createMigrate, persistReducer, persistStore } from 'redux-persist'
const secureStorage = createSecureStore() const secureStorage = createSecureStore()
@ -20,11 +20,26 @@ const contextsPersistConfig = {
storage: AsyncStorage storage: AsyncStorage
} }
const instancesMigration = {
2: (state: InstancesState) => {
return {
...state,
local: {
...state.local,
instances: state.local.instances.map(instance => {
instance.max_toot_chars = 500
return instance
})
}
}
}
}
const instancesPersistConfig = { const instancesPersistConfig = {
key: 'instances', key: 'instances',
prefix, prefix,
version: 1, version: 2,
storage: secureStorage storage: secureStorage,
migrate: createMigrate(instancesMigration, { debug: true })
} }
const settingsPersistConfig = { const settingsPersistConfig = {

View File

@ -13,6 +13,7 @@ export type InstanceLocal = {
url: string url: string
token: string token: string
uri: Mastodon.Instance['uri'] uri: Mastodon.Instance['uri']
max_toot_chars: number
account: { account: {
id: Mastodon.Account['id'] id: Mastodon.Account['id']
acct: Mastodon.Account['acct'] acct: Mastodon.Account['acct']
@ -54,11 +55,13 @@ export const localAddInstance = createAsyncThunk(
url, url,
token, token,
uri, uri,
max_toot_chars = 500,
appData appData
}: { }: {
url: InstanceLocal['url'] url: InstanceLocal['url']
token: InstanceLocal['token'] token: InstanceLocal['token']
uri: Mastodon.Instance['uri'] uri: Mastodon.Instance['uri']
max_toot_chars?: number
appData: InstanceLocal['appData'] appData: InstanceLocal['appData']
}): Promise<{ type: 'add' | 'overwrite'; data: InstanceLocal }> => { }): Promise<{ type: 'add' | 'overwrite'; data: InstanceLocal }> => {
const { store } = require('@root/store') const { store } = require('@root/store')
@ -107,6 +110,7 @@ export const localAddInstance = createAsyncThunk(
url, url,
token, token,
uri, uri,
max_toot_chars,
account: { account: {
id, id,
acct, acct,
@ -273,6 +277,10 @@ export const getLocalUri = ({ instances: { local } }: RootState) =>
local.activeIndex !== null local.activeIndex !== null
? local.instances[local.activeIndex].uri ? local.instances[local.activeIndex].uri
: undefined : undefined
export const getLocalMaxTootChar = ({ instances: { local } }: RootState) =>
local.activeIndex !== null
? local.instances[local.activeIndex].max_toot_chars
: 500
export const getLocalAccount = ({ instances: { local } }: RootState) => export const getLocalAccount = ({ instances: { local } }: RootState) =>
local.activeIndex !== null local.activeIndex !== null
? local.instances[local.activeIndex].account ? local.instances[local.activeIndex].account