nicolium: allow pinning/unpinning instances on mobile
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
@ -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<IInstanceInfoPanel> = ({ 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 (
|
||||
<Widget
|
||||
title={remoteInstance.host}
|
||||
onActionClick={handlePinHost}
|
||||
actionIcon={isPinned ? iconPushPinSlash : iconPushPin}
|
||||
actionTitle={intl.formatMessage(isPinned ? messages.unpinHost : messages.pinHost, { host })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { InstanceInfoPanel as default };
|
||||
@ -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'),
|
||||
);
|
||||
|
||||
@ -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 = () => {
|
||||
|
||||
<Layout.Aside>
|
||||
<PromoPanel />
|
||||
<InstanceInfoPanel host={instance} />
|
||||
{(disclosed || account?.is_admin) && <InstanceModerationPanel host={instance} />}
|
||||
<LinkFooter />
|
||||
</Layout.Aside>
|
||||
|
||||
@ -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 (
|
||||
<Column
|
||||
label={instance}
|
||||
@ -42,7 +74,7 @@ const RemoteTimelinePage: React.FC = () => {
|
||||
truncateTitle={false}
|
||||
action={<DropdownMenu items={items} src={iconDotsThreeVertical} />}
|
||||
>
|
||||
{!pinned && (
|
||||
{!isPinned && (
|
||||
<div className='mb-4 flex gap-2 px-2'>
|
||||
<IconButton
|
||||
className='text-gray-400 hover:text-gray-600'
|
||||
|
||||
Reference in New Issue
Block a user