save state of code

This commit is contained in:
Alexander Bentkamp
2022-12-14 14:02:57 +01:00
parent 4114cbc304
commit 32b9d028a7
7 changed files with 63 additions and 15 deletions
+55
View File
@@ -0,0 +1,55 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { Connection } from '../connection'
interface GameInfo {
title: null|string,
introduction: null|string,
worlds: null|{nodes: string[], edges: string[][]},
authors: null|string[],
conclusion: null|string,
}
interface LevelInfo {
title: null|string,
introduction: null|string,
index: number,
tactics: any[],
lemmas: any[],
descrText: null|string,
descrFormat: null|string,
}
const customBaseQuery = async (
args : {method: string, params?: any},
{ signal, dispatch, getState, extra },
extraOptions
) => {
try {
const connection : Connection = extra.connection
let leanClient = await connection.startLeanClient()
console.log(`Sending request ${args.method}`)
let res = await leanClient.sendRequest(args.method, args.params)
console.log('Received response', res)
return {'data': res}
} catch (e) {
return {'error': e}
}
}
// Define a service using a base URL and expected endpoints
export const apiSlice = createApi({
reducerPath: 'gameApi',
baseQuery: customBaseQuery,
endpoints: (builder) => ({
getGameInfo: builder.query<GameInfo, void>({
query: () => {return {method: 'info', params: {}}},
}),
loadLevel: builder.query<LevelInfo, {world: string, level: number}>({
query: ({world, level}) => {return {method: "loadLevel", params: {world, level}}},
}),
}),
})
// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetGameInfoQuery, useLoadLevelQuery } = apiSlice
+30
View File
@@ -0,0 +1,30 @@
import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
interface ProgressState {
code: {[world: string]: {[level: number]: string}}
}
const initialState = { code: {} } as ProgressState
export const progressSlice = createSlice({
name: 'progress',
initialState,
reducers: {
codeEdited(state, action: PayloadAction<{world: string, level: number, code: string}>) {
if (!state.code[action.payload.world]) {
state.code[action.payload.world] = {}
}
state.code[action.payload.world][action.payload.level] = action.payload.code
},
}
})
export function selectCode(world: string, level: number) {
return (state) => {
if (!state.progress.code[world]) { return undefined }
state.progress.code[world][level];
}
}
export const { codeEdited } = progressSlice.actions
+24
View File
@@ -0,0 +1,24 @@
import { configureStore } from '@reduxjs/toolkit';
import { connection } from '../connection'
import thunkMiddleware from 'redux-thunk'
import { apiSlice } from './api'
import { progressSlice } from './progress'
export const store = configureStore({
reducer: {
[apiSlice.reducerPath]: apiSlice.reducer,
[progressSlice.name]: progressSlice.reducer,
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
thunk: {
extraArgument: { connection }
}
}).concat(apiSlice.middleware),
});
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch