feat: mute
This commit is contained in:
@@ -18,6 +18,12 @@ export default async function handler({ operation, data = {}, payload }) {
|
|||||||
await table.setItem("afterMid", afterMid);
|
await table.setItem("afterMid", afterMid);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "updateMute":
|
||||||
|
{
|
||||||
|
await table.setItem("muteUsers", data.muteUsers || {});
|
||||||
|
await table.setItem("muteChannels", data.muteChannels || {});
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "updateReadChannels":
|
case "updateReadChannels":
|
||||||
{
|
{
|
||||||
await table.setItem("readChannels", data.readChannels);
|
await table.setItem("readChannels", data.readChannels);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { createApi } from "@reduxjs/toolkit/query/react";
|
|||||||
import { KEY_UID } from "../config";
|
import { KEY_UID } from "../config";
|
||||||
import baseQuery from "./base.query";
|
import baseQuery from "./base.query";
|
||||||
import { resetAuthData, setUid } from "../slices/auth.data";
|
import { resetAuthData, setUid } from "../slices/auth.data";
|
||||||
|
import { updateMute } from "../slices/footprint";
|
||||||
import { fullfillContacts } from "../slices/contacts";
|
import { fullfillContacts } from "../slices/contacts";
|
||||||
import BASE_URL, { ContentTypes } from "../config";
|
import BASE_URL, { ContentTypes } from "../config";
|
||||||
import { onMessageSendStarted } from "./handlers";
|
import { onMessageSendStarted } from "./handlers";
|
||||||
@@ -47,6 +48,21 @@ export const contactApi = createApi({
|
|||||||
deleteContact: builder.query({
|
deleteContact: builder.query({
|
||||||
query: (uid) => ({ url: `/admin/user/${uid}`, method: "DELETE" }),
|
query: (uid) => ({ url: `/admin/user/${uid}`, method: "DELETE" }),
|
||||||
}),
|
}),
|
||||||
|
updateMuteSetting: builder.mutation({
|
||||||
|
query: (data) => ({
|
||||||
|
url: `/user/mute`,
|
||||||
|
method: "POST",
|
||||||
|
body: data,
|
||||||
|
}),
|
||||||
|
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||||
|
try {
|
||||||
|
await queryFulfilled;
|
||||||
|
dispatch(updateMute(data));
|
||||||
|
} catch (error) {
|
||||||
|
console.log("update mute failed", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
updateAvatar: builder.mutation({
|
updateAvatar: builder.mutation({
|
||||||
query: (data) => ({
|
query: (data) => ({
|
||||||
headers: {
|
headers: {
|
||||||
@@ -89,6 +105,7 @@ export const contactApi = createApi({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
|
useUpdateMuteSettingMutation,
|
||||||
useLazyDeleteContactQuery,
|
useLazyDeleteContactQuery,
|
||||||
useUpdateInfoMutation,
|
useUpdateInfoMutation,
|
||||||
useUpdateAvatarMutation,
|
useUpdateAvatarMutation,
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ const initialState = {
|
|||||||
afterMid: 0,
|
afterMid: 0,
|
||||||
readUsers: {},
|
readUsers: {},
|
||||||
readChannels: {},
|
readChannels: {},
|
||||||
|
muteUsers: {},
|
||||||
|
muteChannels: {},
|
||||||
};
|
};
|
||||||
const footprintSlice = createSlice({
|
const footprintSlice = createSlice({
|
||||||
name: "footprint",
|
name: "footprint",
|
||||||
@@ -18,8 +20,17 @@ const footprintSlice = createSlice({
|
|||||||
afterMid = 0,
|
afterMid = 0,
|
||||||
readUsers = {},
|
readUsers = {},
|
||||||
readChannels = {},
|
readChannels = {},
|
||||||
|
muteUsers = {},
|
||||||
|
muteChannels = {},
|
||||||
} = action.payload;
|
} = action.payload;
|
||||||
return { usersVersion, afterMid, readUsers, readChannels };
|
return {
|
||||||
|
usersVersion,
|
||||||
|
afterMid,
|
||||||
|
readUsers,
|
||||||
|
readChannels,
|
||||||
|
muteUsers,
|
||||||
|
muteChannels,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
updateUsersVersion(state, action) {
|
updateUsersVersion(state, action) {
|
||||||
const usersVersion = action.payload;
|
const usersVersion = action.payload;
|
||||||
@@ -29,6 +40,47 @@ const footprintSlice = createSlice({
|
|||||||
const afterMid = action.payload;
|
const afterMid = action.payload;
|
||||||
state.afterMid = afterMid;
|
state.afterMid = afterMid;
|
||||||
},
|
},
|
||||||
|
updateMute(state, action) {
|
||||||
|
const payload = action.payload || {};
|
||||||
|
Object.keys(payload).forEach((key) => {
|
||||||
|
switch (key) {
|
||||||
|
case "remove_users":
|
||||||
|
{
|
||||||
|
const uids = payload.remove_users;
|
||||||
|
uids.forEach((id) => {
|
||||||
|
delete state.muteUsers[id];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "remove_groups":
|
||||||
|
{
|
||||||
|
const gids = payload.remove_groups;
|
||||||
|
gids.forEach((id) => {
|
||||||
|
delete state.muteChannels[id];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "add_users":
|
||||||
|
{
|
||||||
|
const mutes = payload.add_users;
|
||||||
|
mutes.forEach(({ uid, expired_in = null }) => {
|
||||||
|
state.muteUsers[uid] = { expired_in };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "add_groups":
|
||||||
|
{
|
||||||
|
const mutes = payload.add_groups;
|
||||||
|
mutes.forEach(({ gid, expired_in = null }) => {
|
||||||
|
state.muteChannels[gid] = { expired_in };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
updateReadUsers(state, action) {
|
updateReadUsers(state, action) {
|
||||||
const reads = action.payload || [];
|
const reads = action.payload || [];
|
||||||
if (reads.length == 0) return;
|
if (reads.length == 0) return;
|
||||||
@@ -52,5 +104,6 @@ export const {
|
|||||||
updateUsersVersion,
|
updateUsersVersion,
|
||||||
updateReadChannels,
|
updateReadChannels,
|
||||||
updateReadUsers,
|
updateReadUsers,
|
||||||
|
updateMute,
|
||||||
} = footprintSlice.actions;
|
} = footprintSlice.actions;
|
||||||
export default footprintSlice.reducer;
|
export default footprintSlice.reducer;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
updateUsersVersion,
|
updateUsersVersion,
|
||||||
updateReadChannels,
|
updateReadChannels,
|
||||||
updateReadUsers,
|
updateReadUsers,
|
||||||
|
updateMute,
|
||||||
} from "../../../app/slices/footprint";
|
} from "../../../app/slices/footprint";
|
||||||
import {
|
import {
|
||||||
updateUsersByLogs,
|
updateUsersByLogs,
|
||||||
@@ -151,9 +152,45 @@ export default function useStreaming() {
|
|||||||
case "user_settings_changed":
|
case "user_settings_changed":
|
||||||
{
|
{
|
||||||
console.log("users settings");
|
console.log("users settings");
|
||||||
const { read_index_users = [], read_index_groups = [] } = data;
|
Object.keys(data).forEach((key) => {
|
||||||
dispatch(updateReadChannels(read_index_groups));
|
switch (key) {
|
||||||
dispatch(updateReadUsers(read_index_users));
|
case "read_index_groups":
|
||||||
|
dispatch(updateReadChannels(data[key]));
|
||||||
|
break;
|
||||||
|
case "read_index_users":
|
||||||
|
dispatch(updateReadUsers(data[key]));
|
||||||
|
break;
|
||||||
|
case "add_mute_users":
|
||||||
|
case "mute_users":
|
||||||
|
case "add_mute_groups":
|
||||||
|
case "mute_groups":
|
||||||
|
{
|
||||||
|
const arr = data[key];
|
||||||
|
if (arr && arr.length) {
|
||||||
|
const _key = key.endsWith("users")
|
||||||
|
? "add_users"
|
||||||
|
: "add_groups";
|
||||||
|
dispatch(updateMute({ [_key]: arr }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "remove_mute_users":
|
||||||
|
case "remove_mute_groups":
|
||||||
|
{
|
||||||
|
const arr = data[key];
|
||||||
|
if (arr && arr.length) {
|
||||||
|
const _key = key.endsWith("users")
|
||||||
|
? "remove_users"
|
||||||
|
: "remove_groups";
|
||||||
|
dispatch(updateMute({ [_key]: arr }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "users_state":
|
case "users_state":
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import ContextMenu from "../../../common/component/ContextMenu";
|
|||||||
import Tooltip from "../../../common/component/Tooltip";
|
import Tooltip from "../../../common/component/Tooltip";
|
||||||
// import { useDebounce} from "rooks";
|
// import { useDebounce} from "rooks";
|
||||||
import { useReadMessageMutation } from "../../../app/services/message";
|
import { useReadMessageMutation } from "../../../app/services/message";
|
||||||
|
import { useUpdateMuteSettingMutation } from "../../../app/services/contact";
|
||||||
|
|
||||||
import StyledLink from "./styled";
|
import StyledLink from "./styled";
|
||||||
import { toggleChannelSetting } from "../../../app/slices/ui";
|
import { toggleChannelSetting } from "../../../app/slices/ui";
|
||||||
@@ -17,6 +18,7 @@ import { getUnreadCount } from "../utils";
|
|||||||
const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [muteChannel] = useUpdateMuteSettingMutation();
|
||||||
const [updateReadIndex] = useReadMessageMutation();
|
const [updateReadIndex] = useReadMessageMutation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -25,17 +27,23 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
|||||||
handleContextMenuEvent,
|
handleContextMenuEvent,
|
||||||
hideContextMenu,
|
hideContextMenu,
|
||||||
} = useContextMenu();
|
} = useContextMenu();
|
||||||
const { channel, mids, messageData, readIndex, loginUid } = useSelector(
|
const {
|
||||||
(store) => {
|
channel,
|
||||||
|
mids,
|
||||||
|
messageData,
|
||||||
|
readIndex,
|
||||||
|
muted,
|
||||||
|
loginUid,
|
||||||
|
} = useSelector((store) => {
|
||||||
return {
|
return {
|
||||||
channel: store.channels.byId[id],
|
channel: store.channels.byId[id],
|
||||||
mids: store.channelMessage[id],
|
mids: store.channelMessage[id],
|
||||||
messageData: store.message,
|
messageData: store.message,
|
||||||
loginUid: store.authData.uid,
|
loginUid: store.authData.uid,
|
||||||
readIndex: store.footprint.readChannels[id],
|
readIndex: store.footprint.readChannels[id],
|
||||||
|
muted: store.footprint.muteChannels[id],
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
);
|
|
||||||
const handleChannelSetting = (evt) => {
|
const handleChannelSetting = (evt) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
@@ -66,8 +74,15 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
|||||||
updateReadIndex(param);
|
updateReadIndex(param);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleMute = () => {
|
||||||
|
const data = muted
|
||||||
|
? { remove_groups: [id] }
|
||||||
|
: { add_groups: [{ gid: id }] };
|
||||||
|
muteChannel(data);
|
||||||
|
};
|
||||||
const { is_public, name } = channel;
|
const { is_public, name } = channel;
|
||||||
const unreads = getUnreadCount({ mids, messageData, readIndex, loginUid });
|
const unreads = getUnreadCount({ mids, messageData, readIndex, loginUid });
|
||||||
|
const isDot = muted || unreads > 99;
|
||||||
return (
|
return (
|
||||||
<Tippy
|
<Tippy
|
||||||
interactive
|
interactive
|
||||||
@@ -86,7 +101,8 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
|||||||
handler: handleReadAll,
|
handler: handleReadAll,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Mute",
|
title: muted ? "Unmute" : "Mute",
|
||||||
|
handler: handleMute,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Notification Settings",
|
title: "Notification Settings",
|
||||||
@@ -123,8 +139,8 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
|
|||||||
<i className="setting" onClick={handleChannelSetting}></i>
|
<i className="setting" onClick={handleChannelSetting}></i>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{unreads > 0 && (
|
{unreads > 0 && (
|
||||||
<i className={`badge ${unreads > 99 ? "dot" : ""}`}>
|
<i className={`badge ${isDot ? "dot" : ""}`}>
|
||||||
{unreads > 99 ? null : unreads}
|
{isDot ? null : unreads}
|
||||||
</i>
|
</i>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user