mirror of
https://github.com/tooot-app/app
synced 2024-12-22 07:34:06 +01:00
Fixed #535
This commit is contained in:
parent
44f83e44b9
commit
1b58bcad3e
36
src/@types/mastodon.d.ts
vendored
36
src/@types/mastodon.d.ts
vendored
@ -30,6 +30,7 @@ declare namespace Mastodon {
|
||||
bot: boolean
|
||||
source?: Source
|
||||
suspended?: boolean
|
||||
role?: Role
|
||||
}
|
||||
|
||||
type Announcement = {
|
||||
@ -384,6 +385,8 @@ declare namespace Mastodon {
|
||||
mention: boolean
|
||||
poll: boolean
|
||||
status: boolean
|
||||
'admin.sign_up': boolean
|
||||
'admin.report': boolean
|
||||
}
|
||||
server_key: string
|
||||
}
|
||||
@ -409,6 +412,18 @@ declare namespace Mastodon {
|
||||
hashtags?: Tag[]
|
||||
}
|
||||
|
||||
type Role = {
|
||||
// Added since 4.0
|
||||
id: string
|
||||
name: string
|
||||
color: string
|
||||
position: number
|
||||
permissions: string
|
||||
highlighted: boolean
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
type Status = {
|
||||
// Base
|
||||
id: string
|
||||
@ -479,25 +494,4 @@ declare namespace Mastodon {
|
||||
history: { day: string; accounts: string; uses: string }[]
|
||||
following: boolean // Since v4.0
|
||||
}
|
||||
|
||||
type WebSocketStream =
|
||||
| 'user'
|
||||
| 'public'
|
||||
| 'public:local'
|
||||
| 'hashtag'
|
||||
| 'hashtag:local'
|
||||
| 'list'
|
||||
| 'direct'
|
||||
type WebSocket =
|
||||
| {
|
||||
stream: WebSocketStream[]
|
||||
event: 'update'
|
||||
payload: string // Status
|
||||
}
|
||||
| { stream: WebSocketStream[]; event: 'delete'; payload: Status['id'] }
|
||||
| {
|
||||
stream: WebSocketStream[]
|
||||
event: 'notification'
|
||||
payload: string // Notification
|
||||
}
|
||||
}
|
||||
|
@ -135,10 +135,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||
instance => paths[0] === `@${instance.account.acct}@${instance.uri}`
|
||||
)
|
||||
if (instanceIndex !== -1 && instanceActive !== instanceIndex) {
|
||||
initQuery({
|
||||
instance: instances[instanceIndex],
|
||||
prefetch: { enabled: true }
|
||||
})
|
||||
initQuery({ instance: instances[instanceIndex] })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,7 @@ interface Props {
|
||||
additionalActions?: () => void
|
||||
}
|
||||
|
||||
const AccountButton: React.FC<Props> = ({
|
||||
instance,
|
||||
selected = false,
|
||||
additionalActions
|
||||
}) => {
|
||||
const AccountButton: React.FC<Props> = ({ instance, selected = false, additionalActions }) => {
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
@ -27,12 +23,10 @@ const AccountButton: React.FC<Props> = ({
|
||||
marginBottom: StyleConstants.Spacing.M,
|
||||
marginRight: StyleConstants.Spacing.M
|
||||
}}
|
||||
content={`@${instance.account.acct}@${instance.uri}${
|
||||
selected ? ' ✓' : ''
|
||||
}`}
|
||||
content={`@${instance.account.acct}@${instance.uri}${selected ? ' ✓' : ''}`}
|
||||
onPress={() => {
|
||||
haptics('Light')
|
||||
initQuery({ instance, prefetch: { enabled: true } })
|
||||
initQuery({ instance })
|
||||
navigation.goBack()
|
||||
if (additionalActions) {
|
||||
additionalActions()
|
||||
|
@ -19,6 +19,11 @@
|
||||
"version": 3.5,
|
||||
"reference": "https://github.com/mastodon/mastodon/releases/tag/v3.5.0"
|
||||
},
|
||||
{
|
||||
"feature": "notification_type_admin_signup",
|
||||
"version": 3.5,
|
||||
"reference": "https://github.com/mastodon/mastodon/releases/tag/v3.5.0"
|
||||
},
|
||||
{
|
||||
"feature": "notification_types_positive_filter",
|
||||
"version": 3.5,
|
||||
@ -33,5 +38,10 @@
|
||||
"feature": "follow_tags",
|
||||
"version": 4.0,
|
||||
"reference": "https://github.com/mastodon/mastodon/releases/tag/v4.0.0"
|
||||
},
|
||||
{
|
||||
"feature": "notification_type_admin_report",
|
||||
"version": 4.0,
|
||||
"reference": "https://github.com/mastodon/mastodon/releases/tag/v3.5.0"
|
||||
}
|
||||
]
|
2
src/helpers/permissions.ts
Normal file
2
src/helpers/permissions.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const PERMISSION_MANAGE_REPORTS = 0x0000000000000010
|
||||
export const PERMISSION_MANAGE_USERS = 0x0000000000000400
|
@ -214,6 +214,12 @@
|
||||
"status": {
|
||||
"heading": "Toot from subscribed users"
|
||||
},
|
||||
"admin.sign_up": {
|
||||
"heading": "Admin: sign up"
|
||||
},
|
||||
"admin.report": {
|
||||
"heading": "Admin: reports"
|
||||
},
|
||||
"howitworks": "Learn how routing works"
|
||||
},
|
||||
"root": {
|
||||
@ -225,10 +231,8 @@
|
||||
}
|
||||
},
|
||||
"push": {
|
||||
"content": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled"
|
||||
}
|
||||
"content_true": "Enabled",
|
||||
"content_false": "Disabled"
|
||||
},
|
||||
"update": {
|
||||
"title": "Update to latest version"
|
||||
|
@ -21,7 +21,7 @@ const TabMeProfileRoot: React.FC<
|
||||
|
||||
const { showActionSheetWithOptions } = useActionSheet()
|
||||
|
||||
const { data, isLoading } = useProfileQuery({})
|
||||
const { data, isLoading } = useProfileQuery()
|
||||
const { mutateAsync } = useProfileMutation()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
|
@ -17,7 +17,7 @@ const ProfileAvatarHeader: React.FC<Props> = ({ type, messageRef }) => {
|
||||
|
||||
const { showActionSheetWithOptions } = useActionSheet()
|
||||
|
||||
const query = useProfileQuery({})
|
||||
const query = useProfileQuery()
|
||||
const mutation = useProfileMutation()
|
||||
|
||||
return (
|
||||
|
@ -3,28 +3,48 @@ import Icon from '@components/Icon'
|
||||
import { MenuContainer, MenuRow } from '@components/Menu'
|
||||
import CustomText from '@components/Text'
|
||||
import browserPackage from '@helpers/browserPackage'
|
||||
import { PERMISSION_MANAGE_REPORTS, PERMISSION_MANAGE_USERS } from '@helpers/permissions'
|
||||
import { useAppDispatch } from '@root/store'
|
||||
import { isDevelopment } from '@utils/checkEnvironment'
|
||||
import { useProfileQuery } from '@utils/queryHooks/profile'
|
||||
import { getExpoToken } from '@utils/slices/appSlice'
|
||||
import { updateInstancePush } from '@utils/slices/instances/updatePush'
|
||||
import { updateInstancePushAlert } from '@utils/slices/instances/updatePushAlert'
|
||||
import { updateInstancePushDecode } from '@utils/slices/instances/updatePushDecode'
|
||||
import {
|
||||
clearPushLoading,
|
||||
getInstanceAccount,
|
||||
getInstancePush,
|
||||
getInstanceUri
|
||||
} from '@utils/slices/instancesSlice'
|
||||
import { getInstanceAccount, getInstancePush, getInstanceUri } from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import * as Notifications from 'expo-notifications'
|
||||
import * as WebBrowser from 'expo-web-browser'
|
||||
import React, { useState, useEffect, useMemo } from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { AppState, Linking, ScrollView, View } from 'react-native'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
export const PUSH_DEFAULT: [
|
||||
'follow',
|
||||
'follow_request',
|
||||
'favourite',
|
||||
'reblog',
|
||||
'mention',
|
||||
'poll',
|
||||
'status'
|
||||
] = ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'status']
|
||||
export const PUSH_ADMIN: { type: 'admin.sign_up' | 'admin.report'; permission: number }[] = [
|
||||
{ type: 'admin.sign_up', permission: PERMISSION_MANAGE_USERS },
|
||||
{ type: 'admin.report', permission: PERMISSION_MANAGE_REPORTS }
|
||||
]
|
||||
export const checkPushAdminPermission = (
|
||||
permission: number,
|
||||
permissions?: string | number
|
||||
): boolean =>
|
||||
permissions
|
||||
? !!(
|
||||
(typeof permissions === 'string' ? parseInt(permissions || '0') : permissions) & permission
|
||||
)
|
||||
: false
|
||||
|
||||
const TabMePush: React.FC = () => {
|
||||
const { colors } = useTheme()
|
||||
const { t } = useTranslation('screenTabs')
|
||||
@ -58,40 +78,21 @@ const TabMePush: React.FC = () => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(clearPushLoading())
|
||||
}, [])
|
||||
|
||||
const isLoading = instancePush?.global.loading || instancePush?.decode.loading
|
||||
|
||||
const alerts = useMemo(() => {
|
||||
return instancePush?.alerts
|
||||
? (
|
||||
['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'status'] as [
|
||||
'follow',
|
||||
'follow_request',
|
||||
'favourite',
|
||||
'reblog',
|
||||
'mention',
|
||||
'poll',
|
||||
'status'
|
||||
]
|
||||
).map(alert => (
|
||||
const alerts = () =>
|
||||
instancePush?.alerts
|
||||
? PUSH_DEFAULT.map(alert => (
|
||||
<MenuRow
|
||||
key={alert}
|
||||
title={t(`me.push.${alert}.heading`)}
|
||||
switchDisabled={!pushEnabled || !instancePush.global.value || isLoading}
|
||||
switchValue={instancePush?.alerts[alert].value}
|
||||
switchDisabled={!pushEnabled || !instancePush.global}
|
||||
switchValue={instancePush?.alerts[alert]}
|
||||
switchOnValueChange={() =>
|
||||
dispatch(
|
||||
updateInstancePushAlert({
|
||||
changed: alert,
|
||||
alerts: {
|
||||
...instancePush?.alerts,
|
||||
[alert]: {
|
||||
...instancePush?.alerts[alert],
|
||||
value: !instancePush?.alerts[alert].value
|
||||
}
|
||||
[alert]: instancePush?.alerts[alert]
|
||||
}
|
||||
})
|
||||
)
|
||||
@ -99,7 +100,32 @@ const TabMePush: React.FC = () => {
|
||||
/>
|
||||
))
|
||||
: null
|
||||
}, [pushEnabled, instancePush?.global, instancePush?.alerts, isLoading])
|
||||
|
||||
const profileQuery = useProfileQuery()
|
||||
const adminAlerts = () =>
|
||||
profileQuery.data?.role?.permissions
|
||||
? PUSH_ADMIN.map(({ type, permission }) =>
|
||||
checkPushAdminPermission(permission, profileQuery.data.role?.permissions) ? (
|
||||
<MenuRow
|
||||
key={type}
|
||||
title={t(`me.push.${type}.heading`)}
|
||||
switchDisabled={!pushEnabled || !instancePush.global}
|
||||
switchValue={instancePush?.alerts[type]}
|
||||
switchOnValueChange={() =>
|
||||
dispatch(
|
||||
updateInstancePushAlert({
|
||||
changed: type,
|
||||
alerts: {
|
||||
...instancePush?.alerts,
|
||||
[type]: instancePush?.alerts[type]
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : null
|
||||
)
|
||||
: null
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
@ -134,22 +160,19 @@ const TabMePush: React.FC = () => {
|
||||
acct: `@${instanceAccount?.acct}@${instanceUri}`
|
||||
})}
|
||||
description={t('me.push.global.description')}
|
||||
loading={instancePush?.global.loading}
|
||||
switchDisabled={!pushEnabled || isLoading}
|
||||
switchValue={pushEnabled === false ? false : instancePush?.global.value}
|
||||
switchOnValueChange={() => dispatch(updateInstancePush(!instancePush?.global.value))}
|
||||
switchDisabled={!pushEnabled}
|
||||
switchValue={pushEnabled === false ? false : instancePush?.global}
|
||||
switchOnValueChange={() => dispatch(updateInstancePush(!instancePush?.global))}
|
||||
/>
|
||||
</MenuContainer>
|
||||
<MenuContainer>
|
||||
<MenuRow
|
||||
title={t('me.push.decode.heading')}
|
||||
description={t('me.push.decode.description')}
|
||||
loading={instancePush?.decode.loading}
|
||||
switchDisabled={!pushEnabled || !instancePush?.global.value || isLoading}
|
||||
switchValue={instancePush?.decode.value}
|
||||
switchOnValueChange={() =>
|
||||
dispatch(updateInstancePushDecode(!instancePush?.decode.value))
|
||||
}
|
||||
loading={instancePush?.decode}
|
||||
switchDisabled={!pushEnabled || !instancePush?.global}
|
||||
switchValue={instancePush?.decode}
|
||||
switchOnValueChange={() => dispatch(updateInstancePushDecode(!instancePush?.decode))}
|
||||
/>
|
||||
<MenuRow
|
||||
title={t('me.push.howitworks')}
|
||||
@ -161,7 +184,8 @@ const TabMePush: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
</MenuContainer>
|
||||
<MenuContainer>{alerts}</MenuContainer>
|
||||
<MenuContainer children={alerts()} />
|
||||
<MenuContainer children={adminAlerts()} />
|
||||
</>
|
||||
) : (
|
||||
<View
|
||||
@ -169,11 +193,19 @@ const TabMePush: React.FC = () => {
|
||||
flex: 1,
|
||||
minHeight: '100%',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
|
||||
}}
|
||||
>
|
||||
<Icon name='Frown' size={StyleConstants.Font.Size.L} color={colors.primaryDefault} />
|
||||
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
|
||||
<CustomText
|
||||
fontStyle='M'
|
||||
style={{
|
||||
color: colors.primaryDefault,
|
||||
textAlign: 'center',
|
||||
marginTop: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
{t('me.push.notAvailable')}
|
||||
</CustomText>
|
||||
</View>
|
||||
|
@ -50,10 +50,7 @@ const Collections: React.FC = () => {
|
||||
}
|
||||
}, [announcementsQuery.data])
|
||||
|
||||
const instancePush = useSelector(
|
||||
getInstancePush,
|
||||
(prev, next) => prev?.global.value === next?.global.value
|
||||
)
|
||||
const instancePush = useSelector(getInstancePush, (prev, next) => prev?.global === next?.global)
|
||||
|
||||
return (
|
||||
<MenuContainer>
|
||||
@ -102,11 +99,7 @@ const Collections: React.FC = () => {
|
||||
iconFront={instancePush ? 'Bell' : 'BellOff'}
|
||||
iconBack='ChevronRight'
|
||||
title={t('me.stacks.push.name')}
|
||||
content={
|
||||
instancePush.global.value
|
||||
? t('me.root.push.content.enabled')
|
||||
: t('me.root.push.content.disabled')
|
||||
}
|
||||
content={t('me.root.push.content', { context: instancePush.global.toString() })}
|
||||
onPress={() => navigation.navigate('Tab-Me-Push')}
|
||||
/>
|
||||
</MenuContainer>
|
||||
|
@ -2,6 +2,7 @@ import haptics from '@components/haptics'
|
||||
import { MenuContainer, MenuRow } from '@components/Menu'
|
||||
import { LOCALES } from '@root/i18n/locales'
|
||||
import { TabMeStackScreenProps } from '@utils/navigation/navigators'
|
||||
import { useProfileQuery } from '@utils/queryHooks/profile'
|
||||
import androidDefaults from '@utils/slices/instances/push/androidDefaults'
|
||||
import { getInstances } from '@utils/slices/instancesSlice'
|
||||
import { changeLanguage } from '@utils/slices/settingsSlice'
|
||||
@ -10,15 +11,18 @@ import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FlatList, Platform } from 'react-native'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { checkPushAdminPermission, PUSH_ADMIN, PUSH_DEFAULT } from './Push'
|
||||
|
||||
const TabMeSettingsLanguage: React.FC<
|
||||
TabMeStackScreenProps<'Tab-Me-Settings-Language'>
|
||||
> = ({ navigation }) => {
|
||||
const TabMeSettingsLanguage: React.FC<TabMeStackScreenProps<'Tab-Me-Settings-Language'>> = ({
|
||||
navigation
|
||||
}) => {
|
||||
const { i18n, t } = useTranslation('screenTabs')
|
||||
const languages = Object.entries(LOCALES)
|
||||
const instances = useSelector(getInstances)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const profileQuery = useProfileQuery({ options: { enabled: Platform.OS === 'android' } })
|
||||
|
||||
const change = (lang: string) => {
|
||||
haptics('Success')
|
||||
|
||||
@ -29,41 +33,29 @@ const TabMeSettingsLanguage: React.FC<
|
||||
if (Platform.OS === 'android') {
|
||||
instances.forEach(instance => {
|
||||
const accountFull = `@${instance.account.acct}@${instance.uri}`
|
||||
if (instance.push.decode.value === false) {
|
||||
if (instance.push.decode === false) {
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_default`, {
|
||||
groupId: accountFull,
|
||||
name: t('me.push.default.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
} else {
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_follow`, {
|
||||
groupId: accountFull,
|
||||
name: t('me.push.follow.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
Notifications.setNotificationChannelAsync(
|
||||
`${accountFull}_favourite`,
|
||||
{
|
||||
for (const push of PUSH_DEFAULT) {
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_${push}`, {
|
||||
groupId: accountFull,
|
||||
name: t('me.push.favourite.heading'),
|
||||
name: t(`me.push.${push}.heading`),
|
||||
...androidDefaults
|
||||
})
|
||||
}
|
||||
for (const { type, permission } of PUSH_ADMIN) {
|
||||
if (checkPushAdminPermission(permission, profileQuery.data?.role?.permissions)) {
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_${type}`, {
|
||||
groupId: accountFull,
|
||||
name: t(`me.push.${type}.heading`),
|
||||
...androidDefaults
|
||||
})
|
||||
}
|
||||
)
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_reblog`, {
|
||||
groupId: accountFull,
|
||||
name: t('me.push.reblog.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_mention`, {
|
||||
groupId: accountFull,
|
||||
name: t('me.push.mention.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_poll`, {
|
||||
groupId: accountFull,
|
||||
name: t('me.push.poll.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,13 +1,8 @@
|
||||
import apiInstance from '@api/instance'
|
||||
import NetInfo from '@react-native-community/netinfo'
|
||||
import { store } from '@root/store'
|
||||
import initQuery from '@utils/initQuery'
|
||||
import { getPreviousTab } from '@utils/slices/contextsSlice'
|
||||
import removeInstance from '@utils/slices/instances/remove'
|
||||
import {
|
||||
getInstance,
|
||||
updateInstanceAccount
|
||||
} from '@utils/slices/instancesSlice'
|
||||
import { getInstance, updateInstanceAccount } from '@utils/slices/instancesSlice'
|
||||
import { onlineManager } from 'react-query'
|
||||
import log from './log'
|
||||
|
||||
@ -22,9 +17,7 @@ const netInfo = async (): Promise<{
|
||||
|
||||
onlineManager.setEventListener(setOnline => {
|
||||
return NetInfo.addEventListener(state => {
|
||||
setOnline(
|
||||
typeof state.isConnected === 'boolean' ? state.isConnected : undefined
|
||||
)
|
||||
setOnline(typeof state.isConnected === 'boolean' ? state.isConnected : undefined)
|
||||
})
|
||||
})
|
||||
|
||||
@ -60,23 +53,6 @@ const netInfo = async (): Promise<{
|
||||
})
|
||||
)
|
||||
|
||||
if (instance.timelinesLookback) {
|
||||
const previousTab = getPreviousTab(store.getState())
|
||||
let loadPage:
|
||||
| Extract<App.Pages, 'Following' | 'Local' | 'LocalPublic'>
|
||||
| undefined = undefined
|
||||
if (previousTab === 'Tab-Local') {
|
||||
loadPage = 'Following'
|
||||
} else if (previousTab === 'Tab-Public') {
|
||||
loadPage = 'LocalPublic'
|
||||
}
|
||||
|
||||
// await initQuery({
|
||||
// instance,
|
||||
// prefetch: { enabled: true, page: loadPage }
|
||||
// })
|
||||
}
|
||||
|
||||
return Promise.resolve({ connected: true })
|
||||
}
|
||||
} else {
|
||||
|
@ -46,7 +46,7 @@ const instancesPersistConfig = {
|
||||
key: 'instances',
|
||||
prefix,
|
||||
storage: Platform.OS === 'ios' ? secureStorage : AsyncStorage,
|
||||
version: 10,
|
||||
version: 11,
|
||||
// @ts-ignore
|
||||
migrate: createMigrate(instancesMigration)
|
||||
}
|
||||
|
@ -1,33 +1,11 @@
|
||||
import queryClient from '@helpers/queryClient'
|
||||
import { store } from '@root/store'
|
||||
import { InstanceLatest } from './migrations/instances/migration'
|
||||
// import { prefetchTimelineQuery } from './queryHooks/timeline'
|
||||
import { updateInstanceActive } from './slices/instancesSlice'
|
||||
|
||||
const initQuery = async ({
|
||||
instance,
|
||||
prefetch
|
||||
}: {
|
||||
instance: InstanceLatest
|
||||
prefetch?: { enabled: boolean; page?: 'Following' | 'LocalPublic' }
|
||||
}) => {
|
||||
const initQuery = async ({ instance }: { instance: InstanceLatest }) => {
|
||||
store.dispatch(updateInstanceActive(instance))
|
||||
await queryClient.resetQueries()
|
||||
|
||||
// if (prefetch?.enabled && instance.timelinesLookback) {
|
||||
// if (
|
||||
// prefetch.page &&
|
||||
// instance.timelinesLookback[prefetch.page]?.ids?.length > 0
|
||||
// ) {
|
||||
// await prefetchTimelineQuery(instance.timelinesLookback[prefetch.page])
|
||||
// }
|
||||
|
||||
// for (const page of Object.keys(instance.timelinesLookback)) {
|
||||
// if (page !== prefetch.page) {
|
||||
// prefetchTimelineQuery(instance.timelinesLookback[page])
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
export default initQuery
|
||||
|
@ -6,6 +6,7 @@ import { InstanceV7 } from './v7'
|
||||
import { InstanceV8 } from './v8'
|
||||
import { InstanceV9 } from './v9'
|
||||
import { InstanceV10 } from './v10'
|
||||
import { InstanceV11 } from './v11'
|
||||
|
||||
const instancesMigration = {
|
||||
4: (state: InstanceV3): InstanceV4 => {
|
||||
@ -128,9 +129,34 @@ const instancesMigration = {
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
11: (state: { instances: InstanceV10[] }): { instances: InstanceV11[] } => {
|
||||
return {
|
||||
instances: state.instances.map(instance => {
|
||||
return {
|
||||
...instance,
|
||||
push: {
|
||||
...instance.push,
|
||||
global: instance.push.global.value,
|
||||
decode: instance.push.decode.value,
|
||||
alerts: {
|
||||
follow: instance.push.alerts.follow.value,
|
||||
follow_request: instance.push.alerts.follow_request.value,
|
||||
favourite: instance.push.alerts.favourite.value,
|
||||
reblog: instance.push.alerts.reblog.value,
|
||||
mention: instance.push.alerts.mention.value,
|
||||
poll: instance.push.alerts.poll.value,
|
||||
status: instance.push.alerts.status.value,
|
||||
'admin.sign_up': false,
|
||||
'admin.report': false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { InstanceV10 as InstanceLatest }
|
||||
export { InstanceV11 as InstanceLatest }
|
||||
|
||||
export default instancesMigration
|
||||
|
60
src/utils/migrations/instances/v11.ts
Normal file
60
src/utils/migrations/instances/v11.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { ComposeStateDraft } from '@screens/Compose/utils/types'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
|
||||
export type InstanceV11 = {
|
||||
active: boolean
|
||||
appData: {
|
||||
clientId: string
|
||||
clientSecret: string
|
||||
}
|
||||
url: string
|
||||
token: string
|
||||
uri: Mastodon.Instance['uri']
|
||||
urls: Mastodon.Instance['urls']
|
||||
account: {
|
||||
id: Mastodon.Account['id']
|
||||
acct: Mastodon.Account['acct']
|
||||
avatarStatic: Mastodon.Account['avatar_static']
|
||||
preferences: Mastodon.Preferences
|
||||
}
|
||||
version: string
|
||||
configuration?: Mastodon.Instance['configuration']
|
||||
filters: Mastodon.Filter[]
|
||||
notifications_filter: {
|
||||
follow: boolean
|
||||
follow_request: boolean
|
||||
favourite: boolean
|
||||
reblog: boolean
|
||||
mention: boolean
|
||||
poll: boolean
|
||||
status: boolean
|
||||
update: boolean
|
||||
}
|
||||
push: {
|
||||
global: boolean
|
||||
decode: boolean
|
||||
alerts: Mastodon.PushSubscription['alerts']
|
||||
keys: {
|
||||
auth?: string
|
||||
public?: string // legacy
|
||||
private?: string // legacy
|
||||
}
|
||||
}
|
||||
timelinesLookback?: {
|
||||
[key: string]: {
|
||||
queryKey: QueryKeyTimeline
|
||||
ids: Mastodon.Status['id'][]
|
||||
}
|
||||
}
|
||||
mePage: {
|
||||
lists: { shown: boolean }
|
||||
announcements: { shown: boolean; unread: number }
|
||||
}
|
||||
drafts: ComposeStateDraft[]
|
||||
frequentEmojis: {
|
||||
emoji: Pick<Mastodon.Emoji, 'shortcode' | 'url' | 'static_url'>
|
||||
score: number
|
||||
count: number
|
||||
lastUsed: number
|
||||
}[]
|
||||
}
|
@ -23,7 +23,7 @@ const pushUseConnect = () => {
|
||||
|
||||
const expoToken = useSelector(getExpoToken)
|
||||
const instances = useSelector(getInstances, (prev, next) => prev.length === next.length)
|
||||
const pushEnabled = instances.filter(instance => instance.push.global.value)
|
||||
const pushEnabled = instances.filter(instance => instance.push.global)
|
||||
|
||||
const connect = () => {
|
||||
apiTooot({
|
||||
@ -60,7 +60,7 @@ const pushUseConnect = () => {
|
||||
dispatch(disableAllPushes())
|
||||
|
||||
instances.forEach(instance => {
|
||||
if (instance.push.global.value) {
|
||||
if (instance.push.global) {
|
||||
apiGeneral<{}>({
|
||||
method: 'delete',
|
||||
domain: instance.url,
|
||||
|
@ -31,10 +31,7 @@ const pushUseReceive = () => {
|
||||
description: notification.request.content.body!,
|
||||
onPress: () => {
|
||||
if (notificationIndex !== -1) {
|
||||
initQuery({
|
||||
instance: instances[notificationIndex],
|
||||
prefetch: { enabled: true }
|
||||
})
|
||||
initQuery({ instance: instances[notificationIndex] })
|
||||
}
|
||||
pushUseNavigate(payloadData.notification_id)
|
||||
}
|
||||
|
@ -27,10 +27,7 @@ const pushUseRespond = () => {
|
||||
instance.account.id === payloadData.accountId
|
||||
)
|
||||
if (notificationIndex !== -1) {
|
||||
initQuery({
|
||||
instance: instances[notificationIndex],
|
||||
prefetch: { enabled: true }
|
||||
})
|
||||
initQuery({ instance: instances[notificationIndex] })
|
||||
}
|
||||
pushUseNavigate(payloadData.notification_id)
|
||||
}
|
||||
|
@ -21,12 +21,12 @@ const queryFunction = async () => {
|
||||
return res.body
|
||||
}
|
||||
|
||||
const useProfileQuery = ({
|
||||
options
|
||||
}: {
|
||||
options?: UseQueryOptions<AccountWithSource, AxiosError>
|
||||
}) => {
|
||||
return useQuery(queryKey, queryFunction, options)
|
||||
const useProfileQuery = (
|
||||
params: {
|
||||
options: UseQueryOptions<AccountWithSource, AxiosError>
|
||||
} | void
|
||||
) => {
|
||||
return useQuery(queryKey, queryFunction, params?.options)
|
||||
}
|
||||
|
||||
type MutationVarsProfileBase =
|
||||
|
@ -90,16 +90,18 @@ const addInstance = createAsyncThunk(
|
||||
update: true
|
||||
},
|
||||
push: {
|
||||
global: { loading: false, value: false },
|
||||
decode: { loading: false, value: false },
|
||||
global: false,
|
||||
decode: false,
|
||||
alerts: {
|
||||
follow: { loading: false, value: true },
|
||||
follow_request: { loading: false, value: true },
|
||||
favourite: { loading: false, value: true },
|
||||
reblog: { loading: false, value: true },
|
||||
mention: { loading: false, value: true },
|
||||
poll: { loading: false, value: true },
|
||||
status: { loading: false, value: true }
|
||||
follow: true,
|
||||
follow_request: true,
|
||||
favourite: true,
|
||||
reblog: true,
|
||||
mention: true,
|
||||
poll: true,
|
||||
status: true,
|
||||
'admin.sign_up': false,
|
||||
'admin.report': false
|
||||
},
|
||||
keys: { auth: undefined, public: undefined, private: undefined }
|
||||
},
|
||||
|
@ -6,7 +6,6 @@ import { RootState } from '@root/store'
|
||||
import * as Sentry from '@sentry/react-native'
|
||||
import { InstanceLatest } from '@utils/migrations/instances/migration'
|
||||
import { getInstance } from '@utils/slices/instancesSlice'
|
||||
import { Theme } from '@utils/styles/themes'
|
||||
import * as Notifications from 'expo-notifications'
|
||||
import * as Random from 'expo-random'
|
||||
import i18next from 'i18next'
|
||||
@ -97,7 +96,7 @@ const pushRegister = async (
|
||||
accountId,
|
||||
accountFull,
|
||||
serverKey: res.body.server_key,
|
||||
auth: instancePush.decode.value === false ? null : auth
|
||||
auth: instancePush.decode === false ? null : auth
|
||||
})
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
@ -106,7 +105,7 @@ const pushRegister = async (
|
||||
...androidDefaults
|
||||
}).then(group => {
|
||||
if (group) {
|
||||
if (instancePush.decode.value === false) {
|
||||
if (instancePush.decode === false) {
|
||||
Notifications.setNotificationChannelAsync(`${group.id}_default`, {
|
||||
groupId: group.id,
|
||||
name: i18n.t('meSettingsPush:content.default.heading'),
|
||||
|
@ -6,7 +6,7 @@ import { updateInstancePush } from './updatePush'
|
||||
const removeInstance = createAsyncThunk(
|
||||
'instances/remove',
|
||||
async (instance: InstanceLatest, { dispatch }): Promise<InstanceLatest> => {
|
||||
if (instance.push.global.value) {
|
||||
if (instance.push.global) {
|
||||
dispatch(updateInstancePush(false))
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ export const updateInstancePushDecode = createAsyncThunk(
|
||||
async (
|
||||
disable: boolean,
|
||||
{ getState }
|
||||
): Promise<{ disable: InstanceLatest['push']['decode']['value'] }> => {
|
||||
): Promise<{ disable: InstanceLatest['push']['decode'] }> => {
|
||||
const state = getState() as RootState
|
||||
const instance = getInstance(state)
|
||||
if (!instance?.url || !instance.account.id || !instance.push.keys) {
|
||||
@ -43,14 +43,11 @@ export const updateInstancePushDecode = createAsyncThunk(
|
||||
name: i18n.t('meSettingsPush:content.follow.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
Notifications.setNotificationChannelAsync(
|
||||
`${accountFull}_favourite`,
|
||||
{
|
||||
groupId: accountFull,
|
||||
name: i18n.t('meSettingsPush:content.favourite.heading'),
|
||||
...androidDefaults
|
||||
}
|
||||
)
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_favourite`, {
|
||||
groupId: accountFull,
|
||||
name: i18n.t('meSettingsPush:content.favourite.heading'),
|
||||
...androidDefaults
|
||||
})
|
||||
Notifications.setNotificationChannelAsync(`${accountFull}_reblog`, {
|
||||
groupId: accountFull,
|
||||
name: i18n.t('meSettingsPush:content.reblog.heading'),
|
||||
@ -74,9 +71,7 @@ export const updateInstancePushDecode = createAsyncThunk(
|
||||
...androidDefaults
|
||||
})
|
||||
Notifications.deleteNotificationChannelAsync(`${accountFull}_follow`)
|
||||
Notifications.deleteNotificationChannelAsync(
|
||||
`${accountFull}_favourite`
|
||||
)
|
||||
Notifications.deleteNotificationChannelAsync(`${accountFull}_favourite`)
|
||||
Notifications.deleteNotificationChannelAsync(`${accountFull}_reblog`)
|
||||
Notifications.deleteNotificationChannelAsync(`${accountFull}_mention`)
|
||||
Notifications.deleteNotificationChannelAsync(`${accountFull}_poll`)
|
||||
|
@ -73,18 +73,11 @@ const instancesSlice = createSlice({
|
||||
},
|
||||
clearPushLoading: ({ instances }) => {
|
||||
const activeIndex = findInstanceActive(instances)
|
||||
instances[activeIndex].push.global.loading = false
|
||||
instances[activeIndex].push.decode.loading = false
|
||||
instances[activeIndex].push.alerts.favourite.loading = false
|
||||
instances[activeIndex].push.alerts.follow.loading = false
|
||||
instances[activeIndex].push.alerts.mention.loading = false
|
||||
instances[activeIndex].push.alerts.poll.loading = false
|
||||
instances[activeIndex].push.alerts.reblog.loading = false
|
||||
},
|
||||
disableAllPushes: ({ instances }) => {
|
||||
instances = instances.map(instance => {
|
||||
let newInstance = instance
|
||||
newInstance.push.global.value = false
|
||||
newInstance.push.global = false
|
||||
return newInstance
|
||||
})
|
||||
},
|
||||
@ -238,48 +231,21 @@ const instancesSlice = createSlice({
|
||||
// Update Instance Push Global
|
||||
.addCase(updateInstancePush.fulfilled, (state, action) => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
state.instances[activeIndex].push.global.loading = false
|
||||
state.instances[activeIndex].push.global.value = action.meta.arg
|
||||
state.instances[activeIndex].push.global = action.meta.arg
|
||||
state.instances[activeIndex].push.keys = { auth: action.payload }
|
||||
})
|
||||
.addCase(updateInstancePush.rejected, state => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
state.instances[activeIndex].push.global.loading = false
|
||||
})
|
||||
.addCase(updateInstancePush.pending, state => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
state.instances[activeIndex].push.global.loading = true
|
||||
})
|
||||
|
||||
// Update Instance Push Decode
|
||||
.addCase(updateInstancePushDecode.fulfilled, (state, action) => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
state.instances[activeIndex].push.decode.loading = false
|
||||
state.instances[activeIndex].push.decode.value = action.payload.disable
|
||||
})
|
||||
.addCase(updateInstancePushDecode.rejected, state => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
state.instances[activeIndex].push.decode.loading = false
|
||||
})
|
||||
.addCase(updateInstancePushDecode.pending, state => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
state.instances[activeIndex].push.decode.loading = true
|
||||
state.instances[activeIndex].push.decode = action.payload.disable
|
||||
})
|
||||
|
||||
// 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.payload
|
||||
})
|
||||
.addCase(updateInstancePushAlert.rejected, (state, action) => {
|
||||
const activeIndex = findInstanceActive(state.instances)
|
||||
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
|
||||
})
|
||||
|
||||
// Check if frequently used emojis still exist
|
||||
.addCase(checkEmojis.fulfilled, (state, action) => {
|
||||
@ -412,7 +378,6 @@ export const {
|
||||
updateInstanceNotificationsFilter,
|
||||
updateInstanceDraft,
|
||||
removeInstanceDraft,
|
||||
clearPushLoading,
|
||||
disableAllPushes,
|
||||
updateInstanceTimelineLookback,
|
||||
updateInstanceMePage,
|
||||
|
Loading…
Reference in New Issue
Block a user