Redux toolkit (#115)
* add @redux/toolkit * bump react version to allow for hooks * add remote-redux devtools to help track extension state * add remote-redux server to allow for remote state viewing * setup react-redux for current user * setup watch mode for running redux remote dev watch to options * move screenshots
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { SuccessOrFailType } from '../config';
|
||||
import { SuccessOrFailType } from '../config/config';
|
||||
interface AlertProps {
|
||||
text: string;
|
||||
type: SuccessOrFailType;
|
||||
|
||||
@@ -2,7 +2,7 @@ import axios, { AxiosResponse } from 'axios';
|
||||
import moment from 'moment';
|
||||
import { Tabs } from 'webextension-polyfill-ts';
|
||||
import { User } from '../types/user';
|
||||
import config from '../config';
|
||||
import config from '../config/config';
|
||||
import { SummariesPayload, GrandTotal } from '../types/summaries';
|
||||
|
||||
class WakaTimeCore {
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import createStore from './stores/createStore';
|
||||
import checkCurrentUser from './utils/checkCurrentUser';
|
||||
const container = document.getElementById('wakatime');
|
||||
|
||||
const store = createStore('WakaTime-Options');
|
||||
checkCurrentUser(store)(30 * 1000);
|
||||
|
||||
const openOptions = async (): Promise<void> => {
|
||||
await browser.runtime.openOptionsPage();
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<>
|
||||
<Provider store={store}>
|
||||
<h1>POPUP GO HERE</h1>
|
||||
<div onClick={openOptions}>Open options</div>
|
||||
</>,
|
||||
</Provider>,
|
||||
container,
|
||||
);
|
||||
|
||||
37
src/reducers/currentUser.ts
Normal file
37
src/reducers/currentUser.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import axios, { AxiosResponse } from 'axios';
|
||||
import { User, UserPayload } from '../types/user';
|
||||
import config from '../config/config';
|
||||
|
||||
type NameType = 'currentUser';
|
||||
export const name: NameType = 'currentUser';
|
||||
|
||||
export const fetchCurrentUser = createAsyncThunk<User, undefined>(`[${name}]`, async () => {
|
||||
const userPayload: AxiosResponse<UserPayload> = await axios.get(config.currentUserApiUrl);
|
||||
return userPayload.data.data;
|
||||
});
|
||||
|
||||
export interface CurrentUser {
|
||||
error?: unknown;
|
||||
pending?: boolean;
|
||||
user?: User;
|
||||
}
|
||||
export const initialState: CurrentUser = {};
|
||||
|
||||
const currentUser = createSlice({
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(fetchCurrentUser.fulfilled, (state, { payload }) => {
|
||||
state.user = payload;
|
||||
});
|
||||
builder.addCase(fetchCurrentUser.rejected, (state, { error }) => {
|
||||
state.user = undefined;
|
||||
state.error = error;
|
||||
});
|
||||
},
|
||||
initialState,
|
||||
name,
|
||||
reducers: {},
|
||||
});
|
||||
|
||||
export const actions = currentUser.actions;
|
||||
export default currentUser.reducer;
|
||||
41
src/stores/createStore.ts
Normal file
41
src/stores/createStore.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { configureStore, Store } from '@reduxjs/toolkit';
|
||||
import logger from 'redux-logger';
|
||||
import { reduxBatch } from '@manaflair/redux-batch';
|
||||
import devToolsEnhancer from 'remote-redux-devtools';
|
||||
import currentUserReducer, {
|
||||
initialState as InitalCurrentUser,
|
||||
CurrentUser,
|
||||
} from '../reducers/currentUser';
|
||||
import isProd from '../utils/isProd';
|
||||
|
||||
export interface RootState {
|
||||
currentUser: CurrentUser;
|
||||
}
|
||||
|
||||
const preloadedState: RootState = {
|
||||
currentUser: InitalCurrentUser,
|
||||
};
|
||||
|
||||
export type RootStore = Store<RootState>;
|
||||
export default (appName: string): RootStore => {
|
||||
const enhancers = [reduxBatch];
|
||||
if (!isProd()) {
|
||||
enhancers.push(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
devToolsEnhancer({ hostname: 'localhost', name: appName, port: 8000, realtime: true }),
|
||||
);
|
||||
}
|
||||
const store = configureStore({
|
||||
devTools: true,
|
||||
enhancers,
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
|
||||
preloadedState,
|
||||
reducer: {
|
||||
currentUser: currentUserReducer,
|
||||
},
|
||||
});
|
||||
|
||||
return store;
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { browser } from 'webextension-polyfill-ts';
|
||||
import config from '../config';
|
||||
import config from '../config/config';
|
||||
|
||||
type ColorIconTypes = 'gray' | 'red' | 'white' | '';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import config, { ApiStates } from '../config';
|
||||
import config, { ApiStates } from '../config/config';
|
||||
|
||||
import changeExtensionIcon from './changeExtensionIcon';
|
||||
import changeExtensionTooltip from './changeExtensionTooltip';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { browser } from 'webextension-polyfill-ts';
|
||||
import config from '../config';
|
||||
import config from '../config/config';
|
||||
|
||||
/**
|
||||
* It changes the extension title
|
||||
|
||||
16
src/utils/checkCurrentUser.ts
Normal file
16
src/utils/checkCurrentUser.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { RootStore } from '../stores/createStore';
|
||||
import { fetchCurrentUser } from '../reducers/currentUser';
|
||||
|
||||
type unsub = () => void;
|
||||
export default (store: RootStore) => (time: number): unsub => {
|
||||
const fetchUser = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
store.dispatch(fetchCurrentUser());
|
||||
};
|
||||
fetchUser();
|
||||
const timeout = setInterval(fetchUser, time);
|
||||
return () => {
|
||||
clearInterval(timeout);
|
||||
};
|
||||
};
|
||||
1
src/utils/isProd.ts
Normal file
1
src/utils/isProd.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default (): boolean => process.env.NODE_ENV !== 'development';
|
||||
Reference in New Issue
Block a user