Commit 12a1dc4e authored by Robert Knight's avatar Robert Knight

Improve `initialState` definitions in store modules

Convert the `initialState` functions in store modules to `const` values
for modules where the state is static (ie. does not depend on
`settings`) and add better type documentation.

Most references to the state are not currently type-checked, but they
will be in future. In the interim this serves as useful documentation
for humans.
parent f5833aeb
...@@ -6,31 +6,33 @@ ...@@ -6,31 +6,33 @@
import { actionTypes } from '../util'; import { actionTypes } from '../util';
import { createStoreModule } from '../create-store'; import { createStoreModule } from '../create-store';
function initialState() { const initialState = {
return { /**
/** * Annotation `$tag`s that correspond to annotations with active API requests
* Annotation `$tag`s that correspond to annotations with active API requests *
*/ * @type {string[]}
activeAnnotationSaveRequests: [], */
/** activeAnnotationSaveRequests: [],
* The number of API requests that have started and not yet completed. /**
*/ * The number of API requests that have started and not yet completed.
activeApiRequests: 0, */
/** activeApiRequests: 0,
* The number of annotation fetches that have started and not yet completed. /**
*/ * The number of annotation fetches that have started and not yet completed.
activeAnnotationFetches: 0, */
/** activeAnnotationFetches: 0,
* Have annotations ever been fetched? /**
*/ * Have annotations ever been fetched?
hasFetchedAnnotations: false, */
/** hasFetchedAnnotations: false,
* The number of total annotation results the service reported as /**
* matching the most recent load/search request * The number of total annotation results the service reported as
*/ * matching the most recent load/search request
annotationResultCount: null, *
}; * @type {number|null}
} */
annotationResultCount: null,
};
const reducers = { const reducers = {
API_REQUEST_STARTED(state) { API_REQUEST_STARTED(state) {
......
...@@ -89,21 +89,30 @@ function initializeAnnotation(annotation, tag) { ...@@ -89,21 +89,30 @@ function initializeAnnotation(annotation, tag) {
}); });
} }
function initialState() { const initialState = {
return { /**
/** @type {Annotation[]} */ * Set of all currently loaded annotations.
annotations: [], *
// A set of annotations that are currently "focused" — e.g. hovered over in * @type {Annotation[]}
// the UI */
focused: {}, annotations: [],
// A map of annotations that should appear as "highlighted", e.g. the /**
// target of a single-annotation view * A set of annotations that are currently "focused" — e.g. hovered over in
highlighted: {}, * the UI.
// The local tag to assign to the next annotation that is loaded into the *
// app * @type {Record<string, boolean>}
nextTag: 1, */
}; focused: {},
} /**
* A map of annotations that should appear as "highlighted", e.g. the
* target of a single-annotation view
*
* @type {Record<string, boolean>}
*/
highlighted: {},
/** The local tag to assign to the next annotation that is loaded into the app. */
nextTag: 1,
};
const reducers = { const reducers = {
ADD_ANNOTATIONS: function (state, action) { ADD_ANNOTATIONS: function (state, action) {
......
...@@ -16,18 +16,10 @@ import { createStoreModule } from '../create-store'; ...@@ -16,18 +16,10 @@ import { createStoreModule } from '../create-store';
* `persistedDefaults` service. * `persistedDefaults` service.
*/ */
function initialState() { const initialState = {
/** annotationPrivacy: /** @type {'private'|'shared'|null} */ (null),
* Note that the persisted presence of any of these defaults cannot be focusedGroup: /** @type {string|null} */ (null),
* guaranteed, so consumers of said defaults should be prepared to handle };
* missing (i.e. `null`) values. As `null` is a sentinal value indicating
* "not set/unavailable", a `null` value for a default is otherwise invalid.
*/
return {
annotationPrivacy: null,
focusedGroup: null,
};
}
const reducers = { const reducers = {
SET_DEFAULT: function (state, action) { SET_DEFAULT: function (state, action) {
......
...@@ -11,9 +11,8 @@ import { createStoreModule } from '../create-store'; ...@@ -11,9 +11,8 @@ import { createStoreModule } from '../create-store';
* existing annotations. * existing annotations.
*/ */
function initialState() { /** @type {Draft[]} */
return []; const initialState = [];
}
/** /**
* Helper class to encapsulate the draft properties and a few simple methods. * Helper class to encapsulate the draft properties and a few simple methods.
......
...@@ -20,10 +20,8 @@ import { createStoreModule } from '../create-store'; ...@@ -20,10 +20,8 @@ import { createStoreModule } from '../create-store';
* @prop {string} uri - Current primary URI of the document being displayed * @prop {string} uri - Current primary URI of the document being displayed
*/ */
function initialState() { /** @type {Frame[]} */
// The list of frames connected to the sidebar app const initialState = [];
return [];
}
const reducers = { const reducers = {
CONNECT_FRAME: function (state, action) { CONNECT_FRAME: function (state, action) {
......
...@@ -9,21 +9,19 @@ import session from './session'; ...@@ -9,21 +9,19 @@ import session from './session';
* @typedef {import('../../../types/api').Group} Group * @typedef {import('../../../types/api').Group} Group
*/ */
function initialState() { const initialState = {
return { /**
/** * List of groups.
* List of groups. * @type {Group[]}
* @type {Group[]} */
*/ groups: [],
groups: [],
/**
/** * ID of currently selected group.
* ID of currently selected group. * @type {string|null}
* @type {string|null} */
*/ focusedGroupId: null,
focusedGroupId: null, };
};
}
const reducers = { const reducers = {
FOCUS_GROUP(state, action) { FOCUS_GROUP(state, action) {
......
...@@ -2,9 +2,7 @@ import { actionTypes } from '../util'; ...@@ -2,9 +2,7 @@ import { actionTypes } from '../util';
import { replaceURLParams } from '../../util/url'; import { replaceURLParams } from '../../util/url';
import { createStoreModule } from '../create-store'; import { createStoreModule } from '../create-store';
function initialState() { const initialState = /** @type {Record<string, string>|null} */ (null);
return null;
}
const reducers = { const reducers = {
UPDATE_LINKS(state, action) { UPDATE_LINKS(state, action) {
......
...@@ -16,17 +16,23 @@ import annotations from './annotations'; ...@@ -16,17 +16,23 @@ import annotations from './annotations';
import groups from './groups'; import groups from './groups';
import route from './route'; import route from './route';
function initialState() { const initialState = {
return { /**
// Map of ID -> updated annotation for updates that have been received over * Map of ID -> updated annotation for updates that have been received over
// the WebSocket but not yet applied * the WebSocket but not yet applied
pendingUpdates: {}, *
* @type {Record<string, Annotation>}
// Set of IDs of annotations which have been deleted but for which the */
// deletion has not yet been applied pendingUpdates: {},
pendingDeletions: {},
}; /**
} * Set of IDs of annotations which have been deleted but for which the
* deletion has not yet been applied
*
* @type {Record<string, boolean>}
*/
pendingDeletions: {},
};
const reducers = { const reducers = {
RECEIVE_REAL_TIME_UPDATES(state, action) { RECEIVE_REAL_TIME_UPDATES(state, action) {
......
...@@ -2,24 +2,29 @@ import { actionTypes } from '../util'; ...@@ -2,24 +2,29 @@ import { actionTypes } from '../util';
import { createStoreModule } from '../create-store'; import { createStoreModule } from '../create-store';
function initialState() { /**
return { * @typedef {'annotation'|'notebook'|'sidebar'|'stream'} RouteName
/** */
* The current route.
* One of null (if no route active yet), "sidebar", "annotation" or "stream".
*/
name: null,
/** const initialState = {
* Parameters of the current route. /**
* * The current route.
* - The "annotation" route has an "id" (annotation ID) parameter. *
* - The "stream" route has a "q" (query) parameter. * @type {RouteName|null}
* - The "sidebar" route has no parameters. */
*/ name: null,
params: {},
}; /**
} * Parameters of the current route.
*
* - The "annotation" route has an "id" (annotation ID) parameter.
* - The "stream" route has a "q" (query) parameter.
* - The "sidebar" route has no parameters.
*
* @type {Record<string, string>}
*/
params: {},
};
const reducers = { const reducers = {
CHANGE_ROUTE(state, { name, params }) { CHANGE_ROUTE(state, { name, params }) {
......
...@@ -16,21 +16,20 @@ import * as util from '../util'; ...@@ -16,21 +16,20 @@ import * as util from '../util';
import { createStoreModule } from '../create-store'; import { createStoreModule } from '../create-store';
function initialState() { const initialState = {
return { /*
/* * The `panelName` of the currently-active sidebar panel.
* The `panelName` of the currently-active sidebar panel. * Only one `panelName` may be active at a time, but it is valid (though not
* Only one `panelName` may be active at a time, but it is valid (though not * the standard use case) for multiple `SidebarPanel` components to share
* the standard use case) for multiple `SidebarPanel` components to share * the same `panelName`—`panelName` is not intended as a unique ID/key.
* the same `panelName`—`panelName` is not intended as a unique ID/key. *
* * e.g. If `activePanelName` were `foobar`, all `SidebarPanel` components
* e.g. If `activePanelName` were `foobar`, all `SidebarPanel` components * with `panelName` of `foobar` would be active, and thus visible.
* with `panelName` of `foobar` would be active, and thus visible. *
* * @type {PanelName|null}
*/ */
activePanelName: null, activePanelName: null,
}; };
}
const reducers = { const reducers = {
OPEN_SIDEBAR_PANEL: function (state, action) { OPEN_SIDEBAR_PANEL: function (state, action) {
......
...@@ -16,11 +16,11 @@ import * as util from '../util'; ...@@ -16,11 +16,11 @@ import * as util from '../util';
* maintains state only; it's up to other layers to handle the management * maintains state only; it's up to other layers to handle the management
* and interactions with these messages. * and interactions with these messages.
*/ */
function initialState() {
return { const initialState = {
messages: [], /** @type {ToastMessage[]} */
}; messages: [],
} };
const reducers = { const reducers = {
ADD_MESSAGE: function (state, action) { ADD_MESSAGE: function (state, action) {
......
...@@ -7,14 +7,14 @@ import { createStoreModule } from '../create-store'; ...@@ -7,14 +7,14 @@ import { createStoreModule } from '../create-store';
* sidebar. * sidebar.
*/ */
function initialState() { const initialState = {
return { /**
// Has the sidebar ever been opened? NB: This is not necessarily the * Has the sidebar ever been opened? NB: This is not necessarily the
// current state of the sidebar, but tracks whether it has ever been open * current state of the sidebar, but tracks whether it has ever been open
sidebarHasOpened: false, */
visibleHighlights: false, sidebarHasOpened: false,
}; visibleHighlights: false,
} };
const reducers = { const reducers = {
SET_HIGHLIGHTS_VISIBLE: function (state, action) { SET_HIGHLIGHTS_VISIBLE: function (state, action) {
......
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