web: add redux store
This commit is contained in:
parent
51ffb6fe71
commit
d26ef10958
6 changed files with 151 additions and 0 deletions
73
package-lock.json
generated
73
package-lock.json
generated
|
@ -10,6 +10,7 @@
|
|||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@lit/localize": "^0.11.4",
|
||||
"@reduxjs/toolkit": "^1.9.1",
|
||||
"bootstrap-icons": "^1.10.2",
|
||||
"lit": "^2.4.1",
|
||||
"redux": "^4.2.0"
|
||||
|
@ -280,6 +281,29 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@reduxjs/toolkit": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.1.tgz",
|
||||
"integrity": "sha512-HikrdY+IDgRfRYlCTGUQaiCxxDDgM1mQrRbZ6S1HFZX5ZYuJ4o8EstNmhTwHdPl2rTmLxzwSu0b3AyeyTlR+RA==",
|
||||
"dependencies": {
|
||||
"immer": "^9.0.16",
|
||||
"redux": "^4.2.0",
|
||||
"redux-thunk": "^2.4.2",
|
||||
"reselect": "^4.1.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17.0.0 || ^18",
|
||||
"react-redux": "^7.2.1 || ^8.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-redux": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@types/accepts": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
|
||||
|
@ -2036,6 +2060,15 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immer": {
|
||||
"version": "9.0.16",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
|
||||
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
}
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -2884,6 +2917,14 @@
|
|||
"@babel/runtime": "^7.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/redux-thunk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
|
||||
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
|
||||
"peerDependencies": {
|
||||
"redux": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
|
@ -2901,6 +2942,11 @@
|
|||
"url": "https://github.com/sponsors/mysticatea"
|
||||
}
|
||||
},
|
||||
"node_modules/reselect": {
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
|
||||
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
|
@ -3697,6 +3743,17 @@
|
|||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@reduxjs/toolkit": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.1.tgz",
|
||||
"integrity": "sha512-HikrdY+IDgRfRYlCTGUQaiCxxDDgM1mQrRbZ6S1HFZX5ZYuJ4o8EstNmhTwHdPl2rTmLxzwSu0b3AyeyTlR+RA==",
|
||||
"requires": {
|
||||
"immer": "^9.0.16",
|
||||
"redux": "^4.2.0",
|
||||
"redux-thunk": "^2.4.2",
|
||||
"reselect": "^4.1.7"
|
||||
}
|
||||
},
|
||||
"@types/accepts": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
|
||||
|
@ -5023,6 +5080,11 @@
|
|||
"integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==",
|
||||
"dev": true
|
||||
},
|
||||
"immer": {
|
||||
"version": "9.0.16",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
|
||||
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -5666,6 +5728,12 @@
|
|||
"@babel/runtime": "^7.9.2"
|
||||
}
|
||||
},
|
||||
"redux-thunk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
|
||||
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
|
@ -5677,6 +5745,11 @@
|
|||
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
|
||||
"dev": true
|
||||
},
|
||||
"reselect": {
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
|
||||
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@lit/localize": "^0.11.4",
|
||||
"@reduxjs/toolkit": "^1.9.1",
|
||||
"bootstrap-icons": "^1.10.2",
|
||||
"lit": "^2.4.1",
|
||||
"redux": "^4.2.0"
|
||||
|
|
24
src/web/actions/app.ts
Normal file
24
src/web/actions/app.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import {Action} from "redux";
|
||||
|
||||
import {ActionCreator} from "../types";
|
||||
|
||||
export type ModalName = "compose" | "notifications";
|
||||
|
||||
export interface OpenModalAppAction extends Action<"app/openModal"> {
|
||||
id: ModalName,
|
||||
}
|
||||
|
||||
export type CloseModalAppAction = Action<"app/closeModal">;
|
||||
|
||||
export type AppAction
|
||||
= OpenModalAppAction
|
||||
| CloseModalAppAction;
|
||||
|
||||
export const openModal: ActionCreator<OpenModalAppAction, [ModalName]> = (id) => ({
|
||||
type: "app/openModal",
|
||||
id,
|
||||
});
|
||||
|
||||
export const closeModal: ActionCreator<CloseModalAppAction> = () => ({
|
||||
type: "app/closeModal",
|
||||
});
|
29
src/web/reducers/app.ts
Normal file
29
src/web/reducers/app.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import {Reducer} from "redux";
|
||||
|
||||
import {ModalName} from "../actions/app";
|
||||
import {RootAction} from "../store";
|
||||
|
||||
export interface AppState {
|
||||
modal: ModalName | null;
|
||||
}
|
||||
|
||||
const INITIAL_STATE: AppState = {
|
||||
modal: null,
|
||||
};
|
||||
|
||||
export const appReducer: Reducer<AppState, RootAction> = (state = INITIAL_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case "app/openModal":
|
||||
return {
|
||||
modal: action.id,
|
||||
...state
|
||||
};
|
||||
case "app/closeModal":
|
||||
return {
|
||||
modal: null,
|
||||
...state
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
17
src/web/store.ts
Normal file
17
src/web/store.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {configureStore, Store} from "@reduxjs/toolkit";
|
||||
|
||||
import {AppAction} from "./actions/app";
|
||||
import {appReducer, AppState} from "./reducers/app";
|
||||
|
||||
export interface RootState {
|
||||
app?: AppState;
|
||||
}
|
||||
|
||||
export type RootAction = AppAction;
|
||||
|
||||
const store: Store<RootState, RootAction> = configureStore({
|
||||
reducer: {
|
||||
app: appReducer,
|
||||
},
|
||||
});
|
||||
export default store;
|
7
src/web/types.ts
Normal file
7
src/web/types.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import {Action} from "redux";
|
||||
|
||||
/**
|
||||
* The `ActionCreator` type provided by redux sucks balls
|
||||
* because its params are `any[]`, so here is our own one
|
||||
*/
|
||||
export type ActionCreator<A extends Action, P extends any[] = []> = (...params: P) => A;
|
Loading…
Reference in a new issue