diff --git a/src/redux/createAsyncThunkWithTypes.ts b/src/redux/createAsyncThunkWithTypes.ts new file mode 100644 index 000000000..cecaa5091 --- /dev/null +++ b/src/redux/createAsyncThunkWithTypes.ts @@ -0,0 +1,14 @@ +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { AppDispatch, RootState } from "./store"; + +/** + * Use instead of createAsyncThunk to provide basic typing to all async thunks + * + * Thematically this belongs in `store.ts`. However, this causes + * "Cannot access 'createAsyncThunk' before initialization", + * so this has to be moved into it's own file. + */ +export const createAppAsyncThunk = createAsyncThunk.withTypes<{ + state: RootState + dispatch: AppDispatch +}>(); diff --git a/src/redux/metadataSlice.ts b/src/redux/metadataSlice.ts index fe0424385..26cac6484 100644 --- a/src/redux/metadataSlice.ts +++ b/src/redux/metadataSlice.ts @@ -1,8 +1,9 @@ -import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit"; +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { client } from "../util/client"; import { httpRequestState } from "../types"; import { settings } from "../config"; +import { createAppAsyncThunk } from "./createAsyncThunkWithTypes"; export interface Catalog { fields: MetadataField[], @@ -36,7 +37,7 @@ const initialState: metadata & httpRequestState = { errorReason: "unknown", }; -export const fetchMetadata = createAsyncThunk("metadata/fetchMetadata", async () => { +export const fetchMetadata = createAppAsyncThunk("metadata/fetchMetadata", async () => { if (!settings.id) { throw new Error("Missing media package identifier"); } diff --git a/src/redux/subtitleSlice.ts b/src/redux/subtitleSlice.ts index 770edbe7a..f25269282 100644 --- a/src/redux/subtitleSlice.ts +++ b/src/redux/subtitleSlice.ts @@ -1,7 +1,7 @@ import { Segment, SubtitleCue, SubtitlesInEditor } from "./../types"; -import { createAsyncThunk, createSlice, nanoid, PayloadAction } from "@reduxjs/toolkit"; +import { createSlice, nanoid, PayloadAction } from "@reduxjs/toolkit"; import { roundToDecimalPlace } from "../util/utilityFunctions"; -import { video } from "./videoSlice"; +import { createAppAsyncThunk } from "./createAsyncThunkWithTypes"; export interface subtitle { isDisplayEditView: boolean; // Should the edit view be displayed @@ -253,7 +253,7 @@ export const { * Will grab the state from videoState to skip past deleted segment if preview * mode is active. */ -export const setCurrentlyAtAndTriggerPreview = createAsyncThunk("subtitleState/setCurrentlyAtAndTriggerPreview", +export const setCurrentlyAtAndTriggerPreview = createAppAsyncThunk("subtitleState/setCurrentlyAtAndTriggerPreview", async (milliseconds: number, { getState, dispatch }) => { milliseconds = roundToDecimalPlace(milliseconds, 0); @@ -261,7 +261,7 @@ export const setCurrentlyAtAndTriggerPreview = createAsyncThunk("subtitleState/s milliseconds = 0; } - const allStates = getState() as { videoState: video, subtitleState: subtitle; }; + const allStates = getState(); const segments: Segment[] = allStates.videoState.segments; let triggered = false; diff --git a/src/redux/videoSlice.ts b/src/redux/videoSlice.ts index b7ff287be..abd040880 100644 --- a/src/redux/videoSlice.ts +++ b/src/redux/videoSlice.ts @@ -1,10 +1,11 @@ import { clamp } from "lodash"; -import { createSlice, nanoid, createAsyncThunk, PayloadAction, createSelector } from "@reduxjs/toolkit"; +import { createSlice, nanoid, PayloadAction, createSelector } from "@reduxjs/toolkit"; import { client } from "../util/client"; import { Segment, httpRequestState, Track, Workflow, SubtitlesFromOpencast } from "../types"; import { roundToDecimalPlace } from "../util/utilityFunctions"; import { settings } from "../config"; +import { createAppAsyncThunk } from "./createAsyncThunkWithTypes"; export interface video { isPlaying: boolean, // Are videos currently playing? @@ -81,7 +82,7 @@ export const initialState: video & httpRequestState = { errorReason: "unknown", }; -export const fetchVideoInformation = createAsyncThunk("video/fetchVideoInformation", async () => { +export const fetchVideoInformation = createAppAsyncThunk("video/fetchVideoInformation", async () => { if (!settings.id) { throw new Error("Missing media package identifier"); } diff --git a/src/redux/workflowPostSlice.ts b/src/redux/workflowPostSlice.ts index a86291646..c1ec1ec6d 100644 --- a/src/redux/workflowPostSlice.ts +++ b/src/redux/workflowPostSlice.ts @@ -1,7 +1,8 @@ -import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; +import { createSlice } from "@reduxjs/toolkit"; import { client } from "../util/client"; import { Segment, PostEditArgument, httpRequestState } from "../types"; import { settings } from "../config"; +import { createAppAsyncThunk } from "./createAsyncThunkWithTypes"; const initialState: httpRequestState = { status: "idle", @@ -10,7 +11,7 @@ const initialState: httpRequestState = { }; export const postVideoInformation = - createAsyncThunk("video/postVideoInformation", async (argument: PostEditArgument) => { + createAppAsyncThunk("video/postVideoInformation", async (argument: PostEditArgument) => { if (!settings.id) { throw new Error("Missing media package id"); }