mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-09 22:53:02 -04:00
Merge branch 'dev'
This commit is contained in:
commit
a8ae13ec08
26 changed files with 269 additions and 129 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "equicord",
|
"name": "equicord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.10.4",
|
"version": "1.10.5",
|
||||||
"description": "The other cutest Discord client mod",
|
"description": "The other cutest Discord client mod",
|
||||||
"homepage": "https://github.com/Equicord/Equicord#readme",
|
"homepage": "https://github.com/Equicord/Equicord#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -5,3 +5,73 @@
|
||||||
.vc-plugin-modal-description {
|
.vc-plugin-modal-description {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* warning modal */
|
||||||
|
|
||||||
|
.vc-text-selectable {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-warning-info {
|
||||||
|
gap: 15px;
|
||||||
|
flex-direction: column;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-warning-info img {
|
||||||
|
width: 70%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
margin: auto auto 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-warning-info strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-warning-info button.disable-warning {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: transparent;
|
||||||
|
color: red;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: fit-content;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-warning-info button.disable-warning:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--text-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-warning-info button.disable-warning:active {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-danger {
|
||||||
|
color: var(--text-danger);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-normal {
|
||||||
|
color: var(--text-normal);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-normal.margin-bottom {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-danger-background {
|
||||||
|
background-color: var(--button-danger-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-danger-background-no-margin {
|
||||||
|
background-color: var(--button-danger-background) !important;
|
||||||
|
color: var(--header-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-modal-close-button {
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
|
@ -407,36 +407,27 @@ export function openWarningModal(plugin: Plugin, pluginModalProps: ModalProps, o
|
||||||
transitionState={warningModalProps.transitionState}
|
transitionState={warningModalProps.transitionState}
|
||||||
>
|
>
|
||||||
<ModalHeader separator={false}>
|
<ModalHeader separator={false}>
|
||||||
<Text style={{ flexGrow: 1, color: "var(--text-danger)", fontSize: "1.4rem", fontWeight: "bold" }}>Warning: Dangerous Action</Text>
|
<Text className="text-danger">Warning: Dangerous Action</Text>
|
||||||
<ModalCloseButton onClick={warningModalProps.onClose} />
|
<ModalCloseButton onClick={warningModalProps.onClose} className="vc-modal-close-button" />
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<Forms.FormSection>
|
<Forms.FormSection>
|
||||||
<Flex className="vc-warning-info" style={{ gap: "15px", flexDirection: "column", userSelect: "none" }}>
|
<Flex className="vc-warning-info">
|
||||||
<img
|
<img
|
||||||
src="https://media.tenor.com/Y6DXKZiBCs8AAAAi/stavario-josefbenes.gif"
|
src="https://media.tenor.com/Y6DXKZiBCs8AAAAi/stavario-josefbenes.gif"
|
||||||
alt="Warning"
|
alt="Warning"
|
||||||
style={{ width: "60%", height: "auto", marginBottom: "10px", display: "block", margin: "auto" }}
|
|
||||||
/>
|
/>
|
||||||
<Text style={{ fontSize: "1.2rem", color: "var(--text-normal)" }}>
|
<Text className="text-normal">
|
||||||
You are about to reset all settings for <strong>{plugin.name}</strong> to their default values.
|
You are about to reset all settings for <strong>{plugin.name}</strong> to their default values.
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ fontSize: "1.2rem", color: "var(--text-danger)", fontWeight: "bold" }}>
|
<Text className="text-danger">
|
||||||
This action is irreversible.
|
This action is irreversible.
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{ fontSize: "1.2rem", color: "var(--text-normal)", marginBottom: "10px" }}>
|
<Text className="text-normal margin-bottom">
|
||||||
If you are certain you want to proceed, click <strong>Confirm Reset</strong>. Otherwise, click <strong>Cancel</strong>.
|
If you are certain you want to proceed, click <strong>Confirm Reset</strong>. Otherwise, click <strong>Cancel</strong>.
|
||||||
</Text>
|
</Text>
|
||||||
{!Settings.ignoreResetWarning && (
|
{!Settings.ignoreResetWarning && (
|
||||||
<Button style={{
|
<Button className="disable-warning" onClick={() => {
|
||||||
fontSize: "0.8rem",
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
color: "red",
|
|
||||||
cursor: "pointer",
|
|
||||||
margin: "0 auto",
|
|
||||||
width: "fit-content",
|
|
||||||
textDecoration: "underline"
|
|
||||||
}} onClick={() => {
|
|
||||||
Settings.ignoreResetWarning = true;
|
Settings.ignoreResetWarning = true;
|
||||||
}}>
|
}}>
|
||||||
Disable this warning forever
|
Disable this warning forever
|
||||||
|
@ -466,7 +457,7 @@ export function openWarningModal(plugin: Plugin, pluginModalProps: ModalProps, o
|
||||||
}}
|
}}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
style={{ marginLeft: "10px", backgroundColor: "var(--button-danger-background)" }}
|
className="button-danger-background-no-margin"
|
||||||
>
|
>
|
||||||
Confirm Reset
|
Confirm Reset
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -429,35 +429,26 @@ export default function PluginSettings() {
|
||||||
{enabledPlugins.length > 0 && (
|
{enabledPlugins.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
style={{ backgroundColor: "var(--button-danger-background)", margin: "20px 0" }}
|
className="button-danger-background"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (Settings.ignoreResetWarning) return resetCheckAndDo();
|
if (Settings.ignoreResetWarning) return resetCheckAndDo();
|
||||||
|
|
||||||
return Alerts.show({
|
return Alerts.show({
|
||||||
title: "Disable All Plugins",
|
title: "Disable All Plugins",
|
||||||
body: (
|
body: (
|
||||||
<div style={{ textAlign: "center" }}>
|
<div className="alert-body">
|
||||||
<img
|
<img
|
||||||
src="https://media.tenor.com/Y6DXKZiBCs8AAAAi/stavario-josefbenes.gif"
|
src="https://media.tenor.com/Y6DXKZiBCs8AAAAi/stavario-josefbenes.gif"
|
||||||
alt="Warning"
|
alt="Warning"
|
||||||
style={{ width: "60%", height: "auto", marginBottom: "10px", display: "block", margin: "auto" }}
|
|
||||||
/>
|
/>
|
||||||
<p style={{ fontSize: "1.2rem", color: "var(--text-danger)", fontWeight: "bold" }}>
|
<p className="warning-text">
|
||||||
WARNING: You are about to disable <span style={{ textDecoration: "underline" }}>{enabledPlugins.length}</span> plugins!
|
WARNING: You are about to disable <span>{enabledPlugins.length}</span> plugins!
|
||||||
</p>
|
</p>
|
||||||
<p style={{ fontSize: "1rem" }}>
|
<p>
|
||||||
Are you absolutely sure you want to proceed? You can always enable them back later.
|
Are you absolutely sure you want to proceed? You can always enable them back later.
|
||||||
</p>
|
</p>
|
||||||
{!Settings.ignoreResetWarning && (
|
{!Settings.ignoreResetWarning && (
|
||||||
<Button style={{
|
<Button className="disable-warning" onClick={() => {
|
||||||
fontSize: "0.8rem",
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
color: "red",
|
|
||||||
cursor: "pointer",
|
|
||||||
margin: "0 auto",
|
|
||||||
width: "fit-content",
|
|
||||||
textDecoration: "underline"
|
|
||||||
}} onClick={() => {
|
|
||||||
Settings.ignoreResetWarning = true;
|
Settings.ignoreResetWarning = true;
|
||||||
}}>
|
}}>
|
||||||
Disable this warning forever
|
Disable this warning forever
|
||||||
|
@ -466,6 +457,7 @@ export default function PluginSettings() {
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
confirmText: "Disable All",
|
confirmText: "Disable All",
|
||||||
|
confirmColor: "button-danger-background-no-margin",
|
||||||
cancelText: "Cancel",
|
cancelText: "Cancel",
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
resetCheckAndDo();
|
resetCheckAndDo();
|
||||||
|
|
|
@ -124,3 +124,66 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* disable all modal */
|
||||||
|
|
||||||
|
.button-danger-background {
|
||||||
|
background-color: var(--button-danger-background) !important;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-danger-background-no-margin {
|
||||||
|
background-color: var(--button-danger-background) !important;
|
||||||
|
color: var(--header-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-danger-background:hover {
|
||||||
|
background-color: var(--button-danger-background-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-body {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-body img {
|
||||||
|
width: 60%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
margin: auto auto 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-body p.warning-text {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--text-danger);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-body p {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-body span {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable-warning {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: transparent !important;
|
||||||
|
color: var(--text-danger) !important;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: fit-content;
|
||||||
|
text-decoration: underline;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable-warning:hover {
|
||||||
|
color: var(--text-danger);
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable-warning:active {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
|
@ -134,8 +134,9 @@ export async function sendSticker({
|
||||||
file = await toGIF(sticker.image, ffmpegState.ffmpeg);
|
file = await toGIF(sticker.image, ffmpegState.ffmpeg);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const response = await fetch(sticker.image, { cache: "force-cache" });
|
const url = new URL(sticker.image);
|
||||||
// const blob = await response.blob();
|
url.searchParams.set("t", Date.now().toString()); // To prevent caching, in order to avoid CORS bug in Chrome
|
||||||
|
const response = await fetch(sticker.image);
|
||||||
const orgImageUrl = URL.createObjectURL(await response.blob());
|
const orgImageUrl = URL.createObjectURL(await response.blob());
|
||||||
const processedImage = await resizeImage(orgImageUrl);
|
const processedImage = await resizeImage(orgImageUrl);
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "ImageModalAPI",
|
name: "DynamicImageModalAPI",
|
||||||
authors: [Devs.sadan, Devs.Nuckyz],
|
authors: [Devs.sadan, Devs.Nuckyz],
|
||||||
description: "Allows you to open Image Modals",
|
description: "Allows you to omit either width or height when opening an image modal",
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "SCALE_DOWN:",
|
find: "SCALE_DOWN:",
|
|
@ -209,7 +209,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
get electronVersion() {
|
get electronVersion() {
|
||||||
return VencordNative.native.getVersions().electron || window.armcord?.electron || null;
|
return VencordNative.native.getVersions().electron || window.legcord?.electron || null;
|
||||||
},
|
},
|
||||||
|
|
||||||
get chromiumVersion() {
|
get chromiumVersion() {
|
||||||
|
|
|
@ -75,7 +75,7 @@ async function generateDebugInfoMessage() {
|
||||||
if (IS_DISCORD_DESKTOP) return `Discord Desktop v${DiscordNative.app.getVersion()}`;
|
if (IS_DISCORD_DESKTOP) return `Discord Desktop v${DiscordNative.app.getVersion()}`;
|
||||||
if (IS_VESKTOP) return `Vesktop v${VesktopNative.app.getVersion()}`;
|
if (IS_VESKTOP) return `Vesktop v${VesktopNative.app.getVersion()}`;
|
||||||
if (IS_EQUIBOP) return `Equibop v${VesktopNative.app.getVersion()}`;
|
if (IS_EQUIBOP) return `Equibop v${VesktopNative.app.getVersion()}`;
|
||||||
if ("armcord" in window) return `ArmCord v${window.armcord.version}`;
|
if ("legcord" in window) return `LegCord v${window.armcord.version}`;
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
const name = typeof unsafeWindow !== "undefined" ? "UserScript" : "Web";
|
const name = typeof unsafeWindow !== "undefined" ? "UserScript" : "Web";
|
||||||
|
|
|
@ -73,8 +73,8 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
// ArmCord comes with its own arRPC implementation, so this plugin just confuses users
|
// Legcord comes with its own arRPC implementation, so this plugin just confuses users
|
||||||
if ("armcord" in window) return;
|
if ("legcord" in window) return;
|
||||||
|
|
||||||
if (ws) ws.close();
|
if (ws) ws.close();
|
||||||
ws = new WebSocket("ws://127.0.0.1:1337"); // try to open WebSocket
|
ws = new WebSocket("ws://127.0.0.1:1337"); // try to open WebSocket
|
||||||
|
|
|
@ -65,7 +65,7 @@ export default definePlugin({
|
||||||
name: "BetterRoleContext",
|
name: "BetterRoleContext",
|
||||||
description: "Adds options to copy role color / edit role / view role icon when right clicking roles in the user profile",
|
description: "Adds options to copy role color / edit role / view role icon when right clicking roles in the user profile",
|
||||||
authors: [Devs.Ven, Devs.goodbee],
|
authors: [Devs.Ven, Devs.goodbee],
|
||||||
dependencies: ["UserSettingsAPI", "ImageModalAPI"],
|
dependencies: ["UserSettingsAPI"],
|
||||||
|
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
|
@ -99,7 +99,11 @@ export default definePlugin({
|
||||||
id="vc-view-role-icon"
|
id="vc-view-role-icon"
|
||||||
label="View Role Icon"
|
label="View Role Icon"
|
||||||
action={() => {
|
action={() => {
|
||||||
openImageModal(`${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${role.id}/${role.icon}.${settings.store.roleIconFileFormat}`);
|
openImageModal({
|
||||||
|
url: `${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${role.id}/${role.icon}.${settings.store.roleIconFileFormat}`,
|
||||||
|
height: 128,
|
||||||
|
width: 128
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
icon={ImageIcon}
|
icon={ImageIcon}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -57,7 +57,11 @@ export const handleViewPreview = async ({ guildId, channelId, ownerId }: Applica
|
||||||
const previewUrl = await ApplicationStreamPreviewStore.getPreviewURL(guildId, channelId, ownerId);
|
const previewUrl = await ApplicationStreamPreviewStore.getPreviewURL(guildId, channelId, ownerId);
|
||||||
if (!previewUrl) return;
|
if (!previewUrl) return;
|
||||||
|
|
||||||
openImageModal(previewUrl);
|
openImageModal({
|
||||||
|
url: previewUrl,
|
||||||
|
height: 720,
|
||||||
|
width: 1280
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addViewStreamContext: NavContextMenuPatchCallback = (children, { userId }: { userId: string | bigint; }) => {
|
export const addViewStreamContext: NavContextMenuPatchCallback = (children, { userId }: { userId: string | bigint; }) => {
|
||||||
|
@ -89,7 +93,6 @@ export default definePlugin({
|
||||||
name: "BiggerStreamPreview",
|
name: "BiggerStreamPreview",
|
||||||
description: "This plugin allows you to enlarge stream previews",
|
description: "This plugin allows you to enlarge stream previews",
|
||||||
authors: [Devs.phil],
|
authors: [Devs.phil],
|
||||||
dependencies: ["ImageModalAPI"],
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"user-context": userContextPatch,
|
"user-context": userContextPatch,
|
||||||
"stream-context": streamContextPatch
|
"stream-context": streamContextPatch
|
||||||
|
|
|
@ -181,13 +181,6 @@ export default definePlugin({
|
||||||
replace: "$&$self.unMountMagnifier();"
|
replace: "$&$self.unMountMagnifier();"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
find: ".carouselModal",
|
|
||||||
replacement: {
|
|
||||||
match: /(?<=\.carouselModal.{0,100}onClick:)\i,/,
|
|
||||||
replace: "()=>{},"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,3 @@
|
||||||
|
|
||||||
/* https://googlechrome.github.io/samples/image-rendering-pixelated/index.html */
|
/* https://googlechrome.github.io/samples/image-rendering-pixelated/index.html */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make the carousel take up less space so we can click the backdrop and exit out of it */
|
|
||||||
[class*="modalCarouselWrapper_"] {
|
|
||||||
top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
[class*="carouselModal_"] {
|
|
||||||
height: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel");
|
||||||
const UserUtils = findByPropsLazy("getGlobalName");
|
const UserUtils = findByPropsLazy("getGlobalName");
|
||||||
|
|
||||||
const ProfileListClasses = findByPropsLazy("emptyIconFriends", "emptyIconGuilds");
|
const ProfileListClasses = findByPropsLazy("emptyIconFriends", "emptyIconGuilds");
|
||||||
const ExpandableList = findComponentByCodeLazy(".mutualFriendItem]");
|
const ExpandableList = findComponentByCodeLazy('"PRESS_SECTION"');
|
||||||
const GuildLabelClasses = findByPropsLazy("guildNick", "guildAvatarWithoutIcon");
|
const GuildLabelClasses = findByPropsLazy("guildNick", "guildAvatarWithoutIcon");
|
||||||
|
|
||||||
function getGroupDMName(channel: Channel) {
|
function getGroupDMName(channel: Channel) {
|
||||||
|
@ -142,16 +142,15 @@ export default definePlugin({
|
||||||
const mutualGDms = getMutualGroupDms(user.id);
|
const mutualGDms = getMutualGroupDms(user.id);
|
||||||
if (mutualGDms.length === 0) return null;
|
if (mutualGDms.length === 0) return null;
|
||||||
|
|
||||||
const header = getMutualGDMCountText(user);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Divider}
|
{Divider}
|
||||||
<ExpandableList
|
<ExpandableList
|
||||||
className={listStyle}
|
listClassName={listStyle}
|
||||||
header={header}
|
header={"Mutual Groups"}
|
||||||
isLoadingHeader={false}
|
isLoading={false}
|
||||||
children={renderClickableGDMs(mutualGDms, () => { })}
|
items={renderClickableGDMs(mutualGDms, () => { })}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -91,15 +91,6 @@ export default definePlugin({
|
||||||
replace: "async function $1 if(await $self.handleLink(...arguments)) return;"
|
replace: "async function $1 if(await $self.handleLink(...arguments)) return;"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Make Spotify profile activity links open in app on web
|
|
||||||
{
|
|
||||||
find: "WEB_OPEN(",
|
|
||||||
predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify,
|
|
||||||
replacement: {
|
|
||||||
match: /\i\.\i\.isProtocolRegistered\(\)(.{0,100})window.open/g,
|
|
||||||
replace: "true$1VencordNative.native.openExternal"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
find: "no artist ids in metadata",
|
find: "no artist ids in metadata",
|
||||||
predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify,
|
predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify,
|
||||||
|
|
|
@ -80,7 +80,10 @@ function GuildInfoModal({ guild }: GuildProps) {
|
||||||
className={cl("banner")}
|
className={cl("banner")}
|
||||||
src={bannerUrl}
|
src={bannerUrl}
|
||||||
alt=""
|
alt=""
|
||||||
onClick={() => openImageModal(bannerUrl)}
|
onClick={() => openImageModal({
|
||||||
|
url: bannerUrl,
|
||||||
|
width: 1024
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -89,8 +92,10 @@ function GuildInfoModal({ guild }: GuildProps) {
|
||||||
? <img
|
? <img
|
||||||
src={iconUrl}
|
src={iconUrl}
|
||||||
alt=""
|
alt=""
|
||||||
onClick={() => openImageModal(iconUrl, {
|
onClick={() => openImageModal({
|
||||||
width: 256
|
url: iconUrl,
|
||||||
|
height: 512,
|
||||||
|
width: 512,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
: <div aria-hidden className={classes(IconClasses.childWrapper, IconClasses.acronym)}>{guild.acronym}</div>
|
: <div aria-hidden className={classes(IconClasses.childWrapper, IconClasses.acronym)}>{guild.acronym}</div>
|
||||||
|
@ -153,7 +158,15 @@ function Owner(guildId: string, owner: User) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cl("owner")}>
|
<div className={cl("owner")}>
|
||||||
<img src={ownerAvatarUrl} alt="" onClick={() => openImageModal(ownerAvatarUrl)} />
|
<img
|
||||||
|
src={ownerAvatarUrl}
|
||||||
|
alt=""
|
||||||
|
onClick={() => openImageModal({
|
||||||
|
url: ownerAvatarUrl,
|
||||||
|
height: 512,
|
||||||
|
width: 512
|
||||||
|
})}
|
||||||
|
/>
|
||||||
{Parser.parse(`<@${owner.id}>`)}
|
{Parser.parse(`<@${owner.id}>`)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,8 +30,8 @@ export default definePlugin({
|
||||||
name: "ServerInfo",
|
name: "ServerInfo",
|
||||||
description: "Allows you to view info about a server",
|
description: "Allows you to view info about a server",
|
||||||
authors: [Devs.Ven, Devs.Nuckyz],
|
authors: [Devs.Ven, Devs.Nuckyz],
|
||||||
|
dependencies: ["DynamicImageModalAPI"],
|
||||||
tags: ["guild", "info", "ServerProfile"],
|
tags: ["guild", "info", "ServerProfile"],
|
||||||
dependencies: ["ImageModalAPI"],
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"guild-context": Patch,
|
"guild-context": Patch,
|
||||||
"guild-header-popout": Patch
|
"guild-header-popout": Patch
|
||||||
|
|
|
@ -229,7 +229,7 @@ function AlbumContextMenu({ track }: { track: Track; }) {
|
||||||
id="view-cover"
|
id="view-cover"
|
||||||
label="View Album Cover"
|
label="View Album Cover"
|
||||||
// trolley
|
// trolley
|
||||||
action={() => openImageModal(track.album.image.url)}
|
action={() => openImageModal(track.album.image)}
|
||||||
icon={ImageIcon}
|
icon={ImageIcon}
|
||||||
/>
|
/>
|
||||||
<Menu.MenuControlItem
|
<Menu.MenuControlItem
|
||||||
|
|
|
@ -33,7 +33,6 @@ export default definePlugin({
|
||||||
name: "SpotifyControls",
|
name: "SpotifyControls",
|
||||||
description: "Adds a Spotify player above the account panel",
|
description: "Adds a Spotify player above the account panel",
|
||||||
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000],
|
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000],
|
||||||
dependencies: ["ImageModalAPI"],
|
|
||||||
options: {
|
options: {
|
||||||
hoverControls: {
|
hoverControls: {
|
||||||
description: "Show controls on hover",
|
description: "Show controls on hover",
|
||||||
|
|
|
@ -67,7 +67,10 @@ const settings = definePluginSettings({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function openImage(url: string) {
|
const openAvatar = (url: string) => openImage(url, 512, 512);
|
||||||
|
const openBanner = (url: string) => openImage(url, 1024);
|
||||||
|
|
||||||
|
function openImage(url: string, width: number, height?: number) {
|
||||||
const format = url.startsWith("/") ? "png" : settings.store.format;
|
const format = url.startsWith("/") ? "png" : settings.store.format;
|
||||||
|
|
||||||
const u = new URL(url, window.location.href);
|
const u = new URL(url, window.location.href);
|
||||||
|
@ -76,11 +79,13 @@ function openImage(url: string) {
|
||||||
url = u.toString();
|
url = u.toString();
|
||||||
|
|
||||||
u.searchParams.set("size", "4096");
|
u.searchParams.set("size", "4096");
|
||||||
const originalUrl = u.toString();
|
const original = u.toString();
|
||||||
|
|
||||||
openImageModal(url, {
|
openImageModal({
|
||||||
original: originalUrl,
|
url,
|
||||||
height: 256
|
original,
|
||||||
|
width,
|
||||||
|
height
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,14 +98,14 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
id="view-avatar"
|
id="view-avatar"
|
||||||
label="View Avatar"
|
label="View Avatar"
|
||||||
action={() => openImage(IconUtils.getUserAvatarURL(user, true))}
|
action={() => openAvatar(IconUtils.getUserAvatarURL(user, true))}
|
||||||
icon={ImageIcon}
|
icon={ImageIcon}
|
||||||
/>
|
/>
|
||||||
{memberAvatar && (
|
{memberAvatar && (
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
id="view-server-avatar"
|
id="view-server-avatar"
|
||||||
label="View Server Avatar"
|
label="View Server Avatar"
|
||||||
action={() => openImage(IconUtils.getGuildMemberAvatarURLSimple({
|
action={() => openAvatar(IconUtils.getGuildMemberAvatarURLSimple({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
avatar: memberAvatar,
|
avatar: memberAvatar,
|
||||||
guildId: guildId!,
|
guildId: guildId!,
|
||||||
|
@ -126,7 +131,7 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon
|
||||||
id="view-icon"
|
id="view-icon"
|
||||||
label="View Icon"
|
label="View Icon"
|
||||||
action={() =>
|
action={() =>
|
||||||
openImage(IconUtils.getGuildIconURL({
|
openAvatar(IconUtils.getGuildIconURL({
|
||||||
id,
|
id,
|
||||||
icon,
|
icon,
|
||||||
canAnimate: true
|
canAnimate: true
|
||||||
|
@ -140,7 +145,7 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon
|
||||||
id="view-banner"
|
id="view-banner"
|
||||||
label="View Banner"
|
label="View Banner"
|
||||||
action={() =>
|
action={() =>
|
||||||
openImage(IconUtils.getGuildBannerURL(guild, true)!)
|
openBanner(IconUtils.getGuildBannerURL(guild, true)!)
|
||||||
}
|
}
|
||||||
icon={ImageIcon}
|
icon={ImageIcon}
|
||||||
/>
|
/>
|
||||||
|
@ -158,7 +163,7 @@ const GroupDMContext: NavContextMenuPatchCallback = (children, { channel }: Grou
|
||||||
id="view-group-channel-icon"
|
id="view-group-channel-icon"
|
||||||
label="View Icon"
|
label="View Icon"
|
||||||
action={() =>
|
action={() =>
|
||||||
openImage(IconUtils.getChannelIconURL(channel)!)
|
openAvatar(IconUtils.getChannelIconURL(channel)!)
|
||||||
}
|
}
|
||||||
icon={ImageIcon}
|
icon={ImageIcon}
|
||||||
/>
|
/>
|
||||||
|
@ -170,12 +175,13 @@ export default definePlugin({
|
||||||
name: "ViewIcons",
|
name: "ViewIcons",
|
||||||
authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz, Devs.nyx],
|
authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz, Devs.nyx],
|
||||||
description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.",
|
description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.",
|
||||||
dependencies: ["ImageModalAPI"],
|
|
||||||
tags: ["ImageUtilities"],
|
tags: ["ImageUtilities"],
|
||||||
|
dependencies: ["DynamicImageModalAPI"],
|
||||||
|
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
openImage,
|
openAvatar,
|
||||||
|
openBanner,
|
||||||
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"user-context": UserContext,
|
"user-context": UserContext,
|
||||||
|
@ -189,7 +195,7 @@ export default definePlugin({
|
||||||
find: ".overlay:void 0,status:",
|
find: ".overlay:void 0,status:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",{...\2,/,
|
match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",{...\2,/,
|
||||||
replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openImage($1)},"
|
replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openAvatar($1)},"
|
||||||
},
|
},
|
||||||
all: true
|
all: true
|
||||||
},
|
},
|
||||||
|
@ -198,7 +204,7 @@ export default definePlugin({
|
||||||
find: 'backgroundColor:"COMPLETE"',
|
find: 'backgroundColor:"COMPLETE"',
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(\.banner,.+?),style:{(?=.+?backgroundImage:null!=(\i)\?"url\("\.concat\(\2,)/,
|
match: /(\.banner,.+?),style:{(?=.+?backgroundImage:null!=(\i)\?"url\("\.concat\(\2,)/,
|
||||||
replace: (_, rest, bannerSrc) => `${rest},onClick:()=>${bannerSrc}!=null&&$self.openImage(${bannerSrc}),style:{cursor:${bannerSrc}!=null?"pointer":void 0,`
|
replace: (_, rest, bannerSrc) => `${rest},onClick:()=>${bannerSrc}!=null&&$self.openBanner(${bannerSrc}),style:{cursor:${bannerSrc}!=null?"pointer":void 0,`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Group DMs top small & large icon
|
// Group DMs top small & large icon
|
||||||
|
@ -206,7 +212,7 @@ export default definePlugin({
|
||||||
find: /\.recipients\.length>=2(?!<isMultiUserDM.{0,50})/,
|
find: /\.recipients\.length>=2(?!<isMultiUserDM.{0,50})/,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /null==\i\.icon\?.+?src:(\(0,\i\.\i\).+?\))(?=[,}])/,
|
match: /null==\i\.icon\?.+?src:(\(0,\i\.\i\).+?\))(?=[,}])/,
|
||||||
replace: (m, iconUrl) => `${m},onClick:()=>$self.openImage(${iconUrl})`
|
replace: (m, iconUrl) => `${m},onClick:()=>$self.openAvatar(${iconUrl})`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// User DMs top small icon
|
// User DMs top small icon
|
||||||
|
@ -214,7 +220,7 @@ export default definePlugin({
|
||||||
find: ".cursorPointer:null,children",
|
find: ".cursorPointer:null,children",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
|
match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
|
||||||
replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})`
|
replace: (m, avatarUrl) => `${m},onClick:()=>$self.openAvatar(${avatarUrl})`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// User Dms top large icon
|
// User Dms top large icon
|
||||||
|
@ -222,7 +228,7 @@ export default definePlugin({
|
||||||
find: 'experimentLocation:"empty_messages"',
|
find: 'experimentLocation:"empty_messages"',
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
|
match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
|
||||||
replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})`
|
replace: (m, avatarUrl) => `${m},onClick:()=>$self.openAvatar(${avatarUrl})`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -25,7 +25,7 @@ const KeyBinds = findByPropsLazy("JUMP_TO_GUILD", "SERVER_NEXT");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "WebKeybinds",
|
name: "WebKeybinds",
|
||||||
description: "Re-adds keybinds missing in the web version of Discord: ctrl+t, ctrl+shift+t, ctrl+tab, ctrl+shift+tab, ctrl+1-9, ctrl+,. Only works fully on Vesktop/ArmCord, not inside your browser",
|
description: "Re-adds keybinds missing in the web version of Discord: ctrl+t, ctrl+shift+t, ctrl+tab, ctrl+shift+tab, ctrl+1-9, ctrl+,. Only works fully on Vesktop/Legcord, not inside your browser",
|
||||||
authors: [Devs.Ven],
|
authors: [Devs.Ven],
|
||||||
enabledByDefault: true,
|
enabledByDefault: true,
|
||||||
|
|
||||||
|
|
|
@ -928,6 +928,10 @@ export const EquicordDevs = Object.freeze({
|
||||||
name: "Leko",
|
name: "Leko",
|
||||||
id: 108153734541942784n
|
id: 108153734541942784n
|
||||||
},
|
},
|
||||||
|
SomeAspy: {
|
||||||
|
name: "SomeAspy",
|
||||||
|
id: 516750892372852754n,
|
||||||
|
},
|
||||||
} satisfies Record<string, Dev>);
|
} satisfies Record<string, Dev>);
|
||||||
|
|
||||||
// iife so #__PURE__ works correctly
|
// iife so #__PURE__ works correctly
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
.vc-imagemodal-fix {
|
|
||||||
|
.vc-position-inherit {
|
||||||
position: inherit;
|
position: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy pasted from discord css. not really webpack-findable since it's the only class in the module
|
||||||
|
**/
|
||||||
|
|
||||||
|
.vc-image-modal {
|
||||||
|
background: transparent!important;
|
||||||
|
box-shadow: none!important;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(width <= 485px) {
|
||||||
|
.vc-image-modal {
|
||||||
|
display:relative;
|
||||||
|
overflow: visible;
|
||||||
|
overflow: initial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
import "./discord.css";
|
import "./discord.css";
|
||||||
|
|
||||||
import { MessageObject } from "@api/MessageEvents";
|
import { MessageObject } from "@api/MessageEvents";
|
||||||
import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
|
import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
|
||||||
import { Channel, Guild, Message, User } from "discord-types/general";
|
import { Channel, Guild, Message, User } from "discord-types/general";
|
||||||
|
|
||||||
import { ImageModal, openModal } from "./modal";
|
import { ImageModal, ImageModalItem, openModal } from "./modal";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the invite modal
|
* Open the invite modal
|
||||||
|
@ -110,23 +110,23 @@ export function sendMessage(
|
||||||
return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra);
|
return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FIX_CLASS_NAME = "vc-imagemodal-fix";
|
/**
|
||||||
|
* You must specify either height or width
|
||||||
export function openImageModal(url: string, props?: Partial<React.ComponentProps<ImageModal>>): string {
|
*/
|
||||||
|
export function openImageModal(props: Omit<ImageModalItem, "type">): string {
|
||||||
return openModal(modalProps => (
|
return openModal(modalProps => (
|
||||||
<ImageModal
|
<ImageModal
|
||||||
{...modalProps}
|
{...modalProps}
|
||||||
renderLinkComponent={props => <MaskedLink {...props} />}
|
className="vc-image-modal"
|
||||||
// Don't render forward message button scaleDown_f97a12 contain_f97a12
|
fit="vc-position-inherit"
|
||||||
renderForwardComponent={() => null}
|
|
||||||
shouldHideMediaOptions={false}
|
|
||||||
shouldAnimate={true}
|
|
||||||
fit={FIX_CLASS_NAME}
|
|
||||||
items={[{
|
items={[{
|
||||||
...props,
|
|
||||||
type: "IMAGE",
|
type: "IMAGE",
|
||||||
url,
|
original: props.url,
|
||||||
|
...props,
|
||||||
}]}
|
}]}
|
||||||
|
onClose={modalProps.onClose}
|
||||||
|
shouldHideMediaOptions={false}
|
||||||
|
shouldAnimate
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,23 +101,21 @@ export const Modals = findByPropsLazy("ModalRoot", "ModalCloseButton") as {
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: type this
|
export interface ImageModalItem {
|
||||||
export type ImageModal = any & ComponentType<{
|
type: "IMAGE" | "VIDEO";
|
||||||
className?: string;
|
url: string;
|
||||||
src: string;
|
|
||||||
placeholder: string;
|
|
||||||
original: string;
|
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
animated?: boolean;
|
original?: string;
|
||||||
responsive?: boolean;
|
}
|
||||||
renderLinkComponent(props: any): ReactNode;
|
|
||||||
renderForwardComponent(props: any): ReactNode;
|
export type ImageModal = ComponentType<{
|
||||||
maxWidth?: number;
|
className?: string;
|
||||||
maxHeight?: number;
|
fit?: string;
|
||||||
shouldAnimate?: boolean;
|
|
||||||
onClose?(): void;
|
onClose?(): void;
|
||||||
shouldHideMediaOptions?: boolean;
|
shouldHideMediaOptions?: boolean;
|
||||||
|
shouldAnimate?: boolean;
|
||||||
|
items: ImageModalItem[];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export const ImageModal = findComponentByCodeLazy(".MEDIA_MODAL_CLOSE") as ImageModal;
|
export const ImageModal = findComponentByCodeLazy(".MEDIA_MODAL_CLOSE") as ImageModal;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue