diff --git a/packages/nicolium/src/components/panels/instance-info-panel.tsx b/packages/nicolium/src/components/panels/instance-info-panel.tsx deleted file mode 100644 index 61f06ab5e..000000000 --- a/packages/nicolium/src/components/panels/instance-info-panel.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import iconPushPinSlash from '@phosphor-icons/core/regular/push-pin-slash.svg'; -import iconPushPin from '@phosphor-icons/core/regular/push-pin.svg'; -import React from 'react'; -import { useIntl, defineMessages } from 'react-intl'; - -import { changeSetting } from '@/actions/settings'; -import Widget from '@/components/ui/widget'; -import { useRemoteInstance } from '@/queries/instance/use-remote-instance'; -import { useSettings } from '@/stores/settings'; - -const messages = defineMessages({ - pinHost: { id: 'remote_instance.pin_host', defaultMessage: 'Pin {host}' }, - unpinHost: { id: 'remote_instance.unpin_host', defaultMessage: 'Unpin {host}' }, -}); - -interface IInstanceInfoPanel { - /** Hostname (domain) of the remote instance, eg "gleasonator.com" */ - host: string; -} - -/** Widget that displays information about a remote instance to users. */ -const InstanceInfoPanel: React.FC = ({ host }) => { - const intl = useIntl(); - - const settings = useSettings(); - const remoteInstance = useRemoteInstance(host); - const pinnedHosts = settings.remote_timeline.pinnedHosts; - const isPinned = pinnedHosts.includes(host); - - const pinHost = (host: string) => { - changeSetting(['remote_timeline', 'pinnedHosts'], [...pinnedHosts, host]); - }; - - const unpinHost = (host: string) => { - changeSetting( - ['remote_timeline', 'pinnedHosts'], - pinnedHosts.filter((value) => value !== host), - ); - }; - - const handlePinHost = () => { - if (!isPinned) { - pinHost(host); - } else { - unpinHost(host); - } - }; - - if (!remoteInstance) return null; - - return ( - - ); -}; - -export { InstanceInfoPanel as default }; diff --git a/packages/nicolium/src/features/ui/util/async-components.ts b/packages/nicolium/src/features/ui/util/async-components.ts index e98fdf49a..6d2378aa4 100644 --- a/packages/nicolium/src/features/ui/util/async-components.ts +++ b/packages/nicolium/src/features/ui/util/async-components.ts @@ -10,7 +10,6 @@ export const CryptoDonatePanel = lazy( () => import('@/features/crypto-donate/components/crypto-donate-panel'), ); export const GroupMediaPanel = lazy(() => import('@/components/panels/group-media-panel')); -export const InstanceInfoPanel = lazy(() => import('@/components/panels/instance-info-panel')); export const InstanceModerationPanel = lazy( () => import('@/components/panels/instance-moderation-panel'), ); diff --git a/packages/nicolium/src/layouts/remote-instance-layout.tsx b/packages/nicolium/src/layouts/remote-instance-layout.tsx index 74ae9d2a9..8104ad68a 100644 --- a/packages/nicolium/src/layouts/remote-instance-layout.tsx +++ b/packages/nicolium/src/layouts/remote-instance-layout.tsx @@ -4,11 +4,7 @@ import React from 'react'; import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; import { layouts } from '@/features/ui/router'; -import { - PromoPanel, - InstanceInfoPanel, - InstanceModerationPanel, -} from '@/features/ui/util/async-components'; +import { PromoPanel, InstanceModerationPanel } from '@/features/ui/util/async-components'; import { useOwnAccount } from '@/hooks/use-own-account'; import { useFederationRestrictionsDisclosed } from '@/utils/state'; @@ -27,7 +23,6 @@ const RemoteInstanceLayout = () => { - {(disclosed || account?.is_admin) && } diff --git a/packages/nicolium/src/pages/timelines/remote-timeline.tsx b/packages/nicolium/src/pages/timelines/remote-timeline.tsx index 1820b2483..00b74e17e 100644 --- a/packages/nicolium/src/pages/timelines/remote-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/remote-timeline.tsx @@ -1,10 +1,13 @@ import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconPushPinSlash from '@phosphor-icons/core/regular/push-pin-slash.svg'; +import iconPushPin from '@phosphor-icons/core/regular/push-pin.svg'; import iconX from '@phosphor-icons/core/regular/x.svg'; import { useNavigate } from '@tanstack/react-router'; -import React from 'react'; +import React, { useMemo } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { changeSetting } from '@/actions/settings'; import { PublicTimelineColumn } from '@/columns/timeline'; import DropdownMenu from '@/components/dropdown-menu'; import { TimelinePicker } from '@/components/timeline-picker'; @@ -17,24 +20,53 @@ import { useSettings } from '@/stores/settings'; const messages = defineMessages({ close: { id: 'remote_timeline.close', defaultMessage: 'Close remote timeline' }, + pinHost: { id: 'remote_instance.pin_host', defaultMessage: 'Pin {host}' }, + unpinHost: { id: 'remote_instance.unpin_host', defaultMessage: 'Unpin {host}' }, }); /** View statuses from a remote instance. */ const RemoteTimelinePage: React.FC = () => { const { instance } = remoteTimelineRoute.useParams(); - const items = useTimelineFiltersOptions('public'); + const timelineFiltersOptions = useTimelineFiltersOptions('public'); const intl = useIntl(); const navigate = useNavigate(); const settings = useSettings(); - const pinned = settings.remote_timeline.pinnedHosts.includes(instance); + const isPinned = settings.remote_timeline.pinnedHosts.includes(instance); const handleCloseClick: React.MouseEventHandler = () => { navigate({ to: '/timeline/fediverse' }); }; + const handlePinHost = () => { + if (!isPinned) { + changeSetting( + ['remote_timeline', 'pinnedHosts'], + [...settings.remote_timeline.pinnedHosts, instance], + ); + } else { + changeSetting( + ['remote_timeline', 'pinnedHosts'], + settings.remote_timeline.pinnedHosts.filter((value) => value !== instance), + ); + } + }; + + const items = useMemo( + () => [ + ...timelineFiltersOptions, + null, + { + text: intl.formatMessage(isPinned ? messages.unpinHost : messages.pinHost, { instance }), + action: handlePinHost, + icon: isPinned ? iconPushPinSlash : iconPushPin, + }, + ], + [timelineFiltersOptions, isPinned, instance], + ); + return ( { truncateTitle={false} action={} > - {!pinned && ( + {!isPinned && (