diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js index 4028d3b10a..73f62d43ea 100644 --- a/app/javascript/flavours/glitch/actions/timelines.js +++ b/app/javascript/flavours/glitch/actions/timelines.js @@ -1,5 +1,6 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { reinsertAnnualReport, TIMELINE_WRAPSTODON } from '@/flavours/glitch/reducers/slices/annual_report'; import api, { getLinks } from 'flavours/glitch/api'; import { compareId } from 'flavours/glitch/compare_id'; import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state'; @@ -7,7 +8,7 @@ import { toServerSideType } from 'flavours/glitch/utils/filters'; import { importFetchedStatus, importFetchedStatuses } from './importer'; import { submitMarkers } from './markers'; -import {timelineDelete} from './timelines_typed'; +import { timelineDelete } from './timelines_typed'; export { disconnectTimeline } from './timelines_typed'; @@ -25,9 +26,16 @@ export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'; export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL'; 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_GAP = null; +export const TIMELINE_NON_STATUS_MARKERS = [ + TIMELINE_GAP, + TIMELINE_SUGGESTIONS, + TIMELINE_WRAPSTODON, +]; + export const loadPending = timeline => ({ type: TIMELINE_LOAD_PENDING, timeline, @@ -135,6 +143,7 @@ export function expandTimeline(timelineId, path, params = {}) { if (timelineId === 'home') { dispatch(submitMarkers()); + dispatch(reinsertAnnualReport()) } } catch(error) { dispatch(expandTimelineFail(timelineId, error, isLoadingMore)); diff --git a/app/javascript/flavours/glitch/actions/timelines_typed.ts b/app/javascript/flavours/glitch/actions/timelines_typed.ts index 485b94ed52..28cbf4058e 100644 --- a/app/javascript/flavours/glitch/actions/timelines_typed.ts +++ b/app/javascript/flavours/glitch/actions/timelines_typed.ts @@ -2,6 +2,12 @@ import { createAction } from '@reduxjs/toolkit'; import { usePendingItems as preferPendingItems } from 'flavours/glitch/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( 'timeline/disconnect', ({ timeline }: { timeline: string }) => ({ diff --git a/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js index 2ff85c0b25..f485119d92 100644 --- a/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js +++ b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js @@ -4,10 +4,10 @@ import { connect } from 'react-redux'; import { debounce } from 'lodash'; -import { scrollTopTimeline, loadPending, TIMELINE_SUGGESTIONS } from '@/flavours/glitch/actions/timelines'; +import { scrollTopTimeline, loadPending } from '@/flavours/glitch/actions/timelines'; +import { isNonStatusId } from '@/flavours/glitch/actions/timelines_typed'; import StatusList from '@/flavours/glitch/components/status_list'; import { me } from '@/flavours/glitch/initial_state'; -import { TIMELINE_WRAPSTODON } from '@/flavours/glitch/reducers/slices/annual_report'; const getRegex = createSelector([ (state, { regex }) => regex, @@ -29,7 +29,7 @@ const makeGetStatusIds = (pending = false) => createSelector([ getRegex, ], (columnSettings, statusIds, statuses, regex) => { 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); diff --git a/app/javascript/flavours/glitch/reducers/slices/annual_report.ts b/app/javascript/flavours/glitch/reducers/slices/annual_report.ts index 2a8a708e49..68e50ec7ba 100644 --- a/app/javascript/flavours/glitch/reducers/slices/annual_report.ts +++ b/app/javascript/flavours/glitch/reducers/slices/annual_report.ts @@ -6,6 +6,7 @@ import { importFetchedStatuses, } from '@/flavours/glitch/actions/importer'; import { insertIntoTimeline } from '@/flavours/glitch/actions/timelines'; +import { timelineDelete } from '@/flavours/glitch/actions/timelines_typed'; import type { ApiAnnualReportState } from '@/flavours/glitch/api/annual_report'; import { 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( `${annualReportSlice.name}/fetchReportState`, async (_arg: unknown, { getState }) => { diff --git a/app/javascript/flavours/glitch/reducers/timelines.js b/app/javascript/flavours/glitch/reducers/timelines.js index f4944472bb..3a7da91651 100644 --- a/app/javascript/flavours/glitch/reducers/timelines.js +++ b/app/javascript/flavours/glitch/reducers/timelines.js @@ -1,6 +1,6 @@ import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; -import { timelineDelete } from 'flavours/glitch/actions/timelines_typed'; +import { timelineDelete, isNonStatusId } from 'flavours/glitch/actions/timelines_typed'; import { blockAccountSuccess, @@ -19,7 +19,6 @@ import { TIMELINE_MARK_AS_PARTIAL, TIMELINE_INSERT, TIMELINE_GAP, - TIMELINE_SUGGESTIONS, disconnectTimeline, } from '../actions/timelines'; import { compareId } from '../compare_id'; @@ -36,7 +35,6 @@ const initialTimeline = ImmutableMap({ items: ImmutableList(), }); -const isPlaceholder = value => value === TIMELINE_GAP || value === TIMELINE_SUGGESTIONS; const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent, usePendingItems) => { // 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 // newer than the oldest fetched one, as it's most likely that it delimits the gap. // 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 // 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 // anyway). // 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 => { // 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 // 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); // Make sure we aren't inserting duplicates