diff --git a/src/components/sidebar-navigation.tsx b/src/components/sidebar-navigation.tsx index d0868f294..b771c1eb8 100644 --- a/src/components/sidebar-navigation.tsx +++ b/src/components/sidebar-navigation.tsx @@ -5,6 +5,7 @@ import { Stack } from 'soapbox/components/ui'; import { useStatContext } from 'soapbox/contexts/stat-context'; import ComposeButton from 'soapbox/features/ui/components/compose-button'; import { useAppSelector, useFeatures, useOwnAccount, useSettings, useInstance } from 'soapbox/hooks'; +import { useSettingsNotifications } from 'soapbox/hooks/useSettingsNotifications'; import DropdownMenu, { Menu } from './dropdown-menu'; import SidebarNavigationLink from './sidebar-navigation-link'; @@ -30,6 +31,7 @@ const SidebarNavigation = () => { const notificationCount = useAppSelector((state) => state.notifications.unread); const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count()); const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count()); + const settingsNotifications = useSettingsNotifications(); const restrictUnauth = instance.pleroma.metadata.restrict_unauthenticated; @@ -160,7 +162,7 @@ const SidebarNavigation = () => { icon={require('@tabler/icons/outline/settings.svg')} activeIcon={require('@tabler/icons/filled/settings.svg')} text={} - count={features.nip05 && account.acct !== account.source?.nostr?.nip05 ? 1 : 0} + count={settingsNotifications.size} /> {account.staff && ( diff --git a/src/features/edit-identity/index.tsx b/src/features/edit-identity/index.tsx index d4800202c..ab9436241 100644 --- a/src/features/edit-identity/index.tsx +++ b/src/features/edit-identity/index.tsx @@ -1,11 +1,12 @@ import { useMutation, useQuery } from '@tanstack/react-query'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { patchMe } from 'soapbox/actions/me'; +import { changeSetting } from 'soapbox/actions/settings'; import List, { ListItem } from 'soapbox/components/list'; import { Button, CardHeader, CardTitle, Column, Emoji, Form, HStack, Icon, Input, Textarea, Tooltip } from 'soapbox/components/ui'; -import { useApi, useAppDispatch, useInstance, useOwnAccount } from 'soapbox/hooks'; +import { useApi, useAppDispatch, useInstance, useOwnAccount, useSettings } from 'soapbox/hooks'; import { queryClient } from 'soapbox/queries/client'; import { adminAccountSchema } from 'soapbox/schemas/admin-account'; import toast from 'soapbox/toast'; @@ -33,10 +34,20 @@ const EditIdentity: React.FC = () => { const { data: approvedNames } = useNames(); const { data: pendingNames } = usePendingNames(); + const { dismissedSettingsNotifications } = useSettings(); const [username, setUsername] = useState(''); const [reason, setReason] = useState(''); + useEffect(() => { + const dismissed = new Set(dismissedSettingsNotifications); + + if (!dismissed.has('needsNip05')) { + dismissed.add('needsNip05'); + dispatch(changeSetting(['dismissedSettingsNotifications'], [...dismissed])); + } + }, []); + if (!account) return null; const updateName = async (name: string): Promise => { diff --git a/src/features/settings/index.tsx b/src/features/settings/index.tsx index 30a9c2dc8..bdc0b655f 100644 --- a/src/features/settings/index.tsx +++ b/src/features/settings/index.tsx @@ -6,6 +6,7 @@ import CopyableInput from 'soapbox/components/copyable-input'; import List, { ListItem } from 'soapbox/components/list'; import { Card, CardBody, CardHeader, CardTitle, Column, Counter, FormGroup, Text } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector, useFeatures, useInstance, useOwnAccount } from 'soapbox/hooks'; +import { useSettingsNotifications } from 'soapbox/hooks/useSettingsNotifications'; import Preferences from '../preferences'; @@ -46,6 +47,7 @@ const Settings = () => { const features = useFeatures(); const { account } = useOwnAccount(); const instance = useInstance(); + const settingsNotifications = useSettingsNotifications(); const isMfaEnabled = mfa.getIn(['settings', 'totp']); @@ -73,7 +75,7 @@ const Settings = () => { {account?.source?.nostr?.nip05} - {features.nip05 && } + {settingsNotifications.has('needsNip05') && } )} diff --git a/src/hooks/useSettingsNotifications.ts b/src/hooks/useSettingsNotifications.ts new file mode 100644 index 000000000..f8ab9ab78 --- /dev/null +++ b/src/hooks/useSettingsNotifications.ts @@ -0,0 +1,25 @@ +import { useFeatures } from './useFeatures'; +import { useOwnAccount } from './useOwnAccount'; +import { useSettings } from './useSettings'; + +type SettingsNotification = 'needsNip05'; + +/** Get a list of notifications for settings. */ +export function useSettingsNotifications(): Set { + const notifications: Set = new Set(); + + const features = useFeatures(); + const { account } = useOwnAccount(); + const { dismissedSettingsNotifications } = useSettings(); + + if ( + !dismissedSettingsNotifications.includes('needsNip05') + && account + && features.nip05 + && account.acct !== account.source?.nostr?.nip05 + ) { + notifications.add('needsNip05'); + } + + return notifications; +} \ No newline at end of file diff --git a/src/schemas/soapbox/settings.ts b/src/schemas/soapbox/settings.ts index e052720ba..e1b8fe53c 100644 --- a/src/schemas/soapbox/settings.ts +++ b/src/schemas/soapbox/settings.ts @@ -73,6 +73,8 @@ const settingsSchema = z.object({ show: z.boolean().catch(true), }), }), + /** Settings notifications that have been dismissed. See `useSettingsNotifications` hook. */ + dismissedSettingsNotifications: z.array(z.string()).catch([]), }); type Settings = z.infer;