refactor: add typescript support to project
This commit is contained in:
@@ -3,6 +3,7 @@ import { nanoid } from "@reduxjs/toolkit";
|
||||
import baseQuery from "./base.query";
|
||||
import { setAuthData, updateToken, resetAuthData, updateInitialized } from "../slices/auth.data";
|
||||
import BASE_URL, { KEY_DEVICE_KEY } from "../config";
|
||||
|
||||
const getDeviceId = () => {
|
||||
let d = localStorage.getItem(KEY_DEVICE_KEY);
|
||||
if (!d) {
|
||||
@@ -11,6 +12,7 @@ const getDeviceId = () => {
|
||||
}
|
||||
return d;
|
||||
};
|
||||
|
||||
export const authApi = createApi({
|
||||
reducerPath: "authApi",
|
||||
baseQuery,
|
||||
@@ -1,24 +1,59 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
import { KEY_PWA_INSTALLED, KEY_REFRESH_TOKEN, KEY_TOKEN, KEY_UID, KEY_EXPIRE } from "../config";
|
||||
const initialState = {
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { KEY_EXPIRE, KEY_PWA_INSTALLED, KEY_REFRESH_TOKEN, KEY_TOKEN, KEY_UID } from '../config';
|
||||
|
||||
interface State {
|
||||
initialized: boolean;
|
||||
uid: string | null;
|
||||
token: string | null;
|
||||
expireTime: string | number; // todo
|
||||
refreshToken: string | null;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
initialized: true,
|
||||
uid: null,
|
||||
token: localStorage.getItem(KEY_TOKEN),
|
||||
expireTime: localStorage.getItem(KEY_EXPIRE) || +new Date(),
|
||||
refreshToken: localStorage.getItem(KEY_REFRESH_TOKEN)
|
||||
};
|
||||
const emptyState = {
|
||||
|
||||
const emptyState: State = {
|
||||
initialized: true,
|
||||
uid: null,
|
||||
token: null,
|
||||
expireTime: +new Date(),
|
||||
refreshToken: null
|
||||
};
|
||||
|
||||
interface AuthToken {
|
||||
// common
|
||||
server_id: string;
|
||||
token: string;
|
||||
refresh_token: string;
|
||||
expired_in: number;
|
||||
}
|
||||
|
||||
interface User {
|
||||
uid: number;
|
||||
email: string;
|
||||
name: string;
|
||||
gender: number;
|
||||
language: string;
|
||||
is_admin: boolean;
|
||||
avatar_updated_at: number;
|
||||
create_by: string;
|
||||
}
|
||||
|
||||
interface AuthData extends AuthToken {
|
||||
initialized?: boolean;
|
||||
user: User;
|
||||
}
|
||||
|
||||
const authDataSlice = createSlice({
|
||||
name: "authData",
|
||||
name: 'authData',
|
||||
initialState,
|
||||
reducers: {
|
||||
setAuthData(state, action) {
|
||||
setAuthData(state, action: PayloadAction<AuthData>) {
|
||||
const {
|
||||
initialized = true,
|
||||
user: { uid },
|
||||
@@ -27,21 +62,21 @@ const authDataSlice = createSlice({
|
||||
expired_in = 0
|
||||
} = action.payload;
|
||||
state.initialized = initialized;
|
||||
state.uid = uid;
|
||||
state.uid = `${uid}`;
|
||||
state.token = token;
|
||||
state.refreshToken = refresh_token;
|
||||
// 当前时间往后推expire时长
|
||||
console.log("expire", expired_in);
|
||||
console.log('expire', expired_in);
|
||||
const expireTime = +new Date() + Number(expired_in) * 1000;
|
||||
state.expireTime = expireTime;
|
||||
// set local data
|
||||
localStorage.setItem(KEY_EXPIRE, expireTime);
|
||||
localStorage.setItem(KEY_EXPIRE, `${expireTime}`);
|
||||
localStorage.setItem(KEY_TOKEN, token);
|
||||
localStorage.setItem(KEY_REFRESH_TOKEN, refresh_token);
|
||||
localStorage.setItem(KEY_UID, uid);
|
||||
localStorage.setItem(KEY_UID, `${uid}`);
|
||||
},
|
||||
resetAuthData() {
|
||||
console.log("clear auth data");
|
||||
console.log('clear auth data');
|
||||
// remove local data
|
||||
localStorage.removeItem(KEY_EXPIRE);
|
||||
localStorage.removeItem(KEY_TOKEN);
|
||||
@@ -51,28 +86,27 @@ const authDataSlice = createSlice({
|
||||
|
||||
return emptyState;
|
||||
},
|
||||
setUid(state, action) {
|
||||
const uid = action.payload;
|
||||
state.uid = uid;
|
||||
console.log("set uid orginal");
|
||||
setUid(state, action: PayloadAction<string>) {
|
||||
state.uid = action.payload;
|
||||
console.log('set uid original');
|
||||
},
|
||||
updateInitialized(state, action) {
|
||||
const isInitialized = action.payload;
|
||||
state.initialized = isInitialized;
|
||||
updateInitialized(state, action: PayloadAction<boolean>) {
|
||||
state.initialized = action.payload;
|
||||
},
|
||||
updateToken(state, action) {
|
||||
updateToken(state, action: PayloadAction<AuthToken>) {
|
||||
const { token, refresh_token, expired_in } = action.payload;
|
||||
console.log("refresh token");
|
||||
console.log('refresh token');
|
||||
state.token = token;
|
||||
const et = +new Date() + Number(expired_in) * 1000;
|
||||
state.expireTime = et;
|
||||
state.refreshToken = refresh_token;
|
||||
localStorage.setItem(KEY_EXPIRE, et);
|
||||
localStorage.setItem(KEY_EXPIRE, `${et}`);
|
||||
localStorage.setItem(KEY_TOKEN, token);
|
||||
localStorage.setItem(KEY_REFRESH_TOKEN, refresh_token);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const { updateInitialized, setAuthData, resetAuthData, setUid, updateToken } =
|
||||
authDataSlice.actions;
|
||||
export default authDataSlice.reducer;
|
||||
@@ -1,112 +0,0 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
import BASE_URL from "../config";
|
||||
import { getNonNullValues } from "../../common/utils";
|
||||
const initialState = {
|
||||
ids: [],
|
||||
byId: {}
|
||||
};
|
||||
const channelsSlice = createSlice({
|
||||
name: `channels`,
|
||||
initialState,
|
||||
reducers: {
|
||||
resetChannels() {
|
||||
return initialState;
|
||||
},
|
||||
fullfillChannels(state, action) {
|
||||
console.log("set channels store", state);
|
||||
const chs = action.payload || [];
|
||||
state.ids = chs.map(({ gid }) => +gid);
|
||||
state.byId = Object.fromEntries(
|
||||
chs.map((c) => {
|
||||
const { gid, avatar_updated_at } = c;
|
||||
c.icon =
|
||||
avatar_updated_at == 0
|
||||
? ""
|
||||
: `${BASE_URL}/resource/group_avatar?gid=${gid}&t=${avatar_updated_at}`;
|
||||
return [gid, c];
|
||||
})
|
||||
);
|
||||
},
|
||||
addChannel(state, action) {
|
||||
// console.log("set channels store", action);
|
||||
const ch = action.payload;
|
||||
const { gid, avatar_updated_at } = ch;
|
||||
if (!state.ids.includes(+gid)) {
|
||||
state.ids.push(+gid);
|
||||
}
|
||||
state.byId[gid] = {
|
||||
...ch,
|
||||
icon:
|
||||
avatar_updated_at == 0
|
||||
? ""
|
||||
: `${BASE_URL}/resource/group_avatar?gid=${gid}&t=${avatar_updated_at}`
|
||||
};
|
||||
},
|
||||
updateChannel(state, action) {
|
||||
const ignoreInPublic = ["add_member", "remove_member"];
|
||||
const { id, operation, members = [], ...rest } = action.payload;
|
||||
const currChannel = state.byId[id];
|
||||
if (!currChannel || (currChannel.is_public && ignoreInPublic.includes(operation))) return;
|
||||
switch (operation) {
|
||||
case "remove_member":
|
||||
{
|
||||
const filtered = state.byId[id].members.filter(
|
||||
(id) => members.findIndex((uid) => uid == id) == -1
|
||||
);
|
||||
state.byId[id].members = filtered;
|
||||
}
|
||||
break;
|
||||
case "add_member":
|
||||
{
|
||||
const currs = state.byId[id].members;
|
||||
const _set = new Set([...currs, ...members]);
|
||||
console.log("add member to channel", [..._set]);
|
||||
state.byId[id].members = [..._set];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
state.byId[id] = { ...state.byId[id], ...getNonNullValues(rest) };
|
||||
break;
|
||||
}
|
||||
},
|
||||
updatePinMessage(state, action) {
|
||||
const { gid, mid, msg } = action.payload;
|
||||
let msgs = state.byId[gid]?.pinned_messages;
|
||||
if (!msgs) return;
|
||||
if (msg) {
|
||||
if (!msgs) {
|
||||
msgs = [msg];
|
||||
} else {
|
||||
const idx = msgs.findIndex((msg) => msg.mid == mid);
|
||||
if (idx > -1) {
|
||||
msgs.splice(idx, 1);
|
||||
}
|
||||
msgs.push(msg);
|
||||
}
|
||||
} else {
|
||||
// remove
|
||||
const idx = msgs.findIndex((msg) => msg.mid == mid);
|
||||
if (idx > -1) {
|
||||
msgs.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
removeChannel(state, action) {
|
||||
const gid = action.payload;
|
||||
const idx = state.ids.findIndex((i) => i == gid);
|
||||
if (idx > -1) {
|
||||
state.ids.splice(idx, 1);
|
||||
delete state.byId[gid];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
export const {
|
||||
updatePinMessage,
|
||||
resetChannels,
|
||||
fullfillChannels,
|
||||
addChannel,
|
||||
updateChannel,
|
||||
removeChannel
|
||||
} = channelsSlice.actions;
|
||||
export default channelsSlice.reducer;
|
||||
@@ -0,0 +1,121 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import BASE_URL from '../config';
|
||||
import { getNonNullValues } from '../../common/utils';
|
||||
import { Channel, UpdateChannelDTO, UpdatePinnedMessageDTO } from '../../types/channel';
|
||||
|
||||
interface State {
|
||||
ids: number[];
|
||||
byId: { [id: number]: Channel | undefined };
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
ids: [],
|
||||
byId: {}
|
||||
};
|
||||
|
||||
const channelsSlice = createSlice({
|
||||
name: `channels`,
|
||||
initialState,
|
||||
reducers: {
|
||||
resetChannels() {
|
||||
return initialState;
|
||||
},
|
||||
fullfillChannels(state, action: PayloadAction<Channel[]>) {
|
||||
const channels = action.payload || [];
|
||||
state.ids = channels.map(({ gid }) => gid);
|
||||
state.byId = Object.fromEntries(
|
||||
channels.map((c) => {
|
||||
const { gid, avatar_updated_at } = c;
|
||||
c.icon =
|
||||
avatar_updated_at == 0
|
||||
? ''
|
||||
: `${BASE_URL}/resource/group_avatar?gid=${gid}&t=${avatar_updated_at}`;
|
||||
return [gid, c];
|
||||
})
|
||||
);
|
||||
},
|
||||
addChannel(state, action: PayloadAction<Channel>) {
|
||||
const ch = action.payload;
|
||||
const { gid, avatar_updated_at } = ch;
|
||||
if (!state.ids.includes(+gid)) {
|
||||
state.ids.push(+gid);
|
||||
}
|
||||
state.byId[gid] = {
|
||||
...ch,
|
||||
icon:
|
||||
avatar_updated_at == 0
|
||||
? ''
|
||||
: `${BASE_URL}/resource/group_avatar?gid=${gid}&t=${avatar_updated_at}`
|
||||
};
|
||||
},
|
||||
updateChannel(state, action: PayloadAction<UpdateChannelDTO>) {
|
||||
const ignoreInPublic = ['add_member', 'remove_member'];
|
||||
const { gid, operation, members = [], ...rest } = action.payload;
|
||||
const currChannel = state.byId[gid];
|
||||
if (
|
||||
!currChannel ||
|
||||
(currChannel.is_public && ignoreInPublic.includes(operation))
|
||||
) return;
|
||||
switch (operation) {
|
||||
case 'remove_member': {
|
||||
state.byId[gid]!.members = state.byId[gid]!.members.filter(
|
||||
(id) => members.findIndex((uid) => uid == id) == -1
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'add_member': {
|
||||
const currs = state.byId[gid]!.members;
|
||||
const _set = new Set([...currs, ...members]);
|
||||
state.byId[gid]!.members = Array.from(_set);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
state.byId[gid] = { ...state.byId[gid]!, ...getNonNullValues(rest) };
|
||||
break;
|
||||
}
|
||||
},
|
||||
updatePinMessage(state, action: PayloadAction<UpdatePinnedMessageDTO>) {
|
||||
const { gid, mid, msg } = action.payload;
|
||||
let pinnedMessages = state.byId[gid]?.pinned_messages;
|
||||
// add
|
||||
if (msg) {
|
||||
if (!pinnedMessages) {
|
||||
pinnedMessages = [msg];
|
||||
} else {
|
||||
const idx = pinnedMessages.findIndex((msg) => msg.mid == mid);
|
||||
if (idx > -1) {
|
||||
pinnedMessages.splice(idx, 1);
|
||||
}
|
||||
pinnedMessages.push(msg);
|
||||
}
|
||||
} else {
|
||||
// remove
|
||||
if (pinnedMessages) {
|
||||
const idx = pinnedMessages.findIndex((m) => m.mid == mid);
|
||||
if (idx > -1) {
|
||||
pinnedMessages.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
removeChannel(state, action: PayloadAction<number>) {
|
||||
const gid = action.payload;
|
||||
const idx = state.ids.findIndex((i) => i == gid);
|
||||
if (idx > -1) {
|
||||
state.ids.splice(idx, 1);
|
||||
delete state.byId[gid];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const {
|
||||
updatePinMessage,
|
||||
resetChannels,
|
||||
fullfillChannels,
|
||||
addChannel,
|
||||
updateChannel,
|
||||
removeChannel
|
||||
} = channelsSlice.actions;
|
||||
|
||||
export default channelsSlice.reducer;
|
||||
Reference in New Issue
Block a user