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:
3
src/@types/mastodon.d.ts
vendored
3
src/@types/mastodon.d.ts
vendored
@ -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 = {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -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 (
|
||||||
|
23
src/store.ts
23
src/store.ts
@ -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 = {
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user