signal-desktop/ts/state/ducks/linkPreviews.ts

137 lines
3.3 KiB
TypeScript
Raw Normal View History

2021-04-27 22:35:35 +00:00
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
2022-06-17 00:48:57 +00:00
import type { ThunkAction } from 'redux-thunk';
import type { ReadonlyDeep } from 'type-fest';
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
import type { LinkPreviewType } from '../../types/message/LinkPreviews';
import type { MaybeGrabLinkPreviewOptionsType } from '../../types/LinkPreview';
2022-06-17 00:48:57 +00:00
import type { NoopActionType } from './noop';
import type { StateType as RootStateType } from '../reducer';
import { LinkPreviewSourceType } from '../../types/LinkPreview';
2021-08-18 13:34:22 +00:00
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
2022-06-17 00:48:57 +00:00
import { maybeGrabLinkPreview } from '../../services/LinkPreview';
import { strictAssert } from '../../util/assert';
2022-06-17 00:48:57 +00:00
import { useBoundActions } from '../../hooks/useBoundActions';
2021-04-27 22:35:35 +00:00
// State
export type LinkPreviewsStateType = ReadonlyDeep<{
linkPreview?: LinkPreviewType;
source?: LinkPreviewSourceType;
}>;
2021-04-27 22:35:35 +00:00
// Actions
2022-06-17 00:48:57 +00:00
export const ADD_PREVIEW = 'linkPreviews/ADD_PREVIEW';
2021-08-18 13:34:22 +00:00
export const REMOVE_PREVIEW = 'linkPreviews/REMOVE_PREVIEW';
2021-04-27 22:35:35 +00:00
export type AddLinkPreviewActionType = ReadonlyDeep<{
2021-04-27 22:35:35 +00:00
type: 'linkPreviews/ADD_PREVIEW';
2022-06-17 00:48:57 +00:00
payload: {
conversationId?: string;
2022-06-17 00:48:57 +00:00
linkPreview: LinkPreviewType;
source: LinkPreviewSourceType;
};
}>;
2021-04-27 22:35:35 +00:00
export type RemoveLinkPreviewActionType = ReadonlyDeep<{
2021-04-27 22:35:35 +00:00
type: 'linkPreviews/REMOVE_PREVIEW';
payload: {
conversationId?: string;
};
}>;
2021-04-27 22:35:35 +00:00
type LinkPreviewsActionType = ReadonlyDeep<
AddLinkPreviewActionType | RemoveLinkPreviewActionType
>;
2021-04-27 22:35:35 +00:00
// Action Creators
2022-06-17 00:48:57 +00:00
function debouncedMaybeGrabLinkPreview(
message: string,
source: LinkPreviewSourceType,
options?: MaybeGrabLinkPreviewOptionsType
2022-06-17 00:48:57 +00:00
): ThunkAction<void, RootStateType, unknown, NoopActionType> {
return dispatch => {
maybeGrabLinkPreview(message, source, options);
2022-06-17 00:48:57 +00:00
dispatch({
type: 'NOOP',
payload: null,
});
};
}
2021-04-27 22:35:35 +00:00
2022-06-17 00:48:57 +00:00
function addLinkPreview(
linkPreview: LinkPreviewType,
source: LinkPreviewSourceType,
conversationId?: string
2022-06-17 00:48:57 +00:00
): AddLinkPreviewActionType {
if (source === LinkPreviewSourceType.Composer) {
strictAssert(conversationId, 'no conversationId provided');
}
2021-04-27 22:35:35 +00:00
return {
type: ADD_PREVIEW,
2022-06-17 00:48:57 +00:00
payload: {
conversationId,
2022-06-17 00:48:57 +00:00
linkPreview,
source,
},
2021-04-27 22:35:35 +00:00
};
}
function removeLinkPreview(
conversationId?: string
): RemoveLinkPreviewActionType {
2021-04-27 22:35:35 +00:00
return {
type: REMOVE_PREVIEW,
payload: {
conversationId,
},
2021-04-27 22:35:35 +00:00
};
}
2022-06-17 00:48:57 +00:00
export const actions = {
addLinkPreview,
debouncedMaybeGrabLinkPreview,
removeLinkPreview,
};
export const useLinkPreviewActions = (): BoundActionCreatorsMapObject<
typeof actions
> => useBoundActions(actions);
2022-06-17 00:48:57 +00:00
2021-04-27 22:35:35 +00:00
// Reducer
export function getEmptyState(): LinkPreviewsStateType {
return {
linkPreview: undefined,
};
}
export function reducer(
state: Readonly<LinkPreviewsStateType> = getEmptyState(),
action: Readonly<LinkPreviewsActionType>
): LinkPreviewsStateType {
if (action.type === ADD_PREVIEW) {
const { payload } = action;
return {
2022-06-17 00:48:57 +00:00
linkPreview: payload.linkPreview,
source: payload.source,
2021-04-27 22:35:35 +00:00
};
}
if (action.type === REMOVE_PREVIEW) {
2021-08-18 13:34:22 +00:00
return assignWithNoUnnecessaryAllocation(state, {
2021-04-27 22:35:35 +00:00
linkPreview: undefined,
2022-06-17 00:48:57 +00:00
source: undefined,
2021-08-18 13:34:22 +00:00
});
2021-04-27 22:35:35 +00:00
}
return state;
}