diff --git a/src/app/listener.middleware/handler.footprint.ts b/src/app/listener.middleware/handler.footprint.ts index f2dad10b..cad4f030 100644 --- a/src/app/listener.middleware/handler.footprint.ts +++ b/src/app/listener.middleware/handler.footprint.ts @@ -39,6 +39,12 @@ export default async function handler({ operation, data = {}, payload }: Params) await table?.setItem("readUsers", data.readUsers); } break; + case "updateAutoDeleteSetting": + { + await table?.setItem("autoDeleteMsgUsers", data.autoDeleteMsgUsers || []); + await table?.setItem("autoDeleteMsgChannels", data.autoDeleteMsgChannels || []); + } + break; default: break; } diff --git a/src/app/services/user.ts b/src/app/services/user.ts index 5000eadc..b966e0c2 100644 --- a/src/app/services/user.ts +++ b/src/app/services/user.ts @@ -1,7 +1,7 @@ import { createApi } from "@reduxjs/toolkit/query/react"; // import toast from "react-hot-toast"; import baseQuery from "./base.query"; -import { updateMute } from "../slices/footprint"; +import { updateAutoDeleteSetting, updateMute } from "../slices/footprint"; import { fillUsers } from "../slices/users"; import BASE_URL, { ContentTypes } from "../config"; import { onMessageSendStarted } from "./handlers"; @@ -59,7 +59,22 @@ export const userApi = createApi({ url: `/user/burn-after-reading`, body: data, method: "POST" - }) + }), + async onQueryStarted(data, { dispatch, queryFulfilled }) { + try { + await queryFulfilled; + if (data.users) { + // users + dispatch(updateAutoDeleteSetting({ burn_after_reading_users: data.users })); + } + if (data.groups) { + // channel + dispatch(updateAutoDeleteSetting({ burn_after_reading_groups: data.groups })); + } + } catch { + console.log("update auto delete message setting error"); + } + } }), updateMuteSetting: builder.mutation({ diff --git a/src/app/slices/footprint.ts b/src/app/slices/footprint.ts index fedac02e..4fb19395 100644 --- a/src/app/slices/footprint.ts +++ b/src/app/slices/footprint.ts @@ -1,5 +1,6 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { MuteDTO } from "../../types/message"; +import { AutoDeleteMessageSettingDTO, AutoDeleteMsgForGroup, AutoDeleteMsgForUser, AutoDeleteSettingForChannels, AutoDeleteSettingForUsers } from "../../types/sse"; export interface State { usersVersion: number; @@ -8,6 +9,8 @@ export interface State { readChannels: { [gid: number]: number }; muteUsers: { [uid: number]: { expired_in?: number } | undefined }; muteChannels: { [gid: number]: { expired_in?: number } | undefined }; + autoDeleteMsgUsers: AutoDeleteMsgForUser[]; + autoDeleteMsgChannels: AutoDeleteMsgForGroup[]; } const initialState: State = { @@ -16,7 +19,9 @@ const initialState: State = { readUsers: {}, readChannels: {}, muteUsers: {}, - muteChannels: {} + muteChannels: {}, + autoDeleteMsgUsers: [], + autoDeleteMsgChannels: [], }; const footprintSlice = createSlice({ @@ -33,7 +38,9 @@ const footprintSlice = createSlice({ readUsers = {}, readChannels = {}, muteUsers = {}, - muteChannels = {} + muteChannels = {}, + autoDeleteMsgUsers = [], + autoDeleteMsgChannels = [] } = action.payload; return { usersVersion, @@ -41,7 +48,9 @@ const footprintSlice = createSlice({ readUsers, readChannels, muteUsers, - muteChannels + muteChannels, + autoDeleteMsgUsers, + autoDeleteMsgChannels }; }, updateUsersVersion(state, action: PayloadAction) { @@ -50,6 +59,45 @@ const footprintSlice = createSlice({ updateAfterMid(state, action: PayloadAction) { state.afterMid = action.payload; }, + updateAutoDeleteSetting(state, action: PayloadAction) { + const payload = action.payload; + Object.keys(payload).forEach((key) => { + switch (key) { + case "burn_after_reading_users": { + const updates = (payload as AutoDeleteSettingForUsers).burn_after_reading_users; + updates.map(item => { + const { uid } = item; + const idx = state.autoDeleteMsgUsers.findIndex(tmp => tmp.uid == uid); + if (idx !== -1) { + // update + state.autoDeleteMsgUsers[idx] = item; + } else { + // add + state.autoDeleteMsgUsers.push(item); + } + }); + break; + } + case "burn_after_reading_groups": { + const updates = (payload as AutoDeleteSettingForChannels).burn_after_reading_groups; + updates.map(item => { + const { gid } = item; + const idx = state.autoDeleteMsgChannels.findIndex(tmp => tmp.gid == gid); + if (idx !== -1) { + // update + state.autoDeleteMsgChannels[idx] = item; + } else { + // add + state.autoDeleteMsgChannels.push(item); + } + }); + break; + } + default: + break; + } + }); + }, updateMute(state, action: PayloadAction) { const payload = action.payload || {}; Object.keys(payload).forEach((key) => { @@ -111,7 +159,8 @@ export const { updateUsersVersion, updateReadChannels, updateReadUsers, - updateMute + updateMute, + updateAutoDeleteSetting } = footprintSlice.actions; export default footprintSlice.reducer; diff --git a/src/common/component/AutoDeleteMessages.tsx b/src/common/component/AutoDeleteMessages.tsx index 7f3db32d..bb47d113 100644 --- a/src/common/component/AutoDeleteMessages.tsx +++ b/src/common/component/AutoDeleteMessages.tsx @@ -3,6 +3,7 @@ import { toast } from 'react-hot-toast'; import { useTranslation } from "react-i18next"; import { useUpdateAutoDeleteMsgMutation } from "../../app/services/user"; +import { useAppSelector } from '../../app/store'; import SaveTip from "./SaveTip"; import StyledRadio from "./styled/Radio"; @@ -10,11 +11,15 @@ import StyledRadio from "./styled/Radio"; type Props = { id: number, type?: "user" | "channel", - expires_in?: number + // expires_in?: number } -const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) => { +const AutoDeleteMessages = ({ id, type = "channel" }: Props) => { + const setting = useAppSelector(store => type == "channel" ? + store.footprint.autoDeleteMsgChannels.find(item => item.gid == id) + : + store.footprint.autoDeleteMsgUsers.find(item => item.uid == id)); const [updateSetting, { isSuccess }] = useUpdateAutoDeleteMsgMutation(); - const [value, setValue] = useState(expires_in); + const [value, setValue] = useState(setting?.expires_in ?? 0); const { t } = useTranslation("setting", { keyPrefix: "auto_delete_msg" }); const options = [ { title: t("off"), value: 0 }, @@ -29,7 +34,7 @@ const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) => updateSetting(dto); }; const handleReset = () => { - setValue(expires_in); + setValue(setting?.expires_in ?? 0); }; const handleChange = (val: number) => { setValue(val); @@ -39,7 +44,7 @@ const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) => toast.success("Update Successfully!"); } }, [isSuccess]); - + const originalVal = setting?.expires_in ?? 0; return (
@@ -50,11 +55,11 @@ const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) => title)} values={options.map(({ value }) => value)} - value={value} + value={value || 0} onChange={handleChange} />
- {expires_in !== value && } + {originalVal !== value && }
); }; diff --git a/src/common/hook/useStreaming/index.ts b/src/common/hook/useStreaming/index.ts index 93878fc0..541d92b6 100644 --- a/src/common/hook/useStreaming/index.ts +++ b/src/common/hook/useStreaming/index.ts @@ -13,7 +13,8 @@ import { updateUsersVersion, updateReadChannels, updateReadUsers, - updateMute + updateMute, + updateAutoDeleteSetting } from "../../../app/slices/footprint"; import { updateUsersByLogs, updateUsersStatus } from "../../../app/slices/users"; import { resetAuthData, updateLoginUser } from "../../../app/slices/auth.data"; @@ -179,6 +180,22 @@ export default function useStreaming() { } } break; + case "burn_after_reading_users": + { + const arr = data[key]; + if (arr) { + dispatch(updateAutoDeleteSetting({ burn_after_reading_users: arr })); + } + } + break; + case "burn_after_reading_groups": + { + const arr = data[key]; + if (arr) { + dispatch(updateAutoDeleteSetting({ burn_after_reading_groups: arr })); + } + } + break; default: break; diff --git a/src/routes/settingChannel/AutoDeleteMessages.tsx b/src/routes/settingChannel/AutoDeleteMessages.tsx deleted file mode 100644 index 70a37ddd..00000000 --- a/src/routes/settingChannel/AutoDeleteMessages.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useState, useEffect } from 'react'; -import { toast } from 'react-hot-toast'; - -import { useTranslation } from "react-i18next"; -import { useUpdateAutoDeleteMsgMutation } from "../../app/services/user"; -import SaveTip from "../../common/component/SaveTip"; -import StyledRadio from "../../common/component/styled/Radio"; - - -type Props = { - id: number, - type?: "user" | "channel", - expires_in?: number -} -const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) => { - const [updateSetting, { isSuccess }] = useUpdateAutoDeleteMsgMutation(); - const [value, setValue] = useState(expires_in); - const { t } = useTranslation("setting", { keyPrefix: "auto_delete_msg" }); - const options = [ - { title: t("off"), value: 0 }, - { title: t("30_seconds"), value: 30 }, - { title: t("10_min"), value: 10 * 60 }, - { title: t("1_hour"), value: 60 * 60 }, - { title: t("1_day"), value: 24 * 60 * 60 }, - { title: t("1_week"), value: 7 * 24 * 60 * 60 }, - ]; - const handleSave = () => { - const dto = type == "user" ? { users: [{ uid: id, expires_in: value }] } : { groups: [{ gid: id, expires_in: value }] }; - updateSetting(dto); - }; - const handleReset = () => { - setValue(expires_in); - }; - const handleChange = (val: number) => { - setValue(val); - }; - useEffect(() => { - if (isSuccess) { - toast.success("Update Successfully!"); - } - }, [isSuccess]); - - return ( -
-
-

{t("title")}

-

{t("desc")}

-
-
- title)} - values={options.map(({ value }) => value)} - value={value} - onChange={handleChange} - /> -
- {expires_in !== value && } -
- ); -}; - -export default AutoDeleteMessages; \ No newline at end of file diff --git a/src/routes/settingChannel/navs.tsx b/src/routes/settingChannel/navs.tsx index b87719f7..99a2e2b0 100644 --- a/src/routes/settingChannel/navs.tsx +++ b/src/routes/settingChannel/navs.tsx @@ -1,7 +1,7 @@ import { ReactNode } from "react"; import { useTranslation } from "react-i18next"; import Overview from "./Overview"; -import AutoDeleteMessages from './AutoDeleteMessages'; +import AutoDeleteMessages from '../../common/component/AutoDeleteMessages'; import ManageMembers from "../../common/component/ManageMembers"; export interface NavItem { diff --git a/src/types/sse.ts b/src/types/sse.ts index 68e4c76b..d80b3a7c 100644 --- a/src/types/sse.ts +++ b/src/types/sse.ts @@ -46,17 +46,28 @@ export interface MuteChannel { gid: number; expired_at: number; } - +export type AutoDeleteMsgForUser = { + uid: number; expires_in: number | null +} +export type AutoDeleteMsgForGroup = { + gid: number; expires_in: number | null +} export interface UserSettingsEvent { type: "user_settings"; mute_users?: MuteUser[]; mute_groups?: MuteChannel[]; read_index_users?: { uid: number; mid: number }[]; read_index_groups?: { gid: number; mid: number }[]; - burn_after_reading_users?: { uid: number; expires_in: number }[]; - burn_after_reading_groups?: { gid: number; expires_in: number }[]; + burn_after_reading_users?: AutoDeleteMsgForUser[]; + burn_after_reading_groups?: AutoDeleteMsgForGroup[]; } - +export type AutoDeleteSettingForUsers = { + burn_after_reading_users: AutoDeleteMsgForUser[] +} +export type AutoDeleteSettingForChannels = { + burn_after_reading_groups: AutoDeleteMsgForGroup[] +} +export type AutoDeleteMessageSettingDTO = AutoDeleteSettingForUsers | AutoDeleteSettingForChannels export interface UserSettingsChangedEvent { type: "user_settings_changed"; from_device?: string; @@ -66,8 +77,8 @@ export interface UserSettingsChangedEvent { remove_mute_groups?: number[]; read_index_users?: { uid: number; mid: number }[]; read_index_groups?: { gid: number; mid: number }[]; - burn_after_reading_users?: { uid: number; expires_in: number }[]; - burn_after_reading_groups?: { gid: number; expires_in: number }[]; + burn_after_reading_users?: AutoDeleteMsgForUser[]; + burn_after_reading_groups?: AutoDeleteMsgForGroup[]; } export interface RelatedGroupsEvent {