Fix ImagePreview / Add voiceButtons (#409)
* Add AutoJump Back
Fixed not loading messages, properly & failing to jump in some instances.
* Add AutoJump back / Fixed!
Fixed Issue with not jumping to latest message in channel.
Fixed Issue with not loading message(s) properly when jumping.
* Update index.tsx
* Delete src/equicordplugins/autoJump directory
* Create UserChatButtons.tsx
* Create UserChatButtons.css
* Create index.tsx
* Delete index.tsx
* Add VoiceButtons
Allows you to easily deafen / mute people via voice-channel. With customizable settings that allows you to choose whether you want to toggle their video or soundboard in settings.
Source was taken from ClickToChat in vencord just added a few more things to make i way better
* fixes issue with YouTube embeds showing image and changing accounts image still staying
did what creations didnt 😠
* Create index.tsx
* Create styles.css
* Update index.tsx
* Some Fixes
* Update VoiceButtons
* Use MediaEngine Import
* Fix VSC
* Update index.tsx
* Delete src/equicordplugins/betterFormattingRedux directory
---------
Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
parent
df6c721946
commit
056851d4e8
6 changed files with 277 additions and 0 deletions
|
|
@ -3,6 +3,8 @@ import { FluxStore } from "..";
|
|||
export class MediaEngineStore extends FluxStore {
|
||||
isSelfMute(): boolean;
|
||||
isSelfDeaf(): boolean;
|
||||
isLocalMute(userId): boolean;
|
||||
isLocalVideoDisabled(userId): boolean;
|
||||
|
||||
setAv1Enabled(AV1: boolean): void;
|
||||
setH265Enabled(H265: boolean): void;
|
||||
|
|
|
|||
|
|
@ -376,6 +376,24 @@ function updatePreviewPosition(mouseEvent: MouseEvent, element: HTMLElement) {
|
|||
}
|
||||
}
|
||||
|
||||
let previewCheckInterval;
|
||||
|
||||
function watchSourceElement(el: Element) {
|
||||
if (previewCheckInterval) {
|
||||
clearInterval(previewCheckInterval);
|
||||
previewCheckInterval = null;
|
||||
}
|
||||
|
||||
previewCheckInterval = setInterval(() => {
|
||||
const node = el as HTMLElement;
|
||||
if (!document.body.contains(node) || !node.offsetParent) {
|
||||
deleteCurrentPreview();
|
||||
clearInterval(previewCheckInterval);
|
||||
previewCheckInterval = null;
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function addHoverListener(element: Element, sticker: boolean = false) {
|
||||
element.setAttribute("data-processed", "true");
|
||||
|
||||
|
|
@ -406,6 +424,7 @@ function addHoverListener(element: Element, sticker: boolean = false) {
|
|||
|
||||
hoverDelayTimeout = setTimeout(() => {
|
||||
loadImagePreview(strippedURL, sticker);
|
||||
watchSourceElement(element);
|
||||
if (lastMouseEvent) {
|
||||
updatePreviewPosition(lastMouseEvent, element as HTMLElement);
|
||||
}
|
||||
|
|
|
|||
74
src/equicordplugins/voiceButtons/index.tsx
Normal file
74
src/equicordplugins/voiceButtons/index.tsx
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { React } from "@webpack/common";
|
||||
|
||||
import { UserChatButton, UserDeafenButton, UserMuteButton } from "./utils";
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
showChatButton: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Whether you want to display the chat button",
|
||||
restartNeeded: true,
|
||||
},
|
||||
showMuteButton: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Whether you want to display the mute button",
|
||||
restartNeeded: true,
|
||||
},
|
||||
showDeafenButton: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Whether you want to display the deafen button",
|
||||
restartNeeded: true,
|
||||
},
|
||||
muteSoundboard: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Toggles their soundboard upon clicking deafen button.",
|
||||
restartNeeded: false,
|
||||
},
|
||||
disableVideo: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Toggles their video upon clicking deafen button.",
|
||||
restartNeeded: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "VoiceButtons",
|
||||
description: "Quickly DM, mute, or deafen any user right from the voice-call panel.",
|
||||
authors: [EquicordDevs.nicola02nb, EquicordDevs.omaw],
|
||||
settings,
|
||||
patches: [
|
||||
{
|
||||
find: "\"avatarContainerClass\",\"userNameClassName\"",
|
||||
replacement: [
|
||||
{
|
||||
match: /:(\i)\.username.*?flipped\]:\i\}\),children:\[/,
|
||||
replace: "$&$self.renderButtons($1),"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
renderPing(user?: User) {
|
||||
if (!user) return null;
|
||||
return (
|
||||
<div style={{ display: "flex", gap: "4px" }}>
|
||||
{settings.store.showChatButton && <UserChatButton user={user} />}
|
||||
{settings.store.showMuteButton && <UserMuteButton user={user} />}
|
||||
{settings.store.showDeafenButton && <UserDeafenButton user={user} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
3
src/equicordplugins/voiceButtons/styles.css
Normal file
3
src/equicordplugins/voiceButtons/styles.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
div[class^='list_'][class*='collapsed_'] .click-to-chat-btn {
|
||||
display: none;
|
||||
}
|
||||
175
src/equicordplugins/voiceButtons/utils.tsx
Normal file
175
src/equicordplugins/voiceButtons/utils.tsx
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
import { openPrivateChannel } from "@utils/discord";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { findStoreLazy } from "@webpack";
|
||||
import { Button, MediaEngineStore, Tooltip, UserStore, VoiceActions } from "@webpack/common";
|
||||
|
||||
import { settings } from ".";
|
||||
|
||||
const SoundboardStore = findStoreLazy("SoundboardStore");
|
||||
|
||||
export function UserChatButton({ user }: { user: User; }) {
|
||||
if (user.id === UserStore.getCurrentUser().id) return null;
|
||||
return (
|
||||
<div className="click-to-chat-container">
|
||||
<Tooltip text={`Open chat with ${user.globalName} / @${user.username}`}>
|
||||
{({ onMouseEnter, onMouseLeave }) => (
|
||||
<Button
|
||||
size={Button.Sizes.MIN}
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
look={Button.Looks.BLANK}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
openPrivateChannel({ recipientIds: [user.id] } as any);
|
||||
}}
|
||||
disabled={user.id === UserStore.getCurrentUser().id}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<svg
|
||||
className="click-to-chat-button"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="16"
|
||||
height="16"
|
||||
fill="var(--channels-default)"
|
||||
>
|
||||
<path d="M12 22a10 10 0 1 0-8.45-4.64c.13.19.11.44-.04.61l-2.06 2.37A1 1 0 0 0 2.2 22H12Z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
)}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserMuteButton({ user }: { user: User; }) {
|
||||
if (user.id === UserStore.getCurrentUser().id) return null;
|
||||
return (
|
||||
<div className="click-to-chat-container">
|
||||
<Tooltip text={`${MediaEngineStore.isLocalMute(user.id) ? "Unmute" : "Mute"} ${user.globalName} / @${user.username}`}>
|
||||
{({ onMouseEnter, onMouseLeave }) => (
|
||||
<Button
|
||||
size={Button.Sizes.MIN}
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
look={Button.Looks.BLANK}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
VoiceActions.toggleLocalMute(user.id);
|
||||
}}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<svg
|
||||
className="click-to-chat-button"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="16"
|
||||
height="16"
|
||||
fill={MediaEngineStore.isLocalMute(user.id) ? "red" : "var(--channels-default)"}
|
||||
>
|
||||
<path d="M10.78 17.22c-.25.25-.13.67.22.72V20H9a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2h-2v-2.06A8 8 0 0 0 20 10a1 1 0 1 0-2 0 6 6 0 0 1-5.8 6 .52.52 0 0 0-.35.15l-1.07 1.07ZM15.4 4.6a.46.46 0 0 0 .1-.56 4 4 0 0 0-4.03-2c-.4.05-.47.57-.21.89A3.22 3.22 0 0 1 9.9 8l-1.16.43a.5.5 0 0 0-.3.3L8.01 9.9 8 9.94V10c0 .33.04.66.12.96.08.34.5.42.74.18L15.4 4.6ZM5.1 14.07c.17.26.53.3.75.08l.75-.75c.16-.16.19-.41.08-.62a5.99 5.99 0 0 1-.24-.51.62.62 0 0 0-.7-.35c-.23.05-.47.08-.7.08-.37 0-.7.34-.58.7.18.47.4.93.65 1.37Z"></path>
|
||||
<path d="M9.2 3.86a1.21 1.21 0 0 1 0 2.28l-1.37.5a2 2 0 0 0-1.18 1.19l-.51 1.38a1.21 1.21 0 0 1-2.28 0l-.5-1.38a2 2 0 0 0-1.19-1.18L.79 6.14a1.21 1.21 0 0 1 0-2.28l1.38-.5a2 2 0 0 0 1.18-1.19L3.86.79a1.21 1.21 0 0 1 2.28 0l.5 1.38a2 2 0 0 0 1.19 1.18l1.38.51Z"></path>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M22.7 1.3a1 1 0 0 1 0 1.4l-20 20a1 1 0 0 1-1.4-1.4l20-20a1 1 0 0 1 1.4 0Z"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</Button>
|
||||
)}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DeafenIcon({ user, ...props }) {
|
||||
const isDeafened =
|
||||
MediaEngineStore.isLocalMute(user.id) &&
|
||||
SoundboardStore.isLocalSoundboardMuted(user.id) &&
|
||||
MediaEngineStore.isLocalVideoDisabled(user.id);
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={16}
|
||||
height={16}
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
className={""}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill={isDeafened ? "red" : "var(--channels-default)"}
|
||||
fillRule="evenodd"
|
||||
d="M21.76.83a5.02 5.02 0 0 1 .78 7.7 5 5 0 0 1-7.07 0 5.02 5.02 0 0 1 0-7.07 5 5 0 0 1 6.29-.63Zm-4.88 2.05a3 3 0 0 1 3.41-.59l-4 4a3 3 0 0 1 .59-3.41Zm4.83.83-4 4a3 3 0 0 0 4-4Z"
|
||||
clipRule="evenodd"
|
||||
className={""}
|
||||
/>
|
||||
<path
|
||||
fill={isDeafened ? "red" : "var(--channels-default)"}
|
||||
d="M12.38 1c.38.02.58.45.4.78-.15.3-.3.62-.4.95A.4.4 0 0 1 12 3a9 9 0 0 0-8.95 10h1.87a5 5 0 0 1 4.1 2.13l1.37 1.97a3.1 3.1 0 0 1-.17 3.78 2.85 2.85 0 0 1-3.55.74 11 11 0 0 1 5.71-20.61ZM22.22 11.22c.34-.18.76.02.77.4L23 12a11 11 0 0 1-5.67 9.62c-1.27.71-2.73.23-3.55-.74a3.1 3.1 0 0 1-.17-3.78l1.38-1.97a5 5 0 0 1 4.1-2.13h1.86c.03-.33.05-.66.05-1a.4.4 0 0 1 .27-.38c.33-.1.65-.25.95-.4Z"
|
||||
className={""}
|
||||
/>
|
||||
{isDeafened && (
|
||||
<line
|
||||
x1="22"
|
||||
y1="2"
|
||||
x2="2"
|
||||
y2="22"
|
||||
stroke="var(--status-danger)"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserDeafenButton({ user }: { user: User; }) {
|
||||
if (user.id === UserStore.getCurrentUser().id) return null;
|
||||
const isDeafened =
|
||||
MediaEngineStore.isLocalMute(user.id) &&
|
||||
SoundboardStore.isLocalSoundboardMuted(user.id) &&
|
||||
MediaEngineStore.isLocalVideoDisabled(user.id);
|
||||
return (
|
||||
<div className="click-to-deafen-container">
|
||||
<Tooltip text={`${isDeafened ? "Undeafen" : "Deafen"} ${user.globalName} / @${user.username}`}>
|
||||
{({ onMouseEnter, onMouseLeave }) => (
|
||||
<Button
|
||||
size={Button.Sizes.MIN}
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
look={Button.Looks.BLANK}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
VoiceActions.toggleLocalMute(user.id);
|
||||
if (settings.store.muteSoundboard) {
|
||||
VoiceActions.toggleLocalSoundboardMute(user.id);
|
||||
}
|
||||
if (settings.store.disableVideo) {
|
||||
VoiceActions.setDisableLocalVideo(
|
||||
user.id,
|
||||
MediaEngineStore.isLocalVideoDisabled(user.id) ? "ENABLED" : "DISABLED",
|
||||
"default"
|
||||
);
|
||||
}
|
||||
}}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<DeafenIcon user={user} width={16} height={16} />
|
||||
</Button>
|
||||
)}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1148,6 +1148,10 @@ export const EquicordDevs = Object.freeze({
|
|||
justjxke: {
|
||||
name: "justjxke",
|
||||
id: 852558183087472640n
|
||||
},
|
||||
nicola02nb: {
|
||||
name: "nicola02nb",
|
||||
id: 257900031351193600n
|
||||
}
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue