mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Full login flow working
Refresh can be faster
This commit is contained in:
8
src/@types/store.d.ts → src/@types/app.d.ts
vendored
8
src/@types/store.d.ts → src/@types/app.d.ts
vendored
@@ -1,10 +1,4 @@
|
||||
declare namespace store {
|
||||
type InstanceInfoState = {
|
||||
local: string
|
||||
localToken: string
|
||||
remote: string
|
||||
}
|
||||
|
||||
declare namespace App {
|
||||
type Pages =
|
||||
| 'Following'
|
||||
| 'Local'
|
10
src/@types/mastodon.d.ts
vendored
10
src/@types/mastodon.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
declare namespace mastodon {
|
||||
declare namespace Mastodon {
|
||||
type Account = {
|
||||
// Base
|
||||
id: string
|
||||
@@ -184,6 +184,14 @@ declare namespace mastodon {
|
||||
emojis: Emoji[]
|
||||
}
|
||||
|
||||
type Preferences = {
|
||||
'posting:default:visibility'?: 'public' | 'unlisted' | 'private' | 'direct'
|
||||
'posting:default:sensitive'?: boolean
|
||||
'posting:default:language'?: string
|
||||
'reading:expand:media'?: 'default' | 'show_all' | 'hide_all'
|
||||
'reading:expand:spoilers'?: boolean
|
||||
}
|
||||
|
||||
type Status = {
|
||||
// Base
|
||||
id: string
|
||||
|
@@ -22,8 +22,9 @@ const client = async ({
|
||||
}
|
||||
body?: FormData
|
||||
}): Promise<any> => {
|
||||
const state: RootState['instanceInfo'] = store.getState().instanceInfo
|
||||
const url = instanceUrl || store.getState().instanceInfo[instance]
|
||||
const state: RootState['instances'] = store.getState().instances
|
||||
const url =
|
||||
instance === 'remote' ? instanceUrl || state.remote.url : state.local.url
|
||||
|
||||
let response
|
||||
// try {
|
||||
@@ -35,7 +36,7 @@ const client = async ({
|
||||
'Content-Type': 'application/json',
|
||||
...headers,
|
||||
...(instance === 'local' && {
|
||||
Authorization: `Bearer ${state.localToken}`
|
||||
Authorization: `Bearer ${state.local.token}`
|
||||
})
|
||||
},
|
||||
...(body && { body: body }),
|
||||
|
@@ -15,7 +15,7 @@ const renderNode = ({
|
||||
node: HTMLViewNode
|
||||
index: number
|
||||
navigation: any
|
||||
mentions?: mastodon.Mention[]
|
||||
mentions?: Mastodon.Mention[]
|
||||
showFullLink: boolean
|
||||
}) => {
|
||||
if (node.name == 'a') {
|
||||
@@ -80,9 +80,9 @@ const renderNode = ({
|
||||
|
||||
export interface Props {
|
||||
content: string
|
||||
emojis?: mastodon.Emoji[]
|
||||
emojis?: Mastodon.Emoji[]
|
||||
emojiSize?: number
|
||||
mentions?: mastodon.Mention[]
|
||||
mentions?: Mastodon.Mention[]
|
||||
showFullLink?: boolean
|
||||
linesTruncated?: number
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import Emojis from './Emojis'
|
||||
export interface Props {
|
||||
action: 'favourite' | 'follow' | 'mention' | 'poll' | 'reblog'
|
||||
name?: string
|
||||
emojis?: mastodon.Emoji[]
|
||||
emojis?: Mastodon.Emoji[]
|
||||
notification?: boolean
|
||||
}
|
||||
|
||||
|
@@ -10,10 +10,11 @@ import {
|
||||
} from 'react-native'
|
||||
import Toast from 'react-native-toast-message'
|
||||
import { useMutation, useQueryCache } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
|
||||
import client from 'src/api/client'
|
||||
import { getLocalAccountId } from 'src/stacks/common/instancesSlice'
|
||||
import store from 'src/stacks/common/store'
|
||||
|
||||
const fireMutation = async ({
|
||||
id,
|
||||
@@ -106,12 +107,12 @@ const fireMutation = async ({
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
queryKey: store.QueryKey
|
||||
status: mastodon.Status
|
||||
queryKey: App.QueryKey
|
||||
status: Mastodon.Status
|
||||
}
|
||||
|
||||
const ActionsStatus: React.FC<Props> = ({ queryKey, status }) => {
|
||||
const localAccountId = useSelector(state => state.instanceInfo.localAccountId)
|
||||
const localAccountId = getLocalAccountId(store.getState())
|
||||
const [modalVisible, setModalVisible] = useState(false)
|
||||
|
||||
const queryCache = useQueryCache()
|
||||
@@ -129,7 +130,7 @@ const ActionsStatus: React.FC<Props> = ({ queryKey, status }) => {
|
||||
// oldData &&
|
||||
// oldData.map((paging: any) => {
|
||||
// paging.toots.map(
|
||||
// (status: mastodon.Status | mastodon.Notification, i: number) => {
|
||||
// (status: Mastodon.Status | Mastodon.Notification, i: number) => {
|
||||
// if (status.id === newData.id) {
|
||||
// paging.toots[i] = newData
|
||||
// }
|
||||
|
@@ -5,7 +5,7 @@ import AttachmentImage from './Attachment/AttachmentImage'
|
||||
import AttachmentVideo from './Attachment/AttachmentVideo'
|
||||
|
||||
export interface Props {
|
||||
media_attachments: mastodon.Attachment[]
|
||||
media_attachments: Mastodon.Attachment[]
|
||||
sensitive: boolean
|
||||
width: number
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import { Button, Image, Modal, StyleSheet, Pressable, View } from 'react-native'
|
||||
import ImageViewer from 'react-native-image-zoom-viewer'
|
||||
|
||||
export interface Props {
|
||||
media_attachments: mastodon.Attachment[]
|
||||
media_attachments: Mastodon.Attachment[]
|
||||
sensitive: boolean
|
||||
width: number
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import { Video } from 'expo-av'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
|
||||
export interface Props {
|
||||
media_attachments: mastodon.Attachment[]
|
||||
media_attachments: Mastodon.Attachment[]
|
||||
sensitive: boolean
|
||||
width: number
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import { Image, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
|
||||
export interface Props {
|
||||
card: mastodon.Card
|
||||
card: Mastodon.Card
|
||||
}
|
||||
|
||||
const Card: React.FC<Props> = ({ card }) => {
|
||||
|
@@ -6,8 +6,8 @@ import ParseContent from 'src/components/ParseContent'
|
||||
|
||||
export interface Props {
|
||||
content: string
|
||||
emojis: mastodon.Emoji[]
|
||||
mentions: mastodon.Mention[]
|
||||
emojis: Mastodon.Emoji[]
|
||||
mentions: Mastodon.Mention[]
|
||||
spoiler_text?: string
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@ const regexEmoji = new RegExp(/(:[a-z0-9_]+:)/)
|
||||
|
||||
export interface Props {
|
||||
content: string
|
||||
emojis: mastodon.Emoji[]
|
||||
emojis: Mastodon.Emoji[]
|
||||
dimension: number
|
||||
}
|
||||
|
||||
|
@@ -9,6 +9,11 @@ import Emojis from './Emojis'
|
||||
import relativeTime from 'src/utils/relativeTime'
|
||||
import client from 'src/api/client'
|
||||
import { useSelector } from 'react-redux'
|
||||
import {
|
||||
getLocalAccountId,
|
||||
getLocalUrl
|
||||
} from 'src/stacks/common/instancesSlice'
|
||||
import store from 'src/stacks/common/store'
|
||||
|
||||
const fireMutation = async ({
|
||||
id,
|
||||
@@ -116,14 +121,14 @@ const fireMutation = async ({
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
queryKey: store.QueryKey
|
||||
queryKey: App.QueryKey
|
||||
accountId: string
|
||||
domain: string
|
||||
name: string
|
||||
emojis?: mastodon.Emoji[]
|
||||
emojis?: Mastodon.Emoji[]
|
||||
account: string
|
||||
created_at: string
|
||||
application?: mastodon.Application
|
||||
application?: Mastodon.Application
|
||||
}
|
||||
|
||||
const Header: React.FC<Props> = ({
|
||||
@@ -137,8 +142,8 @@ const Header: React.FC<Props> = ({
|
||||
application
|
||||
}) => {
|
||||
const navigation = useNavigation()
|
||||
const localAccountId = useSelector(state => state.instanceInfo.localAccountId)
|
||||
const localDomain = useSelector(state => state.instanceInfo.local)
|
||||
const localAccountId = getLocalAccountId(store.getState())
|
||||
const localDomain = getLocalUrl(store.getState())
|
||||
const [since, setSince] = useState(relativeTime(created_at))
|
||||
const [modalVisible, setModalVisible] = useState(false)
|
||||
|
||||
@@ -158,7 +163,7 @@ const Header: React.FC<Props> = ({
|
||||
// oldData &&
|
||||
// oldData.map((paging: any) => {
|
||||
// paging.toots.map(
|
||||
// (status: mastodon.Status | mastodon.Notification, i: number) => {
|
||||
// (status: Mastodon.Status | Mastodon.Notification, i: number) => {
|
||||
// if (status.id === newData.id) {
|
||||
// paging.toots[i] = newData
|
||||
// }
|
||||
|
@@ -4,7 +4,7 @@ import { StyleSheet, Text, View } from 'react-native'
|
||||
import Emojis from './Emojis'
|
||||
|
||||
export interface Props {
|
||||
poll: mastodon.Poll
|
||||
poll: Mastodon.Poll
|
||||
}
|
||||
// When haven't voted, result should not be shown but intead let people vote
|
||||
const Poll: React.FC<Props> = ({ poll }) => {
|
||||
|
@@ -12,8 +12,8 @@ import Card from './Status/Card'
|
||||
import ActionsStatus from './Status/ActionsStatus'
|
||||
|
||||
export interface Props {
|
||||
notification: mastodon.Notification
|
||||
queryKey: store.QueryKey
|
||||
notification: Mastodon.Notification
|
||||
queryKey: App.QueryKey
|
||||
}
|
||||
|
||||
const TootNotification: React.FC<Props> = ({ notification, queryKey }) => {
|
||||
|
@@ -12,8 +12,8 @@ import Card from './Status/Card'
|
||||
import ActionsStatus from './Status/ActionsStatus'
|
||||
|
||||
export interface Props {
|
||||
status: mastodon.Status
|
||||
queryKey: store.QueryKey
|
||||
status: Mastodon.Status
|
||||
queryKey: App.QueryKey
|
||||
}
|
||||
|
||||
const StatusInTimeline: React.FC<Props> = ({ status, queryKey }) => {
|
||||
|
@@ -1,16 +1,23 @@
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { Button, Text, TextInput, View } from 'react-native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { useQuery } from 'react-query'
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
import { instanceFetch } from 'src/stacks/common/instanceFetch'
|
||||
import { ScreenMeAuthentication } from '../Authentication'
|
||||
import client from 'src/api/client'
|
||||
import * as AppAuth from 'expo-app-auth'
|
||||
import * as AuthSession from 'expo-auth-session'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { updateLocal } from 'src/stacks/common/instancesSlice'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
|
||||
const Instance: React.FC = () => {
|
||||
const navigation = useNavigation()
|
||||
const dispatch = useDispatch()
|
||||
const [instance, setInstance] = useState('')
|
||||
const [applicationData, setApplicationData] = useState<{
|
||||
clientId: string
|
||||
clientSecret: string
|
||||
}>()
|
||||
|
||||
const { isSuccess, refetch, data } = useQuery(
|
||||
['Instance', { instance }],
|
||||
@@ -25,6 +32,7 @@ const Instance: React.FC = () => {
|
||||
debounce(
|
||||
text => {
|
||||
setInstance(text)
|
||||
setApplicationData(undefined)
|
||||
refetch()
|
||||
},
|
||||
1000,
|
||||
@@ -35,26 +43,10 @@ const Instance: React.FC = () => {
|
||||
[]
|
||||
)
|
||||
|
||||
const signInAsync = async (id: string) => {
|
||||
let authState = await AppAuth.authAsync({
|
||||
issuer: `https://${instance}`,
|
||||
scopes: ['read', 'write', 'follow', 'push'],
|
||||
clientId: id,
|
||||
redirectUrl: 'exp://127.0.0.1:19000',
|
||||
serviceConfiguration: {
|
||||
authorizationEndpoint: `https://${instance}/oauth/authorize`,
|
||||
revocationEndpoint: `https://${instance}/oauth/revoke`,
|
||||
tokenEndpoint: `https://${instance}/oauth/token`
|
||||
},
|
||||
additionalParameters: {
|
||||
response_type: 'code'
|
||||
}
|
||||
})
|
||||
console.log(authState)
|
||||
return authState
|
||||
}
|
||||
|
||||
const oauthCreateApplication = async () => {
|
||||
const createApplication = async () => {
|
||||
if (applicationData) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('client_name', 'test_dudu')
|
||||
formData.append('redirect_uris', 'exp://127.0.0.1:19000')
|
||||
@@ -68,20 +60,60 @@ const Instance: React.FC = () => {
|
||||
body: formData
|
||||
})
|
||||
if (res.body?.client_id.length > 0) {
|
||||
return Promise.resolve(res.body)
|
||||
setApplicationData({
|
||||
clientId: res.body.client_id,
|
||||
clientSecret: res.body.client_secret
|
||||
})
|
||||
return Promise.resolve()
|
||||
} else {
|
||||
return Promise.reject()
|
||||
}
|
||||
}
|
||||
|
||||
const oauthFlow = async () => {
|
||||
const applicationData = await oauthCreateApplication()
|
||||
if (applicationData.client_id.length > 0) {
|
||||
await signInAsync(applicationData.client_id)
|
||||
} else {
|
||||
console.error('Application data error')
|
||||
const [request, response, promptAsync] = AuthSession.useAuthRequest(
|
||||
{
|
||||
clientId: applicationData?.clientId!,
|
||||
clientSecret: applicationData?.clientSecret,
|
||||
scopes: ['read', 'write', 'follow', 'push'],
|
||||
redirectUri: 'exp://127.0.0.1:19000'
|
||||
// usePKCE: false
|
||||
},
|
||||
{
|
||||
authorizationEndpoint: `https://${instance}/oauth/authorize`
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
if (request?.clientId) {
|
||||
await promptAsync()
|
||||
}
|
||||
})()
|
||||
}, [request])
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
if (response?.type === 'success') {
|
||||
const { accessToken } = await AuthSession.exchangeCodeAsync(
|
||||
{
|
||||
clientId: applicationData?.clientId!,
|
||||
clientSecret: applicationData?.clientSecret,
|
||||
scopes: ['read', 'write', 'follow', 'push'],
|
||||
redirectUri: 'exp://127.0.0.1:19000',
|
||||
code: response.params.code,
|
||||
extraParams: {
|
||||
grant_type: 'authorization_code'
|
||||
}
|
||||
},
|
||||
{
|
||||
tokenEndpoint: `https://${instance}/oauth/token`
|
||||
}
|
||||
)
|
||||
dispatch(updateLocal({ url: instance, token: accessToken }))
|
||||
navigation.navigate('Local')
|
||||
}
|
||||
})()
|
||||
}, [response])
|
||||
|
||||
return (
|
||||
<View>
|
||||
@@ -99,7 +131,7 @@ const Instance: React.FC = () => {
|
||||
<Button
|
||||
title='登录'
|
||||
disabled={!data?.uri}
|
||||
onPress={async () => await oauthFlow()}
|
||||
onPress={async () => await createApplication()}
|
||||
/>
|
||||
{isSuccess && data && data.uri && (
|
||||
<View>
|
||||
|
@@ -58,8 +58,8 @@ const Information = ({
|
||||
account,
|
||||
emojis
|
||||
}: {
|
||||
account: mastodon.Account
|
||||
emojis: mastodon.Emoji[]
|
||||
account: Mastodon.Account
|
||||
emojis: Mastodon.Emoji[]
|
||||
}) => {
|
||||
return (
|
||||
<View style={styles.information}>
|
||||
|
@@ -13,6 +13,7 @@ import { useNavigation } from '@react-navigation/native'
|
||||
import store from 'src/stacks/common/store'
|
||||
import PostMain from './PostToot/PostMain'
|
||||
import client from 'src/api/client'
|
||||
import { getLocalAccountPreferences } from '../common/instancesSlice'
|
||||
|
||||
const Stack = createNativeStackNavigator()
|
||||
|
||||
@@ -31,7 +32,7 @@ export type PostState = {
|
||||
offset: number
|
||||
}
|
||||
| undefined
|
||||
emojis: mastodon.Emoji[] | undefined
|
||||
emojis: Mastodon.Emoji[] | undefined
|
||||
poll: {
|
||||
active: boolean
|
||||
total: number
|
||||
@@ -130,9 +131,10 @@ const postInitialState: PostState = {
|
||||
expire: '86400'
|
||||
},
|
||||
attachments: [],
|
||||
visibility: store.getState().instanceInfo.localAccount.locked
|
||||
? 'private'
|
||||
: 'public'
|
||||
visibility:
|
||||
getLocalAccountPreferences(store.getState())[
|
||||
'posting:default:visibility'
|
||||
] || 'public'
|
||||
}
|
||||
const postReducer = (state: PostState, action: PostAction): PostState => {
|
||||
switch (action.type) {
|
||||
|
@@ -4,13 +4,12 @@ import { setFocusHandler, useInfiniteQuery } from 'react-query'
|
||||
|
||||
import StatusInNotifications from 'src/components/StatusInNotifications'
|
||||
import StatusInTimeline from 'src/components/StatusInTimeline'
|
||||
import store from './store'
|
||||
import { timelineFetch } from './timelineFetch'
|
||||
|
||||
// Opening nesting hashtag pages
|
||||
|
||||
export interface Props {
|
||||
page: store.Pages
|
||||
page: App.Pages
|
||||
hashtag?: string
|
||||
list?: string
|
||||
toot?: string
|
||||
@@ -38,7 +37,7 @@ const Timeline: React.FC<Props> = ({
|
||||
return () => AppState.removeEventListener('change', handleAppStateChange)
|
||||
})
|
||||
|
||||
const queryKey: store.QueryKey = [
|
||||
const queryKey: App.QueryKey = [
|
||||
page,
|
||||
{ page, hashtag, list, toot, account }
|
||||
]
|
||||
|
@@ -1,15 +1,17 @@
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { Dimensions, FlatList, View } from 'react-native'
|
||||
import { Dimensions, FlatList, Text, View } from 'react-native'
|
||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||
import SegmentedControl from '@react-native-community/segmented-control'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
|
||||
import Timeline from './Timeline'
|
||||
import sharedScreens from 'src/stacks/Shared/sharedScreens'
|
||||
import { getLocalRegistered } from './instancesSlice'
|
||||
import store from './store'
|
||||
|
||||
const Stack = createNativeStackNavigator()
|
||||
|
||||
const Page = ({ item: { page } }: { item: { page: store.TimelinePage } }) => {
|
||||
const Page = ({ item: { page } }: { item: { page: App.Pages } }) => {
|
||||
return (
|
||||
<View style={{ width: Dimensions.get('window').width }}>
|
||||
<Timeline page={page} />
|
||||
@@ -19,10 +21,11 @@ const Page = ({ item: { page } }: { item: { page: store.TimelinePage } }) => {
|
||||
|
||||
export interface Props {
|
||||
name: string
|
||||
content: { title: string; page: string }[]
|
||||
content: { title: string; page: App.Pages }[]
|
||||
}
|
||||
|
||||
const TimelinesCombined: React.FC<Props> = ({ name, content }) => {
|
||||
const localRegistered = getLocalRegistered(store.getState())
|
||||
const [segment, setSegment] = useState(0)
|
||||
const [renderHeader, setRenderHeader] = useState(false)
|
||||
const [segmentManuallyTriggered, setSegmentManuallyTriggered] = useState(
|
||||
@@ -68,7 +71,13 @@ const TimelinesCombined: React.FC<Props> = ({ name, content }) => {
|
||||
data={content}
|
||||
keyExtractor={({ page }) => page}
|
||||
renderItem={({ item, index }) => {
|
||||
return <Page key={index} item={item} />
|
||||
return localRegistered || item.page === 'RemotePublic' ? (
|
||||
<Page key={index} item={item} />
|
||||
) : (
|
||||
<View style={{ width: Dimensions.get('window').width }}>
|
||||
<Text>请先登录</Text>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
ref={horizontalPaging}
|
||||
bounces={false}
|
||||
|
@@ -1,24 +0,0 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
|
||||
const instanceInfoSlice = createSlice({
|
||||
name: 'instanceInfo',
|
||||
initialState: {},
|
||||
reducers: {
|
||||
// increment (state) {
|
||||
// state.value++
|
||||
// },
|
||||
// decrement (state) {
|
||||
// state.value--
|
||||
// },
|
||||
// incrementByAmount (state, action) {
|
||||
// state.value += action.payload
|
||||
// }
|
||||
}
|
||||
})
|
||||
|
||||
// export const getCurrent = state => state.current
|
||||
// export const getCurrentToken = state => state.currentToken
|
||||
// export const getRemote = state => state.remote
|
||||
|
||||
// export const { increment, decrement, incrementByAmount } = counterSlice.actions
|
||||
export default instanceInfoSlice.reducer
|
99
src/stacks/common/instancesSlice.ts
Normal file
99
src/stacks/common/instancesSlice.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import client from 'src/api/client'
|
||||
import { RootState } from './store'
|
||||
|
||||
type InstancesState = {
|
||||
local: {
|
||||
url: string | undefined
|
||||
token: string | undefined
|
||||
account: {
|
||||
id: Mastodon.Account['id'] | undefined
|
||||
preferences: Mastodon.Preferences
|
||||
}
|
||||
}
|
||||
remote: {
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
export const updateLocal = createAsyncThunk(
|
||||
'instances/updateLocal',
|
||||
async ({
|
||||
url,
|
||||
token
|
||||
}: {
|
||||
url: InstancesState['local']['url']
|
||||
token: InstancesState['local']['token']
|
||||
}) => {
|
||||
const {
|
||||
body: { id }
|
||||
} = await client({
|
||||
method: 'get',
|
||||
instance: 'remote',
|
||||
instanceUrl: url,
|
||||
endpoint: `accounts/verify_credentials`,
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
})
|
||||
|
||||
const { body: preferences } = await client({
|
||||
method: 'get',
|
||||
instance: 'remote',
|
||||
instanceUrl: url,
|
||||
endpoint: `preferences`,
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
})
|
||||
|
||||
return {
|
||||
url,
|
||||
token,
|
||||
account: {
|
||||
id,
|
||||
preferences
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const instancesSlice = createSlice({
|
||||
name: 'instances',
|
||||
initialState: {
|
||||
local: {
|
||||
url: undefined,
|
||||
token: undefined,
|
||||
account: {
|
||||
id: undefined,
|
||||
preferences: {
|
||||
'posting:default:visibility': undefined,
|
||||
'posting:default:sensitive': undefined,
|
||||
'posting:default:language': undefined,
|
||||
'reading:expand:media': undefined,
|
||||
'reading:expand:spoilers': undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
url: 'mastodon.social'
|
||||
}
|
||||
} as InstancesState,
|
||||
reducers: {},
|
||||
extraReducers: builder => {
|
||||
builder.addCase(updateLocal.fulfilled, (state, action) => {
|
||||
state.local = action.payload
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export const getLocalRegistered = (state: RootState) =>
|
||||
state.instances.local.url !== undefined &&
|
||||
state.instances.local.token !== undefined
|
||||
export const getLocalUrl = (state: RootState) => state.instances.local.url
|
||||
export const getLocalAccountId = (state: RootState) =>
|
||||
state.instances.local.account.id
|
||||
export const getLocalAccountPreferences = (state: RootState) =>
|
||||
state.instances.local.account.preferences
|
||||
|
||||
// export const {
|
||||
// updateLocalInstance,
|
||||
// updateLocalAccount
|
||||
// } = instancesSlice.actions
|
||||
export default instancesSlice.reducer
|
@@ -1,27 +1,11 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
|
||||
import instanceInfoSlice from 'src/stacks/common/instanceInfoSlice'
|
||||
|
||||
// get site information from local storage and pass to reducers
|
||||
const preloadedState = {
|
||||
instanceInfo: {
|
||||
local: 'social.xmflsct.com',
|
||||
localToken: 'qjzJ0IjvZ1apsn0_wBkGcdjKgX7Dao9KEPhGwggPwAo',
|
||||
localAccountId: '1',
|
||||
localAccount: {
|
||||
locked: false
|
||||
},
|
||||
remote: 'mastodon.social'
|
||||
}
|
||||
}
|
||||
|
||||
const reducer = {
|
||||
instanceInfo: instanceInfoSlice
|
||||
}
|
||||
import instancesSlice from 'src/stacks/common/instancesSlice'
|
||||
|
||||
const store = configureStore({
|
||||
preloadedState,
|
||||
reducer
|
||||
reducer: {
|
||||
instances: instancesSlice
|
||||
}
|
||||
})
|
||||
|
||||
export default store
|
||||
|
@@ -95,7 +95,7 @@ export const timelineFetch = async (
|
||||
pinned: 'true'
|
||||
}
|
||||
})
|
||||
let toots: mastodon.Status[] = res.body
|
||||
let toots: Mastodon.Status[] = res.body
|
||||
res = await client({
|
||||
method: 'get',
|
||||
instance: 'local',
|
||||
|
Reference in New Issue
Block a user