nicolium: add missing experimental circle timeline

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2026-03-05 14:14:13 +01:00
parent 94d7187d4e
commit 6c037c1a1c
3 changed files with 91 additions and 30 deletions

View File

@ -19,6 +19,7 @@ import { type SelectedStatus, useStatus } from '@/queries/statuses/use-status';
import {
useAntennaTimeline,
useBubbleTimeline,
useCircleTimeline,
useGroupTimeline,
useHashtagTimeline,
useHomeTimeline,
@ -347,6 +348,16 @@ const AntennaTimelineColumn: React.FC<IAntennaTimelineColumn> = ({ antennaId })
return <Timeline query={timelineQuery} contextType='public' />;
};
interface ICircleTimelineColumn {
circleId: string;
}
const CircleTimelineColumn: React.FC<ICircleTimelineColumn> = ({ circleId }) => {
const timelineQuery = useCircleTimeline(circleId);
return <Timeline query={timelineQuery} contextType='public' />;
};
const WrenchedTimelineColumn = () => {
const timelineQuery = useWrenchedTimeline();
@ -362,5 +373,6 @@ export {
GroupTimelineColumn,
BubbleTimelineColumn,
AntennaTimelineColumn,
CircleTimelineColumn,
WrenchedTimelineColumn,
};

View File

@ -3,6 +3,7 @@ import React, { useEffect } from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { fetchCircleTimeline } from '@/actions/timelines';
import { CircleTimelineColumn } from '@/columns/timeline';
import DropdownMenu from '@/components/dropdown-menu';
import MissingIndicator from '@/components/missing-indicator';
import Button from '@/components/ui/button';
@ -13,6 +14,7 @@ import { circleTimelineRoute } from '@/features/ui/router';
import { useAppDispatch } from '@/hooks/use-app-dispatch';
import { useCircle, useDeleteCircle } from '@/queries/accounts/use-circles';
import { useModalsActions } from '@/stores/modals';
import { useSettings } from '@/stores/settings';
const messages = defineMessages({
deleteHeading: { id: 'confirmations.delete_circle.heading', defaultMessage: 'Delete circle' },
@ -25,6 +27,48 @@ const messages = defineMessages({
deleteCircle: { id: 'circles.delete', defaultMessage: 'Delete circle' },
});
interface ICircleTimeline {
circleId: string;
}
const CircleTimeline: React.FC<ICircleTimeline> = ({ circleId }) => {
const dispatch = useAppDispatch();
const { openModal } = useModalsActions();
const handleLoadMore = () => {
dispatch(fetchCircleTimeline(circleId, true));
};
const handleEditClick = () => {
openModal('CIRCLE_EDITOR', { circleId });
};
const emptyMessage = (
<div>
<FormattedMessage
id='empty_column.circle'
defaultMessage='There is nothing in this circle yet. When members of this circle create new posts, they will appear here.'
/>
<br />
<br />
<Button onClick={handleEditClick}>
<FormattedMessage id='circle.click_to_add' defaultMessage='Click here to add people' />
</Button>
</div>
);
return (
<Timeline
loadMoreClassName='sm:pb-4 black:sm:pb-0 black:sm:mx-4'
scrollKey='circle_timeline'
timelineId={`circle:${circleId}`}
onLoadMore={handleLoadMore}
emptyMessageText={emptyMessage}
emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')}
/>
);
};
const CircleTimelinePage: React.FC = () => {
const { circleId } = circleTimelineRoute.useParams();
@ -32,6 +76,7 @@ const CircleTimelinePage: React.FC = () => {
const dispatch = useAppDispatch();
const { openModal } = useModalsActions();
const navigate = useNavigate();
const { experimentalTimeline } = useSettings();
const { data: circle, isFetching } = useCircle(circleId);
const { mutate: deleteCircle } = useDeleteCircle();
@ -40,10 +85,6 @@ const CircleTimelinePage: React.FC = () => {
dispatch(fetchCircleTimeline(circleId));
}, [circleId]);
const handleLoadMore = () => {
dispatch(fetchCircleTimeline(circleId, true));
};
const handleEditClick = () => {
openModal('CIRCLE_EDITOR', { circleId });
};
@ -79,20 +120,6 @@ const CircleTimelinePage: React.FC = () => {
return <MissingIndicator />;
}
const emptyMessage = (
<div>
<FormattedMessage
id='empty_column.circle'
defaultMessage='There is nothing in this circle yet. When members of this circle create new posts, they will appear here.'
/>
<br />
<br />
<Button onClick={handleEditClick}>
<FormattedMessage id='circle.click_to_add' defaultMessage='Click here to add people' />
</Button>
</div>
);
const items = [
{
text: intl.formatMessage(messages.editCircle),
@ -116,14 +143,11 @@ const CircleTimelinePage: React.FC = () => {
/>
}
>
<Timeline
loadMoreClassName='sm:pb-4 black:sm:pb-0 black:sm:mx-4'
scrollKey='circle_timeline'
timelineId={`circle:${circleId}`}
onLoadMore={handleLoadMore}
emptyMessageText={emptyMessage}
emptyMessageIcon={require('@phosphor-icons/core/regular/chat-centered-text.svg')}
/>
{experimentalTimeline ? (
<CircleTimelineColumn circleId={circleId} />
) : (
<CircleTimeline circleId={circleId} />
)}
</Column>
);
};

View File

@ -5,6 +5,7 @@ import { useTimeline } from './use-timeline';
import type {
AntennaTimelineParams,
BubbleTimelineParams,
GetCircleStatusesParams,
GroupTimelineParams,
HashtagTimelineParams,
HomeTimelineParams,
@ -46,7 +47,10 @@ const useHashtagTimeline = (
return useTimeline(
`hashtag:${hashtag}`,
(paginationParams) =>
client.timelines.hashtagTimeline(hashtag, { ...params, ...paginationParams }),
client.timelines.hashtagTimeline(hashtag, {
...params,
...paginationParams,
}),
{ stream: 'hashtag', params: { tag: hashtag } },
);
};
@ -84,7 +88,10 @@ const useGroupTimeline = (
return useTimeline(
`group:${groupId}`,
(paginationParams) =>
client.timelines.groupTimeline(groupId, { ...params, ...paginationParams }),
client.timelines.groupTimeline(groupId, {
...params,
...paginationParams,
}),
{ stream: 'group', params: { group: groupId } },
);
};
@ -106,14 +113,31 @@ const useAntennaTimeline = (
const client = useClient();
return useTimeline(`antenna:${antennaId}`, (paginationParams) =>
client.timelines.antennaTimeline(antennaId, { ...params, ...paginationParams }),
client.timelines.antennaTimeline(antennaId, {
...params,
...paginationParams,
}),
);
};
const useCircleTimeline = (
circleId: string,
params?: Omit<GetCircleStatusesParams, keyof PaginationParams>,
) => {
const client = useClient();
return useTimeline(`circle:${circleId}`, (paginationParams) =>
client.circles.getCircleStatuses(circleId, {
...params,
...paginationParams,
}),
);
};
const useWrenchedTimeline = (params?: Omit<WrenchedTimelineParams, keyof PaginationParams>) => {
const client = useClient();
return useTimeline(`wrenched`, (paginationParams) =>
return useTimeline('wrenched', (paginationParams) =>
client.timelines.wrenchedTimeline({ ...params, ...paginationParams }),
);
};
@ -127,5 +151,6 @@ export {
useGroupTimeline,
useBubbleTimeline,
useAntennaTimeline,
useCircleTimeline,
useWrenchedTimeline,
};