Insert newly created post into account timelines (#39733)

This commit is contained in:
Echo 2026-07-07 10:51:39 +02:00 committed by GitHub
parent 3124003705
commit 70bca21056
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 13 deletions

View File

@ -14,6 +14,7 @@ import { useEmoji } from './emojis';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { openModal } from './modal';
import { updateTimeline } from './timelines';
import { insertStatusIntoAccountTimelines } from './timelines_typed';
/** @type {AbortController | undefined} */
let fetchComposeSuggestionsAccountsController;
@ -189,13 +190,13 @@ export function directCompose(account) {
export function submitCompose(successCallback) {
return function (dispatch, getState) {
const status = getState().getIn(['compose', 'text'], '');
const media = getState().getIn(['compose', 'media_attachments']);
const statusId = getState().getIn(['compose', 'id'], null);
const hasQuote = !!getState().getIn(['compose', 'quoted_status_id']);
const statusText = getState().getIn(['compose', 'text'], '');
const media = getState().getIn(['compose', 'media_attachments']);
const statusId = getState().getIn(['compose', 'id'], null);
const hasQuote = !!getState().getIn(['compose', 'quoted_status_id']);
const spoiler_text = getState().getIn(['compose', 'spoiler']) ? getState().getIn(['compose', 'spoiler_text'], '') : '';
const fulltext = `${spoiler_text ?? ''}${countableText(status ?? '')}`;
const fulltext = `${spoiler_text ?? ''}${countableText(statusText ?? '')}`;
const hasText = fulltext.trim().length > 0;
if (!(hasText || media.size !== 0 || (hasQuote && spoiler_text?.length))) {
@ -234,7 +235,7 @@ export function submitCompose(successCallback) {
url: statusId === null ? '/api/v1/statuses' : `/api/v1/statuses/${statusId}`,
method: statusId === null ? 'post' : 'put',
data: {
status,
status: statusText,
spoiler_text,
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
media_ids: media.map(item => item.get('id')),
@ -254,7 +255,7 @@ export function submitCompose(successCallback) {
browserHistory.goBack();
}
dispatch(insertIntoTagHistory(response.data.tags, status));
dispatch(insertIntoTagHistory(response.data.tags, statusText));
dispatch(submitComposeSuccess({ ...response.data }));
if (typeof successCallback === 'function') {
successCallback(response.data);
@ -284,6 +285,8 @@ export function submitCompose(successCallback) {
insertIfOnline(`account:${response.data.account.id}`);
}
dispatch(insertStatusIntoAccountTimelines({ ...response.data }))
dispatch(showAlert({
message: statusId === null ? messages.published : messages.saved,
action: messages.open,

View File

@ -3,6 +3,7 @@ import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
import type { ApiStatusJSON } from '../api_types/statuses';
import type { Status } from '../models/status';
import { createAppThunk } from '../store/typed_functions';
@ -10,6 +11,7 @@ import {
expandTimeline,
insertIntoTimeline,
TIMELINE_NON_STATUS_MARKERS,
updateTimeline,
} from './timelines';
export const expandTimelineByKey = createAppThunk(
@ -208,6 +210,34 @@ export const timelineDeleteStatus = createAction<{
timelineKey: string;
}>('timelines/deleteStatus');
export const insertStatusIntoAccountTimelines = createAppThunk(
(status: ApiStatusJSON, { dispatch, getState }) => {
const currentAccountId = getState().meta.get('me', null) as string | null;
if (!currentAccountId) {
return;
}
const tags = status.tags.map((tag) => tag.name);
const timelines = getState().timelines as ImmutableMap<string, unknown>;
const accountTimelines = timelines.filter((_, key) => {
if (!key.startsWith(`account:${currentAccountId}:`)) {
return false;
}
const parsed = parseTimelineKey(key);
if (parsed?.type !== 'account' || parsed.pinned) {
return false;
}
return !parsed.tagged || tags.includes(parsed.tagged);
});
accountTimelines.forEach((_, timelineKey) => {
dispatch(updateTimeline(timelineKey, status));
});
},
);
export const insertPinnedStatusIntoTimelines = createAppThunk(
(status: Status, { dispatch, getState }) => {
const currentAccountId = getState().meta.get('me', null) as string | null;

View File

@ -109,19 +109,19 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
}));
};
const updateTimeline = (state, timeline, status, usePendingItems) => {
const updateTimeline = (state, timeline, statusId, usePendingItems) => {
const top = state.getIn([timeline, 'top']);
if (usePendingItems || !state.getIn([timeline, 'pendingItems']).isEmpty()) {
if (state.getIn([timeline, 'pendingItems'], ImmutableList()).includes(status.get('id')) || state.getIn([timeline, 'items'], ImmutableList()).includes(status.get('id'))) {
if (state.getIn([timeline, 'pendingItems'], ImmutableList()).includes(statusId) || state.getIn([timeline, 'items'], ImmutableList()).includes(statusId)) {
return state;
}
return state.update(timeline, initialTimeline, map => map.update('pendingItems', list => list.unshift(status.get('id'))).update('unread', unread => unread + 1));
return state.update(timeline, initialTimeline, map => map.update('pendingItems', list => list.unshift(statusId)).update('unread', unread => unread + 1));
}
const ids = state.getIn([timeline, 'items'], ImmutableList());
const includesId = ids.includes(status.get('id'));
const includesId = ids.includes(statusId);
const unread = state.getIn([timeline, 'unread'], 0);
if (includesId) {
@ -133,7 +133,7 @@ const updateTimeline = (state, timeline, status, usePendingItems) => {
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
if (!top) mMap.set('unread', unread + 1);
if (top && ids.size > 40) newIds = newIds.take(20);
mMap.set('items', newIds.unshift(status.get('id')));
mMap.set('items', newIds.unshift(statusId));
}));
};
@ -213,7 +213,7 @@ export default function timelines(state = initialState, action) {
case TIMELINE_EXPAND_SUCCESS:
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent, action.usePendingItems);
case TIMELINE_UPDATE:
return updateTimeline(state, action.timeline, fromJS(action.status), action.usePendingItems);
return updateTimeline(state, action.timeline, action.status.id, action.usePendingItems);
case TIMELINE_CLEAR:
return clearTimeline(state, action.timeline);
case TIMELINE_SCROLL_TOP: