/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import { classes } from "@utils/misc";
import definePlugin, { OptionType } from "@utils/types";
import { findByPropsLazy } from "@webpack";
import { Button, Menu, React, RelationshipStore, TooltipContainer, UserStore, } from "@webpack/common";
import { User } from "discord-types/general";
const { toggleLocalMute } = findByPropsLazy("toggleLocalMute");
const { isLocalMute } = findByPropsLazy("isLocalMute");
const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "banner");
const enum MenuItemParentType {
User,
}
const settings = definePluginSettings({
autoMuteBlocked: {
type: OptionType.BOOLEAN,
default: true,
description: "Automatically mute blocked users.",
restartNeeded: false
}
});
/**
* Adds a "Mute and Block" or "Unmute and Unblock" item to user context menus.
*
* If the user is blocked, the action will unmute and unblock the user. Otherwise,
* the action will mute and block the user.
*
* @param children The menu items to add the new item to.
* @param props The props passed to the user context menu.
* @returns The modified children with the new item added.
*/
const userContextPatch: NavContextMenuPatchCallback = (children, { user }: { user?: User, onClose(): void; }) => {
if (!user) return;
// Determine the label and action based on the user's blocked status
const isBlocked = RelationshipStore.isBlocked(user.id);
const lbl = isBlocked ? "Unmute and Unblock" : "Mute and Block";
/**
* Handles the logic for toggling mute and block/unblock when the user
* clicks the "Mute and Block" or "Unmute and Unblock" context menu item.
*
* If the user is currently blocked, the action will unmute and unblock.
* Otherwise, the action will mute and block.
*
* @private
*/
const action = () => {
// Toggle mute and handle block/unblock logic
if (isBlocked) {
// Logic to unblock the user
if (isLocalMute(user.id)) {
toggleLocalMute(user.id); // Unmute the user
}
} else {
// Logic to block the user
if (!isLocalMute(user.id)) {
toggleLocalMute(user.id); // Mute the user
}
}
};
children.push(
);
};
export default definePlugin({
name: "MuteBlockedUsers",
description: `(Voice)-Mute blocked users for easy recognition / transform a block to a "real" block.`,
authors: [Devs.notvexi],
settings,
patches: [],
contextMenus: {
"user-context": userContextPatch,
"user-profile-actions": userContextPatch,
"user-profile-overflow-menu": userContextPatch
},
/**
* Attaches a listener to the RelationshipStore and runs the automatic muted user check once.
*
* The listener is needed to detect when a user is blocked and should be muted.
* The initial function call is needed to mute users that are already blocked when the plugin is started.
*/
start() {
RelationshipStore.addChangeListener(() => {
this.automaticMuteBlockedUsers();
});
this.automaticMuteBlockedUsers();
},
/**
* Mutes all blocked users and unmutes all unblocked users.
*
* This function is called whenever the RelationshipStore changes.
* It is also called once when the plugin is started.
*
* @private
*/
automaticMuteBlockedUsers() {
const { autoMuteBlocked } = settings.store;
if (!autoMuteBlocked) return;
// Get all relationships and filter for blocked users
const blockedIds = Object.entries(RelationshipStore.getRelationships())
.filter(([_, v]) => v === 2) // 2 represents blocked
.map(([k]) => UserStore.getUser(k).id); // Get user IDs of blocked users
// Mute blocked users
for (const ID of blockedIds) {
if (!isLocalMute(ID)) {
toggleLocalMute(ID);
}
}
// Check for unblocked users
const allUsers = UserStore.getUsers(); // Get all users as a Record
const allUserIds = Object.keys(allUsers);
for (const ID of allUserIds) {
if (!RelationshipStore.isBlocked(ID)) {
// Unmute the user if they are unblocked
if (isLocalMute(ID)) {
toggleLocalMute(ID);
}
}
}
},
BlockUnblockButton: ErrorBoundary.wrap(({ user }: { user: User; }) => {
if (!user) return null; // Return null if no user is provided
// Determine the button label based on the user's blocked status
const isBlocked = RelationshipStore.isBlocked(user.id);
const lbl = isBlocked ? "Unmute and Unblock" : "Mute and Block";
return (
);
}, { noop: true })
});