diff --git a/src/@types/mastodon.d.ts b/src/@types/mastodon.d.ts index 7fec5552..699cbd16 100644 --- a/src/@types/mastodon.d.ts +++ b/src/@types/mastodon.d.ts @@ -395,6 +395,7 @@ declare namespace Mastodon { mention: boolean poll: boolean status: boolean + update: boolean 'admin.sign_up': boolean 'admin.report': boolean } diff --git a/src/components/Menu/Row.tsx b/src/components/Menu/Row.tsx index c4d32e9b..2bfe1cdd 100644 --- a/src/components/Menu/Row.tsx +++ b/src/components/Menu/Row.tsx @@ -85,7 +85,7 @@ const MenuRow: React.FC = ({ > { } }, [appsQuery.data?.vapid_key]) + const pushFeatures = usePushFeatures() + const alerts = () => instancePush?.alerts - ? PUSH_DEFAULT.map(alert => ( + ? PUSH_DEFAULT(pushFeatures).map(alert => ( { const profileQuery = useProfileQuery() const adminAlerts = () => profileQuery.data?.role?.permissions - ? PUSH_ADMIN.map(({ type, permission }) => - checkPermission(permission, profileQuery.data.role?.permissions) ? ( - - dispatch( - updateInstancePushAlert({ - alerts: { - ...instancePush?.alerts, - [type]: instancePush?.alerts[type] - } - }) - ) - } - /> - ) : null - ) + ? PUSH_ADMIN(pushFeatures, profileQuery.data?.role?.permissions).map(({ type }) => ( + + dispatch( + updateInstancePushAlert({ + alerts: { + ...instancePush?.alerts, + [type]: instancePush?.alerts[type] + } + }) + ) + } + /> + )) : null return ( diff --git a/src/screens/Tabs/Me/Root/Collections.tsx b/src/screens/Tabs/Me/Root/Collections.tsx index 8c103221..0988df92 100644 --- a/src/screens/Tabs/Me/Root/Collections.tsx +++ b/src/screens/Tabs/Me/Root/Collections.tsx @@ -4,7 +4,11 @@ import { useAppDispatch } from '@root/store' import { useAnnouncementQuery } from '@utils/queryHooks/announcement' import { useListsQuery } from '@utils/queryHooks/lists' import { useFollowedTagsQuery } from '@utils/queryHooks/tags' -import { getInstanceMePage, updateInstanceMePage } from '@utils/slices/instancesSlice' +import { + checkInstanceFeature, + getInstanceMePage, + updateInstanceMePage +} from '@utils/slices/instancesSlice' import { getInstancePush } from '@utils/slices/instancesSlice' import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' @@ -17,8 +21,10 @@ const Collections: React.FC = () => { const dispatch = useAppDispatch() const mePage = useSelector(getInstanceMePage) + const canFollowTags = useSelector(checkInstanceFeature('follow_tags')) useFollowedTagsQuery({ options: { + enabled: canFollowTags, onSuccess: data => dispatch( updateInstanceMePage({ diff --git a/src/screens/Tabs/Notifications/Filters.tsx b/src/screens/Tabs/Notifications/Filters.tsx index 2a3270ed..f8fa7f54 100644 --- a/src/screens/Tabs/Notifications/Filters.tsx +++ b/src/screens/Tabs/Notifications/Filters.tsx @@ -1,17 +1,12 @@ import { HeaderLeft, HeaderRight } from '@components/Header' import { MenuContainer, MenuRow } from '@components/Menu' -import { - checkPermission, - PERMISSION_MANAGE_REPORTS, - PERMISSION_MANAGE_USERS -} from '@helpers/permissions' import { useAppDispatch } from '@root/store' import { useQueryClient } from '@tanstack/react-query' import { TabNotificationsStackScreenProps } from '@utils/navigation/navigators' import { useProfileQuery } from '@utils/queryHooks/profile' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' +import { PUSH_ADMIN, PUSH_DEFAULT, usePushFeatures } from '@utils/slices/instances/push/utils' import { - checkInstanceFeature, getInstanceNotificationsFilter, updateInstanceNotificationsFilter } from '@utils/slices/instancesSlice' @@ -22,32 +17,12 @@ import { Alert } from 'react-native' import { ScrollView } from 'react-native-gesture-handler' import { useSelector } from 'react-redux' -export const NOTIFICATIONS_FILTERS_DEFAULT: [ - 'follow', - 'follow_request', - 'favourite', - 'reblog', - 'mention', - 'poll', - 'status', - 'update' -] = ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'status', 'update'] - -export const NOTIFICATIONS_FILTERS_ADMIN: { - type: 'admin.sign_up' | 'admin.report' - permission: number -}[] = [ - { type: 'admin.sign_up', permission: PERMISSION_MANAGE_USERS }, - { type: 'admin.report', permission: PERMISSION_MANAGE_REPORTS } -] - const TabNotificationsFilters: React.FC< TabNotificationsStackScreenProps<'Tab-Notifications-Filters'> > = ({ navigation }) => { const { t } = useTranslation('screenTabs') - const hasTypeStatus = useSelector(checkInstanceFeature('notification_type_status')) - const hasTypeUpdate = useSelector(checkInstanceFeature('notification_type_update')) + const pushFeatures = usePushFeatures() const dispatch = useAppDispatch() @@ -103,16 +78,7 @@ const TabNotificationsFilters: React.FC< return ( - {NOTIFICATIONS_FILTERS_DEFAULT.filter(type => { - switch (type) { - case 'status': - return hasTypeStatus - case 'update': - return hasTypeUpdate - default: - return true - } - }).map((type, index) => ( + {PUSH_DEFAULT(pushFeatures).map((type, index) => ( setFilters({ ...filters, [type]: !filters[type] })} /> ))} - {NOTIFICATIONS_FILTERS_ADMIN.filter(({ permission }) => - checkPermission(permission, profileQuery.data?.role?.permissions) - ).map(({ type }) => ( + {PUSH_ADMIN(pushFeatures, profileQuery.data?.role?.permissions).map(({ type }) => ( { + const hasTypeStatus = useSelector(checkInstanceFeature('notification_type_status')) + const hasTypeUpdate = useSelector(checkInstanceFeature('notification_type_update')) + const hasTypeAdminSignup = useSelector(checkInstanceFeature('notification_type_admin_signup')) + const hasTypeAdminReport = useSelector(checkInstanceFeature('notification_type_admin_report')) + return { hasTypeStatus, hasTypeUpdate, hasTypeAdminSignup, hasTypeAdminReport } +} -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 PUSH_DEFAULT = ({ + hasTypeUpdate, + hasTypeStatus +}: { + hasTypeUpdate: boolean + hasTypeStatus: boolean +}) => + ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'update', 'status'].filter( + type => { + switch (type) { + case 'status': + return hasTypeStatus + case 'update': + return hasTypeUpdate + default: + return true + } + } + ) as ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'update', 'status'] + +export const PUSH_ADMIN = ( + { + hasTypeAdminSignup, + hasTypeAdminReport + }: { + hasTypeAdminSignup: boolean + hasTypeAdminReport: boolean + }, + permissions?: string | number | undefined +) => + [ + { type: 'admin.sign_up', permission: PERMISSION_MANAGE_USERS }, + { type: 'admin.report', permission: PERMISSION_MANAGE_REPORTS } + ].filter(({ type, permission }) => { + switch (type) { + case 'admin.sign_up': + return hasTypeAdminSignup && checkPermission(permission, permissions) + case 'admin.report': + return hasTypeAdminReport && checkPermission(permission, permissions) + } + }) as { type: 'admin.sign_up' | 'admin.report'; permission: number }[] export const setChannels = async (instance: InstanceLatest) => { const account = `@${instance.account.acct}@${instance.uri}` @@ -48,23 +86,32 @@ export const setChannels = async (instance: InstanceLatest) => { await Notifications.setNotificationChannelGroupAsync(account, { name: account }) } + const checkFeature = (feature: string) => + features + .filter(f => f.feature === feature) + .filter(f => parseFloat(instance.version) >= f.version)?.length > 0 + const checkFeatures = { + hasTypeStatus: checkFeature('notification_type_status'), + hasTypeUpdate: checkFeature('notification_type_update'), + hasTypeAdminSignup: checkFeature('notification_type_admin_signup'), + hasTypeAdminReport: checkFeature('notification_type_admin_report') + } + if (!instance.push.decode) { await setChannel('default') - for (const push of PUSH_DEFAULT) { + for (const push of PUSH_DEFAULT(checkFeatures)) { await deleteChannel(push) } - for (const { type } of PUSH_ADMIN) { + for (const { type } of PUSH_ADMIN(checkFeatures, profileQuery.role?.permissions)) { await deleteChannel(type) } } else { await deleteChannel('default') - for (const push of PUSH_DEFAULT) { + for (const push of PUSH_DEFAULT(checkFeatures)) { await setChannel(push) } - for (const { type, permission } of PUSH_ADMIN) { - if (checkPermission(permission, profileQuery.role?.permissions)) { - await setChannel(type) - } + for (const { type } of PUSH_ADMIN(checkFeatures, profileQuery.role?.permissions)) { + await setChannel(type) } } }