pl-fe: types

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-11-26 14:08:26 +01:00
parent 32bd753064
commit 8529bf64ad
8 changed files with 64 additions and 63 deletions

View file

@ -179,7 +179,7 @@ const joinEventSuccess = (statusId: string) => ({
statusId, statusId,
}); });
const joinEventFail = (error: unknown, statusId: string, previousState: string | null) => ({ const joinEventFail = (error: unknown, statusId: string, previousState: Exclude<Status['event'], null>['join_state'] | null) => ({
type: EVENT_JOIN_FAIL, type: EVENT_JOIN_FAIL,
error, error,
statusId, statusId,
@ -214,7 +214,7 @@ const leaveEventSuccess = (statusId: string) => ({
statusId, statusId,
}); });
const leaveEventFail = (error: unknown, statusId: string, previousState: string | null) => ({ const leaveEventFail = (error: unknown, statusId: string, previousState: Exclude<Status['event'], null>['join_state'] | null) => ({
type: EVENT_LEAVE_FAIL, type: EVENT_LEAVE_FAIL,
statusId, statusId,
error, error,

View file

@ -99,20 +99,20 @@ const editStatus = (statusId: string) => (dispatch: AppDispatch, getState: () =>
const status = state.statuses[statusId]!; const status = state.statuses[statusId]!;
const poll = status.poll_id ? state.polls[status.poll_id] : undefined; const poll = status.poll_id ? state.polls[status.poll_id] : undefined;
dispatch({ type: STATUS_FETCH_SOURCE_REQUEST }); dispatch<StatusesAction>({ type: STATUS_FETCH_SOURCE_REQUEST });
return getClient(state).statuses.getStatusSource(statusId).then(response => { return getClient(state).statuses.getStatusSource(statusId).then(response => {
dispatch({ type: STATUS_FETCH_SOURCE_SUCCESS }); dispatch<StatusesAction>({ type: STATUS_FETCH_SOURCE_SUCCESS });
dispatch(setComposeToStatus(status, poll, response.text, response.spoiler_text, response.content_type, false)); dispatch(setComposeToStatus(status, poll, response.text, response.spoiler_text, response.content_type, false));
useModalsStore.getState().openModal('COMPOSE'); useModalsStore.getState().openModal('COMPOSE');
}).catch(error => { }).catch(error => {
dispatch({ type: STATUS_FETCH_SOURCE_FAIL, error }); dispatch<StatusesAction>({ type: STATUS_FETCH_SOURCE_FAIL, error });
}); });
}; };
const fetchStatus = (statusId: string, intl?: IntlShape) => const fetchStatus = (statusId: string, intl?: IntlShape) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: STATUS_FETCH_REQUEST, statusId }); dispatch<StatusesAction>({ type: STATUS_FETCH_REQUEST, statusId });
const params = intl && useSettingsStore.getState().settings.autoTranslate ? { const params = intl && useSettingsStore.getState().settings.autoTranslate ? {
language: intl.locale, language: intl.locale,
@ -120,10 +120,10 @@ const fetchStatus = (statusId: string, intl?: IntlShape) =>
return getClient(getState()).statuses.getStatus(statusId, params).then(status => { return getClient(getState()).statuses.getStatus(statusId, params).then(status => {
dispatch(importEntities({ statuses: [status] })); dispatch(importEntities({ statuses: [status] }));
dispatch({ type: STATUS_FETCH_SUCCESS, status }); dispatch<StatusesAction>({ type: STATUS_FETCH_SUCCESS, status });
return status; return status;
}).catch(error => { }).catch(error => {
dispatch({ type: STATUS_FETCH_FAIL, statusId, error, skipAlert: true }); dispatch<StatusesAction>({ type: STATUS_FETCH_FAIL, statusId, error, skipAlert: true });
}); });
}; };
@ -136,10 +136,10 @@ const deleteStatus = (statusId: string, withRedraft = false) =>
const status = state.statuses[statusId]!; const status = state.statuses[statusId]!;
const poll = status.poll_id ? state.polls[status.poll_id] : undefined; const poll = status.poll_id ? state.polls[status.poll_id] : undefined;
dispatch({ type: STATUS_DELETE_REQUEST, params: status }); dispatch<StatusesAction>({ type: STATUS_DELETE_REQUEST, params: status });
return getClient(state).statuses.deleteStatus(statusId).then(response => { return getClient(state).statuses.deleteStatus(statusId).then(response => {
dispatch({ type: STATUS_DELETE_SUCCESS, statusId }); dispatch<StatusesAction>({ type: STATUS_DELETE_SUCCESS, statusId });
dispatch(deleteFromTimelines(statusId)); dispatch(deleteFromTimelines(statusId));
if (withRedraft) { if (withRedraft) {
@ -148,7 +148,7 @@ const deleteStatus = (statusId: string, withRedraft = false) =>
} }
}) })
.catch(error => { .catch(error => {
dispatch({ type: STATUS_DELETE_FAIL, params: status, error }); dispatch<StatusesAction>({ type: STATUS_DELETE_FAIL, params: status, error });
}); });
}; };
@ -157,7 +157,7 @@ const updateStatus = (status: BaseStatus) => (dispatch: AppDispatch) =>
const fetchContext = (statusId: string, intl?: IntlShape) => const fetchContext = (statusId: string, intl?: IntlShape) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: CONTEXT_FETCH_REQUEST, statusId }); dispatch<StatusesAction>({ type: CONTEXT_FETCH_REQUEST, statusId });
const params = intl && useSettingsStore.getState().settings.autoTranslate ? { const params = intl && useSettingsStore.getState().settings.autoTranslate ? {
language: intl.locale, language: intl.locale,
@ -167,14 +167,14 @@ const fetchContext = (statusId: string, intl?: IntlShape) =>
const { ancestors, descendants } = context; const { ancestors, descendants } = context;
const statuses = ancestors.concat(descendants); const statuses = ancestors.concat(descendants);
dispatch(importEntities({ statuses })); dispatch(importEntities({ statuses }));
dispatch({ type: CONTEXT_FETCH_SUCCESS, statusId, ancestors, descendants }); dispatch<StatusesAction>({ type: CONTEXT_FETCH_SUCCESS, statusId, ancestors, descendants });
return context; return context;
}).catch(error => { }).catch(error => {
if (error.response?.status === 404) { if (error.response?.status === 404) {
dispatch(deleteFromTimelines(statusId)); dispatch(deleteFromTimelines(statusId));
} }
dispatch({ type: CONTEXT_FETCH_FAIL, statusId, error, skipAlert: true }); dispatch<StatusesAction>({ type: CONTEXT_FETCH_FAIL, statusId, error, skipAlert: true });
}); });
}; };
@ -319,13 +319,13 @@ const translateStatus = (statusId: string, targetLanguage: string, lazy?: boolea
handleTranslateMany(); handleTranslateMany();
} else { } else {
return client.statuses.translateStatus(statusId, targetLanguage).then(response => { return client.statuses.translateStatus(statusId, targetLanguage).then(response => {
dispatch({ dispatch<StatusesAction>({
type: STATUS_TRANSLATE_SUCCESS, type: STATUS_TRANSLATE_SUCCESS,
statusId, statusId,
translation: response, translation: response,
}); });
}).catch(error => { }).catch(error => {
dispatch({ dispatch<StatusesAction>({
type: STATUS_TRANSLATE_FAIL, type: STATUS_TRANSLATE_FAIL,
statusId, statusId,
error, error,
@ -354,11 +354,18 @@ type StatusesAction =
| { type: typeof STATUS_CREATE_REQUEST; params: CreateStatusParams; idempotencyKey: string; editing: boolean } | { type: typeof STATUS_CREATE_REQUEST; params: CreateStatusParams; idempotencyKey: string; editing: boolean }
| { type: typeof STATUS_CREATE_SUCCESS; status: BaseStatus | ScheduledStatus; params: CreateStatusParams; idempotencyKey: string; editing: boolean } | { type: typeof STATUS_CREATE_SUCCESS; status: BaseStatus | ScheduledStatus; params: CreateStatusParams; idempotencyKey: string; editing: boolean }
| { type: typeof STATUS_CREATE_FAIL; error: unknown; params: CreateStatusParams; idempotencyKey: string; editing: boolean } | { type: typeof STATUS_CREATE_FAIL; error: unknown; params: CreateStatusParams; idempotencyKey: string; editing: boolean }
// editStatus, | { type: typeof STATUS_FETCH_SOURCE_REQUEST }
// fetchStatus, | { type: typeof STATUS_FETCH_SOURCE_SUCCESS }
// deleteStatus, | { type: typeof STATUS_FETCH_SOURCE_FAIL; error: unknown }
// updateStatus, | { type: typeof STATUS_FETCH_REQUEST; statusId: string }
// fetchContext, | { type: typeof STATUS_FETCH_SUCCESS; status: BaseStatus }
| { type: typeof STATUS_FETCH_FAIL; statusId: string; error: unknown; skipAlert: true }
| { type: typeof STATUS_DELETE_REQUEST; params: Pick<Status, 'in_reply_to_id' | 'quote_id'> }
| { type: typeof STATUS_DELETE_SUCCESS; statusId: string }
| { type: typeof STATUS_DELETE_FAIL; params: Pick<Status, 'in_reply_to_id' | 'quote_id'>; error: unknown }
| { type: typeof CONTEXT_FETCH_REQUEST; statusId: string }
| { type: typeof CONTEXT_FETCH_SUCCESS; statusId: string; ancestors: Array<BaseStatus>; descendants: Array<BaseStatus> }
| { type: typeof CONTEXT_FETCH_FAIL; statusId: string; error: unknown; skipAlert: true }
| { type: typeof STATUS_MUTE_REQUEST; statusId: string } | { type: typeof STATUS_MUTE_REQUEST; statusId: string }
| { type: typeof STATUS_MUTE_SUCCESS; statusId: string } | { type: typeof STATUS_MUTE_SUCCESS; statusId: string }
| { type: typeof STATUS_MUTE_FAIL; statusId: string; error: unknown } | { type: typeof STATUS_MUTE_FAIL; statusId: string; error: unknown }

View file

@ -114,16 +114,16 @@ interface TimelineDeleteAction {
type: typeof TIMELINE_DELETE; type: typeof TIMELINE_DELETE;
statusId: string; statusId: string;
accountId: string; accountId: string;
references: Record<string, readonly [statusId: string, accountId: string]>; references: Array<[string, string]>;
reblogOf: string | null; reblogOf: string | null;
} }
const deleteFromTimelines = (statusId: string) => const deleteFromTimelines = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
const accountId = getState().statuses[statusId]?.account?.id!; const accountId = getState().statuses[statusId]?.account?.id!;
const references = Object.fromEntries(Object.entries(getState().statuses) const references: Array<[string, string]> = Object.entries(getState().statuses)
.filter(([key, status]) => [key, status.reblog_id === statusId]) .filter(([key, status]) => [key, status.reblog_id === statusId])
.map(([key, status]) => [key, [status.id, status.account_id] as const])); .map(([key, status]) => [key, status.account_id]);
const reblogOf = getState().statuses[statusId]?.reblog_id || null; const reblogOf = getState().statuses[statusId]?.reblog_id || null;
dispatch<TimelineDeleteAction>({ dispatch<TimelineDeleteAction>({

View file

@ -12,7 +12,6 @@ import {
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines'; import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
import type { Status } from 'pl-api'; import type { Status } from 'pl-api';
import type { AnyAction } from 'redux';
interface State { interface State {
inReplyTos: Record<string, string>; inReplyTos: Record<string, string>;
@ -36,7 +35,7 @@ const importStatus = (state: State, status: Pick<Status, 'id' | 'in_reply_to_id'
state.inReplyTos[id] = inReplyToId; state.inReplyTos[id] = inReplyToId;
if (idempotencyKey) { if (idempotencyKey) {
deletePendingStatus(state, status, idempotencyKey); deletePendingStatus(state, status.in_reply_to_id, idempotencyKey);
} }
}; };
@ -150,16 +149,14 @@ const filterContexts = (
}; };
/** Add a fake status ID for a pending status. */ /** Add a fake status ID for a pending status. */
const importPendingStatus = (state: State, params: Pick<Status, 'id' | 'in_reply_to_id'>, idempotencyKey: string) => { const importPendingStatus = (state: State, inReplyToId: string | null | undefined, idempotencyKey: string) => {
const id = `末pending-${idempotencyKey}`; const id = `末pending-${idempotencyKey}`;
const { in_reply_to_id } = params; return importStatus(state, { id, in_reply_to_id: inReplyToId || null });
return importStatus(state, { id, in_reply_to_id });
}; };
/** Delete a pending status from the reducer. */ /** Delete a pending status from the reducer. */
const deletePendingStatus = (state: State, params: Pick<Status, 'id' | 'in_reply_to_id'>, idempotencyKey: string) => { const deletePendingStatus = (state: State, inReplyToId: string | null | undefined, idempotencyKey: string) => {
const id = `末pending-${idempotencyKey}`; const id = `末pending-${idempotencyKey}`;
const { in_reply_to_id: inReplyToId } = params;
delete state.inReplyTos[id]; delete state.inReplyTos[id];
@ -171,7 +168,7 @@ const deletePendingStatus = (state: State, params: Pick<Status, 'id' | 'in_reply
}; };
/** Contexts reducer. Used for building a nested tree structure for threads. */ /** Contexts reducer. Used for building a nested tree structure for threads. */
const replies = (state = initialState, action: AccountsAction | AnyAction | ImporterAction | StatusesAction | TimelineAction): State => { const replies = (state = initialState, action: AccountsAction | ImporterAction | StatusesAction | TimelineAction): State => {
switch (action.type) { switch (action.type) {
case ACCOUNT_BLOCK_SUCCESS: case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS: case ACCOUNT_MUTE_SUCCESS:
@ -181,9 +178,9 @@ const replies = (state = initialState, action: AccountsAction | AnyAction | Impo
case TIMELINE_DELETE: case TIMELINE_DELETE:
return create(state, (draft) => deleteStatuses(draft, [action.statusId])); return create(state, (draft) => deleteStatuses(draft, [action.statusId]));
case STATUS_CREATE_REQUEST: case STATUS_CREATE_REQUEST:
return create(state, (draft) => importPendingStatus(draft, action.params, action.idempotencyKey)); return create(state, (draft) => importPendingStatus(draft, action.params.in_reply_to_id, action.idempotencyKey));
case STATUS_CREATE_SUCCESS: case STATUS_CREATE_SUCCESS:
return create(state, (draft) => deletePendingStatus(draft, action.status, action.idempotencyKey)); return create(state, (draft) => deletePendingStatus(draft, 'in_reply_to_id' in action.status ? action.status.in_reply_to_id : null, action.idempotencyKey));
case STATUS_IMPORT: case STATUS_IMPORT:
return create(state, (draft) => importStatus(draft, action.status, action.idempotencyKey)); return create(state, (draft) => importStatus(draft, action.status, action.idempotencyKey));
case STATUSES_IMPORT: case STATUSES_IMPORT:

View file

@ -5,10 +5,10 @@ import {
STATUS_CREATE_FAIL, STATUS_CREATE_FAIL,
STATUS_CREATE_REQUEST, STATUS_CREATE_REQUEST,
STATUS_CREATE_SUCCESS, STATUS_CREATE_SUCCESS,
type StatusesAction,
} from 'pl-fe/actions/statuses'; } from 'pl-fe/actions/statuses';
import type { StatusVisibility } from 'pl-fe/normalizers/status'; import type { StatusVisibility } from 'pl-fe/normalizers/status';
import type { AnyAction } from 'redux';
interface PendingStatus { interface PendingStatus {
content_type: string; content_type: string;
@ -49,7 +49,7 @@ const deleteStatus = (state: State, idempotencyKey: string) => {
delete state[idempotencyKey]; delete state[idempotencyKey];
}; };
const pending_statuses = (state = initialState, action: AnyAction): State => { const pending_statuses = (state = initialState, action: StatusesAction): State => {
switch (action.type) { switch (action.type) {
case STATUS_CREATE_REQUEST: case STATUS_CREATE_REQUEST:
if (action.editing) return state; if (action.editing) return state;

View file

@ -7,10 +7,9 @@ import {
SCHEDULED_STATUS_CANCEL_SUCCESS, SCHEDULED_STATUS_CANCEL_SUCCESS,
type ScheduledStatusesAction, type ScheduledStatusesAction,
} from 'pl-fe/actions/scheduled-statuses'; } from 'pl-fe/actions/scheduled-statuses';
import { STATUS_CREATE_SUCCESS } from 'pl-fe/actions/statuses'; import { STATUS_CREATE_SUCCESS, type StatusesAction } from 'pl-fe/actions/statuses';
import type { Status, ScheduledStatus } from 'pl-api'; import type { Status, ScheduledStatus } from 'pl-api';
import type { AnyAction } from 'redux';
type State = Record<string, ScheduledStatus>; type State = Record<string, ScheduledStatus>;
@ -29,7 +28,7 @@ const deleteStatus = (state: State, statusId: string) => {
delete state[statusId]; delete state[statusId];
}; };
const scheduled_statuses = (state: State = initialState, action: AnyAction | ImporterAction | ScheduledStatusesAction) => { const scheduled_statuses = (state: State = initialState, action: ImporterAction | ScheduledStatusesAction | StatusesAction) => {
switch (action.type) { switch (action.type) {
case STATUS_IMPORT: case STATUS_IMPORT:
case STATUS_CREATE_SUCCESS: case STATUS_CREATE_SUCCESS:

View file

@ -52,8 +52,7 @@ import {
} from '../actions/statuses'; } from '../actions/statuses';
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines'; import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
import type { Status as BaseStatus, Translation } from 'pl-api'; import type { Status as BaseStatus, CreateStatusParams, Translation } from 'pl-api';
import type { AnyAction } from 'redux';
type State = Record<string, MinifiedStatus>; type State = Record<string, MinifiedStatus>;
@ -91,7 +90,7 @@ const importStatuses = (state: State, statuses: Array<BaseStatus>) =>{
statuses.forEach(status => importStatus(state, status)); statuses.forEach(status => importStatus(state, status));
}; };
const deleteStatus = (state: State, statusId: string, references: Array<string>) => { const deleteStatus = (state: State, statusId: string, references: Array<[string, string]>) => {
references.forEach(ref => { references.forEach(ref => {
deleteStatus(state, ref[0], []); deleteStatus(state, ref[0], []);
}); });
@ -99,28 +98,28 @@ const deleteStatus = (state: State, statusId: string, references: Array<string>)
delete state[statusId]; delete state[statusId];
}; };
const incrementReplyCount = (state: State, { in_reply_to_id, quote }: BaseStatus) => { const incrementReplyCount = (state: State, { in_reply_to_id, quote_id }: Pick<BaseStatus | CreateStatusParams, 'in_reply_to_id' | 'quote_id'>) => {
if (in_reply_to_id && state[in_reply_to_id]) { if (in_reply_to_id && state[in_reply_to_id]) {
const parent = state[in_reply_to_id]; const parent = state[in_reply_to_id];
parent.replies_count = (typeof parent.replies_count === 'number' ? parent.replies_count : 0) + 1; parent.replies_count = (typeof parent.replies_count === 'number' ? parent.replies_count : 0) + 1;
} }
if (quote?.id && state[quote.id]) { if (quote_id && state[quote_id]) {
const parent = state[quote.id]; const parent = state[quote_id];
parent.quotes_count = (typeof parent.quotes_count === 'number' ? parent.quotes_count : 0) + 1; parent.quotes_count = (typeof parent.quotes_count === 'number' ? parent.quotes_count : 0) + 1;
} }
return state; return state;
}; };
const decrementReplyCount = (state: State, { in_reply_to_id, quote }: BaseStatus) => { const decrementReplyCount = (state: State, { in_reply_to_id, quote_id }: Pick<BaseStatus | CreateStatusParams, 'in_reply_to_id' | 'quote_id'>) => {
if (in_reply_to_id && state[in_reply_to_id]) { if (in_reply_to_id && state[in_reply_to_id]) {
const parent = state[in_reply_to_id]; const parent = state[in_reply_to_id];
parent.replies_count = Math.max(0, parent.replies_count - 1); parent.replies_count = Math.max(0, parent.replies_count - 1);
} }
if (quote?.id) { if (quote_id) {
const parent = state[quote.id]; const parent = state[quote_id];
parent.quotes_count = Math.max(0, parent.quotes_count - 1); parent.quotes_count = Math.max(0, parent.quotes_count - 1);
} }
@ -177,7 +176,7 @@ const deleteTranslation = (state: State, statusId: string) => {
const initialState: State = {}; const initialState: State = {};
const statuses = (state = initialState, action: AnyAction | EmojiReactsAction | EventsAction | ImporterAction | InteractionsAction | StatusesAction | TimelineAction): State => { const statuses = (state = initialState, action: EmojiReactsAction | EventsAction | ImporterAction | InteractionsAction | StatusesAction | TimelineAction): State => {
switch (action.type) { switch (action.type) {
case STATUS_IMPORT: case STATUS_IMPORT:
return create(state, (draft) => importStatus(draft, action.status)); return create(state, (draft) => importStatus(draft, action.status));
@ -317,7 +316,7 @@ const statuses = (state = initialState, action: AnyAction | EmojiReactsAction |
} }
}); });
case STATUS_TRANSLATE_SUCCESS: case STATUS_TRANSLATE_SUCCESS:
return create(state, (draft) => importTranslation(draft, action.statusId, action.translation)); return action.statusId !== null ? create(state, (draft) => importTranslation(draft, action.statusId!, action.translation)) : state;
case STATUS_TRANSLATE_FAIL: case STATUS_TRANSLATE_FAIL:
return create(state, (draft) => { return create(state, (draft) => {
const status = draft[action.statusId]; const status = draft[action.statusId];

View file

@ -19,10 +19,9 @@ import {
type TimelineAction, type TimelineAction,
} from '../actions/timelines'; } from '../actions/timelines';
import type { PaginatedResponse, Status as BaseStatus, Relationship } from 'pl-api'; import type { PaginatedResponse, Status as BaseStatus, Relationship, CreateStatusParams } from 'pl-api';
import type { ImportPosition } from 'pl-fe/entity-store/types'; import type { ImportPosition } from 'pl-fe/entity-store/types';
import type { Status } from 'pl-fe/normalizers/status'; import type { Status } from 'pl-fe/normalizers/status';
import type { AnyAction } from 'redux';
const TRUNCATE_LIMIT = 40; const TRUNCATE_LIMIT = 40;
const TRUNCATE_SIZE = 20; const TRUNCATE_SIZE = 20;
@ -159,14 +158,14 @@ const updateTimelineQueue = (state: State, timelineId: string, statusId: string)
}); });
}; };
const shouldDelete = (timelineId: string, excludeAccount?: string) => { const shouldDelete = (timelineId: string, excludeAccount: string | null) => {
if (!excludeAccount) return true; if (!excludeAccount) return true;
if (timelineId === `account:${excludeAccount}`) return false; if (timelineId === `account:${excludeAccount}`) return false;
if (timelineId.startsWith(`account:${excludeAccount}:`)) return false; if (timelineId.startsWith(`account:${excludeAccount}:`)) return false;
return true; return true;
}; };
const deleteStatus = (state: State, statusId: string, references: Array<string>, excludeAccount?: string) => { const deleteStatus = (state: State, statusId: string, references: Array<[string]> | Array<[string, string]>, excludeAccount: string | null) => {
for (const timelineId in state) { for (const timelineId in state) {
if (shouldDelete(timelineId, excludeAccount)) { if (shouldDelete(timelineId, excludeAccount)) {
state[timelineId].items = state[timelineId].items.filter(id => id !== statusId); state[timelineId].items = state[timelineId].items.filter(id => id !== statusId);
@ -176,7 +175,7 @@ const deleteStatus = (state: State, statusId: string, references: Array<string>,
// Remove reblogs of deleted status // Remove reblogs of deleted status
references.forEach(ref => { references.forEach(ref => {
deleteStatus(state, ref, [], excludeAccount); deleteStatus(state, ref[0], [], excludeAccount);
}); });
}; };
@ -195,10 +194,10 @@ const isReblogOf = (reblog: Pick<Status, 'reblog_id'>, status: Pick<Status, 'id'
const buildReferencesTo = ( const buildReferencesTo = (
statuses: Record<string, Pick<Status, 'id' | 'account' | 'reblog_id'>>, statuses: Record<string, Pick<Status, 'id' | 'account' | 'reblog_id'>>,
status: Pick<Status, 'id'>, status: Pick<Status, 'id'>,
) => ( ): Array<[string]> => (
Object.values(statuses) Object.values(statuses)
.filter(reblog => isReblogOf(reblog, status)) .filter(reblog => isReblogOf(reblog, status))
.map(status => status.id) .map(status => [status.id])
); );
// const filterTimeline = (state: State, timelineId: string, relationship: APIEntity, statuses: ImmutableList<ImmutableMap<string, any>>) => // const filterTimeline = (state: State, timelineId: string, relationship: APIEntity, statuses: ImmutableList<ImmutableMap<string, any>>) =>
@ -238,10 +237,10 @@ const timelineDequeue = (state: State, timelineId: string) => {
// timeline.set('items', addStatusId(items, null)); // timeline.set('items', addStatusId(items, null));
// })); // }));
const getTimelinesForStatus = (status: Pick<BaseStatus, 'visibility' | 'group'>) => { const getTimelinesForStatus = (status: Pick<BaseStatus, 'visibility' | 'group'> | Pick<CreateStatusParams, 'visibility'>) => {
switch (status.visibility) { switch (status.visibility) {
case 'group': case 'group':
return [`group:${status.group?.id}`]; return [`group:${'group' in status && status.group?.id}`];
case 'direct': case 'direct':
return ['direct']; return ['direct'];
case 'public': case 'public':
@ -260,7 +259,7 @@ const replaceId = (ids: Array<string>, oldId: string, newId: string) => {
} }
}; };
const importPendingStatus = (state: State, params: BaseStatus, idempotencyKey: string) => { const importPendingStatus = (state: State, params: CreateStatusParams, idempotencyKey: string) => {
const statusId = `末pending-${idempotencyKey}`; const statusId = `末pending-${idempotencyKey}`;
const timelineIds = getTimelinesForStatus(params); const timelineIds = getTimelinesForStatus(params);
@ -295,14 +294,14 @@ const handleExpandFail = (state: State, timelineId: string) => {
setFailed(state, timelineId, true); setFailed(state, timelineId, true);
}; };
const timelines = (state: State = initialState, action: AccountsAction | AnyAction | InteractionsAction | StatusesAction | TimelineAction): State => { const timelines = (state: State = initialState, action: AccountsAction | InteractionsAction | StatusesAction | TimelineAction): State => {
switch (action.type) { switch (action.type) {
case STATUS_CREATE_REQUEST: case STATUS_CREATE_REQUEST:
if (action.params.scheduled_at) return state; if (action.params.scheduled_at) return state;
return create(state, (draft) => importPendingStatus(draft, action.params, action.idempotencyKey)); return create(state, (draft) => importPendingStatus(draft, action.params, action.idempotencyKey));
case STATUS_CREATE_SUCCESS: case STATUS_CREATE_SUCCESS:
if (action.status.scheduled_at || action.editing) return state; if ('params' in action.status || action.editing) return state;
return create(state, (draft) => importStatus(draft, action.status, action.idempotencyKey)); return create(state, (draft) => importStatus(draft, action.status as BaseStatus, action.idempotencyKey));
case TIMELINE_EXPAND_REQUEST: case TIMELINE_EXPAND_REQUEST:
return create(state, (draft) => setLoading(draft, action.timeline, true)); return create(state, (draft) => setLoading(draft, action.timeline, true));
case TIMELINE_EXPAND_FAIL: case TIMELINE_EXPAND_FAIL: