mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-15 08:48:53 +00:00
Fix issue where Wrapstodon was pushed to the bottom of the feed (#37190)
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
|
import { reinsertAnnualReport, TIMELINE_WRAPSTODON } from '@/mastodon/reducers/slices/annual_report';
|
||||||
import api, { getLinks } from 'mastodon/api';
|
import api, { getLinks } from 'mastodon/api';
|
||||||
import { compareId } from 'mastodon/compare_id';
|
import { compareId } from 'mastodon/compare_id';
|
||||||
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
|
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
|
||||||
|
|
||||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
||||||
import { submitMarkers } from './markers';
|
import { submitMarkers } from './markers';
|
||||||
import {timelineDelete} from './timelines_typed';
|
import { timelineDelete } from './timelines_typed';
|
||||||
|
|
||||||
export { disconnectTimeline } from './timelines_typed';
|
export { disconnectTimeline } from './timelines_typed';
|
||||||
|
|
||||||
@@ -24,9 +25,16 @@ export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
|
|||||||
export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL';
|
export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL';
|
||||||
export const TIMELINE_INSERT = 'TIMELINE_INSERT';
|
export const TIMELINE_INSERT = 'TIMELINE_INSERT';
|
||||||
|
|
||||||
|
// When adding new special markers here, make sure to update TIMELINE_NON_STATUS_MARKERS in actions/timelines_typed.js
|
||||||
export const TIMELINE_SUGGESTIONS = 'inline-follow-suggestions';
|
export const TIMELINE_SUGGESTIONS = 'inline-follow-suggestions';
|
||||||
export const TIMELINE_GAP = null;
|
export const TIMELINE_GAP = null;
|
||||||
|
|
||||||
|
export const TIMELINE_NON_STATUS_MARKERS = [
|
||||||
|
TIMELINE_GAP,
|
||||||
|
TIMELINE_SUGGESTIONS,
|
||||||
|
TIMELINE_WRAPSTODON,
|
||||||
|
];
|
||||||
|
|
||||||
export const loadPending = timeline => ({
|
export const loadPending = timeline => ({
|
||||||
type: TIMELINE_LOAD_PENDING,
|
type: TIMELINE_LOAD_PENDING,
|
||||||
timeline,
|
timeline,
|
||||||
@@ -124,6 +132,7 @@ export function expandTimeline(timelineId, path, params = {}) {
|
|||||||
|
|
||||||
if (timelineId === 'home') {
|
if (timelineId === 'home') {
|
||||||
dispatch(submitMarkers());
|
dispatch(submitMarkers());
|
||||||
|
dispatch(reinsertAnnualReport())
|
||||||
}
|
}
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
|
dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ import { createAction } from '@reduxjs/toolkit';
|
|||||||
|
|
||||||
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
|
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
|
||||||
|
|
||||||
|
import { TIMELINE_NON_STATUS_MARKERS } from './timelines';
|
||||||
|
|
||||||
|
export function isNonStatusId(value: unknown) {
|
||||||
|
return TIMELINE_NON_STATUS_MARKERS.includes(value as string | null);
|
||||||
|
}
|
||||||
|
|
||||||
export const disconnectTimeline = createAction(
|
export const disconnectTimeline = createAction(
|
||||||
'timeline/disconnect',
|
'timeline/disconnect',
|
||||||
({ timeline }: { timeline: string }) => ({
|
({ timeline }: { timeline: string }) => ({
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
import { scrollTopTimeline, loadPending, TIMELINE_SUGGESTIONS } from '@/mastodon/actions/timelines';
|
import { scrollTopTimeline, loadPending } from '@/mastodon/actions/timelines';
|
||||||
|
import { isNonStatusId } from '@/mastodon/actions/timelines_typed';
|
||||||
import StatusList from '@/mastodon/components/status_list';
|
import StatusList from '@/mastodon/components/status_list';
|
||||||
import { me } from '@/mastodon/initial_state';
|
import { me } from '@/mastodon/initial_state';
|
||||||
import { TIMELINE_WRAPSTODON } from '@/mastodon/reducers/slices/annual_report';
|
|
||||||
|
|
||||||
const makeGetStatusIds = (pending = false) => createSelector([
|
const makeGetStatusIds = (pending = false) => createSelector([
|
||||||
(state, { type }) => state.getIn(['settings', type], ImmutableMap()),
|
(state, { type }) => state.getIn(['settings', type], ImmutableMap()),
|
||||||
@@ -15,7 +15,7 @@ const makeGetStatusIds = (pending = false) => createSelector([
|
|||||||
(state) => state.get('statuses'),
|
(state) => state.get('statuses'),
|
||||||
], (columnSettings, statusIds, statuses) => {
|
], (columnSettings, statusIds, statuses) => {
|
||||||
return statusIds.filter(id => {
|
return statusIds.filter(id => {
|
||||||
if (id === null || id === TIMELINE_SUGGESTIONS || id === TIMELINE_WRAPSTODON) return true;
|
if (isNonStatusId(id)) return true;
|
||||||
|
|
||||||
const statusForId = statuses.get(id);
|
const statusForId = statuses.get(id);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
importFetchedStatuses,
|
importFetchedStatuses,
|
||||||
} from '@/mastodon/actions/importer';
|
} from '@/mastodon/actions/importer';
|
||||||
import { insertIntoTimeline } from '@/mastodon/actions/timelines';
|
import { insertIntoTimeline } from '@/mastodon/actions/timelines';
|
||||||
|
import { timelineDelete } from '@/mastodon/actions/timelines_typed';
|
||||||
import type { ApiAnnualReportState } from '@/mastodon/api/annual_report';
|
import type { ApiAnnualReportState } from '@/mastodon/api/annual_report';
|
||||||
import {
|
import {
|
||||||
apiGetAnnualReport,
|
apiGetAnnualReport,
|
||||||
@@ -78,6 +79,25 @@ export const checkAnnualReport = createAppThunk(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const reinsertAnnualReport = createAppThunk(
|
||||||
|
`${annualReportSlice.name}/reinsertAnnualReport`,
|
||||||
|
(_arg: unknown, { dispatch, getState }) => {
|
||||||
|
dispatch(
|
||||||
|
timelineDelete({
|
||||||
|
statusId: TIMELINE_WRAPSTODON,
|
||||||
|
accountId: '',
|
||||||
|
references: [],
|
||||||
|
reblogOf: null,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const { state } = getState().annualReport;
|
||||||
|
if (!state || state === 'ineligible') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(insertIntoTimeline('home', TIMELINE_WRAPSTODON, 1));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const fetchReportState = createDataLoadingThunk(
|
const fetchReportState = createDataLoadingThunk(
|
||||||
`${annualReportSlice.name}/fetchReportState`,
|
`${annualReportSlice.name}/fetchReportState`,
|
||||||
async (_arg: unknown, { getState }) => {
|
async (_arg: unknown, { getState }) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
||||||
|
|
||||||
import { timelineDelete } from 'mastodon/actions/timelines_typed';
|
import { timelineDelete, isNonStatusId } from 'mastodon/actions/timelines_typed';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
blockAccountSuccess,
|
blockAccountSuccess,
|
||||||
@@ -19,7 +19,6 @@ import {
|
|||||||
TIMELINE_MARK_AS_PARTIAL,
|
TIMELINE_MARK_AS_PARTIAL,
|
||||||
TIMELINE_INSERT,
|
TIMELINE_INSERT,
|
||||||
TIMELINE_GAP,
|
TIMELINE_GAP,
|
||||||
TIMELINE_SUGGESTIONS,
|
|
||||||
disconnectTimeline,
|
disconnectTimeline,
|
||||||
} from '../actions/timelines';
|
} from '../actions/timelines';
|
||||||
import { compareId } from '../compare_id';
|
import { compareId } from '../compare_id';
|
||||||
@@ -36,7 +35,6 @@ const initialTimeline = ImmutableMap({
|
|||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const isPlaceholder = value => value === TIMELINE_GAP || value === TIMELINE_SUGGESTIONS;
|
|
||||||
|
|
||||||
const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent, usePendingItems) => {
|
const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent, usePendingItems) => {
|
||||||
// This method is pretty tricky because:
|
// This method is pretty tricky because:
|
||||||
@@ -69,20 +67,20 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
|
|||||||
// First, find the furthest (if properly sorted, oldest) item in the timeline that is
|
// First, find the furthest (if properly sorted, oldest) item in the timeline that is
|
||||||
// newer than the oldest fetched one, as it's most likely that it delimits the gap.
|
// newer than the oldest fetched one, as it's most likely that it delimits the gap.
|
||||||
// Start the gap *after* that item.
|
// Start the gap *after* that item.
|
||||||
const lastIndex = oldIds.findLastIndex(id => !isPlaceholder(id) && compareId(id, newIds.last()) >= 0) + 1;
|
const lastIndex = oldIds.findLastIndex(id => !isNonStatusId(id) && compareId(id, newIds.last()) >= 0) + 1;
|
||||||
|
|
||||||
// Then, try to find the furthest (if properly sorted, oldest) item in the timeline that
|
// Then, try to find the furthest (if properly sorted, oldest) item in the timeline that
|
||||||
// is newer than the most recent fetched one, as it delimits a section comprised of only
|
// is newer than the most recent fetched one, as it delimits a section comprised of only
|
||||||
// items older or within `newIds` (or that were deleted from the server, so should be removed
|
// items older or within `newIds` (or that were deleted from the server, so should be removed
|
||||||
// anyway).
|
// anyway).
|
||||||
// Stop the gap *after* that item.
|
// Stop the gap *after* that item.
|
||||||
const firstIndex = oldIds.take(lastIndex).findLastIndex(id => !isPlaceholder(id) && compareId(id, newIds.first()) > 0) + 1;
|
const firstIndex = oldIds.take(lastIndex).findLastIndex(id => !isNonStatusId(id) && compareId(id, newIds.first()) > 0) + 1;
|
||||||
|
|
||||||
let insertedIds = ImmutableOrderedSet(newIds).withMutations(insertedIds => {
|
let insertedIds = ImmutableOrderedSet(newIds).withMutations(insertedIds => {
|
||||||
// It is possible, though unlikely, that the slice we are replacing contains items older
|
// It is possible, though unlikely, that the slice we are replacing contains items older
|
||||||
// than the elements we got from the API. Get them and add them back at the back of the
|
// than the elements we got from the API. Get them and add them back at the back of the
|
||||||
// slice.
|
// slice.
|
||||||
const olderIds = oldIds.slice(firstIndex, lastIndex).filter(id => !isPlaceholder(id) && compareId(id, newIds.last()) < 0);
|
const olderIds = oldIds.slice(firstIndex, lastIndex).filter(id => !isNonStatusId(id) && compareId(id, newIds.last()) < 0);
|
||||||
insertedIds.union(olderIds);
|
insertedIds.union(olderIds);
|
||||||
|
|
||||||
// Make sure we aren't inserting duplicates
|
// Make sure we aren't inserting duplicates
|
||||||
|
|||||||
Reference in New Issue
Block a user