Make pinning and unpinning directly modify state (#37831)
This commit is contained in:
3 files changed
+105
-59
No files matched your search
@@ -6,7 +6,10 @@ import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||
import { unreblog, reblog } from './interactions_typed';
|
||||
import { openModal } from './modal';
|
||||
import { timelineExpandPinnedFromStatus } from './timelines_typed';
|
||||
import {
|
||||
insertPinnedStatusIntoTimelines,
|
||||
removePinnedStatusFromTimelines,
|
||||
} from './timelines_typed';
|
||||
|
||||
export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST';
|
||||
export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
|
||||
@@ -369,7 +372,7 @@ export function pin(status) {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(pinSuccess(status));
|
||||
dispatch(timelineExpandPinnedFromStatus(status));
|
||||
dispatch(insertPinnedStatusIntoTimelines(status));
|
||||
}).catch(error => {
|
||||
dispatch(pinFail(status, error));
|
||||
});
|
||||
@@ -408,7 +411,7 @@ export function unpin (status) {
|
||||
api().post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unpinSuccess(status));
|
||||
dispatch(timelineExpandPinnedFromStatus(status));
|
||||
dispatch(removePinnedStatusFromTimelines(status));
|
||||
}).catch(error => {
|
||||
dispatch(unpinFail(status, error));
|
||||
});
|
||||
|
||||
@@ -7,8 +7,8 @@ import type { Status } from '../models/status';
|
||||
import { createAppThunk } from '../store/typed_functions';
|
||||
|
||||
import {
|
||||
expandAccountFeaturedTimeline,
|
||||
expandTimeline,
|
||||
insertIntoTimeline,
|
||||
TIMELINE_NON_STATUS_MARKERS,
|
||||
} from './timelines';
|
||||
|
||||
@@ -173,9 +173,13 @@ export function parseTimelineKey(key: string): TimelineParams | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isTimelineKeyPinned(key: string) {
|
||||
export function isTimelineKeyPinned(key: string, accountId?: string) {
|
||||
const parsedKey = parseTimelineKey(key);
|
||||
return parsedKey?.type === 'account' && parsedKey.pinned;
|
||||
const isPinned = parsedKey?.type === 'account' && parsedKey.pinned;
|
||||
if (!accountId || !isPinned) {
|
||||
return isPinned;
|
||||
}
|
||||
return parsedKey.userId === accountId;
|
||||
}
|
||||
|
||||
export function isNonStatusId(value: unknown) {
|
||||
@@ -199,52 +203,71 @@ export const timelineDelete = createAction<{
|
||||
reblogOf: string | null;
|
||||
}>('timelines/delete');
|
||||
|
||||
export const timelineExpandPinnedFromStatus = createAppThunk(
|
||||
export const timelineDeleteStatus = createAction<{
|
||||
statusId: string;
|
||||
timelineKey: string;
|
||||
}>('timelines/deleteStatus');
|
||||
|
||||
export const insertPinnedStatusIntoTimelines = createAppThunk(
|
||||
(status: Status, { dispatch, getState }) => {
|
||||
const accountId = status.getIn(['account', 'id']) as string;
|
||||
if (!accountId) {
|
||||
const currentAccountId = getState().meta.get('me', null) as string | null;
|
||||
if (!currentAccountId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that any of the relevant timelines are actually expanded before dispatching, to avoid unnecessary API calls.
|
||||
const tags =
|
||||
(
|
||||
status.get('tags') as
|
||||
| ImmutableList<ImmutableMap<'name', string>> // We only care about the tag name.
|
||||
| undefined
|
||||
)
|
||||
?.map((tag) => tag.get('name') as string)
|
||||
.toArray() ?? [];
|
||||
|
||||
const timelines = getState().timelines as ImmutableMap<string, unknown>;
|
||||
if (!timelines.some((_, key) => key.startsWith(`account:${accountId}:`))) {
|
||||
return;
|
||||
}
|
||||
|
||||
void dispatch(
|
||||
expandTimelineByParams({
|
||||
type: 'account',
|
||||
userId: accountId,
|
||||
pinned: true,
|
||||
}),
|
||||
);
|
||||
void dispatch(expandAccountFeaturedTimeline(accountId));
|
||||
|
||||
// Iterate over tags and clear those too.
|
||||
const tags = status.get('tags') as
|
||||
| ImmutableList<ImmutableMap<'name', string>> // We only care about the tag name.
|
||||
| undefined;
|
||||
if (!tags) {
|
||||
return;
|
||||
}
|
||||
tags.forEach((tag) => {
|
||||
const tagName = tag.get('name');
|
||||
if (!tagName) {
|
||||
return;
|
||||
const accountTimelines = timelines.filter((_, key) => {
|
||||
if (!key.startsWith(`account:${currentAccountId}:`)) {
|
||||
return false;
|
||||
}
|
||||
const parsed = parseTimelineKey(key);
|
||||
const isPinned = parsed?.type === 'account' && parsed.pinned;
|
||||
if (!isPinned) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void dispatch(
|
||||
expandTimelineByParams({
|
||||
type: 'account',
|
||||
userId: accountId,
|
||||
pinned: true,
|
||||
tagged: tagName,
|
||||
}),
|
||||
);
|
||||
void dispatch(
|
||||
expandAccountFeaturedTimeline(accountId, { tagged: tagName }),
|
||||
);
|
||||
return !parsed.tagged || tags.includes(parsed.tagged);
|
||||
});
|
||||
|
||||
accountTimelines.forEach((_, key) => {
|
||||
dispatch(insertIntoTimeline(key, status.get('id') as string, 0));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const removePinnedStatusFromTimelines = createAppThunk(
|
||||
(status: Status, { dispatch, getState }) => {
|
||||
const currentAccountId = getState().meta.get('me', null) as string | null;
|
||||
if (!currentAccountId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const statusId = status.get('id') as string;
|
||||
const timelines = getState().timelines as ImmutableMap<
|
||||
string,
|
||||
ImmutableMap<'items' | 'pendingItems', ImmutableList<string>>
|
||||
>;
|
||||
|
||||
timelines.forEach((timeline, key) => {
|
||||
if (!isTimelineKeyPinned(key, currentAccountId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
timeline.get('items')?.includes(statusId) ||
|
||||
timeline.get('pendingItems')?.includes(statusId)
|
||||
) {
|
||||
dispatch(timelineDeleteStatus({ statusId, timelineKey: key }));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user