From 8fc99331dbc4498a26f454b2caf693b7d0bef22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 12:02:34 +0100 Subject: [PATCH 01/64] nicolium: make lists selector optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/modals/antenna-editor-modal.tsx | 2 +- packages/nicolium/src/queries/accounts/use-lists.ts | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/nicolium/src/modals/antenna-editor-modal.tsx b/packages/nicolium/src/modals/antenna-editor-modal.tsx index 2f481d9ae..93064c724 100644 --- a/packages/nicolium/src/modals/antenna-editor-modal.tsx +++ b/packages/nicolium/src/modals/antenna-editor-modal.tsx @@ -495,7 +495,7 @@ const EditAntennaForm: React.FC = ({ antennaId, onTabChange }) const { mutate: updateAntenna, isPending: updateDisabled } = useUpdateAntenna(antennaId!); const { mutate: createAntenna, isPending: createDisabled } = useCreateAntenna(); - const { data: lists } = useLists((lists) => lists); + const { data: lists } = useLists(); const [title, setTitle] = useState(antenna ? antenna.title : ''); const [ltl, setLtl] = useState(antenna ? antenna.ltl : false); diff --git a/packages/nicolium/src/queries/accounts/use-lists.ts b/packages/nicolium/src/queries/accounts/use-lists.ts index 90764b31e..0c11f8a21 100644 --- a/packages/nicolium/src/queries/accounts/use-lists.ts +++ b/packages/nicolium/src/queries/accounts/use-lists.ts @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@tanstack/react-query'; +import { useMutation, useQuery, type UseQueryResult } from '@tanstack/react-query'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; @@ -11,7 +11,9 @@ import { minifyAccountList } from '../utils/minify-list'; import type { CreateListParams, List, UpdateListParams } from 'pl-api'; -const useLists = (select?: (data: Array) => T) => { +function useLists(select: (data: Array) => T): UseQueryResult; +function useLists(): UseQueryResult, Error>; +function useLists>(select?: (data: Array) => T) { const client = useClient(); const features = useFeatures(); @@ -21,7 +23,7 @@ const useLists = (select?: (data: Array) => T) => { enabled: features.lists, select, }); -}; +} const useList = (listId?: string) => useLists((data) => (listId ? data.find((list) => list.id === listId) : undefined)); From 96cb8faf2dedbcd9f14023d6ef5390798fd985a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 12:52:03 +0100 Subject: [PATCH 02/64] nicolium: Add a timeline picker to timeline column header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../src/components/timeline-picker.tsx | 213 ++++++++++++++++++ .../nicolium/src/components/ui/column.tsx | 30 ++- .../components/pinned-hosts-picker.tsx | 34 --- packages/nicolium/src/locales/en.json | 1 + .../src/pages/timelines/antenna-timeline.tsx | 3 + .../src/pages/timelines/bubble-timeline.tsx | 8 +- .../src/pages/timelines/circle-timeline.tsx | 3 + .../pages/timelines/community-timeline.tsx | 8 +- .../src/pages/timelines/home-timeline.tsx | 9 +- .../src/pages/timelines/list-timeline.tsx | 7 +- .../src/pages/timelines/public-timeline.tsx | 11 +- .../src/pages/timelines/remote-timeline.tsx | 10 +- .../src/pages/timelines/wrenched-timeline.tsx | 8 +- .../src/queries/accounts/use-antennas.ts | 4 +- .../src/queries/accounts/use-circles.ts | 4 +- .../src/queries/accounts/use-lists.ts | 4 +- .../nicolium/src/styles/new/timelines.scss | 26 +++ 17 files changed, 328 insertions(+), 55 deletions(-) create mode 100644 packages/nicolium/src/components/timeline-picker.tsx delete mode 100644 packages/nicolium/src/features/remote-timeline/components/pinned-hosts-picker.tsx diff --git a/packages/nicolium/src/components/timeline-picker.tsx b/packages/nicolium/src/components/timeline-picker.tsx new file mode 100644 index 000000000..bcdc8fdd1 --- /dev/null +++ b/packages/nicolium/src/components/timeline-picker.tsx @@ -0,0 +1,213 @@ +import React, { useMemo } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { useFeatures } from '@/hooks/use-features'; +import { useLoggedIn } from '@/hooks/use-logged-in'; +import { useAntennas } from '@/queries/accounts/use-antennas'; +import { useCircles } from '@/queries/accounts/use-circles'; +import { useLists } from '@/queries/accounts/use-lists'; +import { useInstance } from '@/stores/instance'; +import { useSettings } from '@/stores/settings'; + +import DropdownMenu, { type Menu } from './dropdown-menu'; +import Icon from './ui/icon'; + +const messages = defineMessages({ + homeTimeline: { id: 'column.home', defaultMessage: 'Home' }, + localTimeline: { id: 'column.community', defaultMessage: 'Local timeline' }, + bubbleTimeline: { id: 'column.bubble', defaultMessage: 'Bubble timeline' }, + federatedTimeline: { id: 'column.public', defaultMessage: 'Fediverse timeline' }, + wrenchedTimeline: { id: 'column.wrenched', defaultMessage: 'Wrenched timeline' }, + lists: { id: 'column.lists', defaultMessage: 'Lists' }, + circles: { id: 'column.circles', defaultMessage: 'Circles' }, + antennas: { id: 'column.antennas', defaultMessage: 'Antennas' }, + pinnedInstances: { id: 'timeline_picker.pinned_instances', defaultMessage: 'Pinned instances' }, +}); + +interface ITimelinePicker { + active: + | 'home' + | 'local' + | 'bubble' + | 'federated' + | 'wrenched' + | `list:${string}` + | `circle:${string}` + | `antenna:${string}` + | `instance:${string}`; +} + +const TimelinePicker: React.FC = ({ active }) => { + const intl = useIntl(); + const features = useFeatures(); + const { isLoggedIn } = useLoggedIn(); + const timelineAccess = useInstance().configuration.timelines_access; + const pinnedHosts = useSettings().remote_timeline.pinnedHosts; + + const { data: lists } = useLists(); + const { data: circles } = useCircles(); + const { data: antennas } = useAntennas(); + + const heading = useMemo(() => { + switch (active) { + case 'home': + return intl.formatMessage(messages.homeTimeline); + case 'local': + return intl.formatMessage(messages.localTimeline); + case 'bubble': + return intl.formatMessage(messages.bubbleTimeline); + case 'federated': + return intl.formatMessage(messages.federatedTimeline); + case 'wrenched': + return intl.formatMessage(messages.wrenchedTimeline); + default: + if (active.startsWith('list:')) { + const list = lists?.find((list) => `list:${list.id}` === active); + return list?.title ?? ''; + } + if (active.startsWith('circle:')) { + const circle = circles?.find((circle) => `circle:${circle.id}` === active); + return circle?.title ?? ''; + } + if (active.startsWith('antenna:')) { + const antenna = antennas?.find((antenna) => `antenna:${antenna.id}` === active); + return antenna?.title ?? ''; + } + if (active.startsWith('instance:')) { + return active.replace('instance:', ''); + } + return ''; + } + }, [active]); + + const items = useMemo(() => { + const items: Menu = []; + + if (isLoggedIn) { + items.push({ + to: '/', + text: intl.formatMessage(messages.homeTimeline), + icon: require('@phosphor-icons/core/regular/house.svg'), + active: active === 'home', + }); + } + + if ( + isLoggedIn + ? timelineAccess.live_feeds.local !== 'disabled' + : timelineAccess.live_feeds.local === 'public' + ) { + items.push({ + to: '/timeline/local', + text: intl.formatMessage(messages.localTimeline), + icon: require('@phosphor-icons/core/regular/planet.svg'), + active: active === 'local', + }); + } + + if ( + features.bubbleTimeline && isLoggedIn + ? timelineAccess.live_feeds.bubble !== 'disabled' + : timelineAccess.live_feeds.bubble === 'public' + ) { + items.push({ + to: '/timeline/bubble', + text: intl.formatMessage(messages.bubbleTimeline), + icon: require('@phosphor-icons/core/regular/graph.svg'), + active: active === 'bubble', + }); + } + if ( + features.bubbleTimeline && isLoggedIn + ? timelineAccess.live_feeds.bubble !== 'disabled' + : timelineAccess.live_feeds.bubble === 'public' + ) { + items.push({ + to: '/timeline/fediverse', + text: intl.formatMessage(messages.federatedTimeline), + icon: require('@phosphor-icons/core/regular/fediverse-logo.svg'), + active: active === 'federated', + }); + } + if ( + features.wrenchedTimeline && isLoggedIn + ? timelineAccess.live_feeds.wrenched !== 'disabled' + : timelineAccess.live_feeds.wrenched === 'public' + ) { + items.push({ + to: '/timeline/wrenched', + text: intl.formatMessage(messages.wrenchedTimeline), + icon: require('@phosphor-icons/core/regular/wrench.svg'), + active: active === 'wrenched', + }); + } + if (lists?.length) { + items.push({ + text: intl.formatMessage(messages.lists), + active: active.startsWith('list:'), + icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + items: lists.map((list) => ({ + to: '/list/$listId', + params: { listId: list.id }, + text: list.title, + icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + active: active === `list:${list.id}`, + })), + }); + } + if (circles?.length) { + items.push({ + text: intl.formatMessage(messages.circles), + active: active.startsWith('circle:'), + icon: require('@phosphor-icons/core/regular/circles-three.svg'), + items: circles.map((circle) => ({ + to: '/circles/$circleId', + params: { circleId: circle.id }, + text: circle.title, + icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + active: active === `circle:${circle.id}`, + })), + }); + } + if (antennas?.length) { + items.push({ + text: intl.formatMessage(messages.antennas), + active: active.startsWith('antenna:'), + icon: require('@phosphor-icons/core/regular/broadcast.svg'), + items: antennas.map((antenna) => ({ + to: '/antennas/$antennaId', + params: { antennaId: antenna.id }, + text: antenna.title, + icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + active: active === `antenna:${antenna.id}`, + })), + }); + } + if (pinnedHosts.length) { + items.push({ + text: intl.formatMessage(messages.pinnedInstances), + active: active.startsWith('instance:'), + icon: require('@phosphor-icons/core/regular/globe-simple.svg'), + items: pinnedHosts.map((instance) => ({ + to: '/timeline/$instance', + params: { instance }, + text: instance, + icon: require('@phosphor-icons/core/regular/globe-simple.svg'), + active: active === `instance:${instance}`, + })), + }); + } + return items; + }, [active, lists, circles, antennas, features, isLoggedIn]); + + return ( + +
+ {heading} + +
+
+ ); +}; + +export { TimelinePicker }; diff --git a/packages/nicolium/src/components/ui/column.tsx b/packages/nicolium/src/components/ui/column.tsx index 69d66291f..60cf9bdf2 100644 --- a/packages/nicolium/src/components/ui/column.tsx +++ b/packages/nicolium/src/components/ui/column.tsx @@ -8,17 +8,28 @@ import { useFrontendConfig } from '@/hooks/use-frontend-config'; import { Card, CardBody, CardHeader, CardTitle, type CardSizes } from './card'; -interface IColumnHeader extends Pick { - label?: React.ReactNode; -} +type IColumnHeader = Pick< + IColumn, + | 'label' + | 'title' + | 'withBack' + | 'backHref' + | 'backParams' + | 'className' + | 'action' + | 'truncateTitle' +>; /** Contains the column title with optional back button. */ const ColumnHeader: React.FC = ({ label, + title, + withBack, backHref, backParams, className, action, + truncateTitle, }) => { const navigate = useNavigate(); const { history } = useRouter(); @@ -37,8 +48,8 @@ const ColumnHeader: React.FC = ({ }; return ( - - + + {action &&
{action}
}
@@ -47,11 +58,13 @@ const ColumnHeader: React.FC = ({ interface IColumn { /** Route the back button goes to. */ + withBack?: boolean; backHref?: LinkOptions['to']; backParams?: LinkOptions['params']; backSearch?: LinkOptions['search']; /** Column title text. */ label?: string; + title?: React.ReactNode; /** Whether this column should have a transparent background. */ transparent?: boolean; /** Whether this column should have a title and back button. */ @@ -66,20 +79,24 @@ interface IColumn { action?: React.ReactNode; /** Column size, inherited from Card. */ size?: CardSizes; + truncateTitle?: boolean; } /** A backdrop for the main section of the UI. */ const Column: React.FC = (props): React.JSX.Element => { const { + withBack = true, backHref, children, label, + title, transparent = false, withHeader = true, className, bodyClassName, action, size, + truncateTitle, } = props; const frontendConfig = useFrontendConfig(); const [isScrolled, setIsScrolled] = useState(false); @@ -120,11 +137,14 @@ const Column: React.FC = (props): React.JSX.Element => { {withHeader && ( )} diff --git a/packages/nicolium/src/features/remote-timeline/components/pinned-hosts-picker.tsx b/packages/nicolium/src/features/remote-timeline/components/pinned-hosts-picker.tsx deleted file mode 100644 index 6342eb417..000000000 --- a/packages/nicolium/src/features/remote-timeline/components/pinned-hosts-picker.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; - -import Button from '@/components/ui/button'; -import { useSettings } from '@/stores/settings'; - -interface IPinnedHostsPicker { - /** The active host among pinned hosts. */ - host?: string; -} - -const PinnedHostsPicker: React.FC = ({ host: activeHost }) => { - const settings = useSettings(); - const pinnedHosts = settings.remote_timeline.pinnedHosts; - - if (!pinnedHosts.length) return null; - - return ( -
- {pinnedHosts.map((host) => ( - - ))} -
- ); -}; - -export { PinnedHostsPicker as default }; diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index 5a6b42a9b..c343fd519 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -2024,6 +2024,7 @@ "timeline.gap.load_newer": "Load newer posts", "timeline.gap.load_older": "Load older posts", "timeline.gap.load_recent": "Load recent posts", + "timeline_picker.pinned_instances": "Pinned instances", "toast.view": "View", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", "trends.no_accounts": "Try entering a search query or browsing the profile directory to find accounts to follow.", diff --git a/packages/nicolium/src/pages/timelines/antenna-timeline.tsx b/packages/nicolium/src/pages/timelines/antenna-timeline.tsx index 9a2cf07db..ac4efed7b 100644 --- a/packages/nicolium/src/pages/timelines/antenna-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/antenna-timeline.tsx @@ -5,6 +5,7 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { AntennaTimelineColumn } from '@/columns/timeline'; import DropdownMenu from '@/components/dropdown-menu'; import MissingIndicator from '@/components/missing-indicator'; +import { TimelinePicker } from '@/components/timeline-picker'; // import Button from '@/components/ui/button'; import Column from '@/components/ui/column'; import Spinner from '@/components/ui/spinner'; @@ -90,6 +91,8 @@ const AntennaTimelinePage: React.FC = () => { src={require('@phosphor-icons/core/regular/dots-three-vertical.svg')} /> } + title={} + truncateTitle={false} > { const intl = useIntl(); return ( - + } + truncateTitle={false} + > { src={require('@phosphor-icons/core/regular/dots-three-vertical.svg')} /> } + title={} + truncateTitle={false} > { const intl = useIntl(); return ( - + } + truncateTitle={false} + > { if (isSledzikRemoved) return null; return ( - + } + withBack={false} + truncateTitle={false} + > diff --git a/packages/nicolium/src/pages/timelines/list-timeline.tsx b/packages/nicolium/src/pages/timelines/list-timeline.tsx index bd67658b0..c64145ccd 100644 --- a/packages/nicolium/src/pages/timelines/list-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/list-timeline.tsx @@ -5,6 +5,7 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { ListTimelineColumn } from '@/columns/timeline'; import DropdownMenu from '@/components/dropdown-menu'; import { EmptyMessage } from '@/components/empty-message'; +import { TimelinePicker } from '@/components/timeline-picker'; import Button from '@/components/ui/button'; import Column from '@/components/ui/column'; import Spinner from '@/components/ui/spinner'; @@ -67,7 +68,11 @@ const ListTimelinePage: React.FC = () => { ); } else if (!list) { return ( - + } + truncateTitle={false} + > } text={ diff --git a/packages/nicolium/src/pages/timelines/public-timeline.tsx b/packages/nicolium/src/pages/timelines/public-timeline.tsx index c0ffbd33e..5124ca2af 100644 --- a/packages/nicolium/src/pages/timelines/public-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/public-timeline.tsx @@ -4,9 +4,9 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { changeSetting } from '@/actions/settings'; import { PublicTimelineColumn } from '@/columns/timeline'; +import { TimelinePicker } from '@/components/timeline-picker'; import Accordion from '@/components/ui/accordion'; import Column from '@/components/ui/column'; -import PinnedHostsPicker from '@/features/remote-timeline/components/pinned-hosts-picker'; import { useInstance } from '@/stores/instance'; import { useSettings } from '@/stores/settings'; @@ -33,9 +33,12 @@ const PublicTimelinePage = () => { }; return ( - - - + } + truncateTitle={false} + > {showExplanationBox && ( { }; return ( - - {instance && } - + } + truncateTitle={false} + > {!pinned && (
{ const intl = useIntl(); return ( - + } + truncateTitle={false} + > , Error>; function useAntennas>(select?: (data: Array) => T) { const client = useClient(); const features = useFeatures(); + const { isLoggedIn } = useLoggedIn(); return useQuery({ queryKey: queryKeys.antennas.all, queryFn: () => client.antennas.fetchAntennas(), - enabled: features.antennas, + enabled: isLoggedIn && features.antennas, select, }); } diff --git a/packages/nicolium/src/queries/accounts/use-circles.ts b/packages/nicolium/src/queries/accounts/use-circles.ts index 35868d31e..fdd4b0e21 100644 --- a/packages/nicolium/src/queries/accounts/use-circles.ts +++ b/packages/nicolium/src/queries/accounts/use-circles.ts @@ -2,6 +2,7 @@ import { type UseQueryResult, useMutation, useQuery } from '@tanstack/react-quer import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; +import { useLoggedIn } from '@/hooks/use-logged-in'; import { queryKeys } from '@/queries/keys'; import { queryClient } from '../client'; @@ -16,11 +17,12 @@ function useCircles(): UseQueryResult, Error>; function useCircles>(select?: (data: Array) => T) { const client = useClient(); const features = useFeatures(); + const { isLoggedIn } = useLoggedIn(); return useQuery({ queryKey: queryKeys.circles.all, queryFn: () => client.circles.fetchCircles(), - enabled: features.circles, + enabled: isLoggedIn && features.circles, select, }); } diff --git a/packages/nicolium/src/queries/accounts/use-lists.ts b/packages/nicolium/src/queries/accounts/use-lists.ts index 0c11f8a21..a4704c040 100644 --- a/packages/nicolium/src/queries/accounts/use-lists.ts +++ b/packages/nicolium/src/queries/accounts/use-lists.ts @@ -2,6 +2,7 @@ import { useMutation, useQuery, type UseQueryResult } from '@tanstack/react-quer import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; +import { useLoggedIn } from '@/hooks/use-logged-in'; import { queryKeys } from '@/queries/keys'; import { queryClient } from '../client'; @@ -16,11 +17,12 @@ function useLists(): UseQueryResult, Error>; function useLists>(select?: (data: Array) => T) { const client = useClient(); const features = useFeatures(); + const { isLoggedIn } = useLoggedIn(); return useQuery({ queryKey: queryKeys.lists.all, queryFn: () => client.lists.getLists(), - enabled: features.lists, + enabled: isLoggedIn && features.lists, select, }); } diff --git a/packages/nicolium/src/styles/new/timelines.scss b/packages/nicolium/src/styles/new/timelines.scss index 662031a2f..b547b37a0 100644 --- a/packages/nicolium/src/styles/new/timelines.scss +++ b/packages/nicolium/src/styles/new/timelines.scss @@ -158,3 +158,29 @@ .⁂-load-more { @include mixins.button($theme: primary, $block: true); } + +.⁂-timeline-picker { + cursor: pointer; + + display: flex; + gap: 0.5rem; + align-items: center; + + margin: -0.25rem -0.5rem; + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + + transition: background 150ms ease-in-out; + + &:hover, &:focus-within, &[aria-expanded="true"] { + background: rgb(var(--color-primary-100)); + + .dark & { + background: rgb(var(--color-primary-800)); + } + + .dark.black & { + background: rgb(var(--color-gray-900)); + } + } +} From 49661a1dd1cb9506a12485f9226c00c68caa7daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 12:55:38 +0100 Subject: [PATCH 03/64] nicolium: pushing too early MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/pages/timelines/circle-timeline.tsx | 2 +- packages/nicolium/src/pages/timelines/list-timeline.tsx | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/nicolium/src/pages/timelines/circle-timeline.tsx b/packages/nicolium/src/pages/timelines/circle-timeline.tsx index 3b22af6cd..f3a457ccd 100644 --- a/packages/nicolium/src/pages/timelines/circle-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/circle-timeline.tsx @@ -91,7 +91,7 @@ const CircleTimelinePage: React.FC = () => { src={require('@phosphor-icons/core/regular/dots-three-vertical.svg')} /> } - title={} + title={} truncateTitle={false} > { ); } else if (!list) { return ( - } - truncateTitle={false} - > + } text={ @@ -107,6 +103,8 @@ const ListTimelinePage: React.FC = () => { return ( } + truncateTitle={false} action={ Date: Wed, 18 Mar 2026 15:10:17 +0100 Subject: [PATCH 04/64] nicolium: allow setting filters for all timelines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/columns/timeline.tsx | 38 ++++-- .../src/components/timeline-picker.tsx | 2 +- .../src/hooks/use-timeline-filters-options.ts | 122 ++++++++++++++++++ packages/nicolium/src/locales/en.json | 7 + .../src/pages/timelines/antenna-timeline.tsx | 34 +++-- .../src/pages/timelines/bubble-timeline.tsx | 9 ++ .../src/pages/timelines/circle-timeline.tsx | 33 +++-- .../pages/timelines/community-timeline.tsx | 9 ++ .../src/pages/timelines/hashtag-timeline.tsx | 13 +- .../src/pages/timelines/home-timeline.tsx | 9 ++ .../src/pages/timelines/list-timeline.tsx | 33 +++-- .../src/pages/timelines/public-timeline.tsx | 9 ++ .../src/pages/timelines/remote-timeline.tsx | 9 ++ .../src/pages/timelines/wrenched-timeline.tsx | 9 ++ .../nicolium/src/schemas/frontend-settings.ts | 27 ++-- 15 files changed, 306 insertions(+), 57 deletions(-) create mode 100644 packages/nicolium/src/hooks/use-timeline-filters-options.ts diff --git a/packages/nicolium/src/columns/timeline.tsx b/packages/nicolium/src/columns/timeline.tsx index 152b3a70e..2d5d14ae2 100644 --- a/packages/nicolium/src/columns/timeline.tsx +++ b/packages/nicolium/src/columns/timeline.tsx @@ -618,9 +618,12 @@ const PublicTimelineColumn: React.FC = ({ instance, ...props }) => { + const timelineFilters = useSettings().timelines.public; const timelineQuery = usePublicTimeline({ local, remote, instance }); - return ; + return ( + + ); }; interface IHashtagTimelineColumn extends IBaseTimeline { @@ -628,9 +631,12 @@ interface IHashtagTimelineColumn extends IBaseTimeline { } const HashtagTimelineColumn: React.FC = ({ hashtag, ...props }) => { + const timelineFilters = useSettings().timelines.hashtag; const timelineQuery = useHashtagTimeline(hashtag); - return ; + return ( + + ); }; interface ILinkTimelineColumn extends IBaseTimeline { @@ -648,9 +654,10 @@ interface IListTimelineColumn extends IBaseTimeline { } const ListTimelineColumn: React.FC = ({ listId, ...props }) => { + const timelineFilters = useSettings().timelines.list; const timelineQuery = useListTimeline(listId); - return ; + return ; }; interface IGroupTimelineColumn extends IBaseTimeline { @@ -658,15 +665,21 @@ interface IGroupTimelineColumn extends IBaseTimeline { } const GroupTimelineColumn: React.FC = ({ groupId, ...props }) => { + const timelineFilters = useSettings().timelines.group; const timelineQuery = useGroupTimeline(groupId); - return ; + return ( + + ); }; const BubbleTimelineColumn: React.FC = (props) => { + const timelineFilters = useSettings().timelines.bubble; const timelineQuery = useBubbleTimeline(); - return ; + return ( + + ); }; interface IAntennaTimelineColumn extends IBaseTimeline { @@ -674,9 +687,12 @@ interface IAntennaTimelineColumn extends IBaseTimeline { } const AntennaTimelineColumn: React.FC = ({ antennaId, ...props }) => { + const timelineFilters = useSettings().timelines.antenna; const timelineQuery = useAntennaTimeline(antennaId); - return ; + return ( + + ); }; interface ICircleTimelineColumn extends IBaseTimeline { @@ -684,15 +700,21 @@ interface ICircleTimelineColumn extends IBaseTimeline { } const CircleTimelineColumn: React.FC = ({ circleId, ...props }) => { + const timelineFilters = useSettings().timelines.bubble; const timelineQuery = useCircleTimeline(circleId); - return ; + return ( + + ); }; const WrenchedTimelineColumn: React.FC = (props) => { + const timelineFilters = useSettings().timelines.wrenched; const timelineQuery = useWrenchedTimeline(); - return ; + return ( + + ); }; interface IAccountTimelineColumn extends IBaseTimeline { diff --git a/packages/nicolium/src/components/timeline-picker.tsx b/packages/nicolium/src/components/timeline-picker.tsx index bcdc8fdd1..7310ad493 100644 --- a/packages/nicolium/src/components/timeline-picker.tsx +++ b/packages/nicolium/src/components/timeline-picker.tsx @@ -78,7 +78,7 @@ const TimelinePicker: React.FC = ({ active }) => { } return ''; } - }, [active]); + }, [active, lists, circles, antennas]); const items = useMemo(() => { const items: Menu = []; diff --git a/packages/nicolium/src/hooks/use-timeline-filters-options.ts b/packages/nicolium/src/hooks/use-timeline-filters-options.ts new file mode 100644 index 000000000..858045809 --- /dev/null +++ b/packages/nicolium/src/hooks/use-timeline-filters-options.ts @@ -0,0 +1,122 @@ +import { useMemo } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { changeSetting } from '@/actions/settings'; +import { useSettings } from '@/stores/settings'; + +import { useFeatures } from './use-features'; + +import type { Menu } from '@/components/dropdown-menu'; + +const messages = defineMessages({ + showReblogs: { id: 'timeline_filters.show_reblogs', defaultMessage: 'Show reposts in timeline' }, + showSelfReblogs: { + id: 'timeline_filters.show_self_reblogs', + defaultMessage: 'Show self-reposts in timeline', + }, + showReplies: { id: 'timeline_filters.show_replies', defaultMessage: 'Show replies in timeline' }, + showQuotes: { id: 'timeline_filters.show_quotes', defaultMessage: 'Show quotes in timeline' }, + showDirect: { + id: 'timeline_filters.show_direct', + defaultMessage: 'Show direct messages in timeline', + }, + hideNonMedia: { + id: 'timeline_filters.show_media_only', + defaultMessage: 'Only show posts with media', + }, + setAsDefault: { + id: 'timeline_filters.set_as_default', + defaultMessage: 'Set as default timeline', + }, +}); + +const defaultSettings = { + showReblogs: true, + showSelfReblogs: true, + showReplies: true, + showQuotes: true, + showDirect: true, + showNonMedia: true, +}; + +const useTimelineFiltersOptions = ( + timeline: + | 'home' + | 'antenna' + | 'bubble' + | 'circle' + | 'local' + | 'group' + | 'hashtag' + | 'list' + | 'public' + | 'wrenched', +) => { + const intl = useIntl(); + const features = useFeatures(); + const timelineSettings = useSettings().timelines[timeline] || defaultSettings; + + return useMemo(() => { + const items: Menu = []; + + if (timeline == 'home') { + items.push({ + text: intl.formatMessage(messages.showReblogs), + type: 'toggle', + checked: timelineSettings?.showReblogs, + onChange: (checked) => changeSetting(['timelines', timeline, 'showReblogs'], checked), + }); + items.push({ + text: intl.formatMessage(messages.showSelfReblogs), + type: 'toggle', + checked: timelineSettings?.showSelfReblogs, + onChange: (checked) => changeSetting(['timelines', timeline, 'showSelfReblogs'], checked), + }); + } + + items.push({ + text: intl.formatMessage(messages.showReplies), + type: 'toggle', + checked: timelineSettings?.showReplies, + onChange: (checked) => changeSetting(['timelines', timeline, 'showReplies'], checked), + }); + + if (features.quotePosts) { + items.push({ + text: intl.formatMessage(messages.showQuotes), + type: 'toggle', + checked: timelineSettings?.showQuotes, + onChange: (checked) => changeSetting(['timelines', timeline, 'showQuotes'], checked), + }); + } + + if (timeline === 'home') { + items.push({ + text: intl.formatMessage(messages.showDirect), + type: 'toggle', + checked: timelineSettings?.showDirect, + onChange: (checked) => changeSetting(['timelines', timeline, 'showDirect'], checked), + }); + } + + items.push({ + text: intl.formatMessage(messages.hideNonMedia), + type: 'toggle', + checked: !timelineSettings?.showNonMedia, + onChange: (checked) => changeSetting(['timelines', timeline, 'showNonMedia'], !checked), + }); + + // { + // items.push(null); + + // items.push({ + // text: intl.formatMessage(messages.setAsDefault), + // icon: require('@phosphor-icons/core/regular/house.svg'), + // }); + // } + + return items; + }, [timeline, features, timelineSettings]); +}; + +export { useTimelineFiltersOptions }; diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index c343fd519..8d01cad8f 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -2024,6 +2024,13 @@ "timeline.gap.load_newer": "Load newer posts", "timeline.gap.load_older": "Load older posts", "timeline.gap.load_recent": "Load recent posts", + "timeline_filters.set_as_default": "Set as default timeline", + "timeline_filters.show_direct": "Show direct messages in timeline", + "timeline_filters.show_media_only": "Only show posts with media", + "timeline_filters.show_quotes": "Show quotes in timeline", + "timeline_filters.show_reblogs": "Show reposts in timeline", + "timeline_filters.show_replies": "Show replies in timeline", + "timeline_filters.show_self_reblogs": "Show self-reposts in timeline", "timeline_picker.pinned_instances": "Pinned instances", "toast.view": "View", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", diff --git a/packages/nicolium/src/pages/timelines/antenna-timeline.tsx b/packages/nicolium/src/pages/timelines/antenna-timeline.tsx index ac4efed7b..03b51c463 100644 --- a/packages/nicolium/src/pages/timelines/antenna-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/antenna-timeline.tsx @@ -1,5 +1,5 @@ import { useNavigate } from '@tanstack/react-router'; -import React from 'react'; +import React, { useMemo } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { AntennaTimelineColumn } from '@/columns/timeline'; @@ -10,6 +10,7 @@ import { TimelinePicker } from '@/components/timeline-picker'; import Column from '@/components/ui/column'; import Spinner from '@/components/ui/spinner'; import { antennaTimelineRoute } from '@/features/ui/router'; +import { useTimelineFiltersOptions } from '@/hooks/use-timeline-filters-options'; import { useAntenna, useDeleteAntenna } from '@/queries/accounts/use-antennas'; import { useModalsActions } from '@/stores/modals'; @@ -34,6 +35,8 @@ const AntennaTimelinePage: React.FC = () => { const { data: antenna, isFetching } = useAntenna(antennaId); const { mutate: deleteAntenna } = useDeleteAntenna(); + const timelineFilterOptions = useTimelineFiltersOptions('antenna'); + const handleEditClick = () => { openModal('ANTENNA_EDITOR', { antennaId }); }; @@ -69,18 +72,23 @@ const AntennaTimelinePage: React.FC = () => { return ; } - const items = [ - { - text: intl.formatMessage(messages.editAntenna), - action: handleEditClick, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), - }, - { - text: intl.formatMessage(messages.deleteAntenna), - action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), - }, - ]; + const items = useMemo( + () => [ + ...timelineFilterOptions, + null, + { + text: intl.formatMessage(messages.editAntenna), + action: handleEditClick, + icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + }, + { + text: intl.formatMessage(messages.deleteAntenna), + action: handleDeleteClick, + icon: require('@phosphor-icons/core/regular/trash.svg'), + }, + ], + [timelineFilterOptions], + ); return ( { const intl = useIntl(); + const items = useTimelineFiltersOptions('bubble'); return ( { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} + action={ + + } > { const intl = useIntl(); const { openModal } = useModalsActions(); const navigate = useNavigate(); + const timelineFilterOptions = useTimelineFiltersOptions('circle'); const { data: circle, isFetching } = useCircle(circleId); const { mutate: deleteCircle } = useDeleteCircle(); @@ -69,18 +71,23 @@ const CircleTimelinePage: React.FC = () => { return ; } - const items = [ - { - text: intl.formatMessage(messages.editCircle), - action: handleEditClick, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), - }, - { - text: intl.formatMessage(messages.deleteCircle), - action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), - }, - ]; + const items = useMemo( + () => [ + ...timelineFilterOptions, + null, + { + text: intl.formatMessage(messages.editCircle), + action: handleEditClick, + icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + }, + { + text: intl.formatMessage(messages.deleteCircle), + action: handleDeleteClick, + icon: require('@phosphor-icons/core/regular/trash.svg'), + }, + ], + [timelineFilterOptions], + ); return ( { + const items = useTimelineFiltersOptions('public'); const intl = useIntl(); return ( @@ -18,6 +21,12 @@ const CommunityTimelinePage = () => { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} + action={ + + } > { const features = useFeatures(); const { data: tag } = useHashtag(hashtag); const { isLoggedIn } = useLoggedIn(); + const items = useTimelineFiltersOptions('hashtag'); const { mutate: followHashtag } = useFollowHashtagMutation(hashtag); const { mutate: unfollowHashtag } = useUnfollowHashtagMutation(hashtag); @@ -33,7 +36,15 @@ const HashtagTimelinePage: React.FC = () => { }; return ( - + + } + > {features.followHashtags && isLoggedIn && ( { const features = useFeatures(); const instance = useInstance(); + const items = useTimelineFiltersOptions('home'); const { isSledzikRemoved } = useUiStore(); if (isSledzikRemoved) return null; @@ -53,6 +56,12 @@ const HomeTimelinePage: React.FC = () => { title={} withBack={false} truncateTitle={false} + action={ + + } > { const intl = useIntl(); const { openModal } = useModalsActions(); const navigate = useNavigate(); + const timelineFilterOptions = useTimelineFiltersOptions('list'); const { data: list, isFetching } = useList(listId); const { mutate: deleteList } = useDeleteList(); @@ -87,18 +89,23 @@ const ListTimelinePage: React.FC = () => { ); } - const items = [ - { - text: intl.formatMessage(messages.editList), - action: handleEditClick, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), - }, - { - text: intl.formatMessage(messages.deleteList), - action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), - }, - ]; + const items = useMemo( + () => [ + ...timelineFilterOptions, + null, + { + text: intl.formatMessage(messages.editList), + action: handleEditClick, + icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + }, + { + text: intl.formatMessage(messages.deleteList), + action: handleDeleteClick, + icon: require('@phosphor-icons/core/regular/trash.svg'), + }, + ], + [timelineFilterOptions], + ); return ( { const instance = useInstance(); const settings = useSettings(); + const items = useTimelineFiltersOptions('public'); const explanationBoxExpanded = settings.explanationBox; const showExplanationBox = settings.showExplanationBox; @@ -38,6 +41,12 @@ const PublicTimelinePage = () => { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} + action={ + + } > {showExplanationBox && ( { const { instance } = remoteTimelineRoute.useParams(); + const items = useTimelineFiltersOptions('public'); const intl = useIntl(); const navigate = useNavigate(); @@ -34,6 +37,12 @@ const RemoteTimelinePage: React.FC = () => { label={instance} title={} truncateTitle={false} + action={ + + } > {!pinned && (
diff --git a/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx b/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx index dd08c9f7c..734db59a3 100644 --- a/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx @@ -2,8 +2,10 @@ import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { WrenchedTimelineColumn } from '@/columns/timeline'; +import DropdownMenu from '@/components/dropdown-menu'; import { TimelinePicker } from '@/components/timeline-picker'; import Column from '@/components/ui/column'; +import { useTimelineFiltersOptions } from '@/hooks/use-timeline-filters-options'; const messages = defineMessages({ title: { id: 'column.wrenched', defaultMessage: 'Recent wrenches timeline' }, @@ -11,6 +13,7 @@ const messages = defineMessages({ const WrenchedTimelinePage = () => { const intl = useIntl(); + const items = useTimelineFiltersOptions('wrenched'); return ( { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} + action={ + + } > ; -type TimelineFilters = Settings['timelines'][string]; +type TimelineFilters = Settings['timelines']['home']; export { settingsSchema, type Settings, type TimelineFilters }; From bc6d85392d1325b5ab4a9c3e25d47f0ad2c1a7b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 15:32:49 +0100 Subject: [PATCH 05/64] nicolium: add aria-haspopup for dropdowns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx b/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx index 79be82a55..d13021616 100644 --- a/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx +++ b/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx @@ -387,6 +387,7 @@ const DropdownMenu: React.FC = (props) => { onClick: handleClick, onKeyPress: handleKeyPress, ref: refs.setReference, + 'aria-haspopup': true, 'aria-expanded': isOpen, }); }, [children, !!items?.length, component]); From 23afe742a979f508fc328a07e0c357c3a35962ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 15:33:47 +0100 Subject: [PATCH 06/64] nicolium: fix disableUserProvidedMedia misses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/media/media-gallery.tsx | 1 - packages/nicolium/src/components/preview-card.tsx | 5 +++-- packages/nicolium/src/components/scroll-top-button.tsx | 4 ++-- packages/nicolium/src/components/statuses/status-media.tsx | 6 +++--- packages/nicolium/src/components/timeline-picker.tsx | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/nicolium/src/components/media/media-gallery.tsx b/packages/nicolium/src/components/media/media-gallery.tsx index cc7609600..88d933a89 100644 --- a/packages/nicolium/src/components/media/media-gallery.tsx +++ b/packages/nicolium/src/components/media/media-gallery.tsx @@ -412,7 +412,6 @@ const MediaGallery: React.FC = (props) => { }[attachment.type]} - // ))}
); diff --git a/packages/nicolium/src/components/preview-card.tsx b/packages/nicolium/src/components/preview-card.tsx index 9596515cb..b1db5b6e1 100644 --- a/packages/nicolium/src/components/preview-card.tsx +++ b/packages/nicolium/src/components/preview-card.tsx @@ -113,6 +113,7 @@ const PreviewCard: React.FC = ({ const intl = useIntl(); const { urlPrivacy: { clearLinksInContent, redirectLinksMode }, + disableUserProvidedMedia, } = useSettings(); const [width, setWidth] = useState(defaultWidth); const [embedded, setEmbedded] = useState(false); @@ -237,7 +238,7 @@ const PreviewCard: React.FC = ({ /> ); - if (interactive) { + if (interactive && !disableUserProvidedMedia) { if (embedded) { embed = ; } else { @@ -295,7 +296,7 @@ const PreviewCard: React.FC = ({ {description}
); - } else if (card.image) { + } else if (card.image && !disableUserProvidedMedia) { embed = (
= ({ accountIds, }) => { const intl = useIntl(); - const { autoloadTimelines } = useSettings(); + const { autoloadTimelines, disableUserProvidedMedia } = useSettings(); // Whether we are scrolled past the `threshold`. const [scrolled, setScrolled] = useState(false); @@ -105,7 +105,7 @@ const ScrollTopButton: React.FC = ({ aria-hidden={!visible} >
- + diff --git a/packages/nicolium/src/styles/new/layout.scss b/packages/nicolium/src/styles/new/layout.scss index 9ea6edc43..ad665175c 100644 --- a/packages/nicolium/src/styles/new/layout.scss +++ b/packages/nicolium/src/styles/new/layout.scss @@ -54,6 +54,19 @@ body { } } +.noscript { + position: absolute; + inset: 0; + padding: 1rem; + text-align: center; + + a { + @include mixins.text($size: inherit, $theme: subtle); + + text-decoration-line: underline; + } +} + #app { height: 100%; } From 8ee0abc86d6dda0c02905f6fe309f75275d3226e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:23:18 +0100 Subject: [PATCH 08/64] nicolium: minor style fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/placeholder-sidebar-suggestions.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx b/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx index a6073c290..3c45cea5e 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx +++ b/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx @@ -9,8 +9,8 @@ const PlaceholderSidebarSuggestions = ({ limit }: { limit: number }) => { return ( <> {new Array(limit).fill(undefined).map((_, idx) => ( -
-
+
+

{generateText(length)}

From 1cbdb1ab3616ca7bc713d249494af000afff5c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:25:02 +0100 Subject: [PATCH 09/64] pl-api: optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/entities/status.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/pl-api/lib/entities/status.ts b/packages/pl-api/lib/entities/status.ts index be8aef867..7937eaa98 100644 --- a/packages/pl-api/lib/entities/status.ts +++ b/packages/pl-api/lib/entities/status.ts @@ -50,12 +50,8 @@ const baseStatusSchema = v.object({ account: v.pipe( v.unknown(), v.transform((account) => { - if ( - typeof window !== 'undefined' && - (window as any).__PL_API_FALLBACK_ACCOUNT && - JSON.stringify(account) === '{}' - ) - return (window as any).__PL_API_FALLBACK_ACCOUNT; + const fallbackAccount = (window as any)?.__PL_API_FALLBACK_ACCOUNT; + if (fallbackAccount && Object.keys(account as object).length > 0) return fallbackAccount; return account; }), accountSchema, From ca8218d0cea11e0ee86052cf4cfb38a2c9acda0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:26:19 +0100 Subject: [PATCH 10/64] pl-api: don't use array with one element for checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/client/accounts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pl-api/lib/client/accounts.ts b/packages/pl-api/lib/client/accounts.ts index 89759d923..2fc9b9ae0 100644 --- a/packages/pl-api/lib/client/accounts.ts +++ b/packages/pl-api/lib/client/accounts.ts @@ -327,7 +327,7 @@ const accounts = (client: PlApiBaseClient) => ({ */ getAccountEndorsements: (accountId: string, params?: GetAccountEndorsementsParams) => client.paginatedGet( - `/api/v1/${[PLEROMA].includes(client.features.version.software as string) ? 'pleroma/' : ''}accounts/${accountId}/endorsements`, + `/api/v1/${client.features.version.software === PLEROMA ? 'pleroma/' : ''}accounts/${accountId}/endorsements`, { params }, accountSchema, ), From 77855b133fda7ba975c1f08cb235a269fb3b842d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:26:58 +0100 Subject: [PATCH 11/64] pl-api: add missing export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/params/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pl-api/lib/params/index.ts b/packages/pl-api/lib/params/index.ts index 7bb9e34bc..5814c9260 100644 --- a/packages/pl-api/lib/params/index.ts +++ b/packages/pl-api/lib/params/index.ts @@ -22,6 +22,7 @@ export * from './scheduled-statuses'; export * from './search'; export * from './settings'; export * from './statuses'; +export * from './stories'; export * from './streaming'; export * from './timelines'; export * from './trends'; From c2c6846f982a61f5185f4e177367dd668b3f8ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:32:42 +0100 Subject: [PATCH 12/64] pl-api: make coerceObject not accept arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/schemas/utils.ts | 4 +++- packages/pl-api/lib/entities/utils.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/nicolium/src/schemas/utils.ts b/packages/nicolium/src/schemas/utils.ts index 93ebb319e..acea8de51 100644 --- a/packages/nicolium/src/schemas/utils.ts +++ b/packages/nicolium/src/schemas/utils.ts @@ -19,7 +19,9 @@ const coerceObject = (shape: T) => v.optional( v.pipe( v.any(), - v.transform((input) => (typeof input === 'object' && input !== null ? input : {})), + v.transform((input) => + typeof input === 'object' && !Array.isArray(input) && input !== null ? input : {}, + ), v.object(shape), ), {}, diff --git a/packages/pl-api/lib/entities/utils.ts b/packages/pl-api/lib/entities/utils.ts index 06d82fcfb..8271dcaa5 100644 --- a/packages/pl-api/lib/entities/utils.ts +++ b/packages/pl-api/lib/entities/utils.ts @@ -40,7 +40,9 @@ const coerceObject = (shape: T) => v.optional( v.pipe( v.any(), - v.transform((input) => (typeof input === 'object' && input !== null ? input : {})), + v.transform((input) => + typeof input === 'object' && !Array.isArray(input) && input !== null ? input : {}, + ), v.object(shape), ), {}, From cee7d9c065f7cd444e86b37ad026db781edeadbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:36:28 +0100 Subject: [PATCH 13/64] pl-api: explicitly specify formdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/pages/settings/import-data.tsx | 2 +- packages/pl-api/lib/client/admin.ts | 4 ++-- packages/pl-api/lib/client/drive.ts | 2 +- packages/pl-api/lib/client/events.ts | 2 +- packages/pl-api/lib/client/oauth.ts | 4 ++-- packages/pl-api/lib/client/settings.ts | 12 ++++++------ packages/pl-api/lib/client/stories.ts | 2 +- packages/pl-api/lib/request.ts | 4 +++- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/nicolium/src/pages/settings/import-data.tsx b/packages/nicolium/src/pages/settings/import-data.tsx index 0e0294fdd..838e73ab4 100644 --- a/packages/nicolium/src/pages/settings/import-data.tsx +++ b/packages/nicolium/src/pages/settings/import-data.tsx @@ -137,7 +137,7 @@ const ImportDataPage = () => { .request('/api/pleroma/archive_import', { method: 'POST', body: form, - contentType: '', + formData: true, }) .then(() => { toast.success(messages.archiveSuccess); diff --git a/packages/pl-api/lib/client/admin.ts b/packages/pl-api/lib/client/admin.ts index f5bf82704..53654e765 100644 --- a/packages/pl-api/lib/client/admin.ts +++ b/packages/pl-api/lib/client/admin.ts @@ -1525,7 +1525,7 @@ const admin = (client: PlApiBaseClient) => { const response = await client.request('/api/v1/admin/custom_emojis', { method: 'POST', body: params, - contentType: '', + formData: true, }); return v.parse(adminCustomEmojiSchema, response.json); @@ -1535,7 +1535,7 @@ const admin = (client: PlApiBaseClient) => { const response = await client.request(`/api/v1/admin/custom_emojis/${emojiId}`, { method: 'PATCH', body: params, - contentType: '', + formData: true, }); return v.parse(adminCustomEmojiSchema, response.json); diff --git a/packages/pl-api/lib/client/drive.ts b/packages/pl-api/lib/client/drive.ts index a410b6f56..5ef824b32 100644 --- a/packages/pl-api/lib/client/drive.ts +++ b/packages/pl-api/lib/client/drive.ts @@ -81,7 +81,7 @@ const drive = (client: PlApiBaseClient) => ({ method: 'POST', body: { file }, params: { folderId }, - contentType: '', + formData: true, }); return v.parse(driveFileSchema, response.json); diff --git a/packages/pl-api/lib/client/events.ts b/packages/pl-api/lib/client/events.ts index ddb832416..f6be65dc0 100644 --- a/packages/pl-api/lib/client/events.ts +++ b/packages/pl-api/lib/client/events.ts @@ -131,7 +131,7 @@ const events = (client: PlApiBaseClient) => ({ */ getEventIcs: async (statusId: string) => { const response = await client.request(`/api/v1/pleroma/events/${statusId}/ics`, { - contentType: '', + formData: true, }); return response.data; diff --git a/packages/pl-api/lib/client/oauth.ts b/packages/pl-api/lib/client/oauth.ts index b17092c82..568ffee02 100644 --- a/packages/pl-api/lib/client/oauth.ts +++ b/packages/pl-api/lib/client/oauth.ts @@ -76,7 +76,7 @@ const oauth = (client: PlApiBaseClient) => ({ const response = await client.request('/oauth/token', { method: 'POST', body: params, - contentType: '', + formData: true, }); return v.parse(tokenSchema, { scope: params.scope || '', ...response.json }); @@ -91,7 +91,7 @@ const oauth = (client: PlApiBaseClient) => ({ const response = await client.request('/oauth/revoke', { method: 'POST', body: params, - contentType: '', + formData: true, }); client.socket?.close(); diff --git a/packages/pl-api/lib/client/settings.ts b/packages/pl-api/lib/client/settings.ts index d4472b3dc..9a6847d2e 100644 --- a/packages/pl-api/lib/client/settings.ts +++ b/packages/pl-api/lib/client/settings.ts @@ -559,7 +559,7 @@ const settings = (client: PlApiBaseClient) => ({ response = await client.request('/api/v1/import', { method: 'POST', body: { data: list, type: 'following', mode }, - contentType: '', + formData: true, }); break; case MITRA: @@ -572,7 +572,7 @@ const settings = (client: PlApiBaseClient) => ({ response = await client.request('/api/pleroma/follow_import', { method: 'POST', body: { list }, - contentType: '', + formData: true, }); } @@ -611,14 +611,14 @@ const settings = (client: PlApiBaseClient) => ({ response = await client.request('/api/v1/import', { method: 'POST', body: { data: list, type: 'blocks', mode }, - contentType: '', + formData: true, }); break; default: response = await client.request('/api/pleroma/blocks_import', { method: 'POST', body: { list }, - contentType: '', + formData: true, }); } @@ -640,14 +640,14 @@ const settings = (client: PlApiBaseClient) => ({ response = await client.request('/api/v1/import', { method: 'POST', body: { data: list, type: 'blocks', mode }, - contentType: '', + formData: true, }); break; default: response = await client.request('/api/pleroma/mutes_import', { method: 'POST', body: { list }, - contentType: '', + formData: true, }); } diff --git a/packages/pl-api/lib/client/stories.ts b/packages/pl-api/lib/client/stories.ts index 88e54dbfe..f39426d35 100644 --- a/packages/pl-api/lib/client/stories.ts +++ b/packages/pl-api/lib/client/stories.ts @@ -110,7 +110,7 @@ const stories = (client: PlApiBaseClient) => ({ const response = await client.request('/api/web/stories/v1/add', { method: 'POST', body: { file }, - contentType: '', + formData: true, }); return v.parse(storyMediaSchema, response.json); diff --git a/packages/pl-api/lib/request.ts b/packages/pl-api/lib/request.ts index 6d4f577cf..cf0935ddf 100644 --- a/packages/pl-api/lib/request.ts +++ b/packages/pl-api/lib/request.ts @@ -78,6 +78,7 @@ interface RequestBody> { onUploadProgress?: (e: ProgressEvent) => void; signal?: AbortSignal; contentType?: string; + formData?: boolean; idempotencyKey?: string; } @@ -96,6 +97,7 @@ function request( onUploadProgress, signal, contentType = 'application/json', + formData, idempotencyKey, }: RequestBody = {}, ) { @@ -108,7 +110,7 @@ function request( else if (this.accessToken) headers.set('Authorization', `Bearer ${this.accessToken}`); else if (this.customAuthorizationToken) headers.set('Authorization', this.customAuthorizationToken); - if (contentType !== '' && body) headers.set('Content-Type', contentType); + if (!formData) headers.set('Content-Type', contentType); if (idempotencyKey) headers.set('Idempotency-Key', idempotencyKey); body = body && contentType === '' ? serialize(body, { indices: true }) : JSON.stringify(body); From decefd73acbd955996964b9d3fdaa4c33ae8f891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:45:37 +0100 Subject: [PATCH 14/64] pl-api: make getLinks not parse the same twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/client-base.ts | 13 ++++++++----- packages/pl-api/lib/client/my-account.ts | 5 ++--- packages/pl-api/lib/request.ts | 19 ++++++++++--------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/pl-api/lib/client-base.ts b/packages/pl-api/lib/client-base.ts index 9bcc579af..70ff502c3 100644 --- a/packages/pl-api/lib/client-base.ts +++ b/packages/pl-api/lib/client-base.ts @@ -3,7 +3,7 @@ import * as v from 'valibot'; import { instanceSchema } from '@/entities/instance'; import { filteredArray } from '@/entities/utils'; import { type Features, getFeatures } from '@/features'; -import request, { getNextLink, getPrevLink, type RequestBody } from '@/request'; +import request, { getLinks, type RequestBody } from '@/request'; import { PaginatedResponse } from '@/responses'; import type { Instance } from '@/entities/instance'; @@ -69,15 +69,18 @@ class PlApiBaseClient { ) => { const targetSchema = isArray ? filteredArray(schema) : schema; - const processResponse = (response: PlApiResponse) => - new PaginatedResponse( + const processResponse = (response: PlApiResponse) => { + const { prev: prevLink, next: nextLink } = getLinks(response); + + return new PaginatedResponse( v.parse(targetSchema, response.json) as IsArray extends true ? Array : T, { - previous: getMore(getPrevLink(response)), - next: getMore(getNextLink(response)), + previous: getMore(prevLink), + next: getMore(nextLink), partial: response.status === 206, }, ); + }; const getMore = (input: string | null) => input ? () => this.request(input).then(processResponse) : null; diff --git a/packages/pl-api/lib/client/my-account.ts b/packages/pl-api/lib/client/my-account.ts index f11c4a5cd..4dc233def 100644 --- a/packages/pl-api/lib/client/my-account.ts +++ b/packages/pl-api/lib/client/my-account.ts @@ -11,7 +11,7 @@ import { } from '@/entities'; import { filteredArray } from '@/entities/utils'; import { GOTOSOCIAL, ICESHRIMP_NET, MITRA, PIXELFED, PLEROMA } from '@/features'; -import { getNextLink, getPrevLink } from '@/request'; +import { getLinks } from '@/request'; import { PaginatedResponse } from '@/responses'; import type { accounts } from './accounts'; @@ -40,8 +40,7 @@ const paginatedIceshrimpAccountsList = async ( const items = await client.accounts.getAccounts(ids); - const prevLink = getPrevLink(response); - const nextLink = getNextLink(response); + const { prev: prevLink, next: nextLink } = getLinks(response); return new PaginatedResponse(items, { previous: prevLink ? () => paginatedIceshrimpAccountsList(client, prevLink, fn) : null, diff --git a/packages/pl-api/lib/request.ts b/packages/pl-api/lib/request.ts index cf0935ddf..25d0e1a6b 100644 --- a/packages/pl-api/lib/request.ts +++ b/packages/pl-api/lib/request.ts @@ -22,14 +22,17 @@ type Response = { @param {object} response - Fetch API response object @returns {object} Link object */ -const getLinks = (response: Pick): LinkHeader => - new LinkHeader(response.headers?.get('link') || undefined); +const getLinks = ( + response: Pick, +): { next: string | null; prev: string | null } => { + const headers = response.headers?.get('link'); + const linkHeader = (headers && new LinkHeader(headers)) || null; -const getNextLink = (response: Pick): string | null => - getLinks(response).refs.find((link) => link.rel.toLocaleLowerCase() === 'next')?.uri || null; - -const getPrevLink = (response: Pick): string | null => - getLinks(response).refs.find((link) => link.rel.toLocaleLowerCase() === 'prev')?.uri || null; + return { + next: linkHeader?.refs.find((link) => link.rel.toLocaleLowerCase() === 'next')?.uri || null, + prev: linkHeader?.refs.find((link) => link.rel.toLocaleLowerCase() === 'prev')?.uri || null, + }; +}; interface AsyncRefreshHeader { id: string; @@ -188,8 +191,6 @@ export { type RequestMeta, type AsyncRefreshHeader, getLinks, - getNextLink, - getPrevLink, getAsyncRefreshHeader, request as default, }; From 759b1cd59a30ba6b5805b16322ff61c2de483bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:50:43 +0100 Subject: [PATCH 15/64] nicolium: move stuff around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/columns/notifications.tsx | 2 +- packages/nicolium/src/columns/search.tsx | 6 +- packages/nicolium/src/columns/timeline.tsx | 2 +- packages/nicolium/src/columns/trends.tsx | 6 +- packages/nicolium/src/components/list.tsx | 2 +- .../index.tsx => components/media/audio.tsx} | 2 +- .../index.tsx => components/media/video.tsx} | 2 +- .../audio => components/media}/visualizer.ts | 0 .../components/panels/account-note-panel.tsx | 0 .../components/panels/birthday-panel.tsx | 0 .../components/panels/group-media-panel.tsx | 0 .../components/panels/instance-info-panel.tsx | 0 .../panels/instance-moderation-panel.tsx | 0 .../components/panels/my-groups-panel.tsx | 2 +- .../components/panels/new-event-panel.tsx | 0 .../components/panels/new-group-panel.tsx | 0 .../components/panels/notifications-panel.tsx | 0 .../panels/pinned-accounts-panel.tsx | 0 .../panels/profile-fields-panel.tsx | 3 +- .../components/panels/profile-info-panel.tsx | 7 +-- .../components/panels/profile-media-panel.tsx | 0 .../ui => }/components/panels/promo-panel.tsx | 0 .../components/panels/sign-up-panel.tsx | 0 .../components/panels/trends-panel.tsx | 2 +- .../ui => }/components/panels/user-panel.tsx | 0 .../components/panels/who-to-follow-panel.tsx | 2 +- .../placeholders}/placeholder-account.tsx | 0 .../placeholders}/placeholder-avatar.tsx | 0 .../placeholders}/placeholder-card.tsx | 2 +- .../placeholder-chat-message.tsx | 3 +- .../placeholders}/placeholder-chat.tsx | 0 .../placeholder-display-name.tsx | 2 +- .../placeholder-event-header.tsx | 2 +- .../placeholder-event-preview.tsx | 3 +- .../placeholders}/placeholder-group-card.tsx | 3 +- .../placeholder-group-search.tsx | 3 +- .../placeholders}/placeholder-hashtag.tsx | 2 +- .../placeholder-media-gallery.tsx | 0 .../placeholder-notification.tsx | 0 .../placeholder-sidebar-suggestions.tsx | 2 +- .../placeholder-sidebar-trends.tsx | 2 +- .../placeholder-status-content.tsx | 2 +- .../placeholders}/placeholder-status.tsx | 0 .../src/components/statuses/status-list.tsx | 2 +- .../src/components/statuses/status-media.tsx | 2 +- .../ui/select-dropdown.tsx} | 0 .../nicolium/src/components/ui/slider.tsx | 2 +- .../src/components/ui/step-slider.tsx | 2 +- .../features/chats/components/chat-list.tsx | 2 +- .../chats/components/chat-message-list.tsx | 2 +- .../components/shoutbox-message-list.tsx | 2 +- .../components/conversations-list.tsx | 2 +- .../event/components/event-header.tsx | 2 +- .../components/group-member-list-item.tsx | 2 +- .../src/features/preferences/index.tsx | 2 +- .../status/components/thread-status.tsx | 2 +- .../src/features/status/components/thread.tsx | 2 +- .../features/ui/components/pending-status.tsx | 4 +- .../ui/components/profile-dropdown.tsx | 2 +- .../src/features/ui/util/async-components.ts | 58 +++++++------------ .../nicolium/src/layouts/event-layout.tsx | 2 +- .../nicolium/src/modals/alt-text-modal.tsx | 2 +- .../src/modals/antenna-editor-modal.tsx | 2 +- .../nicolium/src/modals/birthdays-modal.tsx | 2 +- .../components/edit-list-form.tsx | 2 +- packages/nicolium/src/modals/media-modal.tsx | 6 +- .../nicolium/src/pages/dashboard/account.tsx | 2 +- .../src/pages/groups/group-members.tsx | 2 +- packages/nicolium/src/pages/groups/groups.tsx | 2 +- .../src/pages/settings/edit-filter.tsx | 2 +- .../src/pages/settings/edit-profile.tsx | 2 +- .../nicolium/src/pages/settings/index.tsx | 2 +- .../pages/settings/interaction-policies.tsx | 2 +- .../nicolium/src/pages/settings/privacy.tsx | 2 +- .../src/pages/status-lists/events.tsx | 2 +- .../src/pages/statuses/event-discussion.tsx | 2 +- .../nicolium/src/pages/statuses/status.tsx | 2 +- .../nicolium/src/pages/utils/server-info.tsx | 2 +- .../utils.ts => utils/placeholders.ts} | 0 79 files changed, 85 insertions(+), 109 deletions(-) rename packages/nicolium/src/{features/audio/index.tsx => components/media/audio.tsx} (99%) rename packages/nicolium/src/{features/video/index.tsx => components/media/video.tsx} (99%) rename packages/nicolium/src/{features/audio => components/media}/visualizer.ts (100%) rename packages/nicolium/src/{features/ui => }/components/panels/account-note-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/birthday-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/group-media-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/instance-info-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/instance-moderation-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/my-groups-panel.tsx (90%) rename packages/nicolium/src/{features/ui => }/components/panels/new-event-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/new-group-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/notifications-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/pinned-accounts-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/profile-fields-panel.tsx (89%) rename packages/nicolium/src/{features/ui => }/components/panels/profile-info-panel.tsx (97%) rename packages/nicolium/src/{features/ui => }/components/panels/profile-media-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/promo-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/sign-up-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/trends-panel.tsx (92%) rename packages/nicolium/src/{features/ui => }/components/panels/user-panel.tsx (100%) rename packages/nicolium/src/{features/ui => }/components/panels/who-to-follow-panel.tsx (95%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-account.tsx (100%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-avatar.tsx (100%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-card.tsx (90%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-chat-message.tsx (96%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-chat.tsx (100%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-display-name.tsx (91%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-event-header.tsx (90%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-event-preview.tsx (92%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-group-card.tsx (94%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-group-search.tsx (94%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-hashtag.tsx (82%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-media-gallery.tsx (100%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-notification.tsx (100%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-sidebar-suggestions.tsx (90%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-sidebar-trends.tsx (88%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-status-content.tsx (87%) rename packages/nicolium/src/{features/placeholder/components => components/placeholders}/placeholder-status.tsx (100%) rename packages/nicolium/src/{features/forms/index.tsx => components/ui/select-dropdown.tsx} (100%) rename packages/nicolium/src/{features/placeholder/utils.ts => utils/placeholders.ts} (100%) diff --git a/packages/nicolium/src/columns/notifications.tsx b/packages/nicolium/src/columns/notifications.tsx index f303b970a..900a10f9f 100644 --- a/packages/nicolium/src/columns/notifications.tsx +++ b/packages/nicolium/src/columns/notifications.tsx @@ -7,6 +7,7 @@ import '@/styles/new/notifications.scss'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { saveSettings } from '@/actions/settings'; +import PlaceholderNotification from '@/components/placeholders/placeholder-notification'; import PullToRefresh from '@/components/pull-to-refresh'; import ScrollTopButton from '@/components/scroll-top-button'; import ScrollableList from '@/components/scrollable-list'; @@ -14,7 +15,6 @@ import Icon from '@/components/ui/icon'; import Portal from '@/components/ui/portal'; import Tabs from '@/components/ui/tabs'; import Notification from '@/features/notifications/components/notification'; -import PlaceholderNotification from '@/features/placeholder/components/placeholder-notification'; import { useFeatures } from '@/hooks/use-features'; import { queryClient } from '@/queries/client'; import { queryKeys } from '@/queries/keys'; diff --git a/packages/nicolium/src/columns/search.tsx b/packages/nicolium/src/columns/search.tsx index c068246c5..f6a96b5b8 100644 --- a/packages/nicolium/src/columns/search.tsx +++ b/packages/nicolium/src/columns/search.tsx @@ -4,11 +4,11 @@ import { FormattedMessage } from 'react-intl'; import AccountContainer from '@/components/accounts/account-container'; import Hashtag from '@/components/hashtag'; +import PlaceholderAccount from '@/components/placeholders/placeholder-account'; +import PlaceholderHashtag from '@/components/placeholders/placeholder-hashtag'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; import StatusContainer from '@/components/statuses/status-container'; -import PlaceholderAccount from '@/features/placeholder/components/placeholder-account'; -import PlaceholderHashtag from '@/features/placeholder/components/placeholder-hashtag'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import { useSearchAccounts, useSearchHashtags, diff --git a/packages/nicolium/src/columns/timeline.tsx b/packages/nicolium/src/columns/timeline.tsx index 2d5d14ae2..03051d652 100644 --- a/packages/nicolium/src/columns/timeline.tsx +++ b/packages/nicolium/src/columns/timeline.tsx @@ -4,6 +4,7 @@ import React, { useMemo, useRef, useState } from 'react'; import { defineMessages, FormattedList, FormattedMessage, useIntl } from 'react-intl'; import HoverAccountWrapper from '@/components/accounts/hover-account-wrapper'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import PullToRefresh from '@/components/pull-to-refresh'; import ScrollTopButton from '@/components/scroll-top-button'; import ScrollableList, { type IScrollableList } from '@/components/scrollable-list'; @@ -14,7 +15,6 @@ import Icon from '@/components/ui/icon'; import Portal from '@/components/ui/portal'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import PendingStatus from '@/features/ui/components/pending-status'; import { useFeatures } from '@/hooks/use-features'; import { useAccounts } from '@/queries/accounts/use-accounts'; diff --git a/packages/nicolium/src/columns/trends.tsx b/packages/nicolium/src/columns/trends.tsx index fef62d1e8..728374853 100644 --- a/packages/nicolium/src/columns/trends.tsx +++ b/packages/nicolium/src/columns/trends.tsx @@ -5,13 +5,13 @@ import { FormattedMessage } from 'react-intl'; import AccountContainer from '@/components/accounts/account-container'; import { EmptyMessage } from '@/components/empty-message'; import Hashtag from '@/components/hashtag'; +import PlaceholderAccount from '@/components/placeholders/placeholder-account'; +import PlaceholderHashtag from '@/components/placeholders/placeholder-hashtag'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; import StatusContainer from '@/components/statuses/status-container'; import TrendingLink from '@/components/trending-link'; import Button from '@/components/ui/button'; -import PlaceholderAccount from '@/features/placeholder/components/placeholder-account'; -import PlaceholderHashtag from '@/features/placeholder/components/placeholder-hashtag'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import { useFeatures } from '@/hooks/use-features'; import { useSuggestedAccounts } from '@/queries/trends/use-suggested-accounts'; import { useTrendingLinks } from '@/queries/trends/use-trending-links'; diff --git a/packages/nicolium/src/components/list.tsx b/packages/nicolium/src/components/list.tsx index e03bf8cd0..1fe3eb383 100644 --- a/packages/nicolium/src/components/list.tsx +++ b/packages/nicolium/src/components/list.tsx @@ -4,7 +4,7 @@ import React, { useState } from 'react'; import Icon from '@/components/ui/icon'; import Select from '@/components/ui/select'; -import { SelectDropdown } from '@/features/forms'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; interface IList { children: React.ReactNode; diff --git a/packages/nicolium/src/features/audio/index.tsx b/packages/nicolium/src/components/media/audio.tsx similarity index 99% rename from packages/nicolium/src/features/audio/index.tsx rename to packages/nicolium/src/components/media/audio.tsx index 0b712aa82..1320fc140 100644 --- a/packages/nicolium/src/features/audio/index.tsx +++ b/packages/nicolium/src/components/media/audio.tsx @@ -5,7 +5,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from import { defineMessages, useIntl } from 'react-intl'; import Icon from '@/components/icon'; -import { formatTime, getPointerPosition } from '@/features/video'; +import { formatTime, getPointerPosition } from '@/components/media/video'; import { useSettings } from '@/stores/settings'; import Visualizer from './visualizer'; diff --git a/packages/nicolium/src/features/video/index.tsx b/packages/nicolium/src/components/media/video.tsx similarity index 99% rename from packages/nicolium/src/features/video/index.tsx rename to packages/nicolium/src/components/media/video.tsx index c8987efc9..fc0151bad 100644 --- a/packages/nicolium/src/features/video/index.tsx +++ b/packages/nicolium/src/components/media/video.tsx @@ -14,7 +14,7 @@ import { maximumAspectRatio, } from '@/utils/media-aspect-ratio'; -import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen'; +import { isFullscreen, requestFullscreen, exitFullscreen } from '../../features/ui/util/fullscreen'; const DEFAULT_HEIGHT = 300; diff --git a/packages/nicolium/src/features/audio/visualizer.ts b/packages/nicolium/src/components/media/visualizer.ts similarity index 100% rename from packages/nicolium/src/features/audio/visualizer.ts rename to packages/nicolium/src/components/media/visualizer.ts diff --git a/packages/nicolium/src/features/ui/components/panels/account-note-panel.tsx b/packages/nicolium/src/components/panels/account-note-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/account-note-panel.tsx rename to packages/nicolium/src/components/panels/account-note-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/birthday-panel.tsx b/packages/nicolium/src/components/panels/birthday-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/birthday-panel.tsx rename to packages/nicolium/src/components/panels/birthday-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/group-media-panel.tsx b/packages/nicolium/src/components/panels/group-media-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/group-media-panel.tsx rename to packages/nicolium/src/components/panels/group-media-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/instance-info-panel.tsx b/packages/nicolium/src/components/panels/instance-info-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/instance-info-panel.tsx rename to packages/nicolium/src/components/panels/instance-info-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/instance-moderation-panel.tsx b/packages/nicolium/src/components/panels/instance-moderation-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/instance-moderation-panel.tsx rename to packages/nicolium/src/components/panels/instance-moderation-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/my-groups-panel.tsx b/packages/nicolium/src/components/panels/my-groups-panel.tsx similarity index 90% rename from packages/nicolium/src/features/ui/components/panels/my-groups-panel.tsx rename to packages/nicolium/src/components/panels/my-groups-panel.tsx index ead19bba7..f92a1b3ee 100644 --- a/packages/nicolium/src/features/ui/components/panels/my-groups-panel.tsx +++ b/packages/nicolium/src/components/panels/my-groups-panel.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; +import PlaceholderGroupSearch from '@/components/placeholders/placeholder-group-search'; import Widget from '@/components/ui/widget'; import GroupListItem from '@/features/groups/components/discover/group-list-item'; -import PlaceholderGroupSearch from '@/features/placeholder/components/placeholder-group-search'; import { useGroupsQuery } from '@/queries/groups/use-groups'; const MyGroupsPanel = () => { diff --git a/packages/nicolium/src/features/ui/components/panels/new-event-panel.tsx b/packages/nicolium/src/components/panels/new-event-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/new-event-panel.tsx rename to packages/nicolium/src/components/panels/new-event-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/new-group-panel.tsx b/packages/nicolium/src/components/panels/new-group-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/new-group-panel.tsx rename to packages/nicolium/src/components/panels/new-group-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/notifications-panel.tsx b/packages/nicolium/src/components/panels/notifications-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/notifications-panel.tsx rename to packages/nicolium/src/components/panels/notifications-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/pinned-accounts-panel.tsx b/packages/nicolium/src/components/panels/pinned-accounts-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/pinned-accounts-panel.tsx rename to packages/nicolium/src/components/panels/pinned-accounts-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/profile-fields-panel.tsx b/packages/nicolium/src/components/panels/profile-fields-panel.tsx similarity index 89% rename from packages/nicolium/src/features/ui/components/panels/profile-fields-panel.tsx rename to packages/nicolium/src/components/panels/profile-fields-panel.tsx index aa6857423..b77979871 100644 --- a/packages/nicolium/src/features/ui/components/panels/profile-fields-panel.tsx +++ b/packages/nicolium/src/components/panels/profile-fields-panel.tsx @@ -1,8 +1,7 @@ import React from 'react'; import Widget from '@/components/ui/widget'; - -import { ProfileField } from '../../util/async-components'; +import { ProfileField } from '@/features/ui/util/async-components'; import type { Account } from 'pl-api'; diff --git a/packages/nicolium/src/features/ui/components/panels/profile-info-panel.tsx b/packages/nicolium/src/components/panels/profile-info-panel.tsx similarity index 97% rename from packages/nicolium/src/features/ui/components/panels/profile-info-panel.tsx rename to packages/nicolium/src/components/panels/profile-info-panel.tsx index 9d9e5ff9f..b340c01db 100644 --- a/packages/nicolium/src/features/ui/components/panels/profile-info-panel.tsx +++ b/packages/nicolium/src/components/panels/profile-info-panel.tsx @@ -10,15 +10,14 @@ import Icon from '@/components/ui/icon'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; +import ProfileFamiliarFollowers from '@/features/ui/components/profile-familiar-followers'; +import ProfileStats from '@/features/ui/components/profile-stats'; +import { ProfileField } from '@/features/ui/util/async-components'; import { useAcct } from '@/hooks/use-acct'; import { useAccountScrobbleQuery } from '@/queries/accounts/account-scrobble'; import { useSettings } from '@/stores/settings'; import { capitalize } from '@/utils/strings'; -import { ProfileField } from '../../util/async-components'; -import ProfileFamiliarFollowers from '../profile-familiar-followers'; -import ProfileStats from '../profile-stats'; - import type { Account } from 'pl-api'; const messages = defineMessages({ diff --git a/packages/nicolium/src/features/ui/components/panels/profile-media-panel.tsx b/packages/nicolium/src/components/panels/profile-media-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/profile-media-panel.tsx rename to packages/nicolium/src/components/panels/profile-media-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/promo-panel.tsx b/packages/nicolium/src/components/panels/promo-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/promo-panel.tsx rename to packages/nicolium/src/components/panels/promo-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/sign-up-panel.tsx b/packages/nicolium/src/components/panels/sign-up-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/sign-up-panel.tsx rename to packages/nicolium/src/components/panels/sign-up-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/trends-panel.tsx b/packages/nicolium/src/components/panels/trends-panel.tsx similarity index 92% rename from packages/nicolium/src/features/ui/components/panels/trends-panel.tsx rename to packages/nicolium/src/components/panels/trends-panel.tsx index 28c8287aa..df4be30e3 100644 --- a/packages/nicolium/src/features/ui/components/panels/trends-panel.tsx +++ b/packages/nicolium/src/components/panels/trends-panel.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import Hashtag from '@/components/hashtag'; +import PlaceholderSidebarTrends from '@/components/placeholders/placeholder-sidebar-trends'; import Text from '@/components/ui/text'; import Widget from '@/components/ui/widget'; -import PlaceholderSidebarTrends from '@/features/placeholder/components/placeholder-sidebar-trends'; import useTrendingTags from '@/queries/trends/use-trending-tags'; interface ITrendsPanel { diff --git a/packages/nicolium/src/features/ui/components/panels/user-panel.tsx b/packages/nicolium/src/components/panels/user-panel.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/panels/user-panel.tsx rename to packages/nicolium/src/components/panels/user-panel.tsx diff --git a/packages/nicolium/src/features/ui/components/panels/who-to-follow-panel.tsx b/packages/nicolium/src/components/panels/who-to-follow-panel.tsx similarity index 95% rename from packages/nicolium/src/features/ui/components/panels/who-to-follow-panel.tsx rename to packages/nicolium/src/components/panels/who-to-follow-panel.tsx index 978f3b94d..55107e345 100644 --- a/packages/nicolium/src/features/ui/components/panels/who-to-follow-panel.tsx +++ b/packages/nicolium/src/components/panels/who-to-follow-panel.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AccountContainer from '@/components/accounts/account-container'; +import PlaceholderSidebarSuggestions from '@/components/placeholders/placeholder-sidebar-suggestions'; import Text from '@/components/ui/text'; import Widget from '@/components/ui/widget'; -import PlaceholderSidebarSuggestions from '@/features/placeholder/components/placeholder-sidebar-suggestions'; import { useFeatures } from '@/hooks/use-features'; import { useDismissSuggestion, diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-account.tsx b/packages/nicolium/src/components/placeholders/placeholder-account.tsx similarity index 100% rename from packages/nicolium/src/features/placeholder/components/placeholder-account.tsx rename to packages/nicolium/src/components/placeholders/placeholder-account.tsx diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-avatar.tsx b/packages/nicolium/src/components/placeholders/placeholder-avatar.tsx similarity index 100% rename from packages/nicolium/src/features/placeholder/components/placeholder-avatar.tsx rename to packages/nicolium/src/components/placeholders/placeholder-avatar.tsx diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-card.tsx b/packages/nicolium/src/components/placeholders/placeholder-card.tsx similarity index 90% rename from packages/nicolium/src/features/placeholder/components/placeholder-card.tsx rename to packages/nicolium/src/components/placeholders/placeholder-card.tsx index c8f2af9c5..72ce9fc98 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-card.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-card.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import React from 'react'; -import { randomIntFromInterval, generateText } from '../utils'; +import { randomIntFromInterval, generateText } from '@/utils/placeholders'; /** Fake link preview to display while data is loading. */ const PlaceholderCard: React.FC = React.memo(() => ( diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-chat-message.tsx b/packages/nicolium/src/components/placeholders/placeholder-chat-message.tsx similarity index 96% rename from packages/nicolium/src/features/placeholder/components/placeholder-chat-message.tsx rename to packages/nicolium/src/components/placeholders/placeholder-chat-message.tsx index c5c97f5f1..29aef934f 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-chat-message.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-chat-message.tsx @@ -2,8 +2,7 @@ import clsx from 'clsx'; import React from 'react'; import Text from '@/components/ui/text'; - -import { randomIntFromInterval } from '../utils'; +import { randomIntFromInterval } from '@/utils/placeholders'; import PlaceholderAvatar from './placeholder-avatar'; diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-chat.tsx b/packages/nicolium/src/components/placeholders/placeholder-chat.tsx similarity index 100% rename from packages/nicolium/src/features/placeholder/components/placeholder-chat.tsx rename to packages/nicolium/src/components/placeholders/placeholder-chat.tsx diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-display-name.tsx b/packages/nicolium/src/components/placeholders/placeholder-display-name.tsx similarity index 91% rename from packages/nicolium/src/features/placeholder/components/placeholder-display-name.tsx rename to packages/nicolium/src/components/placeholders/placeholder-display-name.tsx index a071d5270..edecfc26b 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-display-name.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-display-name.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { randomIntFromInterval, generateText } from '../utils'; +import { randomIntFromInterval, generateText } from '@/utils/placeholders'; interface IPlaceholderDisplayName { maxLength: number; diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-event-header.tsx b/packages/nicolium/src/components/placeholders/placeholder-event-header.tsx similarity index 90% rename from packages/nicolium/src/features/placeholder/components/placeholder-event-header.tsx rename to packages/nicolium/src/components/placeholders/placeholder-event-header.tsx index c09c971e8..3725efc4a 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-event-header.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-event-header.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { generateText, randomIntFromInterval } from '../utils'; +import { generateText, randomIntFromInterval } from '@/utils/placeholders'; const PlaceholderEventHeader = () => { const eventNameLength = randomIntFromInterval(5, 25); diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-event-preview.tsx b/packages/nicolium/src/components/placeholders/placeholder-event-preview.tsx similarity index 92% rename from packages/nicolium/src/features/placeholder/components/placeholder-event-preview.tsx rename to packages/nicolium/src/components/placeholders/placeholder-event-preview.tsx index b5f8f2669..290c7059d 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-event-preview.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-event-preview.tsx @@ -1,8 +1,7 @@ import React from 'react'; import Text from '@/components/ui/text'; - -import { generateText, randomIntFromInterval } from '../utils'; +import { generateText, randomIntFromInterval } from '@/utils/placeholders'; const PlaceholderEventPreview = () => { const eventNameLength = randomIntFromInterval(5, 25); diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-group-card.tsx b/packages/nicolium/src/components/placeholders/placeholder-group-card.tsx similarity index 94% rename from packages/nicolium/src/features/placeholder/components/placeholder-group-card.tsx rename to packages/nicolium/src/components/placeholders/placeholder-group-card.tsx index f0406d806..cf6eba642 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-group-card.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-group-card.tsx @@ -1,8 +1,7 @@ import React from 'react'; import Text from '@/components/ui/text'; - -import { generateText, randomIntFromInterval } from '../utils'; +import { generateText, randomIntFromInterval } from '@/utils/placeholders'; const PlaceholderGroupCard = () => { const groupNameLength = randomIntFromInterval(12, 20); diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-group-search.tsx b/packages/nicolium/src/components/placeholders/placeholder-group-search.tsx similarity index 94% rename from packages/nicolium/src/features/placeholder/components/placeholder-group-search.tsx rename to packages/nicolium/src/components/placeholders/placeholder-group-search.tsx index 51395fac5..111992f9b 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-group-search.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-group-search.tsx @@ -1,8 +1,7 @@ import React from 'react'; import Text from '@/components/ui/text'; - -import { generateText, randomIntFromInterval } from '../utils'; +import { generateText, randomIntFromInterval } from '@/utils/placeholders'; const PlaceholderGroupSearch = ({ withJoinAction = true }: { withJoinAction?: boolean }) => { const groupNameLength = randomIntFromInterval(12, 20); diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-hashtag.tsx b/packages/nicolium/src/components/placeholders/placeholder-hashtag.tsx similarity index 82% rename from packages/nicolium/src/features/placeholder/components/placeholder-hashtag.tsx rename to packages/nicolium/src/components/placeholders/placeholder-hashtag.tsx index 9b2a02b63..dc91e71fa 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-hashtag.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-hashtag.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { generateText, randomIntFromInterval } from '../utils'; +import { generateText, randomIntFromInterval } from '@/utils/placeholders'; /** Fake hashtag to display while data is loading. */ const PlaceholderHashtag: React.FC = () => { diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-media-gallery.tsx b/packages/nicolium/src/components/placeholders/placeholder-media-gallery.tsx similarity index 100% rename from packages/nicolium/src/features/placeholder/components/placeholder-media-gallery.tsx rename to packages/nicolium/src/components/placeholders/placeholder-media-gallery.tsx diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-notification.tsx b/packages/nicolium/src/components/placeholders/placeholder-notification.tsx similarity index 100% rename from packages/nicolium/src/features/placeholder/components/placeholder-notification.tsx rename to packages/nicolium/src/components/placeholders/placeholder-notification.tsx diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx b/packages/nicolium/src/components/placeholders/placeholder-sidebar-suggestions.tsx similarity index 90% rename from packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx rename to packages/nicolium/src/components/placeholders/placeholder-sidebar-suggestions.tsx index 3c45cea5e..a529009ee 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-suggestions.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-sidebar-suggestions.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { randomIntFromInterval, generateText } from '../utils'; +import { randomIntFromInterval, generateText } from '@/utils/placeholders'; const PlaceholderSidebarSuggestions = ({ limit }: { limit: number }) => { const length = randomIntFromInterval(15, 3); diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-trends.tsx b/packages/nicolium/src/components/placeholders/placeholder-sidebar-trends.tsx similarity index 88% rename from packages/nicolium/src/features/placeholder/components/placeholder-sidebar-trends.tsx rename to packages/nicolium/src/components/placeholders/placeholder-sidebar-trends.tsx index d3fa2d197..f23b115d8 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-sidebar-trends.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-sidebar-trends.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { randomIntFromInterval, generateText } from '../utils'; +import { randomIntFromInterval, generateText } from '@/utils/placeholders'; const PlaceholderSidebarTrends = ({ limit }: { limit: number }) => { const trend = randomIntFromInterval(6, 3); diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-status-content.tsx b/packages/nicolium/src/components/placeholders/placeholder-status-content.tsx similarity index 87% rename from packages/nicolium/src/features/placeholder/components/placeholder-status-content.tsx rename to packages/nicolium/src/components/placeholders/placeholder-status-content.tsx index 15951295b..69cd86b88 100644 --- a/packages/nicolium/src/features/placeholder/components/placeholder-status-content.tsx +++ b/packages/nicolium/src/components/placeholders/placeholder-status-content.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { randomIntFromInterval, generateText } from '../utils'; +import { randomIntFromInterval, generateText } from '@/utils/placeholders'; interface IPlaceholderStatusContent { maxLength: number; diff --git a/packages/nicolium/src/features/placeholder/components/placeholder-status.tsx b/packages/nicolium/src/components/placeholders/placeholder-status.tsx similarity index 100% rename from packages/nicolium/src/features/placeholder/components/placeholder-status.tsx rename to packages/nicolium/src/components/placeholders/placeholder-status.tsx diff --git a/packages/nicolium/src/components/statuses/status-list.tsx b/packages/nicolium/src/components/statuses/status-list.tsx index 0d2d76d83..e954ce4bc 100644 --- a/packages/nicolium/src/components/statuses/status-list.tsx +++ b/packages/nicolium/src/components/statuses/status-list.tsx @@ -4,9 +4,9 @@ import React, { useRef, useCallback, useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; import LoadGap from '@/components/load-gap'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList, { type IScrollableList } from '@/components/scrollable-list'; import StatusContainer from '@/components/statuses/status-container'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import PendingStatus from '@/features/ui/components/pending-status'; import { timelineToFilterContextType } from '@/queries/settings/use-filters'; import { selectChild } from '@/utils/scroll-utils'; diff --git a/packages/nicolium/src/components/statuses/status-media.tsx b/packages/nicolium/src/components/statuses/status-media.tsx index 18dcd1069..3b4c93e9d 100644 --- a/packages/nicolium/src/components/statuses/status-media.tsx +++ b/packages/nicolium/src/components/statuses/status-media.tsx @@ -1,8 +1,8 @@ import React, { Suspense } from 'react'; import AttachmentThumbs from '@/components/media/attachment-thumbs'; +import PlaceholderCard from '@/components/placeholders/placeholder-card'; import PreviewCard from '@/components/preview-card'; -import PlaceholderCard from '@/features/placeholder/components/placeholder-card'; import { MediaGallery, Video, Audio } from '@/features/ui/util/async-components'; import { useAccount } from '@/queries/accounts/use-account'; import { useModalsActions } from '@/stores/modals'; diff --git a/packages/nicolium/src/features/forms/index.tsx b/packages/nicolium/src/components/ui/select-dropdown.tsx similarity index 100% rename from packages/nicolium/src/features/forms/index.tsx rename to packages/nicolium/src/components/ui/select-dropdown.tsx diff --git a/packages/nicolium/src/components/ui/slider.tsx b/packages/nicolium/src/components/ui/slider.tsx index 8b76e74d2..539343df4 100644 --- a/packages/nicolium/src/components/ui/slider.tsx +++ b/packages/nicolium/src/components/ui/slider.tsx @@ -2,7 +2,7 @@ import clsx from 'clsx'; import throttle from 'lodash/throttle'; import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { getPointerPosition } from '@/features/video'; +import { getPointerPosition } from '@/components/media/video'; interface ISlider { id?: string; diff --git a/packages/nicolium/src/components/ui/step-slider.tsx b/packages/nicolium/src/components/ui/step-slider.tsx index cd7a78db1..1bc2bc9d1 100644 --- a/packages/nicolium/src/components/ui/step-slider.tsx +++ b/packages/nicolium/src/components/ui/step-slider.tsx @@ -1,7 +1,7 @@ import throttle from 'lodash/throttle'; import React, { useCallback, useRef } from 'react'; -import { getPointerPosition } from '@/features/video'; +import { getPointerPosition } from '@/components/media/video'; interface IStepSlider { id?: string; diff --git a/packages/nicolium/src/features/chats/components/chat-list.tsx b/packages/nicolium/src/features/chats/components/chat-list.tsx index 3bd7ace31..8298c9f6d 100644 --- a/packages/nicolium/src/features/chats/components/chat-list.tsx +++ b/packages/nicolium/src/features/chats/components/chat-list.tsx @@ -2,9 +2,9 @@ import clsx from 'clsx'; import React, { useCallback, useRef, useState } from 'react'; import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso'; +import PlaceholderChat from '@/components/placeholders/placeholder-chat'; import PullToRefresh from '@/components/pull-to-refresh'; import Spinner from '@/components/ui/spinner'; -import PlaceholderChat from '@/features/placeholder/components/placeholder-chat'; import { useChats } from '@/queries/chats'; import { useShoutboxIsLoading } from '@/stores/shoutbox'; import { selectChild } from '@/utils/scroll-utils'; diff --git a/packages/nicolium/src/features/chats/components/chat-message-list.tsx b/packages/nicolium/src/features/chats/components/chat-message-list.tsx index e7f065bfa..14ec8550c 100644 --- a/packages/nicolium/src/features/chats/components/chat-message-list.tsx +++ b/packages/nicolium/src/features/chats/components/chat-message-list.tsx @@ -2,12 +2,12 @@ import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react' import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; import { type Components, Virtuoso, type VirtuosoHandle } from 'react-virtuoso'; +import PlaceholderChatMessage from '@/components/placeholders/placeholder-chat-message'; import Avatar from '@/components/ui/avatar'; import Button from '@/components/ui/button'; import Divider from '@/components/ui/divider'; import Spinner from '@/components/ui/spinner'; import Text from '@/components/ui/text'; -import PlaceholderChatMessage from '@/features/placeholder/components/placeholder-chat-message'; import { useRelationshipQuery } from '@/queries/accounts/use-relationship'; import { useChatMessages, diff --git a/packages/nicolium/src/features/chats/components/shoutbox-message-list.tsx b/packages/nicolium/src/features/chats/components/shoutbox-message-list.tsx index aff3c6709..d2e1def02 100644 --- a/packages/nicolium/src/features/chats/components/shoutbox-message-list.tsx +++ b/packages/nicolium/src/features/chats/components/shoutbox-message-list.tsx @@ -4,12 +4,12 @@ import React, { useState, useEffect, useRef, useMemo } from 'react'; import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso'; import HoverAccountWrapper from '@/components/accounts/hover-account-wrapper'; +import PlaceholderChatMessage from '@/components/placeholders/placeholder-chat-message'; import { ParsedContent } from '@/components/statuses/parsed-content'; import Avatar from '@/components/ui/avatar'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; -import PlaceholderChatMessage from '@/features/placeholder/components/placeholder-chat-message'; import { useAccount } from '@/queries/accounts/use-account'; import { useShoutboxIsLoading, useShoutboxMessages, type ShoutMessage } from '@/stores/shoutbox'; diff --git a/packages/nicolium/src/features/conversations/components/conversations-list.tsx b/packages/nicolium/src/features/conversations/components/conversations-list.tsx index b55f88d00..6338c9d60 100644 --- a/packages/nicolium/src/features/conversations/components/conversations-list.tsx +++ b/packages/nicolium/src/features/conversations/components/conversations-list.tsx @@ -2,8 +2,8 @@ import { debounce } from '@tanstack/react-pacer/debouncer'; import React, { useCallback, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import { useConversations } from '@/queries/conversations/use-conversations'; import { selectChild } from '@/utils/scroll-utils'; diff --git a/packages/nicolium/src/features/event/components/event-header.tsx b/packages/nicolium/src/features/event/components/event-header.tsx index 673be77e9..f395d7c69 100644 --- a/packages/nicolium/src/features/event/components/event-header.tsx +++ b/packages/nicolium/src/features/event/components/event-header.tsx @@ -5,6 +5,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import VerificationBadge from '@/components/accounts/verification-badge'; import DropdownMenu, { type Menu as MenuType } from '@/components/dropdown-menu'; import Icon from '@/components/icon'; +import PlaceholderEventHeader from '@/components/placeholders/placeholder-event-header'; import StillImage from '@/components/still-image'; import Button from '@/components/ui/button'; import IconButton from '@/components/ui/icon-button'; @@ -33,7 +34,6 @@ import copy from '@/utils/copy'; import { download } from '@/utils/download'; import { shortNumberFormat } from '@/utils/numbers'; -import PlaceholderEventHeader from '../../placeholder/components/placeholder-event-header'; import EventActionButton from '../components/event-action-button'; import EventDate from '../components/event-date'; diff --git a/packages/nicolium/src/features/group/components/group-member-list-item.tsx b/packages/nicolium/src/features/group/components/group-member-list-item.tsx index 73f637b48..1366d02d8 100644 --- a/packages/nicolium/src/features/group/components/group-member-list-item.tsx +++ b/packages/nicolium/src/features/group/components/group-member-list-item.tsx @@ -5,7 +5,7 @@ import { defineMessages, useIntl } from 'react-intl'; import Account from '@/components/accounts/account'; import DropdownMenu from '@/components/dropdown-menu/dropdown-menu'; -import PlaceholderAccount from '@/features/placeholder/components/placeholder-account'; +import PlaceholderAccount from '@/components/placeholders/placeholder-account'; import { useAccount } from '@/queries/accounts/use-account'; import { useBlockGroupUserMutation } from '@/queries/groups/use-group-blocks'; import { diff --git a/packages/nicolium/src/features/preferences/index.tsx b/packages/nicolium/src/features/preferences/index.tsx index 5648987b3..06a98c544 100644 --- a/packages/nicolium/src/features/preferences/index.tsx +++ b/packages/nicolium/src/features/preferences/index.tsx @@ -7,8 +7,8 @@ import List, { ListItem } from '@/components/list'; import Button from '@/components/ui/button'; import Form from '@/components/ui/form'; import { Multiselect } from '@/components/ui/multiselect'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import StepSlider from '@/components/ui/step-slider'; -import { SelectDropdown } from '@/features/forms'; import SettingToggle from '@/features/settings/components/setting-toggle'; import { useFeatures } from '@/hooks/use-features'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; diff --git a/packages/nicolium/src/features/status/components/thread-status.tsx b/packages/nicolium/src/features/status/components/thread-status.tsx index 56b0a8ee1..3d6ac6fec 100644 --- a/packages/nicolium/src/features/status/components/thread-status.tsx +++ b/packages/nicolium/src/features/status/components/thread-status.tsx @@ -1,9 +1,9 @@ import clsx from 'clsx'; import React from 'react'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import StatusContainer from '@/components/statuses/status-container'; import Tombstone from '@/components/statuses/tombstone'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import { useMinimalStatus } from '@/queries/statuses/use-status'; import { useReplyCount, useReplyToId } from '@/stores/contexts'; import { useStatusMeta } from '@/stores/status-meta'; diff --git a/packages/nicolium/src/features/status/components/thread.tsx b/packages/nicolium/src/features/status/components/thread.tsx index 100b97772..1f3b30d6b 100644 --- a/packages/nicolium/src/features/status/components/thread.tsx +++ b/packages/nicolium/src/features/status/components/thread.tsx @@ -3,10 +3,10 @@ import clsx from 'clsx'; import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { useIntl } from 'react-intl'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; import StatusActionBar from '@/components/statuses/status-action-bar'; import Tombstone from '@/components/statuses/tombstone'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import { Hotkeys } from '@/features/ui/components/hotkeys'; import PendingStatus from '@/features/ui/components/pending-status'; import { diff --git a/packages/nicolium/src/features/ui/components/pending-status.tsx b/packages/nicolium/src/features/ui/components/pending-status.tsx index e8ab1191b..bd75f4b20 100644 --- a/packages/nicolium/src/features/ui/components/pending-status.tsx +++ b/packages/nicolium/src/features/ui/components/pending-status.tsx @@ -3,11 +3,11 @@ import clsx from 'clsx'; import React from 'react'; import Account from '@/components/accounts/account'; +import PlaceholderCard from '@/components/placeholders/placeholder-card'; +import PlaceholderMediaGallery from '@/components/placeholders/placeholder-media-gallery'; import StatusContent from '@/components/statuses/status-content'; import StatusReplyMentions from '@/components/statuses/status-reply-mentions'; import Card from '@/components/ui/card'; -import PlaceholderCard from '@/features/placeholder/components/placeholder-card'; -import PlaceholderMediaGallery from '@/features/placeholder/components/placeholder-media-gallery'; import QuotedStatus from '@/features/status/containers/quoted-status-container'; import { useOwnAccount } from '@/hooks/use-own-account'; import { queryKeys } from '@/queries/keys'; diff --git a/packages/nicolium/src/features/ui/components/profile-dropdown.tsx b/packages/nicolium/src/features/ui/components/profile-dropdown.tsx index abb1add59..1ee3214c8 100644 --- a/packages/nicolium/src/features/ui/components/profile-dropdown.tsx +++ b/packages/nicolium/src/features/ui/components/profile-dropdown.tsx @@ -5,7 +5,7 @@ import { defineMessages, useIntl } from 'react-intl'; import Account from '@/components/accounts/account'; import DropdownMenu from '@/components/dropdown-menu'; -import PlaceholderAccount from '@/features/placeholder/components/placeholder-account'; +import PlaceholderAccount from '@/components/placeholders/placeholder-account'; import { useFeatures } from '@/hooks/use-features'; import { useLoggedInAccount, diff --git a/packages/nicolium/src/features/ui/util/async-components.ts b/packages/nicolium/src/features/ui/util/async-components.ts index dbaccec51..5a252c609 100644 --- a/packages/nicolium/src/features/ui/util/async-components.ts +++ b/packages/nicolium/src/features/ui/util/async-components.ts @@ -1,55 +1,37 @@ import { lazy } from 'react'; // Panels -export const AccountNotePanel = lazy( - () => import('@/features/ui/components/panels/account-note-panel'), -); +export const AccountNotePanel = lazy(() => import('@/components/panels/account-note-panel')); export const AnnouncementsPanel = lazy( () => import('@/components/announcements/announcements-panel'), ); -export const BirthdayPanel = lazy(() => import('@/features/ui/components/panels/birthday-panel')); +export const BirthdayPanel = lazy(() => import('@/components/panels/birthday-panel')); export const CryptoDonatePanel = lazy( () => import('@/features/crypto-donate/components/crypto-donate-panel'), ); -export const GroupMediaPanel = lazy( - () => import('@/features/ui/components/panels/group-media-panel'), -); -export const InstanceInfoPanel = lazy( - () => import('@/features/ui/components/panels/instance-info-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('@/features/ui/components/panels/instance-moderation-panel'), + () => import('@/components/panels/instance-moderation-panel'), ); export const LatestAccountsPanel = lazy( () => import('@/features/admin/components/latest-accounts-panel'), ); -export const MyGroupsPanel = lazy(() => import('@/features/ui/components/panels/my-groups-panel')); -export const NewEventPanel = lazy(() => import('@/features/ui/components/panels/new-event-panel')); -export const NewGroupPanel = lazy(() => import('@/features/ui/components/panels/new-group-panel')); -export const NotificationsPanel = lazy( - () => import('@/features/ui/components/panels/notifications-panel'), -); -export const PinnedAccountsPanel = lazy( - () => import('@/features/ui/components/panels/pinned-accounts-panel'), -); -export const ProfileFieldsPanel = lazy( - () => import('@/features/ui/components/panels/profile-fields-panel'), -); -export const ProfileInfoPanel = lazy( - () => import('@/features/ui/components/panels/profile-info-panel'), -); -export const ProfileMediaPanel = lazy( - () => import('@/features/ui/components/panels/profile-media-panel'), -); -export const PromoPanel = lazy(() => import('@/features/ui/components/panels/promo-panel')); -export const SignUpPanel = lazy(() => import('@/features/ui/components/panels/sign-up-panel')); -export const TrendsPanel = lazy(() => import('@/features/ui/components/panels/trends-panel')); -export const UserPanel = lazy(() => import('@/features/ui/components/panels/user-panel')); -export const WhoToFollowPanel = lazy( - () => import('@/features/ui/components/panels/who-to-follow-panel'), -); +export const MyGroupsPanel = lazy(() => import('@/components/panels/my-groups-panel')); +export const NewEventPanel = lazy(() => import('@/components/panels/new-event-panel')); +export const NewGroupPanel = lazy(() => import('@/components/panels/new-group-panel')); +export const NotificationsPanel = lazy(() => import('@/components/panels/notifications-panel')); +export const PinnedAccountsPanel = lazy(() => import('@/components/panels/pinned-accounts-panel')); +export const ProfileFieldsPanel = lazy(() => import('@/components/panels/profile-fields-panel')); +export const ProfileInfoPanel = lazy(() => import('@/components/panels/profile-info-panel')); +export const ProfileMediaPanel = lazy(() => import('@/components/panels/profile-media-panel')); +export const PromoPanel = lazy(() => import('@/components/panels/promo-panel')); +export const SignUpPanel = lazy(() => import('@/components/panels/sign-up-panel')); +export const TrendsPanel = lazy(() => import('@/components/panels/trends-panel')); +export const UserPanel = lazy(() => import('@/components/panels/user-panel')); +export const WhoToFollowPanel = lazy(() => import('@/components/panels/who-to-follow-panel')); -export const Audio = lazy(() => import('@/features/audio')); +export const Audio = lazy(() => import('@/components/media/audio')); export const ChatWidget = lazy(() => import('@/features/chats/components/chat-widget/chat-widget')); export const ComposeEditor = lazy(() => import('@/features/compose/editor')); export const ComposeForm = lazy(() => import('@/features/compose/components/compose-form')); @@ -62,4 +44,4 @@ export const ModalRoot = lazy(() => import('@/features/ui/components/modal-root' export const ProfileField = lazy(() => import('@/features/ui/components/profile-field')); export const AccountHoverCard = lazy(() => import('@/components/accounts/account-hover-card')); export const StatusHoverCard = lazy(() => import('@/components/statuses/status-hover-card')); -export const Video = lazy(() => import('@/features/video')); +export const Video = lazy(() => import('@/components/media/video')); diff --git a/packages/nicolium/src/layouts/event-layout.tsx b/packages/nicolium/src/layouts/event-layout.tsx index e78e0f457..a3fcebb00 100644 --- a/packages/nicolium/src/layouts/event-layout.tsx +++ b/packages/nicolium/src/layouts/event-layout.tsx @@ -2,11 +2,11 @@ import { Outlet, useLocation, useNavigate } from '@tanstack/react-router'; import React, { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import Column from '@/components/ui/column'; import Layout from '@/components/ui/layout'; import Tabs, { type Item } from '@/components/ui/tabs'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import LinkFooter from '@/features/ui/components/link-footer'; import { layouts } from '@/features/ui/router'; import { diff --git a/packages/nicolium/src/modals/alt-text-modal.tsx b/packages/nicolium/src/modals/alt-text-modal.tsx index 2f2198c64..97a481929 100644 --- a/packages/nicolium/src/modals/alt-text-modal.tsx +++ b/packages/nicolium/src/modals/alt-text-modal.tsx @@ -4,12 +4,12 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import Blurhash from '@/components/media/blurhash'; +import { getPointerPosition } from '@/components/media/video'; import FormGroup from '@/components/ui/form-group'; import Icon from '@/components/ui/icon'; import Modal from '@/components/ui/modal'; import Textarea from '@/components/ui/textarea'; import { MIMETYPE_ICONS } from '@/components/upload'; -import { getPointerPosition } from '@/features/video'; import { useCompose } from '@/hooks/use-compose'; import { useFeatures } from '@/hooks/use-features'; import toast from '@/toast'; diff --git a/packages/nicolium/src/modals/antenna-editor-modal.tsx b/packages/nicolium/src/modals/antenna-editor-modal.tsx index 93064c724..9964ca0f4 100644 --- a/packages/nicolium/src/modals/antenna-editor-modal.tsx +++ b/packages/nicolium/src/modals/antenna-editor-modal.tsx @@ -10,10 +10,10 @@ import FormGroup from '@/components/ui/form-group'; import IconButton from '@/components/ui/icon-button'; import Input from '@/components/ui/input'; import Modal from '@/components/ui/modal'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import Spinner from '@/components/ui/spinner'; import Text from '@/components/ui/text'; import Toggle from '@/components/ui/toggle'; -import { SelectDropdown } from '@/features/forms'; import { useAddAccountsToAntenna, useAddDomainsToAntenna, diff --git a/packages/nicolium/src/modals/birthdays-modal.tsx b/packages/nicolium/src/modals/birthdays-modal.tsx index 1dab66382..8a062415c 100644 --- a/packages/nicolium/src/modals/birthdays-modal.tsx +++ b/packages/nicolium/src/modals/birthdays-modal.tsx @@ -1,11 +1,11 @@ import React, { useState } from 'react'; import { FormattedMessage } from 'react-intl'; +import { getCurrentDate } from '@/components/panels/birthday-panel'; import ScrollableList from '@/components/scrollable-list'; import Modal from '@/components/ui/modal'; import Spinner from '@/components/ui/spinner'; import Account from '@/features/birthdays/account'; -import { getCurrentDate } from '@/features/ui/components/panels/birthday-panel'; import { useBirthdayReminders } from '@/queries/accounts/use-birthday-reminders'; import type { BaseModalProps } from '@/features/ui/components/modal-root'; diff --git a/packages/nicolium/src/modals/list-editor-modal/components/edit-list-form.tsx b/packages/nicolium/src/modals/list-editor-modal/components/edit-list-form.tsx index d19dfcff4..a4d58a684 100644 --- a/packages/nicolium/src/modals/list-editor-modal/components/edit-list-form.tsx +++ b/packages/nicolium/src/modals/list-editor-modal/components/edit-list-form.tsx @@ -7,8 +7,8 @@ import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; import FormGroup from '@/components/ui/form-group'; import Input from '@/components/ui/input'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import Toggle from '@/components/ui/toggle'; -import { SelectDropdown } from '@/features/forms'; import { useFeatures } from '@/hooks/use-features'; import { useList, useUpdateList } from '@/queries/accounts/use-lists'; import toast from '@/toast'; diff --git a/packages/nicolium/src/modals/media-modal.tsx b/packages/nicolium/src/modals/media-modal.tsx index d558fec9c..dbd354538 100644 --- a/packages/nicolium/src/modals/media-modal.tsx +++ b/packages/nicolium/src/modals/media-modal.tsx @@ -5,16 +5,16 @@ import clsx from 'clsx'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; +import Audio from '@/components/media/audio'; import ExtendedVideoPlayer from '@/components/media/extended-video-player'; +import Video from '@/components/media/video'; import MissingIndicator from '@/components/missing-indicator'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import StatusActionBar from '@/components/statuses/status-action-bar'; import Icon from '@/components/ui/icon'; import IconButton from '@/components/ui/icon-button'; -import Audio from '@/features/audio'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import Thread from '@/features/status/components/thread'; import ZoomableImage from '@/features/ui/components/zoomable-image'; -import Video from '@/features/video'; import { useStatus } from '@/queries/statuses/use-status'; import { userTouching } from '@/utils/is-mobile'; diff --git a/packages/nicolium/src/pages/dashboard/account.tsx b/packages/nicolium/src/pages/dashboard/account.tsx index 70fe65a29..fa0303a70 100644 --- a/packages/nicolium/src/pages/dashboard/account.tsx +++ b/packages/nicolium/src/pages/dashboard/account.tsx @@ -8,10 +8,10 @@ import MissingIndicator from '@/components/missing-indicator'; import OutlineBox from '@/components/outline-box'; import Button from '@/components/ui/button'; import Column from '@/components/ui/column'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import TagInput from '@/components/ui/tag-input'; import Text from '@/components/ui/text'; import Toggle from '@/components/ui/toggle'; -import { SelectDropdown } from '@/features/forms'; import ColumnLoading from '@/features/ui/components/column-loading'; import { adminAccountRoute } from '@/features/ui/router'; import { useDeactivateUserModal, useDeleteUserModal } from '@/hooks/use-admin-modals'; diff --git a/packages/nicolium/src/pages/groups/group-members.tsx b/packages/nicolium/src/pages/groups/group-members.tsx index dba81c8bc..d2b50b553 100644 --- a/packages/nicolium/src/pages/groups/group-members.tsx +++ b/packages/nicolium/src/pages/groups/group-members.tsx @@ -3,9 +3,9 @@ import { GroupRoles } from 'pl-api'; import React, { useMemo } from 'react'; import { PendingItemsRow } from '@/components/pending-items-row'; +import PlaceholderAccount from '@/components/placeholders/placeholder-account'; import ScrollableList from '@/components/scrollable-list'; import GroupMemberListItem from '@/features/group/components/group-member-list-item'; -import PlaceholderAccount from '@/features/placeholder/components/placeholder-account'; import { groupMembersRoute } from '@/features/ui/router'; import { useGroupQuery } from '@/queries/groups/use-group'; import { diff --git a/packages/nicolium/src/pages/groups/groups.tsx b/packages/nicolium/src/pages/groups/groups.tsx index 56ddd407f..0a670dcae 100644 --- a/packages/nicolium/src/pages/groups/groups.tsx +++ b/packages/nicolium/src/pages/groups/groups.tsx @@ -3,10 +3,10 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import GroupCard from '@/components/group-card'; +import PlaceholderGroupCard from '@/components/placeholders/placeholder-group-card'; import ScrollableList from '@/components/scrollable-list'; import Button from '@/components/ui/button'; import Text from '@/components/ui/text'; -import PlaceholderGroupCard from '@/features/placeholder/components/placeholder-group-card'; import { useGroupsQuery } from '@/queries/groups/use-groups'; import { useModalsActions } from '@/stores/modals'; diff --git a/packages/nicolium/src/pages/settings/edit-filter.tsx b/packages/nicolium/src/pages/settings/edit-filter.tsx index 57896116a..b70a7cf29 100644 --- a/packages/nicolium/src/pages/settings/edit-filter.tsx +++ b/packages/nicolium/src/pages/settings/edit-filter.tsx @@ -11,10 +11,10 @@ import FormActions from '@/components/ui/form-actions'; import FormGroup from '@/components/ui/form-group'; import Input from '@/components/ui/input'; import Select from '@/components/ui/select'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import Streamfield from '@/components/ui/streamfield'; import Text from '@/components/ui/text'; import Toggle from '@/components/ui/toggle'; -import { SelectDropdown } from '@/features/forms'; import { editFilterRoute } from '@/features/ui/router'; import { useFeatures } from '@/hooks/use-features'; import { useCreateFilter, useFilter, useUpdateFilter } from '@/queries/settings/use-filters'; diff --git a/packages/nicolium/src/pages/settings/edit-profile.tsx b/packages/nicolium/src/pages/settings/edit-profile.tsx index 1099a9851..c9d471676 100644 --- a/packages/nicolium/src/pages/settings/edit-profile.tsx +++ b/packages/nicolium/src/pages/settings/edit-profile.tsx @@ -12,12 +12,12 @@ import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; import FormGroup from '@/components/ui/form-group'; import Input from '@/components/ui/input'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import Streamfield from '@/components/ui/streamfield'; import Textarea from '@/components/ui/textarea'; import Toggle from '@/components/ui/toggle'; import AvatarPicker from '@/features/edit-profile/components/avatar-picker'; import HeaderPicker from '@/features/edit-profile/components/header-picker'; -import { SelectDropdown } from '@/features/forms'; import { useImageField } from '@/hooks/forms/use-image-field'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; diff --git a/packages/nicolium/src/pages/settings/index.tsx b/packages/nicolium/src/pages/settings/index.tsx index bd089f3d8..65a629d5d 100644 --- a/packages/nicolium/src/pages/settings/index.tsx +++ b/packages/nicolium/src/pages/settings/index.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import Hashtag from '@/components/hashtag'; +import PlaceholderHashtag from '@/components/placeholders/placeholder-hashtag'; import ScrollableList from '@/components/scrollable-list'; import Column from '@/components/ui/column'; -import PlaceholderHashtag from '@/features/placeholder/components/placeholder-hashtag'; import { useFollowedTags } from '@/queries/hashtags/use-followed-tags'; const messages = defineMessages({ diff --git a/packages/nicolium/src/pages/settings/interaction-policies.tsx b/packages/nicolium/src/pages/settings/interaction-policies.tsx index 3e205e94d..471228cf8 100644 --- a/packages/nicolium/src/pages/settings/interaction-policies.tsx +++ b/packages/nicolium/src/pages/settings/interaction-policies.tsx @@ -8,10 +8,10 @@ import Column from '@/components/ui/column'; import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; import { InlineMultiselect } from '@/components/ui/inline-multiselect'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import Tabs from '@/components/ui/tabs'; import Text from '@/components/ui/text'; import Warning from '@/features/compose/components/warning'; -import { SelectDropdown } from '@/features/forms'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; import { useInteractionPolicies } from '@/queries/settings/use-interaction-policies'; diff --git a/packages/nicolium/src/pages/settings/privacy.tsx b/packages/nicolium/src/pages/settings/privacy.tsx index f262e6fec..21dadf585 100644 --- a/packages/nicolium/src/pages/settings/privacy.tsx +++ b/packages/nicolium/src/pages/settings/privacy.tsx @@ -12,9 +12,9 @@ import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; import FormGroup from '@/components/ui/form-group'; import Input from '@/components/ui/input'; +import { SelectDropdown } from '@/components/ui/select-dropdown'; import Toggle from '@/components/ui/toggle'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import { SelectDropdown } from '@/features/forms'; import KVStore from '@/storage/kv-store'; import { useSettings } from '@/stores/settings'; import { hasCanvasExtractPermission } from '@/utils/favicon-service'; diff --git a/packages/nicolium/src/pages/status-lists/events.tsx b/packages/nicolium/src/pages/status-lists/events.tsx index 8e81caad3..b822d3c0f 100644 --- a/packages/nicolium/src/pages/status-lists/events.tsx +++ b/packages/nicolium/src/pages/status-lists/events.tsx @@ -2,13 +2,13 @@ import { Link } from '@tanstack/react-router'; import React, { useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import PlaceholderEventPreview from '@/components/placeholders/placeholder-event-preview'; import ReactSwipeableViews from '@/components/react-swipeable-views'; import EventPreview from '@/components/statuses/event-preview'; import Button from '@/components/ui/button'; import Card, { CardBody, CardHeader, CardTitle } from '@/components/ui/card'; import Column from '@/components/ui/column'; import Icon from '@/components/ui/icon'; -import PlaceholderEventPreview from '@/features/placeholder/components/placeholder-event-preview'; import { useStatus } from '@/queries/statuses/use-status'; import { useJoinedEventsTimeline, diff --git a/packages/nicolium/src/pages/statuses/event-discussion.tsx b/packages/nicolium/src/pages/statuses/event-discussion.tsx index 2631d1bf2..77fb8d682 100644 --- a/packages/nicolium/src/pages/statuses/event-discussion.tsx +++ b/packages/nicolium/src/pages/statuses/event-discussion.tsx @@ -2,10 +2,10 @@ import React, { useEffect, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; import MissingIndicator from '@/components/missing-indicator'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; import Tombstone from '@/components/statuses/tombstone'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import ThreadStatus from '@/features/status/components/thread-status'; import PendingStatus from '@/features/ui/components/pending-status'; import { eventDiscussionRoute } from '@/features/ui/router'; diff --git a/packages/nicolium/src/pages/statuses/status.tsx b/packages/nicolium/src/pages/statuses/status.tsx index c81de9928..b1fe0745c 100644 --- a/packages/nicolium/src/pages/statuses/status.tsx +++ b/packages/nicolium/src/pages/statuses/status.tsx @@ -5,9 +5,9 @@ import { defineMessages, useIntl } from 'react-intl'; import { changeSetting } from '@/actions/settings'; import DropdownMenu, { type Menu } from '@/components/dropdown-menu'; import MissingIndicator from '@/components/missing-indicator'; +import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import PullToRefresh from '@/components/pull-to-refresh'; import Column from '@/components/ui/column'; -import PlaceholderStatus from '@/features/placeholder/components/placeholder-status'; import Thread from '@/features/status/components/thread'; import { statusRoute } from '@/features/ui/router'; import { useStatus } from '@/queries/statuses/use-status'; diff --git a/packages/nicolium/src/pages/utils/server-info.tsx b/packages/nicolium/src/pages/utils/server-info.tsx index 2d5cb02b5..a15441ae1 100644 --- a/packages/nicolium/src/pages/utils/server-info.tsx +++ b/packages/nicolium/src/pages/utils/server-info.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; +import PromoPanel from '@/components/panels/promo-panel'; import Column from '@/components/ui/column'; import Divider from '@/components/ui/divider'; import Text from '@/components/ui/text'; import LinkFooter from '@/features/ui/components/link-footer'; -import PromoPanel from '@/features/ui/components/panels/promo-panel'; import { useInstance } from '@/stores/instance'; const messages = defineMessages({ diff --git a/packages/nicolium/src/features/placeholder/utils.ts b/packages/nicolium/src/utils/placeholders.ts similarity index 100% rename from packages/nicolium/src/features/placeholder/utils.ts rename to packages/nicolium/src/utils/placeholders.ts From 0877bf595fac5f500618ae6826d264ae37c8fa12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 16:57:21 +0100 Subject: [PATCH 16/64] nicolium: move more stuff around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/actions/statuses.ts | 2 +- .../src/components/accounts/account.tsx | 2 +- .../groups}/group-action-button.tsx | 0 .../components/{ => groups}/group-card.tsx | 10 +- .../groups}/group-header-image.tsx | 0 .../groups}/group-header.tsx | 0 .../groups}/group-list-item.tsx | 3 +- .../groups}/group-member-count.tsx | 0 .../groups}/group-member-list-item.tsx | 0 .../groups}/group-options-button.tsx | 0 .../groups}/group-privacy.tsx | 0 .../groups}/group-relationship.tsx | 0 .../groups/popover/group-popover.tsx | 4 +- .../components/media/attachment-thumbs.tsx | 2 +- .../navigation}/compose-button.tsx | 2 +- .../navigation}/link-footer.tsx | 0 .../navigation/sidebar-navigation.tsx | 2 +- .../src/components/panels/my-groups-panel.tsx | 2 +- .../nicolium/src/components/polls/poll.tsx | 2 +- .../statuses/events}/event-action-button.tsx | 2 +- .../statuses/events}/event-date.tsx | 2 +- .../statuses/events/event-header.tsx | 582 ++++++++++++++++++ .../statuses/{ => events}/event-preview.tsx | 6 +- .../src/components/statuses/quoted-status.tsx | 2 +- .../statuses/sensitive-content-overlay.tsx | 2 +- .../components/statuses/status-content.tsx | 2 +- .../statuses/status-language-picker.tsx | 2 +- .../src/components/statuses/status-media.tsx | 2 +- .../statuses/status-reply-mentions.tsx | 2 +- .../src/components/statuses/status.tsx | 2 +- .../components/statuses/translate-button.tsx | 2 +- .../compose/components/reply-indicator.tsx | 2 +- .../containers/preview-compose-container.tsx | 4 +- .../src/features/draft-statuses/builder.tsx | 2 +- .../components/draft-status-action-bar.tsx | 2 +- .../event/components/event-header.tsx | 6 +- .../notifications/components/notification.tsx | 2 +- .../features/scheduled-statuses/builder.tsx | 2 +- .../scheduled-status-action-bar.tsx | 2 +- .../components/status-interaction-bar.tsx | 2 +- .../status/components/status-type-icon.tsx | 2 +- .../src/features/status/components/thread.tsx | 2 +- .../features/ui/components/pending-status.tsx | 4 +- packages/nicolium/src/features/ui/index.tsx | 3 +- .../src/features/ui/util/async-components.ts | 2 +- .../nicolium/src/hooks/use-account-gallery.ts | 2 +- .../nicolium/src/hooks/use-can-interact.ts | 2 +- .../nicolium/src/layouts/admin-layout.tsx | 2 +- .../nicolium/src/layouts/default-layout.tsx | 2 +- .../nicolium/src/layouts/event-layout.tsx | 2 +- .../nicolium/src/layouts/events-layout.tsx | 2 +- .../src/layouts/external-login-layout.tsx | 2 +- .../nicolium/src/layouts/group-layout.tsx | 4 +- .../nicolium/src/layouts/groups-layout.tsx | 2 +- packages/nicolium/src/layouts/home-layout.tsx | 2 +- .../src/layouts/manage-groups-layout.tsx | 2 +- .../nicolium/src/layouts/profile-layout.tsx | 2 +- .../src/layouts/remote-instance-layout.tsx | 2 +- .../nicolium/src/layouts/search-layout.tsx | 2 +- .../nicolium/src/layouts/status-layout.tsx | 2 +- .../src/pages/groups/group-members.tsx | 2 +- packages/nicolium/src/pages/groups/groups.tsx | 2 +- .../src/pages/status-lists/events.tsx | 2 +- packages/nicolium/src/pages/utils/landing.tsx | 2 +- .../nicolium/src/pages/utils/server-info.tsx | 2 +- packages/nicolium/src/queries/keys.ts | 2 +- .../statuses/normalize.ts} | 0 .../statuses/use-status-interactions.ts | 2 +- .../src/queries/statuses/use-status.ts | 2 +- .../src/queries/utils/import-entities.ts | 2 +- packages/nicolium/src/stores/compose.ts | 2 +- packages/nicolium/src/stores/timelines.ts | 2 +- .../ui/util => utils}/global-hotkeys.tsx | 2 +- .../util => utils}/pending-status-builder.ts | 2 +- packages/nicolium/src/utils/status.ts | 2 +- 75 files changed, 660 insertions(+), 76 deletions(-) rename packages/nicolium/src/{features/group/components => components/groups}/group-action-button.tsx (100%) rename packages/nicolium/src/components/{ => groups}/group-card.tsx (82%) rename packages/nicolium/src/{features/group/components => components/groups}/group-header-image.tsx (100%) rename packages/nicolium/src/{features/group/components => components/groups}/group-header.tsx (100%) rename packages/nicolium/src/{features/groups/components/discover => components/groups}/group-list-item.tsx (97%) rename packages/nicolium/src/{features/group/components => components/groups}/group-member-count.tsx (100%) rename packages/nicolium/src/{features/group/components => components/groups}/group-member-list-item.tsx (100%) rename packages/nicolium/src/{features/group/components => components/groups}/group-options-button.tsx (100%) rename packages/nicolium/src/{features/group/components => components/groups}/group-privacy.tsx (100%) rename packages/nicolium/src/{features/group/components => components/groups}/group-relationship.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/navigation}/compose-button.tsx (97%) rename packages/nicolium/src/{features/ui/components => components/navigation}/link-footer.tsx (100%) rename packages/nicolium/src/{features/event/components => components/statuses/events}/event-action-button.tsx (97%) rename packages/nicolium/src/{features/event/components => components/statuses/events}/event-date.tsx (96%) create mode 100644 packages/nicolium/src/components/statuses/events/event-header.tsx rename packages/nicolium/src/components/statuses/{ => events}/event-preview.tsx (93%) rename packages/nicolium/src/{normalizers/status.ts => queries/statuses/normalize.ts} (100%) rename packages/nicolium/src/{features/ui/util => utils}/global-hotkeys.tsx (98%) rename packages/nicolium/src/{features/ui/util => utils}/pending-status-builder.ts (95%) diff --git a/packages/nicolium/src/actions/statuses.ts b/packages/nicolium/src/actions/statuses.ts index e03a21246..fb298425e 100644 --- a/packages/nicolium/src/actions/statuses.ts +++ b/packages/nicolium/src/actions/statuses.ts @@ -12,7 +12,7 @@ import { shouldHaveCard } from '@/utils/status'; import { importEntities } from '../queries/utils/import-entities'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { useQueryClient } from '@tanstack/react-query'; import type { CreateStatusParams, PlApiClient, Status as BaseStatus } from 'pl-api'; import type { IntlShape } from 'react-intl'; diff --git a/packages/nicolium/src/components/accounts/account.tsx b/packages/nicolium/src/components/accounts/account.tsx index fba99bb03..2a7f1a28b 100644 --- a/packages/nicolium/src/components/accounts/account.tsx +++ b/packages/nicolium/src/components/accounts/account.tsx @@ -20,7 +20,7 @@ import Badge from '../badge'; import RelativeTimestamp from '../relative-timestamp'; import { ParsedContent } from '../statuses/parsed-content'; -import type { StatusApprovalStatus } from '@/normalizers/status'; +import type { StatusApprovalStatus } from '@/queries/statuses/normalize'; import type { Account as AccountSchema } from 'pl-api'; interface IInstanceFavicon { diff --git a/packages/nicolium/src/features/group/components/group-action-button.tsx b/packages/nicolium/src/components/groups/group-action-button.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-action-button.tsx rename to packages/nicolium/src/components/groups/group-action-button.tsx diff --git a/packages/nicolium/src/components/group-card.tsx b/packages/nicolium/src/components/groups/group-card.tsx similarity index 82% rename from packages/nicolium/src/components/group-card.tsx rename to packages/nicolium/src/components/groups/group-card.tsx index 09d4047cd..2401dc8f1 100644 --- a/packages/nicolium/src/components/group-card.tsx +++ b/packages/nicolium/src/components/groups/group-card.tsx @@ -2,13 +2,13 @@ import React from 'react'; import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; -import GroupHeaderImage from '@/features/group/components/group-header-image'; -import GroupMemberCount from '@/features/group/components/group-member-count'; -import GroupPrivacy from '@/features/group/components/group-privacy'; -import GroupRelationship from '@/features/group/components/group-relationship'; import { useGroupQuery } from '@/queries/groups/use-group'; -import GroupAvatar from './groups/group-avatar'; +import GroupAvatar from './group-avatar'; +import GroupHeaderImage from './group-header-image'; +import GroupMemberCount from './group-member-count'; +import GroupPrivacy from './group-privacy'; +import GroupRelationship from './group-relationship'; interface IGroupCard { groupId: string; diff --git a/packages/nicolium/src/features/group/components/group-header-image.tsx b/packages/nicolium/src/components/groups/group-header-image.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-header-image.tsx rename to packages/nicolium/src/components/groups/group-header-image.tsx diff --git a/packages/nicolium/src/features/group/components/group-header.tsx b/packages/nicolium/src/components/groups/group-header.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-header.tsx rename to packages/nicolium/src/components/groups/group-header.tsx diff --git a/packages/nicolium/src/features/groups/components/discover/group-list-item.tsx b/packages/nicolium/src/components/groups/group-list-item.tsx similarity index 97% rename from packages/nicolium/src/features/groups/components/discover/group-list-item.tsx rename to packages/nicolium/src/components/groups/group-list-item.tsx index 9a65463ed..312307279 100644 --- a/packages/nicolium/src/features/groups/components/discover/group-list-item.tsx +++ b/packages/nicolium/src/components/groups/group-list-item.tsx @@ -6,10 +6,11 @@ import GroupAvatar from '@/components/groups/group-avatar'; import Icon from '@/components/ui/icon'; import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; -import GroupActionButton from '@/features/group/components/group-action-button'; import { useGroupQuery } from '@/queries/groups/use-group'; import { shortNumberFormat } from '@/utils/numbers'; +import GroupActionButton from './group-action-button'; + interface IGroupListItem { groupId: string; withJoinAction?: boolean; diff --git a/packages/nicolium/src/features/group/components/group-member-count.tsx b/packages/nicolium/src/components/groups/group-member-count.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-member-count.tsx rename to packages/nicolium/src/components/groups/group-member-count.tsx diff --git a/packages/nicolium/src/features/group/components/group-member-list-item.tsx b/packages/nicolium/src/components/groups/group-member-list-item.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-member-list-item.tsx rename to packages/nicolium/src/components/groups/group-member-list-item.tsx diff --git a/packages/nicolium/src/features/group/components/group-options-button.tsx b/packages/nicolium/src/components/groups/group-options-button.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-options-button.tsx rename to packages/nicolium/src/components/groups/group-options-button.tsx diff --git a/packages/nicolium/src/features/group/components/group-privacy.tsx b/packages/nicolium/src/components/groups/group-privacy.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-privacy.tsx rename to packages/nicolium/src/components/groups/group-privacy.tsx diff --git a/packages/nicolium/src/features/group/components/group-relationship.tsx b/packages/nicolium/src/components/groups/group-relationship.tsx similarity index 100% rename from packages/nicolium/src/features/group/components/group-relationship.tsx rename to packages/nicolium/src/components/groups/group-relationship.tsx diff --git a/packages/nicolium/src/components/groups/popover/group-popover.tsx b/packages/nicolium/src/components/groups/popover/group-popover.tsx index c0c810931..bc6599c1d 100644 --- a/packages/nicolium/src/components/groups/popover/group-popover.tsx +++ b/packages/nicolium/src/components/groups/popover/group-popover.tsx @@ -7,11 +7,11 @@ import Divider from '@/components/ui/divider'; import Popover from '@/components/ui/popover'; import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; -import GroupMemberCount from '@/features/group/components/group-member-count'; -import GroupPrivacy from '@/features/group/components/group-privacy'; import { groupTimelineRoute } from '@/features/ui/router'; import GroupAvatar from '../group-avatar'; +import GroupMemberCount from '../group-member-count'; +import GroupPrivacy from '../group-privacy'; import type { Group } from 'pl-api'; diff --git a/packages/nicolium/src/components/media/attachment-thumbs.tsx b/packages/nicolium/src/components/media/attachment-thumbs.tsx index f69d97da4..54f376437 100644 --- a/packages/nicolium/src/components/media/attachment-thumbs.tsx +++ b/packages/nicolium/src/components/media/attachment-thumbs.tsx @@ -6,7 +6,7 @@ import { useSettings } from '@/stores/settings'; import { useMediaVisible } from '../statuses/sensitive-content-overlay'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { MediaAttachment } from 'pl-api'; interface IAttachmentThumbs { diff --git a/packages/nicolium/src/features/ui/components/compose-button.tsx b/packages/nicolium/src/components/navigation/compose-button.tsx similarity index 97% rename from packages/nicolium/src/features/ui/components/compose-button.tsx rename to packages/nicolium/src/components/navigation/compose-button.tsx index 14c4854cd..a146c6a9f 100644 --- a/packages/nicolium/src/features/ui/components/compose-button.tsx +++ b/packages/nicolium/src/components/navigation/compose-button.tsx @@ -8,7 +8,7 @@ import { useGroupQuery } from '@/queries/groups/use-group'; import { useComposeActions } from '@/stores/compose'; import { useModalsActions } from '@/stores/modals'; -import { layouts } from '../router'; +import { layouts } from '../../features/ui/router'; interface IComposeButton { /** Whether the button should shrink to fit in a smaller space. */ diff --git a/packages/nicolium/src/features/ui/components/link-footer.tsx b/packages/nicolium/src/components/navigation/link-footer.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/link-footer.tsx rename to packages/nicolium/src/components/navigation/link-footer.tsx diff --git a/packages/nicolium/src/components/navigation/sidebar-navigation.tsx b/packages/nicolium/src/components/navigation/sidebar-navigation.tsx index 1ff3034bd..e970e0f2d 100644 --- a/packages/nicolium/src/components/navigation/sidebar-navigation.tsx +++ b/packages/nicolium/src/components/navigation/sidebar-navigation.tsx @@ -3,9 +3,9 @@ import clsx from 'clsx'; import React, { useMemo } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import ComposeButton from '@/components/navigation/compose-button'; import Icon from '@/components/ui/icon'; import { useStatContext } from '@/contexts/stat-context'; -import ComposeButton from '@/features/ui/components/compose-button'; import ProfileDropdown from '@/features/ui/components/profile-dropdown'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; diff --git a/packages/nicolium/src/components/panels/my-groups-panel.tsx b/packages/nicolium/src/components/panels/my-groups-panel.tsx index f92a1b3ee..aa9c07faf 100644 --- a/packages/nicolium/src/components/panels/my-groups-panel.tsx +++ b/packages/nicolium/src/components/panels/my-groups-panel.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; +import GroupListItem from '@/components/groups/group-list-item'; import PlaceholderGroupSearch from '@/components/placeholders/placeholder-group-search'; import Widget from '@/components/ui/widget'; -import GroupListItem from '@/features/groups/components/discover/group-list-item'; import { useGroupsQuery } from '@/queries/groups/use-groups'; const MyGroupsPanel = () => { diff --git a/packages/nicolium/src/components/polls/poll.tsx b/packages/nicolium/src/components/polls/poll.tsx index 33b4eace9..1bd056469 100644 --- a/packages/nicolium/src/components/polls/poll.tsx +++ b/packages/nicolium/src/components/polls/poll.tsx @@ -10,7 +10,7 @@ import { useStatusMeta } from '@/stores/status-meta'; import PollFooter from './poll-footer'; import PollOption from './poll-option'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; type Selected = Record; diff --git a/packages/nicolium/src/features/event/components/event-action-button.tsx b/packages/nicolium/src/components/statuses/events/event-action-button.tsx similarity index 97% rename from packages/nicolium/src/features/event/components/event-action-button.tsx rename to packages/nicolium/src/components/statuses/events/event-action-button.tsx index 235a11475..82b31f89b 100644 --- a/packages/nicolium/src/features/event/components/event-action-button.tsx +++ b/packages/nicolium/src/components/statuses/events/event-action-button.tsx @@ -10,7 +10,7 @@ import { import { useModalsActions } from '@/stores/modals'; import type { ButtonThemes } from '@/components/ui/button/useButtonStyles'; -import type { NormalizedStatus as StatusEntity } from '@/normalizers/status'; +import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; const messages = defineMessages({ leaveHeading: { id: 'confirmations.leave_event.heading', defaultMessage: 'Leave event' }, diff --git a/packages/nicolium/src/features/event/components/event-date.tsx b/packages/nicolium/src/components/statuses/events/event-date.tsx similarity index 96% rename from packages/nicolium/src/features/event/components/event-date.tsx rename to packages/nicolium/src/components/statuses/events/event-date.tsx index c6e39bdf5..de279d9b5 100644 --- a/packages/nicolium/src/features/event/components/event-date.tsx +++ b/packages/nicolium/src/components/statuses/events/event-date.tsx @@ -3,7 +3,7 @@ import { FormattedDate } from 'react-intl'; import Icon from '@/components/icon'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; interface IEventDate { status: Pick; diff --git a/packages/nicolium/src/components/statuses/events/event-header.tsx b/packages/nicolium/src/components/statuses/events/event-header.tsx new file mode 100644 index 000000000..b77a0619a --- /dev/null +++ b/packages/nicolium/src/components/statuses/events/event-header.tsx @@ -0,0 +1,582 @@ +import { Link, useNavigate } from '@tanstack/react-router'; +import React from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; + +import VerificationBadge from '@/components/accounts/verification-badge'; +import DropdownMenu, { type Menu as MenuType } from '@/components/dropdown-menu'; +import Icon from '@/components/icon'; +import PlaceholderEventHeader from '@/components/placeholders/placeholder-event-header'; +import StillImage from '@/components/still-image'; +import Button from '@/components/ui/button'; +import IconButton from '@/components/ui/icon-button'; +import Text from '@/components/ui/text'; +import Emojify from '@/features/emoji/emojify'; +import { useDeleteStatusModal, useToggleStatusSensitivityModal } from '@/hooks/use-admin-modals'; +import { useClient } from '@/hooks/use-client'; +import { useFeatures } from '@/hooks/use-features'; +import { useOwnAccount } from '@/hooks/use-own-account'; +import { useAccount } from '@/queries/accounts/use-account'; +import { useChats } from '@/queries/chats'; +import { useDeleteStatus } from '@/queries/statuses/use-status'; +import { + useBookmarkStatus, + usePinStatus, + useReblogStatus, + useUnbookmarkStatus, + useUnpinStatus, + useUnreblogStatus, +} from '@/queries/statuses/use-status-interactions'; +import { useComposeActions } from '@/stores/compose'; +import { useModalsActions } from '@/stores/modals'; +import { useSettings } from '@/stores/settings'; +import toast from '@/toast'; +import copy from '@/utils/copy'; +import { download } from '@/utils/download'; +import { shortNumberFormat } from '@/utils/numbers'; + +import EventActionButton from './event-action-button'; +import EventDate from './event-date'; + +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; + +const messages = defineMessages({ + bannerHeader: { id: 'event.banner', defaultMessage: 'Event banner' }, + exportIcs: { id: 'event.export_ics', defaultMessage: 'Export to your calendar' }, + copy: { id: 'event.copy', defaultMessage: 'Copy link to event' }, + copySuccess: { id: 'event.copy.success', defaultMessage: 'Link to event copied to clipboard' }, + copyStatus: { id: 'status.copy_content', defaultMessage: 'Copy post content' }, + copyStatusSuccess: { + id: 'status.copy_content.success', + defaultMessage: 'Post content copied to clipboard', + }, + external: { id: 'event.external', defaultMessage: 'View event on {domain}' }, + bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' }, + unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' }, + quotePost: { id: 'event.quote', defaultMessage: 'Quote event' }, + reblog: { id: 'event.reblog', defaultMessage: 'Repost event' }, + reblogPrivate: { id: 'status.reblog_private', defaultMessage: 'Repost to original audience' }, + cancelReblogPrivate: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' }, + reblogVisibilityPublic: { + id: 'status.reblog_visibility_public', + defaultMessage: 'Public repost', + }, + reblogVisibilityUnlisted: { + id: 'status.reblog_visibility_unlisted', + defaultMessage: 'Quiet public repost', + }, + reblogVisibilityPrivate: { + id: 'status.reblog_visibility_private', + defaultMessage: 'Followers-only repost', + }, + unreblog: { id: 'event.unreblog', defaultMessage: 'Un-repost event' }, + pin: { id: 'status.pin', defaultMessage: 'Pin on profile' }, + unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, + delete: { id: 'status.delete', defaultMessage: 'Delete' }, + mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, + chat: { id: 'status.chat', defaultMessage: 'Chat with @{name}' }, + direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, + report: { id: 'account.report', defaultMessage: 'Report @{name}' }, + adminAccount: { id: 'status.admin_account', defaultMessage: 'Moderate @{name}' }, + adminStatus: { + id: 'status.admin_status', + defaultMessage: 'Open this post in the moderation interface', + }, + markStatusSensitive: { + id: 'admin.statuses.actions.mark_status_sensitive', + defaultMessage: 'Mark post sensitive', + }, + markStatusNotSensitive: { + id: 'admin.statuses.actions.mark_status_not_sensitive', + defaultMessage: 'Mark post not sensitive', + }, + deleteStatus: { id: 'admin.statuses.actions.delete_status', defaultMessage: 'Delete post' }, +}); + +interface IEventHeader { + status?: Pick< + Status, + | 'id' + | 'account_id' + | 'bookmarked' + | 'event' + | 'group_id' + | 'pinned' + | 'reblog_id' + | 'reblogged' + | 'sensitive' + | 'spoiler_text' + | 'uri' + | 'url' + | 'visibility' + | 'list_id' + >; +} + +const EventHeader: React.FC = ({ status }) => { + const intl = useIntl(); + const navigate = useNavigate(); + const { quoteCompose, mentionCompose, directCompose } = useComposeActions(); + + const { openModal } = useModalsActions(); + const { getOrCreateChatByAccountId } = useChats(); + + const client = useClient(); + const features = useFeatures(); + const { boostModal } = useSettings(); + const { data: ownAccount } = useOwnAccount(); + const { data: account } = useAccount(status?.account_id!); + const isStaff = ownAccount ? (ownAccount.is_admin ?? ownAccount.is_moderator) : false; + const isAdmin = ownAccount ? ownAccount.is_admin : false; + + const { mutate: reblogStatus } = useReblogStatus(status?.id!); + const { mutate: unreblogStatus } = useUnreblogStatus(status?.id!); + const { mutate: bookmarkStatus } = useBookmarkStatus(status?.id!); + const { mutate: unbookmarkStatus } = useUnbookmarkStatus(status?.id!); + const { mutate: pinStatus } = usePinStatus(status?.id!); + const { mutate: unpinStatus } = useUnpinStatus(status?.id!); + const { mutate: deleteStatus } = useDeleteStatus(status?.id!); + const deleteStatusModal = useDeleteStatusModal(status?.id!); + const toggleStatusSensitivityModal = useToggleStatusSensitivityModal(status?.id!); + + if (!status || !status.event || !account) { + return ( + <> +
+
+
+ + + + ); + } + const event = status.event; + const banner = event.banner; + + if (!account) return null; + + const username = account.username; + + const handleHeaderClick: React.MouseEventHandler = (e) => { + e.preventDefault(); + e.stopPropagation(); + + openModal('MEDIA', { media: [event.banner!], index: 0 }); + }; + + const handleExportClick = () => { + client.events + .getEventIcs(status.id) + .then((data) => { + download(data, 'calendar.ics'); + }) + .catch(() => {}); + }; + + const handleCopyStatus = () => { + let content = document + .querySelector(`article[data-status-id="${status.id}"] [data-markup="true"]`) + ?.textContent?.trim(); + if (content) { + if (status.spoiler_text.length) content = `${status.spoiler_text}\n\n${content}`; + copy(content, () => toast.success(messages.copyStatusSuccess)); + } + }; + + const handleCopy = () => { + const { uri } = status; + + copy(uri, () => toast.success(messages.copySuccess)); + }; + + const handleBookmarkClick = () => { + if (status.bookmarked) unbookmarkStatus(); + else bookmarkStatus(undefined); + }; + + const handleReblogClick = (visibility?: string) => { + const modalReblog = () => { + if (status.reblogged) unreblogStatus(); + else reblogStatus(visibility); + }; + if (!boostModal) { + modalReblog(); + } else { + openModal('BOOST', { statusId: status.id, onReblog: modalReblog }); + } + }; + + const handleQuoteClick = () => { + quoteCompose(status); + }; + + const handlePinClick = () => { + if (status.pinned) unpinStatus(); + else pinStatus(); + }; + + const handleDeleteClick = () => { + openModal('CONFIRM', { + heading: ( + + ), + message: ( + + ), + confirm: , + onConfirm: () => deleteStatus(undefined), + }); + }; + + const handleMentionClick = () => { + mentionCompose(account); + }; + + const handleChatClick = () => { + getOrCreateChatByAccountId(account.id) + .then((chat) => navigate({ to: '/chats/$chatId', params: { chatId: chat.id } })) + .catch(() => {}); + }; + + const handleDirectClick = () => { + directCompose(account); + }; + + const handleMuteClick = () => { + openModal('BLOCK_MUTE', { accountId: account.id, action: 'MUTE' }); + }; + + const handleBlockClick = () => { + openModal('BLOCK_MUTE', { accountId: account.id, action: 'BLOCK' }); + }; + + const handleReport = () => { + openModal('REPORT', { accountId: account.id, statusIds: [status.id] }); + }; + + const handleToggleStatusSensitivity = () => { + toggleStatusSensitivityModal(status.sensitive); + }; + + const handleDeleteStatus = () => { + deleteStatusModal(); + }; + + const makeMenu = (): MenuType => { + const domain = account.fqn.split('@')[1]; + + const menu: MenuType = [ + { + text: intl.formatMessage(messages.exportIcs), + action: handleExportClick, + icon: require('@phosphor-icons/core/regular/calendar-plus.svg'), + }, + ]; + + menu.push({ + text: intl.formatMessage(messages.copyStatus), + action: handleCopyStatus, + icon: require('@phosphor-icons/core/regular/copy.svg'), + }); + + menu.push({ + text: intl.formatMessage(messages.copy), + action: handleCopy, + icon: require('@phosphor-icons/core/regular/link-simple-horizontal.svg'), + }); + + if (features.federating && !account.local) { + menu.push({ + text: intl.formatMessage(messages.external, { domain }), + icon: require('@phosphor-icons/core/regular/arrow-square-out.svg'), + href: status.uri, + target: '_blank', + }); + } + + if (!ownAccount) return menu; + + if (features.bookmarks) { + menu.push({ + text: intl.formatMessage(status.bookmarked ? messages.unbookmark : messages.bookmark), + action: handleBookmarkClick, + icon: status.bookmarked + ? require('@phosphor-icons/core/regular/bookmark.svg') + : require('@phosphor-icons/core/regular/bookmark-simple.svg'), + }); + } + + if (ownAccount.id === account.id && ['public', 'unlisted'].includes(status.visibility)) { + menu.push({ + text: intl.formatMessage(status.reblogged ? messages.unreblog : messages.reblog), + ...(features.reblogVisibility && !status.reblogged + ? { + items: [ + { + text: intl.formatMessage(messages.reblogVisibilityPublic), + action: () => { + handleReblogClick('public'); + }, + icon: require('@phosphor-icons/core/regular/globe.svg'), + }, + { + text: intl.formatMessage(messages.reblogVisibilityUnlisted), + action: () => { + handleReblogClick('unlisted'); + }, + icon: require('@phosphor-icons/core/regular/moon.svg'), + }, + { + text: intl.formatMessage(messages.reblogVisibilityPrivate), + action: () => { + handleReblogClick('private'); + }, + icon: require('@phosphor-icons/core/regular/lock.svg'), + }, + ], + } + : { + action: () => { + handleReblogClick(); + }, + }), + icon: require('@phosphor-icons/core/regular/repeat.svg'), + }); + + if (features.quotePosts) { + menu.push({ + text: intl.formatMessage(messages.quotePost), + action: handleQuoteClick, + icon: require('@phosphor-icons/core/regular/quotes.svg'), + }); + } + } else if (status.visibility === 'private' || status.visibility === 'mutuals_only') { + menu.push({ + text: intl.formatMessage( + status.reblogged ? messages.cancelReblogPrivate : messages.reblogPrivate, + ), + action: () => { + handleReblogClick(); + }, + icon: require('@phosphor-icons/core/regular/repeat.svg'), + }); + } + + menu.push(null); + + if (ownAccount.id === account.id) { + if (['public', 'unlisted'].includes(status.visibility)) { + menu.push({ + text: intl.formatMessage(status.pinned ? messages.unpin : messages.pin), + action: handlePinClick, + icon: status.pinned + ? require('@phosphor-icons/core/regular/push-pin-slash.svg') + : require('@phosphor-icons/core/regular/push-pin.svg'), + }); + } + + menu.push({ + text: intl.formatMessage(messages.delete), + action: handleDeleteClick, + icon: require('@phosphor-icons/core/regular/trash.svg'), + destructive: true, + }); + } else { + menu.push({ + text: intl.formatMessage(messages.mention, { name: username }), + action: handleMentionClick, + icon: require('@phosphor-icons/core/regular/at.svg'), + }); + + if (account.accepts_chat_messages === true) { + menu.push({ + text: intl.formatMessage(messages.chat, { name: username }), + action: handleChatClick, + icon: require('@phosphor-icons/core/regular/chats-teardrop.svg'), + }); + } else if (features.privacyScopes) { + menu.push({ + text: intl.formatMessage(messages.direct, { name: username }), + action: handleDirectClick, + icon: require('@phosphor-icons/core/regular/chat-circle.svg'), + }); + } + + menu.push(null); + menu.push({ + text: intl.formatMessage(messages.mute, { name: username }), + action: handleMuteClick, + icon: require('@phosphor-icons/core/regular/speaker-simple-x.svg'), + }); + menu.push({ + text: intl.formatMessage(messages.block, { name: username }), + action: handleBlockClick, + icon: require('@phosphor-icons/core/regular/prohibit.svg'), + }); + menu.push({ + text: intl.formatMessage(messages.report, { name: username }), + action: handleReport, + icon: require('@phosphor-icons/core/regular/flag.svg'), + }); + } + + if (isStaff) { + menu.push(null); + + menu.push({ + text: intl.formatMessage(messages.adminAccount, { name: username }), + to: '/nicolium/admin/accounts/$accountId', + params: { accountId: account.id }, + icon: require('@phosphor-icons/core/regular/gavel.svg'), + }); + + if (isAdmin && features.pleromaAdminStatuses) { + menu.push({ + text: intl.formatMessage(messages.adminStatus), + href: `/pleroma/admin/#/statuses/${status.id}/`, + icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + }); + } + + if (features.pleromaAdminStatuses) { + menu.push({ + text: intl.formatMessage( + !status.sensitive ? messages.markStatusSensitive : messages.markStatusNotSensitive, + ), + action: handleToggleStatusSensitivity, + icon: require('@phosphor-icons/core/regular/warning.svg'), + }); + } + + if (account.id !== ownAccount?.id) { + menu.push({ + text: intl.formatMessage(messages.deleteStatus), + action: handleDeleteStatus, + icon: require('@phosphor-icons/core/regular/trash.svg'), + destructive: true, + }); + } + } + + return menu; + }; + + const handleParticipantsClick: React.MouseEventHandler = (e) => { + e.preventDefault(); + e.stopPropagation(); + + if (!ownAccount) { + openModal('UNAUTHORIZED'); + } else { + openModal('EVENT_PARTICIPANTS', { statusId: status.id }); + } + }; + + return ( + <> +
+
+ {banner && ( + + + + )} +
+
+
+
+ + {event.name} + + + + + + + {account.id === ownAccount?.id ? ( + + ) : ( + + )} +
+ +
+
+ + + +
+ + + + {account.verified && } +
+ + ), + }} + /> +
+
+ + {(event.join_mode !== 'external' || event.participants_count > 0) && ( +
+ + + + + + +
+ )} + + + + {event.location && ( +
+ + {event.location.name} +
+ )} +
+
+ + ); +}; + +export { EventHeader as default }; diff --git a/packages/nicolium/src/components/statuses/event-preview.tsx b/packages/nicolium/src/components/statuses/events/event-preview.tsx similarity index 93% rename from packages/nicolium/src/components/statuses/event-preview.tsx rename to packages/nicolium/src/components/statuses/events/event-preview.tsx index e0cc51555..1088e4b10 100644 --- a/packages/nicolium/src/components/statuses/event-preview.tsx +++ b/packages/nicolium/src/components/statuses/events/event-preview.tsx @@ -4,14 +4,14 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import VerificationBadge from '@/components/accounts/verification-badge'; import Icon from '@/components/icon'; +import EventActionButton from '@/components/statuses/events/event-action-button'; +import EventDate from '@/components/statuses/events/event-date'; import Button from '@/components/ui/button'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; -import EventActionButton from '@/features/event/components/event-action-button'; -import EventDate from '@/features/event/components/event-date'; import { useAccount } from '@/queries/accounts/use-account'; -import type { NormalizedStatus as StatusEntity } from '@/normalizers/status'; +import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; const messages = defineMessages({ eventBanner: { id: 'event.banner', defaultMessage: 'Event banner' }, diff --git a/packages/nicolium/src/components/statuses/quoted-status.tsx b/packages/nicolium/src/components/statuses/quoted-status.tsx index 41811ee96..fab6714cc 100644 --- a/packages/nicolium/src/components/statuses/quoted-status.tsx +++ b/packages/nicolium/src/components/statuses/quoted-status.tsx @@ -7,7 +7,7 @@ import AccountContainer from '@/components/accounts/account-container'; import OutlineBox from '../outline-box'; -import EventPreview from './event-preview'; +import EventPreview from './events/event-preview'; import StatusContent from './status-content'; import StatusReplyMentions from './status-reply-mentions'; diff --git a/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx b/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx index d44bd559f..a65d36dc9 100644 --- a/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx +++ b/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx @@ -7,7 +7,7 @@ import Text from '@/components/ui/text'; import { useSettings } from '@/stores/settings'; import { useStatusMeta, useStatusMetaActions } from '@/stores/status-meta'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { FilterResult } from 'pl-api'; const useMediaVisible = ( diff --git a/packages/nicolium/src/components/statuses/status-content.tsx b/packages/nicolium/src/components/statuses/status-content.tsx index 30f069a56..5d667ba66 100644 --- a/packages/nicolium/src/components/statuses/status-content.tsx +++ b/packages/nicolium/src/components/statuses/status-content.tsx @@ -27,7 +27,7 @@ import StatusMedia from './status-media'; import TranslateButton from './translate-button'; import type { Sizes } from '@/components/ui/text'; -import type { NormalizedStatus } from '@/normalizers/status'; +import type { NormalizedStatus } from '@/queries/statuses/normalize'; const BIG_EMOJI_LIMIT = 10; diff --git a/packages/nicolium/src/components/statuses/status-language-picker.tsx b/packages/nicolium/src/components/statuses/status-language-picker.tsx index 59bc5fa36..b7c8aba6c 100644 --- a/packages/nicolium/src/components/statuses/status-language-picker.tsx +++ b/packages/nicolium/src/components/statuses/status-language-picker.tsx @@ -8,7 +8,7 @@ import { useStatusMeta, useStatusMetaActions } from '@/stores/status-meta'; import DropdownMenu from '../dropdown-menu'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; const messages = defineMessages({ languageVersions: { diff --git a/packages/nicolium/src/components/statuses/status-media.tsx b/packages/nicolium/src/components/statuses/status-media.tsx index 3b4c93e9d..b6fc3bf11 100644 --- a/packages/nicolium/src/components/statuses/status-media.tsx +++ b/packages/nicolium/src/components/statuses/status-media.tsx @@ -10,7 +10,7 @@ import { useSettings } from '@/stores/settings'; import { useMediaVisible } from './sensitive-content-overlay'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { MediaAttachment } from 'pl-api'; interface IStatusMedia { diff --git a/packages/nicolium/src/components/statuses/status-reply-mentions.tsx b/packages/nicolium/src/components/statuses/status-reply-mentions.tsx index fbbfd81ff..095e8eb40 100644 --- a/packages/nicolium/src/components/statuses/status-reply-mentions.tsx +++ b/packages/nicolium/src/components/statuses/status-reply-mentions.tsx @@ -6,7 +6,7 @@ import HoverAccountWrapper from '@/components/accounts/hover-account-wrapper'; import HoverStatusWrapper from '@/components/statuses/hover-status-wrapper'; import { useModalsActions } from '@/stores/modals'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; interface IStatusReplyMentions { status: Pick; diff --git a/packages/nicolium/src/components/statuses/status.tsx b/packages/nicolium/src/components/statuses/status.tsx index 1fb6288d1..67390a711 100644 --- a/packages/nicolium/src/components/statuses/status.tsx +++ b/packages/nicolium/src/components/statuses/status.tsx @@ -29,7 +29,7 @@ import { textForScreenReader } from '@/utils/status'; import HashtagLink from '../hashtag-link'; import RelativeTimestamp from '../relative-timestamp'; -import EventPreview from './event-preview'; +import EventPreview from './events/event-preview'; import RssFeedInfo from './rss-feed-info'; import StatusActionBar from './status-action-bar'; import StatusContent from './status-content'; diff --git a/packages/nicolium/src/components/statuses/translate-button.tsx b/packages/nicolium/src/components/statuses/translate-button.tsx index d5abf13c6..b4938f3b7 100644 --- a/packages/nicolium/src/components/statuses/translate-button.tsx +++ b/packages/nicolium/src/components/statuses/translate-button.tsx @@ -16,7 +16,7 @@ import { import { useSettings } from '@/stores/settings'; import { useStatusMeta, useStatusMetaActions } from '@/stores/status-meta'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { Instance } from 'pl-api'; const canRemoteTranslate = ( diff --git a/packages/nicolium/src/features/compose/components/reply-indicator.tsx b/packages/nicolium/src/features/compose/components/reply-indicator.tsx index 7ebc96c68..f0ae5bc4c 100644 --- a/packages/nicolium/src/features/compose/components/reply-indicator.tsx +++ b/packages/nicolium/src/features/compose/components/reply-indicator.tsx @@ -8,7 +8,7 @@ import { ParsedContent } from '@/components/statuses/parsed-content'; import QuotedStatusIndicator from '@/components/statuses/quoted-status-indicator'; import { getTextDirection } from '@/utils/rtl'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; interface IReplyIndicator { className?: string; diff --git a/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx b/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx index 807a2b2dc..2cf99ea32 100644 --- a/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx +++ b/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx @@ -3,7 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AccountContainer from '@/components/accounts/account-container'; import OutlineBox from '@/components/outline-box'; -import EventPreview from '@/components/statuses/event-preview'; +import EventPreview from '@/components/statuses/events/event-preview'; import QuotedStatusIndicator from '@/components/statuses/quoted-status-indicator'; import SensitiveContentOverlay from '@/components/statuses/sensitive-content-overlay'; import StatusContent from '@/components/statuses/status-content'; @@ -15,7 +15,7 @@ import Text from '@/components/ui/text'; import Toggle from '@/components/ui/toggle'; import { useCompose, useComposeActions } from '@/stores/compose'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; const messages = defineMessages({ close: { diff --git a/packages/nicolium/src/features/draft-statuses/builder.tsx b/packages/nicolium/src/features/draft-statuses/builder.tsx index 8ad1db390..49bed3957 100644 --- a/packages/nicolium/src/features/draft-statuses/builder.tsx +++ b/packages/nicolium/src/features/draft-statuses/builder.tsx @@ -1,7 +1,7 @@ import { pollSchema, statusSchema, type Account } from 'pl-api'; import * as v from 'valibot'; -import { normalizeStatus } from '@/normalizers/status'; +import { normalizeStatus } from '@/queries/statuses/normalize'; import type { DraftStatus } from '@/queries/statuses/use-draft-statuses'; diff --git a/packages/nicolium/src/features/draft-statuses/components/draft-status-action-bar.tsx b/packages/nicolium/src/features/draft-statuses/components/draft-status-action-bar.tsx index 3e13eea91..26f7c7312 100644 --- a/packages/nicolium/src/features/draft-statuses/components/draft-status-action-bar.tsx +++ b/packages/nicolium/src/features/draft-statuses/components/draft-status-action-bar.tsx @@ -11,7 +11,7 @@ import { useComposeActions } from '@/stores/compose'; import { useModalsActions } from '@/stores/modals'; import { useSettings } from '@/stores/settings'; -import type { NormalizedStatus as StatusEntity } from '@/normalizers/status'; +import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; import type { DraftStatus } from '@/queries/statuses/use-draft-statuses'; const messages = defineMessages({ diff --git a/packages/nicolium/src/features/event/components/event-header.tsx b/packages/nicolium/src/features/event/components/event-header.tsx index f395d7c69..8c7fab13b 100644 --- a/packages/nicolium/src/features/event/components/event-header.tsx +++ b/packages/nicolium/src/features/event/components/event-header.tsx @@ -34,10 +34,10 @@ import copy from '@/utils/copy'; import { download } from '@/utils/download'; import { shortNumberFormat } from '@/utils/numbers'; -import EventActionButton from '../components/event-action-button'; -import EventDate from '../components/event-date'; +import EventActionButton from '../../../components/statuses/events/event-action-button'; +import EventDate from '../../../components/statuses/events/event-date'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; const messages = defineMessages({ bannerHeader: { id: 'event.banner', defaultMessage: 'Event banner' }, diff --git a/packages/nicolium/src/features/notifications/components/notification.tsx b/packages/nicolium/src/features/notifications/components/notification.tsx index a3b276cd1..d298d1294 100644 --- a/packages/nicolium/src/features/notifications/components/notification.tsx +++ b/packages/nicolium/src/features/notifications/components/notification.tsx @@ -35,7 +35,7 @@ import { useModalsActions } from '@/stores/modals'; import { useSettings } from '@/stores/settings'; import { useStatusMetaActions } from '@/stores/status-meta'; -import type { NormalizedStatus as StatusEntity } from '@/normalizers/status'; +import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; import type { NotificationType } from '@/utils/notification'; import type { Account, NotificationGroup } from 'pl-api'; diff --git a/packages/nicolium/src/features/scheduled-statuses/builder.tsx b/packages/nicolium/src/features/scheduled-statuses/builder.tsx index 33b4ce049..4dfd61717 100644 --- a/packages/nicolium/src/features/scheduled-statuses/builder.tsx +++ b/packages/nicolium/src/features/scheduled-statuses/builder.tsx @@ -1,7 +1,7 @@ import { statusSchema, type Account, type ScheduledStatus } from 'pl-api'; import * as v from 'valibot'; -import { normalizeStatus } from '@/normalizers/status'; +import { normalizeStatus } from '@/queries/statuses/normalize'; const buildStatus = (account: Account, scheduledStatus: ScheduledStatus) => { const poll = scheduledStatus.params.poll diff --git a/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx b/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx index 02f7c771e..9ac4e5f0d 100644 --- a/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx +++ b/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status-action-bar.tsx @@ -6,7 +6,7 @@ import { useCancelScheduledStatusMutation } from '@/queries/statuses/scheduled-s import { useModalsActions } from '@/stores/modals'; import { useSettings } from '@/stores/settings'; -import type { NormalizedStatus as StatusEntity } from '@/normalizers/status'; +import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; const messages = defineMessages({ cancel: { id: 'scheduled_status.cancel', defaultMessage: 'Cancel' }, diff --git a/packages/nicolium/src/features/status/components/status-interaction-bar.tsx b/packages/nicolium/src/features/status/components/status-interaction-bar.tsx index 89013f9b3..87971cafb 100644 --- a/packages/nicolium/src/features/status/components/status-interaction-bar.tsx +++ b/packages/nicolium/src/features/status/components/status-interaction-bar.tsx @@ -9,7 +9,7 @@ import { useFeatures } from '@/hooks/use-features'; import { useAccount } from '@/queries/accounts/use-account'; import { useModalsActions } from '@/stores/modals'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; interface IStatusInteractionBar { status: Pick< diff --git a/packages/nicolium/src/features/status/components/status-type-icon.tsx b/packages/nicolium/src/features/status/components/status-type-icon.tsx index 8aba30190..080621d5e 100644 --- a/packages/nicolium/src/features/status/components/status-type-icon.tsx +++ b/packages/nicolium/src/features/status/components/status-type-icon.tsx @@ -3,7 +3,7 @@ import { defineMessages, type MessageDescriptor, useIntl } from 'react-intl'; import Icon from '@/components/ui/icon'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; interface IStatusTypeIcon { visibility: Status['visibility']; diff --git a/packages/nicolium/src/features/status/components/thread.tsx b/packages/nicolium/src/features/status/components/thread.tsx index 1f3b30d6b..76266e409 100644 --- a/packages/nicolium/src/features/status/components/thread.tsx +++ b/packages/nicolium/src/features/status/components/thread.tsx @@ -26,7 +26,7 @@ import { textForScreenReader } from '@/utils/status'; import DetailedStatus from './detailed-status'; import ThreadStatus from './thread-status'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { SelectedStatus } from '@/queries/statuses/use-status'; import type { Account } from 'pl-api'; import type { VirtuosoHandle } from 'react-virtuoso'; diff --git a/packages/nicolium/src/features/ui/components/pending-status.tsx b/packages/nicolium/src/features/ui/components/pending-status.tsx index bd75f4b20..671f7b737 100644 --- a/packages/nicolium/src/features/ui/components/pending-status.tsx +++ b/packages/nicolium/src/features/ui/components/pending-status.tsx @@ -13,11 +13,11 @@ import { useOwnAccount } from '@/hooks/use-own-account'; import { queryKeys } from '@/queries/keys'; import { usePendingStatus } from '@/stores/pending-statuses'; -import { buildStatus } from '../util/pending-status-builder'; +import { buildStatus } from '../../../utils/pending-status-builder'; import PollPreview from './poll-preview'; -import type { NormalizedStatus as StatusEntity } from '@/normalizers/status'; +import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; import type { Poll } from 'pl-api'; const shouldHaveCard = (pendingStatus: StatusEntity) => diff --git a/packages/nicolium/src/features/ui/index.tsx b/packages/nicolium/src/features/ui/index.tsx index c08736821..d36c47f79 100644 --- a/packages/nicolium/src/features/ui/index.tsx +++ b/packages/nicolium/src/features/ui/index.tsx @@ -29,6 +29,8 @@ import { useShoutboxSubscription } from '@/stores/shoutbox'; import { useIsDropdownMenuOpen } from '@/stores/ui'; import { useIsStandalone } from '@/utils/state'; +import GlobalHotkeys from '../../utils/global-hotkeys'; + import { ModalRoot, AccountHoverCard, @@ -36,7 +38,6 @@ import { DropdownNavigation, StatusHoverCard, } from './util/async-components'; -import GlobalHotkeys from './util/global-hotkeys'; // Dummy import, to make sure that ends up in the application bundle. // Without this it ends up in ~8 very commonly used bundles. import '@/components/statuses/status'; diff --git a/packages/nicolium/src/features/ui/util/async-components.ts b/packages/nicolium/src/features/ui/util/async-components.ts index 5a252c609..c3bc0f752 100644 --- a/packages/nicolium/src/features/ui/util/async-components.ts +++ b/packages/nicolium/src/features/ui/util/async-components.ts @@ -38,7 +38,7 @@ export const ComposeForm = lazy(() => import('@/features/compose/components/comp export const DatePicker = lazy(() => import('@/features/birthdays/date-picker')); export const DropdownNavigation = lazy(() => import('@/components/navigation/dropdown-navigation')); export const EmojiPicker = lazy(() => import('@/features/emoji/components/emoji-picker')); -export const EventHeader = lazy(() => import('@/features/event/components/event-header')); +export const EventHeader = lazy(() => import('@/components/statuses/events/event-header')); export const MediaGallery = lazy(() => import('@/components/media/media-gallery')); export const ModalRoot = lazy(() => import('@/features/ui/components/modal-root')); export const ProfileField = lazy(() => import('@/features/ui/components/profile-field')); diff --git a/packages/nicolium/src/hooks/use-account-gallery.ts b/packages/nicolium/src/hooks/use-account-gallery.ts index 79b8a2463..022a58cef 100644 --- a/packages/nicolium/src/hooks/use-account-gallery.ts +++ b/packages/nicolium/src/hooks/use-account-gallery.ts @@ -6,7 +6,7 @@ import { useGroupMediaTimeline, } from '@/queries/timelines/use-account-media-timeline'; -import type { NormalizedStatus } from '@/normalizers/status'; +import type { NormalizedStatus } from '@/queries/statuses/normalize'; import type { MediaAttachment } from 'pl-api'; type AccountGalleryAttachment = MediaAttachment & { diff --git a/packages/nicolium/src/hooks/use-can-interact.ts b/packages/nicolium/src/hooks/use-can-interact.ts index 88f331132..4f0d59987 100644 --- a/packages/nicolium/src/hooks/use-can-interact.ts +++ b/packages/nicolium/src/hooks/use-can-interact.ts @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import type { NormalizedStatus } from '@/normalizers/status'; +import type { NormalizedStatus } from '@/queries/statuses/normalize'; import type { InteractionPolicy, InteractionPolicyEntry } from 'pl-api'; const useCanInteract = ( diff --git a/packages/nicolium/src/layouts/admin-layout.tsx b/packages/nicolium/src/layouts/admin-layout.tsx index f40b57290..6cd4fda7b 100644 --- a/packages/nicolium/src/layouts/admin-layout.tsx +++ b/packages/nicolium/src/layouts/admin-layout.tsx @@ -4,7 +4,7 @@ import React from 'react'; import Layout from '@/components/ui/layout'; import { LatestAccountsPanel } from '@/features/ui/util/async-components'; -import LinkFooter from '../features/ui/components/link-footer'; +import LinkFooter from '../components/navigation/link-footer'; const AdminLayout = () => ( <> diff --git a/packages/nicolium/src/layouts/default-layout.tsx b/packages/nicolium/src/layouts/default-layout.tsx index 8cbf88b40..e63b08735 100644 --- a/packages/nicolium/src/layouts/default-layout.tsx +++ b/packages/nicolium/src/layouts/default-layout.tsx @@ -1,9 +1,9 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import LinkFooter from '@/features/ui/components/link-footer'; import { WhoToFollowPanel, TrendsPanel, SignUpPanel } from '@/features/ui/util/async-components'; import { useFeatures } from '@/hooks/use-features'; const DefaultLayout: React.FC = () => { diff --git a/packages/nicolium/src/layouts/event-layout.tsx b/packages/nicolium/src/layouts/event-layout.tsx index a3fcebb00..f3d29dac1 100644 --- a/packages/nicolium/src/layouts/event-layout.tsx +++ b/packages/nicolium/src/layouts/event-layout.tsx @@ -2,12 +2,12 @@ import { Outlet, useLocation, useNavigate } from '@tanstack/react-router'; import React, { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; +import LinkFooter from '@/components/navigation/link-footer'; import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import Column from '@/components/ui/column'; import Layout from '@/components/ui/layout'; import Tabs, { type Item } from '@/components/ui/tabs'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import LinkFooter from '@/features/ui/components/link-footer'; import { layouts } from '@/features/ui/router'; import { EventHeader, diff --git a/packages/nicolium/src/layouts/events-layout.tsx b/packages/nicolium/src/layouts/events-layout.tsx index 8d132ff89..32fa83cdc 100644 --- a/packages/nicolium/src/layouts/events-layout.tsx +++ b/packages/nicolium/src/layouts/events-layout.tsx @@ -1,8 +1,8 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; -import LinkFooter from '@/features/ui/components/link-footer'; import { WhoToFollowPanel, TrendsPanel, NewEventPanel } from '@/features/ui/util/async-components'; import { useFeatures } from '@/hooks/use-features'; diff --git a/packages/nicolium/src/layouts/external-login-layout.tsx b/packages/nicolium/src/layouts/external-login-layout.tsx index 88ebcfacb..5d798700b 100644 --- a/packages/nicolium/src/layouts/external-login-layout.tsx +++ b/packages/nicolium/src/layouts/external-login-layout.tsx @@ -1,9 +1,9 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import LinkFooter from '@/features/ui/components/link-footer'; import { WhoToFollowPanel, TrendsPanel, SignUpPanel } from '@/features/ui/util/async-components'; import { useFeatures } from '@/hooks/use-features'; import { useIsStandalone } from '@/utils/state'; diff --git a/packages/nicolium/src/layouts/group-layout.tsx b/packages/nicolium/src/layouts/group-layout.tsx index f8ded8827..d6b4453d9 100644 --- a/packages/nicolium/src/layouts/group-layout.tsx +++ b/packages/nicolium/src/layouts/group-layout.tsx @@ -2,13 +2,13 @@ import { Outlet, useLocation } from '@tanstack/react-router'; import React, { useMemo } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; +import GroupHeader from '@/components/groups/group-header'; +import LinkFooter from '@/components/navigation/link-footer'; import Column from '@/components/ui/column'; import Icon from '@/components/ui/icon'; import Layout from '@/components/ui/layout'; import Tabs, { type Item } from '@/components/ui/tabs'; import Text from '@/components/ui/text'; -import GroupHeader from '@/features/group/components/group-header'; -import LinkFooter from '@/features/ui/components/link-footer'; import { layouts } from '@/features/ui/router'; import { GroupMediaPanel, SignUpPanel } from '@/features/ui/util/async-components'; import { useOwnAccount } from '@/hooks/use-own-account'; diff --git a/packages/nicolium/src/layouts/groups-layout.tsx b/packages/nicolium/src/layouts/groups-layout.tsx index ac1b95139..677601593 100644 --- a/packages/nicolium/src/layouts/groups-layout.tsx +++ b/packages/nicolium/src/layouts/groups-layout.tsx @@ -1,9 +1,9 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Column from '@/components/ui/column'; import Layout from '@/components/ui/layout'; -import LinkFooter from '@/features/ui/components/link-footer'; import { MyGroupsPanel, NewGroupPanel } from '@/features/ui/util/async-components'; /** Layout to display groups. */ diff --git a/packages/nicolium/src/layouts/home-layout.tsx b/packages/nicolium/src/layouts/home-layout.tsx index 3671ec20c..99e126e1e 100644 --- a/packages/nicolium/src/layouts/home-layout.tsx +++ b/packages/nicolium/src/layouts/home-layout.tsx @@ -3,12 +3,12 @@ import clsx from 'clsx'; import React, { useRef } from 'react'; import { BANNER_HTML } from '@/build-config'; +import LinkFooter from '@/components/navigation/link-footer'; import Avatar from '@/components/ui/avatar'; import Layout from '@/components/ui/layout'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Warning from '@/features/compose/components/warning'; -import LinkFooter from '@/features/ui/components/link-footer'; import { WhoToFollowPanel, TrendsPanel, diff --git a/packages/nicolium/src/layouts/manage-groups-layout.tsx b/packages/nicolium/src/layouts/manage-groups-layout.tsx index 5434dbdcd..6d787c603 100644 --- a/packages/nicolium/src/layouts/manage-groups-layout.tsx +++ b/packages/nicolium/src/layouts/manage-groups-layout.tsx @@ -1,8 +1,8 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; -import LinkFooter from '@/features/ui/components/link-footer'; import { MyGroupsPanel, NewGroupPanel } from '@/features/ui/util/async-components'; /** Layout to display groups. */ diff --git a/packages/nicolium/src/layouts/profile-layout.tsx b/packages/nicolium/src/layouts/profile-layout.tsx index 414911146..a87b781ea 100644 --- a/packages/nicolium/src/layouts/profile-layout.tsx +++ b/packages/nicolium/src/layouts/profile-layout.tsx @@ -2,12 +2,12 @@ import { Navigate, Outlet, useLocation } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage } from 'react-intl'; +import LinkFooter from '@/components/navigation/link-footer'; import Column from '@/components/ui/column'; import Layout from '@/components/ui/layout'; import Tabs, { type Item } from '@/components/ui/tabs'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Header from '@/features/account/components/header'; -import LinkFooter from '@/features/ui/components/link-footer'; import { layouts } from '@/features/ui/router'; import { WhoToFollowPanel, diff --git a/packages/nicolium/src/layouts/remote-instance-layout.tsx b/packages/nicolium/src/layouts/remote-instance-layout.tsx index e62323593..74ae9d2a9 100644 --- a/packages/nicolium/src/layouts/remote-instance-layout.tsx +++ b/packages/nicolium/src/layouts/remote-instance-layout.tsx @@ -1,8 +1,8 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; -import LinkFooter from '@/features/ui/components/link-footer'; import { layouts } from '@/features/ui/router'; import { PromoPanel, diff --git a/packages/nicolium/src/layouts/search-layout.tsx b/packages/nicolium/src/layouts/search-layout.tsx index e8c6fe5dd..a6324d013 100644 --- a/packages/nicolium/src/layouts/search-layout.tsx +++ b/packages/nicolium/src/layouts/search-layout.tsx @@ -1,9 +1,9 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import LinkFooter from '@/features/ui/components/link-footer'; import { WhoToFollowPanel, TrendsPanel, SignUpPanel } from '@/features/ui/util/async-components'; import { useFeatures } from '@/hooks/use-features'; const SearchLayout = () => { diff --git a/packages/nicolium/src/layouts/status-layout.tsx b/packages/nicolium/src/layouts/status-layout.tsx index 0d4ce575c..f03acbdde 100644 --- a/packages/nicolium/src/layouts/status-layout.tsx +++ b/packages/nicolium/src/layouts/status-layout.tsx @@ -1,9 +1,9 @@ import { Outlet } from '@tanstack/react-router'; import React from 'react'; +import LinkFooter from '@/components/navigation/link-footer'; import Layout from '@/components/ui/layout'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import LinkFooter from '@/features/ui/components/link-footer'; import { WhoToFollowPanel, TrendsPanel, SignUpPanel } from '@/features/ui/util/async-components'; import { useFeatures } from '@/hooks/use-features'; const StatusLayout = () => { diff --git a/packages/nicolium/src/pages/groups/group-members.tsx b/packages/nicolium/src/pages/groups/group-members.tsx index d2b50b553..702a7cdaa 100644 --- a/packages/nicolium/src/pages/groups/group-members.tsx +++ b/packages/nicolium/src/pages/groups/group-members.tsx @@ -2,10 +2,10 @@ import clsx from 'clsx'; import { GroupRoles } from 'pl-api'; import React, { useMemo } from 'react'; +import GroupMemberListItem from '@/components/groups/group-member-list-item'; import { PendingItemsRow } from '@/components/pending-items-row'; import PlaceholderAccount from '@/components/placeholders/placeholder-account'; import ScrollableList from '@/components/scrollable-list'; -import GroupMemberListItem from '@/features/group/components/group-member-list-item'; import { groupMembersRoute } from '@/features/ui/router'; import { useGroupQuery } from '@/queries/groups/use-group'; import { diff --git a/packages/nicolium/src/pages/groups/groups.tsx b/packages/nicolium/src/pages/groups/groups.tsx index 0a670dcae..62b31d658 100644 --- a/packages/nicolium/src/pages/groups/groups.tsx +++ b/packages/nicolium/src/pages/groups/groups.tsx @@ -2,7 +2,7 @@ import { Link } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage } from 'react-intl'; -import GroupCard from '@/components/group-card'; +import GroupCard from '@/components/groups/group-card'; import PlaceholderGroupCard from '@/components/placeholders/placeholder-group-card'; import ScrollableList from '@/components/scrollable-list'; import Button from '@/components/ui/button'; diff --git a/packages/nicolium/src/pages/status-lists/events.tsx b/packages/nicolium/src/pages/status-lists/events.tsx index b822d3c0f..868b860c4 100644 --- a/packages/nicolium/src/pages/status-lists/events.tsx +++ b/packages/nicolium/src/pages/status-lists/events.tsx @@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import PlaceholderEventPreview from '@/components/placeholders/placeholder-event-preview'; import ReactSwipeableViews from '@/components/react-swipeable-views'; -import EventPreview from '@/components/statuses/event-preview'; +import EventPreview from '@/components/statuses/events/event-preview'; import Button from '@/components/ui/button'; import Card, { CardBody, CardHeader, CardTitle } from '@/components/ui/card'; import Column from '@/components/ui/column'; diff --git a/packages/nicolium/src/pages/utils/landing.tsx b/packages/nicolium/src/pages/utils/landing.tsx index 1c6ddf897..59a17b99c 100644 --- a/packages/nicolium/src/pages/utils/landing.tsx +++ b/packages/nicolium/src/pages/utils/landing.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; +import LinkFooter from '@/components/navigation/link-footer'; import Button from '@/components/ui/button'; import Card, { CardTitle } from '@/components/ui/card'; import Column from '@/components/ui/column'; import Text from '@/components/ui/text'; -import LinkFooter from '@/features/ui/components/link-footer'; import sourceCode from '@/utils/code'; import { LogoText } from '../timelines/landing-timeline'; diff --git a/packages/nicolium/src/pages/utils/server-info.tsx b/packages/nicolium/src/pages/utils/server-info.tsx index a15441ae1..5b75e09f2 100644 --- a/packages/nicolium/src/pages/utils/server-info.tsx +++ b/packages/nicolium/src/pages/utils/server-info.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; +import LinkFooter from '@/components/navigation/link-footer'; import PromoPanel from '@/components/panels/promo-panel'; import Column from '@/components/ui/column'; import Divider from '@/components/ui/divider'; import Text from '@/components/ui/text'; -import LinkFooter from '@/features/ui/components/link-footer'; import { useInstance } from '@/stores/instance'; const messages = defineMessages({ diff --git a/packages/nicolium/src/queries/keys.ts b/packages/nicolium/src/queries/keys.ts index b557369b7..061804c4d 100644 --- a/packages/nicolium/src/queries/keys.ts +++ b/packages/nicolium/src/queries/keys.ts @@ -13,7 +13,7 @@ import type { MinifiedAdminReport, MinifiedConversation, } from './utils/minify-list'; -import type { NormalizedStatus } from '@/normalizers/status'; +import type { NormalizedStatus } from '@/queries/statuses/normalize'; import type { DataTag, InfiniteData } from '@tanstack/react-query'; import type { Account, diff --git a/packages/nicolium/src/normalizers/status.ts b/packages/nicolium/src/queries/statuses/normalize.ts similarity index 100% rename from packages/nicolium/src/normalizers/status.ts rename to packages/nicolium/src/queries/statuses/normalize.ts diff --git a/packages/nicolium/src/queries/statuses/use-status-interactions.ts b/packages/nicolium/src/queries/statuses/use-status-interactions.ts index 66d77740c..896540ad0 100644 --- a/packages/nicolium/src/queries/statuses/use-status-interactions.ts +++ b/packages/nicolium/src/queries/statuses/use-status-interactions.ts @@ -23,7 +23,7 @@ import { simulateEmojiReact, simulateUnEmojiReact } from '@/utils/emoji-reacts'; import { queryKeys } from '../keys'; import { filterById } from '../utils/filter-id'; -import type { NormalizedStatus } from '@/normalizers/status'; +import type { NormalizedStatus } from '@/queries/statuses/normalize'; import type { EmojiReaction, PaginatedResponse } from 'pl-api'; const messages = defineMessages({ diff --git a/packages/nicolium/src/queries/statuses/use-status.ts b/packages/nicolium/src/queries/statuses/use-status.ts index bace5ebde..5fec9c107 100644 --- a/packages/nicolium/src/queries/statuses/use-status.ts +++ b/packages/nicolium/src/queries/statuses/use-status.ts @@ -10,8 +10,8 @@ import { useMemo } from 'react'; import { decrementReplyCount, incrementReplyCount } from '@/actions/statuses'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; -import { normalizeStatus, type NormalizedStatus } from '@/normalizers/status'; import { useFilters } from '@/queries/settings/use-filters'; +import { normalizeStatus, type NormalizedStatus } from '@/queries/statuses/normalize'; import { importEntities } from '@/queries/utils/import-entities'; import { useComposeActions } from '@/stores/compose'; import { useContextsActions } from '@/stores/contexts'; diff --git a/packages/nicolium/src/queries/utils/import-entities.ts b/packages/nicolium/src/queries/utils/import-entities.ts index 85d43fee4..e1bb5a9de 100644 --- a/packages/nicolium/src/queries/utils/import-entities.ts +++ b/packages/nicolium/src/queries/utils/import-entities.ts @@ -1,9 +1,9 @@ import { notifyManager } from '@tanstack/react-query'; -import { normalizeStatus } from '@/normalizers/status'; import { selectAccount } from '@/queries/accounts/selectors'; import { queryClient } from '@/queries/client'; import { queryKeys } from '@/queries/keys'; +import { normalizeStatus } from '@/queries/statuses/normalize'; import { useContextStore } from '@/stores/contexts'; import type { diff --git a/packages/nicolium/src/stores/compose.ts b/packages/nicolium/src/stores/compose.ts index d88bf02a9..d0466e90e 100644 --- a/packages/nicolium/src/stores/compose.ts +++ b/packages/nicolium/src/stores/compose.ts @@ -24,7 +24,7 @@ import { useUiStoreActions } from './ui'; import type { AutoSuggestion } from '@/components/autosuggest-input'; import type { Language } from '@/features/preferences'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { LinkOptions } from '@tanstack/react-router'; import type { Account, diff --git a/packages/nicolium/src/stores/timelines.ts b/packages/nicolium/src/stores/timelines.ts index ee82db147..e9a67f27f 100644 --- a/packages/nicolium/src/stores/timelines.ts +++ b/packages/nicolium/src/stores/timelines.ts @@ -3,7 +3,7 @@ import { mutative } from 'zustand-mutative'; import { findStatuses } from '@/queries/statuses/use-status'; -import type { NormalizedStatus } from '@/normalizers/status'; +import type { NormalizedStatus } from '@/queries/statuses/normalize'; import type { CreateStatusParams, Status } from 'pl-api'; type TimelineEntry = diff --git a/packages/nicolium/src/features/ui/util/global-hotkeys.tsx b/packages/nicolium/src/utils/global-hotkeys.tsx similarity index 98% rename from packages/nicolium/src/features/ui/util/global-hotkeys.tsx rename to packages/nicolium/src/utils/global-hotkeys.tsx index c9c53b999..5226886a5 100644 --- a/packages/nicolium/src/features/ui/util/global-hotkeys.tsx +++ b/packages/nicolium/src/utils/global-hotkeys.tsx @@ -6,7 +6,7 @@ import { useOwnAccount } from '@/hooks/use-own-account'; import { useComposeActions } from '@/stores/compose'; import { useModalsActions } from '@/stores/modals'; -import { Hotkeys } from '../components/hotkeys'; +import { Hotkeys } from '../features/ui/components/hotkeys'; import type { LexicalEditor } from 'lexical'; diff --git a/packages/nicolium/src/features/ui/util/pending-status-builder.ts b/packages/nicolium/src/utils/pending-status-builder.ts similarity index 95% rename from packages/nicolium/src/features/ui/util/pending-status-builder.ts rename to packages/nicolium/src/utils/pending-status-builder.ts index 0ae956de0..4658d1c47 100644 --- a/packages/nicolium/src/features/ui/util/pending-status-builder.ts +++ b/packages/nicolium/src/utils/pending-status-builder.ts @@ -1,9 +1,9 @@ import { statusSchema, type Account } from 'pl-api'; import * as v from 'valibot'; -import { normalizeStatus } from '@/normalizers/status'; import { queryClient } from '@/queries/client'; import { queryKeys } from '@/queries/keys'; +import { normalizeStatus } from '@/queries/statuses/normalize'; import type { PendingStatus } from '@/stores/pending-statuses'; diff --git a/packages/nicolium/src/utils/status.ts b/packages/nicolium/src/utils/status.ts index b3f6ac16f..79669f26c 100644 --- a/packages/nicolium/src/utils/status.ts +++ b/packages/nicolium/src/utils/status.ts @@ -1,6 +1,6 @@ import { selectAccount } from '@/queries/accounts/selectors'; -import type { NormalizedStatus as Status } from '@/normalizers/status'; +import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { IntlShape } from 'react-intl'; /** Grab the first external link from a status. */ From d7f1deede6fb24701e0e4d84c19793210814d7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:14:43 +0100 Subject: [PATCH 17/64] nicolium: move more stuff around, enough for today MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/columns/notifications.tsx | 2 +- packages/nicolium/src/columns/timeline.tsx | 2 +- .../accounts/account-header.tsx} | 10 +- .../accounts/account-hover-card.tsx | 4 +- .../accounts}/account-menu.tsx | 0 .../src/components/accounts/account.tsx | 2 +- .../accounts}/action-button.tsx | 0 .../accounts}/profile-familiar-followers.tsx | 0 .../accounts}/profile-field.tsx | 0 .../accounts}/profile-stats.tsx | 0 .../accounts}/subscription-button.tsx | 0 .../nicolium/src/components/media/video.tsx | 3 +- .../media}/zoomable-image.tsx | 0 .../navigation/dropdown-navigation.tsx | 2 +- .../components/notification.tsx | 0 .../components/panels/profile-info-panel.tsx | 4 +- .../src/components/panels/sign-up-panel.tsx | 6 +- .../polls}/poll-preview.tsx | 0 .../statuses}/pending-status.tsx | 6 +- .../components/statuses/status-action-bar.tsx | 2 +- .../statuses/status-language-picker.tsx | 2 +- .../src/components/statuses/status-list.tsx | 2 +- .../components/chats-page-settings.tsx | 2 +- .../compose/components/language-dropdown.tsx | 5 +- .../components/draft-status.tsx | 2 +- .../event/components/event-header.tsx | 582 ------------------ .../src/features/reply-mentions/account.tsx | 80 --- .../components/scheduled-status.tsx | 2 +- .../src/features/status/components/thread.tsx | 2 +- packages/nicolium/src/features/ui/index.tsx | 3 +- .../src/features/ui/util/async-components.ts | 4 +- .../nicolium/src/layouts/profile-layout.tsx | 4 +- .../manage-group-modal/steps/details-step.tsx | 4 +- packages/nicolium/src/modals/media-modal.tsx | 2 +- .../src/modals/reply-mentions-modal.tsx | 81 ++- .../src/pages/account-lists/directory.tsx | 2 +- .../auth}/components/captcha.tsx | 0 .../auth}/components/consumer-button.tsx | 0 .../auth}/components/consumers-list.tsx | 0 .../auth}/components/external-login-form.tsx | 0 .../auth}/components/login-form.tsx | 0 .../auth}/components/otp-auth-form.tsx | 0 .../auth}/components/registration-form.tsx | 3 +- .../src/pages/auth/external-login.tsx | 3 +- packages/nicolium/src/pages/auth/login.tsx | 7 +- .../src/pages/auth/register-with-invite.tsx | 3 +- .../nicolium/src/pages/auth/registration.tsx | 3 +- .../src/pages/dashboard/awaiting-approval.tsx | 2 +- .../dashboard}/components/counter.tsx | 0 .../dashboard}/components/dashcounter.tsx | 0 .../dashboard}/components/dimension.tsx | 0 .../components/latest-accounts-panel.tsx | 0 .../components/registration-mode-picker.tsx | 0 .../dashboard}/components/report.tsx | 0 .../dashboard}/components/retention.tsx | 0 .../components/theme-editor}/color.tsx | 0 .../components/theme-editor}/palette.tsx | 0 .../components/unapproved-account.tsx | 0 .../src/pages/dashboard/dashboard.tsx | 10 +- .../nicolium/src/pages/dashboard/reports.tsx | 2 +- .../src/pages/dashboard/theme-editor.tsx | 3 +- .../src/pages/developers/settings-store.tsx | 2 +- .../nicolium/src/pages/groups/edit-group.tsx | 4 +- .../settings}/components/avatar-picker.tsx | 0 .../settings/components}/disable-otp-form.tsx | 0 .../settings/components}/enable-otp-form.tsx | 0 .../settings}/components/header-picker.tsx | 0 .../settings/components/messages-settings.tsx | 0 .../settings/components}/otp-confirm-form.tsx | 0 .../settings/components/preferences.tsx} | 4 +- .../settings/components/setting-toggle.tsx | 0 .../src/pages/settings/edit-profile.tsx | 4 +- .../nicolium/src/pages/settings/mfa-form.tsx | 6 +- .../nicolium/src/pages/settings/settings.tsx | 4 +- .../status-lists}/components/conversation.tsx | 0 .../components/conversations-list.tsx | 0 .../src/pages/status-lists/conversations.tsx | 2 +- .../status-lists/interaction-requests.tsx | 2 +- .../src/pages/statuses/event-discussion.tsx | 2 +- packages/nicolium/src/pages/utils/about.tsx | 2 +- .../notifications/use-notifications.ts | 5 +- packages/nicolium/src/stores/compose.ts | 2 +- .../{features/ui/util => utils}/fullscreen.ts | 0 83 files changed, 155 insertions(+), 742 deletions(-) rename packages/nicolium/src/{features/account/components/header.tsx => components/accounts/account-header.tsx} (97%) rename packages/nicolium/src/{features/account/components => components/accounts}/account-menu.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/accounts}/action-button.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/accounts}/profile-familiar-followers.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/accounts}/profile-field.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/accounts}/profile-stats.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/accounts}/subscription-button.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/media}/zoomable-image.tsx (100%) rename packages/nicolium/src/{features/notifications => }/components/notification.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/polls}/poll-preview.tsx (100%) rename packages/nicolium/src/{features/ui/components => components/statuses}/pending-status.tsx (96%) delete mode 100644 packages/nicolium/src/features/event/components/event-header.tsx delete mode 100644 packages/nicolium/src/features/reply-mentions/account.tsx rename packages/nicolium/src/{features/auth-login => pages/auth}/components/captcha.tsx (100%) rename packages/nicolium/src/{features/auth-login => pages/auth}/components/consumer-button.tsx (100%) rename packages/nicolium/src/{features/auth-login => pages/auth}/components/consumers-list.tsx (100%) rename packages/nicolium/src/{features/external-login => pages/auth}/components/external-login-form.tsx (100%) rename packages/nicolium/src/{features/auth-login => pages/auth}/components/login-form.tsx (100%) rename packages/nicolium/src/{features/auth-login => pages/auth}/components/otp-auth-form.tsx (100%) rename packages/nicolium/src/{features/auth-login => pages/auth}/components/registration-form.tsx (99%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/counter.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/dashcounter.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/dimension.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/latest-accounts-panel.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/registration-mode-picker.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/report.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/retention.tsx (100%) rename packages/nicolium/src/{features/theme-editor/components => pages/dashboard/components/theme-editor}/color.tsx (100%) rename packages/nicolium/src/{features/theme-editor/components => pages/dashboard/components/theme-editor}/palette.tsx (100%) rename packages/nicolium/src/{features/admin => pages/dashboard}/components/unapproved-account.tsx (100%) rename packages/nicolium/src/{features/edit-profile => pages/settings}/components/avatar-picker.tsx (100%) rename packages/nicolium/src/{features/security/mfa => pages/settings/components}/disable-otp-form.tsx (100%) rename packages/nicolium/src/{features/security/mfa => pages/settings/components}/enable-otp-form.tsx (100%) rename packages/nicolium/src/{features/edit-profile => pages/settings}/components/header-picker.tsx (100%) rename packages/nicolium/src/{features => pages}/settings/components/messages-settings.tsx (100%) rename packages/nicolium/src/{features/security/mfa => pages/settings/components}/otp-confirm-form.tsx (100%) rename packages/nicolium/src/{features/preferences/index.tsx => pages/settings/components/preferences.tsx} (99%) rename packages/nicolium/src/{features => pages}/settings/components/setting-toggle.tsx (100%) rename packages/nicolium/src/{features/conversations => pages/status-lists}/components/conversation.tsx (100%) rename packages/nicolium/src/{features/conversations => pages/status-lists}/components/conversations-list.tsx (100%) rename packages/nicolium/src/{features/ui/util => utils}/fullscreen.ts (100%) diff --git a/packages/nicolium/src/columns/notifications.tsx b/packages/nicolium/src/columns/notifications.tsx index 900a10f9f..87a4a7689 100644 --- a/packages/nicolium/src/columns/notifications.tsx +++ b/packages/nicolium/src/columns/notifications.tsx @@ -7,6 +7,7 @@ import '@/styles/new/notifications.scss'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { saveSettings } from '@/actions/settings'; +import Notification from '@/components/notification'; import PlaceholderNotification from '@/components/placeholders/placeholder-notification'; import PullToRefresh from '@/components/pull-to-refresh'; import ScrollTopButton from '@/components/scroll-top-button'; @@ -14,7 +15,6 @@ import ScrollableList from '@/components/scrollable-list'; import Icon from '@/components/ui/icon'; import Portal from '@/components/ui/portal'; import Tabs from '@/components/ui/tabs'; -import Notification from '@/features/notifications/components/notification'; import { useFeatures } from '@/hooks/use-features'; import { queryClient } from '@/queries/client'; import { queryKeys } from '@/queries/keys'; diff --git a/packages/nicolium/src/columns/timeline.tsx b/packages/nicolium/src/columns/timeline.tsx index 03051d652..234b6c426 100644 --- a/packages/nicolium/src/columns/timeline.tsx +++ b/packages/nicolium/src/columns/timeline.tsx @@ -8,6 +8,7 @@ import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import PullToRefresh from '@/components/pull-to-refresh'; import ScrollTopButton from '@/components/scroll-top-button'; import ScrollableList, { type IScrollableList } from '@/components/scrollable-list'; +import PendingStatus from '@/components/statuses/pending-status'; import Status, { StatusFollowedTagInfo } from '@/components/statuses/status'; import StatusInfo from '@/components/statuses/status-info'; import Tombstone from '@/components/statuses/tombstone'; @@ -15,7 +16,6 @@ import Icon from '@/components/ui/icon'; import Portal from '@/components/ui/portal'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; -import PendingStatus from '@/features/ui/components/pending-status'; import { useFeatures } from '@/hooks/use-features'; import { useAccounts } from '@/queries/accounts/use-accounts'; import { type SelectedStatus, useStatus } from '@/queries/statuses/use-status'; diff --git a/packages/nicolium/src/features/account/components/header.tsx b/packages/nicolium/src/components/accounts/account-header.tsx similarity index 97% rename from packages/nicolium/src/features/account/components/header.tsx rename to packages/nicolium/src/components/accounts/account-header.tsx index ab854acba..52e021397 100644 --- a/packages/nicolium/src/features/account/components/header.tsx +++ b/packages/nicolium/src/components/accounts/account-header.tsx @@ -7,6 +7,8 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import * as v from 'valibot'; import Account from '@/components/accounts/account'; +import ActionButton from '@/components/accounts/action-button'; +import SubscriptionButton from '@/components/accounts/subscription-button'; import VerificationBadge from '@/components/accounts/verification-badge'; import Badge from '@/components/badge'; import AltIndicator from '@/components/media/alt-indicator'; @@ -17,8 +19,6 @@ import IconButton from '@/components/ui/icon-button'; import Popover from '@/components/ui/popover'; import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; -import ActionButton from '@/features/ui/components/action-button'; -import SubscriptionButton from '@/features/ui/components/subscription-button'; import { useFeatures } from '@/hooks/use-features'; import { useOwnAccount } from '@/hooks/use-own-account'; import { useChats } from '@/queries/chats'; @@ -67,11 +67,11 @@ const MovedNote: React.FC = ({ from, to }) => (
); -interface IHeader { +interface IAccountHeader { account?: AccountEntity; } -const Header: React.FC = ({ account }) => { +const AccountHeader: React.FC = ({ account }) => { const intl = useIntl(); const navigate = useNavigate(); @@ -370,4 +370,4 @@ const Header: React.FC = ({ account }) => { ); }; -export { Header as default }; +export { AccountHeader as default }; diff --git a/packages/nicolium/src/components/accounts/account-hover-card.tsx b/packages/nicolium/src/components/accounts/account-hover-card.tsx index b655287f4..0c6c03adf 100644 --- a/packages/nicolium/src/components/accounts/account-hover-card.tsx +++ b/packages/nicolium/src/components/accounts/account-hover-card.tsx @@ -4,13 +4,13 @@ import clsx from 'clsx'; import React, { useEffect } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; +import ActionButton from '@/components/accounts/action-button'; +import { isTimezoneLabel } from '@/components/accounts/profile-field'; import Badge from '@/components/badge'; import Card, { CardBody } from '@/components/ui/card'; import Icon from '@/components/ui/icon'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import ActionButton from '@/features/ui/components/action-button'; -import { isTimezoneLabel } from '@/features/ui/components/profile-field'; import { UserPanel } from '@/features/ui/util/async-components'; import { useAccountScrobbleQuery } from '@/queries/accounts/account-scrobble'; import { useAccount } from '@/queries/accounts/use-account'; diff --git a/packages/nicolium/src/features/account/components/account-menu.tsx b/packages/nicolium/src/components/accounts/account-menu.tsx similarity index 100% rename from packages/nicolium/src/features/account/components/account-menu.tsx rename to packages/nicolium/src/components/accounts/account-menu.tsx diff --git a/packages/nicolium/src/components/accounts/account.tsx b/packages/nicolium/src/components/accounts/account.tsx index 2a7f1a28b..ca4ea12ff 100644 --- a/packages/nicolium/src/components/accounts/account.tsx +++ b/packages/nicolium/src/components/accounts/account.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx'; import React, { useLayoutEffect, useRef, useState } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; +import ActionButton from '@/components/accounts/action-button'; import HoverAccountWrapper from '@/components/accounts/hover-account-wrapper'; import VerificationBadge from '@/components/accounts/verification-badge'; import Avatar from '@/components/ui/avatar'; @@ -12,7 +13,6 @@ import IconButton from '@/components/ui/icon-button'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; -import ActionButton from '@/features/ui/components/action-button'; import { useAcct } from '@/hooks/use-acct'; import { useSettings } from '@/stores/settings'; diff --git a/packages/nicolium/src/features/ui/components/action-button.tsx b/packages/nicolium/src/components/accounts/action-button.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/action-button.tsx rename to packages/nicolium/src/components/accounts/action-button.tsx diff --git a/packages/nicolium/src/features/ui/components/profile-familiar-followers.tsx b/packages/nicolium/src/components/accounts/profile-familiar-followers.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/profile-familiar-followers.tsx rename to packages/nicolium/src/components/accounts/profile-familiar-followers.tsx diff --git a/packages/nicolium/src/features/ui/components/profile-field.tsx b/packages/nicolium/src/components/accounts/profile-field.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/profile-field.tsx rename to packages/nicolium/src/components/accounts/profile-field.tsx diff --git a/packages/nicolium/src/features/ui/components/profile-stats.tsx b/packages/nicolium/src/components/accounts/profile-stats.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/profile-stats.tsx rename to packages/nicolium/src/components/accounts/profile-stats.tsx diff --git a/packages/nicolium/src/features/ui/components/subscription-button.tsx b/packages/nicolium/src/components/accounts/subscription-button.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/subscription-button.tsx rename to packages/nicolium/src/components/accounts/subscription-button.tsx diff --git a/packages/nicolium/src/components/media/video.tsx b/packages/nicolium/src/components/media/video.tsx index fc0151bad..b5d5252e0 100644 --- a/packages/nicolium/src/components/media/video.tsx +++ b/packages/nicolium/src/components/media/video.tsx @@ -7,6 +7,7 @@ import { defineMessages, useIntl } from 'react-intl'; import Icon from '@/components/icon'; import Blurhash from '@/components/media/blurhash'; import { useSettings } from '@/stores/settings'; +import { isFullscreen, requestFullscreen, exitFullscreen } from '@/utils/fullscreen'; import { isPanoramic, isPortrait, @@ -14,8 +15,6 @@ import { maximumAspectRatio, } from '@/utils/media-aspect-ratio'; -import { isFullscreen, requestFullscreen, exitFullscreen } from '../../features/ui/util/fullscreen'; - const DEFAULT_HEIGHT = 300; type Position = { x: number; y: number }; diff --git a/packages/nicolium/src/features/ui/components/zoomable-image.tsx b/packages/nicolium/src/components/media/zoomable-image.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/zoomable-image.tsx rename to packages/nicolium/src/components/media/zoomable-image.tsx diff --git a/packages/nicolium/src/components/navigation/dropdown-navigation.tsx b/packages/nicolium/src/components/navigation/dropdown-navigation.tsx index 296187655..f28431e49 100644 --- a/packages/nicolium/src/components/navigation/dropdown-navigation.tsx +++ b/packages/nicolium/src/components/navigation/dropdown-navigation.tsx @@ -6,11 +6,11 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { FormattedMessage } from 'react-intl'; import Account from '@/components/accounts/account'; +import ProfileStats from '@/components/accounts/profile-stats'; import Divider from '@/components/ui/divider'; import Icon from '@/components/ui/icon'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import ProfileStats from '@/features/ui/components/profile-stats'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; import { useRegistrationStatus } from '@/hooks/use-registration-status'; diff --git a/packages/nicolium/src/features/notifications/components/notification.tsx b/packages/nicolium/src/components/notification.tsx similarity index 100% rename from packages/nicolium/src/features/notifications/components/notification.tsx rename to packages/nicolium/src/components/notification.tsx diff --git a/packages/nicolium/src/components/panels/profile-info-panel.tsx b/packages/nicolium/src/components/panels/profile-info-panel.tsx index b340c01db..dfcfad17d 100644 --- a/packages/nicolium/src/components/panels/profile-info-panel.tsx +++ b/packages/nicolium/src/components/panels/profile-info-panel.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; +import ProfileFamiliarFollowers from '@/components/accounts/profile-familiar-followers'; +import ProfileStats from '@/components/accounts/profile-stats'; import Scrobble from '@/components/accounts/scrobble'; import Badge from '@/components/badge'; import Markup from '@/components/markup'; @@ -10,8 +12,6 @@ import Icon from '@/components/ui/icon'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; -import ProfileFamiliarFollowers from '@/features/ui/components/profile-familiar-followers'; -import ProfileStats from '@/features/ui/components/profile-stats'; import { ProfileField } from '@/features/ui/util/async-components'; import { useAcct } from '@/hooks/use-acct'; import { useAccountScrobbleQuery } from '@/queries/accounts/account-scrobble'; diff --git a/packages/nicolium/src/components/panels/sign-up-panel.tsx b/packages/nicolium/src/components/panels/sign-up-panel.tsx index 3f9e8af6c..4de4b494f 100644 --- a/packages/nicolium/src/components/panels/sign-up-panel.tsx +++ b/packages/nicolium/src/components/panels/sign-up-panel.tsx @@ -6,10 +6,10 @@ import { fetchInstance } from '@/actions/instance'; import Button from '@/components/ui/button'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import LoginForm from '@/features/auth-login/components/login-form'; -import OtpAuthForm from '@/features/auth-login/components/otp-auth-form'; -import ExternalLoginForm from '@/features/external-login/components/external-login-form'; import { useRegistrationStatus } from '@/hooks/use-registration-status'; +import ExternalLoginForm from '@/pages/auth/components/external-login-form'; +import LoginForm from '@/pages/auth/components/login-form'; +import OtpAuthForm from '@/pages/auth/components/otp-auth-form'; import { useAuthActions } from '@/stores/auth'; import { useInstance } from '@/stores/instance'; import { getRedirectUrl } from '@/utils/redirect'; diff --git a/packages/nicolium/src/features/ui/components/poll-preview.tsx b/packages/nicolium/src/components/polls/poll-preview.tsx similarity index 100% rename from packages/nicolium/src/features/ui/components/poll-preview.tsx rename to packages/nicolium/src/components/polls/poll-preview.tsx diff --git a/packages/nicolium/src/features/ui/components/pending-status.tsx b/packages/nicolium/src/components/statuses/pending-status.tsx similarity index 96% rename from packages/nicolium/src/features/ui/components/pending-status.tsx rename to packages/nicolium/src/components/statuses/pending-status.tsx index 671f7b737..c356b0c02 100644 --- a/packages/nicolium/src/features/ui/components/pending-status.tsx +++ b/packages/nicolium/src/components/statuses/pending-status.tsx @@ -5,6 +5,7 @@ import React from 'react'; import Account from '@/components/accounts/account'; import PlaceholderCard from '@/components/placeholders/placeholder-card'; import PlaceholderMediaGallery from '@/components/placeholders/placeholder-media-gallery'; +import PollPreview from '@/components/polls/poll-preview'; import StatusContent from '@/components/statuses/status-content'; import StatusReplyMentions from '@/components/statuses/status-reply-mentions'; import Card from '@/components/ui/card'; @@ -12,10 +13,7 @@ import QuotedStatus from '@/features/status/containers/quoted-status-container'; import { useOwnAccount } from '@/hooks/use-own-account'; import { queryKeys } from '@/queries/keys'; import { usePendingStatus } from '@/stores/pending-statuses'; - -import { buildStatus } from '../../../utils/pending-status-builder'; - -import PollPreview from './poll-preview'; +import { buildStatus } from '@/utils/pending-status-builder'; import type { NormalizedStatus as StatusEntity } from '@/queries/statuses/normalize'; import type { Poll } from 'pl-api'; diff --git a/packages/nicolium/src/components/statuses/status-action-bar.tsx b/packages/nicolium/src/components/statuses/status-action-bar.tsx index 7bdec7366..8dc3d9a4e 100644 --- a/packages/nicolium/src/components/statuses/status-action-bar.tsx +++ b/packages/nicolium/src/components/statuses/status-action-bar.tsx @@ -9,13 +9,13 @@ import DropdownMenu from '@/components/dropdown-menu'; import StatusActionButton from '@/components/statuses/status-action-button'; import { useCurrentAccount } from '@/contexts/current-account-context'; import EmojiPickerDropdown from '@/features/emoji/containers/emoji-picker-dropdown-container'; -import { languages } from '@/features/preferences'; import { layouts } from '@/features/ui/router'; import { useDeleteStatusModal, useToggleStatusSensitivityModal } from '@/hooks/use-admin-modals'; import { useCanInteract } from '@/hooks/use-can-interact'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; import { useOwnAccount } from '@/hooks/use-own-account'; +import { languages } from '@/pages/settings/components/preferences'; import { useUnblockAccountMutation } from '@/queries/accounts/use-relationship'; import { useChats } from '@/queries/chats'; import { useGroupQuery } from '@/queries/groups/use-group'; diff --git a/packages/nicolium/src/components/statuses/status-language-picker.tsx b/packages/nicolium/src/components/statuses/status-language-picker.tsx index b7c8aba6c..93453e3db 100644 --- a/packages/nicolium/src/components/statuses/status-language-picker.tsx +++ b/packages/nicolium/src/components/statuses/status-language-picker.tsx @@ -3,7 +3,7 @@ import { defineMessages, useIntl } from 'react-intl'; import Icon from '@/components/ui/icon'; import Text from '@/components/ui/text'; -import { type Language, languages } from '@/features/preferences'; +import { type Language, languages } from '@/pages/settings/components/preferences'; import { useStatusMeta, useStatusMetaActions } from '@/stores/status-meta'; import DropdownMenu from '../dropdown-menu'; diff --git a/packages/nicolium/src/components/statuses/status-list.tsx b/packages/nicolium/src/components/statuses/status-list.tsx index e954ce4bc..d70bce566 100644 --- a/packages/nicolium/src/components/statuses/status-list.tsx +++ b/packages/nicolium/src/components/statuses/status-list.tsx @@ -6,8 +6,8 @@ import { FormattedMessage } from 'react-intl'; import LoadGap from '@/components/load-gap'; import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList, { type IScrollableList } from '@/components/scrollable-list'; +import PendingStatus from '@/components/statuses/pending-status'; import StatusContainer from '@/components/statuses/status-container'; -import PendingStatus from '@/features/ui/components/pending-status'; import { timelineToFilterContextType } from '@/queries/settings/use-filters'; import { selectChild } from '@/utils/scroll-utils'; diff --git a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx index 94a0833b5..f46610a95 100644 --- a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx +++ b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx @@ -9,8 +9,8 @@ import { CardBody, CardTitle } from '@/components/ui/card'; import Form from '@/components/ui/form'; import IconButton from '@/components/ui/icon-button'; import Toggle from '@/components/ui/toggle'; -import SettingToggle from '@/features/settings/components/setting-toggle'; import { useOwnAccount } from '@/hooks/use-own-account'; +import SettingToggle from '@/pages/settings/components/setting-toggle'; import { useUpdateCredentials } from '@/queries/accounts/use-account-credentials'; import { useSettings } from '@/stores/settings'; import toast from '@/toast'; diff --git a/packages/nicolium/src/features/compose/components/language-dropdown.tsx b/packages/nicolium/src/features/compose/components/language-dropdown.tsx index 843b74fbe..9ac56573d 100644 --- a/packages/nicolium/src/features/compose/components/language-dropdown.tsx +++ b/packages/nicolium/src/features/compose/components/language-dropdown.tsx @@ -6,8 +6,11 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import DropdownMenu from '@/components/dropdown-menu'; import Icon from '@/components/ui/icon'; import Input from '@/components/ui/input'; -import { type Language, languages as languagesObject } from '@/features/preferences'; import { useFeatures } from '@/hooks/use-features'; +import { + type Language, + languages as languagesObject, +} from '@/pages/settings/components/preferences'; import { useCompose, useComposeActions } from '@/stores/compose'; import { useSettings } from '@/stores/settings'; diff --git a/packages/nicolium/src/features/draft-statuses/components/draft-status.tsx b/packages/nicolium/src/features/draft-statuses/components/draft-status.tsx index 635c6f726..7430c70a9 100644 --- a/packages/nicolium/src/features/draft-statuses/components/draft-status.tsx +++ b/packages/nicolium/src/features/draft-statuses/components/draft-status.tsx @@ -5,10 +5,10 @@ import { FormattedMessage } from 'react-intl'; import Account from '@/components/accounts/account'; import AttachmentThumbs from '@/components/media/attachment-thumbs'; import OutlineBox from '@/components/outline-box'; +import PollPreview from '@/components/polls/poll-preview'; import StatusContent from '@/components/statuses/status-content'; import StatusReplyMentions from '@/components/statuses/status-reply-mentions'; import QuotedStatus from '@/features/status/containers/quoted-status-container'; -import PollPreview from '@/features/ui/components/poll-preview'; import { useOwnAccount } from '@/hooks/use-own-account'; import { buildPoll, buildStatus } from '../builder'; diff --git a/packages/nicolium/src/features/event/components/event-header.tsx b/packages/nicolium/src/features/event/components/event-header.tsx deleted file mode 100644 index 8c7fab13b..000000000 --- a/packages/nicolium/src/features/event/components/event-header.tsx +++ /dev/null @@ -1,582 +0,0 @@ -import { Link, useNavigate } from '@tanstack/react-router'; -import React from 'react'; -import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; - -import VerificationBadge from '@/components/accounts/verification-badge'; -import DropdownMenu, { type Menu as MenuType } from '@/components/dropdown-menu'; -import Icon from '@/components/icon'; -import PlaceholderEventHeader from '@/components/placeholders/placeholder-event-header'; -import StillImage from '@/components/still-image'; -import Button from '@/components/ui/button'; -import IconButton from '@/components/ui/icon-button'; -import Text from '@/components/ui/text'; -import Emojify from '@/features/emoji/emojify'; -import { useDeleteStatusModal, useToggleStatusSensitivityModal } from '@/hooks/use-admin-modals'; -import { useClient } from '@/hooks/use-client'; -import { useFeatures } from '@/hooks/use-features'; -import { useOwnAccount } from '@/hooks/use-own-account'; -import { useAccount } from '@/queries/accounts/use-account'; -import { useChats } from '@/queries/chats'; -import { useDeleteStatus } from '@/queries/statuses/use-status'; -import { - useBookmarkStatus, - usePinStatus, - useReblogStatus, - useUnbookmarkStatus, - useUnpinStatus, - useUnreblogStatus, -} from '@/queries/statuses/use-status-interactions'; -import { useComposeActions } from '@/stores/compose'; -import { useModalsActions } from '@/stores/modals'; -import { useSettings } from '@/stores/settings'; -import toast from '@/toast'; -import copy from '@/utils/copy'; -import { download } from '@/utils/download'; -import { shortNumberFormat } from '@/utils/numbers'; - -import EventActionButton from '../../../components/statuses/events/event-action-button'; -import EventDate from '../../../components/statuses/events/event-date'; - -import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; - -const messages = defineMessages({ - bannerHeader: { id: 'event.banner', defaultMessage: 'Event banner' }, - exportIcs: { id: 'event.export_ics', defaultMessage: 'Export to your calendar' }, - copy: { id: 'event.copy', defaultMessage: 'Copy link to event' }, - copySuccess: { id: 'event.copy.success', defaultMessage: 'Link to event copied to clipboard' }, - copyStatus: { id: 'status.copy_content', defaultMessage: 'Copy post content' }, - copyStatusSuccess: { - id: 'status.copy_content.success', - defaultMessage: 'Post content copied to clipboard', - }, - external: { id: 'event.external', defaultMessage: 'View event on {domain}' }, - bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' }, - unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' }, - quotePost: { id: 'event.quote', defaultMessage: 'Quote event' }, - reblog: { id: 'event.reblog', defaultMessage: 'Repost event' }, - reblogPrivate: { id: 'status.reblog_private', defaultMessage: 'Repost to original audience' }, - cancelReblogPrivate: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' }, - reblogVisibilityPublic: { - id: 'status.reblog_visibility_public', - defaultMessage: 'Public repost', - }, - reblogVisibilityUnlisted: { - id: 'status.reblog_visibility_unlisted', - defaultMessage: 'Quiet public repost', - }, - reblogVisibilityPrivate: { - id: 'status.reblog_visibility_private', - defaultMessage: 'Followers-only repost', - }, - unreblog: { id: 'event.unreblog', defaultMessage: 'Un-repost event' }, - pin: { id: 'status.pin', defaultMessage: 'Pin on profile' }, - unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, - delete: { id: 'status.delete', defaultMessage: 'Delete' }, - mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, - chat: { id: 'status.chat', defaultMessage: 'Chat with @{name}' }, - direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, - mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, - block: { id: 'account.block', defaultMessage: 'Block @{name}' }, - report: { id: 'account.report', defaultMessage: 'Report @{name}' }, - adminAccount: { id: 'status.admin_account', defaultMessage: 'Moderate @{name}' }, - adminStatus: { - id: 'status.admin_status', - defaultMessage: 'Open this post in the moderation interface', - }, - markStatusSensitive: { - id: 'admin.statuses.actions.mark_status_sensitive', - defaultMessage: 'Mark post sensitive', - }, - markStatusNotSensitive: { - id: 'admin.statuses.actions.mark_status_not_sensitive', - defaultMessage: 'Mark post not sensitive', - }, - deleteStatus: { id: 'admin.statuses.actions.delete_status', defaultMessage: 'Delete post' }, -}); - -interface IEventHeader { - status?: Pick< - Status, - | 'id' - | 'account_id' - | 'bookmarked' - | 'event' - | 'group_id' - | 'pinned' - | 'reblog_id' - | 'reblogged' - | 'sensitive' - | 'spoiler_text' - | 'uri' - | 'url' - | 'visibility' - | 'list_id' - >; -} - -const EventHeader: React.FC = ({ status }) => { - const intl = useIntl(); - const navigate = useNavigate(); - const { quoteCompose, mentionCompose, directCompose } = useComposeActions(); - - const { openModal } = useModalsActions(); - const { getOrCreateChatByAccountId } = useChats(); - - const client = useClient(); - const features = useFeatures(); - const { boostModal } = useSettings(); - const { data: ownAccount } = useOwnAccount(); - const { data: account } = useAccount(status?.account_id!); - const isStaff = ownAccount ? (ownAccount.is_admin ?? ownAccount.is_moderator) : false; - const isAdmin = ownAccount ? ownAccount.is_admin : false; - - const { mutate: reblogStatus } = useReblogStatus(status?.id!); - const { mutate: unreblogStatus } = useUnreblogStatus(status?.id!); - const { mutate: bookmarkStatus } = useBookmarkStatus(status?.id!); - const { mutate: unbookmarkStatus } = useUnbookmarkStatus(status?.id!); - const { mutate: pinStatus } = usePinStatus(status?.id!); - const { mutate: unpinStatus } = useUnpinStatus(status?.id!); - const { mutate: deleteStatus } = useDeleteStatus(status?.id!); - const deleteStatusModal = useDeleteStatusModal(status?.id!); - const toggleStatusSensitivityModal = useToggleStatusSensitivityModal(status?.id!); - - if (!status || !status.event || !account) { - return ( - <> -
-
-
- - - - ); - } - const event = status.event; - const banner = event.banner; - - if (!account) return null; - - const username = account.username; - - const handleHeaderClick: React.MouseEventHandler = (e) => { - e.preventDefault(); - e.stopPropagation(); - - openModal('MEDIA', { media: [event.banner!], index: 0 }); - }; - - const handleExportClick = () => { - client.events - .getEventIcs(status.id) - .then((data) => { - download(data, 'calendar.ics'); - }) - .catch(() => {}); - }; - - const handleCopyStatus = () => { - let content = document - .querySelector(`article[data-status-id="${status.id}"] [data-markup="true"]`) - ?.textContent?.trim(); - if (content) { - if (status.spoiler_text.length) content = `${status.spoiler_text}\n\n${content}`; - copy(content, () => toast.success(messages.copyStatusSuccess)); - } - }; - - const handleCopy = () => { - const { uri } = status; - - copy(uri, () => toast.success(messages.copySuccess)); - }; - - const handleBookmarkClick = () => { - if (status.bookmarked) unbookmarkStatus(); - else bookmarkStatus(undefined); - }; - - const handleReblogClick = (visibility?: string) => { - const modalReblog = () => { - if (status.reblogged) unreblogStatus(); - else reblogStatus(visibility); - }; - if (!boostModal) { - modalReblog(); - } else { - openModal('BOOST', { statusId: status.id, onReblog: modalReblog }); - } - }; - - const handleQuoteClick = () => { - quoteCompose(status); - }; - - const handlePinClick = () => { - if (status.pinned) unpinStatus(); - else pinStatus(); - }; - - const handleDeleteClick = () => { - openModal('CONFIRM', { - heading: ( - - ), - message: ( - - ), - confirm: , - onConfirm: () => deleteStatus(undefined), - }); - }; - - const handleMentionClick = () => { - mentionCompose(account); - }; - - const handleChatClick = () => { - getOrCreateChatByAccountId(account.id) - .then((chat) => navigate({ to: '/chats/$chatId', params: { chatId: chat.id } })) - .catch(() => {}); - }; - - const handleDirectClick = () => { - directCompose(account); - }; - - const handleMuteClick = () => { - openModal('BLOCK_MUTE', { accountId: account.id, action: 'MUTE' }); - }; - - const handleBlockClick = () => { - openModal('BLOCK_MUTE', { accountId: account.id, action: 'BLOCK' }); - }; - - const handleReport = () => { - openModal('REPORT', { accountId: account.id, statusIds: [status.id] }); - }; - - const handleToggleStatusSensitivity = () => { - toggleStatusSensitivityModal(status.sensitive); - }; - - const handleDeleteStatus = () => { - deleteStatusModal(); - }; - - const makeMenu = (): MenuType => { - const domain = account.fqn.split('@')[1]; - - const menu: MenuType = [ - { - text: intl.formatMessage(messages.exportIcs), - action: handleExportClick, - icon: require('@phosphor-icons/core/regular/calendar-plus.svg'), - }, - ]; - - menu.push({ - text: intl.formatMessage(messages.copyStatus), - action: handleCopyStatus, - icon: require('@phosphor-icons/core/regular/copy.svg'), - }); - - menu.push({ - text: intl.formatMessage(messages.copy), - action: handleCopy, - icon: require('@phosphor-icons/core/regular/link-simple-horizontal.svg'), - }); - - if (features.federating && !account.local) { - menu.push({ - text: intl.formatMessage(messages.external, { domain }), - icon: require('@phosphor-icons/core/regular/arrow-square-out.svg'), - href: status.uri, - target: '_blank', - }); - } - - if (!ownAccount) return menu; - - if (features.bookmarks) { - menu.push({ - text: intl.formatMessage(status.bookmarked ? messages.unbookmark : messages.bookmark), - action: handleBookmarkClick, - icon: status.bookmarked - ? require('@phosphor-icons/core/regular/bookmark.svg') - : require('@phosphor-icons/core/regular/bookmark-simple.svg'), - }); - } - - if (ownAccount.id === account.id && ['public', 'unlisted'].includes(status.visibility)) { - menu.push({ - text: intl.formatMessage(status.reblogged ? messages.unreblog : messages.reblog), - ...(features.reblogVisibility && !status.reblogged - ? { - items: [ - { - text: intl.formatMessage(messages.reblogVisibilityPublic), - action: () => { - handleReblogClick('public'); - }, - icon: require('@phosphor-icons/core/regular/globe.svg'), - }, - { - text: intl.formatMessage(messages.reblogVisibilityUnlisted), - action: () => { - handleReblogClick('unlisted'); - }, - icon: require('@phosphor-icons/core/regular/moon.svg'), - }, - { - text: intl.formatMessage(messages.reblogVisibilityPrivate), - action: () => { - handleReblogClick('private'); - }, - icon: require('@phosphor-icons/core/regular/lock.svg'), - }, - ], - } - : { - action: () => { - handleReblogClick(); - }, - }), - icon: require('@phosphor-icons/core/regular/repeat.svg'), - }); - - if (features.quotePosts) { - menu.push({ - text: intl.formatMessage(messages.quotePost), - action: handleQuoteClick, - icon: require('@phosphor-icons/core/regular/quotes.svg'), - }); - } - } else if (status.visibility === 'private' || status.visibility === 'mutuals_only') { - menu.push({ - text: intl.formatMessage( - status.reblogged ? messages.cancelReblogPrivate : messages.reblogPrivate, - ), - action: () => { - handleReblogClick(); - }, - icon: require('@phosphor-icons/core/regular/repeat.svg'), - }); - } - - menu.push(null); - - if (ownAccount.id === account.id) { - if (['public', 'unlisted'].includes(status.visibility)) { - menu.push({ - text: intl.formatMessage(status.pinned ? messages.unpin : messages.pin), - action: handlePinClick, - icon: status.pinned - ? require('@phosphor-icons/core/regular/push-pin-slash.svg') - : require('@phosphor-icons/core/regular/push-pin.svg'), - }); - } - - menu.push({ - text: intl.formatMessage(messages.delete), - action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), - destructive: true, - }); - } else { - menu.push({ - text: intl.formatMessage(messages.mention, { name: username }), - action: handleMentionClick, - icon: require('@phosphor-icons/core/regular/at.svg'), - }); - - if (account.accepts_chat_messages === true) { - menu.push({ - text: intl.formatMessage(messages.chat, { name: username }), - action: handleChatClick, - icon: require('@phosphor-icons/core/regular/chats-teardrop.svg'), - }); - } else if (features.privacyScopes) { - menu.push({ - text: intl.formatMessage(messages.direct, { name: username }), - action: handleDirectClick, - icon: require('@phosphor-icons/core/regular/chat-circle.svg'), - }); - } - - menu.push(null); - menu.push({ - text: intl.formatMessage(messages.mute, { name: username }), - action: handleMuteClick, - icon: require('@phosphor-icons/core/regular/speaker-simple-x.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.block, { name: username }), - action: handleBlockClick, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.report, { name: username }), - action: handleReport, - icon: require('@phosphor-icons/core/regular/flag.svg'), - }); - } - - if (isStaff) { - menu.push(null); - - menu.push({ - text: intl.formatMessage(messages.adminAccount, { name: username }), - to: '/nicolium/admin/accounts/$accountId', - params: { accountId: account.id }, - icon: require('@phosphor-icons/core/regular/gavel.svg'), - }); - - if (isAdmin && features.pleromaAdminStatuses) { - menu.push({ - text: intl.formatMessage(messages.adminStatus), - href: `/pleroma/admin/#/statuses/${status.id}/`, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), - }); - } - - if (features.pleromaAdminStatuses) { - menu.push({ - text: intl.formatMessage( - !status.sensitive ? messages.markStatusSensitive : messages.markStatusNotSensitive, - ), - action: handleToggleStatusSensitivity, - icon: require('@phosphor-icons/core/regular/warning.svg'), - }); - } - - if (account.id !== ownAccount?.id) { - menu.push({ - text: intl.formatMessage(messages.deleteStatus), - action: handleDeleteStatus, - icon: require('@phosphor-icons/core/regular/trash.svg'), - destructive: true, - }); - } - } - - return menu; - }; - - const handleParticipantsClick: React.MouseEventHandler = (e) => { - e.preventDefault(); - e.stopPropagation(); - - if (!ownAccount) { - openModal('UNAUTHORIZED'); - } else { - openModal('EVENT_PARTICIPANTS', { statusId: status.id }); - } - }; - - return ( - <> -
-
- {banner && ( - - - - )} -
-
-
-
- - {event.name} - - - - - - - {account.id === ownAccount?.id ? ( - - ) : ( - - )} -
- -
-
- - - -
- - - - {account.verified && } -
- - ), - }} - /> -
-
- - {(event.join_mode !== 'external' || event.participants_count > 0) && ( -
- - - - - - -
- )} - - - - {event.location && ( -
- - {event.location.name} -
- )} -
-
- - ); -}; - -export { EventHeader as default }; diff --git a/packages/nicolium/src/features/reply-mentions/account.tsx b/packages/nicolium/src/features/reply-mentions/account.tsx deleted file mode 100644 index 379ecddeb..000000000 --- a/packages/nicolium/src/features/reply-mentions/account.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React from 'react'; -import { defineMessages, useIntl } from 'react-intl'; - -import AccountComponent from '@/components/accounts/account'; -import IconButton from '@/components/ui/icon-button'; -import { useAccount } from '@/queries/accounts/use-account'; -import { useCompose, useComposeActions } from '@/stores/compose'; - -const messages = defineMessages({ - remove: { id: 'reply_mentions.account.remove', defaultMessage: 'Remove from mentions' }, - add: { id: 'reply_mentions.account.add', defaultMessage: 'Add to mentions' }, -}); - -interface IAccount { - composeId: string; - accountId: string; - author: boolean; -} - -const Account: React.FC = ({ composeId, accountId, author }) => { - const intl = useIntl(); - const { updateCompose } = useComposeActions(); - - const compose = useCompose(composeId); - const { data: account } = useAccount(accountId); - const added = !!account && compose.to?.includes(account.acct); - - const onRemove = () => - updateCompose(composeId, (draft) => { - if (account) { - draft.to = draft.to?.filter((acct) => acct !== account.acct) || []; - } - }); - const onAdd = () => - updateCompose(composeId, (draft) => { - if (account) { - if (draft.to?.includes(account.acct)) return; - draft.to = [...(draft.to || []), account.acct]; - } - }); - - if (!account) return null; - - let button; - - if (added) { - button = ( - - ); - } else { - button = ( - - ); - } - - return ( -
- -
- ); -}; - -export { Account as default }; diff --git a/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status.tsx b/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status.tsx index 59c349adc..2e8848304 100644 --- a/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status.tsx +++ b/packages/nicolium/src/features/scheduled-statuses/components/scheduled-status.tsx @@ -3,10 +3,10 @@ import React from 'react'; import Account from '@/components/accounts/account'; import AttachmentThumbs from '@/components/media/attachment-thumbs'; +import PollPreview from '@/components/polls/poll-preview'; import StatusContent from '@/components/statuses/status-content'; import StatusReplyMentions from '@/components/statuses/status-reply-mentions'; import { buildPoll } from '@/features/draft-statuses/builder'; -import PollPreview from '@/features/ui/components/poll-preview'; import { useOwnAccount } from '@/hooks/use-own-account'; import { buildStatus } from '../builder'; diff --git a/packages/nicolium/src/features/status/components/thread.tsx b/packages/nicolium/src/features/status/components/thread.tsx index 76266e409..0c223e91d 100644 --- a/packages/nicolium/src/features/status/components/thread.tsx +++ b/packages/nicolium/src/features/status/components/thread.tsx @@ -5,10 +5,10 @@ import { useIntl } from 'react-intl'; import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; +import PendingStatus from '@/components/statuses/pending-status'; import StatusActionBar from '@/components/statuses/status-action-bar'; import Tombstone from '@/components/statuses/tombstone'; import { Hotkeys } from '@/features/ui/components/hotkeys'; -import PendingStatus from '@/features/ui/components/pending-status'; import { useFavouriteStatus, useReblogStatus, diff --git a/packages/nicolium/src/features/ui/index.tsx b/packages/nicolium/src/features/ui/index.tsx index d36c47f79..3880a3255 100644 --- a/packages/nicolium/src/features/ui/index.tsx +++ b/packages/nicolium/src/features/ui/index.tsx @@ -27,10 +27,9 @@ import { useInstance, useInstanceStore } from '@/stores/instance'; import { useModalsActions } from '@/stores/modals'; import { useShoutboxSubscription } from '@/stores/shoutbox'; import { useIsDropdownMenuOpen } from '@/stores/ui'; +import GlobalHotkeys from '@/utils/global-hotkeys'; import { useIsStandalone } from '@/utils/state'; -import GlobalHotkeys from '../../utils/global-hotkeys'; - import { ModalRoot, AccountHoverCard, diff --git a/packages/nicolium/src/features/ui/util/async-components.ts b/packages/nicolium/src/features/ui/util/async-components.ts index c3bc0f752..e98fdf49a 100644 --- a/packages/nicolium/src/features/ui/util/async-components.ts +++ b/packages/nicolium/src/features/ui/util/async-components.ts @@ -15,7 +15,7 @@ export const InstanceModerationPanel = lazy( () => import('@/components/panels/instance-moderation-panel'), ); export const LatestAccountsPanel = lazy( - () => import('@/features/admin/components/latest-accounts-panel'), + () => import('@/pages/dashboard/components/latest-accounts-panel'), ); export const MyGroupsPanel = lazy(() => import('@/components/panels/my-groups-panel')); export const NewEventPanel = lazy(() => import('@/components/panels/new-event-panel')); @@ -41,7 +41,7 @@ export const EmojiPicker = lazy(() => import('@/features/emoji/components/emoji- export const EventHeader = lazy(() => import('@/components/statuses/events/event-header')); export const MediaGallery = lazy(() => import('@/components/media/media-gallery')); export const ModalRoot = lazy(() => import('@/features/ui/components/modal-root')); -export const ProfileField = lazy(() => import('@/features/ui/components/profile-field')); +export const ProfileField = lazy(() => import('@/components/accounts/profile-field')); export const AccountHoverCard = lazy(() => import('@/components/accounts/account-hover-card')); export const StatusHoverCard = lazy(() => import('@/components/statuses/status-hover-card')); export const Video = lazy(() => import('@/components/media/video')); diff --git a/packages/nicolium/src/layouts/profile-layout.tsx b/packages/nicolium/src/layouts/profile-layout.tsx index a87b781ea..2664d9d87 100644 --- a/packages/nicolium/src/layouts/profile-layout.tsx +++ b/packages/nicolium/src/layouts/profile-layout.tsx @@ -2,12 +2,12 @@ import { Navigate, Outlet, useLocation } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage } from 'react-intl'; +import AccountHeader from '@/components/accounts/account-header'; import LinkFooter from '@/components/navigation/link-footer'; import Column from '@/components/ui/column'; import Layout from '@/components/ui/layout'; import Tabs, { type Item } from '@/components/ui/tabs'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import Header from '@/features/account/components/header'; import { layouts } from '@/features/ui/router'; import { WhoToFollowPanel, @@ -103,7 +103,7 @@ const ProfileLayout: React.FC = () => { label={account ? `@${acct}` : ''} withHeader={false} > -
+ {account && showTabs && ( diff --git a/packages/nicolium/src/modals/manage-group-modal/steps/details-step.tsx b/packages/nicolium/src/modals/manage-group-modal/steps/details-step.tsx index ccb947fe4..89117a132 100644 --- a/packages/nicolium/src/modals/manage-group-modal/steps/details-step.tsx +++ b/packages/nicolium/src/modals/manage-group-modal/steps/details-step.tsx @@ -5,9 +5,9 @@ import Form from '@/components/ui/form'; import FormGroup from '@/components/ui/form-group'; import Input from '@/components/ui/input'; import Textarea from '@/components/ui/textarea'; -import AvatarPicker from '@/features/edit-profile/components/avatar-picker'; -import HeaderPicker from '@/features/edit-profile/components/header-picker'; import { usePreview } from '@/hooks/forms/use-preview'; +import AvatarPicker from '@/pages/settings/components/avatar-picker'; +import HeaderPicker from '@/pages/settings/components/header-picker'; import { useInstance } from '@/stores/instance'; import { useSettings } from '@/stores/settings'; import resizeImage from '@/utils/resize-image'; diff --git a/packages/nicolium/src/modals/media-modal.tsx b/packages/nicolium/src/modals/media-modal.tsx index dbd354538..02ce975c8 100644 --- a/packages/nicolium/src/modals/media-modal.tsx +++ b/packages/nicolium/src/modals/media-modal.tsx @@ -8,13 +8,13 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import Audio from '@/components/media/audio'; import ExtendedVideoPlayer from '@/components/media/extended-video-player'; import Video from '@/components/media/video'; +import ZoomableImage from '@/components/media/zoomable-image'; import MissingIndicator from '@/components/missing-indicator'; import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import StatusActionBar from '@/components/statuses/status-action-bar'; import Icon from '@/components/ui/icon'; import IconButton from '@/components/ui/icon-button'; import Thread from '@/features/status/components/thread'; -import ZoomableImage from '@/features/ui/components/zoomable-image'; import { useStatus } from '@/queries/statuses/use-status'; import { userTouching } from '@/utils/is-mobile'; diff --git a/packages/nicolium/src/modals/reply-mentions-modal.tsx b/packages/nicolium/src/modals/reply-mentions-modal.tsx index d1ec2c253..4e02a4100 100644 --- a/packages/nicolium/src/modals/reply-mentions-modal.tsx +++ b/packages/nicolium/src/modals/reply-mentions-modal.tsx @@ -1,15 +1,88 @@ import React from 'react'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; +import AccountComponent from '@/components/accounts/account'; +import IconButton from '@/components/ui/icon-button'; import Modal from '@/components/ui/modal'; -import Account from '@/features/reply-mentions/account'; -import { useCompose } from '@/hooks/use-compose'; import { useOwnAccount } from '@/hooks/use-own-account'; +import { useAccount } from '@/queries/accounts/use-account'; import { useMinimalStatus } from '@/queries/statuses/use-status'; +import { useCompose, useComposeActions } from '@/stores/compose'; import { statusToMentionsAccountIdsArray } from '@/stores/compose'; import type { BaseModalProps } from '@/features/ui/components/modal-root'; +const messages = defineMessages({ + remove: { id: 'reply_mentions.account.remove', defaultMessage: 'Remove from mentions' }, + add: { id: 'reply_mentions.account.add', defaultMessage: 'Add to mentions' }, +}); + +interface IReplyMentionAccount { + composeId: string; + accountId: string; + author: boolean; +} + +const ReplyMentionAccount: React.FC = ({ composeId, accountId, author }) => { + const intl = useIntl(); + const { updateCompose } = useComposeActions(); + + const compose = useCompose(composeId); + const { data: account } = useAccount(accountId); + const added = !!account && compose.to?.includes(account.acct); + + const onRemove = () => + updateCompose(composeId, (draft) => { + if (account) { + draft.to = draft.to?.filter((acct) => acct !== account.acct) || []; + } + }); + const onAdd = () => + updateCompose(composeId, (draft) => { + if (account) { + if (draft.to?.includes(account.acct)) return; + draft.to = [...(draft.to || []), account.acct]; + } + }); + + if (!account) return null; + + let button; + + if (added) { + button = ( + + ); + } else { + button = ( + + ); + } + + return ( +
+ +
+ ); +}; + interface ReplyMentionsModalProps { composeId: string; } @@ -39,7 +112,7 @@ const ReplyMentionsModal: React.FC = ( >
{mentions.map((accountId) => ( - ( diff --git a/packages/nicolium/src/pages/auth/login.tsx b/packages/nicolium/src/pages/auth/login.tsx index 1ed5cfcc1..6228beca7 100644 --- a/packages/nicolium/src/pages/auth/login.tsx +++ b/packages/nicolium/src/pages/auth/login.tsx @@ -7,14 +7,15 @@ import { BigCard } from '@/components/ui/big-card'; import Button from '@/components/ui/button'; import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; -import ConsumersList from '@/features/auth-login/components/consumers-list'; -import LoginForm from '@/features/auth-login/components/login-form'; -import OtpAuthForm from '@/features/auth-login/components/otp-auth-form'; import { useAuthActions } from '@/stores/auth'; import { useModalsActions } from '@/stores/modals'; import { getRedirectUrl } from '@/utils/redirect'; import { useIsStandalone } from '@/utils/state'; +import ConsumersList from './components/consumers-list'; +import LoginForm from './components/login-form'; +import OtpAuthForm from './components/otp-auth-form'; + import type { NicoliumResponse } from '@/api'; const LoginPage = () => { diff --git a/packages/nicolium/src/pages/auth/register-with-invite.tsx b/packages/nicolium/src/pages/auth/register-with-invite.tsx index 29ef33367..44869fb48 100644 --- a/packages/nicolium/src/pages/auth/register-with-invite.tsx +++ b/packages/nicolium/src/pages/auth/register-with-invite.tsx @@ -2,10 +2,11 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import { BigCard } from '@/components/ui/big-card'; -import RegistrationForm from '@/features/auth-login/components/registration-form'; import { inviteRoute } from '@/features/ui/router'; import { useInstance } from '@/stores/instance'; +import RegistrationForm from './components/registration-form'; + /** Page to register with an invitation. */ const RegisterWithInvitePage: React.FC = () => { const { token } = inviteRoute.useParams(); diff --git a/packages/nicolium/src/pages/auth/registration.tsx b/packages/nicolium/src/pages/auth/registration.tsx index 6eb4111d1..24c23c773 100644 --- a/packages/nicolium/src/pages/auth/registration.tsx +++ b/packages/nicolium/src/pages/auth/registration.tsx @@ -3,10 +3,11 @@ import { FormattedMessage } from 'react-intl'; import { BigCard } from '@/components/ui/big-card'; import Text from '@/components/ui/text'; -import RegistrationForm from '@/features/auth-login/components/registration-form'; import { useRegistrationStatus } from '@/hooks/use-registration-status'; import { useInstance } from '@/stores/instance'; +import RegistrationForm from './components/registration-form'; + const RegistrationPage: React.FC = () => { const instance = useInstance(); const { isOpen } = useRegistrationStatus(); diff --git a/packages/nicolium/src/pages/dashboard/awaiting-approval.tsx b/packages/nicolium/src/pages/dashboard/awaiting-approval.tsx index a8c0b736a..2e3772ed8 100644 --- a/packages/nicolium/src/pages/dashboard/awaiting-approval.tsx +++ b/packages/nicolium/src/pages/dashboard/awaiting-approval.tsx @@ -3,7 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import ScrollableList from '@/components/scrollable-list'; import Column from '@/components/ui/column'; -import UnapprovedAccount from '@/features/admin/components/unapproved-account'; +import UnapprovedAccount from '@/pages/dashboard/components/unapproved-account'; import { useAdminAccounts } from '@/queries/admin/use-accounts'; const messages = defineMessages({ diff --git a/packages/nicolium/src/features/admin/components/counter.tsx b/packages/nicolium/src/pages/dashboard/components/counter.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/counter.tsx rename to packages/nicolium/src/pages/dashboard/components/counter.tsx diff --git a/packages/nicolium/src/features/admin/components/dashcounter.tsx b/packages/nicolium/src/pages/dashboard/components/dashcounter.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/dashcounter.tsx rename to packages/nicolium/src/pages/dashboard/components/dashcounter.tsx diff --git a/packages/nicolium/src/features/admin/components/dimension.tsx b/packages/nicolium/src/pages/dashboard/components/dimension.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/dimension.tsx rename to packages/nicolium/src/pages/dashboard/components/dimension.tsx diff --git a/packages/nicolium/src/features/admin/components/latest-accounts-panel.tsx b/packages/nicolium/src/pages/dashboard/components/latest-accounts-panel.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/latest-accounts-panel.tsx rename to packages/nicolium/src/pages/dashboard/components/latest-accounts-panel.tsx diff --git a/packages/nicolium/src/features/admin/components/registration-mode-picker.tsx b/packages/nicolium/src/pages/dashboard/components/registration-mode-picker.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/registration-mode-picker.tsx rename to packages/nicolium/src/pages/dashboard/components/registration-mode-picker.tsx diff --git a/packages/nicolium/src/features/admin/components/report.tsx b/packages/nicolium/src/pages/dashboard/components/report.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/report.tsx rename to packages/nicolium/src/pages/dashboard/components/report.tsx diff --git a/packages/nicolium/src/features/admin/components/retention.tsx b/packages/nicolium/src/pages/dashboard/components/retention.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/retention.tsx rename to packages/nicolium/src/pages/dashboard/components/retention.tsx diff --git a/packages/nicolium/src/features/theme-editor/components/color.tsx b/packages/nicolium/src/pages/dashboard/components/theme-editor/color.tsx similarity index 100% rename from packages/nicolium/src/features/theme-editor/components/color.tsx rename to packages/nicolium/src/pages/dashboard/components/theme-editor/color.tsx diff --git a/packages/nicolium/src/features/theme-editor/components/palette.tsx b/packages/nicolium/src/pages/dashboard/components/theme-editor/palette.tsx similarity index 100% rename from packages/nicolium/src/features/theme-editor/components/palette.tsx rename to packages/nicolium/src/pages/dashboard/components/theme-editor/palette.tsx diff --git a/packages/nicolium/src/features/admin/components/unapproved-account.tsx b/packages/nicolium/src/pages/dashboard/components/unapproved-account.tsx similarity index 100% rename from packages/nicolium/src/features/admin/components/unapproved-account.tsx rename to packages/nicolium/src/pages/dashboard/components/unapproved-account.tsx diff --git a/packages/nicolium/src/pages/dashboard/dashboard.tsx b/packages/nicolium/src/pages/dashboard/dashboard.tsx index 62b803f9f..a2446e563 100644 --- a/packages/nicolium/src/pages/dashboard/dashboard.tsx +++ b/packages/nicolium/src/pages/dashboard/dashboard.tsx @@ -5,13 +5,13 @@ import List, { ListItem } from '@/components/list'; import { CardTitle } from '@/components/ui/card'; import Column from '@/components/ui/column'; import Icon from '@/components/ui/icon'; -import { Counter } from '@/features/admin/components/counter'; -import { DashCounter, DashCounters } from '@/features/admin/components/dashcounter'; -import { Dimension } from '@/features/admin/components/dimension'; -import RegistrationModePicker from '@/features/admin/components/registration-mode-picker'; -import { Retention } from '@/features/admin/components/retention'; import { useFeatures } from '@/hooks/use-features'; import { useOwnAccount } from '@/hooks/use-own-account'; +import { Counter } from '@/pages/dashboard/components/counter'; +import { DashCounter, DashCounters } from '@/pages/dashboard/components/dashcounter'; +import { Dimension } from '@/pages/dashboard/components/dimension'; +import RegistrationModePicker from '@/pages/dashboard/components/registration-mode-picker'; +import { Retention } from '@/pages/dashboard/components/retention'; import { usePendingUsersCount } from '@/queries/admin/use-accounts'; import { usePendingReportsCount } from '@/queries/admin/use-reports'; import { useInstance } from '@/stores/instance'; diff --git a/packages/nicolium/src/pages/dashboard/reports.tsx b/packages/nicolium/src/pages/dashboard/reports.tsx index 9ad4db841..77f1dfb8f 100644 --- a/packages/nicolium/src/pages/dashboard/reports.tsx +++ b/packages/nicolium/src/pages/dashboard/reports.tsx @@ -6,8 +6,8 @@ import ScrollableList from '@/components/scrollable-list'; import Column from '@/components/ui/column'; import IconButton from '@/components/ui/icon-button'; import Text from '@/components/ui/text'; -import Report from '@/features/admin/components/report'; import { adminReportsRoute } from '@/features/ui/router'; +import Report from '@/pages/dashboard/components/report'; import { useAccount } from '@/queries/accounts/use-account'; import { useReports } from '@/queries/admin/use-reports'; diff --git a/packages/nicolium/src/pages/dashboard/theme-editor.tsx b/packages/nicolium/src/pages/dashboard/theme-editor.tsx index ad9443815..e9fb09bee 100644 --- a/packages/nicolium/src/pages/dashboard/theme-editor.tsx +++ b/packages/nicolium/src/pages/dashboard/theme-editor.tsx @@ -11,7 +11,6 @@ import Column from '@/components/ui/column'; import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; import ColorPicker from '@/features/frontend-config/components/color-picker'; -import Palette, { type ColorGroup } from '@/features/theme-editor/components/palette'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; import { normalizeColors } from '@/hooks/use-theme-css'; import { getUpdateFrontendConfigParams, useUpdateAdminConfig } from '@/queries/admin/use-config'; @@ -20,6 +19,8 @@ import { useFrontendConfigStore } from '@/stores/frontend-config'; import toast from '@/toast'; import { download } from '@/utils/download'; +import Palette, { type ColorGroup } from './components/theme-editor/palette'; + import type { ColorChangeHandler } from 'react-color'; const messages = defineMessages({ diff --git a/packages/nicolium/src/pages/developers/settings-store.tsx b/packages/nicolium/src/pages/developers/settings-store.tsx index c23ded91b..e3538c00b 100644 --- a/packages/nicolium/src/pages/developers/settings-store.tsx +++ b/packages/nicolium/src/pages/developers/settings-store.tsx @@ -10,7 +10,7 @@ import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; import FormGroup from '@/components/ui/form-group'; import Textarea from '@/components/ui/textarea'; -import SettingToggle from '@/features/settings/components/setting-toggle'; +import SettingToggle from '@/pages/settings/components/setting-toggle'; import { useSettingsStore, useSettingsStoreActions } from '@/stores/settings'; import toast from '@/toast'; diff --git a/packages/nicolium/src/pages/groups/edit-group.tsx b/packages/nicolium/src/pages/groups/edit-group.tsx index d5163c341..eed2eade1 100644 --- a/packages/nicolium/src/pages/groups/edit-group.tsx +++ b/packages/nicolium/src/pages/groups/edit-group.tsx @@ -10,11 +10,11 @@ import Icon from '@/components/ui/icon'; import Input from '@/components/ui/input'; import Spinner from '@/components/ui/spinner'; import Textarea from '@/components/ui/textarea'; -import AvatarPicker from '@/features/edit-profile/components/avatar-picker'; -import HeaderPicker from '@/features/edit-profile/components/header-picker'; import { editGroupRoute } from '@/features/ui/router'; import { useImageField } from '@/hooks/forms/use-image-field'; import { useTextField } from '@/hooks/forms/use-text-field'; +import AvatarPicker from '@/pages/settings/components/avatar-picker'; +import HeaderPicker from '@/pages/settings/components/header-picker'; import { useGroupQuery, useUpdateGroupMutation } from '@/queries/groups/use-group'; import { useInstance } from '@/stores/instance'; import toast from '@/toast'; diff --git a/packages/nicolium/src/features/edit-profile/components/avatar-picker.tsx b/packages/nicolium/src/pages/settings/components/avatar-picker.tsx similarity index 100% rename from packages/nicolium/src/features/edit-profile/components/avatar-picker.tsx rename to packages/nicolium/src/pages/settings/components/avatar-picker.tsx diff --git a/packages/nicolium/src/features/security/mfa/disable-otp-form.tsx b/packages/nicolium/src/pages/settings/components/disable-otp-form.tsx similarity index 100% rename from packages/nicolium/src/features/security/mfa/disable-otp-form.tsx rename to packages/nicolium/src/pages/settings/components/disable-otp-form.tsx diff --git a/packages/nicolium/src/features/security/mfa/enable-otp-form.tsx b/packages/nicolium/src/pages/settings/components/enable-otp-form.tsx similarity index 100% rename from packages/nicolium/src/features/security/mfa/enable-otp-form.tsx rename to packages/nicolium/src/pages/settings/components/enable-otp-form.tsx diff --git a/packages/nicolium/src/features/edit-profile/components/header-picker.tsx b/packages/nicolium/src/pages/settings/components/header-picker.tsx similarity index 100% rename from packages/nicolium/src/features/edit-profile/components/header-picker.tsx rename to packages/nicolium/src/pages/settings/components/header-picker.tsx diff --git a/packages/nicolium/src/features/settings/components/messages-settings.tsx b/packages/nicolium/src/pages/settings/components/messages-settings.tsx similarity index 100% rename from packages/nicolium/src/features/settings/components/messages-settings.tsx rename to packages/nicolium/src/pages/settings/components/messages-settings.tsx diff --git a/packages/nicolium/src/features/security/mfa/otp-confirm-form.tsx b/packages/nicolium/src/pages/settings/components/otp-confirm-form.tsx similarity index 100% rename from packages/nicolium/src/features/security/mfa/otp-confirm-form.tsx rename to packages/nicolium/src/pages/settings/components/otp-confirm-form.tsx diff --git a/packages/nicolium/src/features/preferences/index.tsx b/packages/nicolium/src/pages/settings/components/preferences.tsx similarity index 99% rename from packages/nicolium/src/features/preferences/index.tsx rename to packages/nicolium/src/pages/settings/components/preferences.tsx index 06a98c544..5b4dd42d6 100644 --- a/packages/nicolium/src/features/preferences/index.tsx +++ b/packages/nicolium/src/pages/settings/components/preferences.tsx @@ -9,17 +9,17 @@ import Form from '@/components/ui/form'; import { Multiselect } from '@/components/ui/multiselect'; import { SelectDropdown } from '@/components/ui/select-dropdown'; import StepSlider from '@/components/ui/step-slider'; -import SettingToggle from '@/features/settings/components/setting-toggle'; import { useFeatures } from '@/hooks/use-features'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; import { PaletteListItem } from '@/pages/dashboard/theme-editor'; +import SettingToggle from '@/pages/settings/components/setting-toggle'; import { useInstance } from '@/stores/instance'; import { useDefaultSettings, useSettings } from '@/stores/settings'; import sourceCode from '@/utils/code'; import colors from '@/utils/colors'; import { useIsStandalone } from '@/utils/state'; -import ThemeToggle from '../ui/components/theme-toggle'; +import ThemeToggle from '../../../features/ui/components/theme-toggle'; const languages = { en: 'English', diff --git a/packages/nicolium/src/features/settings/components/setting-toggle.tsx b/packages/nicolium/src/pages/settings/components/setting-toggle.tsx similarity index 100% rename from packages/nicolium/src/features/settings/components/setting-toggle.tsx rename to packages/nicolium/src/pages/settings/components/setting-toggle.tsx diff --git a/packages/nicolium/src/pages/settings/edit-profile.tsx b/packages/nicolium/src/pages/settings/edit-profile.tsx index c9d471676..4fdbce424 100644 --- a/packages/nicolium/src/pages/settings/edit-profile.tsx +++ b/packages/nicolium/src/pages/settings/edit-profile.tsx @@ -16,12 +16,12 @@ import { SelectDropdown } from '@/components/ui/select-dropdown'; import Streamfield from '@/components/ui/streamfield'; import Textarea from '@/components/ui/textarea'; import Toggle from '@/components/ui/toggle'; -import AvatarPicker from '@/features/edit-profile/components/avatar-picker'; -import HeaderPicker from '@/features/edit-profile/components/header-picker'; import { useImageField } from '@/hooks/forms/use-image-field'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; import { useOwnAccount } from '@/hooks/use-own-account'; +import AvatarPicker from '@/pages/settings/components/avatar-picker'; +import HeaderPicker from '@/pages/settings/components/header-picker'; import { useAuthActions } from '@/stores/auth'; import { useInstance } from '@/stores/instance'; import toast from '@/toast'; diff --git a/packages/nicolium/src/pages/settings/mfa-form.tsx b/packages/nicolium/src/pages/settings/mfa-form.tsx index e0b78db17..d5673da5f 100644 --- a/packages/nicolium/src/pages/settings/mfa-form.tsx +++ b/packages/nicolium/src/pages/settings/mfa-form.tsx @@ -5,9 +5,9 @@ import Column from '@/components/ui/column'; import { useFeatures } from '@/hooks/use-features'; import { useMfaConfig } from '@/queries/security/use-mfa'; -import DisableOtpForm from '../../features/security/mfa/disable-otp-form'; -import EnableOtpForm from '../../features/security/mfa/enable-otp-form'; -import OtpConfirmForm from '../../features/security/mfa/otp-confirm-form'; +import DisableOtpForm from './components/disable-otp-form'; +import EnableOtpForm from './components/enable-otp-form'; +import OtpConfirmForm from './components/otp-confirm-form'; const messages = defineMessages({ heading: { id: 'column.mfa', defaultMessage: 'Multi-factor authentication' }, diff --git a/packages/nicolium/src/pages/settings/settings.tsx b/packages/nicolium/src/pages/settings/settings.tsx index 86fa9ac4d..9fab57e1b 100644 --- a/packages/nicolium/src/pages/settings/settings.tsx +++ b/packages/nicolium/src/pages/settings/settings.tsx @@ -5,10 +5,10 @@ import List, { ListItem } from '@/components/list'; import Card, { CardBody, CardHeader, CardTitle } from '@/components/ui/card'; import Column from '@/components/ui/column'; import Text from '@/components/ui/text'; -import Preferences from '@/features/preferences'; -import MessagesSettings from '@/features/settings/components/messages-settings'; import { useFeatures } from '@/hooks/use-features'; import { useOwnAccount } from '@/hooks/use-own-account'; +import MessagesSettings from '@/pages/settings/components/messages-settings'; +import Preferences from '@/pages/settings/components/preferences'; import { useMfaConfig } from '@/queries/security/use-mfa'; const messages = defineMessages({ diff --git a/packages/nicolium/src/features/conversations/components/conversation.tsx b/packages/nicolium/src/pages/status-lists/components/conversation.tsx similarity index 100% rename from packages/nicolium/src/features/conversations/components/conversation.tsx rename to packages/nicolium/src/pages/status-lists/components/conversation.tsx diff --git a/packages/nicolium/src/features/conversations/components/conversations-list.tsx b/packages/nicolium/src/pages/status-lists/components/conversations-list.tsx similarity index 100% rename from packages/nicolium/src/features/conversations/components/conversations-list.tsx rename to packages/nicolium/src/pages/status-lists/components/conversations-list.tsx diff --git a/packages/nicolium/src/pages/status-lists/conversations.tsx b/packages/nicolium/src/pages/status-lists/conversations.tsx index 26f0d6252..147be7c8f 100644 --- a/packages/nicolium/src/pages/status-lists/conversations.tsx +++ b/packages/nicolium/src/pages/status-lists/conversations.tsx @@ -2,8 +2,8 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import Column from '@/components/ui/column'; -import ConversationsList from '@/features/conversations/components/conversations-list'; import { useDirectStream } from '@/hooks/streaming/use-direct-stream'; +import ConversationsList from '@/pages/status-lists/components/conversations-list'; const messages = defineMessages({ title: { id: 'column.direct', defaultMessage: 'Direct messages' }, diff --git a/packages/nicolium/src/pages/status-lists/interaction-requests.tsx b/packages/nicolium/src/pages/status-lists/interaction-requests.tsx index 2b4097a29..9d8a85986 100644 --- a/packages/nicolium/src/pages/status-lists/interaction-requests.tsx +++ b/packages/nicolium/src/pages/status-lists/interaction-requests.tsx @@ -6,6 +6,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import AccountContainer from '@/components/accounts/account-container'; import Icon from '@/components/icon'; import AttachmentThumbs from '@/components/media/attachment-thumbs'; +import { buildLink } from '@/components/notification'; import PullToRefresh from '@/components/pull-to-refresh'; import RelativeTimestamp from '@/components/relative-timestamp'; import ScrollableList from '@/components/scrollable-list'; @@ -13,7 +14,6 @@ import StatusContent from '@/components/statuses/status-content'; import Button from '@/components/ui/button'; import Column from '@/components/ui/column'; import Text from '@/components/ui/text'; -import { buildLink } from '@/features/notifications/components/notification'; import { Hotkeys } from '@/features/ui/components/hotkeys'; import { useOwnAccount } from '@/hooks/use-own-account'; import { useAccount } from '@/queries/accounts/use-account'; diff --git a/packages/nicolium/src/pages/statuses/event-discussion.tsx b/packages/nicolium/src/pages/statuses/event-discussion.tsx index 77fb8d682..a90888c89 100644 --- a/packages/nicolium/src/pages/statuses/event-discussion.tsx +++ b/packages/nicolium/src/pages/statuses/event-discussion.tsx @@ -4,10 +4,10 @@ import { FormattedMessage } from 'react-intl'; import MissingIndicator from '@/components/missing-indicator'; import PlaceholderStatus from '@/components/placeholders/placeholder-status'; import ScrollableList from '@/components/scrollable-list'; +import PendingStatus from '@/components/statuses/pending-status'; import Tombstone from '@/components/statuses/tombstone'; import { useCurrentAccount } from '@/contexts/current-account-context'; import ThreadStatus from '@/features/status/components/thread-status'; -import PendingStatus from '@/features/ui/components/pending-status'; import { eventDiscussionRoute } from '@/features/ui/router'; import { ComposeForm } from '@/features/ui/util/async-components'; import { useStatus } from '@/queries/statuses/use-status'; diff --git a/packages/nicolium/src/pages/utils/about.tsx b/packages/nicolium/src/pages/utils/about.tsx index f5175d1da..ec0201897 100644 --- a/packages/nicolium/src/pages/utils/about.tsx +++ b/packages/nicolium/src/pages/utils/about.tsx @@ -3,9 +3,9 @@ import { FormattedMessage } from 'react-intl'; import { Navlinks } from '@/components/navigation/navlinks'; import Card from '@/components/ui/card'; -import { languages } from '@/features/preferences'; import { aboutRoute } from '@/features/ui/router'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; +import { languages } from '@/pages/settings/components/preferences'; import { useAboutPage } from '@/queries/frontend/use-about-page'; import { useSettings } from '@/stores/settings'; diff --git a/packages/nicolium/src/queries/notifications/use-notifications.ts b/packages/nicolium/src/queries/notifications/use-notifications.ts index c6b90f340..f19f9545d 100644 --- a/packages/nicolium/src/queries/notifications/use-notifications.ts +++ b/packages/nicolium/src/queries/notifications/use-notifications.ts @@ -10,10 +10,7 @@ import { import { useCallback, useEffect, useMemo } from 'react'; import { useIntl } from 'react-intl'; -import { - getNotificationStatusId, - notificationMessages, -} from '@/features/notifications/components/notification'; +import { getNotificationStatusId, notificationMessages } from '@/components/notification'; import { useClient } from '@/hooks/use-client'; import { useLoggedIn } from '@/hooks/use-logged-in'; import { appendFollowRequest } from '@/queries/accounts/use-follow-requests'; diff --git a/packages/nicolium/src/stores/compose.ts b/packages/nicolium/src/stores/compose.ts index d0466e90e..00f1a2d9a 100644 --- a/packages/nicolium/src/stores/compose.ts +++ b/packages/nicolium/src/stores/compose.ts @@ -23,7 +23,7 @@ import toast from '@/toast'; import { useUiStoreActions } from './ui'; import type { AutoSuggestion } from '@/components/autosuggest-input'; -import type { Language } from '@/features/preferences'; +import type { Language } from '@/pages/settings/components/preferences'; import type { NormalizedStatus as Status } from '@/queries/statuses/normalize'; import type { LinkOptions } from '@tanstack/react-router'; import type { diff --git a/packages/nicolium/src/features/ui/util/fullscreen.ts b/packages/nicolium/src/utils/fullscreen.ts similarity index 100% rename from packages/nicolium/src/features/ui/util/fullscreen.ts rename to packages/nicolium/src/utils/fullscreen.ts From 5c7629908827e56b88ca81874852d0f380f621aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:17:53 +0100 Subject: [PATCH 18/64] nicolium: no MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/features/ui/router/index.tsx | 16 ++++++++-------- .../nicolium/src/features/ui/router/util.tsx | 2 +- .../src/pages/{utils => compose}/new-status.tsx | 0 .../src/pages/{utils => compose}/share.tsx | 0 .../{utils => errors}/generic-not-found.tsx | 0 .../{utils => errors}/intentional-error.tsx | 0 .../src/pages/{utils => instance}/about.tsx | 0 .../pages/{utils => instance}/crypto-donate.tsx | 0 .../federation-restrictions.tsx | 0 .../src/pages/{utils => instance}/landing.tsx | 0 .../pages/{utils => instance}/server-info.tsx | 0 .../src/pages/timelines/landing-timeline.tsx | 2 +- 12 files changed, 10 insertions(+), 10 deletions(-) rename packages/nicolium/src/pages/{utils => compose}/new-status.tsx (100%) rename packages/nicolium/src/pages/{utils => compose}/share.tsx (100%) rename packages/nicolium/src/pages/{utils => errors}/generic-not-found.tsx (100%) rename packages/nicolium/src/pages/{utils => errors}/intentional-error.tsx (100%) rename packages/nicolium/src/pages/{utils => instance}/about.tsx (100%) rename packages/nicolium/src/pages/{utils => instance}/crypto-donate.tsx (100%) rename packages/nicolium/src/pages/{utils => instance}/federation-restrictions.tsx (100%) rename packages/nicolium/src/pages/{utils => instance}/landing.tsx (100%) rename packages/nicolium/src/pages/{utils => instance}/server-info.tsx (100%) diff --git a/packages/nicolium/src/features/ui/router/index.tsx b/packages/nicolium/src/features/ui/router/index.tsx index 488779b04..61e2817b8 100644 --- a/packages/nicolium/src/features/ui/router/index.tsx +++ b/packages/nicolium/src/features/ui/router/index.tsx @@ -759,7 +759,7 @@ export const groupMembershipRequestsRoute = createRoute({ export const newStatusRoute = createRoute({ getParentRoute: () => layouts.default, path: '/statuses/new', - component: lazy(() => import('@/pages/utils/new-status')), + component: lazy(() => import('@/pages/compose/new-status')), }); export const scheduledStatusesRoute = createRoute({ @@ -1045,19 +1045,19 @@ export const adminRulesRoute = createRoute({ export const serverInfoRoute = createRoute({ getParentRoute: () => layouts.empty, path: '/info', - component: lazy(() => import('@/pages/utils/server-info')), + component: lazy(() => import('@/pages/instance/server-info')), }); export const aboutRoute = createRoute({ getParentRoute: () => layouts.default, path: '/about/{-$slug}', - component: lazy(() => import('@/pages/utils/about')), + component: lazy(() => import('@/pages/instance/about')), }); export const shareRoute = createRoute({ getParentRoute: () => layouts.default, path: '/share', - component: lazy(() => import('@/pages/utils/share')), + component: lazy(() => import('@/pages/compose/share')), validateSearch: v.object({ title: v.optional(v.string(), ''), text: v.optional(v.string(), ''), @@ -1098,7 +1098,7 @@ export const developersSwRoute = createRoute({ export const errorRoute = createRoute({ getParentRoute: () => layouts.empty, path: '/error', - component: lazy(() => import('@/pages/utils/intentional-error')), + component: lazy(() => import('@/pages/errors/intentional-error')), }); export const networkErrorRoute = createRoute({ @@ -1116,7 +1116,7 @@ export const networkErrorRoute = createRoute({ export const cryptoDonateRoute = createRoute({ getParentRoute: () => layouts.default, path: '/donate/crypto', - component: lazy(() => import('@/pages/utils/crypto-donate')), + component: lazy(() => import('@/pages/instance/crypto-donate')), beforeLoad: ({ context: { hasCrypto } }) => { if (!hasCrypto) throw notFound(); }, @@ -1126,7 +1126,7 @@ export const cryptoDonateRoute = createRoute({ export const federationRestrictionsRoute = createRoute({ getParentRoute: () => layouts.default, path: '/federation_restrictions', - component: lazy(() => import('@/pages/utils/federation-restrictions')), + component: lazy(() => import('@/pages/instance/federation-restrictions')), beforeLoad: ({ context: { features } }) => { if (!features.federating) throw notFound(); }, @@ -1465,7 +1465,7 @@ const router = createRouter({ isAdmin: false, hasCrypto: false, }, - defaultNotFoundComponent: lazy(() => import('@/pages/utils/generic-not-found')), + defaultNotFoundComponent: lazy(() => import('@/pages/errors/generic-not-found')), defaultPendingComponent: PendingComponent, defaultErrorComponent: SiteError, defaultPreload: 'intent', diff --git a/packages/nicolium/src/features/ui/router/util.tsx b/packages/nicolium/src/features/ui/router/util.tsx index be0db2637..690f77633 100644 --- a/packages/nicolium/src/features/ui/router/util.tsx +++ b/packages/nicolium/src/features/ui/router/util.tsx @@ -7,7 +7,7 @@ import { useLoggedIn } from '@/hooks/use-logged-in'; import { useIsStandalone } from '@/utils/state'; const HomeTimeline = lazyRouteComponent(() => import('@/pages/timelines/home-timeline')); -const LandingPage = lazyRouteComponent(() => import('@/pages/utils/landing')); +const LandingPage = lazyRouteComponent(() => import('@/pages/instance/landing')); const LandingTimeline = lazyRouteComponent(() => import('@/pages/timelines/landing-timeline')); const HomeRoute = () => { diff --git a/packages/nicolium/src/pages/utils/new-status.tsx b/packages/nicolium/src/pages/compose/new-status.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/new-status.tsx rename to packages/nicolium/src/pages/compose/new-status.tsx diff --git a/packages/nicolium/src/pages/utils/share.tsx b/packages/nicolium/src/pages/compose/share.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/share.tsx rename to packages/nicolium/src/pages/compose/share.tsx diff --git a/packages/nicolium/src/pages/utils/generic-not-found.tsx b/packages/nicolium/src/pages/errors/generic-not-found.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/generic-not-found.tsx rename to packages/nicolium/src/pages/errors/generic-not-found.tsx diff --git a/packages/nicolium/src/pages/utils/intentional-error.tsx b/packages/nicolium/src/pages/errors/intentional-error.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/intentional-error.tsx rename to packages/nicolium/src/pages/errors/intentional-error.tsx diff --git a/packages/nicolium/src/pages/utils/about.tsx b/packages/nicolium/src/pages/instance/about.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/about.tsx rename to packages/nicolium/src/pages/instance/about.tsx diff --git a/packages/nicolium/src/pages/utils/crypto-donate.tsx b/packages/nicolium/src/pages/instance/crypto-donate.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/crypto-donate.tsx rename to packages/nicolium/src/pages/instance/crypto-donate.tsx diff --git a/packages/nicolium/src/pages/utils/federation-restrictions.tsx b/packages/nicolium/src/pages/instance/federation-restrictions.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/federation-restrictions.tsx rename to packages/nicolium/src/pages/instance/federation-restrictions.tsx diff --git a/packages/nicolium/src/pages/utils/landing.tsx b/packages/nicolium/src/pages/instance/landing.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/landing.tsx rename to packages/nicolium/src/pages/instance/landing.tsx diff --git a/packages/nicolium/src/pages/utils/server-info.tsx b/packages/nicolium/src/pages/instance/server-info.tsx similarity index 100% rename from packages/nicolium/src/pages/utils/server-info.tsx rename to packages/nicolium/src/pages/instance/server-info.tsx diff --git a/packages/nicolium/src/pages/timelines/landing-timeline.tsx b/packages/nicolium/src/pages/timelines/landing-timeline.tsx index c15dc8da6..079e4b462 100644 --- a/packages/nicolium/src/pages/timelines/landing-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/landing-timeline.tsx @@ -8,7 +8,7 @@ import { ParsedContent } from '@/components/statuses/parsed-content'; import Button from '@/components/ui/button'; import Column from '@/components/ui/column'; import { useRegistrationStatus } from '@/hooks/use-registration-status'; -import { About } from '@/pages/utils/about'; +import { About } from '@/pages/instance/about'; import { usePublicTimeline } from '@/queries/timelines/use-timelines'; import { useInstance } from '@/stores/instance'; import { getTextDirection } from '@/utils/rtl'; From 49a46d4192bca4159506455f04f704e48ed77291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:26:23 +0100 Subject: [PATCH 19/64] nicolium: last one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/frontend-config}/color-picker.tsx | 0 .../components/frontend-config}/crypto-address-input.tsx | 0 .../components/frontend-config}/footer-link-input.tsx | 0 .../components}/frontend-config/forkawesome.json | 0 .../components/frontend-config}/icon-picker-dropdown.tsx | 0 .../components/frontend-config}/icon-picker-menu.tsx | 0 .../dashboard/components/frontend-config}/icon-picker.tsx | 0 .../components/frontend-config}/promo-panel-input.tsx | 0 .../components/frontend-config}/site-preview.tsx | 0 .../src/pages/dashboard/components/theme-editor/color.tsx | 2 +- packages/nicolium/src/pages/dashboard/frontend-config.tsx | 8 ++++---- packages/nicolium/src/pages/dashboard/theme-editor.tsx | 2 +- 12 files changed, 6 insertions(+), 6 deletions(-) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/color-picker.tsx (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/crypto-address-input.tsx (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/footer-link-input.tsx (100%) rename packages/nicolium/src/{features => pages/dashboard/components}/frontend-config/forkawesome.json (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/icon-picker-dropdown.tsx (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/icon-picker-menu.tsx (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/icon-picker.tsx (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/promo-panel-input.tsx (100%) rename packages/nicolium/src/{features/frontend-config/components => pages/dashboard/components/frontend-config}/site-preview.tsx (100%) diff --git a/packages/nicolium/src/features/frontend-config/components/color-picker.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/color-picker.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/color-picker.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/color-picker.tsx diff --git a/packages/nicolium/src/features/frontend-config/components/crypto-address-input.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/crypto-address-input.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/crypto-address-input.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/crypto-address-input.tsx diff --git a/packages/nicolium/src/features/frontend-config/components/footer-link-input.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/footer-link-input.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/footer-link-input.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/footer-link-input.tsx diff --git a/packages/nicolium/src/features/frontend-config/forkawesome.json b/packages/nicolium/src/pages/dashboard/components/frontend-config/forkawesome.json similarity index 100% rename from packages/nicolium/src/features/frontend-config/forkawesome.json rename to packages/nicolium/src/pages/dashboard/components/frontend-config/forkawesome.json diff --git a/packages/nicolium/src/features/frontend-config/components/icon-picker-dropdown.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/icon-picker-dropdown.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx diff --git a/packages/nicolium/src/features/frontend-config/components/icon-picker-menu.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-menu.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/icon-picker-menu.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-menu.tsx diff --git a/packages/nicolium/src/features/frontend-config/components/icon-picker.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/icon-picker.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker.tsx diff --git a/packages/nicolium/src/features/frontend-config/components/promo-panel-input.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/promo-panel-input.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/promo-panel-input.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/promo-panel-input.tsx diff --git a/packages/nicolium/src/features/frontend-config/components/site-preview.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/site-preview.tsx similarity index 100% rename from packages/nicolium/src/features/frontend-config/components/site-preview.tsx rename to packages/nicolium/src/pages/dashboard/components/frontend-config/site-preview.tsx diff --git a/packages/nicolium/src/pages/dashboard/components/theme-editor/color.tsx b/packages/nicolium/src/pages/dashboard/components/theme-editor/color.tsx index 83238207a..708b2cee0 100644 --- a/packages/nicolium/src/pages/dashboard/components/theme-editor/color.tsx +++ b/packages/nicolium/src/pages/dashboard/components/theme-editor/color.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import ColorPicker from '@/features/frontend-config/components/color-picker'; +import ColorPicker from '@/pages/dashboard/components/frontend-config/color-picker'; import type { ColorChangeHandler } from 'react-color'; diff --git a/packages/nicolium/src/pages/dashboard/frontend-config.tsx b/packages/nicolium/src/pages/dashboard/frontend-config.tsx index d60ec89d4..b3daf3fbf 100644 --- a/packages/nicolium/src/pages/dashboard/frontend-config.tsx +++ b/packages/nicolium/src/pages/dashboard/frontend-config.tsx @@ -18,13 +18,13 @@ import Select from '@/components/ui/select'; import Streamfield from '@/components/ui/streamfield'; import Textarea from '@/components/ui/textarea'; import Toggle from '@/components/ui/toggle'; -import CryptoAddressInput from '@/features/frontend-config/components/crypto-address-input'; -import FooterLinkInput from '@/features/frontend-config/components/footer-link-input'; -import PromoPanelInput from '@/features/frontend-config/components/promo-panel-input'; -import SitePreview from '@/features/frontend-config/components/site-preview'; import ThemeSelector from '@/features/ui/components/theme-selector'; import { useClient } from '@/hooks/use-client'; import { useFeatures } from '@/hooks/use-features'; +import CryptoAddressInput from '@/pages/dashboard/components/frontend-config/crypto-address-input'; +import FooterLinkInput from '@/pages/dashboard/components/frontend-config/footer-link-input'; +import PromoPanelInput from '@/pages/dashboard/components/frontend-config/promo-panel-input'; +import SitePreview from '@/pages/dashboard/components/frontend-config/site-preview'; import { getUpdateFrontendConfigParams, useUpdateAdminConfig } from '@/queries/admin/use-config'; import { cryptoAddressSchema, diff --git a/packages/nicolium/src/pages/dashboard/theme-editor.tsx b/packages/nicolium/src/pages/dashboard/theme-editor.tsx index e9fb09bee..a28358800 100644 --- a/packages/nicolium/src/pages/dashboard/theme-editor.tsx +++ b/packages/nicolium/src/pages/dashboard/theme-editor.tsx @@ -10,9 +10,9 @@ import Button from '@/components/ui/button'; import Column from '@/components/ui/column'; import Form from '@/components/ui/form'; import FormActions from '@/components/ui/form-actions'; -import ColorPicker from '@/features/frontend-config/components/color-picker'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; import { normalizeColors } from '@/hooks/use-theme-css'; +import ColorPicker from '@/pages/dashboard/components/frontend-config/color-picker'; import { getUpdateFrontendConfigParams, useUpdateAdminConfig } from '@/queries/admin/use-config'; import { frontendConfigSchema } from '@/schemas/frontend-config'; import { useFrontendConfigStore } from '@/stores/frontend-config'; From c11740aa24299ea3897c472a6e40bf8452d30eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:30:28 +0100 Subject: [PATCH 20/64] pl-api: hotfix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/entities/status.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pl-api/lib/entities/status.ts b/packages/pl-api/lib/entities/status.ts index 7937eaa98..7d9818b13 100644 --- a/packages/pl-api/lib/entities/status.ts +++ b/packages/pl-api/lib/entities/status.ts @@ -51,7 +51,7 @@ const baseStatusSchema = v.object({ v.unknown(), v.transform((account) => { const fallbackAccount = (window as any)?.__PL_API_FALLBACK_ACCOUNT; - if (fallbackAccount && Object.keys(account as object).length > 0) return fallbackAccount; + if (fallbackAccount && Object.keys(account as object).length === 0) return fallbackAccount; return account; }), accountSchema, From c5f1cd7b150124b19dc29afbf068d47792f4369b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:30:57 +0100 Subject: [PATCH 21/64] nicolium: use title to show custom emoji name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/still-image.tsx | 2 ++ packages/nicolium/src/components/ui/emoji.tsx | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/nicolium/src/components/still-image.tsx b/packages/nicolium/src/components/still-image.tsx index d7919b9be..860107412 100644 --- a/packages/nicolium/src/components/still-image.tsx +++ b/packages/nicolium/src/components/still-image.tsx @@ -88,6 +88,7 @@ const StillImage: React.FC = ({ {alt} = ({ {alt} ) : ( diff --git a/packages/nicolium/src/components/ui/emoji.tsx b/packages/nicolium/src/components/ui/emoji.tsx index 89aff5db4..3525bee53 100644 --- a/packages/nicolium/src/components/ui/emoji.tsx +++ b/packages/nicolium/src/components/ui/emoji.tsx @@ -50,6 +50,7 @@ const Emoji: React.FC = (props) => { {alt From e30991aa0db29378a3602e6020741c1836af9221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:38:26 +0100 Subject: [PATCH 22/64] nicolium: fix import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/frontend-config/icon-picker-dropdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx index 08ba34a5c..58258d777 100644 --- a/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx +++ b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx @@ -19,7 +19,7 @@ const IconPickerDropdown: React.FC = ({ value, onPickIcon } const intl = useIntl(); const title = intl.formatMessage(messages.emoji); - const forkAwesomeIcons = require('../forkawesome.json'); + const forkAwesomeIcons = require('./forkawesome.json'); return (
From 9635112f898145b4749ebef0c514037b170c7e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:40:11 +0100 Subject: [PATCH 23/64] nicolium: update some imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/ui/avatar.tsx | 3 ++- packages/nicolium/src/service-worker/sw.ts | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/nicolium/src/components/ui/avatar.tsx b/packages/nicolium/src/components/ui/avatar.tsx index 615836080..796de40a9 100644 --- a/packages/nicolium/src/components/ui/avatar.tsx +++ b/packages/nicolium/src/components/ui/avatar.tsx @@ -3,6 +3,7 @@ import { FastAverageColor } from 'fast-average-color'; import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import missingAvatar from '@/assets/images/avatar-missing.png'; import StillImage, { type IStillImage } from '@/components/still-image'; import { useSettings } from '@/stores/settings'; @@ -142,7 +143,7 @@ const Avatar: React.FC = (props) => { diff --git a/packages/nicolium/src/service-worker/sw.ts b/packages/nicolium/src/service-worker/sw.ts index 25aa1402e..d03cfe8f9 100644 --- a/packages/nicolium/src/service-worker/sw.ts +++ b/packages/nicolium/src/service-worker/sw.ts @@ -3,6 +3,10 @@ import IntlMessageFormat from 'intl-messageformat'; import 'intl-pluralrules'; import unescape from 'lodash/unescape'; +import iconExpand from '../assets/images/web-push/web-push-icon_expand.png'; +import iconFavourite from '../assets/images/web-push/web-push-icon_favourite.png'; +import iconReblog from '../assets/images/web-push/web-push-icon_reblog.png'; + import locales from './web-push-locales'; import type { @@ -230,21 +234,21 @@ const handlePush = (event: PushEvent) => { /** Native action to open a status on the device. */ const actionExpand = (preferred_locale: string) => ({ action: 'expand', - icon: `/${require('../assets/images/web-push/web-push-icon_expand.png')}`, + icon: `/${iconExpand}`, title: formatMessage('status.show_more', preferred_locale), }); /** Native action to repost status. */ const actionReblog = (preferred_locale: string) => ({ action: 'reblog', - icon: `/${require('../assets/images/web-push/web-push-icon_reblog.png')}`, + icon: `/${iconReblog}`, title: formatMessage('status.reblog', preferred_locale), }); /** Native action to like status. */ const actionFavourite = (preferred_locale: string) => ({ action: 'favourite', - icon: `/${require('../assets/images/web-push/web-push-icon_favourite.png')}`, + icon: `/${iconFavourite}`, title: formatMessage('status.favourite', preferred_locale), }); From ce1fb848ee6a5ce90104256693581fcbd57c02d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 17:50:39 +0100 Subject: [PATCH 24/64] nicolium: don't use require for imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/columns/notifications.tsx | 63 ++----- packages/nicolium/src/columns/timeline.tsx | 18 +- .../components/accounts/account-header.tsx | 12 +- .../accounts/account-hover-card.tsx | 12 +- .../accounts/account-local-time.tsx | 6 +- .../src/components/accounts/account-menu.tsx | 89 ++++++---- .../src/components/accounts/account.tsx | 5 +- .../src/components/accounts/action-button.tsx | 13 +- .../src/components/accounts/profile-field.tsx | 3 +- .../src/components/accounts/scrobble.tsx | 6 +- .../accounts/subscription-button.tsx | 8 +- .../accounts/verification-badge.tsx | 3 +- .../announcements/reactions-bar.tsx | 3 +- .../components/authorize-reject-buttons.tsx | 9 +- .../src/components/birthday-input.tsx | 10 +- .../dropdown-menu/dropdown-menu-item.tsx | 3 +- .../dropdown-menu/dropdown-menu.tsx | 6 +- .../nicolium/src/components/empty-message.tsx | 7 +- .../components/groups/group-header-image.tsx | 6 +- .../src/components/groups/group-header.tsx | 6 +- .../src/components/groups/group-list-item.tsx | 11 +- .../groups/group-member-list-item.tsx | 11 +- .../groups/group-options-button.tsx | 9 +- .../src/components/groups/group-privacy.tsx | 17 +- .../components/groups/group-relationship.tsx | 11 +- packages/nicolium/src/components/list.tsx | 3 +- packages/nicolium/src/components/load-gap.tsx | 3 +- .../src/components/location-search.tsx | 9 +- .../src/components/media/alt-indicator.tsx | 3 +- .../nicolium/src/components/media/audio.tsx | 23 +-- .../src/components/media/media-gallery.tsx | 11 +- .../nicolium/src/components/media/video.tsx | 33 ++-- .../components/navigation/compose-button.tsx | 5 +- .../navigation/dropdown-navigation.tsx | 93 ++++++---- .../navigation/sidebar-navigation.tsx | 151 ++++++++++------ .../navigation/thumb-navigation.tsx | 34 ++-- .../nicolium/src/components/notification.tsx | 53 ++++-- .../components/panels/instance-info-panel.tsx | 8 +- .../panels/instance-moderation-panel.tsx | 11 +- .../src/components/panels/new-event-panel.tsx | 8 +- .../components/panels/profile-info-panel.tsx | 29 ++-- .../src/components/panels/user-panel.tsx | 3 +- .../components/panels/who-to-follow-panel.tsx | 3 +- .../src/components/pending-items-row.tsx | 6 +- .../src/components/polls/poll-option.tsx | 11 +- .../nicolium/src/components/preview-card.tsx | 15 +- .../src/components/scroll-top-button.tsx | 3 +- .../nicolium/src/components/search-input.tsx | 8 +- .../statuses/events/event-action-button.tsx | 9 +- .../components/statuses/events/event-date.tsx | 3 +- .../statuses/events/event-header.tsx | 85 +++++---- .../statuses/events/event-preview.tsx | 6 +- .../statuses/quoted-status-indicator.tsx | 3 +- .../src/components/statuses/quoted-status.tsx | 3 +- .../src/components/statuses/rss-feed-info.tsx | 3 +- .../statuses/sensitive-content-overlay.tsx | 6 +- .../components/statuses/status-action-bar.tsx | 163 ++++++++++-------- .../components/statuses/status-content.tsx | 9 +- .../statuses/status-language-picker.tsx | 8 +- .../statuses/status-reactions-bar.tsx | 3 +- .../src/components/statuses/status.tsx | 29 ++-- .../components/statuses/translate-button.tsx | 9 +- .../src/components/timeline-picker.tsx | 38 ++-- .../nicolium/src/components/trending-link.tsx | 3 +- .../nicolium/src/components/ui/accordion.tsx | 15 +- .../nicolium/src/components/ui/avatar.tsx | 6 +- packages/nicolium/src/components/ui/card.tsx | 3 +- packages/nicolium/src/components/ui/input.tsx | 11 +- packages/nicolium/src/components/ui/modal.tsx | 9 +- .../src/components/ui/multiselect.tsx | 6 +- .../src/components/ui/streamfield.tsx | 3 +- packages/nicolium/src/components/ui/tag.tsx | 3 +- packages/nicolium/src/components/ui/toast.tsx | 14 +- .../nicolium/src/components/ui/widget.tsx | 3 +- .../src/components/upload-progress.tsx | 6 +- .../src/features/birthdays/account.tsx | 3 +- .../chats/components/chat-composer.tsx | 3 +- .../chats/components/chat-list-item.tsx | 9 +- .../chats/components/chat-message.tsx | 14 +- .../chats/components/chat-pane/chat-pane.tsx | 3 +- .../components/chat-search/chat-search.tsx | 8 +- .../features/chats/components/chat-upload.tsx | 3 +- .../chat-widget/chat-pane-header.tsx | 3 +- .../components/chat-widget/chat-settings.tsx | 3 +- .../components/chat-widget/chat-window.tsx | 11 +- .../headers/chat-search-header.tsx | 3 +- .../chat-widget/shoutbox-window.tsx | 3 +- .../chats-page/components/chats-page-chat.tsx | 12 +- .../chats-page/components/chats-page-new.tsx | 3 +- .../components/chats-page-settings.tsx | 3 +- .../components/chats-page-shoutbox.tsx | 3 +- .../components/chats-page-sidebar.tsx | 6 +- .../chats/components/shoutbox-composer.tsx | 3 +- .../components/upload-button.tsx | 7 +- .../compose-event/tabs/edit-event.tsx | 10 +- .../compose/components/compose-form.tsx | 15 +- .../components/content-type-button.tsx | 18 +- .../compose/components/drive-button.tsx | 3 +- .../components/interaction-policy-button.tsx | 3 +- .../compose/components/language-dropdown.tsx | 23 ++- .../compose/components/location-button.tsx | 3 +- .../compose/components/location-form.tsx | 10 +- .../compose/components/poll-button.tsx | 3 +- .../compose/components/privacy-dropdown.tsx | 39 +++-- .../compose/components/reply-indicator.tsx | 3 +- .../compose/components/schedule-button.tsx | 3 +- .../compose/components/schedule-form.tsx | 3 +- .../components/sensitive-media-button.tsx | 3 +- .../compose/components/upload-button.tsx | 8 +- .../containers/preview-compose-container.tsx | 9 +- .../compose/editor/nodes/image-component.tsx | 9 +- .../floating-block-type-toolbar-plugin.tsx | 6 +- .../plugins/floating-link-editor-plugin.tsx | 14 +- .../floating-text-format-toolbar-plugin.tsx | 59 ++++--- .../components/crypto-address.tsx | 3 +- .../emoji/components/emoji-picker.tsx | 3 +- .../emoji-picker-dropdown-container.tsx | 3 +- .../components/instance-restrictions.tsx | 31 ++-- .../components/restricted-instance.tsx | 10 +- .../status/components/detailed-status.tsx | 3 +- .../status/components/status-type-icon.tsx | 18 +- .../ui/components/profile-dropdown.tsx | 6 +- .../features/ui/components/theme-selector.tsx | 28 ++- .../src/hooks/use-timeline-filters-options.ts | 2 +- .../nicolium/src/layouts/group-layout.tsx | 6 +- .../src/modals/antenna-editor-modal.tsx | 5 +- packages/nicolium/src/modals/boost-modal.tsx | 7 +- .../compose-interaction-policy-modal.tsx | 7 +- .../src/modals/edit-bookmark-folder-modal.tsx | 3 +- .../nicolium/src/modals/event-map-modal.tsx | 17 +- .../list-adder-modal/components/list.tsx | 9 +- .../list-editor-modal/components/account.tsx | 6 +- .../list-editor-modal/components/search.tsx | 3 +- .../steps/confirmation-step.tsx | 6 +- packages/nicolium/src/modals/media-modal.tsx | 28 ++- .../src/modals/reply-mentions-modal.tsx | 9 +- .../report-modal/steps/other-actions-step.tsx | 6 +- .../modals/select-bookmark-folder-modal.tsx | 8 +- .../src/modals/select-drive-file-modal.tsx | 6 +- .../src/pages/account-lists/antennas.tsx | 17 +- .../src/pages/account-lists/circles.tsx | 6 +- .../src/pages/account-lists/lists.tsx | 6 +- .../src/pages/accounts/account-gallery.tsx | 6 +- .../pages/auth/components/consumer-button.tsx | 21 ++- .../auth/components/registration-form.tsx | 3 +- .../nicolium/src/pages/dashboard/account.tsx | 8 +- .../src/pages/dashboard/announcements.tsx | 3 +- .../src/pages/dashboard/dashboard.tsx | 3 +- .../nicolium/src/pages/dashboard/domains.tsx | 3 +- .../nicolium/src/pages/dashboard/report.tsx | 18 +- .../nicolium/src/pages/dashboard/reports.tsx | 3 +- .../nicolium/src/pages/dashboard/rules.tsx | 3 +- .../src/pages/dashboard/theme-editor.tsx | 9 +- .../src/pages/developers/developers.tsx | 36 ++-- .../pages/developers/service-worker-info.tsx | 6 +- packages/nicolium/src/pages/drive/drive.tsx | 69 ++++---- packages/nicolium/src/pages/fun/circle.tsx | 13 +- .../nicolium/src/pages/groups/edit-group.tsx | 8 +- packages/nicolium/src/pages/groups/groups.tsx | 3 +- packages/nicolium/src/pages/search/search.tsx | 14 +- .../nicolium/src/pages/settings/aliases.tsx | 9 +- .../src/pages/settings/auth-token-list.tsx | 3 +- .../settings/components/avatar-picker.tsx | 6 +- .../settings/components/header-picker.tsx | 6 +- .../src/pages/settings/domain-blocks.tsx | 3 +- .../pages/settings/rss-feed-subscriptions.tsx | 6 +- .../pages/status-lists/bookmark-folders.tsx | 9 +- .../src/pages/status-lists/bookmarks.tsx | 14 +- .../src/pages/status-lists/events.tsx | 12 +- .../status-lists/interaction-requests.tsx | 9 +- .../src/pages/statuses/event-information.tsx | 9 +- .../nicolium/src/pages/statuses/status.tsx | 20 +-- .../src/pages/timelines/antenna-timeline.tsx | 17 +- .../src/pages/timelines/bubble-timeline.tsx | 11 +- .../src/pages/timelines/circle-timeline.tsx | 17 +- .../pages/timelines/community-timeline.tsx | 11 +- .../src/pages/timelines/group-timeline.tsx | 3 +- .../src/pages/timelines/hashtag-timeline.tsx | 8 +- .../src/pages/timelines/home-timeline.tsx | 11 +- .../src/pages/timelines/landing-timeline.tsx | 3 +- .../src/pages/timelines/link-timeline.tsx | 3 +- .../src/pages/timelines/list-timeline.tsx | 17 +- .../src/pages/timelines/public-timeline.tsx | 14 +- .../src/pages/timelines/remote-timeline.tsx | 14 +- .../src/pages/timelines/wrenched-timeline.tsx | 11 +- 185 files changed, 1271 insertions(+), 1145 deletions(-) diff --git a/packages/nicolium/src/columns/notifications.tsx b/packages/nicolium/src/columns/notifications.tsx index 87a4a7689..57ffdaf38 100644 --- a/packages/nicolium/src/columns/notifications.tsx +++ b/packages/nicolium/src/columns/notifications.tsx @@ -1,9 +1,16 @@ +import iconAt from '@phosphor-icons/core/regular/at.svg'; +import iconBellSimpleRinging from '@phosphor-icons/core/regular/bell-simple-ringing.svg'; +import iconCalendarDots from '@phosphor-icons/core/regular/calendar-dots.svg'; +import iconChartBar from '@phosphor-icons/core/regular/chart-bar.svg'; + +import '@/styles/new/notifications.scss'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; +import iconStar from '@phosphor-icons/core/regular/star.svg'; +import iconUserPlus from '@phosphor-icons/core/regular/user-plus.svg'; import { useQueryClient } from '@tanstack/react-query'; import clsx from 'clsx'; import debounce from 'lodash/debounce'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; - -import '@/styles/new/notifications.scss'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { saveSettings } from '@/actions/settings'; @@ -89,84 +96,46 @@ const FilterBar = () => { }); } else { items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.mentions), action: onClick('mention'), name: 'mention', }); if (features.accountNotifies) items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.statuses), action: onClick('status'), name: 'status', }); items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.favourites), action: onClick('favourite'), name: 'favourite', }); items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.boosts), action: onClick('reblog'), name: 'reblog', }); if (features.polls) items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.polls), action: onClick('poll'), name: 'poll', }); if (features.events) items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.events), action: onClick('events'), name: 'events', }); items.push({ - text: ( - - ), + text: , title: intl.formatMessage(messages.follows), action: onClick('follow'), name: 'follow', diff --git a/packages/nicolium/src/columns/timeline.tsx b/packages/nicolium/src/columns/timeline.tsx index 234b6c426..e99a84c40 100644 --- a/packages/nicolium/src/columns/timeline.tsx +++ b/packages/nicolium/src/columns/timeline.tsx @@ -1,3 +1,7 @@ +import iconArrowLineDown from '@phosphor-icons/core/regular/arrow-line-down.svg'; +import iconCaretDoubleDown from '@phosphor-icons/core/regular/caret-double-down.svg'; +import iconCaretDoubleUp from '@phosphor-icons/core/regular/caret-double-up.svg'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useMemo, useRef, useState } from 'react'; @@ -64,7 +68,7 @@ const messages = defineMessages({ const SkipPinned: React.FC> = ({ onClick }) => { return (
@@ -250,13 +254,7 @@ const TimelineStatusInfo: React.FC = ({ status, rebloggedBy - } + icon={} text={ // status.visibility === 'private' ? ( // = ({ from, to }) => (
- +

= ({ account }) => { if (account.accepts_chat_messages) { return ( { createAndNavigateToChat.mutate(account.id); }} @@ -277,7 +281,7 @@ const AccountHeader: React.FC = ({ account }) => { return ( = ({ account }) => { return ( = ({ visible = true }) => { {account.local ? (

- + = ({ visible = true }) => { {account.pronouns.length > 0 && (
- + = ({ accountId, field }) => className='mt-1 flex items-center gap-0.5' title={intl.formatMessage(messages.timezone, { timezone: field.value })} > - + {localTime} {me !== accountId && isTimezoneEqual && ( diff --git a/packages/nicolium/src/components/accounts/account-menu.tsx b/packages/nicolium/src/components/accounts/account-menu.tsx index 176efbb03..4d519742b 100644 --- a/packages/nicolium/src/components/accounts/account-menu.tsx +++ b/packages/nicolium/src/components/accounts/account-menu.tsx @@ -1,3 +1,25 @@ +import iconArrowSquareOut from '@phosphor-icons/core/regular/arrow-square-out.svg'; +import iconArrowsClockwise from '@phosphor-icons/core/regular/arrows-clockwise.svg'; +import iconAt from '@phosphor-icons/core/regular/at.svg'; +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; +import iconEnvelopeSimple from '@phosphor-icons/core/regular/envelope-simple.svg'; +import iconExport from '@phosphor-icons/core/regular/export.svg'; +import iconFlag from '@phosphor-icons/core/regular/flag.svg'; +import iconGavel from '@phosphor-icons/core/regular/gavel.svg'; +import iconLinkSimpleHorizontal from '@phosphor-icons/core/regular/link-simple-horizontal.svg'; +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; +import iconMagnifyingGlass from '@phosphor-icons/core/regular/magnifying-glass.svg'; +import iconNotePencil from '@phosphor-icons/core/regular/note-pencil.svg'; +import iconProhibit from '@phosphor-icons/core/regular/prohibit.svg'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; +import iconRss from '@phosphor-icons/core/regular/rss.svg'; +import iconSlidersHorizontal from '@phosphor-icons/core/regular/sliders-horizontal.svg'; +import iconSpeakerSimpleX from '@phosphor-icons/core/regular/speaker-simple-x.svg'; +import iconTag from '@phosphor-icons/core/regular/tag.svg'; +import iconTooth from '@phosphor-icons/core/regular/tooth.svg'; +import iconUserCheck from '@phosphor-icons/core/regular/user-check.svg'; +import iconUserMinus from '@phosphor-icons/core/regular/user-minus.svg'; +import iconUser from '@phosphor-icons/core/regular/user.svg'; import { GOTOSOCIAL, MASTODON } from 'pl-api'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -332,7 +354,7 @@ const AccountMenu: React.FC = ({ account }) => { if (features.rssFeeds && account.local && (software !== GOTOSOCIAL || account.enable_rss)) { menu.push({ text: intl.formatMessage(messages.subscribeFeed), - icon: require('@phosphor-icons/core/regular/rss.svg'), + icon: iconRss, href: software === MASTODON ? `${account.url}.rss` : `${account.url}/feed.rss`, target: '_blank', }); @@ -342,7 +364,7 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.share, { name: account.username }), action: handleShare, - icon: require('@phosphor-icons/core/regular/export.svg'), + icon: iconExport, }); } @@ -352,14 +374,14 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.profileExternal, { domain }), href: account.url, - icon: require('@phosphor-icons/core/regular/arrow-square-out.svg'), + icon: iconArrowSquareOut, }); } menu.push({ text: intl.formatMessage(messages.copy), action: handleCopy, - icon: require('@phosphor-icons/core/regular/link-simple-horizontal.svg'), + icon: iconLinkSimpleHorizontal, }); if (!ownAccount) return menu; @@ -372,7 +394,7 @@ const AccountMenu: React.FC = ({ account }) => { ), to: '/search', search: { type: 'statuses', accountId: account.id }, - icon: require('@phosphor-icons/core/regular/magnifying-glass.svg'), + icon: iconMagnifyingGlass, }); } @@ -384,36 +406,36 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.editProfile), to: '/settings/profile', - icon: require('@phosphor-icons/core/regular/user.svg'), + icon: iconUser, }); menu.push({ text: intl.formatMessage(messages.preferences), to: '/settings', - icon: require('@phosphor-icons/core/regular/sliders-horizontal.svg'), + icon: iconSlidersHorizontal, }); menu.push(null); menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes', - icon: require('@phosphor-icons/core/regular/speaker-simple-x.svg'), + icon: iconSpeakerSimpleX, }); menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks', - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: account.username }), action: onMention, - icon: require('@phosphor-icons/core/regular/at.svg'), + icon: iconAt, }); if (features.privacyScopes) { menu.push({ text: intl.formatMessage(messages.direct, { name: account.username }), action: onDirect, - icon: require('@phosphor-icons/core/regular/envelope-simple.svg'), + icon: iconEnvelopeSimple, }); } @@ -422,13 +444,13 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.username }), action: onReblogToggle, - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, }); } else { menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.username }), action: onReblogToggle, - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, }); } @@ -436,7 +458,7 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.addOrRemoveFromList), action: onAddToList, - icon: require('@phosphor-icons/core/regular/list-bullets.svg'), + icon: iconListBullets, }); } @@ -446,16 +468,14 @@ const AccountMenu: React.FC = ({ account }) => { account.relationship?.endorsed ? messages.unendorse : messages.endorse, ), action: onEndorseToggle, - icon: account.relationship?.endorsed - ? require('@phosphor-icons/core/regular/user-minus.svg') - : require('@phosphor-icons/core/regular/user-check.svg'), + icon: account.relationship?.endorsed ? iconUserMinus : iconUserCheck, }); } } else if (features.lists && features.unrestrictedLists) { menu.push({ text: intl.formatMessage(messages.addOrRemoveFromList), action: onAddToList, - icon: require('@phosphor-icons/core/regular/list-bullets.svg'), + icon: iconListBullets, }); } @@ -463,7 +483,7 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.bite, { name: account.username }), action: onBite, - icon: require('@phosphor-icons/core/regular/tooth.svg'), + icon: iconTooth, }); } @@ -471,7 +491,7 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.loadActivities), action: onLoadActivities, - icon: require('@phosphor-icons/core/regular/arrows-clockwise.svg'), + icon: iconArrowsClockwise, }); } @@ -479,14 +499,14 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.note, { name: account.acct }), action: onEditNote, - icon: require('@phosphor-icons/core/regular/note-pencil.svg'), + icon: iconNotePencil, }); } menu.push({ text: intl.formatMessage(messages.nickname, { name: account.acct }), action: onEditNickname, - icon: require('@phosphor-icons/core/regular/tag.svg'), + icon: iconTag, }); menu.push(null); @@ -495,7 +515,7 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.removeFromFollowers), action: onRemoveFromFollowers, - icon: require('@phosphor-icons/core/regular/user-minus.svg'), + icon: iconUserMinus, }); } @@ -503,13 +523,13 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.unmute, { name: account.username }), action: onMute, - icon: require('@phosphor-icons/core/regular/speaker-simple-x.svg'), + icon: iconSpeakerSimpleX, }); } else { menu.push({ text: intl.formatMessage(messages.mute, { name: account.username }), action: onMute, - icon: require('@phosphor-icons/core/regular/speaker-simple-x.svg'), + icon: iconSpeakerSimpleX, }); } @@ -517,20 +537,20 @@ const AccountMenu: React.FC = ({ account }) => { menu.push({ text: intl.formatMessage(messages.unblock, { name: account.username }), action: onBlock, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } else { menu.push({ text: intl.formatMessage(messages.block, { name: account.username }), action: onBlock, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } menu.push({ text: intl.formatMessage(messages.report, { name: account.username }), action: onReport, - icon: require('@phosphor-icons/core/regular/flag.svg'), + icon: iconFlag, }); } @@ -545,7 +565,7 @@ const AccountMenu: React.FC = ({ account }) => { action: () => { onUnblockDomain(domain); }, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } else { menu.push({ @@ -553,7 +573,7 @@ const AccountMenu: React.FC = ({ account }) => { action: () => { onBlockDomain(domain); }, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } } @@ -565,7 +585,7 @@ const AccountMenu: React.FC = ({ account }) => { text: intl.formatMessage(messages.adminAccount, { name: account.username }), to: '/nicolium/admin/accounts/$accountId', params: { accountId: account.id }, - icon: require('@phosphor-icons/core/regular/gavel.svg'), + icon: iconGavel, }); } @@ -578,12 +598,7 @@ const AccountMenu: React.FC = ({ account }) => { return ( - + ); }; diff --git a/packages/nicolium/src/components/accounts/account.tsx b/packages/nicolium/src/components/accounts/account.tsx index ca4ea12ff..56609a2d9 100644 --- a/packages/nicolium/src/components/accounts/account.tsx +++ b/packages/nicolium/src/components/accounts/account.tsx @@ -1,3 +1,4 @@ +import iconLock from '@phosphor-icons/core/regular/lock.svg'; import { Link, linkOptions, useNavigate, useRouter } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useLayoutEffect, useRef, useState } from 'react'; @@ -311,7 +312,7 @@ const Account = ({ {withLocked && !timestamp && account.locked && ( <> @@ -423,7 +424,7 @@ const Account = ({ {withLocked && !timestamp && account.locked && ( <> diff --git a/packages/nicolium/src/components/accounts/action-button.tsx b/packages/nicolium/src/components/accounts/action-button.tsx index 32d313ed5..a12889088 100644 --- a/packages/nicolium/src/components/accounts/action-button.tsx +++ b/packages/nicolium/src/components/accounts/action-button.tsx @@ -1,3 +1,6 @@ +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; +import iconProhibit from '@phosphor-icons/core/regular/prohibit.svg'; +import iconTooth from '@phosphor-icons/core/regular/tooth.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -212,7 +215,7 @@ const ActionButton: React.FC = ({ account, actionType, small = tr /> } onClick={handleBite} - icon={require('@phosphor-icons/core/regular/tooth.svg')} + icon={iconTooth} /> ); }; @@ -243,7 +246,7 @@ const ActionButton: React.FC = ({ account, actionType, small = tr return ( )} diff --git a/packages/nicolium/src/components/authorize-reject-buttons.tsx b/packages/nicolium/src/components/authorize-reject-buttons.tsx index f39a5beec..c4809f42b 100644 --- a/packages/nicolium/src/components/authorize-reject-buttons.tsx +++ b/packages/nicolium/src/components/authorize-reject-buttons.tsx @@ -1,3 +1,6 @@ +import iconStopFill from '@phosphor-icons/core/fill/stop-fill.svg'; +import iconCheck from '@phosphor-icons/core/regular/check.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import clsx from 'clsx'; import React, { useEffect, useRef, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -129,7 +132,7 @@ const AuthorizeRejectButtons: React.FC = ({
= ({ /> = ({ })} > = ({ value, onChange, required }) = ({ value, onChange, required }) = ({ value, onChange, required }) = ({ value, onChange, required }) diff --git a/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx b/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx index d13021616..7e38f901d 100644 --- a/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx +++ b/packages/nicolium/src/components/dropdown-menu/dropdown-menu.tsx @@ -8,6 +8,8 @@ import { size, useFloating, } from '@floating-ui/react'; +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; import clsx from 'clsx'; import { supportsPassiveEvents } from 'detect-passive-events'; import React, { useEffect, useMemo, useRef, useState } from 'react'; @@ -201,7 +203,7 @@ const DropdownMenuContent: React.FC = ({
= (props) => { onOpen, onShiftClick, placement: initialPlacement = 'top', - src = require('@phosphor-icons/core/regular/dots-three.svg'), + src = iconDotsThree, title = 'Menu', width, className, diff --git a/packages/nicolium/src/components/empty-message.tsx b/packages/nicolium/src/components/empty-message.tsx index 0eec37e0b..53e30a21f 100644 --- a/packages/nicolium/src/components/empty-message.tsx +++ b/packages/nicolium/src/components/empty-message.tsx @@ -1,3 +1,4 @@ +import iconEmpty from '@phosphor-icons/core/regular/empty.svg'; import React from 'react'; import Icon from './ui/icon'; @@ -8,11 +9,7 @@ interface IEmptyMessage { icon?: string | false; } -const EmptyMessage: React.FC = ({ - heading, - text, - icon = require('@phosphor-icons/core/regular/empty.svg'), -}) => ( +const EmptyMessage: React.FC = ({ heading, text, icon = iconEmpty }) => (
{icon !== false && } diff --git a/packages/nicolium/src/components/groups/group-header-image.tsx b/packages/nicolium/src/components/groups/group-header-image.tsx index 416d55d72..afa7a0256 100644 --- a/packages/nicolium/src/components/groups/group-header-image.tsx +++ b/packages/nicolium/src/components/groups/group-header-image.tsx @@ -1,3 +1,4 @@ +import iconImageSquare from '@phosphor-icons/core/regular/image-square.svg'; import clsx from 'clsx'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -32,10 +33,7 @@ const GroupHeaderImage: React.FC = ({ className, group }) => 'flex items-center justify-center bg-gray-200 dark:bg-gray-800/30', )} > - +
); } diff --git a/packages/nicolium/src/components/groups/group-header.tsx b/packages/nicolium/src/components/groups/group-header.tsx index 5f0f0288b..e41304f43 100644 --- a/packages/nicolium/src/components/groups/group-header.tsx +++ b/packages/nicolium/src/components/groups/group-header.tsx @@ -1,3 +1,4 @@ +import iconImageSquare from '@phosphor-icons/core/regular/image-square.svg'; import { mediaAttachmentSchema } from 'pl-api'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -118,10 +119,7 @@ const GroupHeader: React.FC = ({ group }) => { className='flex h-32 w-full items-center justify-center bg-gray-200 dark:bg-gray-800/30 md:rounded-t-xl lg:h-52' > {isHeaderMissing ? ( - + ) : ( header )} diff --git a/packages/nicolium/src/components/groups/group-list-item.tsx b/packages/nicolium/src/components/groups/group-list-item.tsx index 312307279..f8c4c3e5f 100644 --- a/packages/nicolium/src/components/groups/group-list-item.tsx +++ b/packages/nicolium/src/components/groups/group-list-item.tsx @@ -1,3 +1,5 @@ +import iconGlobe from '@phosphor-icons/core/regular/globe.svg'; +import iconLock from '@phosphor-icons/core/regular/lock.svg'; import { Link } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -38,14 +40,7 @@ const GroupListItem: React.FC = ({ groupId, withJoinAction = tru
- + {group.locked ? ( diff --git a/packages/nicolium/src/components/groups/group-member-list-item.tsx b/packages/nicolium/src/components/groups/group-member-list-item.tsx index 1366d02d8..5f407eea0 100644 --- a/packages/nicolium/src/components/groups/group-member-list-item.tsx +++ b/packages/nicolium/src/components/groups/group-member-list-item.tsx @@ -1,3 +1,6 @@ +import iconProhibit from '@phosphor-icons/core/regular/prohibit.svg'; +import iconSuitcase from '@phosphor-icons/core/regular/suitcase.svg'; +import iconUserMinus from '@phosphor-icons/core/regular/user-minus.svg'; import clsx from 'clsx'; import { GroupRoles } from 'pl-api'; import React, { useMemo } from 'react'; @@ -159,7 +162,7 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { if (isMemberUser) { items.push({ text: intl.formatMessage(messages.groupModPromoteMod, { role: GroupRoles.ADMIN }), - icon: require('@phosphor-icons/core/regular/suitcase.svg'), + icon: iconSuitcase, action: handleAdminAssignment, }); } else if (isMemberAdmin) { @@ -168,7 +171,7 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { role: GroupRoles.ADMIN, name: account.username, }), - icon: require('@phosphor-icons/core/regular/suitcase.svg'), + icon: iconSuitcase, action: handleUserAssignment, destructive: true, }); @@ -182,13 +185,13 @@ const GroupMemberListItem = ({ member, group }: IGroupMemberListItem) => { ) { items.push({ text: intl.formatMessage(messages.groupModKick, { name: account.username }), - icon: require('@phosphor-icons/core/regular/user-minus.svg'), + icon: iconUserMinus, action: handleKickFromGroup, }); items.push({ text: intl.formatMessage(messages.groupModBlock, { name: account.username }), - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, action: handleBlockFromGroup, destructive: true, }); diff --git a/packages/nicolium/src/components/groups/group-options-button.tsx b/packages/nicolium/src/components/groups/group-options-button.tsx index 9dc3dfdb7..b2df06703 100644 --- a/packages/nicolium/src/components/groups/group-options-button.tsx +++ b/packages/nicolium/src/components/groups/group-options-button.tsx @@ -1,3 +1,6 @@ +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; +import iconExport from '@phosphor-icons/core/regular/export.svg'; +import iconSignOut from '@phosphor-icons/core/regular/sign-out.svg'; import { GroupRoles, type Group } from 'pl-api'; import React, { useMemo } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -67,7 +70,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { if (canShare) { items.push({ text: intl.formatMessage(messages.share), - icon: require('@phosphor-icons/core/regular/export.svg'), + icon: iconExport, action: handleShare, }); } @@ -76,7 +79,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { items.push(null); items.push({ text: intl.formatMessage(messages.leave), - icon: require('@phosphor-icons/core/regular/sign-out.svg'), + icon: iconSignOut, action: handleLeave, }); } @@ -91,7 +94,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { return ( (
@@ -54,14 +52,7 @@ const GroupPrivacy = ({ group }: IGroupPolicy) => ( } >
- + {group.locked ? ( diff --git a/packages/nicolium/src/components/groups/group-relationship.tsx b/packages/nicolium/src/components/groups/group-relationship.tsx index 3b113cc71..6c881a3fb 100644 --- a/packages/nicolium/src/components/groups/group-relationship.tsx +++ b/packages/nicolium/src/components/groups/group-relationship.tsx @@ -1,3 +1,5 @@ +import iconGavel from '@phosphor-icons/core/regular/gavel.svg'; +import iconUsers from '@phosphor-icons/core/regular/users.svg'; import { GroupRoles, type Group } from 'pl-api'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -22,14 +24,7 @@ const GroupRelationship = ({ group }: IGroupRelationship) => { data-testid='group-relationship' className='flex items-center gap-1 text-primary-600 dark:text-primary-400' > - + {isOwner ? ( diff --git a/packages/nicolium/src/components/list.tsx b/packages/nicolium/src/components/list.tsx index 1fe3eb383..d5f3b3bbe 100644 --- a/packages/nicolium/src/components/list.tsx +++ b/packages/nicolium/src/components/list.tsx @@ -1,3 +1,4 @@ +import iconCaretRight from '@phosphor-icons/core/regular/caret-right.svg'; import { Link, type LinkOptions } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useState } from 'react'; @@ -105,7 +106,7 @@ const ListItem: React.FC = ({
{children} - +
) : null} diff --git a/packages/nicolium/src/components/load-gap.tsx b/packages/nicolium/src/components/load-gap.tsx index b604eba85..82b3af2db 100644 --- a/packages/nicolium/src/components/load-gap.tsx +++ b/packages/nicolium/src/components/load-gap.tsx @@ -1,3 +1,4 @@ +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -27,7 +28,7 @@ const LoadGap: React.FC = ({ disabled, maxId, onClick }) => { onClick={handleClick} aria-label={intl.formatMessage(messages.loadMore)} > - + ); }; diff --git a/packages/nicolium/src/components/location-search.tsx b/packages/nicolium/src/components/location-search.tsx index d7b70dcb5..62ae944a0 100644 --- a/packages/nicolium/src/components/location-search.tsx +++ b/packages/nicolium/src/components/location-search.tsx @@ -1,3 +1,5 @@ +import iconBackspace from '@phosphor-icons/core/regular/backspace.svg'; +import iconMagnifyingGlass from '@phosphor-icons/core/regular/magnifying-glass.svg'; import { useDebounce } from '@uidotdev/usehooks'; import clsx from 'clsx'; import React, { useState } from 'react'; @@ -81,13 +83,10 @@ const LocationSearch: React.FC = ({ id, onSelected }) => { title={intl.formatMessage(messages.clear)} > - +
); diff --git a/packages/nicolium/src/components/media/alt-indicator.tsx b/packages/nicolium/src/components/media/alt-indicator.tsx index abaa289e3..504ddfd46 100644 --- a/packages/nicolium/src/components/media/alt-indicator.tsx +++ b/packages/nicolium/src/components/media/alt-indicator.tsx @@ -1,3 +1,4 @@ +import iconWarning from '@phosphor-icons/core/regular/warning.svg'; import clsx from 'clsx'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -12,7 +13,7 @@ interface IAltIndicator extends Pick, 'tit const AltIndicator: React.FC = React.forwardRef( ({ className, warning, message, ...props }, ref) => ( - {warning && } + {warning && } {message ?? ( )} diff --git a/packages/nicolium/src/components/media/audio.tsx b/packages/nicolium/src/components/media/audio.tsx index 1320fc140..15705828b 100644 --- a/packages/nicolium/src/components/media/audio.tsx +++ b/packages/nicolium/src/components/media/audio.tsx @@ -1,3 +1,8 @@ +import iconDownloadSimple from '@phosphor-icons/core/regular/download-simple.svg'; +import iconPause from '@phosphor-icons/core/regular/pause.svg'; +import iconPlay from '@phosphor-icons/core/regular/play.svg'; +import iconSpeakerHigh from '@phosphor-icons/core/regular/speaker-high.svg'; +import iconSpeakerX from '@phosphor-icons/core/regular/speaker-x.svg'; import clsx from 'clsx'; import debounce from 'lodash/debounce'; import throttle from 'lodash/throttle'; @@ -554,13 +559,7 @@ const Audio: React.FC = (props) => { className={clsx('player-button', fullscreen && 'py-2.5')} onClick={togglePlay} > - +
= (props) => { download target='_blank' > - +
diff --git a/packages/nicolium/src/components/media/media-gallery.tsx b/packages/nicolium/src/components/media/media-gallery.tsx index 88d933a89..88b3aa4b4 100644 --- a/packages/nicolium/src/components/media/media-gallery.tsx +++ b/packages/nicolium/src/components/media/media-gallery.tsx @@ -1,3 +1,5 @@ +import iconPaperclip from '@phosphor-icons/core/regular/paperclip.svg'; +import iconSpeakerHigh from '@phosphor-icons/core/regular/speaker-high.svg'; import clsx from 'clsx'; import React, { useState, useRef, useLayoutEffect, type CSSProperties } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -172,10 +174,7 @@ const Item: React.FC = ({ const attachmentIcon = ( ); @@ -277,7 +276,7 @@ const Item: React.FC = ({ title={attachment.description} > - + {ext} @@ -385,7 +384,7 @@ const MediaGallery: React.FC = (props) => { src={ MIMETYPE_ICONS[ (attachment.type === 'unknown' && attachment.mime_type) || attachment.type - ] ?? require('@phosphor-icons/core/regular/paperclip.svg') + ] ?? iconPaperclip } /> diff --git a/packages/nicolium/src/components/media/video.tsx b/packages/nicolium/src/components/media/video.tsx index b5d5252e0..e8c82527b 100644 --- a/packages/nicolium/src/components/media/video.tsx +++ b/packages/nicolium/src/components/media/video.tsx @@ -1,3 +1,10 @@ +import iconArrowsInSimple from '@phosphor-icons/core/regular/arrows-in-simple.svg'; +import iconArrowsOutSimple from '@phosphor-icons/core/regular/arrows-out-simple.svg'; +import iconDownloadSimple from '@phosphor-icons/core/regular/download-simple.svg'; +import iconPause from '@phosphor-icons/core/regular/pause.svg'; +import iconPlay from '@phosphor-icons/core/regular/play.svg'; +import iconSpeakerHigh from '@phosphor-icons/core/regular/speaker-high.svg'; +import iconSpeakerX from '@phosphor-icons/core/regular/speaker-x.svg'; import clsx from 'clsx'; import debounce from 'lodash/debounce'; import throttle from 'lodash/throttle'; @@ -566,13 +573,7 @@ const Video: React.FC = ({ onClick={togglePlay} autoFocus={autoFocus} > - +
= ({ download target='_blank' > - +
diff --git a/packages/nicolium/src/components/navigation/compose-button.tsx b/packages/nicolium/src/components/navigation/compose-button.tsx index a146c6a9f..b2613a6f0 100644 --- a/packages/nicolium/src/components/navigation/compose-button.tsx +++ b/packages/nicolium/src/components/navigation/compose-button.tsx @@ -1,3 +1,4 @@ +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; import { useMatch } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -36,7 +37,7 @@ const HomeComposeButton: React.FC = ({ shrink }) => { return ( {switcher && } @@ -526,7 +553,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => <> @@ -540,7 +567,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => {features.bubbleTimeline && timelineAccess.live_feeds.bubble === 'public' && ( } onClick={closeSidebar} /> @@ -549,7 +576,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => {features.federating && timelineAccess.live_feeds.remote === 'public' && ( } onClick={closeSidebar} /> @@ -558,7 +585,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => {features.wrenchedTimeline && timelineAccess.live_feeds.wrenched === 'public' && ( } onClick={closeSidebar} /> @@ -570,7 +597,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => } onClick={closeSidebar} /> @@ -578,7 +605,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => {isOpen && ( } onClick={closeSidebar} /> @@ -588,7 +615,7 @@ const DropdownNavigation: React.FC = React.memo((): React.JSX.Element | null => } onClick={closeSidebar} /> diff --git a/packages/nicolium/src/components/navigation/sidebar-navigation.tsx b/packages/nicolium/src/components/navigation/sidebar-navigation.tsx index e970e0f2d..0fa829802 100644 --- a/packages/nicolium/src/components/navigation/sidebar-navigation.tsx +++ b/packages/nicolium/src/components/navigation/sidebar-navigation.tsx @@ -1,3 +1,52 @@ +import iconBellSimpleFill from '@phosphor-icons/core/fill/bell-simple-fill.svg'; +import iconChatsTeardropFill from '@phosphor-icons/core/fill/chats-teardrop-fill.svg'; +import iconCloudFill from '@phosphor-icons/core/fill/cloud-fill.svg'; +import iconEnvelopeSimpleFill from '@phosphor-icons/core/fill/envelope-simple-fill.svg'; +import iconFediverseLogoFill from '@phosphor-icons/core/fill/fediverse-logo-fill.svg'; +import iconGaugeFill from '@phosphor-icons/core/fill/gauge-fill.svg'; +import iconGraphFill from '@phosphor-icons/core/fill/graph-fill.svg'; +import iconHouseFill from '@phosphor-icons/core/fill/house-fill.svg'; +import iconMagnifyingGlassFill from '@phosphor-icons/core/fill/magnifying-glass-fill.svg'; +import iconPlanetFill from '@phosphor-icons/core/fill/planet-fill.svg'; +import iconSignInFill from '@phosphor-icons/core/fill/sign-in-fill.svg'; +import iconSlidersHorizontalFill from '@phosphor-icons/core/fill/sliders-horizontal-fill.svg'; +import iconUserFill from '@phosphor-icons/core/fill/user-fill.svg'; +import iconUserPlusFill from '@phosphor-icons/core/fill/user-plus-fill.svg'; +import iconUsersThreeFill from '@phosphor-icons/core/fill/users-three-fill.svg'; +import iconWrenchFill from '@phosphor-icons/core/fill/wrench-fill.svg'; +import iconAddressBook from '@phosphor-icons/core/regular/address-book.svg'; +import iconBellSimple from '@phosphor-icons/core/regular/bell-simple.svg'; +import iconBookOpen from '@phosphor-icons/core/regular/book-open.svg'; +import iconBookmarks from '@phosphor-icons/core/regular/bookmarks.svg'; +import iconBroadcast from '@phosphor-icons/core/regular/broadcast.svg'; +import iconCalendarDots from '@phosphor-icons/core/regular/calendar-dots.svg'; +import iconCaretDown from '@phosphor-icons/core/regular/caret-down.svg'; +import iconChatsTeardrop from '@phosphor-icons/core/regular/chats-teardrop.svg'; +import iconCirclesThree from '@phosphor-icons/core/regular/circles-three.svg'; +import iconCloud from '@phosphor-icons/core/regular/cloud.svg'; +import iconCode from '@phosphor-icons/core/regular/code.svg'; +import iconDotsThreeCircle from '@phosphor-icons/core/regular/dots-three-circle.svg'; +import iconEnvelopeSimple from '@phosphor-icons/core/regular/envelope-simple.svg'; +import iconFediverseLogo from '@phosphor-icons/core/regular/fediverse-logo.svg'; +import iconGauge from '@phosphor-icons/core/regular/gauge.svg'; +import iconGraph from '@phosphor-icons/core/regular/graph.svg'; +import iconHash from '@phosphor-icons/core/regular/hash.svg'; +import iconHeartHalf from '@phosphor-icons/core/regular/heart-half.svg'; +import iconHourglass from '@phosphor-icons/core/regular/hourglass.svg'; +import iconHouse from '@phosphor-icons/core/regular/house.svg'; +import iconKeyboard from '@phosphor-icons/core/regular/keyboard.svg'; +import iconListDashes from '@phosphor-icons/core/regular/list-dashes.svg'; +import iconMagnifyingGlass from '@phosphor-icons/core/regular/magnifying-glass.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconPlanet from '@phosphor-icons/core/regular/planet.svg'; +import iconQuestion from '@phosphor-icons/core/regular/question.svg'; +import iconRss from '@phosphor-icons/core/regular/rss.svg'; +import iconSignIn from '@phosphor-icons/core/regular/sign-in.svg'; +import iconSlidersHorizontal from '@phosphor-icons/core/regular/sliders-horizontal.svg'; +import iconUserPlus from '@phosphor-icons/core/regular/user-plus.svg'; +import iconUser from '@phosphor-icons/core/regular/user.svg'; +import iconUsersThree from '@phosphor-icons/core/regular/users-three.svg'; +import iconWrench from '@phosphor-icons/core/regular/wrench.svg'; import { useInfiniteQuery } from '@tanstack/react-query'; import clsx from 'clsx'; import React, { useMemo } from 'react'; @@ -101,7 +150,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/conversations', text: intl.formatMessage(messages.conversations), - icon: require('@phosphor-icons/core/regular/envelope-simple.svg'), + icon: iconEnvelopeSimple, }); } @@ -109,7 +158,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/follow_requests', text: intl.formatMessage(messages.followRequests), - icon: require('@phosphor-icons/core/regular/user-plus.svg'), + icon: iconUserPlus, count: followRequestsCount, }); } @@ -118,7 +167,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/interaction_requests', text: intl.formatMessage(messages.interactionRequests), - icon: require('@phosphor-icons/core/regular/heart-half.svg'), + icon: iconHeartHalf, count: interactionRequestsCount, }); } @@ -127,7 +176,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/bookmarks', text: intl.formatMessage(messages.bookmarks), - icon: require('@phosphor-icons/core/regular/bookmarks.svg'), + icon: iconBookmarks, }); } @@ -135,7 +184,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/lists', text: intl.formatMessage(messages.lists), - icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + icon: iconListDashes, }); } @@ -143,7 +192,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/circles', text: intl.formatMessage(messages.circles), - icon: require('@phosphor-icons/core/regular/circles-three.svg'), + icon: iconCirclesThree, }); } @@ -151,7 +200,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/antennas', text: intl.formatMessage({ id: 'column.antennas', defaultMessage: 'Antennas' }), - icon: require('@phosphor-icons/core/regular/broadcast.svg'), + icon: iconBroadcast, }); } @@ -159,7 +208,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/events', text: intl.formatMessage(messages.events), - icon: require('@phosphor-icons/core/regular/calendar-dots.svg'), + icon: iconCalendarDots, }); } @@ -167,7 +216,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/directory', text: intl.formatMessage(messages.profileDirectory), - icon: require('@phosphor-icons/core/regular/address-book.svg'), + icon: iconAddressBook, }); } @@ -175,7 +224,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/followed_tags', text: intl.formatMessage(messages.followedTags), - icon: require('@phosphor-icons/core/regular/hash.svg'), + icon: iconHash, }); } @@ -183,14 +232,14 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push({ to: '/rss_feed_subscriptions', text: intl.formatMessage(messages.rssFeedSubscriptions), - icon: require('@phosphor-icons/core/regular/rss.svg'), + icon: iconRss, }); } if (scheduledStatusCount > 0) { menu.push({ to: '/scheduled_statuses', - icon: require('@phosphor-icons/core/regular/hourglass.svg'), + icon: iconHourglass, text: intl.formatMessage(messages.scheduledStatuses), count: scheduledStatusCount, }); @@ -199,7 +248,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) if (draftCount > 0) { menu.push({ to: '/draft_statuses', - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, text: intl.formatMessage(messages.drafts), count: draftCount, }); @@ -208,26 +257,26 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) menu.push(null); menu.push({ - icon: require('@phosphor-icons/core/regular/question.svg'), + icon: iconQuestion, text: intl.formatMessage(messages.help), items: [ { action: () => { openModal('HOTKEYS'); }, - icon: require('@phosphor-icons/core/regular/keyboard.svg'), + icon: iconKeyboard, text: intl.formatMessage(messages.keyboardShortcuts), }, { href: 'https://nicolium.app/docs/', target: '_blank', - icon: require('@phosphor-icons/core/regular/book-open.svg'), + icon: iconBookOpen, text: intl.formatMessage(messages.docs), }, { href: sourceCode.url, target: '_blank', - icon: require('@phosphor-icons/core/regular/code.svg'), + icon: iconCode, text: intl.formatMessage(messages.sourceCode), }, ], @@ -265,7 +314,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) account={account} action={ } @@ -282,15 +331,15 @@ const SidebarNavigation: React.FC = React.memo(({ shrink })
    } /> } /> @@ -298,8 +347,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) <> } /> @@ -307,8 +356,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) {features.chats && ( } @@ -318,8 +367,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) {!features.chats && features.conversations && ( } /> )} @@ -327,8 +376,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) {features.groups && ( } /> )} @@ -336,32 +385,32 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) } /> {features.drive && ( } /> )} } /> {(account.is_admin ?? account.is_moderator) && ( } /> @@ -377,8 +426,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) : timelineAccess.live_feeds.wrenched === 'public') && ( } /> )} @@ -388,8 +437,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) : timelineAccess.live_feeds.local === 'public') && ( @@ -406,8 +455,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) : timelineAccess.live_feeds.bubble === 'public') && ( } /> )} @@ -418,8 +467,8 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) : timelineAccess.live_feeds.remote === 'public') && ( } /> )} @@ -429,7 +478,7 @@ const SidebarNavigation: React.FC = React.memo(({ shrink }) {menu.length > 0 && ( } /> @@ -439,16 +488,16 @@ const SidebarNavigation: React.FC = React.memo(({ shrink })
    } /> {isOpen && ( } /> )} diff --git a/packages/nicolium/src/components/navigation/thumb-navigation.tsx b/packages/nicolium/src/components/navigation/thumb-navigation.tsx index 80c81fec5..3a84832a1 100644 --- a/packages/nicolium/src/components/navigation/thumb-navigation.tsx +++ b/packages/nicolium/src/components/navigation/thumb-navigation.tsx @@ -1,3 +1,13 @@ +import iconBellSimpleFill from '@phosphor-icons/core/fill/bell-simple-fill.svg'; +import iconChatsTeardropFill from '@phosphor-icons/core/fill/chats-teardrop-fill.svg'; +import iconHouseFill from '@phosphor-icons/core/fill/house-fill.svg'; +import iconMagnifyingGlassFill from '@phosphor-icons/core/fill/magnifying-glass-fill.svg'; +import iconBellSimple from '@phosphor-icons/core/regular/bell-simple.svg'; +import iconChatsTeardrop from '@phosphor-icons/core/regular/chats-teardrop.svg'; +import iconHouse from '@phosphor-icons/core/regular/house.svg'; +import iconList from '@phosphor-icons/core/regular/list.svg'; +import iconMagnifyingGlass from '@phosphor-icons/core/regular/magnifying-glass.svg'; +import iconPlusSquare from '@phosphor-icons/core/regular/plus-square.svg'; import { useQueryClient } from '@tanstack/react-query'; import { useMatch } from '@tanstack/react-router'; import React from 'react'; @@ -58,7 +68,7 @@ const ThumbNavigation: React.FC = React.memo((): React.JSX.Element => { onClick={handleOpenComposeModal} title={intl.formatMessage(messages.compose)} > - + ); @@ -69,12 +79,12 @@ const ThumbNavigation: React.FC = React.memo((): React.JSX.Element => { onClick={isSidebarOpen ? closeSidebar : openSidebar} title={intl.formatMessage(isSidebarOpen ? messages.closeSidebar : messages.openSidebar)} > - + { {/* {features.groups && ( } to='/groups' exact @@ -94,8 +104,8 @@ const ThumbNavigation: React.FC = React.memo((): React.JSX.Element => { {(!standalone || account) && ( { {account && ( { {account && features.chats && ( <> > = { - follow: require('@phosphor-icons/core/regular/user-plus.svg'), - follow_request: require('@phosphor-icons/core/regular/user-plus.svg'), - follow_request_accepted: require('@phosphor-icons/core/regular/user-plus.svg'), - mention: require('@phosphor-icons/core/regular/at.svg'), - favourite: require('@phosphor-icons/core/regular/star.svg'), - reblog: require('@phosphor-icons/core/regular/repeat.svg'), - status: require('@phosphor-icons/core/regular/bell-simple-ringing.svg'), - poll: require('@phosphor-icons/core/regular/chart-bar.svg'), - move: require('@phosphor-icons/core/regular/suitcase.svg'), - chat_mention: require('@phosphor-icons/core/regular/chats-teardrop.svg'), - emoji_reaction: require('@phosphor-icons/core/regular/smiley.svg'), - update: require('@phosphor-icons/core/regular/pencil-simple-line.svg'), - event_reminder: require('@phosphor-icons/core/regular/calendar-star.svg'), - participation_request: require('@phosphor-icons/core/regular/calendar-dot.svg'), - participation_accepted: require('@phosphor-icons/core/regular/calendar-dot.svg'), - bite: require('@phosphor-icons/core/regular/tooth.svg'), - reply: require('@phosphor-icons/core/regular/arrow-bend-up-left.svg'), - quote: require('@phosphor-icons/core/regular/quotes.svg'), - quoted_update: require('@phosphor-icons/core/regular/pencil-simple-line.svg'), + follow: iconUserPlus, + follow_request: iconUserPlus, + follow_request_accepted: iconUserPlus, + mention: iconAt, + favourite: iconStar, + reblog: iconRepeat, + status: iconBellSimpleRinging, + poll: iconChartBar, + move: iconSuitcase, + chat_mention: iconChatsTeardrop, + emoji_reaction: iconSmiley, + update: iconPencilSimpleLine, + event_reminder: iconCalendarStar, + participation_request: iconCalendarDot, + participation_accepted: iconCalendarDot, + bite: iconTooth, + reply: iconArrowBendUpLeft, + quote: iconQuotes, + quoted_update: iconPencilSimpleLine, }; // For use by the service worker diff --git a/packages/nicolium/src/components/panels/instance-info-panel.tsx b/packages/nicolium/src/components/panels/instance-info-panel.tsx index 415084eb7..61f06ab5e 100644 --- a/packages/nicolium/src/components/panels/instance-info-panel.tsx +++ b/packages/nicolium/src/components/panels/instance-info-panel.tsx @@ -1,3 +1,5 @@ +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'; @@ -50,11 +52,7 @@ const InstanceInfoPanel: React.FC = ({ host }) => { ); diff --git a/packages/nicolium/src/components/panels/instance-moderation-panel.tsx b/packages/nicolium/src/components/panels/instance-moderation-panel.tsx index 5ec95f9d9..95e0e5e04 100644 --- a/packages/nicolium/src/components/panels/instance-moderation-panel.tsx +++ b/packages/nicolium/src/components/panels/instance-moderation-panel.tsx @@ -1,3 +1,5 @@ +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; import React from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; @@ -33,7 +35,7 @@ const InstanceModerationPanel: React.FC = ({ host }) = { text: intl.formatMessage(messages.editFederation), action: handleEditFederation, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, }, ]; @@ -48,12 +50,7 @@ const InstanceModerationPanel: React.FC = ({ host }) = /> } action={ - account?.is_admin ? ( - - ) : undefined + account?.is_admin ? : undefined } > diff --git a/packages/nicolium/src/components/panels/new-event-panel.tsx b/packages/nicolium/src/components/panels/new-event-panel.tsx index 023dee8a8..836ba455e 100644 --- a/packages/nicolium/src/components/panels/new-event-panel.tsx +++ b/packages/nicolium/src/components/panels/new-event-panel.tsx @@ -1,3 +1,4 @@ +import iconCalendarDot from '@phosphor-icons/core/regular/calendar-dot.svg'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -19,12 +20,7 @@ const NewEventPanel = () => (
    -
diff --git a/packages/nicolium/src/components/panels/profile-info-panel.tsx b/packages/nicolium/src/components/panels/profile-info-panel.tsx index dfcfad17d..568b51b94 100644 --- a/packages/nicolium/src/components/panels/profile-info-panel.tsx +++ b/packages/nicolium/src/components/panels/profile-info-panel.tsx @@ -1,3 +1,9 @@ +import iconBalloon from '@phosphor-icons/core/regular/balloon.svg'; +import iconCake from '@phosphor-icons/core/regular/cake.svg'; +import iconCalendarDots from '@phosphor-icons/core/regular/calendar-dots.svg'; +import iconLock from '@phosphor-icons/core/regular/lock.svg'; +import iconMapPin from '@phosphor-icons/core/regular/map-pin.svg'; +import iconTag from '@phosphor-icons/core/regular/tag.svg'; import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; @@ -131,11 +137,7 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => return (
@@ -207,7 +209,7 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => {account.locked && ( @@ -231,10 +233,7 @@ const ProfileInfoPanel: React.FC = ({ account, username }) =>
{account.local ? (
- + = ({ account, username }) => {account.location ? (
- + {account.location}
@@ -268,10 +264,7 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => pronouns: account.pronouns.join('/'), })} > - + {account.pronouns.join('/')}
diff --git a/packages/nicolium/src/components/panels/user-panel.tsx b/packages/nicolium/src/components/panels/user-panel.tsx index 72a71924f..418d37de0 100644 --- a/packages/nicolium/src/components/panels/user-panel.tsx +++ b/packages/nicolium/src/components/panels/user-panel.tsx @@ -1,3 +1,4 @@ +import iconLock from '@phosphor-icons/core/regular/lock.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import React from 'react'; @@ -115,7 +116,7 @@ const UserPanel: React.FC = ({ accountId, action, badges, domain }) {account.locked && ( diff --git a/packages/nicolium/src/components/panels/who-to-follow-panel.tsx b/packages/nicolium/src/components/panels/who-to-follow-panel.tsx index 55107e345..d112ac464 100644 --- a/packages/nicolium/src/components/panels/who-to-follow-panel.tsx +++ b/packages/nicolium/src/components/panels/who-to-follow-panel.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import { Link } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -57,7 +58,7 @@ const WhoToFollowPanel = ({ limit }: IWhoToFollowPanel) => { diff --git a/packages/nicolium/src/components/pending-items-row.tsx b/packages/nicolium/src/components/pending-items-row.tsx index 8b042a140..a578497ea 100644 --- a/packages/nicolium/src/components/pending-items-row.tsx +++ b/packages/nicolium/src/components/pending-items-row.tsx @@ -1,3 +1,5 @@ +import iconCaretRight from '@phosphor-icons/core/regular/caret-right.svg'; +import iconWarningCircle from '@phosphor-icons/core/regular/warning-circle.svg'; import { Link, type LinkOptions } from '@tanstack/react-router'; import clsx from 'clsx'; import React from 'react'; @@ -27,7 +29,7 @@ const PendingItemsRow: React.FC = ({ count, size = 'md', ...pr )} > = ({ count, size = 'md', ...pr
diff --git a/packages/nicolium/src/components/polls/poll-option.tsx b/packages/nicolium/src/components/polls/poll-option.tsx index 69fc4179c..94e9d0a1e 100644 --- a/packages/nicolium/src/components/polls/poll-option.tsx +++ b/packages/nicolium/src/components/polls/poll-option.tsx @@ -1,3 +1,5 @@ +import iconCheckCircle from '@phosphor-icons/core/regular/check-circle.svg'; +import iconCheck from '@phosphor-icons/core/regular/check.svg'; import { animated, config, useSpring } from '@react-spring/web'; import clsx from 'clsx'; import React from 'react'; @@ -104,12 +106,7 @@ const PollOptionText: React.FC = ({ aria-checked={active} aria-label={option.title} > - {active && ( - - )} + {active && }
@@ -165,7 +162,7 @@ const PollOption: React.FC = (props): React.JSX.Element | null => {
{voted ? ( diff --git a/packages/nicolium/src/components/preview-card.tsx b/packages/nicolium/src/components/preview-card.tsx index b1db5b6e1..78c027f32 100644 --- a/packages/nicolium/src/components/preview-card.tsx +++ b/packages/nicolium/src/components/preview-card.tsx @@ -1,3 +1,7 @@ +import iconArrowSquareOut from '@phosphor-icons/core/regular/arrow-square-out.svg'; +import iconLinkSimple from '@phosphor-icons/core/regular/link-simple.svg'; +import iconMagnifyingGlassPlus from '@phosphor-icons/core/regular/magnifying-glass-plus.svg'; +import iconPlay from '@phosphor-icons/core/regular/play.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import DOMPurify from 'dompurify'; @@ -212,7 +216,7 @@ const PreviewCard: React.FC = ({ {trimmedDescription && {trimmedDescription}}
- + {card.provider_name} @@ -242,10 +246,10 @@ const PreviewCard: React.FC = ({ if (embedded) { embed = ; } else { - let iconVariant = require('@phosphor-icons/core/regular/play.svg'); + let iconVariant = iconPlay; if (card.type === 'photo') { - iconVariant = require('@phosphor-icons/core/regular/magnifying-glass-plus.svg'); + iconVariant = iconMagnifyingGlassPlus; } embed = ( @@ -277,10 +281,7 @@ const PreviewCard: React.FC = ({ className='text-gray-700 hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100' title={intl.formatMessage(messages.externalLink)} > - + )}
diff --git a/packages/nicolium/src/components/scroll-top-button.tsx b/packages/nicolium/src/components/scroll-top-button.tsx index 6904bdb80..f0e0d9d0b 100644 --- a/packages/nicolium/src/components/scroll-top-button.tsx +++ b/packages/nicolium/src/components/scroll-top-button.tsx @@ -1,3 +1,4 @@ +import iconArrowLineUp from '@phosphor-icons/core/regular/arrow-line-up.svg'; import clsx from 'clsx'; import throttle from 'lodash/throttle'; import React, { useState, useEffect, useCallback } from 'react'; @@ -108,7 +109,7 @@ const ScrollTopButton: React.FC = ({ {accountIds?.length && !disableUserProvidedMedia ? ( ) : ( - + )}

{buttonMessage}

diff --git a/packages/nicolium/src/components/search-input.tsx b/packages/nicolium/src/components/search-input.tsx index de8e608c4..4fcdf8e9c 100644 --- a/packages/nicolium/src/components/search-input.tsx +++ b/packages/nicolium/src/components/search-input.tsx @@ -1,3 +1,5 @@ +import iconMagnifyingGlass from '@phosphor-icons/core/regular/magnifying-glass.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import { useNavigate } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useState } from 'react'; @@ -62,7 +64,7 @@ const SearchInput = React.memo(() => { const makeMenu = () => [ { text: intl.formatMessage(messages.action, { query: value }), - icon: require('@phosphor-icons/core/regular/magnifying-glass.svg'), + icon: iconMagnifyingGlass, action: handleSubmit, }, ]; @@ -95,13 +97,13 @@ const SearchInput = React.memo(() => { } > diff --git a/packages/nicolium/src/components/statuses/events/event-action-button.tsx b/packages/nicolium/src/components/statuses/events/event-action-button.tsx index 82b31f89b..b18a5b7a2 100644 --- a/packages/nicolium/src/components/statuses/events/event-action-button.tsx +++ b/packages/nicolium/src/components/statuses/events/event-action-button.tsx @@ -1,3 +1,6 @@ +import iconArrowSquareOut from '@phosphor-icons/core/regular/arrow-square-out.svg'; +import iconCheck from '@phosphor-icons/core/regular/check.svg'; +import iconProhibit from '@phosphor-icons/core/regular/prohibit.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -44,7 +47,7 @@ const EventActionButton: React.FC = ({ status, theme = 'secondary' className='min-w-max' size='sm' theme={theme} - icon={require('@phosphor-icons/core/regular/arrow-square-out.svg')} + icon={iconArrowSquareOut} href={status.url} > @@ -99,14 +102,14 @@ const EventActionButton: React.FC = ({ status, theme = 'secondary' switch (event.join_state) { case 'accept': buttonLabel = ; - buttonIcon = require('@phosphor-icons/core/regular/check.svg'); + buttonIcon = iconCheck; break; case 'pending': buttonLabel = ; break; case 'reject': buttonLabel = ; - buttonIcon = require('@phosphor-icons/core/regular/prohibit.svg'); + buttonIcon = iconProhibit; buttonDisabled = true; break; default: diff --git a/packages/nicolium/src/components/statuses/events/event-date.tsx b/packages/nicolium/src/components/statuses/events/event-date.tsx index de279d9b5..0c7e7efb3 100644 --- a/packages/nicolium/src/components/statuses/events/event-date.tsx +++ b/packages/nicolium/src/components/statuses/events/event-date.tsx @@ -1,3 +1,4 @@ +import iconCalendarDots from '@phosphor-icons/core/regular/calendar-dots.svg'; import React from 'react'; import { FormattedDate } from 'react-intl'; @@ -80,7 +81,7 @@ const EventDate: React.FC = ({ status }) => { return (
- + {date}
); diff --git a/packages/nicolium/src/components/statuses/events/event-header.tsx b/packages/nicolium/src/components/statuses/events/event-header.tsx index b77a0619a..3a3dc161a 100644 --- a/packages/nicolium/src/components/statuses/events/event-header.tsx +++ b/packages/nicolium/src/components/statuses/events/event-header.tsx @@ -1,3 +1,30 @@ +import iconArrowSquareOut from '@phosphor-icons/core/regular/arrow-square-out.svg'; +import iconAt from '@phosphor-icons/core/regular/at.svg'; +import iconBookmarkSimple from '@phosphor-icons/core/regular/bookmark-simple.svg'; +import iconBookmark from '@phosphor-icons/core/regular/bookmark.svg'; +import iconCalendarPlus from '@phosphor-icons/core/regular/calendar-plus.svg'; +import iconChatCircle from '@phosphor-icons/core/regular/chat-circle.svg'; +import iconChatsTeardrop from '@phosphor-icons/core/regular/chats-teardrop.svg'; +import iconCopy from '@phosphor-icons/core/regular/copy.svg'; +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; +import iconFlagBanner from '@phosphor-icons/core/regular/flag-banner.svg'; +import iconFlag from '@phosphor-icons/core/regular/flag.svg'; +import iconGavel from '@phosphor-icons/core/regular/gavel.svg'; +import iconGlobe from '@phosphor-icons/core/regular/globe.svg'; +import iconLinkSimpleHorizontal from '@phosphor-icons/core/regular/link-simple-horizontal.svg'; +import iconLock from '@phosphor-icons/core/regular/lock.svg'; +import iconMapPin from '@phosphor-icons/core/regular/map-pin.svg'; +import iconMoon from '@phosphor-icons/core/regular/moon.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconProhibit from '@phosphor-icons/core/regular/prohibit.svg'; +import iconPushPinSlash from '@phosphor-icons/core/regular/push-pin-slash.svg'; +import iconPushPin from '@phosphor-icons/core/regular/push-pin.svg'; +import iconQuotes from '@phosphor-icons/core/regular/quotes.svg'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; +import iconSpeakerSimpleX from '@phosphor-icons/core/regular/speaker-simple-x.svg'; +import iconTrash from '@phosphor-icons/core/regular/trash.svg'; +import iconUsers from '@phosphor-icons/core/regular/users.svg'; +import iconWarning from '@phosphor-icons/core/regular/warning.svg'; import { Link, useNavigate } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -273,26 +300,26 @@ const EventHeader: React.FC = ({ status }) => { { text: intl.formatMessage(messages.exportIcs), action: handleExportClick, - icon: require('@phosphor-icons/core/regular/calendar-plus.svg'), + icon: iconCalendarPlus, }, ]; menu.push({ text: intl.formatMessage(messages.copyStatus), action: handleCopyStatus, - icon: require('@phosphor-icons/core/regular/copy.svg'), + icon: iconCopy, }); menu.push({ text: intl.formatMessage(messages.copy), action: handleCopy, - icon: require('@phosphor-icons/core/regular/link-simple-horizontal.svg'), + icon: iconLinkSimpleHorizontal, }); if (features.federating && !account.local) { menu.push({ text: intl.formatMessage(messages.external, { domain }), - icon: require('@phosphor-icons/core/regular/arrow-square-out.svg'), + icon: iconArrowSquareOut, href: status.uri, target: '_blank', }); @@ -304,9 +331,7 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(status.bookmarked ? messages.unbookmark : messages.bookmark), action: handleBookmarkClick, - icon: status.bookmarked - ? require('@phosphor-icons/core/regular/bookmark.svg') - : require('@phosphor-icons/core/regular/bookmark-simple.svg'), + icon: status.bookmarked ? iconBookmark : iconBookmarkSimple, }); } @@ -321,21 +346,21 @@ const EventHeader: React.FC = ({ status }) => { action: () => { handleReblogClick('public'); }, - icon: require('@phosphor-icons/core/regular/globe.svg'), + icon: iconGlobe, }, { text: intl.formatMessage(messages.reblogVisibilityUnlisted), action: () => { handleReblogClick('unlisted'); }, - icon: require('@phosphor-icons/core/regular/moon.svg'), + icon: iconMoon, }, { text: intl.formatMessage(messages.reblogVisibilityPrivate), action: () => { handleReblogClick('private'); }, - icon: require('@phosphor-icons/core/regular/lock.svg'), + icon: iconLock, }, ], } @@ -344,14 +369,14 @@ const EventHeader: React.FC = ({ status }) => { handleReblogClick(); }, }), - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, }); if (features.quotePosts) { menu.push({ text: intl.formatMessage(messages.quotePost), action: handleQuoteClick, - icon: require('@phosphor-icons/core/regular/quotes.svg'), + icon: iconQuotes, }); } } else if (status.visibility === 'private' || status.visibility === 'mutuals_only') { @@ -362,7 +387,7 @@ const EventHeader: React.FC = ({ status }) => { action: () => { handleReblogClick(); }, - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, }); } @@ -373,36 +398,34 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(status.pinned ? messages.unpin : messages.pin), action: handlePinClick, - icon: status.pinned - ? require('@phosphor-icons/core/regular/push-pin-slash.svg') - : require('@phosphor-icons/core/regular/push-pin.svg'), + icon: status.pinned ? iconPushPinSlash : iconPushPin, }); } menu.push({ text: intl.formatMessage(messages.delete), action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: username }), action: handleMentionClick, - icon: require('@phosphor-icons/core/regular/at.svg'), + icon: iconAt, }); if (account.accepts_chat_messages === true) { menu.push({ text: intl.formatMessage(messages.chat, { name: username }), action: handleChatClick, - icon: require('@phosphor-icons/core/regular/chats-teardrop.svg'), + icon: iconChatsTeardrop, }); } else if (features.privacyScopes) { menu.push({ text: intl.formatMessage(messages.direct, { name: username }), action: handleDirectClick, - icon: require('@phosphor-icons/core/regular/chat-circle.svg'), + icon: iconChatCircle, }); } @@ -410,17 +433,17 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(messages.mute, { name: username }), action: handleMuteClick, - icon: require('@phosphor-icons/core/regular/speaker-simple-x.svg'), + icon: iconSpeakerSimpleX, }); menu.push({ text: intl.formatMessage(messages.block, { name: username }), action: handleBlockClick, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); menu.push({ text: intl.formatMessage(messages.report, { name: username }), action: handleReport, - icon: require('@phosphor-icons/core/regular/flag.svg'), + icon: iconFlag, }); } @@ -431,14 +454,14 @@ const EventHeader: React.FC = ({ status }) => { text: intl.formatMessage(messages.adminAccount, { name: username }), to: '/nicolium/admin/accounts/$accountId', params: { accountId: account.id }, - icon: require('@phosphor-icons/core/regular/gavel.svg'), + icon: iconGavel, }); if (isAdmin && features.pleromaAdminStatuses) { menu.push({ text: intl.formatMessage(messages.adminStatus), href: `/pleroma/admin/#/statuses/${status.id}/`, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, }); } @@ -448,7 +471,7 @@ const EventHeader: React.FC = ({ status }) => { !status.sensitive ? messages.markStatusSensitive : messages.markStatusNotSensitive, ), action: handleToggleStatusSensitivity, - icon: require('@phosphor-icons/core/regular/warning.svg'), + icon: iconWarning, }); } @@ -456,7 +479,7 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(messages.deleteStatus), action: handleDeleteStatus, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); } @@ -499,7 +522,7 @@ const EventHeader: React.FC = ({ status }) => { = ({ status }) => {
- + = ({ status }) => { {(event.join_mode !== 'external' || event.participants_count > 0) && (
- + = ({ status }) => { {event.location && (
- + {event.location.name}
)} diff --git a/packages/nicolium/src/components/statuses/events/event-preview.tsx b/packages/nicolium/src/components/statuses/events/event-preview.tsx index 1088e4b10..90d214480 100644 --- a/packages/nicolium/src/components/statuses/events/event-preview.tsx +++ b/packages/nicolium/src/components/statuses/events/event-preview.tsx @@ -1,3 +1,5 @@ +import iconMapPin from '@phosphor-icons/core/regular/map-pin.svg'; +import iconUser from '@phosphor-icons/core/regular/user.svg'; import clsx from 'clsx'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -77,7 +79,7 @@ const EventPreview: React.FC = ({
- +
@@ -90,7 +92,7 @@ const EventPreview: React.FC = ({ {event.location && (
- + {event.location.name}
)} diff --git a/packages/nicolium/src/components/statuses/quoted-status-indicator.tsx b/packages/nicolium/src/components/statuses/quoted-status-indicator.tsx index d262eb822..a5a12b762 100644 --- a/packages/nicolium/src/components/statuses/quoted-status-indicator.tsx +++ b/packages/nicolium/src/components/statuses/quoted-status-indicator.tsx @@ -1,3 +1,4 @@ +import iconQuotes from '@phosphor-icons/core/regular/quotes.svg'; import React from 'react'; import Icon from '@/components/ui/icon'; @@ -17,7 +18,7 @@ const QuotedStatusIndicator: React.FC = ({ statusId, sta return (
- +

{statusUrl}

); diff --git a/packages/nicolium/src/components/statuses/quoted-status.tsx b/packages/nicolium/src/components/statuses/quoted-status.tsx index fab6714cc..342aa6cde 100644 --- a/packages/nicolium/src/components/statuses/quoted-status.tsx +++ b/packages/nicolium/src/components/statuses/quoted-status.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import { linkOptions, useNavigate, useRouter } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { type MouseEventHandler } from 'react'; @@ -68,7 +69,7 @@ const QuotedStatus: React.FC = ({ status, onCancel, compose }) => if (onCancel) { actions = { onActionClick: handleClose, - actionIcon: require('@phosphor-icons/core/regular/x.svg'), + actionIcon: iconX, actionAlignment: 'top', actionTitle: intl.formatMessage(messages.cancel), }; diff --git a/packages/nicolium/src/components/statuses/rss-feed-info.tsx b/packages/nicolium/src/components/statuses/rss-feed-info.tsx index 08955fc4a..151223747 100644 --- a/packages/nicolium/src/components/statuses/rss-feed-info.tsx +++ b/packages/nicolium/src/components/statuses/rss-feed-info.tsx @@ -1,3 +1,4 @@ +import iconRss from '@phosphor-icons/core/regular/rss.svg'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -26,7 +27,7 @@ const RssFeedInfo: React.FC = ({ feed, timestamp }) => (

- + · diff --git a/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx b/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx index a65d36dc9..65b80faf9 100644 --- a/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx +++ b/packages/nicolium/src/components/statuses/sensitive-content-overlay.tsx @@ -1,3 +1,5 @@ +import iconEyeSlash from '@phosphor-icons/core/regular/eye-slash.svg'; +import iconEye from '@phosphor-icons/core/regular/eye.svg'; import clsx from 'clsx'; import React, { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -83,7 +85,7 @@ const SensitiveContentOverlay = React.forwardRef} - icon={require('@phosphor-icons/core/regular/eye-slash.svg')} + icon={iconEyeSlash} onClick={toggleVisibility} theme='primary' size='sm' @@ -123,7 +125,7 @@ const SensitiveContentOverlay = React.forwardRef diff --git a/packages/nicolium/src/components/statuses/status-action-bar.tsx b/packages/nicolium/src/components/statuses/status-action-bar.tsx index 8dc3d9a4e..01cea8bfc 100644 --- a/packages/nicolium/src/components/statuses/status-action-bar.tsx +++ b/packages/nicolium/src/components/statuses/status-action-bar.tsx @@ -1,3 +1,45 @@ +import iconStarFill from '@phosphor-icons/core/fill/star-fill.svg'; +import iconThumbsDownFill from '@phosphor-icons/core/fill/thumbs-down-fill.svg'; +import iconThumbsUpFill from '@phosphor-icons/core/fill/thumbs-up-fill.svg'; +import iconWrenchFill from '@phosphor-icons/core/fill/wrench-fill.svg'; +import iconArrowBendDoubleUpLeft from '@phosphor-icons/core/regular/arrow-bend-double-up-left.svg'; +import iconArrowBendUpLeft from '@phosphor-icons/core/regular/arrow-bend-up-left.svg'; +import iconArrowSquareOut from '@phosphor-icons/core/regular/arrow-square-out.svg'; +import iconArrowsClockwise from '@phosphor-icons/core/regular/arrows-clockwise.svg'; +import iconArrowsVertical from '@phosphor-icons/core/regular/arrows-vertical.svg'; +import iconAt from '@phosphor-icons/core/regular/at.svg'; +import iconBellSimpleSlash from '@phosphor-icons/core/regular/bell-simple-slash.svg'; +import iconBellSimple from '@phosphor-icons/core/regular/bell-simple.svg'; +import iconBookmarkSimple from '@phosphor-icons/core/regular/bookmark-simple.svg'; +import iconBookmark from '@phosphor-icons/core/regular/bookmark.svg'; +import iconChatCircle from '@phosphor-icons/core/regular/chat-circle.svg'; +import iconChatsTeardrop from '@phosphor-icons/core/regular/chats-teardrop.svg'; +import iconCodeSimple from '@phosphor-icons/core/regular/code-simple.svg'; +import iconCopy from '@phosphor-icons/core/regular/copy.svg'; +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; +import iconExport from '@phosphor-icons/core/regular/export.svg'; +import iconFlag from '@phosphor-icons/core/regular/flag.svg'; +import iconFolders from '@phosphor-icons/core/regular/folders.svg'; +import iconGavel from '@phosphor-icons/core/regular/gavel.svg'; +import iconGlobe from '@phosphor-icons/core/regular/globe.svg'; +import iconLinkSimpleHorizontal from '@phosphor-icons/core/regular/link-simple-horizontal.svg'; +import iconLock from '@phosphor-icons/core/regular/lock.svg'; +import iconMoon from '@phosphor-icons/core/regular/moon.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconProhibit from '@phosphor-icons/core/regular/prohibit.svg'; +import iconPushPinSlash from '@phosphor-icons/core/regular/push-pin-slash.svg'; +import iconPushPin from '@phosphor-icons/core/regular/push-pin.svg'; +import iconQuotes from '@phosphor-icons/core/regular/quotes.svg'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; +import iconSmiley from '@phosphor-icons/core/regular/smiley.svg'; +import iconSpeakerX from '@phosphor-icons/core/regular/speaker-x.svg'; +import iconStar from '@phosphor-icons/core/regular/star.svg'; +import iconThumbsDown from '@phosphor-icons/core/regular/thumbs-down.svg'; +import iconThumbsUp from '@phosphor-icons/core/regular/thumbs-up.svg'; +import iconTranslate from '@phosphor-icons/core/regular/translate.svg'; +import iconTrash from '@phosphor-icons/core/regular/trash.svg'; +import iconWarning from '@phosphor-icons/core/regular/warning.svg'; +import iconWrench from '@phosphor-icons/core/regular/wrench.svg'; import { useMatch, useNavigate } from '@tanstack/react-router'; import { type Account, type CustomEmoji, GroupRoles } from 'pl-api'; import React, { useCallback, useMemo } from 'react'; @@ -371,11 +413,7 @@ const ReplyButton: React.FC = ({ const replyButton = ( = ({ const { mutate: reblogStatus } = useReblogStatus(status.id); const { mutate: unreblogStatus } = useUnreblogStatus(status.id); - let reblogIcon = require('@phosphor-icons/core/regular/repeat.svg'); + let reblogIcon = iconRepeat; if (status.visibility === 'direct') { - reblogIcon = require('@phosphor-icons/core/regular/at.svg'); + reblogIcon = iconAt; } else if (status.visibility === 'private' || status.visibility === 'mutuals_only') { - reblogIcon = require('@phosphor-icons/core/regular/lock.svg'); + reblogIcon = iconLock; } const handleReblogClick: React.EventHandler = (e) => { @@ -504,12 +542,12 @@ const ReblogButton: React.FC = ({ { text: intl.formatMessage(status.reblogged ? messages.cancelReblogPrivate : messages.reblog), action: handleReblogClick, - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, }, { text: intl.formatMessage(messages.quotePost), action: handleQuoteClick, - icon: require('@phosphor-icons/core/regular/quotes.svg'), + icon: iconQuotes, disabled: !canQuote.canInteract, }, ]; @@ -561,16 +599,8 @@ const FavouriteButton: React.FC = ({ const favouriteButton = ( = ({ return ( = ({ status, withLabels, me }) => { return ( = ({ if (expandable) { menu.push({ text: intl.formatMessage(messages.open), - icon: require('@phosphor-icons/core/regular/arrows-vertical.svg'), + icon: iconArrowsVertical, to: '/@{$username}/posts/$statusId', params: { username: status.account.acct, statusId: status.id }, }); @@ -1010,7 +1040,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.copyStatus), action: handleCopyStatus, - icon: require('@phosphor-icons/core/regular/copy.svg'), + icon: iconCopy, }); } @@ -1018,14 +1048,14 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.copy), action: handleCopy, - icon: require('@phosphor-icons/core/regular/link-simple-horizontal.svg'), + icon: iconLinkSimpleHorizontal, }); if ('share' in navigator) { menu.push({ text: intl.formatMessage(messages.share), action: handleShare, - icon: require('@phosphor-icons/core/regular/export.svg'), + icon: iconExport, }); } @@ -1033,7 +1063,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.embed), action: handleEmbed, - icon: require('@phosphor-icons/core/regular/code-simple.svg'), + icon: iconCodeSimple, }); } } @@ -1046,7 +1076,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.viewReactions), action: handleOpenReactionsModal, - icon: require('@phosphor-icons/core/regular/smiley.svg'), + icon: iconSmiley, }); } @@ -1056,9 +1086,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(status.bookmarked ? messages.unbookmark : messages.bookmark), action: handleBookmarkClick, - icon: status.bookmarked - ? require('@phosphor-icons/core/regular/bookmark.svg') - : require('@phosphor-icons/core/regular/bookmark-simple.svg'), + icon: status.bookmarked ? iconBookmark : iconBookmarkSimple, }); } @@ -1068,7 +1096,7 @@ const MenuButton: React.FC = ({ status.bookmark_folder ? messages.bookmarkChangeFolder : messages.bookmarkSetFolder, ), action: handleBookmarkFolderClick, - icon: require('@phosphor-icons/core/regular/folders.svg'), + icon: iconFolders, }); } @@ -1076,7 +1104,7 @@ const MenuButton: React.FC = ({ const { hostname: domain } = new URL(status.uri); menu.push({ text: intl.formatMessage(messages.external, { domain }), - icon: require('@phosphor-icons/core/regular/arrow-square-out.svg'), + icon: iconArrowSquareOut, href: status.uri, target: '_blank', }); @@ -1089,16 +1117,14 @@ const MenuButton: React.FC = ({ mutingConversation ? messages.unmuteConversation : messages.muteConversation, ), action: handleConversationMuteClick, - icon: mutingConversation - ? require('@phosphor-icons/core/regular/bell-simple.svg') - : require('@phosphor-icons/core/regular/bell-simple-slash.svg'), + icon: mutingConversation ? iconBellSimple : iconBellSimpleSlash, }); if (!status.in_reply_to_id && features.loadConversation) { menu.push({ text: intl.formatMessage(messages.loadConversation), action: handleLoadConversationClick, - icon: require('@phosphor-icons/core/regular/arrows-clockwise.svg'), + icon: iconArrowsClockwise, }); } @@ -1107,28 +1133,28 @@ const MenuButton: React.FC = ({ if (publicStatus && !status.reblogged && features.reblogVisibility) { menu.push({ text: intl.formatMessage(messages.reblogVisibility), - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, items: [ { text: intl.formatMessage(messages.reblogVisibilityPublic), action: (e) => { handleReblogClick(e, 'public'); }, - icon: require('@phosphor-icons/core/regular/globe.svg'), + icon: iconGlobe, }, { text: intl.formatMessage(messages.reblogVisibilityUnlisted), action: (e) => { handleReblogClick(e, 'unlisted'); }, - icon: require('@phosphor-icons/core/regular/moon.svg'), + icon: iconMoon, }, { text: intl.formatMessage(messages.reblogVisibilityPrivate), action: (e) => { handleReblogClick(e, 'private'); }, - icon: require('@phosphor-icons/core/regular/lock.svg'), + icon: iconLock, }, ], }); @@ -1139,9 +1165,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(status.pinned ? messages.unpin : messages.pin), action: handlePinClick, - icon: status.pinned - ? require('@phosphor-icons/core/regular/push-pin-slash.svg') - : require('@phosphor-icons/core/regular/push-pin.svg'), + icon: status.pinned ? iconPushPinSlash : iconPushPin, }); } else if (status.visibility === 'private' || status.visibility === 'mutuals_only') { menu.push({ @@ -1149,27 +1173,27 @@ const MenuButton: React.FC = ({ status.reblogged ? messages.cancelReblogPrivate : messages.reblogPrivate, ), action: handleReblogClick, - icon: require('@phosphor-icons/core/regular/repeat.svg'), + icon: iconRepeat, }); } menu.push({ text: intl.formatMessage(messages.delete), action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); if (features.editStatuses) { menu.push({ text: intl.formatMessage(messages.edit), action: handleEditClick, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, }); } else { menu.push({ text: intl.formatMessage(messages.redraft), action: handleRedraftClick, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, destructive: true, }); } @@ -1177,20 +1201,20 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.mention, { name: username }), action: handleMentionClick, - icon: require('@phosphor-icons/core/regular/at.svg'), + icon: iconAt, }); if (status.account.accepts_chat_messages === true) { menu.push({ text: intl.formatMessage(messages.chat, { name: username }), action: handleChatClick, - icon: require('@phosphor-icons/core/regular/chats-teardrop.svg'), + icon: iconChatsTeardrop, }); } else if (features.privacyScopes) { menu.push({ text: intl.formatMessage(messages.direct, { name: username }), action: handleDirectClick, - icon: require('@phosphor-icons/core/regular/chat-circle.svg'), + icon: iconChatCircle, }); } @@ -1199,25 +1223,25 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.mute, { name: username }), action: handleMuteClick, - icon: require('@phosphor-icons/core/regular/speaker-x.svg'), + icon: iconSpeakerX, }); if (status.account.relationship?.blocking) { menu.push({ text: intl.formatMessage(messages.unblock, { name: username }), action: handleUnblockClick, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } else { menu.push({ text: intl.formatMessage(messages.block, { name: username }), action: handleBlockClick, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, }); } menu.push({ text: intl.formatMessage(messages.report, { name: username }), action: handleReport, - icon: require('@phosphor-icons/core/regular/flag.svg'), + icon: iconFlag, }); } @@ -1226,13 +1250,13 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.hideTranslation), action: handleTranslate, - icon: require('@phosphor-icons/core/regular/translate.svg'), + icon: iconTranslate, }); } else { menu.push({ text: intl.formatMessage(messages.translate), action: handleTranslate, - icon: require('@phosphor-icons/core/regular/translate.svg'), + icon: iconTranslate, }); } @@ -1241,7 +1265,7 @@ const MenuButton: React.FC = ({ language: languages[status.language as 'en'] || status.language, }), action: handleIgnoreLanguage, - icon: require('@phosphor-icons/core/regular/flag.svg'), + icon: iconFlag, }); } @@ -1261,7 +1285,7 @@ const MenuButton: React.FC = ({ menu.push({ text: 'Ban from Group', action: handleBlockFromGroup, - icon: require('@phosphor-icons/core/regular/prohibit.svg'), + icon: iconProhibit, destructive: true, }); } @@ -1270,7 +1294,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.groupModDelete), action: handleDeleteFromGroup, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); } @@ -1283,14 +1307,14 @@ const MenuButton: React.FC = ({ text: intl.formatMessage(messages.adminAccount, { name: username }), to: '/nicolium/admin/accounts/$accountId', params: { accountId: status.account_id }, - icon: require('@phosphor-icons/core/regular/gavel.svg'), + icon: iconGavel, }); if (isAdmin && features.pleromaAdminStatuses) { menu.push({ text: intl.formatMessage(messages.adminStatus), href: `/pleroma/admin/#/statuses/${status.id}/`, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, }); } @@ -1300,7 +1324,7 @@ const MenuButton: React.FC = ({ !status.sensitive ? messages.markStatusSensitive : messages.markStatusNotSensitive, ), action: handleToggleStatusSensitivity, - icon: require('@phosphor-icons/core/regular/warning.svg'), + icon: iconWarning, }); } @@ -1308,7 +1332,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.redact), action: handleRedactStatus, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, destructive: true, }); } @@ -1317,7 +1341,7 @@ const MenuButton: React.FC = ({ menu.push({ text: intl.formatMessage(messages.deleteStatus), action: handleDeleteStatus, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); } @@ -1339,10 +1363,7 @@ const MenuButton: React.FC = ({ return useMemo( () => ( - + ), [menu], diff --git a/packages/nicolium/src/components/statuses/status-content.tsx b/packages/nicolium/src/components/statuses/status-content.tsx index 5d667ba66..7d794e847 100644 --- a/packages/nicolium/src/components/statuses/status-content.tsx +++ b/packages/nicolium/src/components/statuses/status-content.tsx @@ -1,3 +1,5 @@ +import iconCaretDown from '@phosphor-icons/core/regular/caret-down.svg'; +import iconCaretRight from '@phosphor-icons/core/regular/caret-right.svg'; import clsx from 'clsx'; import React, { useState, useRef, useLayoutEffect, useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -43,10 +45,7 @@ const ReadMoreButton: React.FC = ({ onClick, preview }) => ( {!preview && ( )}
@@ -231,7 +230,7 @@ const StatusContent: React.FC = React.memo( {expandable && ( )} diff --git a/packages/nicolium/src/components/statuses/status.tsx b/packages/nicolium/src/components/statuses/status.tsx index 67390a711..93839945a 100644 --- a/packages/nicolium/src/components/statuses/status.tsx +++ b/packages/nicolium/src/components/statuses/status.tsx @@ -1,3 +1,8 @@ +import iconHash from '@phosphor-icons/core/regular/hash.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconPushPin from '@phosphor-icons/core/regular/push-pin.svg'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; +import iconUsersThree from '@phosphor-icons/core/regular/users-three.svg'; import { Link, linkOptions, useNavigate, useRouter } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useEffect, useMemo, useRef } from 'react'; @@ -77,7 +82,7 @@ const AccountInfo: React.FC = React.memo(({ status }) => { = ({ avatarSize={avatarSize} icon={ @@ -370,13 +375,7 @@ const Status: React.FC = React.memo((props) => { - } + icon={} text={ = React.memo((props) => { - } + icon={} text={ status.visibility === 'private' ? ( = React.memo((props) => { avatarSize={avatarSize} icon={ @@ -482,7 +475,7 @@ const Status: React.FC = React.memo((props) => { avatarSize={avatarSize} icon={ diff --git a/packages/nicolium/src/components/statuses/translate-button.tsx b/packages/nicolium/src/components/statuses/translate-button.tsx index b4938f3b7..c258449e8 100644 --- a/packages/nicolium/src/components/statuses/translate-button.tsx +++ b/packages/nicolium/src/components/statuses/translate-button.tsx @@ -1,3 +1,5 @@ +import iconCircleNotch from '@phosphor-icons/core/regular/circle-notch.svg'; +import iconTranslate from '@phosphor-icons/core/regular/translate.svg'; import React, { useEffect } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; @@ -180,14 +182,11 @@ const TranslateButton: React.FC = ({ status }) => { const button = ( )} - +
diff --git a/packages/nicolium/src/components/ui/avatar.tsx b/packages/nicolium/src/components/ui/avatar.tsx index 796de40a9..53a72f8c9 100644 --- a/packages/nicolium/src/components/ui/avatar.tsx +++ b/packages/nicolium/src/components/ui/avatar.tsx @@ -1,3 +1,4 @@ +import iconImageSquare from '@phosphor-icons/core/regular/image-square.svg'; import clsx from 'clsx'; import { FastAverageColor } from 'fast-average-color'; import React, { useEffect, useState } from 'react'; @@ -123,10 +124,7 @@ const Avatar: React.FC = (props) => { )} >
- +
); diff --git a/packages/nicolium/src/components/ui/card.tsx b/packages/nicolium/src/components/ui/card.tsx index e271356fa..dbb3e78c0 100644 --- a/packages/nicolium/src/components/ui/card.tsx +++ b/packages/nicolium/src/components/ui/card.tsx @@ -1,3 +1,4 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import React from 'react'; @@ -81,7 +82,7 @@ const CardHeader: React.FC = ({ aria-label={intl.formatMessage(messages.back)} title={intl.formatMessage(messages.back)} > - + ); }; diff --git a/packages/nicolium/src/components/ui/input.tsx b/packages/nicolium/src/components/ui/input.tsx index 71a4a85c6..060958df8 100644 --- a/packages/nicolium/src/components/ui/input.tsx +++ b/packages/nicolium/src/components/ui/input.tsx @@ -1,3 +1,5 @@ +import iconEyeSlash from '@phosphor-icons/core/regular/eye-slash.svg'; +import iconEye from '@phosphor-icons/core/regular/eye.svg'; import clsx from 'clsx'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -134,14 +136,7 @@ const Input = React.forwardRef((props, ref) => { >
diff --git a/packages/nicolium/src/components/ui/modal.tsx b/packages/nicolium/src/components/ui/modal.tsx index d10c06c7c..9ea19a584 100644 --- a/packages/nicolium/src/components/ui/modal.tsx +++ b/packages/nicolium/src/components/ui/modal.tsx @@ -1,3 +1,6 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; +import iconTwitterLogo from '@phosphor-icons/core/regular/twitter-logo.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import clsx from 'clsx'; import React from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -21,10 +24,10 @@ const useDefaultCloseIcon = (): string => { account?.url === 'https://donotsta.re/users/pmysl' || account?.url === 'https://to.juz.sie.federu.je/@pmysl' ) { - return require('@phosphor-icons/core/regular/twitter-logo.svg'); + return iconTwitterLogo; } - return require('@phosphor-icons/core/regular/x.svg'); + return iconX; }; interface IModal { @@ -120,7 +123,7 @@ const Modal = React.forwardRef(
{onBack && ( diff --git a/packages/nicolium/src/components/ui/multiselect.tsx b/packages/nicolium/src/components/ui/multiselect.tsx index 1ad963c91..91f4182e0 100644 --- a/packages/nicolium/src/components/ui/multiselect.tsx +++ b/packages/nicolium/src/components/ui/multiselect.tsx @@ -23,6 +23,7 @@ THE SOFTWARE. */ // Adapted from [multiselect-react-dropdown](https://github.com/srigar/multiselect-react-dropdown) +import iconXCircle from '@phosphor-icons/core/regular/x-circle.svg'; import clsx from 'clsx'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -234,10 +235,7 @@ const Multiselect: React.FC = ({ title={intl.formatMessage(messages.removeItem)} aria-label={intl.formatMessage(messages.removeItem)} > - + ))} diff --git a/packages/nicolium/src/components/ui/streamfield.tsx b/packages/nicolium/src/components/ui/streamfield.tsx index 10a74e6f9..5f4ee8708 100644 --- a/packages/nicolium/src/components/ui/streamfield.tsx +++ b/packages/nicolium/src/components/ui/streamfield.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import React, { useRef } from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; @@ -118,7 +119,7 @@ const Streamfield = ({ { onRemoveItem(i); }} diff --git a/packages/nicolium/src/components/ui/tag.tsx b/packages/nicolium/src/components/ui/tag.tsx index 38d38c0b0..765570beb 100644 --- a/packages/nicolium/src/components/ui/tag.tsx +++ b/packages/nicolium/src/components/ui/tag.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import IconButton from './icon-button'; @@ -17,7 +18,7 @@ const Tag: React.FC = ({ tag, onDelete }) => ( { onDelete(tag); }} diff --git a/packages/nicolium/src/components/ui/toast.tsx b/packages/nicolium/src/components/ui/toast.tsx index 385bb139a..c4138115a 100644 --- a/packages/nicolium/src/components/ui/toast.tsx +++ b/packages/nicolium/src/components/ui/toast.tsx @@ -1,3 +1,7 @@ +import iconCheckCircle from '@phosphor-icons/core/regular/check-circle.svg'; +import iconInfo from '@phosphor-icons/core/regular/info.svg'; +import iconWarningCircle from '@phosphor-icons/core/regular/warning-circle.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import { Link, type LinkOptions } from '@tanstack/react-router'; import clsx from 'clsx'; import React from 'react'; @@ -50,13 +54,11 @@ const Toast: React.FC = (props) => { const renderIcon = () => { switch (type) { case 'success': - return ; + return ; case 'info': - return ; + return ; case 'error': - return ( - - ); + return ; } }; @@ -122,7 +124,7 @@ const Toast: React.FC = (props) => { title={intl.formatMessage(messages.close)} aria-label={intl.formatMessage(messages.close)} > - +
diff --git a/packages/nicolium/src/components/ui/widget.tsx b/packages/nicolium/src/components/ui/widget.tsx index ac60ac39c..079fa6f9e 100644 --- a/packages/nicolium/src/components/ui/widget.tsx +++ b/packages/nicolium/src/components/ui/widget.tsx @@ -1,3 +1,4 @@ +import iconArrowRight from '@phosphor-icons/core/regular/arrow-right.svg'; import clsx from 'clsx'; import React, { useMemo } from 'react'; @@ -22,7 +23,7 @@ const Widget: React.FC = ({ title, children, onActionClick, - actionIcon = require('@phosphor-icons/core/regular/arrow-right.svg'), + actionIcon = iconArrowRight, actionTitle, action, className, diff --git a/packages/nicolium/src/components/upload-progress.tsx b/packages/nicolium/src/components/upload-progress.tsx index 23630638e..afde8ff3c 100644 --- a/packages/nicolium/src/components/upload-progress.tsx +++ b/packages/nicolium/src/components/upload-progress.tsx @@ -1,3 +1,4 @@ +import iconUploadSimple from '@phosphor-icons/core/regular/upload-simple.svg'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -13,10 +14,7 @@ interface IUploadProgress { /** Displays a progress bar for uploading files. */ const UploadProgress: React.FC = ({ progress }) => (
- +
diff --git a/packages/nicolium/src/features/birthdays/account.tsx b/packages/nicolium/src/features/birthdays/account.tsx index ebfab5281..f70782692 100644 --- a/packages/nicolium/src/features/birthdays/account.tsx +++ b/packages/nicolium/src/features/birthdays/account.tsx @@ -1,3 +1,4 @@ +import iconCake from '@phosphor-icons/core/regular/cake.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -39,7 +40,7 @@ const Account: React.FC = ({ accountId }) => { date: formattedBirthday, })} > - + {formattedBirthday}
diff --git a/packages/nicolium/src/features/chats/components/chat-composer.tsx b/packages/nicolium/src/features/chats/components/chat-composer.tsx index b5e106143..bf26f02ed 100644 --- a/packages/nicolium/src/features/chats/components/chat-composer.tsx +++ b/packages/nicolium/src/features/chats/components/chat-composer.tsx @@ -1,3 +1,4 @@ +import iconPaperPlaneRight from '@phosphor-icons/core/regular/paper-plane-right.svg'; import React, { useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -252,7 +253,7 @@ const ChatComposer = React.forwardRef ) : null} = React.memo( }, }); }, - icon: require('@phosphor-icons/core/regular/sign-out.svg'), + icon: iconSignOut, }, ], [], @@ -169,10 +171,7 @@ const ChatListItem: React.FC = React.memo( {features.chatsDelete && (
- +
)} diff --git a/packages/nicolium/src/features/chats/components/chat-message.tsx b/packages/nicolium/src/features/chats/components/chat-message.tsx index 1acb75f93..a663f3326 100644 --- a/packages/nicolium/src/features/chats/components/chat-message.tsx +++ b/packages/nicolium/src/features/chats/components/chat-message.tsx @@ -1,3 +1,6 @@ +import iconClipboard from '@phosphor-icons/core/regular/clipboard.svg'; +import iconDotsThree from '@phosphor-icons/core/regular/dots-three.svg'; +import iconTrash from '@phosphor-icons/core/regular/trash.svg'; import clsx from 'clsx'; import escape from 'lodash/escape'; import React, { useMemo, useState } from 'react'; @@ -119,7 +122,7 @@ const ChatMessage: React.FC = React.memo((props) => { action: () => { handleCopyText(chatMessage); }, - icon: require('@phosphor-icons/core/regular/clipboard.svg'), + icon: iconClipboard, }); } @@ -129,7 +132,7 @@ const ChatMessage: React.FC = React.memo((props) => { action: () => { deleteChatMessage.mutate(chatMessage.id); }, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); } else { @@ -138,7 +141,7 @@ const ChatMessage: React.FC = React.memo((props) => { action: () => { deleteChatMessage.mutate(chatMessage.id); }, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, }); } @@ -180,10 +183,7 @@ const ChatMessage: React.FC = React.memo((props) => { })} data-testid='chat-message-menu' > - + )} diff --git a/packages/nicolium/src/features/chats/components/chat-pane/chat-pane.tsx b/packages/nicolium/src/features/chats/components/chat-pane/chat-pane.tsx index f1eb415b0..4558c4bff 100644 --- a/packages/nicolium/src/features/chats/components/chat-pane/chat-pane.tsx +++ b/packages/nicolium/src/features/chats/components/chat-pane/chat-pane.tsx @@ -1,3 +1,4 @@ +import iconNotePencil from '@phosphor-icons/core/regular/note-pencil.svg'; import React, { useCallback } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -103,7 +104,7 @@ const ChatPane = () => { toggleChatPane(); } }} - secondaryActionIcon={require('@phosphor-icons/core/regular/note-pencil.svg')} + secondaryActionIcon={iconNotePencil} secondaryActionTitle={intl.formatMessage(messages.newChat)} /> diff --git a/packages/nicolium/src/features/chats/components/chat-search/chat-search.tsx b/packages/nicolium/src/features/chats/components/chat-search/chat-search.tsx index 3e0ea5e2c..3bf1a7413 100644 --- a/packages/nicolium/src/features/chats/components/chat-search/chat-search.tsx +++ b/packages/nicolium/src/features/chats/components/chat-search/chat-search.tsx @@ -1,3 +1,5 @@ +import iconMagnifyingGlass from '@phosphor-icons/core/regular/magnifying-glass.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import { useMutation } from '@tanstack/react-query'; import { useNavigate } from '@tanstack/react-router'; import React, { useRef, useState } from 'react'; @@ -110,11 +112,7 @@ const ChatSearch: React.FC = ({ isMainPage = false }) => { )} >
navigate({ to: '/chats' })} title={intl.formatMessage(messages.back)} @@ -156,7 +160,7 @@ const ChatsPageChat = () => {
(
diff --git a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-new.tsx b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-new.tsx index 12720c7c8..8ef178c7b 100644 --- a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-new.tsx +++ b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-new.tsx @@ -1,3 +1,4 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; import { useNavigate } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -21,7 +22,7 @@ const ChatsPageNew: React.FC = () => {
navigate({ to: '/chats' })} title={intl.formatMessage(messages.back)} diff --git a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx index f46610a95..e2247ee15 100644 --- a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx +++ b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-settings.tsx @@ -1,3 +1,4 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; import { useNavigate } from '@tanstack/react-router'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -72,7 +73,7 @@ const ChatsPageSettings = () => {
navigate({ to: '/chats' })} title={intl.formatMessage(messages.back)} diff --git a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx index 21528cbf7..5afd5b334 100644 --- a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx +++ b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx @@ -1,3 +1,4 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; import { useNavigate } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -25,7 +26,7 @@ const ChatsPageShoutbox = () => {
navigate({ to: '/chats' })} title={intl.formatMessage(messages.back)} diff --git a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx index acabbb533..955c066a2 100644 --- a/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx +++ b/packages/nicolium/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx @@ -1,3 +1,5 @@ +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconSlidersHorizontal from '@phosphor-icons/core/regular/sliders-horizontal.svg'; import { useNavigate } from '@tanstack/react-router'; import React, { useCallback } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -45,14 +47,14 @@ const ChatsPageSidebar = () => {
= ({ disabled, onSelectFile }) => { return (
@@ -251,14 +250,14 @@ const getLanguageDropdown = title={intl.formatMessage(messages.deleteLanguage)} onClick={handleDeleteLanguageClick} > - + ) : ( ))} @@ -301,9 +300,9 @@ const LanguageDropdownButton: React.FC = ({ composeId, return ( ); diff --git a/packages/nicolium/src/features/compose/components/location-button.tsx b/packages/nicolium/src/features/compose/components/location-button.tsx index 15740ca8f..cee9ed331 100644 --- a/packages/nicolium/src/features/compose/components/location-button.tsx +++ b/packages/nicolium/src/features/compose/components/location-button.tsx @@ -1,3 +1,4 @@ +import iconMapPin from '@phosphor-icons/core/regular/map-pin.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -44,7 +45,7 @@ const LocationButton: React.FC = ({ composeId }) => { return ( = ({ composeId }) => {
{location ? (
- +
{location.description} @@ -53,7 +51,7 @@ const LocationForm: React.FC = ({ composeId }) => {
{ onChangeLocation(null); }} diff --git a/packages/nicolium/src/features/compose/components/poll-button.tsx b/packages/nicolium/src/features/compose/components/poll-button.tsx index 8f700518c..7905cfa95 100644 --- a/packages/nicolium/src/features/compose/components/poll-button.tsx +++ b/packages/nicolium/src/features/compose/components/poll-button.tsx @@ -1,3 +1,4 @@ +import iconChartBar from '@phosphor-icons/core/regular/chart-bar.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -36,7 +37,7 @@ const PollButton: React.FC = ({ composeId, disabled }) => { return ( [ { - icon: require('@phosphor-icons/core/regular/globe.svg'), + icon: iconGlobe, value: 'public', text: intl.formatMessage(messages.publicShort), meta: intl.formatMessage(messages.publicLong), }, { - icon: require('@phosphor-icons/core/regular/moon.svg'), + icon: iconMoon, value: 'unlisted', text: intl.formatMessage(messages.unlistedShort), meta: intl.formatMessage(messages.unlistedLong), }, { - icon: require('@phosphor-icons/core/regular/lock.svg'), + icon: iconLock, value: 'private', text: intl.formatMessage(messages.privateShort), meta: intl.formatMessage(messages.privateLong), }, isReply && features.createStatusConversationScope ? { - icon: require('@phosphor-icons/core/regular/chats-circle.svg'), + icon: iconChatsCircle, value: 'conversation', text: intl.formatMessage(messages.conversationShort), meta: intl.formatMessage(messages.conversationLong), @@ -90,7 +101,7 @@ const getItems = ( : undefined, features.createStatusMutualsOnlyScope ? { - icon: require('@phosphor-icons/core/regular/users-three.svg'), + icon: iconUsersThree, value: 'mutuals_only', text: intl.formatMessage(messages.mutualsOnlyShort), meta: intl.formatMessage(messages.mutualsOnlyLong), @@ -98,21 +109,21 @@ const getItems = ( : undefined, features.createStatusSubscribersScope ? { - icon: require('@phosphor-icons/core/regular/coins.svg'), + icon: iconCoins, value: 'subscribers', text: intl.formatMessage(messages.subscribersShort), meta: intl.formatMessage(messages.subscribersLong), } : undefined, { - icon: require('@phosphor-icons/core/regular/at.svg'), + icon: iconAt, value: 'direct', text: intl.formatMessage(messages.directShort), meta: intl.formatMessage(messages.directLong), }, features.createStatusLocalScope ? { - icon: require('@phosphor-icons/core/regular/planet.svg'), + icon: iconPlanet, value: 'local', text: intl.formatMessage(messages.localShort), meta: intl.formatMessage(messages.localLong), @@ -120,10 +131,10 @@ const getItems = ( : undefined, features.createStatusListScope && Object.keys(lists).length ? ({ - icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + icon: iconListDashes, value: '', items: Object.values(lists).map((list) => ({ - icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + icon: iconListDashes, value: `list:${list.id}`, text: list.title, })), @@ -133,10 +144,10 @@ const getItems = ( : undefined, features.circles && Object.keys(circles).length ? ({ - icon: require('@phosphor-icons/core/regular/circles-three.svg'), + icon: iconCirclesThree, value: '', items: Object.values(circles).map((circle) => ({ - icon: require('@phosphor-icons/core/regular/list-dashes.svg'), + icon: iconListDashes, value: `circle:${circle.id}`, text: circle.title, })), @@ -188,7 +199,7 @@ const PrivacyDropdown: React.FC = ({ composeId, compact }) => if (features.localOnlyStatuses) items.push({ - icon: require('@phosphor-icons/core/regular/planet.svg'), + icon: iconPlanet, text: intl.formatMessage(messages.localShort), meta: intl.formatMessage(messages.localLong), type: 'toggle', @@ -222,7 +233,7 @@ const PrivacyDropdown: React.FC = ({ composeId, compact }) => ); diff --git a/packages/nicolium/src/features/compose/components/reply-indicator.tsx b/packages/nicolium/src/features/compose/components/reply-indicator.tsx index f0ae5bc4c..c4cb75f46 100644 --- a/packages/nicolium/src/features/compose/components/reply-indicator.tsx +++ b/packages/nicolium/src/features/compose/components/reply-indicator.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import clsx from 'clsx'; import React from 'react'; @@ -49,7 +50,7 @@ const ReplyIndicator: React.FC = ({ if (!hideActions && onCancel) { actions = { onActionClick: handleClick, - actionIcon: require('@phosphor-icons/core/regular/x.svg'), + actionIcon: iconX, actionAlignment: 'top', actionTitle: 'Dismiss', }; diff --git a/packages/nicolium/src/features/compose/components/schedule-button.tsx b/packages/nicolium/src/features/compose/components/schedule-button.tsx index 978fb538e..7bbe809fd 100644 --- a/packages/nicolium/src/features/compose/components/schedule-button.tsx +++ b/packages/nicolium/src/features/compose/components/schedule-button.tsx @@ -1,3 +1,4 @@ +import iconCalendarPlus from '@phosphor-icons/core/regular/calendar-plus.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -36,7 +37,7 @@ const ScheduleButton: React.FC = ({ composeId, disabled }) => { return ( = ({ composeId }) => { /> diff --git a/packages/nicolium/src/features/compose/components/sensitive-media-button.tsx b/packages/nicolium/src/features/compose/components/sensitive-media-button.tsx index e68158188..c1328e9f5 100644 --- a/packages/nicolium/src/features/compose/components/sensitive-media-button.tsx +++ b/packages/nicolium/src/features/compose/components/sensitive-media-button.tsx @@ -1,3 +1,4 @@ +import iconWarning from '@phosphor-icons/core/regular/warning.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -30,7 +31,7 @@ const SensitiveMediaButton: React.FC = ({ composeId }) => return ( = ({ return null; } - const src = - icon ?? - (onlyImages(attachmentTypes) - ? require('@phosphor-icons/core/regular/image.svg') - : require('@phosphor-icons/core/regular/paperclip.svg')); + const src = icon ?? (onlyImages(attachmentTypes) ? iconImage : iconPaperclip); return (
diff --git a/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx b/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx index 2cf99ea32..9f8dcd798 100644 --- a/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx +++ b/packages/nicolium/src/features/compose/containers/preview-compose-container.tsx @@ -1,3 +1,5 @@ +import iconEye from '@phosphor-icons/core/regular/eye.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -59,10 +61,7 @@ const PreviewComposeContainer: React.FC = ({ composeId }
- + @@ -72,7 +71,7 @@ const PreviewComposeContainer: React.FC = ({ composeId } - + )} diff --git a/packages/nicolium/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx b/packages/nicolium/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx index af393a5c5..e2517e02a 100644 --- a/packages/nicolium/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx +++ b/packages/nicolium/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx @@ -7,6 +7,8 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; import { $createHorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode'; import { $wrapNodeInElement, mergeRegister } from '@lexical/utils'; +import iconImage from '@phosphor-icons/core/regular/image.svg'; +import iconMinus from '@phosphor-icons/core/regular/minus.svg'; import { $createParagraphNode, $getSelection, @@ -76,7 +78,7 @@ const UploadButton: React.FC = ({ onSelectFile }) => { fileElement.current?.click(); }; - const src = require('@phosphor-icons/core/regular/image.svg'); + const src = iconImage; return (
) : ( @@ -242,11 +240,7 @@ const FloatingLinkEditor = ({ } }} > - +
)} diff --git a/packages/nicolium/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx b/packages/nicolium/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx index e009e6c61..56b9f840a 100644 --- a/packages/nicolium/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx +++ b/packages/nicolium/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx @@ -22,6 +22,24 @@ import { } from '@lexical/rich-text'; import { $setBlocksType } from '@lexical/selection'; import { $findMatchingParent, $getNearestNodeOfType, mergeRegister } from '@lexical/utils'; +import iconCaretDown from '@phosphor-icons/core/regular/caret-down.svg'; +import iconCode from '@phosphor-icons/core/regular/code.svg'; +import iconLinkSimpleHorizontal from '@phosphor-icons/core/regular/link-simple-horizontal.svg'; +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; +import iconListChecks from '@phosphor-icons/core/regular/list-checks.svg'; +import iconListNumbers from '@phosphor-icons/core/regular/list-numbers.svg'; +import iconQuotes from '@phosphor-icons/core/regular/quotes.svg'; +import iconTextAlignLeft from '@phosphor-icons/core/regular/text-align-left.svg'; +import iconTextB from '@phosphor-icons/core/regular/text-b.svg'; +import iconTextHFive from '@phosphor-icons/core/regular/text-h-five.svg'; +import iconTextHFour from '@phosphor-icons/core/regular/text-h-four.svg'; +import iconTextHOne from '@phosphor-icons/core/regular/text-h-one.svg'; +import iconTextHSix from '@phosphor-icons/core/regular/text-h-six.svg'; +import iconTextHThree from '@phosphor-icons/core/regular/text-h-three.svg'; +import iconTextHTwo from '@phosphor-icons/core/regular/text-h-two.svg'; +import iconTextItalic from '@phosphor-icons/core/regular/text-italic.svg'; +import iconTextStrikethrough from '@phosphor-icons/core/regular/text-strikethrough.svg'; +import iconTextUnderline from '@phosphor-icons/core/regular/text-underline.svg'; import clsx from 'clsx'; import { $createParagraphNode, @@ -74,18 +92,18 @@ const messages = defineMessages({ }); const blockTypeToIcon = { - bullet: require('@phosphor-icons/core/regular/list-bullets.svg'), - check: require('@phosphor-icons/core/regular/list-checks.svg'), - code: require('@phosphor-icons/core/regular/code.svg'), - h1: require('@phosphor-icons/core/regular/text-h-one.svg'), - h2: require('@phosphor-icons/core/regular/text-h-two.svg'), - h3: require('@phosphor-icons/core/regular/text-h-three.svg'), - h4: require('@phosphor-icons/core/regular/text-h-four.svg'), - h5: require('@phosphor-icons/core/regular/text-h-five.svg'), - h6: require('@phosphor-icons/core/regular/text-h-six.svg'), - number: require('@phosphor-icons/core/regular/list-numbers.svg'), - paragraph: require('@phosphor-icons/core/regular/text-align-left.svg'), - quote: require('@phosphor-icons/core/regular/quotes.svg'), + bullet: iconListBullets, + check: iconListChecks, + code: iconCode, + h1: iconTextHOne, + h2: iconTextHTwo, + h3: iconTextHThree, + h4: iconTextHFour, + h5: iconTextHFive, + h6: iconTextHSix, + number: iconListNumbers, + paragraph: iconTextAlignLeft, + quote: iconQuotes, }; const blockTypeToBlockName = { @@ -212,10 +230,7 @@ const BlockTypeDropdown = ({ type='button' > - + {showDropDown && (
{ @@ -411,7 +426,7 @@ const TextFormatFloatingToolbar = ({ active={isItalic} aria-label={intl.formatMessage(messages.formatItalic)} title={intl.formatMessage(messages.formatItalic)} - icon={require('@phosphor-icons/core/regular/text-italic.svg')} + icon={iconTextItalic} /> { @@ -420,7 +435,7 @@ const TextFormatFloatingToolbar = ({ active={isUnderline} aria-label={intl.formatMessage(messages.formatUnderline)} title={intl.formatMessage(messages.formatUnderline)} - icon={require('@phosphor-icons/core/regular/text-underline.svg')} + icon={iconTextUnderline} /> { @@ -429,7 +444,7 @@ const TextFormatFloatingToolbar = ({ active={isStrikethrough} aria-label={intl.formatMessage(messages.formatStrikethrough)} title={intl.formatMessage(messages.formatStrikethrough)} - icon={require('@phosphor-icons/core/regular/text-strikethrough.svg')} + icon={iconTextStrikethrough} /> { @@ -438,14 +453,14 @@ const TextFormatFloatingToolbar = ({ active={isCode} aria-label={intl.formatMessage(messages.insertCodeBlock)} title={intl.formatMessage(messages.insertCodeBlock)} - icon={require('@phosphor-icons/core/regular/code.svg')} + icon={iconCode} /> )} diff --git a/packages/nicolium/src/features/crypto-donate/components/crypto-address.tsx b/packages/nicolium/src/features/crypto-donate/components/crypto-address.tsx index 7e2d22db0..6f7425036 100644 --- a/packages/nicolium/src/features/crypto-donate/components/crypto-address.tsx +++ b/packages/nicolium/src/features/crypto-donate/components/crypto-address.tsx @@ -1,3 +1,4 @@ +import iconQrCode from '@phosphor-icons/core/regular/qr-code.svg'; import React from 'react'; import CopyableInput from '@/components/copyable-input'; @@ -40,7 +41,7 @@ const CryptoAddress: React.FC = (props): React.JSX.Element => {
diff --git a/packages/nicolium/src/features/emoji/components/emoji-picker.tsx b/packages/nicolium/src/features/emoji/components/emoji-picker.tsx index 5c08796b5..39c8a45a7 100644 --- a/packages/nicolium/src/features/emoji/components/emoji-picker.tsx +++ b/packages/nicolium/src/features/emoji/components/emoji-picker.tsx @@ -1,3 +1,4 @@ +import spritesheetURL from 'emoji-datasource/img/twitter/sheets/32.png'; import { Picker as EmojiPicker } from 'emoji-mart'; import React, { useRef, useEffect } from 'react'; @@ -5,7 +6,7 @@ import { joinPublicPath } from '@/utils/static'; import data from '../data'; -const getSpritesheetURL = () => require('emoji-datasource/img/twitter/sheets/32.png'); +const getSpritesheetURL = () => spritesheetURL; const getImageURL = (set: string, name: string) => joinPublicPath(`/packs/emoji/${name}.svg`); diff --git a/packages/nicolium/src/features/emoji/containers/emoji-picker-dropdown-container.tsx b/packages/nicolium/src/features/emoji/containers/emoji-picker-dropdown-container.tsx index 67c8410e9..2b8976019 100644 --- a/packages/nicolium/src/features/emoji/containers/emoji-picker-dropdown-container.tsx +++ b/packages/nicolium/src/features/emoji/containers/emoji-picker-dropdown-container.tsx @@ -1,4 +1,5 @@ import { useFloating, shift, flip, autoUpdate, useTransitionStyles } from '@floating-ui/react'; +import iconSmiley from '@phosphor-icons/core/regular/smiley.svg'; import clsx from 'clsx'; import React, { useMemo, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -92,7 +93,7 @@ const EmojiPickerDropdownContainer: React.FC = ({ theme === 'inverse', })} ref={refs.setReference} - src={require('@phosphor-icons/core/regular/smiley.svg')} + src={iconSmiley} title={title} aria-label={title} aria-expanded={isOpen} diff --git a/packages/nicolium/src/features/federation-restrictions/components/instance-restrictions.tsx b/packages/nicolium/src/features/federation-restrictions/components/instance-restrictions.tsx index 88040cea4..2dbf86d89 100644 --- a/packages/nicolium/src/features/federation-restrictions/components/instance-restrictions.tsx +++ b/packages/nicolium/src/features/federation-restrictions/components/instance-restrictions.tsx @@ -1,3 +1,9 @@ +import iconCheck from '@phosphor-icons/core/regular/check.svg'; +import iconEyeSlash from '@phosphor-icons/core/regular/eye-slash.svg'; +import iconImageBroken from '@phosphor-icons/core/regular/image-broken.svg'; +import iconLockOpen from '@phosphor-icons/core/regular/lock-open.svg'; +import iconLock from '@phosphor-icons/core/regular/lock.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -49,7 +55,7 @@ const InstanceRestrictions: React.FC = ({ remoteInstance if (followers_only) { items.push( - + = ({ remoteInstance ); } else if (federated_timeline_removal) { items.push( - + = ({ remoteInstance if (fullMediaRemoval) { items.push( - + = ({ remoteInstance ); } else if (partialMediaRemoval) { items.push( - + = ({ remoteInstance if (!fullMediaRemoval && media_nsfw) { items.push( - + = ({ remoteInstance if (remoteInstance.federation.reject) { return ( - + = ({ remoteInstance } else if (hasRestrictions(remoteInstance)) { return ( <> - + = ({ remoteInstance ); } else { return ( - + = ({ host }) => { return (
- +
{remoteInstance.host}
diff --git a/packages/nicolium/src/features/status/components/detailed-status.tsx b/packages/nicolium/src/features/status/components/detailed-status.tsx index 52e23df4a..de7d7edc2 100644 --- a/packages/nicolium/src/features/status/components/detailed-status.tsx +++ b/packages/nicolium/src/features/status/components/detailed-status.tsx @@ -1,3 +1,4 @@ +import iconUsersThree from '@phosphor-icons/core/regular/users-three.svg'; import { Link } from '@tanstack/react-router'; import React, { useRef } from 'react'; import { defineMessages, FormattedDate, FormattedMessage, useIntl } from 'react-intl'; @@ -55,7 +56,7 @@ const DetailedStatus: React.FC = ({ avatarSize={42} icon={ diff --git a/packages/nicolium/src/features/status/components/status-type-icon.tsx b/packages/nicolium/src/features/status/components/status-type-icon.tsx index 080621d5e..131d1bee9 100644 --- a/packages/nicolium/src/features/status/components/status-type-icon.tsx +++ b/packages/nicolium/src/features/status/components/status-type-icon.tsx @@ -1,3 +1,9 @@ +import iconAt from '@phosphor-icons/core/regular/at.svg'; +import iconCoins from '@phosphor-icons/core/regular/coins.svg'; +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; +import iconLock from '@phosphor-icons/core/regular/lock.svg'; +import iconPlanet from '@phosphor-icons/core/regular/planet.svg'; +import iconUsersThree from '@phosphor-icons/core/regular/users-three.svg'; import React from 'react'; import { defineMessages, type MessageDescriptor, useIntl } from 'react-intl'; @@ -41,12 +47,12 @@ const messages: Record = defineMessages({ }); const STATUS_TYPE_ICONS: Record = { - direct: require('@phosphor-icons/core/regular/at.svg'), - private: require('@phosphor-icons/core/regular/lock.svg'), - mutuals_only: require('@phosphor-icons/core/regular/users-three.svg'), - local: require('@phosphor-icons/core/regular/planet.svg'), - list: require('@phosphor-icons/core/regular/list-bullets.svg'), - subscribers: require('@phosphor-icons/core/regular/coins.svg'), + direct: iconAt, + private: iconLock, + mutuals_only: iconUsersThree, + local: iconPlanet, + list: iconListBullets, + subscribers: iconCoins, }; const StatusTypeIcon: React.FC = React.memo(({ visibility }) => { diff --git a/packages/nicolium/src/features/ui/components/profile-dropdown.tsx b/packages/nicolium/src/features/ui/components/profile-dropdown.tsx index 1ee3214c8..fff07b946 100644 --- a/packages/nicolium/src/features/ui/components/profile-dropdown.tsx +++ b/packages/nicolium/src/features/ui/components/profile-dropdown.tsx @@ -1,3 +1,5 @@ +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; +import iconSignOut from '@phosphor-icons/core/regular/sign-out.svg'; import { Link, type LinkOptions } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useMemo } from 'react'; @@ -92,14 +94,14 @@ const ProfileDropdown: React.FC = ({ account, children }) => { menu.push({ text: intl.formatMessage(messages.add), linkOptions: { to: '/login/add' }, - icon: require('@phosphor-icons/core/regular/plus.svg'), + icon: iconPlus, }); menu.push({ text: intl.formatMessage(messages.logout, { acct: account.acct }), linkOptions: { to: '/logout' }, action: handleLogOut, - icon: require('@phosphor-icons/core/regular/sign-out.svg'), + icon: iconSignOut, }); return () => ( diff --git a/packages/nicolium/src/features/ui/components/theme-selector.tsx b/packages/nicolium/src/features/ui/components/theme-selector.tsx index 20bd6d432..52bb5a97e 100644 --- a/packages/nicolium/src/features/ui/components/theme-selector.tsx +++ b/packages/nicolium/src/features/ui/components/theme-selector.tsx @@ -1,3 +1,8 @@ +import iconCaretDown from '@phosphor-icons/core/regular/caret-down.svg'; +import iconDesktop from '@phosphor-icons/core/regular/desktop.svg'; +import iconMoonStars from '@phosphor-icons/core/regular/moon-stars.svg'; +import iconMoon from '@phosphor-icons/core/regular/moon.svg'; +import iconSunDim from '@phosphor-icons/core/regular/sun-dim.svg'; import React, { useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -15,13 +20,13 @@ const ThemeSelector: React.FC = ({ id, value, onChange }) => { const themeIconSrc = useMemo(() => { switch (value) { case 'system': - return require('@phosphor-icons/core/regular/desktop.svg'); + return iconDesktop; case 'light': - return require('@phosphor-icons/core/regular/sun-dim.svg'); + return iconSunDim; case 'dark': - return require('@phosphor-icons/core/regular/moon.svg'); + return iconMoon; case 'black': - return require('@phosphor-icons/core/regular/moon-stars.svg'); + return iconMoonStars; default: return null; } @@ -34,7 +39,15 @@ const ThemeSelector: React.FC = ({ id, value, onChange }) => { return (
- + {themeIconSrc ? ( + + ) : ( +
+ )}
- +
); diff --git a/packages/nicolium/src/hooks/use-timeline-filters-options.ts b/packages/nicolium/src/hooks/use-timeline-filters-options.ts index 858045809..30d8205b5 100644 --- a/packages/nicolium/src/hooks/use-timeline-filters-options.ts +++ b/packages/nicolium/src/hooks/use-timeline-filters-options.ts @@ -111,7 +111,7 @@ const useTimelineFiltersOptions = ( // items.push({ // text: intl.formatMessage(messages.setAsDefault), - // icon: require('@phosphor-icons/core/regular/house.svg'), + // icon: iconHouse, // }); // } diff --git a/packages/nicolium/src/layouts/group-layout.tsx b/packages/nicolium/src/layouts/group-layout.tsx index d6b4453d9..d91d7f811 100644 --- a/packages/nicolium/src/layouts/group-layout.tsx +++ b/packages/nicolium/src/layouts/group-layout.tsx @@ -1,3 +1,4 @@ +import iconEyeSlash from '@phosphor-icons/core/regular/eye-slash.svg'; import { Outlet, useLocation } from '@tanstack/react-router'; import React, { useMemo } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -24,10 +25,7 @@ const messages = defineMessages({ const PrivacyBlankslate = () => (
- +
diff --git a/packages/nicolium/src/modals/antenna-editor-modal.tsx b/packages/nicolium/src/modals/antenna-editor-modal.tsx index 9964ca0f4..c4d929659 100644 --- a/packages/nicolium/src/modals/antenna-editor-modal.tsx +++ b/packages/nicolium/src/modals/antenna-editor-modal.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import React, { useMemo, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -257,7 +258,7 @@ const AntennaValuesForm: React.FC = ({
{item} = ({
{item} = ({ values={{ combo: ( - Shift +{' '} - + Shift + ), }} diff --git a/packages/nicolium/src/modals/compose-interaction-policy-modal.tsx b/packages/nicolium/src/modals/compose-interaction-policy-modal.tsx index 393764bbe..874961d49 100644 --- a/packages/nicolium/src/modals/compose-interaction-policy-modal.tsx +++ b/packages/nicolium/src/modals/compose-interaction-policy-modal.tsx @@ -1,3 +1,4 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; import { Link } from '@tanstack/react-router'; import { create } from 'mutative'; import React, { useEffect, useState } from 'react'; @@ -92,11 +93,7 @@ const ComposeInteractionPolicyModal: React.FC< /> } onClose={onClickClose} - closeIcon={ - composeId === 'compose-modal' - ? require('@phosphor-icons/core/regular/arrow-left.svg') - : undefined - } + closeIcon={composeId === 'compose-modal' ? iconArrowLeft : undefined} closePosition={composeId === 'compose-modal' ? 'left' : undefined} >
diff --git a/packages/nicolium/src/modals/edit-bookmark-folder-modal.tsx b/packages/nicolium/src/modals/edit-bookmark-folder-modal.tsx index 4325d85dc..05743808a 100644 --- a/packages/nicolium/src/modals/edit-bookmark-folder-modal.tsx +++ b/packages/nicolium/src/modals/edit-bookmark-folder-modal.tsx @@ -1,4 +1,5 @@ import { useFloating, shift, autoUpdate, flip } from '@floating-ui/react'; +import iconSmiley from '@phosphor-icons/core/regular/smiley.svg'; import React, { useState } from 'react'; import { createPortal } from 'react-dom'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -73,7 +74,7 @@ const EmojiPicker: React.FC = ({ emoji, emojiUrl, ...props }) => { ) : ( )} diff --git a/packages/nicolium/src/modals/event-map-modal.tsx b/packages/nicolium/src/modals/event-map-modal.tsx index 8e9a82db9..9554d3792 100644 --- a/packages/nicolium/src/modals/event-map-modal.tsx +++ b/packages/nicolium/src/modals/event-map-modal.tsx @@ -1,19 +1,23 @@ +import iconCompass from '@phosphor-icons/core/regular/compass.svg'; import L from 'leaflet'; +import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png'; +import iconUrl from 'leaflet/dist/images/marker-icon.png'; +import shadowUrl from 'leaflet/dist/images/marker-shadow.png'; import React, { useEffect, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; +import 'leaflet/dist/leaflet.css'; import Button from '@/components/ui/button'; import Modal from '@/components/ui/modal'; import { useFrontendConfig } from '@/hooks/use-frontend-config'; import { useMinimalStatus } from '@/queries/statuses/use-status'; -import 'leaflet/dist/leaflet.css'; import type { BaseModalProps } from '@/features/ui/components/modal-root'; L.Icon.Default.mergeOptions({ - iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'), - iconUrl: require('leaflet/dist/images/marker-icon.png'), - shadowUrl: require('leaflet/dist/images/marker-shadow.png'), + iconRetinaUrl, + iconUrl, + shadowUrl, }); interface EventMapModalProps { @@ -65,10 +69,7 @@ const EventMapModal: React.FC = ({ onClose, >
-
diff --git a/packages/nicolium/src/modals/list-adder-modal/components/list.tsx b/packages/nicolium/src/modals/list-adder-modal/components/list.tsx index 26c5656d6..11f748bb1 100644 --- a/packages/nicolium/src/modals/list-adder-modal/components/list.tsx +++ b/packages/nicolium/src/modals/list-adder-modal/components/list.tsx @@ -1,3 +1,6 @@ +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -44,7 +47,7 @@ const List: React.FC = ({ listId, accountId, added }) => { @@ -54,7 +57,7 @@ const List: React.FC = ({ listId, accountId, added }) => { @@ -63,7 +66,7 @@ const List: React.FC = ({ listId, accountId, added }) => { return (
- + {list.title} {button}
diff --git a/packages/nicolium/src/modals/list-editor-modal/components/account.tsx b/packages/nicolium/src/modals/list-editor-modal/components/account.tsx index fa8a45fe5..222ddf9dd 100644 --- a/packages/nicolium/src/modals/list-editor-modal/components/account.tsx +++ b/packages/nicolium/src/modals/list-editor-modal/components/account.tsx @@ -1,3 +1,5 @@ +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -24,7 +26,7 @@ const Account: React.FC = ({ accountId, added, onAdd, onRemove }) => { if (added) { button = ( = ({ accountId, added, onAdd, onRemove }) => { } else { button = ( = ({ value, onSubmit }) => { }} > diff --git a/packages/nicolium/src/modals/manage-group-modal/steps/confirmation-step.tsx b/packages/nicolium/src/modals/manage-group-modal/steps/confirmation-step.tsx index 83ff8a5f4..5a4e6a221 100644 --- a/packages/nicolium/src/modals/manage-group-modal/steps/confirmation-step.tsx +++ b/packages/nicolium/src/modals/manage-group-modal/steps/confirmation-step.tsx @@ -1,3 +1,5 @@ +import iconExport from '@phosphor-icons/core/regular/export.svg'; +import iconLinkSimple from '@phosphor-icons/core/regular/link-simple.svg'; import React from 'react'; import { FormattedMessage, defineMessages } from 'react-intl'; @@ -115,7 +117,7 @@ const ConfirmationStep: React.FC = ({ group }) => {
= (props) => { onClick={handleNextClick} aria-label={intl.formatMessage(messages.next)} > - +
diff --git a/packages/nicolium/src/modals/reply-mentions-modal.tsx b/packages/nicolium/src/modals/reply-mentions-modal.tsx index 4e02a4100..470457974 100644 --- a/packages/nicolium/src/modals/reply-mentions-modal.tsx +++ b/packages/nicolium/src/modals/reply-mentions-modal.tsx @@ -1,3 +1,6 @@ +import iconArrowLeft from '@phosphor-icons/core/regular/arrow-left.svg'; +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -52,7 +55,7 @@ const ReplyMentionAccount: React.FC = ({ composeId, accoun if (added) { button = ( = ({ composeId, accoun } else { button = ( = ( } onClose={onClickClose} - closeIcon={require('@phosphor-icons/core/regular/arrow-left.svg')} + closeIcon={iconArrowLeft} closePosition='left' >
diff --git a/packages/nicolium/src/modals/report-modal/steps/other-actions-step.tsx b/packages/nicolium/src/modals/report-modal/steps/other-actions-step.tsx index 020b2d191..40798307c 100644 --- a/packages/nicolium/src/modals/report-modal/steps/other-actions-step.tsx +++ b/packages/nicolium/src/modals/report-modal/steps/other-actions-step.tsx @@ -1,3 +1,5 @@ +import iconArrowsInSimple from '@phosphor-icons/core/regular/arrows-in-simple.svg'; +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; import React, { useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -106,7 +108,7 @@ const OtherActionsStep = ({
) : (
@@ -126,7 +128,7 @@ const SelectBookmarkFolderModal: React.FC - + ) : ( - + )} {folder.name}
diff --git a/packages/nicolium/src/modals/select-drive-file-modal.tsx b/packages/nicolium/src/modals/select-drive-file-modal.tsx index c506eab07..62458c82b 100644 --- a/packages/nicolium/src/modals/select-drive-file-modal.tsx +++ b/packages/nicolium/src/modals/select-drive-file-modal.tsx @@ -1,3 +1,4 @@ +import iconFolder from '@phosphor-icons/core/regular/folder.svg'; import defaultIcon from '@phosphor-icons/core/regular/paperclip.svg'; import clsx from 'clsx'; import React, { useMemo } from 'react'; @@ -48,10 +49,7 @@ const Folder: React.FC = ({ folder, active, disabled, onSelect, onDoubl onClick={disabled ? undefined : () => onSelect?.(folder)} disabled={disabled} > - + {folder.name} diff --git a/packages/nicolium/src/pages/account-lists/antennas.tsx b/packages/nicolium/src/pages/account-lists/antennas.tsx index 687720487..17313dd72 100644 --- a/packages/nicolium/src/pages/account-lists/antennas.tsx +++ b/packages/nicolium/src/pages/account-lists/antennas.tsx @@ -1,3 +1,6 @@ +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; @@ -39,7 +42,7 @@ const AntennasPage: React.FC = () => { action: () => { openModal('ANTENNA_EDITOR', {}); }, - icon: require('@phosphor-icons/core/regular/plus.svg'), + icon: iconPlus, }, ]; @@ -53,12 +56,7 @@ const AntennasPage: React.FC = () => { return ( - } + action={} >
{/* */} @@ -76,10 +74,7 @@ const AntennasPage: React.FC = () => { params={{ antennaId: antenna.id }} label={
- + {antenna.title}
} diff --git a/packages/nicolium/src/pages/account-lists/circles.tsx b/packages/nicolium/src/pages/account-lists/circles.tsx index 361c3f8fd..8226f9b86 100644 --- a/packages/nicolium/src/pages/account-lists/circles.tsx +++ b/packages/nicolium/src/pages/account-lists/circles.tsx @@ -1,3 +1,4 @@ +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; import React, { useState } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; @@ -100,10 +101,7 @@ const CirclesPage: React.FC = () => { params={{ circleId: circle.id }} label={
- + {circle.title}
} diff --git a/packages/nicolium/src/pages/account-lists/lists.tsx b/packages/nicolium/src/pages/account-lists/lists.tsx index 2ef0b89e3..1b41bb303 100644 --- a/packages/nicolium/src/pages/account-lists/lists.tsx +++ b/packages/nicolium/src/pages/account-lists/lists.tsx @@ -1,3 +1,4 @@ +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; import React, { useState } from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; @@ -111,10 +112,7 @@ const ListsPage: React.FC = () => { params={{ listId: list.id }} label={
- + {list.title}
} diff --git a/packages/nicolium/src/pages/accounts/account-gallery.tsx b/packages/nicolium/src/pages/accounts/account-gallery.tsx index 7ad5dfa7f..1ad0b44fd 100644 --- a/packages/nicolium/src/pages/accounts/account-gallery.tsx +++ b/packages/nicolium/src/pages/accounts/account-gallery.tsx @@ -1,3 +1,5 @@ +import iconEyeSlash from '@phosphor-icons/core/regular/eye-slash.svg'; +import iconSpeakerHigh from '@phosphor-icons/core/regular/speaker-high.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useState } from 'react'; @@ -116,7 +118,7 @@ const MediaItem: React.FC = ({ attachment, onOpenMedia, isLast }) => thumbnail = (
- + {fileExtension}
@@ -126,7 +128,7 @@ const MediaItem: React.FC = ({ attachment, onOpenMedia, isLast }) => if (!visible) { icon = ( - + ); } diff --git a/packages/nicolium/src/pages/auth/components/consumer-button.tsx b/packages/nicolium/src/pages/auth/components/consumer-button.tsx index 9718ce0df..887e5a8a8 100644 --- a/packages/nicolium/src/pages/auth/components/consumer-button.tsx +++ b/packages/nicolium/src/pages/auth/components/consumer-button.tsx @@ -1,3 +1,10 @@ +import iconFacebookLogo from '@phosphor-icons/core/regular/facebook-logo.svg'; +import iconGithubLogo from '@phosphor-icons/core/regular/github-logo.svg'; +import iconGoogleLogo from '@phosphor-icons/core/regular/google-logo.svg'; +import iconKey from '@phosphor-icons/core/regular/key.svg'; +import iconSlackLogo from '@phosphor-icons/core/regular/slack-logo.svg'; +import iconSquaresFour from '@phosphor-icons/core/regular/squares-four.svg'; +import iconTwitterLogo from '@phosphor-icons/core/regular/twitter-logo.svg'; import React from 'react'; import { useIntl, defineMessages } from 'react-intl'; @@ -12,12 +19,12 @@ const messages = defineMessages({ /** Map between OAuth providers and brand icons. */ const BRAND_ICONS: Record = { - twitter: require('@phosphor-icons/core/regular/twitter-logo.svg'), - facebook: require('@phosphor-icons/core/regular/facebook-logo.svg'), - google: require('@phosphor-icons/core/regular/google-logo.svg'), - microsoft: require('@phosphor-icons/core/regular/squares-four.svg'), - slack: require('@phosphor-icons/core/regular/slack-logo.svg'), - github: require('@phosphor-icons/core/regular/github-logo.svg'), + twitter: iconTwitterLogo, + facebook: iconFacebookLogo, + google: iconGoogleLogo, + microsoft: iconSquaresFour, + slack: iconSlackLogo, + github: iconGithubLogo, }; interface IConsumerButton { @@ -28,7 +35,7 @@ interface IConsumerButton { const ConsumerButton: React.FC = ({ provider }) => { const intl = useIntl(); - const icon = BRAND_ICONS[provider] || require('@phosphor-icons/core/regular/key.svg'); + const icon = BRAND_ICONS[provider] || iconKey; const handleClick = () => { prepareRequest(provider); diff --git a/packages/nicolium/src/pages/auth/components/registration-form.tsx b/packages/nicolium/src/pages/auth/components/registration-form.tsx index 7683dad60..088f2562a 100644 --- a/packages/nicolium/src/pages/auth/components/registration-form.tsx +++ b/packages/nicolium/src/pages/auth/components/registration-form.tsx @@ -1,3 +1,4 @@ +import iconAt from '@phosphor-icons/core/regular/at.svg'; import { Link, useNavigate } from '@tanstack/react-router'; import debounce from 'lodash/debounce'; import React, { useState, useRef, useCallback } from 'react'; @@ -298,7 +299,7 @@ const RegistrationForm: React.FC = ({ inviteToken }) => { autoCorrect='off' autoCapitalize='off' pattern='^[a-zA-Z\d_-]+' - icon={require('@phosphor-icons/core/regular/at.svg')} + icon={iconAt} onChange={onUsernameChange} value={params.username} required diff --git a/packages/nicolium/src/pages/dashboard/account.tsx b/packages/nicolium/src/pages/dashboard/account.tsx index fa0303a70..5d1df10c2 100644 --- a/packages/nicolium/src/pages/dashboard/account.tsx +++ b/packages/nicolium/src/pages/dashboard/account.tsx @@ -1,3 +1,4 @@ +import iconArrowSquareOut from '@phosphor-icons/core/regular/arrow-square-out.svg'; import { PLEROMA } from 'pl-api'; import React, { type ChangeEventHandler, useMemo, useState } from 'react'; import { defineMessages, FormattedMessage, type MessageDescriptor, useIntl } from 'react-intl'; @@ -344,12 +345,7 @@ const AdminAccountPage: React.FC = () => { {features.version.software === PLEROMA && (
-
)} @@ -87,10 +88,7 @@ const ReportStatuses: React.FC = ({ statusIds }) => { }} className='flex size-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50' > - +
)} @@ -268,7 +266,7 @@ const ReportPage: React.FC = () => { @@ -277,7 +275,7 @@ const ReportPage: React.FC = () => { diff --git a/packages/nicolium/src/pages/dashboard/reports.tsx b/packages/nicolium/src/pages/dashboard/reports.tsx index 77f1dfb8f..2a482ad4f 100644 --- a/packages/nicolium/src/pages/dashboard/reports.tsx +++ b/packages/nicolium/src/pages/dashboard/reports.tsx @@ -1,3 +1,4 @@ +import iconX from '@phosphor-icons/core/regular/x.svg'; import { useNavigate } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedList, FormattedMessage, useIntl } from 'react-intl'; @@ -48,7 +49,7 @@ const Reports: React.FC = () => {
diff --git a/packages/nicolium/src/pages/dashboard/rules.tsx b/packages/nicolium/src/pages/dashboard/rules.tsx index ccc16fe90..6382b6a09 100644 --- a/packages/nicolium/src/pages/dashboard/rules.tsx +++ b/packages/nicolium/src/pages/dashboard/rules.tsx @@ -1,3 +1,4 @@ +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; import React from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -100,7 +101,7 @@ const RulesPage: React.FC = () => {
); @@ -170,7 +185,7 @@ const Breadcrumbs: React.FC = ({ folderId, depth = 0, onClick }) = aria-label={intl.formatMessage(messages.home)} title={intl.formatMessage(messages.home)} > - + {label} ); @@ -181,7 +196,7 @@ const Breadcrumbs: React.FC = ({ folderId, depth = 0, onClick }) = const spacer = (
- +
); @@ -214,7 +229,7 @@ const Breadcrumbs: React.FC = ({ folderId, depth = 0, onClick }) = {spacer}
- +
{spacer} {button} @@ -451,44 +466,44 @@ const File: React.FC = ({ file, index, onMove }) => { isMedia ? { text: intl.formatMessage(messages.fileView), - icon: require('@phosphor-icons/core/regular/eye.svg'), + icon: iconEye, action: handleView, } : { text: intl.formatMessage(messages.fileDownload), - icon: require('@phosphor-icons/core/regular/download.svg'), + icon: iconDownload, href: file.url, }, { text: intl.formatMessage(messages.fileRename), - icon: require('@phosphor-icons/core/regular/cursor-text.svg'), + icon: iconCursorText, action: handleRename, }, { text: intl.formatMessage(messages.updateDescription), - icon: require('@phosphor-icons/core/regular/file-text.svg'), + icon: iconFileText, action: handleUpdateDescription, }, file.sensitive ? { text: intl.formatMessage(messages.unmarkSensitive), - icon: require('@phosphor-icons/core/regular/eye.svg'), + icon: iconEye, action: handleToggleSensitive, } : { text: intl.formatMessage(messages.markSensitive), - icon: require('@phosphor-icons/core/regular/eye-slash.svg'), + icon: iconEyeSlash, action: handleToggleSensitive, }, null, { text: intl.formatMessage(messages.fileMove), - icon: require('@phosphor-icons/core/regular/folders.svg'), + icon: iconFolders, action: handleMove, }, { text: intl.formatMessage(messages.fileDelete), - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, action: handleDelete, }, @@ -517,7 +532,7 @@ const File: React.FC = ({ file, index, onMove }) => { }} > @@ -670,23 +685,23 @@ const Folder: React.FC = ({ folder, index, onMove }) => { return [ { text: intl.formatMessage(messages.folderView), - icon: require('@phosphor-icons/core/regular/folder-open.svg'), + icon: iconFolderOpen, to: '/drive/{-$folderId}', params: { folderId: folder.id ?? undefined }, }, { text: intl.formatMessage(messages.folderRename), - icon: require('@phosphor-icons/core/regular/cursor-text.svg'), + icon: iconCursorText, action: handleRename, }, { text: intl.formatMessage(messages.folderMove), - icon: require('@phosphor-icons/core/regular/folders.svg'), + icon: iconFolders, action: handleMove, }, { text: intl.formatMessage(messages.folderDelete), - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, destructive: true, action: handleDelete, }, @@ -715,17 +730,14 @@ const Folder: React.FC = ({ folder, index, onMove }) => { }} >
- + {folder.name}
@@ -747,7 +759,7 @@ const DrivePage: React.FC = () => { const items: Menu = [ { text: intl.formatMessage(messages.fileUpload), - icon: require('@phosphor-icons/core/regular/upload.svg'), + icon: iconUpload, onSelectFile: (files: FileList) => { uploadFile(files[0], { onSuccess: () => { @@ -761,7 +773,7 @@ const DrivePage: React.FC = () => { }, { text: intl.formatMessage(messages.newFolder), - icon: require('@phosphor-icons/core/regular/folder-plus.svg'), + icon: iconFolderPlus, action: () => { openModal('TEXT_FIELD', { heading: , @@ -812,12 +824,7 @@ const DrivePage: React.FC = () => { label={data?.name ?? intl.formatMessage(messages.heading)} backHref={'/drive/{-$folderId}'} backParams={{ folderId: data?.parent_id ?? undefined }} - action={ - - } + action={} >
@@ -830,7 +837,7 @@ const DrivePage: React.FC = () => { defaultMessage='There are no files or folders in this folder.' /> } - icon={require('@phosphor-icons/core/regular/folder-open.svg')} + icon={iconFolderOpen} /> ) : (
diff --git a/packages/nicolium/src/pages/fun/circle.tsx b/packages/nicolium/src/pages/fun/circle.tsx index 421f4b4bb..fd882c158 100644 --- a/packages/nicolium/src/pages/fun/circle.tsx +++ b/packages/nicolium/src/pages/fun/circle.tsx @@ -21,6 +21,9 @@ import toast from '@/toast'; const toRad = (x: number) => x * (Math.PI / 180); +import iconDownloadSimple from '@phosphor-icons/core/regular/download-simple.svg'; +import iconNotePencil from '@phosphor-icons/core/regular/note-pencil.svg'; + import avatarMissing from '@/assets/images/avatar-missing.png'; const HEIGHT = 1000; @@ -256,16 +259,10 @@ const CirclePage: React.FC = () => {
- -
diff --git a/packages/nicolium/src/pages/groups/edit-group.tsx b/packages/nicolium/src/pages/groups/edit-group.tsx index eed2eade1..aebf958e2 100644 --- a/packages/nicolium/src/pages/groups/edit-group.tsx +++ b/packages/nicolium/src/pages/groups/edit-group.tsx @@ -1,3 +1,4 @@ +import iconLock from '@phosphor-icons/core/regular/lock.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -117,12 +118,7 @@ const EditGroup: React.FC = () => { placeholder={intl.formatMessage(messages.groupNamePlaceholder)} maxLength={maxName} {...displayName} - append={ - - } + append={} disabled /> diff --git a/packages/nicolium/src/pages/groups/groups.tsx b/packages/nicolium/src/pages/groups/groups.tsx index 62b31d658..c77cffa8a 100644 --- a/packages/nicolium/src/pages/groups/groups.tsx +++ b/packages/nicolium/src/pages/groups/groups.tsx @@ -1,3 +1,4 @@ +import iconUsersThree from '@phosphor-icons/core/regular/users-three.svg'; import { Link } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -45,7 +46,7 @@ const Groups: React.FC = () => { {!(!isFetching && groupIds.length === 0) && (
@@ -196,7 +192,7 @@ const SearchResults = () => { diff --git a/packages/nicolium/src/pages/settings/aliases.tsx b/packages/nicolium/src/pages/settings/aliases.tsx index 98b76cfc9..67beca1f1 100644 --- a/packages/nicolium/src/pages/settings/aliases.tsx +++ b/packages/nicolium/src/pages/settings/aliases.tsx @@ -1,3 +1,6 @@ +import iconBackspace from '@phosphor-icons/core/regular/backspace.svg'; +import iconPlus from '@phosphor-icons/core/regular/plus.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import clsx from 'clsx'; import React, { useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -56,7 +59,7 @@ const Account: React.FC = ({ accountId, aliases }) => { if (!added && accountId !== me) { button = ( = ({ onSubmit }) => { title={intl.formatMessage(messages.clear)} > @@ -210,7 +213,7 @@ const AliasesPage = () => { aria-label={intl.formatMessage(messages.delete)} > - + = ({ token, isCurrent }) => { {token.app_name} {token.app_website && ( - + )}

diff --git a/packages/nicolium/src/pages/settings/components/avatar-picker.tsx b/packages/nicolium/src/pages/settings/components/avatar-picker.tsx index 6a7bae157..1a17b0aa9 100644 --- a/packages/nicolium/src/pages/settings/components/avatar-picker.tsx +++ b/packages/nicolium/src/pages/settings/components/avatar-picker.tsx @@ -1,3 +1,4 @@ +import iconCameraPlus from '@phosphor-icons/core/regular/camera-plus.svg'; import clsx from 'clsx'; import React, { useRef } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -80,10 +81,7 @@ const AvatarPicker = React.forwardRef( }, )} > - +
diff --git a/packages/nicolium/src/pages/settings/components/header-picker.tsx b/packages/nicolium/src/pages/settings/components/header-picker.tsx index 78dee1cc7..8e18cee06 100644 --- a/packages/nicolium/src/pages/settings/components/header-picker.tsx +++ b/packages/nicolium/src/pages/settings/components/header-picker.tsx @@ -1,3 +1,5 @@ +import iconUpload from '@phosphor-icons/core/regular/upload.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import clsx from 'clsx'; import React, { useRef } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -96,7 +98,7 @@ const HeaderPicker = React.forwardRef( }, )} > - + @@ -117,7 +119,7 @@ const HeaderPicker = React.forwardRef( {onClear && src && ( = ({ domain }) => { {domain} diff --git a/packages/nicolium/src/pages/settings/rss-feed-subscriptions.tsx b/packages/nicolium/src/pages/settings/rss-feed-subscriptions.tsx index 2ab1865e8..106c0f63d 100644 --- a/packages/nicolium/src/pages/settings/rss-feed-subscriptions.tsx +++ b/packages/nicolium/src/pages/settings/rss-feed-subscriptions.tsx @@ -1,3 +1,5 @@ +import iconRss from '@phosphor-icons/core/regular/rss.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; @@ -123,7 +125,7 @@ const RssFeedSubscriptions = () => { {feed.image_url ? ( ) : ( - + )}
{feed.title} @@ -135,7 +137,7 @@ const RssFeedSubscriptions = () => { onClick={handleDelete(feed.url)} disabled={isPending} className='size-8 text-gray-700 dark:text-gray-600' - src={require('@phosphor-icons/core/regular/x.svg')} + src={iconX} title={intl.formatMessage(messages.deleteFeed)} />
diff --git a/packages/nicolium/src/pages/status-lists/bookmark-folders.tsx b/packages/nicolium/src/pages/status-lists/bookmark-folders.tsx index ff84d4c94..c84148730 100644 --- a/packages/nicolium/src/pages/status-lists/bookmark-folders.tsx +++ b/packages/nicolium/src/pages/status-lists/bookmark-folders.tsx @@ -1,3 +1,5 @@ +import iconBookmarks from '@phosphor-icons/core/regular/bookmarks.svg'; +import iconFolderSimple from '@phosphor-icons/core/regular/folder-simple.svg'; import { Navigate } from '@tanstack/react-router'; import React from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -120,7 +122,7 @@ const BookmarkFoldersPage: React.FC = () => { params={{ folderId: 'all' }} label={
- + { className='size-5 flex-none' /> ) : ( - + )} {folder.name}
diff --git a/packages/nicolium/src/pages/status-lists/bookmarks.tsx b/packages/nicolium/src/pages/status-lists/bookmarks.tsx index 8f5057a8e..dc79c57d4 100644 --- a/packages/nicolium/src/pages/status-lists/bookmarks.tsx +++ b/packages/nicolium/src/pages/status-lists/bookmarks.tsx @@ -1,3 +1,6 @@ +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconTrash from '@phosphor-icons/core/regular/trash.svg'; import { useNavigate } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -101,12 +104,12 @@ const BookmarksPage: React.FC = () => { { text: intl.formatMessage(messages.editFolder), action: handleEditFolder, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, }, { text: intl.formatMessage(messages.deleteFolder), action: handleDeleteFolder, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, }, ] : []; @@ -114,12 +117,7 @@ const BookmarksPage: React.FC = () => { return ( - } + action={} > = ({ statusIds, isLoading, emptyMe }} className='flex size-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50' > - +
)} @@ -89,10 +88,7 @@ const EventCarousel: React.FC = ({ statusIds, isLoading, emptyMe }} className='flex size-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50' > - +
)} diff --git a/packages/nicolium/src/pages/status-lists/interaction-requests.tsx b/packages/nicolium/src/pages/status-lists/interaction-requests.tsx index 9d8a85986..24e29d664 100644 --- a/packages/nicolium/src/pages/status-lists/interaction-requests.tsx +++ b/packages/nicolium/src/pages/status-lists/interaction-requests.tsx @@ -1,3 +1,6 @@ +import iconArrowBendUpLeft from '@phosphor-icons/core/regular/arrow-bend-up-left.svg'; +import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; +import iconStar from '@phosphor-icons/core/regular/star.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import React from 'react'; @@ -61,9 +64,9 @@ const messages = defineMessages({ }); const icons = { - favourite: require('@phosphor-icons/core/regular/star.svg'), - reblog: require('@phosphor-icons/core/regular/repeat.svg'), - reply: require('@phosphor-icons/core/regular/arrow-bend-up-left.svg'), + favourite: iconStar, + reblog: iconRepeat, + reply: iconArrowBendUpLeft, }; const avatarSize = 42; diff --git a/packages/nicolium/src/pages/statuses/event-information.tsx b/packages/nicolium/src/pages/statuses/event-information.tsx index 29aabe2a1..f3795ff5a 100644 --- a/packages/nicolium/src/pages/statuses/event-information.tsx +++ b/packages/nicolium/src/pages/statuses/event-information.tsx @@ -1,3 +1,6 @@ +import iconCalendarDots from '@phosphor-icons/core/regular/calendar-dots.svg'; +import iconLinkSimple from '@phosphor-icons/core/regular/link-simple.svg'; +import iconMapPin from '@phosphor-icons/core/regular/map-pin.svg'; import React, { useCallback } from 'react'; import { FormattedDate, FormattedMessage } from 'react-intl'; @@ -76,7 +79,7 @@ const EventInformationPage: React.FC = () => {
- +

{text}

@@ -104,7 +107,7 @@ const EventInformationPage: React.FC = () => {
- +

{

} - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} /> ); diff --git a/packages/nicolium/src/pages/timelines/community-timeline.tsx b/packages/nicolium/src/pages/timelines/community-timeline.tsx index 2383dc9c2..df513a9a4 100644 --- a/packages/nicolium/src/pages/timelines/community-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/community-timeline.tsx @@ -1,3 +1,5 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -21,12 +23,7 @@ const CommunityTimelinePage = () => { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} - action={ - - } + action={} > { defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} /> ); diff --git a/packages/nicolium/src/pages/timelines/group-timeline.tsx b/packages/nicolium/src/pages/timelines/group-timeline.tsx index c9003b500..da56af871 100644 --- a/packages/nicolium/src/pages/timelines/group-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/group-timeline.tsx @@ -1,3 +1,4 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; import { Link } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useEffect, useRef } from 'react'; @@ -75,7 +76,7 @@ const GroupTimelinePage: React.FC = () => { defaultMessage='There are no posts in this group yet.' /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} // showGroup={falsse} />
diff --git a/packages/nicolium/src/pages/timelines/hashtag-timeline.tsx b/packages/nicolium/src/pages/timelines/hashtag-timeline.tsx index f0a2b129f..5166f1d11 100644 --- a/packages/nicolium/src/pages/timelines/hashtag-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/hashtag-timeline.tsx @@ -1,3 +1,4 @@ +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -38,12 +39,7 @@ const HashtagTimelinePage: React.FC = () => { return ( - } + action={} > {features.followHashtags && isLoggedIn && ( diff --git a/packages/nicolium/src/pages/timelines/home-timeline.tsx b/packages/nicolium/src/pages/timelines/home-timeline.tsx index c565f6696..7481709e2 100644 --- a/packages/nicolium/src/pages/timelines/home-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/home-timeline.tsx @@ -1,3 +1,5 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; @@ -56,12 +58,7 @@ const HomeTimelinePage: React.FC = () => { title={} withBack={false} truncateTitle={false} - action={ - - } + action={} > { )}
} - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} /> ); diff --git a/packages/nicolium/src/pages/timelines/landing-timeline.tsx b/packages/nicolium/src/pages/timelines/landing-timeline.tsx index 079e4b462..2dc8d522a 100644 --- a/packages/nicolium/src/pages/timelines/landing-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/landing-timeline.tsx @@ -1,3 +1,4 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; import clsx from 'clsx'; import React from 'react'; import { FormattedMessage } from 'react-intl'; @@ -82,7 +83,7 @@ const LandingTimelinePage = () => { defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} /> ) : ( diff --git a/packages/nicolium/src/pages/timelines/link-timeline.tsx b/packages/nicolium/src/pages/timelines/link-timeline.tsx index a94281a8a..fb28c3e5b 100644 --- a/packages/nicolium/src/pages/timelines/link-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/link-timeline.tsx @@ -1,3 +1,4 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -27,7 +28,7 @@ const LinkTimelinePage: React.FC = () => { defaultMessage='There are no posts with this link yet.' /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} /> ); diff --git a/packages/nicolium/src/pages/timelines/list-timeline.tsx b/packages/nicolium/src/pages/timelines/list-timeline.tsx index c517b0a72..8a69f11cc 100644 --- a/packages/nicolium/src/pages/timelines/list-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/list-timeline.tsx @@ -1,3 +1,7 @@ +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconListBullets from '@phosphor-icons/core/regular/list-bullets.svg'; +import iconPencilSimple from '@phosphor-icons/core/regular/pencil-simple.svg'; +import iconTrash from '@phosphor-icons/core/regular/trash.svg'; import { useNavigate } from '@tanstack/react-router'; import React, { useMemo } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; @@ -96,12 +100,12 @@ const ListTimelinePage: React.FC = () => { { text: intl.formatMessage(messages.editList), action: handleEditClick, - icon: require('@phosphor-icons/core/regular/pencil-simple.svg'), + icon: iconPencilSimple, }, { text: intl.formatMessage(messages.deleteList), action: handleDeleteClick, - icon: require('@phosphor-icons/core/regular/trash.svg'), + icon: iconTrash, }, ], [timelineFilterOptions], @@ -112,12 +116,7 @@ const ListTimelinePage: React.FC = () => { label={title} title={} truncateTitle={false} - action={ - - } + action={} > {
} - emptyMessageIcon={require('@phosphor-icons/core/regular/list-bullets.svg')} + emptyMessageIcon={iconListBullets} /> ); diff --git a/packages/nicolium/src/pages/timelines/public-timeline.tsx b/packages/nicolium/src/pages/timelines/public-timeline.tsx index c9a9d5d45..9d7271fcf 100644 --- a/packages/nicolium/src/pages/timelines/public-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/public-timeline.tsx @@ -1,3 +1,6 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import { Link } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -41,12 +44,7 @@ const PublicTimelinePage = () => { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} - action={ - - } + action={} > {showExplanationBox && ( { /> } action={dismissExplanationBox} - actionIcon={require('@phosphor-icons/core/regular/x.svg')} + actionIcon={iconX} actionLabel={intl.formatMessage(messages.dismiss)} expanded={explanationBoxExpanded} onToggle={toggleExplanationBox} @@ -88,7 +86,7 @@ const PublicTimelinePage = () => { defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up' /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} /> ); diff --git a/packages/nicolium/src/pages/timelines/remote-timeline.tsx b/packages/nicolium/src/pages/timelines/remote-timeline.tsx index 0a1f2fcad..1820b2483 100644 --- a/packages/nicolium/src/pages/timelines/remote-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/remote-timeline.tsx @@ -1,3 +1,6 @@ +import iconChatCenteredText from '@phosphor-icons/core/regular/chat-centered-text.svg'; +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconX from '@phosphor-icons/core/regular/x.svg'; import { useNavigate } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -37,19 +40,14 @@ const RemoteTimelinePage: React.FC = () => { label={instance} title={} truncateTitle={false} - action={ - - } + action={} > {!pinned && (
@@ -71,7 +69,7 @@ const RemoteTimelinePage: React.FC = () => { values={{ instance }} /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')} + emptyMessageIcon={iconChatCenteredText} instance={instance} /> diff --git a/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx b/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx index 734db59a3..d3d06131c 100644 --- a/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/wrenched-timeline.tsx @@ -1,3 +1,5 @@ +import iconDotsThreeVertical from '@phosphor-icons/core/regular/dots-three-vertical.svg'; +import iconWrench from '@phosphor-icons/core/regular/wrench.svg'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -21,12 +23,7 @@ const WrenchedTimelinePage = () => { label={intl.formatMessage(messages.title)} title={} truncateTitle={false} - action={ - - } + action={} > { defaultMessage='There is nothing here! 🔧 a public post to fill it up' /> } - emptyMessageIcon={require('@phosphor-icons/core/regular/wrench.svg')} + emptyMessageIcon={iconWrench} /> ); From 941b3b5fbb614d2f39f997ea9e0ca9d8e1097745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 18:03:19 +0100 Subject: [PATCH 25/64] nicolium: lint doesn't help sometimes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/columns/notifications.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nicolium/src/columns/notifications.tsx b/packages/nicolium/src/columns/notifications.tsx index 57ffdaf38..42a2cfa40 100644 --- a/packages/nicolium/src/columns/notifications.tsx +++ b/packages/nicolium/src/columns/notifications.tsx @@ -2,8 +2,6 @@ import iconAt from '@phosphor-icons/core/regular/at.svg'; import iconBellSimpleRinging from '@phosphor-icons/core/regular/bell-simple-ringing.svg'; import iconCalendarDots from '@phosphor-icons/core/regular/calendar-dots.svg'; import iconChartBar from '@phosphor-icons/core/regular/chart-bar.svg'; - -import '@/styles/new/notifications.scss'; import iconRepeat from '@phosphor-icons/core/regular/repeat.svg'; import iconStar from '@phosphor-icons/core/regular/star.svg'; import iconUserPlus from '@phosphor-icons/core/regular/user-plus.svg'; @@ -36,6 +34,8 @@ import { selectChild } from '@/utils/scroll-utils'; import type { Item } from '@/components/ui/tabs'; import type { VirtuosoHandle } from 'react-virtuoso'; +import '@/styles/new/notifications.scss'; + const messages = defineMessages({ title: { id: 'column.notifications', defaultMessage: 'Notifications' }, queue: { From 99f57c65d83f4984a00467b0f048373181f323fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 18:15:56 +0100 Subject: [PATCH 26/64] nicolium: remove vite-plugin-require dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/package.json | 1 - .../frontend-config/icon-picker-dropdown.tsx | 2 +- .../frontend-config/icon-picker.tsx | 8 +- packages/nicolium/vite.config.ts | 3 - pnpm-lock.yaml | 539 +++--------------- 5 files changed, 94 insertions(+), 459 deletions(-) diff --git a/packages/nicolium/package.json b/packages/nicolium/package.json index e78c1d7f3..57e9e9266 100644 --- a/packages/nicolium/package.json +++ b/packages/nicolium/package.json @@ -156,7 +156,6 @@ "vite-plugin-compile-time": "^0.4.6", "vite-plugin-html": "^3.2.2", "vite-plugin-pwa": "^1.2.0", - "vite-plugin-require": "^1.2.14", "vite-plugin-static-copy": "^3.3.0", "vitest": "^4.1.0" }, diff --git a/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx index 58258d777..43e946877 100644 --- a/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx +++ b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker-dropdown.tsx @@ -4,6 +4,7 @@ import { defineMessages, useIntl } from 'react-intl'; import ForkAwesomeIcon from '@/components/fork-awesome-icon'; import Popover from '@/components/ui/popover'; +import forkAwesomeIcons from './forkawesome.json'; import IconPickerMenu from './icon-picker-menu'; const messages = defineMessages({ @@ -19,7 +20,6 @@ const IconPickerDropdown: React.FC = ({ value, onPickIcon } const intl = useIntl(); const title = intl.formatMessage(messages.emoji); - const forkAwesomeIcons = require('./forkawesome.json'); return (
diff --git a/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker.tsx b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker.tsx index 059be171a..c36ffed95 100644 --- a/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker.tsx +++ b/packages/nicolium/src/pages/dashboard/components/frontend-config/icon-picker.tsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { Suspense } from 'react'; -import IconPickerDropdown from './icon-picker-dropdown'; +const IconPickerDropdown = React.lazy(() => import('./icon-picker-dropdown')); interface IIconPicker { value: string; @@ -9,7 +9,9 @@ interface IIconPicker { const IconPicker: React.FC = ({ value, onChange }) => (
- + }> + +
); diff --git a/packages/nicolium/vite.config.ts b/packages/nicolium/vite.config.ts index 4fc41b570..615355b8f 100644 --- a/packages/nicolium/vite.config.ts +++ b/packages/nicolium/vite.config.ts @@ -8,7 +8,6 @@ import { defineConfig } from 'vite'; import compileTime from 'vite-plugin-compile-time'; import { createHtmlPlugin } from 'vite-plugin-html'; import { VitePWA } from 'vite-plugin-pwa'; -import vitePluginRequire from 'vite-plugin-require'; import { viteStaticCopy } from 'vite-plugin-static-copy'; const config = defineConfig(() => ({ @@ -35,8 +34,6 @@ const config = defineConfig(() => ({ }, plugins: [ tsgoChecker(), - // @ts-expect-error https://github.com/wangzongming/vite-plugin-require/issues/23 - vitePluginRequire.default(), compileTime(), createHtmlPlugin({ template: 'index.html', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5096f4f7d..afbdcb105 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -380,9 +380,6 @@ importers: vite-plugin-pwa: specifier: ^1.2.0 version: 1.2.0(vite@8.0.0(@types/node@25.5.0)(esbuild@0.24.2)(jiti@1.21.7)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.46.0)(yaml@2.8.2))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0) - vite-plugin-require: - specifier: ^1.2.14 - version: 1.2.14(esbuild@0.24.2)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.24.2)(jiti@1.21.7)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.46.0)(yaml@2.8.2)) vite-plugin-static-copy: specifier: ^3.3.0 version: 3.3.0(vite@8.0.0(@types/node@25.5.0)(esbuild@0.24.2)(jiti@1.21.7)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.46.0)(yaml@2.8.2)) @@ -1828,89 +1825,105 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -2193,96 +2206,112 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-arm64-gnu@0.41.0': resolution: {integrity: sha512-gofu0PuumSOHYczD8p62CPY4UF6ee+rSLZJdUXkpwxg6pILiwSDBIouPskjF/5nF3A7QZTz2O9KFNkNxxFN9tA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-arm64-musl@0.40.0': resolution: {integrity: sha512-tGmWhLD/0YMotCdfezlT6tC/MJG/wKpo4vnQ3Cq+4eBk/BwNv7EmkD0VkD5F/dYkT3b8FNU01X2e8vvJuWoM1w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxfmt/binding-linux-arm64-musl@0.41.0': resolution: {integrity: sha512-VfVZxL0+6RU86T8F8vKiDBa+iHsr8PAjQmKGBzSCAX70b6x+UOMFl+2dNihmKmUwqkCazCPfYjt6SuAPOeQJ3g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxfmt/binding-linux-ppc64-gnu@0.40.0': resolution: {integrity: sha512-rVbFyM3e7YhkVnp0IVYjaSHfrBWcTRWb60LEcdNAJcE2mbhTpbqKufx0FrhWfoxOrW/+7UJonAOShoFFLigDqQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-ppc64-gnu@0.41.0': resolution: {integrity: sha512-bwzokz2eGvdfJbc0i+zXMJ4BBjQPqg13jyWpEEZDOrBCQ91r8KeY2Mi2kUeuMTZNFXju+jcAbAbpyJxRGla0eg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-riscv64-gnu@0.40.0': resolution: {integrity: sha512-3ZqBw14JtWeEoLiioJcXSJz8RQyPE+3jLARnYM1HdPzZG4vk+Ua8CUupt2+d+vSAvMyaQBTN2dZK+kbBS/j5mA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-riscv64-gnu@0.41.0': resolution: {integrity: sha512-POLM//PCH9uqDeNDwWL3b3DkMmI3oI2cU6hwc2lnztD1o7dzrQs3R9nq555BZ6wI7t2lyhT9CS+CRaz5X0XqLA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-riscv64-musl@0.40.0': resolution: {integrity: sha512-JJ4PPSdcbGBjPvb+O7xYm2FmAsKCyuEMYhqatBAHMp/6TA6rVlf9Z/sYPa4/3Bommb+8nndm15SPFRHEPU5qFA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxfmt/binding-linux-riscv64-musl@0.41.0': resolution: {integrity: sha512-NNK7PzhFqLUwx/G12Xtm6scGv7UITvyGdAR5Y+TlqsG+essnuRWR4jRNODWRjzLZod0T3SayRbnkSIWMBov33w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxfmt/binding-linux-s390x-gnu@0.40.0': resolution: {integrity: sha512-Kp0zNJoX9Ik77wUya2tpBY3W9f40VUoMQLWVaob5SgCrblH/t2xr/9B2bWHfs0WCefuGmqXcB+t0Lq77sbBmZw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-s390x-gnu@0.41.0': resolution: {integrity: sha512-qVf/zDC5cN9eKe4qI/O/m445er1IRl6swsSl7jHkqmOSVfknwCe5JXitYjZca+V/cNJSU/xPlC5EFMabMMFDpw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-x64-gnu@0.40.0': resolution: {integrity: sha512-7YTCNzleWTaQTqNGUNQ66qVjpoV6DjbCOea+RnpMBly2bpzrI/uu7Rr+2zcgRfNxyjXaFTVQKaRKjqVdeUfeVA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-x64-gnu@0.41.0': resolution: {integrity: sha512-ojxYWu7vUb6ysYqVCPHuAPVZHAI40gfZ0PDtZAMwVmh2f0V8ExpPIKoAKr7/8sNbAXJBBpZhs2coypIo2jJX4w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxfmt/binding-linux-x64-musl@0.40.0': resolution: {integrity: sha512-hWnSzJ0oegeOwfOEeejYXfBqmnRGHusgtHfCPzmvJvHTwy1s3Neo59UKc1CmpE3zxvrCzJoVHos0rr97GHMNPw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxfmt/binding-linux-x64-musl@0.41.0': resolution: {integrity: sha512-O2exZLBxoCMIv2vlvcbkdedazJPTdG0VSup+0QUCfYQtx751zCZNboX2ZUOiQ/gDTdhtXvSiot0h6GEGkOyalA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxfmt/binding-openharmony-arm64@0.40.0': resolution: {integrity: sha512-28sJC1lR4qtBJGzSRRbPnSW3GxU2+4YyQFE6rCmsUYqZ5XYH8jg0/w+CvEzQ8TuAQz5zLkcA25nFQGwoU0PT3Q==} @@ -2481,96 +2510,112 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-arm64-gnu@1.56.0': resolution: {integrity: sha512-urse2SnugwJRojUkGSSeH2LPMaje5Q50yQtvtL9HFckiyeqXzoFwOAZqD5TR29R2lq7UHidfFDM9EGcchcbb8A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-arm64-musl@1.55.0': resolution: {integrity: sha512-/kp65avi6zZfqEng56TTuhiy3P/3pgklKIdf38yvYeJ9/PgEeRA2A2AqKAKbZBNAqUzrzHhz9jF6j/PZvhJzTQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxlint/binding-linux-arm64-musl@1.56.0': resolution: {integrity: sha512-rkTZkBfJ4TYLjansjSzL6mgZOdN5IvUnSq3oNJSLwBcNvy3dlgQtpHPrRxrCEbbcp7oQ6If0tkNaqfOsphYZ9g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxlint/binding-linux-ppc64-gnu@1.55.0': resolution: {integrity: sha512-A6pTdXwcEEwL/nmz0eUJ6WxmxcoIS+97GbH96gikAyre3s5deC7sts38ZVVowjS2QQFuSWkpA4ZmQC0jZSNvJQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-ppc64-gnu@1.56.0': resolution: {integrity: sha512-uqL1kMH3u69/e1CH2EJhP3CP28jw2ExLsku4o8RVAZ7fySo9zOyI2fy9pVlTAp4voBLVgzndXi3SgtdyCTa2aA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-riscv64-gnu@1.55.0': resolution: {integrity: sha512-clj0lnIN+V52G9tdtZl0LbdTSurnZ1NZj92Je5X4lC7gP5jiCSW+Y/oiDiSauBAD4wrHt2S7nN3pA0zfKYK/6Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-riscv64-gnu@1.56.0': resolution: {integrity: sha512-j0CcMBOgV6KsRaBdsebIeiy7hCjEvq2KdEsiULf2LZqAq0v1M1lWjelhCV57LxsqaIGChXFuFJ0RiFrSRHPhSg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-riscv64-musl@1.55.0': resolution: {integrity: sha512-NNu08pllN5x/O94/sgR3DA8lbrGBnTHsINZZR0hcav1sj79ksTiKKm1mRzvZvacwQ0hUnGinFo+JO75ok2PxYg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxlint/binding-linux-riscv64-musl@1.56.0': resolution: {integrity: sha512-7VDOiL8cDG3DQ/CY3yKjbV1c4YPvc4vH8qW09Vv+5ukq3l/Kcyr6XGCd5NvxUmxqDb2vjMpM+eW/4JrEEsUetA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxlint/binding-linux-s390x-gnu@1.55.0': resolution: {integrity: sha512-BvfQz3PRlWZRoEZ17dZCqgQsMRdpzGZomJkVATwCIGhHVVeHJMQdmdXPSjcT1DCNUrOjXnVyj1RGDj5+/Je2+Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxlint/binding-linux-s390x-gnu@1.56.0': resolution: {integrity: sha512-JGRpX0M+ikD3WpwJ7vKcHKV6Kg0dT52BW2Eu2BupXotYeqGXBrbY+QPkAyKO6MNgKozyTNaRh3r7g+VWgyAQYQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxlint/binding-linux-x64-gnu@1.55.0': resolution: {integrity: sha512-ngSOoFCSBMKVQd24H8zkbcBNc7EHhjnF1sv3mC9NNXQ/4rRjI/4Dj9+9XoDZeFEkF1SX1COSBXF1b2Pr9rqdEw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-x64-gnu@1.56.0': resolution: {integrity: sha512-dNaICPvtmuxFP/VbqdofrLqdS3bM/AKJN3LMJD52si44ea7Be1cBk6NpfIahaysG9Uo+L98QKddU9CD5L8UHnQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxlint/binding-linux-x64-musl@1.55.0': resolution: {integrity: sha512-BDpP7W8GlaG7BR6QjGZAleYzxoyKc/D24spZIF2mB3XsfALQJJT/OBmP8YpeTb1rveFSBHzl8T7l0aqwkWNdGA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxlint/binding-linux-x64-musl@1.56.0': resolution: {integrity: sha512-pF1vOtM+GuXmbklM1hV8WMsn6tCNPvkUzklj/Ej98JhlanbmA2RB1BILgOpwSuCTRTIYx2MXssmEyQQ90QF5aA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxlint/binding-openharmony-arm64@1.55.0': resolution: {integrity: sha512-PS6GFvmde/pc3fCA2Srt51glr8Lcxhpf6WIBFfLphndjRrD34NEcses4TSxQrEcxYo6qVywGfylM0ZhSCF2gGA==} @@ -2649,36 +2694,42 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.6': resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.6': resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.6': resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.6': resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.6': resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [musl] '@parcel/watcher-win32-arm64@2.5.6': resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} @@ -2826,36 +2877,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.9': resolution: {integrity: sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9': resolution: {integrity: sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9': resolution: {integrity: sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.9': resolution: {integrity: sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.9': resolution: {integrity: sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.9': resolution: {integrity: sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==} @@ -2982,66 +3039,79 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -3318,12 +3388,6 @@ packages: '@types/emscripten@1.41.5': resolution: {integrity: sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q==} - '@types/eslint-scope@3.7.7': - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - - '@types/eslint@9.6.1': - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -3347,9 +3411,6 @@ packages: '@types/http-link-header@1.0.7': resolution: {integrity: sha512-snm5oLckop0K3cTDAiBnZDy6ncx9DJ3mCRDvs42C884MbVYPP74Tiq2hFsSDRTyjK6RyDYDIulPiW23ge+g5Lw==} - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/leaflet@1.9.21': resolution: {integrity: sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==} @@ -3554,15 +3615,6 @@ packages: '@vue/compiler-dom@3.5.18': resolution: {integrity: sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==} - '@vue/compiler-dom@3.5.29': - resolution: {integrity: sha512-n0G5o7R3uBVmVxjTIYcz7ovr8sy7QObFG8OQJ3xGCDNhbG60biP/P5KnyY8NLd81OuT1WJflG7N4KWYHaeeaIg==} - - '@vue/compiler-sfc@3.5.29': - resolution: {integrity: sha512-oJZhN5XJs35Gzr50E82jg2cYdZQ78wEwvRO6Y63TvLVTc+6xICzJHP1UIecdSPPYIbkautNBanDiWYa64QSFIA==} - - '@vue/compiler-ssr@3.5.29': - resolution: {integrity: sha512-Y/ARJZE6fpjzL5GH/phJmsFwx3g6t2KmHKHx5q+MLl2kencADKIrhH5MLF6HHpRMmlRAYBRSvv347Mepf1zVNw==} - '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} @@ -3580,69 +3632,12 @@ packages: '@vue/shared@3.5.29': resolution: {integrity: sha512-w7SR0A5zyRByL9XUkCfdLs7t9XOHUyJ67qPGQjOou3p6GvBeBW+AVjUUmlxtZ4PIYaRvE+1LmK44O4uajlZwcg==} - '@webassemblyjs/ast@1.14.1': - resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - - '@webassemblyjs/floating-point-hex-parser@1.13.2': - resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - - '@webassemblyjs/helper-api-error@1.13.2': - resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - - '@webassemblyjs/helper-buffer@1.14.1': - resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - - '@webassemblyjs/helper-numbers@1.13.2': - resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': - resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - - '@webassemblyjs/helper-wasm-section@1.14.1': - resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - - '@webassemblyjs/ieee754@1.13.2': - resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - - '@webassemblyjs/leb128@1.13.2': - resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - - '@webassemblyjs/utf8@1.13.2': - resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - - '@webassemblyjs/wasm-edit@1.14.1': - resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - - '@webassemblyjs/wasm-gen@1.14.1': - resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - - '@webassemblyjs/wasm-opt@1.14.1': - resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - - '@webassemblyjs/wasm-parser@1.14.1': - resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - - '@webassemblyjs/wast-printer@1.14.1': - resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - - '@xtuc/ieee754@1.2.0': - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - - '@xtuc/long@4.2.2': - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - '@yornaath/batshit-devtools@1.7.1': resolution: {integrity: sha512-AyttV1Njj5ug+XqEWY1smV45dTWMlWKtj1B8jcFYgBKUFyUlF/qEhD+iP1E5UaRYW6hQRYD9T2WNDwFTrOMWzQ==} '@yornaath/batshit@0.14.0': resolution: {integrity: sha512-0I+xMi5JoRs3+qVXXhk2AmsEl43MwrG+L+VW+nqw/qQqMFtgRPszLaxhJCfsBKnjfJ0gJzTI1Q9Q9+y903HyHQ==} - acorn-import-phases@1.0.4: - resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} - engines: {node: '>=10.13.0'} - peerDependencies: - acorn: ^8.14.0 - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -3666,14 +3661,6 @@ packages: ajv: optional: true - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -3682,11 +3669,6 @@ packages: ajv: optional: true - ajv-keywords@5.1.0: - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} @@ -3961,10 +3943,6 @@ packages: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} - chrome-trace-event@1.0.4: - resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} - engines: {node: '>=6.0'} - ci-info@4.4.0: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} @@ -4322,10 +4300,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - enhanced-resolve@5.20.0: - resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} - engines: {node: '>=10.13.0'} - entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} @@ -4420,10 +4394,6 @@ packages: peerDependencies: eslint: 9 || 10 - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4450,10 +4420,6 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -4492,10 +4458,6 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - exifr@7.1.3: resolution: {integrity: sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==} @@ -4684,9 +4646,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -4763,9 +4722,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hash-sum@2.0.0: - resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} - hashery@1.5.0: resolution: {integrity: sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==} engines: {node: '>=20'} @@ -5148,10 +5104,6 @@ packages: engines: {node: '>=10'} hasBin: true - jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - jiti@1.21.7: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true @@ -5300,24 +5252,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -5361,10 +5317,6 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - loader-runner@4.3.1: - resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} - engines: {node: '>=6.11.5'} - local-pkg@1.1.1: resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==} engines: {node: '>=14'} @@ -5542,9 +5494,6 @@ packages: resolution: {integrity: sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==} engines: {node: '>=20'} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -5658,14 +5607,6 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -5725,9 +5666,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - neotraverse@0.6.18: resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} engines: {node: '>= 10'} @@ -6516,48 +6454,56 @@ packages: engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] + libc: glibc sass-embedded-linux-arm@1.98.0: resolution: {integrity: sha512-03baQZCxVyEp8v1NWBRlzGYrmVT/LK7ZrHlF1piscGiGxwfdxoLXVuxsylx3qn/dD/4i/rh7Bzk7reK1br9jvQ==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] + libc: glibc sass-embedded-linux-musl-arm64@1.98.0: resolution: {integrity: sha512-LeqNxQA8y4opjhe68CcFvMzCSrBuJqYVFbwElEj9bagHXQHTp9xVPJRn6VcrC+0VLEDq13HVXMv7RslIuU0zmA==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] + libc: musl sass-embedded-linux-musl-arm@1.98.0: resolution: {integrity: sha512-OBkjTDPYR4hSaueOGIM6FDpl9nt/VZwbSRpbNu9/eEJcxE8G/vynRugW8KRZmCFjPy8j/jkGBvvS+k9iOqKV3g==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] + libc: musl sass-embedded-linux-musl-riscv64@1.98.0: resolution: {integrity: sha512-7w6hSuOHKt8FZsmjRb3iGSxEzM87fO9+M8nt5JIQYMhHTj5C+JY/vcske0v715HCVj5e1xyTnbGXf8FcASeAIw==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] + libc: musl sass-embedded-linux-musl-x64@1.98.0: resolution: {integrity: sha512-QikNyDEJOVqPmxyCFkci8ZdCwEssdItfjQFJB+D+Uy5HFqcS5Lv3d3GxWNX/h1dSb23RPyQdQc267ok5SbEyJw==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] + libc: musl sass-embedded-linux-riscv64@1.98.0: resolution: {integrity: sha512-E7fNytc/v4xFBQKzgzBddV/jretA4ULAPO6XmtBiQu4zZBdBozuSxsQLe2+XXeb0X4S2GIl72V7IPABdqke/vA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] + libc: glibc sass-embedded-linux-x64@1.98.0: resolution: {integrity: sha512-VsvP0t/uw00mMNPv3vwyYKUrFbqzxQHnRMO+bHdAMjvLw4NFf6mscpym9Bzf+NXwi1ZNKnB6DtXjmcpcvqFqYg==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] + libc: glibc sass-embedded-unknown-all@1.98.0: resolution: {integrity: sha512-C4MMzcAo3oEDQnW7L8SBgB9F2Fq5qHPnaYTZRMOH3Mp/7kM4OooBInXpCiiFjLnjY95hzP4KyctVx0uYR6MYlQ==} @@ -6596,10 +6542,6 @@ packages: scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - schema-utils@4.3.3: - resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} - engines: {node: '>= 10.13.0'} - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -6967,10 +6909,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} @@ -6979,22 +6917,6 @@ packages: resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} engines: {node: '>=10'} - terser-webpack-plugin@5.3.16: - resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - terser@5.46.0: resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} engines: {node: '>=10'} @@ -7383,12 +7305,6 @@ packages: '@vite-pwa/assets-generator': optional: true - vite-plugin-require@1.2.14: - resolution: {integrity: sha512-i52DfITgYKtOZyh9kOjyy4ENTQBVHG0ozTKHQdFkGAHYqZwM3Dn2c5gsA5rR7IrHQ/PQET3SMz6HkNzZ2fXCyA==} - engines: {node: '>=8', npm: '>=5'} - peerDependencies: - vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 - vite-plugin-static-copy@3.3.0: resolution: {integrity: sha512-XiAtZcev7nppxNFgKoD55rfL+ukVp/RtrnTJONRwRuzv/B2FK2h2ZRCYjvxhwBV/Oarse83SiyXBSxMTfeEM0Q==} engines: {node: ^18.0.0 || >=20.0.0} @@ -7524,18 +7440,6 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - vue-loader@17.4.2: - resolution: {integrity: sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==} - peerDependencies: - '@vue/compiler-sfc': '*' - vue: '*' - webpack: ^4.1.0 || ^5.0.0-0 - peerDependenciesMeta: - '@vue/compiler-sfc': - optional: true - vue: - optional: true - w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -7543,10 +7447,6 @@ packages: warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - watchpack@2.5.1: - resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} - engines: {node: '>=10.13.0'} - web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} @@ -7557,20 +7457,6 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} - webpack-sources@3.3.4: - resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} - engines: {node: '>=10.13.0'} - - webpack@5.105.3: - resolution: {integrity: sha512-LLBBA4oLmT7sZdHiYE/PeVuifOxYyE2uL/V+9VQP7YSYdJU7bSf7H8bZRRxW8kEPMkmVjnrXmoR3oejIdX0xbg==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - whatwg-mimetype@5.0.0: resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} engines: {node: '>=20'} @@ -10348,16 +10234,6 @@ snapshots: '@types/emscripten@1.41.5': {} - '@types/eslint-scope@3.7.7': - dependencies: - '@types/eslint': 9.6.1 - '@types/estree': 1.0.8 - - '@types/eslint@9.6.1': - dependencies: - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.8 @@ -10381,8 +10257,6 @@ snapshots: dependencies: '@types/node': 25.5.0 - '@types/json-schema@7.0.15': {} - '@types/leaflet@1.9.21': dependencies: '@types/geojson': 7946.0.16 @@ -10610,34 +10484,13 @@ snapshots: entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 + optional: true '@vue/compiler-dom@3.5.18': dependencies: '@vue/compiler-core': 3.5.18 '@vue/shared': 3.5.18 - '@vue/compiler-dom@3.5.29': - dependencies: - '@vue/compiler-core': 3.5.29 - '@vue/shared': 3.5.29 - - '@vue/compiler-sfc@3.5.29': - dependencies: - '@babel/parser': 7.29.0 - '@vue/compiler-core': 3.5.29 - '@vue/compiler-dom': 3.5.29 - '@vue/compiler-ssr': 3.5.29 - '@vue/shared': 3.5.29 - estree-walker: 2.0.2 - magic-string: 0.30.21 - postcss: 8.5.8 - source-map-js: 1.2.1 - - '@vue/compiler-ssr@3.5.29': - dependencies: - '@vue/compiler-dom': 3.5.29 - '@vue/shared': 3.5.29 - '@vue/compiler-vue2@2.7.16': dependencies: de-indent: 1.0.2 @@ -10658,87 +10511,8 @@ snapshots: '@vue/shared@3.5.18': {} - '@vue/shared@3.5.29': {} - - '@webassemblyjs/ast@1.14.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - - '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - - '@webassemblyjs/helper-api-error@1.13.2': {} - - '@webassemblyjs/helper-buffer@1.14.1': {} - - '@webassemblyjs/helper-numbers@1.13.2': - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.13.2 - '@webassemblyjs/helper-api-error': 1.13.2 - '@xtuc/long': 4.2.2 - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} - - '@webassemblyjs/helper-wasm-section@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/wasm-gen': 1.14.1 - - '@webassemblyjs/ieee754@1.13.2': - dependencies: - '@xtuc/ieee754': 1.2.0 - - '@webassemblyjs/leb128@1.13.2': - dependencies: - '@xtuc/long': 4.2.2 - - '@webassemblyjs/utf8@1.13.2': {} - - '@webassemblyjs/wasm-edit@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/helper-wasm-section': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-opt': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wast-printer': 1.14.1 - - '@webassemblyjs/wasm-gen@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wasm-opt@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - - '@webassemblyjs/wasm-parser@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-api-error': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wast-printer@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@xtuc/long': 4.2.2 - - '@xtuc/ieee754@1.2.0': {} - - '@xtuc/long@4.2.2': {} + '@vue/shared@3.5.29': + optional: true '@yornaath/batshit-devtools@1.7.1': {} @@ -10746,10 +10520,6 @@ snapshots: dependencies: '@yornaath/batshit-devtools': 1.7.1 - acorn-import-phases@1.0.4(acorn@8.16.0): - dependencies: - acorn: 8.16.0 - acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -10762,19 +10532,10 @@ snapshots: optionalDependencies: ajv: 8.13.0 - ajv-formats@2.1.1(ajv@8.18.0): - optionalDependencies: - ajv: 8.18.0 - ajv-formats@3.0.1(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 - ajv-keywords@5.1.0(ajv@8.18.0): - dependencies: - ajv: 8.18.0 - fast-deep-equal: 3.1.3 - ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 @@ -11170,8 +10931,6 @@ snapshots: dependencies: readdirp: 5.0.0 - chrome-trace-event@1.0.4: {} - ci-info@4.4.0: {} clean-css@5.3.3: @@ -11485,11 +11244,6 @@ snapshots: emoji-regex@8.0.0: {} - enhanced-resolve@5.20.0: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - entities@2.2.0: {} entities@4.5.0: {} @@ -11707,11 +11461,6 @@ snapshots: transitivePeerDependencies: - ts-jest - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 @@ -11776,8 +11525,6 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} estree-util-attach-comments@3.0.0: @@ -11821,8 +11568,6 @@ snapshots: eventemitter3@5.0.1: {} - events@3.3.0: {} - exifr@7.1.3: {} expect-type@1.3.0: {} @@ -12013,8 +11758,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-to-regexp@0.4.1: {} - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -12098,8 +11841,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - hash-sum@2.0.0: {} - hashery@1.5.0: dependencies: hookified: 1.15.1 @@ -12542,12 +12283,6 @@ snapshots: filelist: 1.0.6 picocolors: 1.1.1 - jest-worker@27.5.1: - dependencies: - '@types/node': 25.5.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - jiti@1.21.7: {} jju@1.4.0: {} @@ -12737,8 +12472,6 @@ snapshots: load-tsconfig@0.2.5: {} - loader-runner@4.3.1: {} - local-pkg@1.1.1: dependencies: mlly: 1.7.4 @@ -13027,8 +12760,6 @@ snapshots: meow@14.1.0: {} - merge-stream@2.0.0: {} - merge2@1.4.1: {} micromark-core-commonmark@2.0.3: @@ -13300,12 +13031,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - mimic-function@5.0.1: {} min-indent@1.0.1: {} @@ -13355,8 +13080,6 @@ snapshots: natural-compare@1.4.0: {} - neo-async@2.6.2: {} - neotraverse@0.6.18: {} nlcst-to-string@4.0.0: @@ -14408,13 +14131,6 @@ snapshots: scheduler@0.27.0: {} - schema-utils@4.3.3: - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.18.0 - ajv-formats: 2.1.1(ajv@8.18.0) - ajv-keywords: 5.1.0(ajv@8.18.0) - semver@6.3.1: {} semver@7.5.4: @@ -14895,8 +14611,6 @@ snapshots: - tsx - yaml - tapable@2.3.0: {} - temp-dir@2.0.0: {} tempy@0.6.0: @@ -14906,17 +14620,6 @@ snapshots: type-fest: 0.16.0 unique-string: 2.0.0 - terser-webpack-plugin@5.3.16(esbuild@0.24.2)(webpack@5.105.3(esbuild@0.24.2)): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - serialize-javascript: 6.0.2 - terser: 5.46.0 - webpack: 5.105.3(esbuild@0.24.2) - optionalDependencies: - esbuild: 0.24.2 - terser@5.46.0: dependencies: '@jridgewell/source-map': 0.3.11 @@ -15279,24 +14982,6 @@ snapshots: transitivePeerDependencies: - supports-color - vite-plugin-require@1.2.14(esbuild@0.24.2)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.24.2)(jiti@1.21.7)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.46.0)(yaml@2.8.2)): - dependencies: - '@babel/generator': 7.29.1 - '@babel/parser': 7.29.0 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@vue/compiler-sfc': 3.5.29 - vite: 8.0.0(@types/node@25.5.0)(esbuild@0.24.2)(jiti@1.21.7)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.46.0)(yaml@2.8.2) - vue-loader: 17.4.2(@vue/compiler-sfc@3.5.29)(webpack@5.105.3(esbuild@0.24.2)) - webpack: 5.105.3(esbuild@0.24.2) - transitivePeerDependencies: - - '@swc/core' - - esbuild - - supports-color - - uglify-js - - vue - - webpack-cli - vite-plugin-static-copy@3.3.0(vite@8.0.0(@types/node@25.5.0)(esbuild@0.24.2)(jiti@1.21.7)(sass-embedded@1.98.0)(sass@1.98.0)(terser@5.46.0)(yaml@2.8.2)): dependencies: chokidar: 3.6.0 @@ -15421,15 +15106,6 @@ snapshots: vscode-uri@3.1.0: {} - vue-loader@17.4.2(@vue/compiler-sfc@3.5.29)(webpack@5.105.3(esbuild@0.24.2)): - dependencies: - chalk: 4.1.2 - hash-sum: 2.0.0 - watchpack: 2.5.1 - webpack: 5.105.3(esbuild@0.24.2) - optionalDependencies: - '@vue/compiler-sfc': 3.5.29 - w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -15438,51 +15114,12 @@ snapshots: dependencies: loose-envify: 1.4.0 - watchpack@2.5.1: - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - web-namespaces@2.0.1: {} webidl-conversions@4.0.2: {} webidl-conversions@8.0.1: {} - webpack-sources@3.3.4: {} - - webpack@5.105.3(esbuild@0.24.2): - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) - browserslist: 4.28.1 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.20.0 - es-module-lexer: 2.0.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.1 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 4.3.3 - tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(esbuild@0.24.2)(webpack@5.105.3(esbuild@0.24.2)) - watchpack: 2.5.1 - webpack-sources: 3.3.4 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - whatwg-mimetype@5.0.0: {} whatwg-url@16.0.1: From deb0a7e9195118285402edc4371abc65bd7ea9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 18:28:59 +0100 Subject: [PATCH 27/64] nicolium: use URL.canParse instead of a try/catch block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/actions/consumer-auth.ts | 3 +-- packages/nicolium/src/stores/auth.ts | 14 +++++++------ packages/nicolium/src/utils/auth.ts | 20 +++---------------- packages/nicolium/src/utils/state.ts | 5 ++--- 4 files changed, 14 insertions(+), 28 deletions(-) diff --git a/packages/nicolium/src/actions/consumer-auth.ts b/packages/nicolium/src/actions/consumer-auth.ts index dc9044e61..b814d5876 100644 --- a/packages/nicolium/src/actions/consumer-auth.ts +++ b/packages/nicolium/src/actions/consumer-auth.ts @@ -1,5 +1,4 @@ import * as BuildConfig from '@/build-config'; -import { isURL } from '@/utils/auth'; import sourceCode from '@/utils/code'; import { getScopes } from '@/utils/scopes'; @@ -19,7 +18,7 @@ const createProviderApp = () => { }; const prepareRequest = async (provider: string) => { - const baseURL = isURL(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : ''; + const baseURL = URL.canParse(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : ''; const scopes = getScopes(undefined, true); const app = await createProviderApp(); diff --git a/packages/nicolium/src/stores/auth.ts b/packages/nicolium/src/stores/auth.ts index 3c173eadb..7869752c6 100644 --- a/packages/nicolium/src/stores/auth.ts +++ b/packages/nicolium/src/stores/auth.ts @@ -26,7 +26,7 @@ import { coerceObject } from '@/schemas/utils'; import { setSentryAccount, unsetSentryAccount } from '@/sentry'; import KVStore from '@/storage/kv-store'; import toast from '@/toast'; -import { validId, isURL, parseBaseURL } from '@/utils/auth'; +import { validId, parseBaseURL } from '@/utils/auth'; import sourceCode from '@/utils/code'; import { normalizeUsername } from '@/utils/input'; import { getScopes } from '@/utils/scopes'; @@ -68,7 +68,7 @@ const instance = (() => { } })(); -const backendUrl = isURL(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : ''; +const backendUrl = URL.canParse(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : ''; const mastodonPreloadSchema = coerceObject({ meta: coerceObject({ @@ -189,7 +189,7 @@ const setSessionUser = (state: AuthData) => { const isUpgradingUrlId = (state: AuthData) => { const me = state.me; const user = state.users[me!]; - return validId(me) && user && !isURL(me); + return validId(me) && user && !URL.canParse(me as string); }; const sanitizeState = (state: AuthData) => { @@ -263,7 +263,7 @@ const importTokenData = (state: AuthData, token: Token, app?: CredentialApplicat }; const upgradeNonUrlId = (state: AuthData, account: CredentialAccount) => { - if (isURL(state.me)) return; + if (state.me && URL.canParse(state.me)) return; state.me = state.me === account.id ? account.url : state.me; delete state.users[account.id]; }; @@ -312,7 +312,7 @@ const importMastodonPreloadData = (state: AuthData, data: Record) = const accountUrl = parsedData.accounts[accountId]?.url; const accessToken = parsedData.meta.access_token; - if (validId(accessToken) && validId(accountId) && isURL(accountUrl)) { + if (validId(accessToken) && validId(accountId) && URL.canParse(accountUrl)) { state.tokens[accessToken] = v.parse(tokenSchema, { access_token: accessToken, account: accountId, @@ -830,7 +830,9 @@ const isLoggedIn = () => validId(getCurrentAccountId()); const getAuthUserUrl = () => { const { me, users } = useAuthStore.getState(); - return [users[me!]?.url, me].filter((url) => url).find(isURL); + return [users[me!]?.url, me] + .filter((url): url is string => !!url) + .find((url) => URL.canParse(url)); }; const getMeUrl = () => getOwnAccount()?.url; diff --git a/packages/nicolium/src/utils/auth.ts b/packages/nicolium/src/utils/auth.ts index 9a0008915..246311fe2 100644 --- a/packages/nicolium/src/utils/auth.ts +++ b/packages/nicolium/src/utils/auth.ts @@ -1,23 +1,9 @@ const validId = (id?: string | null | false) => typeof id === 'string' && id !== 'null' && id !== 'undefined'; -const isURL = (url?: string | null) => { - if (typeof url !== 'string') return false; - try { - new URL(url); - return true; - } catch { - return false; - } -}; - const parseBaseURL = (url?: string) => { - if (typeof url !== 'string') return ''; - try { - return new URL(url).origin; - } catch { - return ''; - } + if (!url || !URL.canParse(url)) return ''; + return new URL(url).origin; }; -export { validId, isURL, parseBaseURL }; +export { validId, parseBaseURL }; diff --git a/packages/nicolium/src/utils/state.ts b/packages/nicolium/src/utils/state.ts index 89399bf52..d31b16b3e 100644 --- a/packages/nicolium/src/utils/state.ts +++ b/packages/nicolium/src/utils/state.ts @@ -6,7 +6,6 @@ import * as BuildConfig from '@/build-config'; import { isPrerendered } from '@/precheck'; import { useInstanceStore } from '@/stores/instance'; -import { isURL } from '@/utils/auth'; /** * Determine whether Nicolium is running in standalone mode. @@ -14,12 +13,12 @@ import { isURL } from '@/utils/auth'; */ const isStandalone = (): boolean => { const instanceFetchFailed = useInstanceStore.getState().instanceFetchFailed; - return isURL(BuildConfig.BACKEND_URL) ? false : !isPrerendered && instanceFetchFailed; + return URL.canParse(BuildConfig.BACKEND_URL) ? false : !isPrerendered && instanceFetchFailed; }; const useIsStandalone = () => { const instanceFetchFailed = useInstanceStore((state) => state.instanceFetchFailed); - return isURL(BuildConfig.BACKEND_URL) ? false : !isPrerendered && instanceFetchFailed; + return URL.canParse(BuildConfig.BACKEND_URL) ? false : !isPrerendered && instanceFetchFailed; }; const useFederationRestrictionsDisclosed = () => From 8ca9805e1074299ac356b7893ce9459a2e65b569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 18:46:39 +0100 Subject: [PATCH 28/64] nicolium: no need to import datepicker css in main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/main.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nicolium/src/main.tsx b/packages/nicolium/src/main.tsx index 1fa9495a4..62fa45975 100644 --- a/packages/nicolium/src/main.tsx +++ b/packages/nicolium/src/main.tsx @@ -26,7 +26,6 @@ import '@fontsource/inter/700.css'; import '@fontsource/inter/900.css'; import '@fontsource/roboto-mono/400.css'; import 'line-awesome/dist/font-awesome-line-awesome/css/all.css'; -import 'react-datepicker/dist/react-datepicker.css'; import './styles/i18n.css'; import './styles/application.scss'; import './styles/tailwind.css'; From c9612b7ab29c6434213a6fa78e06ea6406d80307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 18:50:50 +0100 Subject: [PATCH 29/64] nicolium: don't import lineawesome from main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/fork-awesome-icon.tsx | 2 ++ packages/nicolium/src/main.tsx | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nicolium/src/components/fork-awesome-icon.tsx b/packages/nicolium/src/components/fork-awesome-icon.tsx index 8847fdf6b..e6782de37 100644 --- a/packages/nicolium/src/components/fork-awesome-icon.tsx +++ b/packages/nicolium/src/components/fork-awesome-icon.tsx @@ -8,6 +8,8 @@ import clsx from 'clsx'; import React from 'react'; +import 'line-awesome/dist/font-awesome-line-awesome/css/all.css'; + interface IForkAwesomeIcon extends React.HTMLAttributes { id: string; className?: string; diff --git a/packages/nicolium/src/main.tsx b/packages/nicolium/src/main.tsx index 62fa45975..c74a55240 100644 --- a/packages/nicolium/src/main.tsx +++ b/packages/nicolium/src/main.tsx @@ -25,7 +25,6 @@ import '@fontsource/inter/600.css'; import '@fontsource/inter/700.css'; import '@fontsource/inter/900.css'; import '@fontsource/roboto-mono/400.css'; -import 'line-awesome/dist/font-awesome-line-awesome/css/all.css'; import './styles/i18n.css'; import './styles/application.scss'; import './styles/tailwind.css'; From b5c877e98481d22895bf1a39c5885880c228d94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 19:05:42 +0100 Subject: [PATCH 30/64] nicolium: allow pinning/unpinning instances on mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/panels/instance-info-panel.tsx | 61 ------------------- .../src/features/ui/util/async-components.ts | 1 - .../src/layouts/remote-instance-layout.tsx | 7 +-- .../src/pages/timelines/remote-timeline.tsx | 40 ++++++++++-- 4 files changed, 37 insertions(+), 72 deletions(-) delete mode 100644 packages/nicolium/src/components/panels/instance-info-panel.tsx 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 && (
Date: Wed, 18 Mar 2026 19:06:15 +0100 Subject: [PATCH 31/64] nicolium: simplify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/hooks/use-timeline-filters-options.ts | 10 +++++----- packages/nicolium/src/locales/en.json | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/nicolium/src/hooks/use-timeline-filters-options.ts b/packages/nicolium/src/hooks/use-timeline-filters-options.ts index 30d8205b5..aa4364216 100644 --- a/packages/nicolium/src/hooks/use-timeline-filters-options.ts +++ b/packages/nicolium/src/hooks/use-timeline-filters-options.ts @@ -9,16 +9,16 @@ import { useFeatures } from './use-features'; import type { Menu } from '@/components/dropdown-menu'; const messages = defineMessages({ - showReblogs: { id: 'timeline_filters.show_reblogs', defaultMessage: 'Show reposts in timeline' }, + showReblogs: { id: 'timeline_filters.show_reblogs', defaultMessage: 'Show reposts' }, showSelfReblogs: { id: 'timeline_filters.show_self_reblogs', - defaultMessage: 'Show self-reposts in timeline', + defaultMessage: 'Show self-reposts', }, - showReplies: { id: 'timeline_filters.show_replies', defaultMessage: 'Show replies in timeline' }, - showQuotes: { id: 'timeline_filters.show_quotes', defaultMessage: 'Show quotes in timeline' }, + showReplies: { id: 'timeline_filters.show_replies', defaultMessage: 'Show replies' }, + showQuotes: { id: 'timeline_filters.show_quotes', defaultMessage: 'Show quotes' }, showDirect: { id: 'timeline_filters.show_direct', - defaultMessage: 'Show direct messages in timeline', + defaultMessage: 'Show direct messages', }, hideNonMedia: { id: 'timeline_filters.show_media_only', diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index 8d01cad8f..77a14943d 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -2025,12 +2025,12 @@ "timeline.gap.load_older": "Load older posts", "timeline.gap.load_recent": "Load recent posts", "timeline_filters.set_as_default": "Set as default timeline", - "timeline_filters.show_direct": "Show direct messages in timeline", + "timeline_filters.show_direct": "Show direct messages", "timeline_filters.show_media_only": "Only show posts with media", - "timeline_filters.show_quotes": "Show quotes in timeline", - "timeline_filters.show_reblogs": "Show reposts in timeline", - "timeline_filters.show_replies": "Show replies in timeline", - "timeline_filters.show_self_reblogs": "Show self-reposts in timeline", + "timeline_filters.show_quotes": "Show quotes", + "timeline_filters.show_reblogs": "Show reposts", + "timeline_filters.show_replies": "Show replies", + "timeline_filters.show_self_reblogs": "Show self-reposts", "timeline_picker.pinned_instances": "Pinned instances", "toast.view": "View", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", From 70cf8d023c6b5a3699f97dd866e9dd11bdc8a643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 22:24:42 +0100 Subject: [PATCH 32/64] nicolium: fix variable name, do not expose unavailable feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/accounts/account.tsx | 10 +++++++--- .../nicolium/src/pages/timelines/remote-timeline.tsx | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/nicolium/src/components/accounts/account.tsx b/packages/nicolium/src/components/accounts/account.tsx index 56609a2d9..eb0721de8 100644 --- a/packages/nicolium/src/components/accounts/account.tsx +++ b/packages/nicolium/src/components/accounts/account.tsx @@ -15,6 +15,7 @@ import Text from '@/components/ui/text'; import { useCurrentAccount } from '@/contexts/current-account-context'; import Emojify from '@/features/emoji/emojify'; import { useAcct } from '@/hooks/use-acct'; +import { useFeatures } from '@/hooks/use-features'; import { useSettings } from '@/stores/settings'; import Badge from '../badge'; @@ -164,6 +165,8 @@ const Account = ({ const [style, setStyle] = useState({}); + const intl = useIntl(); + const features = useFeatures(); const me = useCurrentAccount(); const username = useAcct(account); const { disableUserProvidedMedia } = useSettings(); @@ -202,8 +205,6 @@ const Account = ({ return null; }; - const intl = useIntl(); - useLayoutEffect(() => { const onResize = () => { const style: React.CSSProperties = {}; @@ -435,7 +436,10 @@ const Account = ({ )} {account.favicon && !disableUserProvidedMedia && ( - + )} {timestamp ? ( diff --git a/packages/nicolium/src/pages/timelines/remote-timeline.tsx b/packages/nicolium/src/pages/timelines/remote-timeline.tsx index 00b74e17e..e4c2f40fc 100644 --- a/packages/nicolium/src/pages/timelines/remote-timeline.tsx +++ b/packages/nicolium/src/pages/timelines/remote-timeline.tsx @@ -59,7 +59,9 @@ const RemoteTimelinePage: React.FC = () => { ...timelineFiltersOptions, null, { - text: intl.formatMessage(isPinned ? messages.unpinHost : messages.pinHost, { instance }), + text: intl.formatMessage(isPinned ? messages.unpinHost : messages.pinHost, { + host: instance, + }), action: handlePinHost, icon: isPinned ? iconPushPinSlash : iconPushPin, }, From 804dc5aa7fefb12241de5c76e50da9324ed31713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 22:36:39 +0100 Subject: [PATCH 33/64] nicolium: make loading account from kvstore improve app loading time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/stores/auth.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/nicolium/src/stores/auth.ts b/packages/nicolium/src/stores/auth.ts index 7869752c6..163d3b3e1 100644 --- a/packages/nicolium/src/stores/auth.ts +++ b/packages/nicolium/src/stores/auth.ts @@ -710,6 +710,8 @@ const useAuthStore = create()( queryClient.setQueryData(queryKeys.accounts.show(account.id), account); get().actions.setCurrentAccountIfUnset(account); if (account.id === get().currentAccountId) fetchMeSuccess(account); + get().actions.verifyCredentials(token, accountUrl!); + return; } catch {} return await get().actions.verifyCredentials(token, accountUrl!); From 1343d2888f11ee621d6cb2e652a54207285120f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 18 Mar 2026 22:47:44 +0100 Subject: [PATCH 34/64] nicolium: try to improve loading time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/actions/instance.ts | 25 +++++++++++++------- packages/nicolium/src/init/nicolium-load.tsx | 6 +++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/nicolium/src/actions/instance.ts b/packages/nicolium/src/actions/instance.ts index 9086d7aba..bf6877f50 100644 --- a/packages/nicolium/src/actions/instance.ts +++ b/packages/nicolium/src/actions/instance.ts @@ -14,16 +14,23 @@ const getHost = () => { } }; -const fetchInstance = async () => { - try { - const client = getClient(); - const instance = await client.instance.getInstance(); +const doFetchInstance = async () => { + const client = getClient(); + const instance = await client.instance.getInstance(); - useInstanceStore.getState().actions.loadInstance(instance); - useComposeStore.getState().actions.importDefaultContentType(instance); - } catch (error) { + useInstanceStore.getState().actions.loadInstance(instance); + useComposeStore.getState().actions.importDefaultContentType(instance); +}; + +const fetchInstance = async () => { + const { fetched, instanceFetchFailed } = useInstanceStore.getState(); + if (fetched || (instanceFetchFailed && !getAuthUserUrl())) return; + + const promise = doFetchInstance().catch((error) => { useInstanceStore.getState().actions.instanceFetchFailed(error); - } + }); + + if (!fetched) await promise; }; const checkIfStandalone = () => @@ -31,9 +38,11 @@ const checkIfStandalone = () => .then(({ ok, headers }) => { const isOk = ok && !!headers.get('content-type')?.includes('application/json'); useInstanceStore.getState().actions.setInstanceFetchFailed(!isOk); + return !isOk; }) .catch((err) => { useInstanceStore.getState().actions.setInstanceFetchFailed(!err.response?.ok); + return true; }); export { getHost, fetchInstance, checkIfStandalone }; diff --git a/packages/nicolium/src/init/nicolium-load.tsx b/packages/nicolium/src/init/nicolium-load.tsx index b32e613eb..e1a6953bb 100644 --- a/packages/nicolium/src/init/nicolium-load.tsx +++ b/packages/nicolium/src/init/nicolium-load.tsx @@ -42,10 +42,12 @@ const NicoliumLoad: React.FC = ({ children }) => { useEffect(() => { /** Load initial data from the backend */ const loadInitial = async () => { - checkIfStandalone(); + const standaloneCheck = checkIfStandalone(); // Await for authenticated fetch await fetchMe(); - // Await for feature detection + // Wait for standalone detection before proceeding + await standaloneCheck; + // Await for feature detection (skipped if already fetched or standalone) await fetchInstance(); // Await for configuration await loadFrontendConfig(); From 7c17c1eb152b4334e2f94c43c3418a553664379e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 06:33:39 +0100 Subject: [PATCH 35/64] nicolium: remove console.log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/columns/trends.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nicolium/src/columns/trends.tsx b/packages/nicolium/src/columns/trends.tsx index 728374853..0af540a44 100644 --- a/packages/nicolium/src/columns/trends.tsx +++ b/packages/nicolium/src/columns/trends.tsx @@ -63,7 +63,6 @@ const TrendsColumn: React.FC = ({ type, multiColumn }) => { isLoading = isLoadingAccounts; placeholderComponent = PlaceholderAccount; - console.log(accounts, isFetching, isLoading); if (!isFetching && !isLoading && accounts?.length === 0) { children = [ Date: Thu, 19 Mar 2026 06:35:37 +0100 Subject: [PATCH 36/64] nicolium: Fix "Discard" button font color invisible when focused (gh #551) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/styles/new/mixins.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nicolium/src/styles/new/mixins.scss b/packages/nicolium/src/styles/new/mixins.scss index 5f7b66aab..6d096fb6f 100644 --- a/packages/nicolium/src/styles/new/mixins.scss +++ b/packages/nicolium/src/styles/new/mixins.scss @@ -296,6 +296,7 @@ } &:focus { + background-color: rgb(var(--color-danger-100)); outline-color: rgb(var(--color-danger-500)); } From a278bf9018c3bb78070d931296d6893b96e2454f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 10:16:16 +0100 Subject: [PATCH 37/64] nicolium: this should make the initial load reasonably fast without breaking stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/actions/instance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nicolium/src/actions/instance.ts b/packages/nicolium/src/actions/instance.ts index bf6877f50..c34659064 100644 --- a/packages/nicolium/src/actions/instance.ts +++ b/packages/nicolium/src/actions/instance.ts @@ -30,7 +30,7 @@ const fetchInstance = async () => { useInstanceStore.getState().actions.instanceFetchFailed(error); }); - if (!fetched) await promise; + if (!fetched && !getAuthUserUrl()) await promise; }; const checkIfStandalone = () => From e8ce2e4982f0d5f3dd4d40d2ff1383d8e31ccf23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20My=C5=9Bli=C5=84ski?= Date: Thu, 19 Mar 2026 10:38:38 +0100 Subject: [PATCH 38/64] pl-api: fix request body serialization for formData and bodiless requests --- packages/pl-api/lib/request.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/pl-api/lib/request.ts b/packages/pl-api/lib/request.ts index 25d0e1a6b..f64e9679a 100644 --- a/packages/pl-api/lib/request.ts +++ b/packages/pl-api/lib/request.ts @@ -113,11 +113,13 @@ function request( else if (this.accessToken) headers.set('Authorization', `Bearer ${this.accessToken}`); else if (this.customAuthorizationToken) headers.set('Authorization', this.customAuthorizationToken); - if (!formData) headers.set('Content-Type', contentType); + body = + body && (formData || contentType === '') + ? serialize(body, { indices: true }) + : JSON.stringify(body); + if (!formData && body) headers.set('Content-Type', contentType); if (idempotencyKey) headers.set('Idempotency-Key', idempotencyKey); - body = body && contentType === '' ? serialize(body, { indices: true }) : JSON.stringify(body); - // Fetch API doesn't report upload progress, use XHR if (onUploadProgress) { return new Promise>((resolve, reject) => { From 4af0ba05c802dbbfe408afec94b3008499286b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 10:52:44 +0100 Subject: [PATCH 39/64] pl-api: simplify --- packages/pl-api/lib/request.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/pl-api/lib/request.ts b/packages/pl-api/lib/request.ts index f64e9679a..5017708cc 100644 --- a/packages/pl-api/lib/request.ts +++ b/packages/pl-api/lib/request.ts @@ -113,13 +113,11 @@ function request( else if (this.accessToken) headers.set('Authorization', `Bearer ${this.accessToken}`); else if (this.customAuthorizationToken) headers.set('Authorization', this.customAuthorizationToken); - body = - body && (formData || contentType === '') - ? serialize(body, { indices: true }) - : JSON.stringify(body); - if (!formData && body) headers.set('Content-Type', contentType); + if (!formData) headers.set('Content-Type', contentType); if (idempotencyKey) headers.set('Idempotency-Key', idempotencyKey); + body = body && formData ? serialize(body, { indices: true }) : JSON.stringify(body); + // Fetch API doesn't report upload progress, use XHR if (onUploadProgress) { return new Promise>((resolve, reject) => { From b1b8bf3e5998db1b43c0e7c3338f169e87aac4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 14:57:20 +0100 Subject: [PATCH 40/64] pl-api: fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/client/media.ts | 2 +- packages/pl-api/lib/client/oauth.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pl-api/lib/client/media.ts b/packages/pl-api/lib/client/media.ts index 9f57089ab..0fdc03518 100644 --- a/packages/pl-api/lib/client/media.ts +++ b/packages/pl-api/lib/client/media.ts @@ -16,7 +16,7 @@ const media = (client: PlApiBaseClient) => ({ uploadMedia: async (params: UploadMediaParams, meta?: RequestMeta) => { const response = await client.request( client.features.mediaV2 ? '/api/v2/media' : '/api/v1/media', - { ...meta, method: 'POST', body: params, contentType: '' }, + { ...meta, method: 'POST', body: params, formData: true }, ); return v.parse(mediaAttachmentSchema, response.json); diff --git a/packages/pl-api/lib/client/oauth.ts b/packages/pl-api/lib/client/oauth.ts index 568ffee02..a2e051a90 100644 --- a/packages/pl-api/lib/client/oauth.ts +++ b/packages/pl-api/lib/client/oauth.ts @@ -19,7 +19,7 @@ const oauth = (client: PlApiBaseClient) => ({ * @see {@link https://docs.joinmastodon.org/methods/oauth/#authorize} */ authorize: async (params: OauthAuthorizeParams) => { - const response = await client.request('/oauth/authorize', { params, contentType: '' }); + const response = await client.request('/oauth/authorize', { params, formData: true }); return v.parse(v.string(), response.json); }, From c32d3c5d2a6f7955bcc3190aeb115c4f8c6b3315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 16:29:26 +0100 Subject: [PATCH 41/64] pl-api: update typdeoc config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/typedoc.config.mjs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/pl-api/typedoc.config.mjs b/packages/pl-api/typedoc.config.mjs index ce91934d2..f7e8f0a00 100644 --- a/packages/pl-api/typedoc.config.mjs +++ b/packages/pl-api/typedoc.config.mjs @@ -7,6 +7,32 @@ const config = { navigation: { includeCategories: true, }, + categorizeByGroup: true, + sort: ['kind', 'alphabetical'], + kindSortOrder: [ + 'Function', + 'Class', + 'Interface', + 'TypeAlias', + 'Variable', + 'Enum', + ], + intentionallyNotExported: [ + 'CreateStatusOptionalParams', + 'CreateStatusWithContent', + 'CreateStatusWithMedia', + 'EditStatusOptionalParams', + 'GetTrends', + 'LanguageParam', + 'OnlyEventsParam', + 'OnlyMediaParam', + 'Params', + 'PlApiClientConstructorOpts', + 'WithMutedParam', + 'WithRelationshipsParam', + ], + groupReferencesByType: true, + suppressCommentWarningsInDeclarationFiles: true, }; export default config; From fa072aaa84cd988d44da4cd78f647726e888cc34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 16:35:26 +0100 Subject: [PATCH 42/64] pl-api: update typedoc-plugin-valibot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pl-api/package.json b/packages/pl-api/package.json index cd0b2a3b8..d4a99d1d3 100644 --- a/packages/pl-api/package.json +++ b/packages/pl-api/package.json @@ -56,7 +56,7 @@ "oxlint": "^1.55.0", "typedoc": "^0.28.17", "typedoc-material-theme": "^1.4.1", - "typedoc-plugin-valibot": "^1.0.0", + "typedoc-plugin-valibot": "^1.0.2", "typescript": "^5.9.3", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index afbdcb105..7b212b4c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -436,8 +436,8 @@ importers: specifier: ^1.4.1 version: 1.4.1(typedoc@0.28.17(typescript@5.9.3)) typedoc-plugin-valibot: - specifier: ^1.0.0 - version: 1.0.1(typedoc@0.28.17(typescript@5.9.3)) + specifier: ^1.0.2 + version: 1.0.2(typedoc@0.28.17(typescript@5.9.3)) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -7049,8 +7049,8 @@ packages: peerDependencies: typedoc: ^0.25.13 || ^0.26.x || ^0.27.x || ^0.28.x - typedoc-plugin-valibot@1.0.1: - resolution: {integrity: sha512-HlF4/zVqPhNZ2KaWuJeqejCwoJfhhDsM92Kp52GHH61bXyrfiVRr9JXHW2ZKpdh5jge8Xw7tmRLYCAPYY6I4ag==} + typedoc-plugin-valibot@1.0.2: + resolution: {integrity: sha512-PTzEEPq4MM9KBV6i/7v3nBstSUpqJGNKViFZCgIQyPc1T35essUCZbAWKa/020feDbtReJ1y5gEWv0LnNx53CQ==} peerDependencies: typedoc: 0.23.x || 0.24.x || 0.25.x || 0.26.x || 0.27.x || 0.28.x @@ -14744,7 +14744,7 @@ snapshots: '@material/material-color-utilities': 0.3.0 typedoc: 0.28.17(typescript@5.9.3) - typedoc-plugin-valibot@1.0.1(typedoc@0.28.17(typescript@5.9.3)): + typedoc-plugin-valibot@1.0.2(typedoc@0.28.17(typescript@5.9.3)): dependencies: typedoc: 0.28.17(typescript@5.9.3) From 681b5778aeb2085245697ca04b1defb32f708aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 16:52:29 +0100 Subject: [PATCH 43/64] nicolium: idk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/actions/instance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nicolium/src/actions/instance.ts b/packages/nicolium/src/actions/instance.ts index c34659064..b664e5346 100644 --- a/packages/nicolium/src/actions/instance.ts +++ b/packages/nicolium/src/actions/instance.ts @@ -23,8 +23,8 @@ const doFetchInstance = async () => { }; const fetchInstance = async () => { - const { fetched, instanceFetchFailed } = useInstanceStore.getState(); - if (fetched || (instanceFetchFailed && !getAuthUserUrl())) return; + const { fetched } = useInstanceStore.getState(); + if (fetched) return; const promise = doFetchInstance().catch((error) => { useInstanceStore.getState().actions.instanceFetchFailed(error); From eac3bf1899dc8c089f7d0555df96ec7431377b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 17:09:41 +0100 Subject: [PATCH 44/64] Revert "nicolium: idk" This reverts commit 681b5778aeb2085245697ca04b1defb32f708aa1. --- packages/nicolium/src/actions/instance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nicolium/src/actions/instance.ts b/packages/nicolium/src/actions/instance.ts index b664e5346..c34659064 100644 --- a/packages/nicolium/src/actions/instance.ts +++ b/packages/nicolium/src/actions/instance.ts @@ -23,8 +23,8 @@ const doFetchInstance = async () => { }; const fetchInstance = async () => { - const { fetched } = useInstanceStore.getState(); - if (fetched) return; + const { fetched, instanceFetchFailed } = useInstanceStore.getState(); + if (fetched || (instanceFetchFailed && !getAuthUserUrl())) return; const promise = doFetchInstance().catch((error) => { useInstanceStore.getState().actions.instanceFetchFailed(error); From d810a0a1b987c57a97f96d7a8506a0b8ea37e662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 17:09:47 +0100 Subject: [PATCH 45/64] Revert "nicolium: make loading account from kvstore improve app loading time" This reverts commit 804dc5aa7fefb12241de5c76e50da9324ed31713. --- packages/nicolium/src/stores/auth.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/nicolium/src/stores/auth.ts b/packages/nicolium/src/stores/auth.ts index 163d3b3e1..7869752c6 100644 --- a/packages/nicolium/src/stores/auth.ts +++ b/packages/nicolium/src/stores/auth.ts @@ -710,8 +710,6 @@ const useAuthStore = create()( queryClient.setQueryData(queryKeys.accounts.show(account.id), account); get().actions.setCurrentAccountIfUnset(account); if (account.id === get().currentAccountId) fetchMeSuccess(account); - get().actions.verifyCredentials(token, accountUrl!); - return; } catch {} return await get().actions.verifyCredentials(token, accountUrl!); From e8419167defa6dcd1ee7103b91e7c98a86e8dfd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 17:22:58 +0100 Subject: [PATCH 46/64] nicolium: disable user-scalable=no MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nicolium/index.html b/packages/nicolium/index.html index f7bbb51e7..a2ddb8c49 100644 --- a/packages/nicolium/index.html +++ b/packages/nicolium/index.html @@ -4,7 +4,7 @@ From e6f13115625bd617f5da21ed0f3f6323931ae6c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 17:35:49 +0100 Subject: [PATCH 47/64] nicolium: fix feature gating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../src/components/timeline-picker.tsx | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/nicolium/src/components/timeline-picker.tsx b/packages/nicolium/src/components/timeline-picker.tsx index 6cf7d7574..e3778bdf5 100644 --- a/packages/nicolium/src/components/timeline-picker.tsx +++ b/packages/nicolium/src/components/timeline-picker.tsx @@ -103,9 +103,10 @@ const TimelinePicker: React.FC = ({ active }) => { } if ( - isLoggedIn + features.publicTimeline && + (isLoggedIn ? timelineAccess.live_feeds.local !== 'disabled' - : timelineAccess.live_feeds.local === 'public' + : timelineAccess.live_feeds.local === 'public') ) { items.push({ to: '/timeline/local', @@ -116,9 +117,10 @@ const TimelinePicker: React.FC = ({ active }) => { } if ( - features.bubbleTimeline && isLoggedIn + features.bubbleTimeline && + (isLoggedIn ? timelineAccess.live_feeds.bubble !== 'disabled' - : timelineAccess.live_feeds.bubble === 'public' + : timelineAccess.live_feeds.bubble === 'public') ) { items.push({ to: '/timeline/bubble', @@ -128,9 +130,10 @@ const TimelinePicker: React.FC = ({ active }) => { }); } if ( - features.bubbleTimeline && isLoggedIn + features.publicTimeline && + (isLoggedIn ? timelineAccess.live_feeds.bubble !== 'disabled' - : timelineAccess.live_feeds.bubble === 'public' + : timelineAccess.live_feeds.bubble === 'public') ) { items.push({ to: '/timeline/fediverse', @@ -140,9 +143,10 @@ const TimelinePicker: React.FC = ({ active }) => { }); } if ( - features.wrenchedTimeline && isLoggedIn + features.wrenchedTimeline && + (isLoggedIn ? timelineAccess.live_feeds.wrenched !== 'disabled' - : timelineAccess.live_feeds.wrenched === 'public' + : timelineAccess.live_feeds.wrenched === 'public') ) { items.push({ to: '/timeline/wrenched', From 9ffe24b9af00b9e4e003efa3ac0c5ceb62e314d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 19 Mar 2026 17:47:26 +0100 Subject: [PATCH 48/64] Revert "nicolium: try to improve loading time" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1343d2888f11ee621d6cb2e652a54207285120f2. Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/actions/instance.ts | 23 ++++++-------------- packages/nicolium/src/init/nicolium-load.tsx | 6 ++--- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/packages/nicolium/src/actions/instance.ts b/packages/nicolium/src/actions/instance.ts index c34659064..9086d7aba 100644 --- a/packages/nicolium/src/actions/instance.ts +++ b/packages/nicolium/src/actions/instance.ts @@ -14,23 +14,16 @@ const getHost = () => { } }; -const doFetchInstance = async () => { - const client = getClient(); - const instance = await client.instance.getInstance(); - - useInstanceStore.getState().actions.loadInstance(instance); - useComposeStore.getState().actions.importDefaultContentType(instance); -}; - const fetchInstance = async () => { - const { fetched, instanceFetchFailed } = useInstanceStore.getState(); - if (fetched || (instanceFetchFailed && !getAuthUserUrl())) return; + try { + const client = getClient(); + const instance = await client.instance.getInstance(); - const promise = doFetchInstance().catch((error) => { + useInstanceStore.getState().actions.loadInstance(instance); + useComposeStore.getState().actions.importDefaultContentType(instance); + } catch (error) { useInstanceStore.getState().actions.instanceFetchFailed(error); - }); - - if (!fetched && !getAuthUserUrl()) await promise; + } }; const checkIfStandalone = () => @@ -38,11 +31,9 @@ const checkIfStandalone = () => .then(({ ok, headers }) => { const isOk = ok && !!headers.get('content-type')?.includes('application/json'); useInstanceStore.getState().actions.setInstanceFetchFailed(!isOk); - return !isOk; }) .catch((err) => { useInstanceStore.getState().actions.setInstanceFetchFailed(!err.response?.ok); - return true; }); export { getHost, fetchInstance, checkIfStandalone }; diff --git a/packages/nicolium/src/init/nicolium-load.tsx b/packages/nicolium/src/init/nicolium-load.tsx index e1a6953bb..b32e613eb 100644 --- a/packages/nicolium/src/init/nicolium-load.tsx +++ b/packages/nicolium/src/init/nicolium-load.tsx @@ -42,12 +42,10 @@ const NicoliumLoad: React.FC = ({ children }) => { useEffect(() => { /** Load initial data from the backend */ const loadInitial = async () => { - const standaloneCheck = checkIfStandalone(); + checkIfStandalone(); // Await for authenticated fetch await fetchMe(); - // Wait for standalone detection before proceeding - await standaloneCheck; - // Await for feature detection (skipped if already fetched or standalone) + // Await for feature detection await fetchInstance(); // Await for configuration await loadFrontendConfig(); From 510ce84dda5cf3f9fb2db4ba87d080db08bc6685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 20 Mar 2026 10:13:14 +0100 Subject: [PATCH 49/64] fix changelog link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- CHANGELOG.md | 165 +-------------------------------------------------- 1 file changed, 1 insertion(+), 164 deletions(-) mode change 100644 => 120000 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index af05d2949..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,164 +0,0 @@ -# Changelog - -## Unreleased - -Changes made since the project forked from Soapbox in April 2024. - -### Major changes - -- Switched to a separate library [`pl-api`](https://codeberg.org/nicolium/nicolium/src/branch/develop/packages/pl-api) for Mastodon API integration. It is mostly written from scratch, inheriting minor code parts from Soapbox/Mastodon. This also comes with improved compatibility with various Mastodon API extensions and abstracts out the implementation details. - -### Added - -- Cat ears - -**Behavior:** - -- Notifications of the same type and reposts of the same post are grouped client-side. -- Date is displayed for notifications that are not about new posts. -- Replies to your posts are displayed differently to other mentions in notification list. -- Hashtags from the last line of a post are displayed in a separate component. Adapted [from Mastodon](https://github.com/mastodon/mastodon/pull/26499). -- Native grouped notifications are used on Mastodon. -- Likes, reposts and reactions lists are displayed on long press of respective buttons. -- User local time is displayed on profile and in account hover card, if specified in profile fields. -- Poll results can be displayed before voting. - -**Settings:** - -- You can add image description to your avatar/backend, if supported by backend. -- GoToSocial users can manage post interaction policies. -- Users can set interface theme color. -- Users can adjust interface size. -- Users can use system font for emoji rendering. - -**Composing posts:** - -- WYSIWYG text formatting, available if Markdown is supported. -- When writing posts, links to statuses are added as quotes, when supported by backend. -- You can select post language manually, when composing. -- You can write posts with multiple language versions, when supported by backend. -- Language detection is done client-side for composed posts, utilizing `fasttext.wasm.js`. -- Draft posts. They are stored locally only and work with any backend. -- New visibility scopes are supported – local-only and list-only for Pleroma. Local-only is a separate switch on GoToSocial. -- On backends that support explicit mentioning, you can choose to include mentions in your replies body. -- GoToSocial users can set per-post interaction policies. -- When adding a URL with tracking parameters, a suggestion to remove them from the URL is displayed. -- On supported backends, you can see post preview before posting. -- When entering a long, all-lowercase hashtag, a suggestion about hashtag accessibility is displayed. - -**Dashboard:** - -- Dashboard main page displays metrics included in Mastodon admin dashboard, if supported by backend. - -**Features:** - -- The most recent scrobble is displayed on user profile/card. -- Users can generate _interaction circles_ for their profiles. -- You can bite users, if supported by backend. -- You can browse Bubble timeline, if supported by backend. -- Mastodon displays trending articles on Search page. -- Posts can be addressed to lists of users, on Pleroma. -- Support for events with external registration. -- Added a dedicated wrench reaction button. -- Interaction requests are supported. You can review pending requests and you get informed if your backend doesn't let you reply to a post. Supported on GoToSocial. -- Events with external sign up are supported. -- Application name used to post a status is displayed. -- Outgoing follow requests are displayed, if supported by backend. -- It is possible to remove tracking parameters from URLs in displayed posts. -- Displayed media now have a button for alternative text preview. -- Links in displayed posts can be configured to always display target domain, even when it's not a part of their content. -- Users can configure redirects from popular websites to proxy services like Nitter and Piped in displayed posts. -- It is possible to boost a post with specific visibility, if supported by backend. -- Pleroma shoutbox is displayed on chats page. -- Displaying user-provided media can be disabled, media descriptions will be displayed instead. -- MFM can be displayed on compatible backends. -- Lists can be set as exclusive and replies policy can be set up, if supported by backend. -- Threads can be displayed in a linear view, similarly to traditional Pleroma-FE, as an alternative to tree view. You can expand spoilers with one click. - -### Changed - -**Behavior:** - -- Separated favourites from reaction emojis. Limit for one reaction per post is removed. Facebook-like emoji reaction bar is removed. -- Simplified sensitive text/media logic. -- Reposting user is mentioned, when replying to a reposted status. -- Notification types filtering options are reasonably merged. -- Search results are never cleared by just leaving the page. -- Status spoilers are displayed with a collapse/expand button, not in an overlay. -- Mentions and hashtags in bio no longer link to external pages. -- Quotes are counted with reblogs for non-detailed statuses. -- Reactions/favourites/reblogs list modal is displayed on long press. -- Various accessibility changes, focused on screen reader compatibility. - -**Settings:** - -- Moved missing description confirmation option back to Settings page. -- Profile fields can be reordered on the Edit profile page. -- Explicit addressing can be disabled on supported backends. -- Developers options are no longer hidden behind a challenge. - -**Composing posts:** - -- Custom emojis are now split into categories. -- GoToSocial users can post with date in the past. -- Post scopes were renamed to match wording used by Mastodon. - -**UI changes:** - -- Removed header. Search bar and profile dropdown are moved to the sidebar. Mobile sidebar button is moved to the thumb navigation. -- Floating action button for creating new posts is moved to the thumb navigation. -- Mobile sidebar UI is changed to look like a popover. -- Added some animations, improved consistency of the existing ones. -- Max width of the layout is increased. -- Updated Lists UI, to match the overall style. -- RSS button is displayed in account header for local users, when unauthenticated. -- Conversations page is always displayed, even when Chats are supported. -- Made it woke. -- Emojis are zoomed on hover. -- Event create/edit form is now a page, instead of a modal. -- A star is used for favorite icon, instead of a heart. -- Account avatars are squared. -- Background gradients can be disabled. Some other visual behavior depends on this setting. -- Tabler Icons were replaced with Phosphor Icons. -- The entire loading process uses the same animation now. -- Changed status info and notification title design. -- Redesigned audio/video player controls. - -**Internal:** - -- Migrated some local stores from Redux to Zustand. Other stores have been migrated away from `immutable`, before moving them either to Zustand or TanStack Query. -- Posts are now emojified during render, instead of when inserting posts to the state. -- Barrel exports are no longer used. -- Search page uses URL params now. -- Themes use `adoptedStyleSheets` to work with stricter CSP. -- Settings store uses a different key in development environment. -- Styles are being migrated from TailwindCSS to just scss. -- Default max image size is increased to match Mastodon limits. - -**Dependencies:** - -- Replaced `react-popper` and `react-overlays` with `@floating-ui/react`. -- `uuid` package is replaced by the `randomUUID()` method. - -### Removed - -- Removed Truth Social-specific features. -- Removed Nostr-specific stuff. -- Removed Rumble-specific embed handling. -- Removed option that pretends to disable name editing for verified users. -- Removed Call to Action banner. -- Removed links to block explorers for crypto addresses. -- Removed support for custom apps provided during build. -- Removed so called 'GDPR banner'. -- Removed embed page which loads too much for the use case. - -### Fixed - -- When initializing FaviconService, canvas export permission is checked. -- Improved regex for mentions in post composer. -- Post tombstones don't interrupt status navigation with hotkeys. -- Emojis are supported in poll options. -- Unsupported content types are not listed as available, when composing a post. -- Admin dashboard now works on non-Pleroma backends. -- Removed excessive calls to `fetchOwnAccounts`. -- Media modal displays the whole thread correctly. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 120000 index 000000000..83b694704 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +CHANGELOG.md \ No newline at end of file From 10ee44c4df8c3b6e83798d933988fd3e286c0039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 20 Mar 2026 13:47:08 +0100 Subject: [PATCH 50/64] nicolium: update changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/CHANGELOG.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/nicolium/CHANGELOG.md b/packages/nicolium/CHANGELOG.md index af05d2949..1037aefec 100644 --- a/packages/nicolium/CHANGELOG.md +++ b/packages/nicolium/CHANGELOG.md @@ -4,6 +4,8 @@ Changes made since the project forked from Soapbox in April 2024. +This changelog does not include a lot of UI changes, consistency improvements, optimizations, accessibility improvements and updates for improved backend compatibility. It's too hard to maintain such a list manually and it wouldn't be really that useful. + ### Major changes - Switched to a separate library [`pl-api`](https://codeberg.org/nicolium/nicolium/src/branch/develop/packages/pl-api) for Mastodon API integration. It is mostly written from scratch, inheriting minor code parts from Soapbox/Mastodon. This also comes with improved compatibility with various Mastodon API extensions and abstracts out the implementation details. @@ -22,6 +24,8 @@ Changes made since the project forked from Soapbox in April 2024. - Likes, reposts and reactions lists are displayed on long press of respective buttons. - User local time is displayed on profile and in account hover card, if specified in profile fields. - Poll results can be displayed before voting. +- By default, home timeline remembers the moment you stopped scrolling and restores the position when you're back in the app. +- A 'Skip pinned posts' button was added to user profiles. **Settings:** @@ -74,6 +78,10 @@ Changes made since the project forked from Soapbox in April 2024. - MFM can be displayed on compatible backends. - Lists can be set as exclusive and replies policy can be set up, if supported by backend. - Threads can be displayed in a linear view, similarly to traditional Pleroma-FE, as an alternative to tree view. You can expand spoilers with one click. +- Iceshrimp.NET drive is supported, allowing to upload and manage files and attach them to uploaded posts. +- Posts (including private ones, also for unauthenticated users) can be translated locally, on browsers supporting Translator API. +- You can set blocks to auto-expire on Pleroma. +- Antennas and circles are supported on Mastodon forks that implement those. ### Changed @@ -89,6 +97,10 @@ Changes made since the project forked from Soapbox in April 2024. - Quotes are counted with reblogs for non-detailed statuses. - Reactions/favourites/reblogs list modal is displayed on long press. - Various accessibility changes, focused on screen reader compatibility. +- Posts in timelines are now displayed grouped together if they belong to the same context. +- Users get asked to update account note when blocking/muting accounts. +- Bookmark folder selection modal lets you filter folders by searching. +- Improved provding meta information for posts to improve Reader Mode on Firefox. **Settings:** @@ -123,10 +135,11 @@ Changes made since the project forked from Soapbox in April 2024. - The entire loading process uses the same animation now. - Changed status info and notification title design. - Redesigned audio/video player controls. +- Some UI elements like sliders got animations and accessibility improvements. **Internal:** -- Migrated some local stores from Redux to Zustand. Other stores have been migrated away from `immutable`, before moving them either to Zustand or TanStack Query. +- Migrated client data stores from Redux to Zustand and remote data stores to TanStack Query. Stores have been migrated away from `immutable`. - Posts are now emojified during render, instead of when inserting posts to the state. - Barrel exports are no longer used. - Search page uses URL params now. @@ -134,11 +147,17 @@ Changes made since the project forked from Soapbox in April 2024. - Settings store uses a different key in development environment. - Styles are being migrated from TailwindCSS to just scss. - Default max image size is increased to match Mastodon limits. +- Router has been migrated from React Router to TanStack Router. **Dependencies:** - Replaced `react-popper` and `react-overlays` with `@floating-ui/react`. - `uuid` package is replaced by the `randomUUID()` method. +- Some libraries, like the PullToRefresh component, have been included directly into the app. +- `react-motion` dependency has been removed, adopting migration to `@react-spring/web` from Mastodon. +- A fork of `react-hotkeys` has been replaced with new hotkey handling system from Mastodon. +- FlexSearch was replaced with `fuzzysort` package for emoji search. +- Replaced ESLint with `oxfmt` and `oxlint`. ### Removed From c9adbe82c93558533d6b968eb001e9ff87706105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 20 Mar 2026 13:54:34 +0100 Subject: [PATCH 51/64] nicolium: changelog page structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/CHANGELOG.md | 233 ++++++++++++++++----------------- 1 file changed, 115 insertions(+), 118 deletions(-) diff --git a/packages/nicolium/CHANGELOG.md b/packages/nicolium/CHANGELOG.md index 1037aefec..329e787a2 100644 --- a/packages/nicolium/CHANGELOG.md +++ b/packages/nicolium/CHANGELOG.md @@ -4,180 +4,177 @@ Changes made since the project forked from Soapbox in April 2024. -This changelog does not include a lot of UI changes, consistency improvements, optimizations, accessibility improvements and updates for improved backend compatibility. It's too hard to maintain such a list manually and it wouldn't be really that useful. +> This changelog does not cover every UI change, consistency improvement, optimization, accessibility improvement, or backend compatibility update — maintaining such a list manually would be impractical. ### Major changes - Switched to a separate library [`pl-api`](https://codeberg.org/nicolium/nicolium/src/branch/develop/packages/pl-api) for Mastodon API integration. It is mostly written from scratch, inheriting minor code parts from Soapbox/Mastodon. This also comes with improved compatibility with various Mastodon API extensions and abstracts out the implementation details. +- Migrated client data stores from Redux to Zustand and remote data stores to TanStack Query. Stores have been migrated away from `immutable`. +- Migrated router from React Router to TanStack Router. +- Styles are being migrated from TailwindCSS to SCSS. +- Cat ears. ### Added -- Cat ears - -**Behavior:** - +#### Behavior - Notifications of the same type and reposts of the same post are grouped client-side. -- Date is displayed for notifications that are not about new posts. -- Replies to your posts are displayed differently to other mentions in notification list. -- Hashtags from the last line of a post are displayed in a separate component. Adapted [from Mastodon](https://github.com/mastodon/mastodon/pull/26499). - Native grouped notifications are used on Mastodon. -- Likes, reposts and reactions lists are displayed on long press of respective buttons. +- Date is displayed for notifications that are not about new posts. +- Replies to your posts are displayed differently from other mentions in the notification list. +- Hashtags from the last line of a post are displayed in a separate component. Adapted [from Mastodon](https://github.com/mastodon/mastodon/pull/26499). +- Likes, reposts, and reactions lists are displayed on long press of respective buttons. - User local time is displayed on profile and in account hover card, if specified in profile fields. - Poll results can be displayed before voting. -- By default, home timeline remembers the moment you stopped scrolling and restores the position when you're back in the app. -- A 'Skip pinned posts' button was added to user profiles. +- Home timeline remembers scroll position by default and restores it when you return to the app. +- A "Skip pinned posts" button was added to user profiles. +- Posts in timelines are displayed grouped together if they belong to the same context. -**Settings:** - -- You can add image description to your avatar/backend, if supported by backend. -- GoToSocial users can manage post interaction policies. -- Users can set interface theme color. -- Users can adjust interface size. -- Users can use system font for emoji rendering. - -**Composing posts:** +#### Composing posts - WYSIWYG text formatting, available if Markdown is supported. -- When writing posts, links to statuses are added as quotes, when supported by backend. -- You can select post language manually, when composing. -- You can write posts with multiple language versions, when supported by backend. -- Language detection is done client-side for composed posts, utilizing `fasttext.wasm.js`. -- Draft posts. They are stored locally only and work with any backend. -- New visibility scopes are supported – local-only and list-only for Pleroma. Local-only is a separate switch on GoToSocial. -- On backends that support explicit mentioning, you can choose to include mentions in your replies body. -- GoToSocial users can set per-post interaction policies. -- When adding a URL with tracking parameters, a suggestion to remove them from the URL is displayed. -- On supported backends, you can see post preview before posting. -- When entering a long, all-lowercase hashtag, a suggestion about hashtag accessibility is displayed. +- Links to statuses are added as quotes when supported by backend. +- Manual post language selection. +- Posts with multiple language versions, when supported by backend. +- Client-side language detection for composed posts via `fasttext.wasm.js`. +- Draft posts, stored locally and compatible with any backend. +- New visibility scopes: local-only and list-only for Pleroma; local-only as a separate switch on GoToSocial. +- Optional inclusion of mentions in reply body on backends that support explicit mentioning. +- Per-post interaction policies for GoToSocial users. +- Suggestion to remove tracking parameters when adding a URL. +- Post preview before posting, on supported backends. +- Suggestion about hashtag accessibility when entering long, all-lowercase hashtags. -**Dashboard:** +#### Features -- Dashboard main page displays metrics included in Mastodon admin dashboard, if supported by backend. - -**Features:** - -- The most recent scrobble is displayed on user profile/card. +- Most recent scrobble is displayed on user profile/card. - Users can generate _interaction circles_ for their profiles. -- You can bite users, if supported by backend. -- You can browse Bubble timeline, if supported by backend. -- Mastodon displays trending articles on Search page. -- Posts can be addressed to lists of users, on Pleroma. -- Support for events with external registration. -- Added a dedicated wrench reaction button. -- Interaction requests are supported. You can review pending requests and you get informed if your backend doesn't let you reply to a post. Supported on GoToSocial. -- Events with external sign up are supported. +- Bite users, if supported by backend. +- Bubble timeline, if supported by backend. +- Mastodon displays trending articles on the Search page. +- Posts can be addressed to lists of users on Pleroma. +- Events with external registration. +- Dedicated wrench reaction button. +- Interaction requests: review pending requests and get informed if your backend doesn't let you reply to a post (GoToSocial). - Application name used to post a status is displayed. - Outgoing follow requests are displayed, if supported by backend. -- It is possible to remove tracking parameters from URLs in displayed posts. -- Displayed media now have a button for alternative text preview. -- Links in displayed posts can be configured to always display target domain, even when it's not a part of their content. -- Users can configure redirects from popular websites to proxy services like Nitter and Piped in displayed posts. -- It is possible to boost a post with specific visibility, if supported by backend. -- Pleroma shoutbox is displayed on chats page. -- Displaying user-provided media can be disabled, media descriptions will be displayed instead. -- MFM can be displayed on compatible backends. -- Lists can be set as exclusive and replies policy can be set up, if supported by backend. -- Threads can be displayed in a linear view, similarly to traditional Pleroma-FE, as an alternative to tree view. You can expand spoilers with one click. -- Iceshrimp.NET drive is supported, allowing to upload and manage files and attach them to uploaded posts. -- Posts (including private ones, also for unauthenticated users) can be translated locally, on browsers supporting Translator API. -- You can set blocks to auto-expire on Pleroma. -- Antennas and circles are supported on Mastodon forks that implement those. +- Remove tracking parameters from URLs in displayed posts. +- Button for alternative text preview on displayed media. +- Option to always display target domain for links, even when not part of content. +- Configurable redirects from popular websites to proxy services like Nitter and Piped in displayed posts. +- Boost a post with specific visibility, if supported by backend. +- Pleroma shoutbox on the chats page. +- Option to disable user-provided media, showing descriptions instead. +- MFM rendering on compatible backends. +- Exclusive lists and replies policy, if supported by backend. +- Linear thread view (similar to traditional Pleroma-FE) as an alternative to tree view, with one-click spoiler expansion. +- Iceshrimp.NET drive support for uploading, managing, and attaching files to posts. +- Local post translation (including private posts, also for unauthenticated users) on browsers supporting the Translator API. +- Auto-expiring blocks on Pleroma. +- Antennas and circles on Mastodon forks that implement those. + +#### Settings + +- Image descriptions for avatar/header, if supported by backend. +- GoToSocial users can manage post interaction policies. +- Interface theme color selection. +- Adjustable interface size. +- Option to use system font for emoji rendering. + +#### Dashboard + +- Dashboard main page displays metrics from the Mastodon admin dashboard, if supported by backend. ### Changed -**Behavior:** +#### Behavior -- Separated favourites from reaction emojis. Limit for one reaction per post is removed. Facebook-like emoji reaction bar is removed. +- Separated favourites from reaction emojis; removed per-post reaction limit and Facebook-like emoji reaction bar. - Simplified sensitive text/media logic. -- Reposting user is mentioned, when replying to a reposted status. -- Notification types filtering options are reasonably merged. +- Reposting user is mentioned when replying to a reposted status. +- Notification type filtering options are reasonably merged. - Search results are never cleared by just leaving the page. -- Status spoilers are displayed with a collapse/expand button, not in an overlay. +- Status spoilers use a collapse/expand button instead of an overlay. - Mentions and hashtags in bio no longer link to external pages. - Quotes are counted with reblogs for non-detailed statuses. - Reactions/favourites/reblogs list modal is displayed on long press. -- Various accessibility changes, focused on screen reader compatibility. -- Posts in timelines are now displayed grouped together if they belong to the same context. +- Various accessibility improvements, focused on screen reader compatibility. - Users get asked to update account note when blocking/muting accounts. -- Bookmark folder selection modal lets you filter folders by searching. -- Improved provding meta information for posts to improve Reader Mode on Firefox. +- Bookmark folder selection modal supports filtering by search. +- Improved meta information for posts to improve Reader Mode on Firefox. -**Settings:** +#### Composing posts -- Moved missing description confirmation option back to Settings page. +- Custom emojis are split into categories. +- GoToSocial users can post with a date in the past. +- Post scopes renamed to match Mastodon wording. + +#### Settings + +- Missing description confirmation option moved back to the Settings page. - Profile fields can be reordered on the Edit profile page. - Explicit addressing can be disabled on supported backends. -- Developers options are no longer hidden behind a challenge. +- Developer options are no longer hidden behind a challenge. -**Composing posts:** +#### UI -- Custom emojis are now split into categories. -- GoToSocial users can post with date in the past. -- Post scopes were renamed to match wording used by Mastodon. - -**UI changes:** - -- Removed header. Search bar and profile dropdown are moved to the sidebar. Mobile sidebar button is moved to the thumb navigation. -- Floating action button for creating new posts is moved to the thumb navigation. -- Mobile sidebar UI is changed to look like a popover. -- Added some animations, improved consistency of the existing ones. -- Max width of the layout is increased. -- Updated Lists UI, to match the overall style. -- RSS button is displayed in account header for local users, when unauthenticated. +- Removed header; search bar and profile dropdown moved to the sidebar; mobile sidebar button moved to thumb navigation. +- Floating action button for new posts moved to thumb navigation. +- Mobile sidebar styled as a popover. +- Added animations and improved consistency of existing ones. +- Increased max width of the layout. +- Updated Lists UI to match overall style. +- RSS button displayed in account header for local users when unauthenticated. - Conversations page is always displayed, even when Chats are supported. - Made it woke. -- Emojis are zoomed on hover. -- Event create/edit form is now a page, instead of a modal. -- A star is used for favorite icon, instead of a heart. +- Emojis zoom on hover. +- Event create/edit form is now a page instead of a modal. +- Star used for favourite icon instead of a heart. - Account avatars are squared. -- Background gradients can be disabled. Some other visual behavior depends on this setting. -- Tabler Icons were replaced with Phosphor Icons. -- The entire loading process uses the same animation now. -- Changed status info and notification title design. +- Background gradients can be disabled; some visual behavior depends on this setting. +- Tabler Icons replaced with Phosphor Icons. +- Unified loading animation across the entire loading process. +- Redesigned status info and notification title. - Redesigned audio/video player controls. -- Some UI elements like sliders got animations and accessibility improvements. +- Animations and accessibility improvements for UI elements like sliders. -**Internal:** +#### Internal -- Migrated client data stores from Redux to Zustand and remote data stores to TanStack Query. Stores have been migrated away from `immutable`. -- Posts are now emojified during render, instead of when inserting posts to the state. +- Posts are emojified during render instead of when inserting into state. - Barrel exports are no longer used. -- Search page uses URL params now. +- Search page uses URL params. - Themes use `adoptedStyleSheets` to work with stricter CSP. - Settings store uses a different key in development environment. -- Styles are being migrated from TailwindCSS to just scss. -- Default max image size is increased to match Mastodon limits. -- Router has been migrated from React Router to TanStack Router. +- Default max image size increased to match Mastodon limits. -**Dependencies:** +#### Dependencies - Replaced `react-popper` and `react-overlays` with `@floating-ui/react`. -- `uuid` package is replaced by the `randomUUID()` method. -- Some libraries, like the PullToRefresh component, have been included directly into the app. -- `react-motion` dependency has been removed, adopting migration to `@react-spring/web` from Mastodon. -- A fork of `react-hotkeys` has been replaced with new hotkey handling system from Mastodon. -- FlexSearch was replaced with `fuzzysort` package for emoji search. +- Replaced `uuid` package with the `randomUUID()` method. +- Inlined some libraries, like the PullToRefresh component, directly into the app. +- Removed `react-motion`; adopted migration to `@react-spring/web` from Mastodon. +- Replaced a fork of `react-hotkeys` with Mastodon's hotkey handling system. +- Replaced FlexSearch with `fuzzysort` for emoji search. - Replaced ESLint with `oxfmt` and `oxlint`. ### Removed -- Removed Truth Social-specific features. -- Removed Nostr-specific stuff. -- Removed Rumble-specific embed handling. -- Removed option that pretends to disable name editing for verified users. -- Removed Call to Action banner. -- Removed links to block explorers for crypto addresses. -- Removed support for custom apps provided during build. -- Removed so called 'GDPR banner'. -- Removed embed page which loads too much for the use case. +- Truth Social-specific features. +- Nostr-specific features. +- Rumble-specific embed handling. +- Option that pretends to disable name editing for verified users. +- Call to Action banner. +- Links to block explorers for crypto addresses. +- Support for custom apps provided during build. +- So called 'GDPR banner'. +- Embed page (loaded too much for the use case). ### Fixed -- When initializing FaviconService, canvas export permission is checked. +- Canvas export permission is checked when initializing FaviconService. - Improved regex for mentions in post composer. -- Post tombstones don't interrupt status navigation with hotkeys. +- Post tombstones no longer interrupt status navigation with hotkeys. - Emojis are supported in poll options. -- Unsupported content types are not listed as available, when composing a post. +- Unsupported content types are not listed as available when composing a post. - Admin dashboard now works on non-Pleroma backends. - Removed excessive calls to `fetchOwnAccounts`. - Media modal displays the whole thread correctly. From ab68f245c076158669d5a671de9b25a6ef6ee3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 20 Mar 2026 23:17:00 +0100 Subject: [PATCH 52/64] nicolium: disable show self-reblogs switch when show reblogs is disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/hooks/use-timeline-filters-options.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nicolium/src/hooks/use-timeline-filters-options.ts b/packages/nicolium/src/hooks/use-timeline-filters-options.ts index aa4364216..be569957c 100644 --- a/packages/nicolium/src/hooks/use-timeline-filters-options.ts +++ b/packages/nicolium/src/hooks/use-timeline-filters-options.ts @@ -59,7 +59,7 @@ const useTimelineFiltersOptions = ( return useMemo(() => { const items: Menu = []; - if (timeline == 'home') { + if (timeline === 'home') { items.push({ text: intl.formatMessage(messages.showReblogs), type: 'toggle', @@ -70,6 +70,7 @@ const useTimelineFiltersOptions = ( text: intl.formatMessage(messages.showSelfReblogs), type: 'toggle', checked: timelineSettings?.showSelfReblogs, + disabled: !timelineSettings?.showReblogs, onChange: (checked) => changeSetting(['timelines', timeline, 'showSelfReblogs'], checked), }); } From e65014708f619e1874a9bf89602e50aa2d37fa97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 20 Mar 2026 23:34:56 +0100 Subject: [PATCH 53/64] nicolium: minor style fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/styles/new/statuses.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nicolium/src/styles/new/statuses.scss b/packages/nicolium/src/styles/new/statuses.scss index 02ec1587e..cc8f76eda 100644 --- a/packages/nicolium/src/styles/new/statuses.scss +++ b/packages/nicolium/src/styles/new/statuses.scss @@ -659,11 +659,11 @@ } .dark.black .⁂-quoted-status:hover & { - background-image: linear-gradient(to bottom, transparent, rgb(var(--color-gray-800))); + background-image: linear-gradient(to bottom, transparent, rgb(var(--color-primary-800))); } .dark .⁂-quoted-status:hover & { - background-image: linear-gradient(to bottom, transparent, rgb(var(--color-gray-800))); + background-image: linear-gradient(to bottom, transparent, rgb(var(--color-primary-800))); } } From d0ab4369312d8ab930df4b6ac7cdab9c88186d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Fri, 20 Mar 2026 23:53:28 +0100 Subject: [PATCH 54/64] nicolium: add opt-in confirmation modal for wrench button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/CHANGELOG.md | 1 + .../components/statuses/status-action-bar.tsx | 29 ++++++++++++++++--- packages/nicolium/src/locales/en.json | 5 ++++ .../pages/settings/components/preferences.tsx | 23 +++++++++++++++ .../nicolium/src/schemas/frontend-settings.ts | 1 + 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/packages/nicolium/CHANGELOG.md b/packages/nicolium/CHANGELOG.md index 329e787a2..87aa0c441 100644 --- a/packages/nicolium/CHANGELOG.md +++ b/packages/nicolium/CHANGELOG.md @@ -17,6 +17,7 @@ Changes made since the project forked from Soapbox in April 2024. ### Added #### Behavior + - Notifications of the same type and reposts of the same post are grouped client-side. - Native grouped notifications are used on Mastodon. - Date is displayed for notifications that are not about new posts. diff --git a/packages/nicolium/src/components/statuses/status-action-bar.tsx b/packages/nicolium/src/components/statuses/status-action-bar.tsx index 01cea8bfc..bc9fe5b84 100644 --- a/packages/nicolium/src/components/statuses/status-action-bar.tsx +++ b/packages/nicolium/src/components/statuses/status-action-bar.tsx @@ -43,7 +43,7 @@ import iconWrench from '@phosphor-icons/core/regular/wrench.svg'; import { useMatch, useNavigate } from '@tanstack/react-router'; import { type Account, type CustomEmoji, GroupRoles } from 'pl-api'; import React, { useCallback, useMemo } from 'react'; -import { defineMessages, useIntl } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { changeSetting } from '@/actions/settings'; import { editStatus, toggleMuteStatus, redactStatus } from '@/actions/statuses'; @@ -230,6 +230,7 @@ const messages = defineMessages({ unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, viewReactions: { id: 'status.view_reactions', defaultMessage: 'View reactions' }, wrench: { id: 'status.wrench', defaultMessage: 'Wrench reaction' }, + wrenchConfirm: { id: 'confirmations.wrench.confirm', defaultMessage: 'Wrench' }, addKnownLanguage: { id: 'status.add_known_language', defaultMessage: 'Do not auto-translate posts in {language}.', @@ -678,7 +679,7 @@ const WrenchButton: React.FC = ({ status, withLabels, me }) => { const features = useFeatures(); const { openModal } = useModalsActions(); - const { showWrenchButton } = useSettings(); + const { showWrenchButton, wrenchModal } = useSettings(); const { mutate: emojiReact } = useEmojiReactMutation(status.id); const { mutate: emojiUnreact } = useEmojiUnreactMutation(status.id); @@ -690,17 +691,37 @@ const WrenchButton: React.FC = ({ status, withLabels, me }) => { const wrenches = showWrenchButton && (status.emoji_reactions.find((emoji) => emoji.name === '🔧') ?? undefined); + const checkConfirmation = (callback: () => void) => { + if (wrenchModal) { + openModal('CONFIRM', { + heading: ( + + ), + message: ( + + ), + confirm: intl.formatMessage(messages.wrenchConfirm), + onConfirm: callback, + }); + } else { + callback(); + } + }; + const handleWrenchClick: React.EventHandler = () => { if (wrenches?.me) { emojiUnreact('🔧'); } else { - emojiReact('🔧'); + checkConfirmation(() => emojiReact('🔧')); } }; const handleWrenchLongPress = () => { if (features.customEmojiReacts && hasLongerWrench) { - emojiReact(hasLongerWrench.shortcode); + checkConfirmation(() => emojiReact(hasLongerWrench.shortcode)); } else if (wrenches?.count) { openModal('REACTIONS', { statusId: status.id, reaction: wrenches.name }); } diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index 77a14943d..32a99b557 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -799,6 +799,9 @@ "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.heading": "Unfollow {name}", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", + "confirmations.wrench.confirm": "Wrench", + "confirmations.wrench.heading": "Wrench the post", + "confirmations.wrench.message": "Are you sure you want to wrench this post? This can have disastrous consequences.", "copy.success": "Copied to clipboard!", "crypto.lightning": "Lightning", "crypto_donate.explanation_box.message": "{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!", @@ -1627,6 +1630,8 @@ "preferences.fields.web_layout_label": "Layout of the web view of your profile", "preferences.fields.web_visibility_label": "Visibility level of posts displayed on your profile", "preferences.fields.wrench_label": "Display wrench reaction button", + "preferences.fields.wrench_modal_hint": "Prevents the consequences of accidentally using the wrench button.", + "preferences.fields.wrench_modal_label": "Show confirmation dialog before adding wrench reaction", "preferences.hints.demetricator": "Decrease social media anxiety by hiding all numbers from the site.", "preferences.hints.mention_policy": "Applies to direct messages and public posts", "preferences.hints.web_include_boosts": "Show reposts created by the account on the web view of your profile", diff --git a/packages/nicolium/src/pages/settings/components/preferences.tsx b/packages/nicolium/src/pages/settings/components/preferences.tsx index 5b4dd42d6..5b439846d 100644 --- a/packages/nicolium/src/pages/settings/components/preferences.tsx +++ b/packages/nicolium/src/pages/settings/components/preferences.tsx @@ -815,6 +815,29 @@ const Preferences = () => { onChange={onToggleChange} /> + + {settings.showWrenchButton && ( + + } + hint={ + + } + > + + + )} diff --git a/packages/nicolium/src/schemas/frontend-settings.ts b/packages/nicolium/src/schemas/frontend-settings.ts index 1be2509cb..9bedeee69 100644 --- a/packages/nicolium/src/schemas/frontend-settings.ts +++ b/packages/nicolium/src/schemas/frontend-settings.ts @@ -21,6 +21,7 @@ const settingsSchema = v.object({ boostModal: v.fallback(v.boolean(), false), deleteModal: v.fallback(v.boolean(), true), missingDescriptionModal: v.fallback(v.boolean(), true), + wrenchModal: v.fallback(v.boolean(), false), ignoreHashtagCasingSuggestions: v.fallback(v.boolean(), false), defaultPrivacy: v.fallback(v.picklist(['public', 'unlisted', 'private', 'direct']), 'public'), defaultContentType: v.fallback( From b391f014526ff53c3d9090d0f49ae0e87e02377a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 12:37:20 +0100 Subject: [PATCH 55/64] nicolium: add confirmation for reposting a post without description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/statuses/status-action-bar.tsx | 36 ++++++++++++++++--- packages/nicolium/src/locales/en.json | 3 ++ .../nicolium/src/schemas/frontend-settings.ts | 1 + 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/nicolium/src/components/statuses/status-action-bar.tsx b/packages/nicolium/src/components/statuses/status-action-bar.tsx index bc9fe5b84..c78558f2a 100644 --- a/packages/nicolium/src/components/statuses/status-action-bar.tsx +++ b/packages/nicolium/src/components/statuses/status-action-bar.tsx @@ -114,6 +114,10 @@ const messages = defineMessages({ id: 'status.bookmark_folder_change', defaultMessage: 'Change bookmark folder', }, + boostConfirm: { + id: 'confirmations.boost_missing_description.confirm', + defaultMessage: 'Repost anyway', + }, cancelReblogPrivate: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' }, cannotReblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be reposted' }, chat: { id: 'status.chat', defaultMessage: 'Chat with @{name}' }, @@ -456,7 +460,7 @@ const ReblogButton: React.FC = ({ const features = useFeatures(); const intl = useIntl(); - const { boostModal } = useSettings(); + const { boostModal, missingDescriptionBoostModal } = useSettings(); const { openModal } = useModalsActions(); const canReblog = useCanInteract(status, 'can_reblog'); const canQuote = useCanInteract(status, 'can_quote'); @@ -474,7 +478,11 @@ const ReblogButton: React.FC = ({ const handleReblogClick: React.EventHandler = (e) => { if (me) { - const modalReblog = () => { + const hasMissingDescriptions = status.media_attachments.some( + (attachment) => attachment.type !== 'unknown' && !attachment.description, + ); + + const doReblog = () => { if (status.reblogged) { unreblogStatus(); } else { @@ -485,10 +493,28 @@ const ReblogButton: React.FC = ({ }); } }; - if ((e && e.shiftKey) || !boostModal) { - modalReblog(); + + if (missingDescriptionBoostModal && hasMissingDescriptions) { + openModal('CONFIRM', { + heading: ( + + ), + message: ( + + ), + confirm: intl.formatMessage(messages.boostConfirm), + onConfirm: doReblog, + }); + } else if ((e && e.shiftKey) || !boostModal) { + doReblog(); } else { - openModal('BOOST', { statusId: status.id, onReblog: modalReblog }); + openModal('BOOST', { statusId: status.id, onReblog: doReblog }); } } else { onOpenUnauthorizedModal('REBLOG'); diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index 32a99b557..f3169b144 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -729,6 +729,9 @@ "confirmations.block_from_group.confirm": "Ban user", "confirmations.block_from_group.heading": "Ban from group", "confirmations.block_from_group.message": "Are you sure you want to ban @{name} from the group?", + "confirmations.boost_missing_description.confirm": "Repost anyway", + "confirmations.boost_missing_description.heading": "Reposting a post with missing description", + "confirmations.boost_missing_description.message": "The post does not have a description for all attachments. Do you want to repost it anyway?", "confirmations.cancel.confirm": "Discard", "confirmations.cancel.heading": "Discard post", "confirmations.cancel.message": "Are you sure you want to discard the currently composed post?", diff --git a/packages/nicolium/src/schemas/frontend-settings.ts b/packages/nicolium/src/schemas/frontend-settings.ts index 9bedeee69..f1dd8b8ab 100644 --- a/packages/nicolium/src/schemas/frontend-settings.ts +++ b/packages/nicolium/src/schemas/frontend-settings.ts @@ -22,6 +22,7 @@ const settingsSchema = v.object({ deleteModal: v.fallback(v.boolean(), true), missingDescriptionModal: v.fallback(v.boolean(), true), wrenchModal: v.fallback(v.boolean(), false), + missingDescriptionBoostModal: v.fallback(v.boolean(), false), ignoreHashtagCasingSuggestions: v.fallback(v.boolean(), false), defaultPrivacy: v.fallback(v.picklist(['public', 'unlisted', 'private', 'direct']), 'public'), defaultContentType: v.fallback( From f2e0e1935db13b6d4ca52df288cf1e2b6c7a6ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 12:57:53 +0100 Subject: [PATCH 56/64] nicolium: add a check for meaningless descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/statuses/status-action-bar.tsx | 32 +++++++++++++++---- packages/nicolium/src/locales/en.json | 1 + 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/nicolium/src/components/statuses/status-action-bar.tsx b/packages/nicolium/src/components/statuses/status-action-bar.tsx index c78558f2a..0432b2739 100644 --- a/packages/nicolium/src/components/statuses/status-action-bar.tsx +++ b/packages/nicolium/src/components/statuses/status-action-bar.tsx @@ -478,10 +478,18 @@ const ReblogButton: React.FC = ({ const handleReblogClick: React.EventHandler = (e) => { if (me) { - const hasMissingDescriptions = status.media_attachments.some( - (attachment) => attachment.type !== 'unknown' && !attachment.description, + const attachments = status.media_attachments.filter( + (attachment) => attachment.type !== 'unknown', ); + const hasMissingDescriptions = attachments.some((attachment) => !attachment.description); + + const hasFilenameDescriptions = attachments.some((attachment) => { + const extension = (attachment.remote_url || attachment.url).split('.').pop()?.toLowerCase(); + + return attachment.description.trim().endsWith(`.${extension}`); + }); + const doReblog = () => { if (status.reblogged) { unreblogStatus(); @@ -494,7 +502,7 @@ const ReblogButton: React.FC = ({ } }; - if (missingDescriptionBoostModal && hasMissingDescriptions) { + if (missingDescriptionBoostModal && (hasMissingDescriptions || hasFilenameDescriptions)) { openModal('CONFIRM', { heading: ( = ({ /> ), message: ( - + <> + {hasMissingDescriptions && ( + + )} + {hasFilenameDescriptions && ( + + )} + ), confirm: intl.formatMessage(messages.boostConfirm), onConfirm: doReblog, diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index f3169b144..4be96c61d 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -730,6 +730,7 @@ "confirmations.block_from_group.heading": "Ban from group", "confirmations.block_from_group.message": "Are you sure you want to ban @{name} from the group?", "confirmations.boost_missing_description.confirm": "Repost anyway", + "confirmations.boost_missing_description.filename_warning": "One or more attachments likely has a filename (e.g. 'image.jpg') as its description instead of meaningful alt text. Do you want to repost it anyway?", "confirmations.boost_missing_description.heading": "Reposting a post with missing description", "confirmations.boost_missing_description.message": "The post does not have a description for all attachments. Do you want to repost it anyway?", "confirmations.cancel.confirm": "Discard", From 5c33d7d8c797627866152180042fff6d283ee3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 13:08:50 +0100 Subject: [PATCH 57/64] nicolium: add a toggle for the new modal lol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../src/components/statuses/status-action-bar.tsx | 1 - packages/nicolium/src/locales/en.json | 1 + .../src/pages/settings/components/preferences.tsx | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/nicolium/src/components/statuses/status-action-bar.tsx b/packages/nicolium/src/components/statuses/status-action-bar.tsx index 0432b2739..fda8f8ee2 100644 --- a/packages/nicolium/src/components/statuses/status-action-bar.tsx +++ b/packages/nicolium/src/components/statuses/status-action-bar.tsx @@ -486,7 +486,6 @@ const ReblogButton: React.FC = ({ const hasFilenameDescriptions = attachments.some((attachment) => { const extension = (attachment.remote_url || attachment.url).split('.').pop()?.toLowerCase(); - return attachment.description.trim().endsWith(`.${extension}`); }); diff --git a/packages/nicolium/src/locales/en.json b/packages/nicolium/src/locales/en.json index 4be96c61d..3a10ad624 100644 --- a/packages/nicolium/src/locales/en.json +++ b/packages/nicolium/src/locales/en.json @@ -1608,6 +1608,7 @@ "preferences.fields.language_label": "Display language", "preferences.fields.media_display_label": "Sensitive content", "preferences.fields.mention_policy_label": "Accept mentions from", + "preferences.fields.missing_description_boost_modal_label": "Show confirmation dialog before reposting a post without media descriptions", "preferences.fields.missing_description_modal_label": "Show confirmation dialog before sending a post without media descriptions", "preferences.fields.preserve_spoilers_label": "Preserve content warning when replying", "preferences.fields.privacy_label": "Default post privacy", diff --git a/packages/nicolium/src/pages/settings/components/preferences.tsx b/packages/nicolium/src/pages/settings/components/preferences.tsx index 5b439846d..d28112dee 100644 --- a/packages/nicolium/src/pages/settings/components/preferences.tsx +++ b/packages/nicolium/src/pages/settings/components/preferences.tsx @@ -801,6 +801,21 @@ const Preferences = () => { /> + + } + > + + + Date: Sat, 21 Mar 2026 15:34:30 +0100 Subject: [PATCH 58/64] nicolium: add a v0.1.0 tag to the changelog as i'm doing a feature freeze MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/nicolium/CHANGELOG.md b/packages/nicolium/CHANGELOG.md index 87aa0c441..a000c5ed1 100644 --- a/packages/nicolium/CHANGELOG.md +++ b/packages/nicolium/CHANGELOG.md @@ -1,10 +1,8 @@ # Changelog -## Unreleased +## v0.1.0 -Changes made since the project forked from Soapbox in April 2024. - -> This changelog does not cover every UI change, consistency improvement, optimization, accessibility improvement, or backend compatibility update — maintaining such a list manually would be impractical. +> This list includes changes made since the project forked from Soapbox in April 2024. It does not cover every UI change, consistency improvement, optimization, accessibility improvement, or backend compatibility update — maintaining such a list manually would be impractical. ### Major changes From 5a02e3d73ec58d37ad1c4d5734717da4da24e5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 17:34:37 +0100 Subject: [PATCH 59/64] nicolium: a terrible fix for 'emoji in display name gets truncated on hover' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../components/panels/profile-info-panel.tsx | 2 +- .../nicolium/src/features/emoji/emojify.tsx | 43 +++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/nicolium/src/components/panels/profile-info-panel.tsx b/packages/nicolium/src/components/panels/profile-info-panel.tsx index 568b51b94..bf5a8381b 100644 --- a/packages/nicolium/src/components/panels/profile-info-panel.tsx +++ b/packages/nicolium/src/components/panels/profile-info-panel.tsx @@ -180,7 +180,7 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => {account.deactivated ? ( ) : ( - + )} diff --git a/packages/nicolium/src/features/emoji/emojify.tsx b/packages/nicolium/src/features/emoji/emojify.tsx index 14af8ff6b..528bb27ff 100644 --- a/packages/nicolium/src/features/emoji/emojify.tsx +++ b/packages/nicolium/src/features/emoji/emojify.tsx @@ -18,16 +18,22 @@ interface IMaybeEmoji { text: string; emojis: Record; nyaize: boolean; + truncated: boolean; } -const MaybeEmoji: React.FC = ({ text, emojis, nyaize: shouldNyaize }) => { +const MaybeEmoji: React.FC = ({ text, emojis, nyaize: shouldNyaize, truncated }) => { if (text.length < 3) return text; if (text in emojis) { const emoji = emojis[text]; const filename = emoji.static_url; if (filename?.length > 0) { - return ; + const emoji = ; + if (truncated) { + return {emoji}; + } else { + return emoji; + } } } @@ -38,10 +44,11 @@ interface IEmojify { text: string; emojis?: Array | Record; nyaize?: boolean; + truncated?: boolean; } const Emojify: React.FC = React.memo( - ({ text, emojis = {}, nyaize: shouldNyaize = false }) => { + ({ text, emojis = {}, nyaize: shouldNyaize = false, truncated = false }) => { const { disableUserProvidedMedia, systemEmojiFont } = useSettings(); if (Array.isArray(emojis)) emojis = makeEmojiMap(emojis); @@ -73,7 +80,7 @@ const Emojify: React.FC = React.memo( const { unified, shortcode } = unicodeMapping[c]; - nodes.push( + const emoji = ( = React.memo( alt={c} title={`:${shortcode}:`} src={joinPublicPath(`packs/emoji/${unified}.svg`)} - />, + /> ); + + if (truncated) { + nodes.push({emoji}); + } else { + nodes.push(emoji); + } } else if (!systemEmojiFont && unqualified in unicodeMapping) { clearStack(); const { unified, shortcode } = unicodeMapping[unqualified]; - nodes.push( + const emoji = ( = React.memo( alt={unqualified} title={`:${shortcode}:`} src={joinPublicPath(`packs/emoji/${unified}.svg`)} - />, + /> ); + + if (truncated) { + nodes.push({emoji}); + } else { + nodes.push(emoji); + } } else if (!disableUserProvidedMedia && c === ':') { if (!open) { clearStack(); @@ -107,7 +126,15 @@ const Emojify: React.FC = React.memo( // we see another : we convert it and clear the stack buffer if (open) { - nodes.push(); + nodes.push( + , + ); stack = ''; } From a08f7f382aa13d302b1152530d85103b72d41482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 17:39:37 +0100 Subject: [PATCH 60/64] nicolium: fix text overflow handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/styles/new/accounts.scss | 4 ++-- packages/nicolium/src/styles/new/components.scss | 4 ++-- packages/nicolium/src/styles/new/statuses.scss | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nicolium/src/styles/new/accounts.scss b/packages/nicolium/src/styles/new/accounts.scss index c8aae3f6e..31fc960ce 100644 --- a/packages/nicolium/src/styles/new/accounts.scss +++ b/packages/nicolium/src/styles/new/accounts.scss @@ -189,7 +189,7 @@ .⁂-profile-field { span[data-markup] { - overflow-wrap: break-word; + overflow-wrap: anywhere; } dt span[data-markup] { @@ -218,7 +218,7 @@ @include mixins.text; overflow: hidden; - overflow-wrap: break-word; + overflow-wrap: anywhere; } } diff --git a/packages/nicolium/src/styles/new/components.scss b/packages/nicolium/src/styles/new/components.scss index 4c219e366..694b1d47b 100644 --- a/packages/nicolium/src/styles/new/components.scss +++ b/packages/nicolium/src/styles/new/components.scss @@ -245,7 +245,7 @@ min-width: 1.25rem; height: 1.25rem; - overflow-wrap: break-word; + overflow-wrap: anywhere; white-space: nowrap; } } @@ -332,7 +332,7 @@ > :first-child { color: rgb(var(--color-gray-900)); - overflow-wrap: break-word; + overflow-wrap: anywhere; .dark & { color: rgb(var(--color-gray-100)); diff --git a/packages/nicolium/src/styles/new/statuses.scss b/packages/nicolium/src/styles/new/statuses.scss index cc8f76eda..30c0fb901 100644 --- a/packages/nicolium/src/styles/new/statuses.scss +++ b/packages/nicolium/src/styles/new/statuses.scss @@ -626,7 +626,7 @@ position: relative; color: rgb(var(--color-gray-900)); text-overflow: ellipsis; - overflow-wrap: break-word; + overflow-wrap: anywhere; &:focus { outline: 2px solid transparent; From e11add51575037bc7b90b34fd7678cb668628734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 17:51:19 +0100 Subject: [PATCH 61/64] nicolium: fix modal navigation, probably MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/components/media/media-gallery.tsx | 7 +++---- packages/nicolium/src/modals/media-modal.tsx | 12 +++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/nicolium/src/components/media/media-gallery.tsx b/packages/nicolium/src/components/media/media-gallery.tsx index 88b3aa4b4..164ccf098 100644 --- a/packages/nicolium/src/components/media/media-gallery.tsx +++ b/packages/nicolium/src/components/media/media-gallery.tsx @@ -117,19 +117,18 @@ const Item: React.FC = ({ // FIXME: wtf? const handleClick: React.MouseEventHandler = (e: any) => { + e.preventDefault(); + e.stopPropagation(); + if (isIOS() && !e.target.autoPlay) { e.target.autoPlay = true; - e.preventDefault(); } else if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { if (hoverToPlay()) { e.target.pause(); e.target.currentTime = 0; } - e.preventDefault(); onClick(index); } - - e.stopPropagation(); }; const handleVideoHover: React.MouseEventHandler = ({ diff --git a/packages/nicolium/src/modals/media-modal.tsx b/packages/nicolium/src/modals/media-modal.tsx index c7babf6b7..d93c2c965 100644 --- a/packages/nicolium/src/modals/media-modal.tsx +++ b/packages/nicolium/src/modals/media-modal.tsx @@ -49,7 +49,9 @@ interface MediaModalProps { } const MediaModal: React.FC = (props) => { - const { statusId, onClose, time = 0 } = props; + const { statusId, time = 0 } = props; + + const onClose = () => props.onClose('MEDIA'); const intl = useIntl(); @@ -301,7 +303,9 @@ const MediaModal: React.FC = (props) => { style={wrapperStyles} className='⁂-media-modal__closer' role='presentation' - onClick={() => { + onClick={(e) => { + e.preventDefault(); + e.stopPropagation(); onClose(); }} > @@ -318,9 +322,7 @@ const MediaModal: React.FC = (props) => { { - onClose('MEDIA'); - }} + onClick={onClose} theme='dark' className='!p-1.5 hover:scale-105 hover:bg-gray-900' iconClassName='h-5 w-5' From b27b3a8a65d422b4b8b7088a0bce6d94b1b3de44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 18:19:01 +0100 Subject: [PATCH 62/64] nicolium: a terrible fix for emoji search exact matches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../nicolium/src/features/emoji/search.ts | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/nicolium/src/features/emoji/search.ts b/packages/nicolium/src/features/emoji/search.ts index 8dfda1b5e..6b8ceba40 100644 --- a/packages/nicolium/src/features/emoji/search.ts +++ b/packages/nicolium/src/features/emoji/search.ts @@ -6,8 +6,15 @@ import type { CustomEmoji } from 'pl-api'; let emojis: EmojiData['emojis'] = {}; -const nativeData: Array<{ key: string; id: string }> = []; -let customData: Array<{ key: string; id: string }> = []; +interface SearchableEmoji { + emojiId: string; + emojiName: string; + emojiKeywords: string; + id: string; +} + +const nativeData: Array = []; +let customData: Array = []; import('./data') .then((data) => { @@ -16,8 +23,10 @@ import('./data') const sortedEmojis = Object.entries(emojis).toSorted((a, b) => a[0].localeCompare(b[0])); for (const [key, emoji] of sortedEmojis) { nativeData.push({ - key: `${emoji.id} ${emoji.name} ${emoji.keywords.join(' ')}`.replaceAll('-', '_'), - id: 'n' + key, + emojiId: emoji.id.replaceAll('-', '_'), + emojiName: emoji.name.replaceAll('-', '_'), + emojiKeywords: `${emoji.id} ${emoji.keywords.join(' ')}`.replaceAll('-', '_'), + id: 'e' + key, }); } }) @@ -25,14 +34,19 @@ import('./data') const addCustomToPool = (customEmojis: CustomEmoji[]) => { customData = customEmojis.map((emoji, i) => ({ - key: emoji.shortcode.replaceAll('-', '_'), + emojiId: '', + emojiName: emoji.shortcode.replaceAll('-', '_'), + emojiKeywords: emoji.shortcode.replaceAll('-', '_'), id: 'c' + i, })); }; const search = (query: string, customEmojis: Array = [], limit = 5): Emoji[] => { return fuzzysort - .go(query.replaceAll('-', '_'), [...nativeData, ...customData], { key: 'key', limit }) + .go(query.replaceAll('-', '_'), [...nativeData, ...customData], { + keys: ['emojiId', 'emojiName', 'emojiKeywords'], + limit, + }) .map((result) => { const { id } = result.obj; From e96a19154affa99e15b87583333269eccc3ea761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 18:39:47 +0100 Subject: [PATCH 63/64] nicolium: dark mode spinner style improvement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../src/components/ui/{spinner.css => spinner.scss} | 13 ++++++++++++- packages/nicolium/src/components/ui/spinner.tsx | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) rename packages/nicolium/src/components/ui/{spinner.css => spinner.scss} (88%) diff --git a/packages/nicolium/src/components/ui/spinner.css b/packages/nicolium/src/components/ui/spinner.scss similarity index 88% rename from packages/nicolium/src/components/ui/spinner.css rename to packages/nicolium/src/components/ui/spinner.scss index 70ce8ac90..58e844e2e 100644 --- a/packages/nicolium/src/components/ui/spinner.css +++ b/packages/nicolium/src/components/ui/spinner.scss @@ -14,12 +14,23 @@ } .spinner > div::after { - @apply block absolute rounded-full bg-gray-700 dark:bg-gray-400; + display: block; + position: absolute; + border-radius: 9999px; content: ' '; top: 3.75%; left: 46.25%; width: 7.5%; height: 22.5%; + background: rgb(var(--color-gray-700)); + + .dark & { + background: rgb(var(--color-gray-400)); + } + + .dark button & { + background: white; + } } .spinner > div:nth-child(1) { diff --git a/packages/nicolium/src/components/ui/spinner.tsx b/packages/nicolium/src/components/ui/spinner.tsx index 2deceb8f9..627862028 100644 --- a/packages/nicolium/src/components/ui/spinner.tsx +++ b/packages/nicolium/src/components/ui/spinner.tsx @@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl'; import Text from './text'; -import './spinner.css'; +import './spinner.scss'; interface ISpinner { /** Width and height of the spinner in pixels. */ From 5a6b0843480e46e4a5835f3e84f38eb96563363e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 21 Mar 2026 18:48:35 +0100 Subject: [PATCH 64/64] nicolium: fix 'exploding buttons #81', finally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/nicolium/src/components/accounts/account.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/nicolium/src/components/accounts/account.tsx b/packages/nicolium/src/components/accounts/account.tsx index eb0721de8..d0ea822c9 100644 --- a/packages/nicolium/src/components/accounts/account.tsx +++ b/packages/nicolium/src/components/accounts/account.tsx @@ -207,15 +207,17 @@ const Account = ({ useLayoutEffect(() => { const onResize = () => { + console.log('resizing'); const style: React.CSSProperties = {}; const actionWidth = actionRef.current?.clientWidth ?? 0; if (overflowRef.current) { + const maxWidth = overflowRef.current.classList.contains('w-fit') + ? overflowRef.current.parentElement!.clientWidth + : overflowRef.current.clientWidth; style.maxWidth = Math.max( 0, - overflowRef.current.clientWidth - - (withAvatar ? avatarSize + 12 : 0) - - (actionWidth ? actionWidth + 12 : 0), + maxWidth - (withAvatar ? avatarSize + 12 : 0) - (actionWidth ? actionWidth + 12 : 0), ); } @@ -344,9 +346,8 @@ const Account = ({ className={clsx('⁂-account-card', { '⁂-account-card--action-top': actionAlignment === 'top', })} - ref={overflowRef} > -
+