Commit 666058a4 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Migrate frames store module to TypeScript

parent a9213ef3
...@@ -5,49 +5,53 @@ import { ...@@ -5,49 +5,53 @@ import {
} from 'reselect'; } from 'reselect';
import shallowEqual from 'shallowequal'; import shallowEqual from 'shallowequal';
import type {
ContentInfoConfig,
DocumentMetadata,
SegmentInfo,
} from '../../../types/annotator';
import { createStoreModule, makeAction } from '../create-store'; import { createStoreModule, makeAction } from '../create-store';
/** export type Frame = {
* @typedef {import('../../../types/annotator').ContentInfoConfig} ContentInfoConfig /**
* @typedef {import('../../../types/annotator').DocumentMetadata} DocumentMetadata * Sub-frames will all have a id (frame identifier) set. The main frame's id
* @typedef {import('../../../types/annotator').SegmentInfo} SegmentInfo * is always `null`
*/ */
id: string | null;
/** /** Metadata about the document currently loaded in this frame */
* @typedef Frame metadata: DocumentMetadata;
* @prop {string|null} id /** Current primary URI of the document being displayed */
* - Sub-frames will all have a id (frame identifier) set. The main frame's id is always `null` uri: string;
* @prop {DocumentMetadata} metadata - Metadata about the document currently loaded in this frame isAnnotationFetchComplete?: boolean;
* @prop {string} uri - Current primary URI of the document being displayed /** Should this frame be retained in the sidebar if the guest disconnects? */
* @prop {boolean} [isAnnotationFetchComplete] persistent: boolean;
* @prop {boolean} persistent - Should this frame be retained in the sidebar
* if the guest disconnects?
* @prop {SegmentInfo} [segment] - Information about the section of a document
* that is currently loaded. This is for content such as EPUBs, where the
* content displayed in a guest frame is only part of the whole document.
*/
const initialState = { /**
/** @type {Frame[]} */ * Information about the section of a document that is currently loaded.
frames: [], * This is for content such as EPUBs, where the content displayed in a guest
* frame is only part of the whole document.
*/
segment?: SegmentInfo;
};
export type State = {
frames: Frame[];
/** /**
* Data for the content information banner shown above the content in the main * Data for the content information banner shown above the content in the main
* guest frame. * guest frame.
*
* @type {ContentInfoConfig|null}
*/ */
contentInfo: null, contentInfo: ContentInfoConfig | null;
}; };
/** @typedef {typeof initialState} State */ const initialState: State = {
frames: [],
contentInfo: null,
};
const reducers = { const reducers = {
/** CONNECT_FRAME(state: State, action: { frame: Frame }) {
* @param {State} state
* @param {{ frame: Frame }} action
*/
CONNECT_FRAME(state, action) {
const frameIndex = state.frames.findIndex( const frameIndex = state.frames.findIndex(
frame => frame.id === action.frame.id frame => frame.id === action.frame.id
); );
...@@ -60,20 +64,15 @@ const reducers = { ...@@ -60,20 +64,15 @@ const reducers = {
return { frames: newFrames }; return { frames: newFrames };
}, },
/** DESTROY_FRAME(state: State, action: { frame: Frame }) {
* @param {State} state
* @param {{ frame: Frame }} action
*/
DESTROY_FRAME(state, action) {
const frames = state.frames.filter(f => f !== action.frame); const frames = state.frames.filter(f => f !== action.frame);
return { frames }; return { frames };
}, },
/** UPDATE_FRAME_ANNOTATION_FETCH_STATUS(
* @param {State} state state: State,
* @param {{ uri: string, isAnnotationFetchComplete: boolean }} action action: { uri: string; isAnnotationFetchComplete: boolean }
*/ ) {
UPDATE_FRAME_ANNOTATION_FETCH_STATUS(state, action) {
const frames = state.frames.map(frame => { const frames = state.frames.map(frame => {
const match = frame.uri && frame.uri === action.uri; const match = frame.uri && frame.uri === action.uri;
if (match) { if (match) {
...@@ -87,11 +86,7 @@ const reducers = { ...@@ -87,11 +86,7 @@ const reducers = {
return { frames }; return { frames };
}, },
/** SET_CONTENT_INFO(state: State, action: { info: ContentInfoConfig }) {
* @param {State} state
* @param {{ info: ContentInfoConfig }} action
*/
SET_CONTENT_INFO(state, action) {
return { contentInfo: action.info }; return { contentInfo: action.info };
}, },
}; };
...@@ -101,46 +96,39 @@ const reducers = { ...@@ -101,46 +96,39 @@ const reducers = {
* *
* If a frame exists with the same ID as `frame` it is replaced, otherwise * If a frame exists with the same ID as `frame` it is replaced, otherwise
* a new frame is added. * a new frame is added.
*
* @param {Frame} frame
*/ */
function connectFrame(frame) { function connectFrame(frame: Frame) {
return makeAction(reducers, 'CONNECT_FRAME', { frame }); return makeAction(reducers, 'CONNECT_FRAME', { frame });
} }
/** /**
* Remove a frame from the list of connected frames. * Remove a frame from the list of connected frames.
*
* @param {Frame} frame
*/ */
function destroyFrame(frame) { function destroyFrame(frame: Frame) {
return makeAction(reducers, 'DESTROY_FRAME', { frame }); return makeAction(reducers, 'DESTROY_FRAME', { frame });
} }
/** /**
* Update the `isAnnotationFetchComplete` flag of the frame. * Update the `isAnnotationFetchComplete` flag of the frame.
*
* @param {string} uri
* @param {boolean} isFetchComplete
*/ */
function updateFrameAnnotationFetchStatus(uri, isFetchComplete) { function updateFrameAnnotationFetchStatus(
uri: string,
isFetchComplete: boolean
) {
return makeAction(reducers, 'UPDATE_FRAME_ANNOTATION_FETCH_STATUS', { return makeAction(reducers, 'UPDATE_FRAME_ANNOTATION_FETCH_STATUS', {
uri, uri,
isAnnotationFetchComplete: isFetchComplete, isAnnotationFetchComplete: isFetchComplete,
}); });
} }
/** @param {ContentInfoConfig} info */ function setContentInfo(info: ContentInfoConfig) {
function setContentInfo(info) {
return makeAction(reducers, 'SET_CONTENT_INFO', { info }); return makeAction(reducers, 'SET_CONTENT_INFO', { info });
} }
/** /**
* Return the list of frames currently connected to the sidebar app. * Return the list of frames currently connected to the sidebar app.
*
* @param {State} state
*/ */
function frames(state) { function frames(state: State) {
return state.frames; return state.frames;
} }
...@@ -155,18 +143,14 @@ function frames(state) { ...@@ -155,18 +143,14 @@ function frames(state) {
* This may be `null` during startup. * This may be `null` during startup.
*/ */
const mainFrame = createSelector( const mainFrame = createSelector(
/** @param {State} state */ (state: State) => state.frames,
state => state.frames,
// Sub-frames will all have a "frame identifier" set. The main frame is the // Sub-frames will all have a "frame identifier" set. The main frame is the
// one with a `null` id. // one with a `null` id.
frames => frames.find(f => !f.id) || null frames => frames.find(f => !f.id) || null
); );
/** function searchUrisForFrame(frame: Frame): string[] {
* @param {Frame} frame
*/
function searchUrisForFrame(frame) {
let uris = [frame.uri]; let uris = [frame.uri];
if (frame.metadata && frame.metadata.documentFingerprint) { if (frame.metadata && frame.metadata.documentFingerprint) {
...@@ -197,17 +181,15 @@ const createShallowEqualSelector = createSelectorCreator( ...@@ -197,17 +181,15 @@ const createShallowEqualSelector = createSelectorCreator(
* values of the array change (are not shallow-equal). * values of the array change (are not shallow-equal).
*/ */
const searchUris = createShallowEqualSelector( const searchUris = createShallowEqualSelector(
/** @param {State} state */ (state: State) =>
state => state.frames.reduce<string[]>(
state.frames.reduce(
(uris, frame) => uris.concat(searchUrisForFrame(frame)), (uris, frame) => uris.concat(searchUrisForFrame(frame)),
/** @type {string[]} */ ([]) []
), ),
uris => uris uris => uris
); );
/** @param {State} state */ function getContentInfo(state: State) {
function getContentInfo(state) {
return state.contentInfo; return state.contentInfo;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment