diff --git a/src/@types/mastodon.d.ts b/src/@types/mastodon.d.ts
index be1819b1..0e452f3a 100644
--- a/src/@types/mastodon.d.ts
+++ b/src/@types/mastodon.d.ts
@@ -475,7 +475,8 @@ declare namespace Mastodon {
// Base
name: string
url: string
- // history: types
+ history: { day: string; accounts: string; uses: string }[]
+ following: boolean // Since v4.0
}
type WebSocketStream =
diff --git a/src/App.tsx b/src/App.tsx
index 01275460..2f26fdb8 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -20,6 +20,7 @@ import * as SplashScreen from 'expo-splash-screen'
import React, { useCallback, useEffect, useState } from 'react'
import { LogBox, Platform } from 'react-native'
import { GestureHandlerRootView } from 'react-native-gesture-handler'
+import { SafeAreaProvider } from 'react-native-safe-area-context'
import { enableFreeze } from 'react-native-screens'
import { QueryClientProvider } from 'react-query'
import { Provider } from 'react-redux'
@@ -95,13 +96,15 @@ const App: React.FC = () => {
}
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
)
} else {
return null
diff --git a/src/components/Message.tsx b/src/components/Message.tsx
index fe706042..ddcdc5fa 100644
--- a/src/components/Message.tsx
+++ b/src/components/Message.tsx
@@ -4,10 +4,8 @@ import { useTheme } from '@utils/styles/ThemeManager'
import { getColors, Theme } from '@utils/styles/themes'
import React, { RefObject } from 'react'
import { AccessibilityInfo } from 'react-native'
-import FlashMessage, {
- hideMessage,
- showMessage
-} from 'react-native-flash-message'
+import FlashMessage, { hideMessage, showMessage } from 'react-native-flash-message'
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
import haptics from './haptics'
const displayMessage = ({
@@ -112,6 +110,7 @@ const removeMessage = () => {
const Message = React.forwardRef((_, ref) => {
const { colors, theme } = useTheme()
+ const insets = useSafeAreaInsets()
return (
((_, ref) => {
shadowOffset: { width: 0, height: 0 },
shadowOpacity: theme === 'light' ? 0.16 : 0.24,
shadowRadius: 4,
- paddingRight: StyleConstants.Spacing.M * 2
+ paddingRight: StyleConstants.Spacing.M * 2,
+ marginTop: insets.top
}}
titleStyle={{
color: colors.primaryDefault,
diff --git a/src/helpers/features.json b/src/helpers/features.json
index 53d2d982..147b20a4 100644
--- a/src/helpers/features.json
+++ b/src/helpers/features.json
@@ -23,5 +23,10 @@
"feature": "notification_types_positive_filter",
"version": 3.5,
"reference": "https://github.com/mastodon/mastodon/releases/tag/v3.5.0"
+ },
+ {
+ "feature": "follow_tags",
+ "version": 4.0,
+ "reference": "https://github.com/mastodon/mastodon/releases/tag/v4.0.0"
}
]
\ No newline at end of file
diff --git a/src/i18n/en/screens/tabs.json b/src/i18n/en/screens/tabs.json
index eb72c7ab..ccef3557 100644
--- a/src/i18n/en/screens/tabs.json
+++ b/src/i18n/en/screens/tabs.json
@@ -310,6 +310,13 @@
"attachments": {
"name": "<0 /><1>\"s media1>"
},
+ "hashtag": {
+ "follow": "Follow",
+ "unfollow": "Unfollow"
+ },
+ "history": {
+ "name": "Edit History"
+ },
"search": {
"header": {
"prefix": "Searching",
@@ -346,9 +353,6 @@
"reblogged_by": "{{count}} boosted",
"favourited_by": "{{count}} favourited"
}
- },
- "history": {
- "name": "Edit History"
}
}
}
\ No newline at end of file
diff --git a/src/screens/AccountSelection.tsx b/src/screens/AccountSelection.tsx
index ff5e99aa..98611a07 100644
--- a/src/screens/AccountSelection.tsx
+++ b/src/screens/AccountSelection.tsx
@@ -9,7 +9,6 @@ import * as VideoThumbnails from 'expo-video-thumbnails'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { FlatList, Image, ScrollView, View } from 'react-native'
-import { SafeAreaProvider } from 'react-native-safe-area-context'
import { useSelector } from 'react-redux'
const Share = ({
@@ -76,9 +75,7 @@ const Share = ({
renderItem={({ item }) => (
)}
- ItemSeparatorComponent={() => (
-
- )}
+ ItemSeparatorComponent={() => }
/>
)
@@ -99,64 +96,60 @@ const ScreenAccountSelection = ({
const instances = useSelector(getInstances, () => true)
return (
-
-
+
- : null}
+
- {share ? : null}
-
- {t('content.select_account')}
-
-
- {instances.length
- ? instances
- .slice()
- .sort((a, b) =>
- `${a.uri}${a.account.acct}`.localeCompare(
- `${b.uri}${b.account.acct}`
- )
+ {t('content.select_account')}
+
+
+ {instances.length
+ ? instances
+ .slice()
+ .sort((a, b) =>
+ `${a.uri}${a.account.acct}`.localeCompare(`${b.uri}${b.account.acct}`)
+ )
+ .map((instance, index) => {
+ return (
+ {
+ navigationRef.navigate('Screen-Compose', {
+ type: 'share',
+ ...share
+ })
+ }}
+ />
)
- .map((instance, index) => {
- return (
- {
- navigationRef.navigate('Screen-Compose', {
- type: 'share',
- ...share
- })
- }}
- />
- )
- })
- : null}
-
+ })
+ : null}
-
-
+
+
)
}
diff --git a/src/screens/Actions.tsx b/src/screens/Actions.tsx
index c6db5ffa..54626356 100644
--- a/src/screens/Actions.tsx
+++ b/src/screens/Actions.tsx
@@ -3,11 +3,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect } from 'react'
import { Dimensions, StyleSheet, View } from 'react-native'
-import {
- PanGestureHandler,
- State,
- TapGestureHandler
-} from 'react-native-gesture-handler'
+import { PanGestureHandler, State, TapGestureHandler } from 'react-native-gesture-handler'
import Animated, {
Extrapolate,
interpolate,
@@ -17,10 +13,7 @@ import Animated, {
useSharedValue,
withTiming
} from 'react-native-reanimated'
-import {
- SafeAreaProvider,
- useSafeAreaInsets
-} from 'react-native-safe-area-context'
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
import ActionsAltText from './Actions/AltText'
import ActionsNotificationsFilter from './Actions/NotificationsFilter'
@@ -39,12 +32,7 @@ const ScreenActions = ({
}, [])
const styleTop = useAnimatedStyle(() => {
return {
- bottom: interpolate(
- panY.value,
- [0, screenHeight],
- [0, -screenHeight],
- Extrapolate.CLAMP
- )
+ bottom: interpolate(panY.value, [0, screenHeight], [0, -screenHeight], Extrapolate.CLAMP)
}
})
const dismiss = useCallback(() => {
@@ -73,45 +61,35 @@ const ScreenActions = ({
}
return (
-
-
- {
- if (nativeEvent.state === State.ACTIVE) {
- dismiss()
- }
- }}
+
+ {
+ if (nativeEvent.state === State.ACTIVE) {
+ dismiss()
+ }
+ }}
+ >
+
-
-
-
-
- {actions()}
-
-
-
-
-
-
+
+
+
+ {actions()}
+
+
+
+
+
)
}
diff --git a/src/screens/ImagesViewer.tsx b/src/screens/ImagesViewer.tsx
index 4771d265..f9d3b095 100644
--- a/src/screens/ImagesViewer.tsx
+++ b/src/screens/ImagesViewer.tsx
@@ -20,7 +20,7 @@ import { Directions, Gesture, LongPressGestureHandler } from 'react-native-gestu
import { LiveTextImageView } from 'react-native-live-text-image-view'
import { runOnJS, useSharedValue } from 'react-native-reanimated'
import { Zoom, createZoomListComponent } from 'react-native-reanimated-zoom'
-import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
import saveImage from './ImageViewer/save'
const ZoomFlatList = createZoomListComponent(FlatList)
@@ -153,7 +153,7 @@ const ScreenImagesViewer = ({
)
return (
-
+
-
+
)
}
diff --git a/src/screens/Tabs/Local.tsx b/src/screens/Tabs/Local.tsx
index acc03b1a..c5d5ac17 100644
--- a/src/screens/Tabs/Local.tsx
+++ b/src/screens/Tabs/Local.tsx
@@ -12,7 +12,7 @@ import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Platform } from 'react-native'
import ContextMenu from 'react-native-context-menu-view'
-import TabSharedRoot from './Shared/Root'
+import TabShared from './Shared'
const Stack = createNativeStackNavigator()
@@ -96,7 +96,7 @@ const TabLocal = React.memo(
/>
)}
/>
- {TabSharedRoot({ Stack })}
+ {TabShared({ Stack })}
)
},
diff --git a/src/screens/Tabs/Me.tsx b/src/screens/Tabs/Me.tsx
index 27ffcc1f..d7d2ac86 100644
--- a/src/screens/Tabs/Me.tsx
+++ b/src/screens/Tabs/Me.tsx
@@ -16,7 +16,7 @@ import TabMeSettings from './Me/Settings'
import TabMeSettingsFontsize from './Me/SettingsFontsize'
import TabMeSettingsLanguage from './Me/SettingsLanguage'
import TabMeSwitch from './Me/Switch'
-import TabSharedRoot from './Shared/Root'
+import TabShared from './Shared'
const Stack = createNativeStackNavigator()
@@ -187,7 +187,7 @@ const TabMe = React.memo(
})}
/>
- {TabSharedRoot({ Stack })}
+ {TabShared({ Stack })}
)
},
diff --git a/src/screens/Tabs/Notifications.tsx b/src/screens/Tabs/Notifications.tsx
index da04b603..e3621e49 100644
--- a/src/screens/Tabs/Notifications.tsx
+++ b/src/screens/Tabs/Notifications.tsx
@@ -10,7 +10,7 @@ import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import React, { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { Platform } from 'react-native'
-import TabSharedRoot from './Shared/Root'
+import TabShared from './Shared'
const Stack = createNativeStackNavigator()
@@ -65,7 +65,7 @@ const TabNotifications = React.memo(
children={children}
options={screenOptionsRoot}
/>
- {TabSharedRoot({ Stack })}
+ {TabShared({ Stack })}
)
},
diff --git a/src/screens/Tabs/Public.tsx b/src/screens/Tabs/Public.tsx
index 8c4a7bf7..bd493b17 100644
--- a/src/screens/Tabs/Public.tsx
+++ b/src/screens/Tabs/Public.tsx
@@ -12,7 +12,7 @@ import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Dimensions } from 'react-native'
import { TabView } from 'react-native-tab-view'
-import TabSharedRoot from './Shared/Root'
+import TabShared from './Shared'
const Stack = createNativeStackNavigator()
@@ -107,7 +107,7 @@ const TabPublic = React.memo(
return (
- {TabSharedRoot({ Stack })}
+ {TabShared({ Stack })}
)
},
diff --git a/src/screens/Tabs/Shared/Hashtag.tsx b/src/screens/Tabs/Shared/Hashtag.tsx
index 93cd5061..e905e8a7 100644
--- a/src/screens/Tabs/Shared/Hashtag.tsx
+++ b/src/screens/Tabs/Shared/Hashtag.tsx
@@ -1,24 +1,78 @@
+import haptics from '@components/haptics'
+import { HeaderRight } from '@components/Header'
+import { displayMessage } from '@components/Message'
import Timeline from '@components/Timeline'
import TimelineDefault from '@components/Timeline/Default'
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
+import { useTagsMutation, useTagsQuery } from '@utils/queryHooks/tags'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
-import React from 'react'
+import { checkInstanceFeature } from '@utils/slices/instancesSlice'
+import { useTheme } from '@utils/styles/ThemeManager'
+import React, { useEffect } from 'react'
+import { useTranslation } from 'react-i18next'
+import { useSelector } from 'react-redux'
-const TabSharedHashtag: React.FC<
- TabSharedStackScreenProps<'Tab-Shared-Hashtag'>
-> = ({
+const TabSharedHashtag: React.FC> = ({
+ navigation,
route: {
params: { hashtag }
}
}) => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }]
+
+ const { theme } = useTheme()
+ const { t } = useTranslation('screenTabs')
+
+ const canFollowTags = useSelector(checkInstanceFeature('follow_tags'))
+ const { data, isFetching, refetch } = useTagsQuery({
+ tag: hashtag,
+ options: { enabled: canFollowTags }
+ })
+ const mutation = useTagsMutation({
+ onSuccess: () => {
+ haptics('Success')
+ refetch()
+ },
+ onError: (err: any, { to }) => {
+ displayMessage({
+ theme,
+ type: 'error',
+ message: t('common:message.error.message', {
+ function: to ? t('shared.hashtag.follow') : t('shared.hashtag.unfollow')
+ }),
+ ...(err.status &&
+ typeof err.status === 'number' &&
+ err.data &&
+ err.data.error &&
+ typeof err.data.error === 'string' && {
+ description: err.data.error
+ })
+ })
+ }
+ })
+ useEffect(() => {
+ if (!canFollowTags) return
+
+ navigation.setOptions({
+ headerRight: () => (
+
+ typeof data?.following === 'boolean' &&
+ mutation.mutate({ tag: hashtag, type: 'follow', to: !data.following })
+ }
+ />
+ )
+ })
+ }, [canFollowTags, data?.following, isFetching])
+
return (
(
-
- )
+ renderItem: ({ item }) =>
}}
/>
)
diff --git a/src/screens/Tabs/Shared/Root.tsx b/src/screens/Tabs/Shared/index.tsx
similarity index 83%
rename from src/screens/Tabs/Shared/Root.tsx
rename to src/screens/Tabs/Shared/index.tsx
index ec2ff51a..a98e71c9 100644
--- a/src/screens/Tabs/Shared/Root.tsx
+++ b/src/screens/Tabs/Shared/index.tsx
@@ -20,11 +20,7 @@ import { Trans, useTranslation } from 'react-i18next'
import { Platform, TextInput, View } from 'react-native'
import ContextMenu, { ContextMenuAction } from 'react-native-context-menu-view'
-const TabSharedRoot = ({
- Stack
-}: {
- Stack: ReturnType
-}) => {
+const TabShared = ({ Stack }: { Stack: ReturnType }) => {
const { colors, mode } = useTheme()
const { t } = useTranslation('screenTabs')
@@ -50,9 +46,7 @@ const TabSharedRoot = ({
backgroundColor: `rgba(255, 255, 255, 0)`
},
title: '',
- headerLeft: () => (
- navigation.goBack()} background />
- ),
+ headerLeft: () => navigation.goBack()} background />,
headerRight: () => {
const actions: ContextMenuAction[] = []
@@ -77,13 +71,10 @@ const TabSharedRoot = ({
dropdownMenuMode
>
{}}
background
@@ -132,9 +123,7 @@ const TabSharedRoot = ({
key='Tab-Shared-Hashtag'
name='Tab-Shared-Hashtag'
component={TabSharedHashtag}
- options={({
- route
- }: TabSharedStackScreenProps<'Tab-Shared-Hashtag'>) => ({
+ options={({ route }: TabSharedStackScreenProps<'Tab-Shared-Hashtag'>) => ({
title: `#${decodeURIComponent(route.params.hashtag)}`
})}
/>
@@ -150,24 +139,16 @@ const TabSharedRoot = ({
key='Tab-Shared-Search'
name='Tab-Shared-Search'
component={TabSharedSearch}
- options={({
- navigation
- }: TabSharedStackScreenProps<'Tab-Shared-Search'>) => ({
+ options={({ navigation }: TabSharedStackScreenProps<'Tab-Shared-Search'>) => ({
...(Platform.OS === 'ios'
? {
- headerLeft: () => (
- navigation.goBack()} />
- )
+ headerLeft: () => navigation.goBack()} />
}
: { headerLeft: () => null }),
headerTitle: () => {
- const onChangeText = debounce(
- (text: string) => navigation.setParams({ text }),
- 1000,
- {
- trailing: true
- }
- )
+ const onChangeText = debounce((text: string) => navigation.setParams({ text }), 1000, {
+ trailing: true
+ })
return (
- navigation.setParams({ text })
- }
+ onSubmitEditing={({ nativeEvent: { text } }) => navigation.setParams({ text })}
placeholder={t('shared.search.header.placeholder')}
placeholderTextColor={colors.secondary}
returnKeyType='go'
@@ -216,9 +195,7 @@ const TabSharedRoot = ({
key='Tab-Shared-Toot'
name='Tab-Shared-Toot'
component={TabSharedToot}
- options={{
- title: t('shared.toot.name')
- }}
+ options={{ title: t('shared.toot.name') }}
/>
(
-
+
)
})
})}
@@ -244,4 +219,4 @@ const TabSharedRoot = ({
)
}
-export default TabSharedRoot
+export default TabShared
diff --git a/src/utils/queryHooks/tags.ts b/src/utils/queryHooks/tags.ts
new file mode 100644
index 00000000..d7fe37bc
--- /dev/null
+++ b/src/utils/queryHooks/tags.ts
@@ -0,0 +1,59 @@
+import apiInstance from '@api/instance'
+import { AxiosError } from 'axios'
+import {
+ QueryFunctionContext,
+ useMutation,
+ UseMutationOptions,
+ useQuery,
+ UseQueryOptions
+} from 'react-query'
+
+type QueryKeyFollowedTags = ['FollowedTags']
+const useFollowedTagsQuery = ({
+ options
+}: {
+ options?: UseQueryOptions
+}) => {
+ const queryKey: QueryKeyFollowedTags = ['FollowedTags']
+ return useQuery(
+ queryKey,
+ async ({ pageParam }: QueryFunctionContext) => {
+ const params: { [key: string]: string } = { ...pageParam }
+ const res = await apiInstance({ method: 'get', url: `followed_tags`, params })
+ return res.body
+ },
+ options
+ )
+}
+
+type QueryKeyTags = ['Tags', { tag: string }]
+const queryFunction = ({ queryKey }: QueryFunctionContext) => {
+ const { tag } = queryKey[1]
+
+ return apiInstance({ method: 'get', url: `tags/${tag}` }).then(res => res.body)
+}
+const useTagsQuery = ({
+ options,
+ ...queryKeyParams
+}: QueryKeyTags[1] & {
+ options?: UseQueryOptions
+}) => {
+ const queryKey: QueryKeyTags = ['Tags', { ...queryKeyParams }]
+ return useQuery(queryKey, queryFunction, options)
+}
+
+type MutationVarsAnnouncement = { tag: string; type: 'follow'; to: boolean }
+const mutationFunction = async ({ tag, type, to }: MutationVarsAnnouncement) => {
+ switch (type) {
+ case 'follow':
+ return apiInstance<{}>({
+ method: 'post',
+ url: `tags/${tag}/${to ? 'follow' : 'unfollow'}`
+ })
+ }
+}
+const useTagsMutation = (options: UseMutationOptions<{}, AxiosError, MutationVarsAnnouncement>) => {
+ return useMutation(mutationFunction, options)
+}
+
+export { useFollowedTagsQuery, useTagsQuery, useTagsMutation }
diff --git a/src/utils/slices/instancesSlice.ts b/src/utils/slices/instancesSlice.ts
index 48f56887..8747943f 100644
--- a/src/utils/slices/instancesSlice.ts
+++ b/src/utils/slices/instancesSlice.ts
@@ -29,10 +29,7 @@ const instancesSlice = createSlice({
name: 'instances',
initialState: instancesInitialState,
reducers: {
- updateInstanceActive: (
- { instances },
- action: PayloadAction
- ) => {
+ updateInstanceActive: ({ instances }, action: PayloadAction) => {
instances = instances.map(instance => {
instance.active =
instance.url === action.payload.url &&
@@ -43,9 +40,7 @@ const instancesSlice = createSlice({
},
updateInstanceAccount: (
{ instances },
- action: PayloadAction<
- Pick
- >
+ action: PayloadAction>
) => {
const activeIndex = findInstanceActive(instances)
instances[activeIndex].account = {
@@ -60,10 +55,7 @@ const instancesSlice = createSlice({
const activeIndex = findInstanceActive(instances)
instances[activeIndex].notifications_filter = action.payload
},
- updateInstanceDraft: (
- { instances },
- action: PayloadAction
- ) => {
+ updateInstanceDraft: ({ instances }, action: PayloadAction) => {
const activeIndex = findInstanceActive(instances)
const draftIndex = instances[activeIndex].drafts.findIndex(
({ timestamp }) => timestamp === action.payload.timestamp
@@ -74,10 +66,7 @@ const instancesSlice = createSlice({
instances[activeIndex].drafts[draftIndex] = action.payload
}
},
- removeInstanceDraft: (
- { instances },
- action: PayloadAction
- ) => {
+ removeInstanceDraft: ({ instances }, action: PayloadAction) => {
const activeIndex = findInstanceActive(instances)
instances[activeIndex].drafts = instances[activeIndex].drafts?.filter(
draft => draft.timestamp !== action.payload
@@ -126,9 +115,7 @@ const instancesSlice = createSlice({
action: PayloadAction
) => {
const HALF_LIFE = 60 * 60 * 24 * 7 // 1 week
- const calculateScore = (
- emoji: InstanceLatest['frequentEmojis'][0]
- ): number => {
+ const calculateScore = (emoji: InstanceLatest['frequentEmojis'][0]): number => {
var seconds = (new Date().getTime() - emoji.lastUsed) / 1000
var score = emoji.count + 1
var order = Math.log(Math.max(score, 1)) / Math.LN10
@@ -137,9 +124,7 @@ const instancesSlice = createSlice({
}
const activeIndex = findInstanceActive(instances)
const foundEmojiIndex = instances[activeIndex].frequentEmojis?.findIndex(
- e =>
- e.emoji.shortcode === action.payload.shortcode &&
- e.emoji.url === action.payload.url
+ e => e.emoji.shortcode === action.payload.shortcode && e.emoji.url === action.payload.url
)
let newEmojisSort: InstanceLatest['frequentEmojis']
if (foundEmojiIndex > -1) {
@@ -147,11 +132,11 @@ const instancesSlice = createSlice({
.map((e, i) =>
i === foundEmojiIndex
? {
- ...e,
- score: calculateScore(e),
- count: e.count + 1,
- lastUsed: new Date().getTime()
- }
+ ...e,
+ score: calculateScore(e),
+ count: e.count + 1,
+ lastUsed: new Date().getTime()
+ }
: e
)
.sort((a, b) => b.score - a.score)
@@ -218,8 +203,7 @@ const instancesSlice = createSlice({
return true
}
})
- state.instances.length &&
- (state.instances[state.instances.length - 1].active = true)
+ state.instances.length && (state.instances[state.instances.length - 1].active = true)
analytics('logout')
})
@@ -250,8 +234,7 @@ const instancesSlice = createSlice({
.addCase(updateConfiguration.fulfilled, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].version = action.payload?.version || '0'
- state.instances[activeIndex].configuration =
- action.payload.configuration
+ state.instances[activeIndex].configuration = action.payload.configuration
})
.addCase(updateConfiguration.rejected, (_, action) => {
console.error(action.error)
@@ -291,22 +274,16 @@ const instancesSlice = createSlice({
// Update Instance Push Individual Alert
.addCase(updateInstancePushAlert.fulfilled, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
- state.instances[activeIndex].push.alerts[
- action.meta.arg.changed
- ].loading = false
+ state.instances[activeIndex].push.alerts[action.meta.arg.changed].loading = false
state.instances[activeIndex].push.alerts = action.payload
})
.addCase(updateInstancePushAlert.rejected, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
- state.instances[activeIndex].push.alerts[
- action.meta.arg.changed
- ].loading = false
+ state.instances[activeIndex].push.alerts[action.meta.arg.changed].loading = false
})
.addCase(updateInstancePushAlert.pending, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
- state.instances[activeIndex].push.alerts[
- action.meta.arg.changed
- ].loading = true
+ state.instances[activeIndex].push.alerts[action.meta.arg.changed].loading = true
})
// Check if frequently used emojis still exist
@@ -317,8 +294,7 @@ const instancesSlice = createSlice({
activeIndex
].frequentEmojis?.filter(emoji => {
return action.payload?.find(
- e =>
- e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url
+ e => e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url
)
})
})
@@ -331,8 +307,7 @@ const instancesSlice = createSlice({
export const getInstanceActive = ({ instances: { instances } }: RootState) =>
findInstanceActive(instances)
-export const getInstances = ({ instances: { instances } }: RootState) =>
- instances
+export const getInstances = ({ instances: { instances } }: RootState) => instances
export const getInstance = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]
@@ -350,42 +325,30 @@ export const getInstanceVersion = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]?.version
export const checkInstanceFeature =
(feature: string) =>
- ({ instances: { instances } }: RootState): Boolean => {
- return (
- features
- .filter(f => f.feature === feature)
- .filter(
- f =>
- parseFloat(instances[findInstanceActive(instances)]?.version) >=
- f.version
- )?.length > 0
- )
- }
+ ({ instances: { instances } }: RootState): boolean => {
+ return (
+ features
+ .filter(f => f.feature === feature)
+ .filter(f => parseFloat(instances[findInstanceActive(instances)]?.version) >= f.version)
+ ?.length > 0
+ )
+ }
/* Get Instance Configuration */
-export const getInstanceConfigurationStatusMaxChars = ({
- instances: { instances }
-}: RootState) =>
- instances[findInstanceActive(instances)]?.configuration?.statuses
- .max_characters || 500
+export const getInstanceConfigurationStatusMaxChars = ({ instances: { instances } }: RootState) =>
+ instances[findInstanceActive(instances)]?.configuration?.statuses.max_characters || 500
export const getInstanceConfigurationStatusMaxAttachments = ({
instances: { instances }
}: RootState) =>
- instances[findInstanceActive(instances)]?.configuration?.statuses
- .max_media_attachments || 4
+ instances[findInstanceActive(instances)]?.configuration?.statuses.max_media_attachments || 4
-export const getInstanceConfigurationStatusCharsURL = ({
- instances: { instances }
-}: RootState) =>
- instances[findInstanceActive(instances)]?.configuration?.statuses
- .characters_reserved_per_url || 23
+export const getInstanceConfigurationStatusCharsURL = ({ instances: { instances } }: RootState) =>
+ instances[findInstanceActive(instances)]?.configuration?.statuses.characters_reserved_per_url ||
+ 23
-export const getInstanceConfigurationMediaAttachments = ({
- instances: { instances }
-}: RootState) =>
- instances[findInstanceActive(instances)]?.configuration
- ?.media_attachments || {
+export const getInstanceConfigurationMediaAttachments = ({ instances: { instances } }: RootState) =>
+ instances[findInstanceActive(instances)]?.configuration?.media_attachments || {
supported_mime_types: [
'image/jpeg',
'image/png',
@@ -418,9 +381,7 @@ export const getInstanceConfigurationMediaAttachments = ({
video_matrix_limit: 2304000
}
-export const getInstanceConfigurationPoll = ({
- instances: { instances }
-}: RootState) =>
+export const getInstanceConfigurationPoll = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]?.configuration?.polls || {
max_options: 4,
max_characters_per_option: 50,
@@ -432,16 +393,14 @@ export const getInstanceConfigurationPoll = ({
export const getInstanceAccount = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]?.account
-export const getInstanceNotificationsFilter = ({
- instances: { instances }
-}: RootState) => instances[findInstanceActive(instances)]?.notifications_filter
+export const getInstanceNotificationsFilter = ({ instances: { instances } }: RootState) =>
+ instances[findInstanceActive(instances)]?.notifications_filter
export const getInstancePush = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]?.push
-export const getInstanceTimelinesLookback = ({
- instances: { instances }
-}: RootState) => instances[findInstanceActive(instances)]?.timelinesLookback
+export const getInstanceTimelinesLookback = ({ instances: { instances } }: RootState) =>
+ instances[findInstanceActive(instances)]?.timelinesLookback
export const getInstanceMePage = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]?.mePage
@@ -449,9 +408,8 @@ export const getInstanceMePage = ({ instances: { instances } }: RootState) =>
export const getInstanceDrafts = ({ instances: { instances } }: RootState) =>
instances[findInstanceActive(instances)]?.drafts
-export const getInstanceFrequentEmojis = ({
- instances: { instances }
-}: RootState) => instances[findInstanceActive(instances)]?.frequentEmojis
+export const getInstanceFrequentEmojis = ({ instances: { instances } }: RootState) =>
+ instances[findInstanceActive(instances)]?.frequentEmojis
export const {
updateInstanceActive,