feat(plugin): User Voice Show (#694)

Co-authored-by: V <vendicated@riseup.net>
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
This commit is contained in:
LordElias 2023-04-06 03:22:54 +02:00 committed by GitHub
parent df7357b357
commit e261c93563
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 188 additions and 0 deletions

View file

@ -0,0 +1,18 @@
.vc-uvs-button > div {
white-space: normal !important;
}
.vc-uvs-button {
width: 100%;
margin: auto;
height: unset;
}
.vc-uvs-header {
color: var(--header-primary);
margin-bottom: 6px;
}
.vc-uvs-modal-margin > [class^="section"] {
margin: 0 12px;
}

View file

@ -0,0 +1,61 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import "./VoiceChannelSection.css";
import { findByCodeLazy, findByPropsLazy } from "@webpack";
import { Button, Forms, PermissionStore, Toasts } from "@webpack/common";
import { Channel } from "discord-types/general";
const ChannelActions = findByPropsLazy("selectChannel", "selectVoiceChannel");
const UserPopoutSection = findByCodeLazy(".lastSection", ".children");
const CONNECT = 1n << 20n;
interface VoiceChannelFieldProps {
channel: Channel;
label: string;
showHeader: boolean;
}
export const VoiceChannelSection = ({ channel, label, showHeader }: VoiceChannelFieldProps) => (
<UserPopoutSection>
{showHeader && <Forms.FormTitle className="vc-uvs-header">In a voice channel</Forms.FormTitle>}
<Button
className="vc-uvs-button"
color={Button.Colors.TRANSPARENT}
size={Button.Sizes.SMALL}
onClick={() => {
if (PermissionStore.can(CONNECT, channel))
ChannelActions.selectVoiceChannel(channel.id);
else
Toasts.show({
message: "Insufficient permissions to enter the channel.",
id: "user-voice-show-insufficient-permissions",
type: Toasts.Type.FAILURE,
options: {
position: Toasts.Position.BOTTOM,
}
});
}}
>
{label}
</Button>
</UserPopoutSection>
);

View file

@ -0,0 +1,105 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { definePluginSettings } from "@api/settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { findStoreLazy } from "@webpack";
import { ChannelStore, GuildStore } from "@webpack/common";
import { User } from "discord-types/general";
import { VoiceChannelSection } from "./components/VoiceChannelSection";
const VoiceStateStore = findStoreLazy("VoiceStateStore");
const settings = definePluginSettings({
showInUserProfileModal: {
type: OptionType.BOOLEAN,
description: "Show a user's voice channel in their profile modal",
default: true,
},
showVoiceChannelSectionHeader: {
type: OptionType.BOOLEAN,
description: 'Whether to show "IN A VOICE CHANNEL" above the join button',
default: true,
}
});
interface UserProps {
user: User;
}
const VoiceChannelField = ErrorBoundary.wrap(({ user }: UserProps) => {
const { channelId } = VoiceStateStore.getVoiceStateForUser(user.id) ?? {};
if (!channelId) return null;
const channel = ChannelStore.getChannel(channelId);
const guild = GuildStore.getGuild(channel.guild_id);
if (!guild) return null; // When in DM call
const result = `${guild.name} | ${channel.name}`;
return (
<VoiceChannelSection
channel={channel}
label={result}
showHeader={settings.store.showVoiceChannelSectionHeader}
/>
);
});
export default definePlugin({
name: "UserVoiceShow",
description: "Shows whether a User is currently in a voice channel somewhere in their profile",
authors: [Devs.LordElias],
settings,
patchModal({ user }: UserProps) {
if (!settings.store.showInUserProfileModal)
return null;
return (
<div className="vc-uvs-modal-margin">
<VoiceChannelField user={user} />
</div>
);
},
patchPopout: ({ user }: UserProps) => <VoiceChannelField user={user} />,
patches: [
{
find: ".showCopiableUsername",
replacement: {
match: /\(0,\w\.jsx\)\(\w{2},{user:\w,setNote/,
// paste my fancy custom button above the message field
replace: "$self.patchPopout(arguments[0]),$&",
}
},
{
find: ".USER_PROFILE_MODAL",
replacement: {
match: /,{user:\w{1,2}}\)(?!;case)/,
// paste my fancy custom button below the username
replace: "$&,$self.patchModal(arguments[0])",
}
}
],
});

View file

@ -226,6 +226,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "TheKodeToad",
id: 706152404072267788n
},
LordElias: {
name: "LordElias",
id: 319460781567639554n
},
juby: {
name: "Juby210",
id: 324622488644616195n