mirror of
https://github.com/glitch-soc/mastodon.git
synced 2026-03-29 03:00:33 +02:00
[Glitch] Fix: Changes to pins update immediately
Port b4fb25643a to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||
import { unreblog, reblog } from './interactions_typed';
|
||||
import { openModal } from './modal';
|
||||
import { timelineExpandPinnedFromStatus } from './timelines_typed';
|
||||
|
||||
export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST';
|
||||
export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
|
||||
@@ -368,6 +369,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));
|
||||
}).catch(error => {
|
||||
dispatch(pinFail(status, error));
|
||||
});
|
||||
@@ -406,6 +408,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));
|
||||
}).catch(error => {
|
||||
dispatch(unpinFail(status, error));
|
||||
});
|
||||
|
||||
@@ -57,4 +57,29 @@ describe('parseTimelineKey', () => {
|
||||
tagged: 'nature',
|
||||
});
|
||||
});
|
||||
|
||||
test('parses legacy account timeline key with pinned correctly', () => {
|
||||
const params = parseTimelineKey('account:789:pinned:nature');
|
||||
expect(params).toEqual({
|
||||
type: 'account',
|
||||
userId: '789',
|
||||
replies: false,
|
||||
boosts: false,
|
||||
media: false,
|
||||
pinned: true,
|
||||
tagged: 'nature',
|
||||
});
|
||||
});
|
||||
|
||||
test('parses legacy account timeline key with media correctly', () => {
|
||||
const params = parseTimelineKey('account:789:media');
|
||||
expect(params).toEqual({
|
||||
type: 'account',
|
||||
userId: '789',
|
||||
replies: false,
|
||||
boosts: false,
|
||||
media: true,
|
||||
pinned: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||
|
||||
import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state';
|
||||
|
||||
import type { Status } from '../models/status';
|
||||
import { createAppThunk } from '../store/typed_functions';
|
||||
|
||||
import { expandTimeline, TIMELINE_NON_STATUS_MARKERS } from './timelines';
|
||||
import {
|
||||
expandAccountFeaturedTimeline,
|
||||
expandTimeline,
|
||||
TIMELINE_NON_STATUS_MARKERS,
|
||||
} from './timelines';
|
||||
|
||||
export const expandTimelineByKey = createAppThunk(
|
||||
(args: { key: string; maxId?: number }, { dispatch }) => {
|
||||
@@ -119,8 +125,25 @@ export function parseTimelineKey(key: string): TimelineParams | null {
|
||||
type: 'account',
|
||||
userId,
|
||||
tagged: segments[3],
|
||||
pinned: false,
|
||||
boosts: false,
|
||||
replies: false,
|
||||
media: false,
|
||||
};
|
||||
|
||||
// Handle legacy keys.
|
||||
const flagsSegment = segments[2];
|
||||
if (!flagsSegment || !/^[01]{4}$/.test(flagsSegment)) {
|
||||
if (flagsSegment === 'pinned') {
|
||||
parsed.pinned = true;
|
||||
} else if (flagsSegment === 'with_replies') {
|
||||
parsed.replies = true;
|
||||
} else if (flagsSegment === 'media') {
|
||||
parsed.media = true;
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
const view = segments[2]?.split('') ?? [];
|
||||
for (let i = 0; i < view.length; i++) {
|
||||
const flagName = ACCOUNT_FILTERS[i];
|
||||
@@ -150,6 +173,11 @@ export function parseTimelineKey(key: string): TimelineParams | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isTimelineKeyPinned(key: string) {
|
||||
const parsedKey = parseTimelineKey(key);
|
||||
return parsedKey?.type === 'account' && parsedKey.pinned;
|
||||
}
|
||||
|
||||
export function isNonStatusId(value: unknown) {
|
||||
return TIMELINE_NON_STATUS_MARKERS.includes(value as string | null);
|
||||
}
|
||||
@@ -170,3 +198,53 @@ export const timelineDelete = createAction<{
|
||||
references: string[];
|
||||
reblogOf: string | null;
|
||||
}>('timelines/delete');
|
||||
|
||||
export const timelineExpandPinnedFromStatus = createAppThunk(
|
||||
(status: Status, { dispatch, getState }) => {
|
||||
const accountId = status.getIn(['account', 'id']) as string;
|
||||
if (!accountId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that any of the relevant timelines are actually expanded before dispatching, to avoid unnecessary API calls.
|
||||
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;
|
||||
}
|
||||
|
||||
void dispatch(
|
||||
expandTimelineByParams({
|
||||
type: 'account',
|
||||
userId: accountId,
|
||||
pinned: true,
|
||||
tagged: tagName,
|
||||
}),
|
||||
);
|
||||
void dispatch(
|
||||
expandAccountFeaturedTimeline(accountId, { tagged: tagName }),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
||||
|
||||
import { timelineDelete, isNonStatusId } from 'flavours/glitch/actions/timelines_typed';
|
||||
|
||||
import {
|
||||
blockAccountSuccess,
|
||||
@@ -21,6 +20,7 @@ import {
|
||||
TIMELINE_GAP,
|
||||
disconnectTimeline,
|
||||
} from '../actions/timelines';
|
||||
import { timelineDelete, isTimelineKeyPinned, isNonStatusId } from '../actions/timelines_typed';
|
||||
import { compareId } from '../compare_id';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
@@ -50,7 +50,7 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
|
||||
|
||||
if (!next && !isLoadingRecent) mMap.set('hasMore', false);
|
||||
|
||||
if (timeline.endsWith(':pinned')) {
|
||||
if (isTimelineKeyPinned(timeline)) {
|
||||
mMap.set('items', statuses.map(status => status.get('id')));
|
||||
} else if (!statuses.isEmpty()) {
|
||||
usePendingItems = isLoadingRecent && (usePendingItems || !mMap.get('pendingItems').isEmpty());
|
||||
|
||||
Reference in New Issue
Block a user