feat: auto delete msg setting
This commit is contained in:
@@ -39,6 +39,12 @@ export default async function handler({ operation, data = {}, payload }: Params)
|
|||||||
await table?.setItem("readUsers", data.readUsers);
|
await table?.setItem("readUsers", data.readUsers);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "updateAutoDeleteSetting":
|
||||||
|
{
|
||||||
|
await table?.setItem("autoDeleteMsgUsers", data.autoDeleteMsgUsers || []);
|
||||||
|
await table?.setItem("autoDeleteMsgChannels", data.autoDeleteMsgChannels || []);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||||
// import toast from "react-hot-toast";
|
// import toast from "react-hot-toast";
|
||||||
import baseQuery from "./base.query";
|
import baseQuery from "./base.query";
|
||||||
import { updateMute } from "../slices/footprint";
|
import { updateAutoDeleteSetting, updateMute } from "../slices/footprint";
|
||||||
import { fillUsers } from "../slices/users";
|
import { fillUsers } from "../slices/users";
|
||||||
import BASE_URL, { ContentTypes } from "../config";
|
import BASE_URL, { ContentTypes } from "../config";
|
||||||
import { onMessageSendStarted } from "./handlers";
|
import { onMessageSendStarted } from "./handlers";
|
||||||
@@ -59,7 +59,22 @@ export const userApi = createApi({
|
|||||||
url: `/user/burn-after-reading`,
|
url: `/user/burn-after-reading`,
|
||||||
body: data,
|
body: data,
|
||||||
method: "POST"
|
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<void, MuteDTO>({
|
updateMuteSetting: builder.mutation<void, MuteDTO>({
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
import { MuteDTO } from "../../types/message";
|
import { MuteDTO } from "../../types/message";
|
||||||
|
import { AutoDeleteMessageSettingDTO, AutoDeleteMsgForGroup, AutoDeleteMsgForUser, AutoDeleteSettingForChannels, AutoDeleteSettingForUsers } from "../../types/sse";
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
usersVersion: number;
|
usersVersion: number;
|
||||||
@@ -8,6 +9,8 @@ export interface State {
|
|||||||
readChannels: { [gid: number]: number };
|
readChannels: { [gid: number]: number };
|
||||||
muteUsers: { [uid: number]: { expired_in?: number } | undefined };
|
muteUsers: { [uid: number]: { expired_in?: number } | undefined };
|
||||||
muteChannels: { [gid: number]: { expired_in?: number } | undefined };
|
muteChannels: { [gid: number]: { expired_in?: number } | undefined };
|
||||||
|
autoDeleteMsgUsers: AutoDeleteMsgForUser[];
|
||||||
|
autoDeleteMsgChannels: AutoDeleteMsgForGroup[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: State = {
|
const initialState: State = {
|
||||||
@@ -16,7 +19,9 @@ const initialState: State = {
|
|||||||
readUsers: {},
|
readUsers: {},
|
||||||
readChannels: {},
|
readChannels: {},
|
||||||
muteUsers: {},
|
muteUsers: {},
|
||||||
muteChannels: {}
|
muteChannels: {},
|
||||||
|
autoDeleteMsgUsers: [],
|
||||||
|
autoDeleteMsgChannels: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const footprintSlice = createSlice({
|
const footprintSlice = createSlice({
|
||||||
@@ -33,7 +38,9 @@ const footprintSlice = createSlice({
|
|||||||
readUsers = {},
|
readUsers = {},
|
||||||
readChannels = {},
|
readChannels = {},
|
||||||
muteUsers = {},
|
muteUsers = {},
|
||||||
muteChannels = {}
|
muteChannels = {},
|
||||||
|
autoDeleteMsgUsers = [],
|
||||||
|
autoDeleteMsgChannels = []
|
||||||
} = action.payload;
|
} = action.payload;
|
||||||
return {
|
return {
|
||||||
usersVersion,
|
usersVersion,
|
||||||
@@ -41,7 +48,9 @@ const footprintSlice = createSlice({
|
|||||||
readUsers,
|
readUsers,
|
||||||
readChannels,
|
readChannels,
|
||||||
muteUsers,
|
muteUsers,
|
||||||
muteChannels
|
muteChannels,
|
||||||
|
autoDeleteMsgUsers,
|
||||||
|
autoDeleteMsgChannels
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
updateUsersVersion(state, action: PayloadAction<number>) {
|
updateUsersVersion(state, action: PayloadAction<number>) {
|
||||||
@@ -50,6 +59,45 @@ const footprintSlice = createSlice({
|
|||||||
updateAfterMid(state, action: PayloadAction<number>) {
|
updateAfterMid(state, action: PayloadAction<number>) {
|
||||||
state.afterMid = action.payload;
|
state.afterMid = action.payload;
|
||||||
},
|
},
|
||||||
|
updateAutoDeleteSetting(state, action: PayloadAction<AutoDeleteMessageSettingDTO>) {
|
||||||
|
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<MuteDTO>) {
|
updateMute(state, action: PayloadAction<MuteDTO>) {
|
||||||
const payload = action.payload || {};
|
const payload = action.payload || {};
|
||||||
Object.keys(payload).forEach((key) => {
|
Object.keys(payload).forEach((key) => {
|
||||||
@@ -111,7 +159,8 @@ export const {
|
|||||||
updateUsersVersion,
|
updateUsersVersion,
|
||||||
updateReadChannels,
|
updateReadChannels,
|
||||||
updateReadUsers,
|
updateReadUsers,
|
||||||
updateMute
|
updateMute,
|
||||||
|
updateAutoDeleteSetting
|
||||||
} = footprintSlice.actions;
|
} = footprintSlice.actions;
|
||||||
|
|
||||||
export default footprintSlice.reducer;
|
export default footprintSlice.reducer;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { toast } from 'react-hot-toast';
|
|||||||
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useUpdateAutoDeleteMsgMutation } from "../../app/services/user";
|
import { useUpdateAutoDeleteMsgMutation } from "../../app/services/user";
|
||||||
|
import { useAppSelector } from '../../app/store';
|
||||||
import SaveTip from "./SaveTip";
|
import SaveTip from "./SaveTip";
|
||||||
import StyledRadio from "./styled/Radio";
|
import StyledRadio from "./styled/Radio";
|
||||||
|
|
||||||
@@ -10,11 +11,15 @@ import StyledRadio from "./styled/Radio";
|
|||||||
type Props = {
|
type Props = {
|
||||||
id: number,
|
id: number,
|
||||||
type?: "user" | "channel",
|
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 [updateSetting, { isSuccess }] = useUpdateAutoDeleteMsgMutation();
|
||||||
const [value, setValue] = useState(expires_in);
|
const [value, setValue] = useState<number>(setting?.expires_in ?? 0);
|
||||||
const { t } = useTranslation("setting", { keyPrefix: "auto_delete_msg" });
|
const { t } = useTranslation("setting", { keyPrefix: "auto_delete_msg" });
|
||||||
const options = [
|
const options = [
|
||||||
{ title: t("off"), value: 0 },
|
{ title: t("off"), value: 0 },
|
||||||
@@ -29,7 +34,7 @@ const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) =>
|
|||||||
updateSetting(dto);
|
updateSetting(dto);
|
||||||
};
|
};
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setValue(expires_in);
|
setValue(setting?.expires_in ?? 0);
|
||||||
};
|
};
|
||||||
const handleChange = (val: number) => {
|
const handleChange = (val: number) => {
|
||||||
setValue(val);
|
setValue(val);
|
||||||
@@ -39,7 +44,7 @@ const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) =>
|
|||||||
toast.success("Update Successfully!");
|
toast.success("Update Successfully!");
|
||||||
}
|
}
|
||||||
}, [isSuccess]);
|
}, [isSuccess]);
|
||||||
|
const originalVal = setting?.expires_in ?? 0;
|
||||||
return (
|
return (
|
||||||
<section className="max-w-[512px] h-full relative">
|
<section className="max-w-[512px] h-full relative">
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
@@ -50,11 +55,11 @@ const AutoDeleteMessages = ({ id, type = "channel", expires_in = 0 }: Props) =>
|
|||||||
<StyledRadio
|
<StyledRadio
|
||||||
options={options.map(({ title }) => title)}
|
options={options.map(({ title }) => title)}
|
||||||
values={options.map(({ value }) => value)}
|
values={options.map(({ value }) => value)}
|
||||||
value={value}
|
value={value || 0}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{expires_in !== value && <SaveTip saveHandler={handleSave} resetHandler={handleReset} />}
|
{originalVal !== value && <SaveTip saveHandler={handleSave} resetHandler={handleReset} />}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import {
|
|||||||
updateUsersVersion,
|
updateUsersVersion,
|
||||||
updateReadChannels,
|
updateReadChannels,
|
||||||
updateReadUsers,
|
updateReadUsers,
|
||||||
updateMute
|
updateMute,
|
||||||
|
updateAutoDeleteSetting
|
||||||
} from "../../../app/slices/footprint";
|
} from "../../../app/slices/footprint";
|
||||||
import { updateUsersByLogs, updateUsersStatus } from "../../../app/slices/users";
|
import { updateUsersByLogs, updateUsersStatus } from "../../../app/slices/users";
|
||||||
import { resetAuthData, updateLoginUser } from "../../../app/slices/auth.data";
|
import { resetAuthData, updateLoginUser } from "../../../app/slices/auth.data";
|
||||||
@@ -179,6 +180,22 @@ export default function useStreaming() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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 (
|
|
||||||
<section className="max-w-[512px] h-full relative">
|
|
||||||
<div className="text-sm">
|
|
||||||
<h2 >{t("title")}</h2>
|
|
||||||
<p className="text-gray-500">{t("desc")}</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4">
|
|
||||||
<StyledRadio
|
|
||||||
options={options.map(({ title }) => title)}
|
|
||||||
values={options.map(({ value }) => value)}
|
|
||||||
value={value}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{expires_in !== value && <SaveTip saveHandler={handleSave} resetHandler={handleReset} />}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AutoDeleteMessages;
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Overview from "./Overview";
|
import Overview from "./Overview";
|
||||||
import AutoDeleteMessages from './AutoDeleteMessages';
|
import AutoDeleteMessages from '../../common/component/AutoDeleteMessages';
|
||||||
import ManageMembers from "../../common/component/ManageMembers";
|
import ManageMembers from "../../common/component/ManageMembers";
|
||||||
|
|
||||||
export interface NavItem {
|
export interface NavItem {
|
||||||
|
|||||||
+17
-6
@@ -46,17 +46,28 @@ export interface MuteChannel {
|
|||||||
gid: number;
|
gid: number;
|
||||||
expired_at: 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 {
|
export interface UserSettingsEvent {
|
||||||
type: "user_settings";
|
type: "user_settings";
|
||||||
mute_users?: MuteUser[];
|
mute_users?: MuteUser[];
|
||||||
mute_groups?: MuteChannel[];
|
mute_groups?: MuteChannel[];
|
||||||
read_index_users?: { uid: number; mid: number }[];
|
read_index_users?: { uid: number; mid: number }[];
|
||||||
read_index_groups?: { gid: number; mid: number }[];
|
read_index_groups?: { gid: number; mid: number }[];
|
||||||
burn_after_reading_users?: { uid: number; expires_in: number }[];
|
burn_after_reading_users?: AutoDeleteMsgForUser[];
|
||||||
burn_after_reading_groups?: { gid: number; expires_in: number }[];
|
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 {
|
export interface UserSettingsChangedEvent {
|
||||||
type: "user_settings_changed";
|
type: "user_settings_changed";
|
||||||
from_device?: string;
|
from_device?: string;
|
||||||
@@ -66,8 +77,8 @@ export interface UserSettingsChangedEvent {
|
|||||||
remove_mute_groups?: number[];
|
remove_mute_groups?: number[];
|
||||||
read_index_users?: { uid: number; mid: number }[];
|
read_index_users?: { uid: number; mid: number }[];
|
||||||
read_index_groups?: { gid: number; mid: number }[];
|
read_index_groups?: { gid: number; mid: number }[];
|
||||||
burn_after_reading_users?: { uid: number; expires_in: number }[];
|
burn_after_reading_users?: AutoDeleteMsgForUser[];
|
||||||
burn_after_reading_groups?: { gid: number; expires_in: number }[];
|
burn_after_reading_groups?: AutoDeleteMsgForGroup[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RelatedGroupsEvent {
|
export interface RelatedGroupsEvent {
|
||||||
|
|||||||
Reference in New Issue
Block a user