mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-08 06:03:03 -04:00
add wallpaperFree (#262)
* add wallpaperFree * fix lint ???????? * fix lint again * Fixes --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
parent
1c24c4d173
commit
78209ef7bf
7 changed files with 453 additions and 1 deletions
|
@ -98,7 +98,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
|
||||||
- JumpToStart by Samwich
|
- JumpToStart by Samwich
|
||||||
- KeyboardSounds by HypedDomi
|
- KeyboardSounds by HypedDomi
|
||||||
- KeywordNotify by camila314 & x3rt
|
- KeywordNotify by camila314 & x3rt
|
||||||
- - LastActive by Crxa
|
- LastActive by Crxa
|
||||||
- LimitMiddleClickPaste by no dev listed
|
- LimitMiddleClickPaste by no dev listed
|
||||||
- LoginWithQR by nexpid
|
- LoginWithQR by nexpid
|
||||||
- MediaPlaybackSpeed by D3SOX
|
- MediaPlaybackSpeed by D3SOX
|
||||||
|
@ -177,6 +177,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
|
||||||
- ViewRawVariant by Kyuuhachi
|
- ViewRawVariant by Kyuuhachi
|
||||||
- VoiceChatUtilities by D3SOX
|
- VoiceChatUtilities by D3SOX
|
||||||
- VoiceJoinMessages by Sqaaakoi & maintained by thororen
|
- VoiceJoinMessages by Sqaaakoi & maintained by thororen
|
||||||
|
- WallpaperFree by Joona
|
||||||
- WebpackTarball by Kyuuhachi
|
- WebpackTarball by Kyuuhachi
|
||||||
- WhitelistedEmojis by Creations
|
- WhitelistedEmojis by Creations
|
||||||
- WhosWatching by fres
|
- WhosWatching by fres
|
||||||
|
|
67
src/equicordplugins/wallpaperFree/components/ctxmenu.tsx
Normal file
67
src/equicordplugins/wallpaperFree/components/ctxmenu.tsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2025 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
|
import { openModal } from "@utils/modal";
|
||||||
|
import { ChannelStore, FluxDispatcher, Menu } from "@webpack/common";
|
||||||
|
|
||||||
|
import { SetCustomWallpaperModal, SetDiscordWallpaperModal } from "./modal";
|
||||||
|
import { ChatWallpaperStore, fetchWallpapers } from "./util";
|
||||||
|
|
||||||
|
|
||||||
|
const addWallpaperMenu = (channelId?: string, guildId?: string) => {
|
||||||
|
const setWallpaper = (url?: string) => {
|
||||||
|
FluxDispatcher.dispatch({
|
||||||
|
// @ts-ignore
|
||||||
|
type: "VC_WALLPAPER_FREE_CHANGE",
|
||||||
|
channelId,
|
||||||
|
guildId,
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Menu.MenuItem label="Wallpaper Free" key="vc-wpfree-menu" id="vc-wpfree-menu">
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="Set custom wallpaper"
|
||||||
|
id="vc-wpfree-set-custom"
|
||||||
|
action={() => openModal(props => <SetCustomWallpaperModal props={props} onSelect={setWallpaper} />)}
|
||||||
|
/>
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="Set a Discord wallpaper"
|
||||||
|
id="vc-wpfree-set-discord"
|
||||||
|
action={async () => {
|
||||||
|
ChatWallpaperStore.shouldFetchWallpapers && await fetchWallpapers();
|
||||||
|
openModal(props => <SetDiscordWallpaperModal props={props} onSelect={setWallpaper} />);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Menu.MenuSeparator />
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="Remove Custom Wallpaper"
|
||||||
|
id="vc-wpfree-remove"
|
||||||
|
color="danger"
|
||||||
|
action={() => setWallpaper(void 0)}
|
||||||
|
/>
|
||||||
|
</Menu.MenuItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserContextPatch: NavContextMenuPatchCallback = (children, args) => {
|
||||||
|
if (!args.user) return;
|
||||||
|
const dmChannelId = ChannelStore.getDMFromUserId(args.user.id);
|
||||||
|
children.push(addWallpaperMenu(dmChannelId));
|
||||||
|
};
|
||||||
|
|
||||||
|
const ChannelContextPatch: NavContextMenuPatchCallback = (children, args) => {
|
||||||
|
if (!args.channel) return;
|
||||||
|
children.push(addWallpaperMenu(args.channel.id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const GuildContextPatch: NavContextMenuPatchCallback = (children, args) => {
|
||||||
|
if (!args.guild) return;
|
||||||
|
children.push(addWallpaperMenu(void 0, args.guild.id));
|
||||||
|
};
|
||||||
|
|
||||||
|
export { ChannelContextPatch, GuildContextPatch, UserContextPatch };
|
116
src/equicordplugins/wallpaperFree/components/modal.tsx
Normal file
116
src/equicordplugins/wallpaperFree/components/modal.tsx
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2025 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal";
|
||||||
|
import { Button, lodash, Text, TextInput, useState, useStateFromStores } from "@webpack/common";
|
||||||
|
|
||||||
|
import { ChatWallpaperStore, Wallpaper } from "./util";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
props: ModalProps;
|
||||||
|
onSelect: (url: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SetCustomWallpaperModal({ props, onSelect }: Props) {
|
||||||
|
const [url, setUrl] = useState("");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalRoot {...props} size={ModalSize.SMALL}>
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/normal" style={{ marginBottom: 8 }}>
|
||||||
|
Set a custom wallpaper
|
||||||
|
</Text>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
placeholder="The image url"
|
||||||
|
value={url}
|
||||||
|
onChange={setUrl}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
{url && (
|
||||||
|
<img
|
||||||
|
src={url}
|
||||||
|
alt="Wallpaper preview"
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
width: "100%",
|
||||||
|
height: "auto",
|
||||||
|
objectFit: "cover",
|
||||||
|
border: "1px solid var(--background-modifier-accent)",
|
||||||
|
borderRadius: 8
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
|
||||||
|
<Button onClick={props.onClose}>Cancel</Button>
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.BRAND}
|
||||||
|
onClick={() => {
|
||||||
|
onSelect(url);
|
||||||
|
props.onClose();
|
||||||
|
}}
|
||||||
|
disabled={!url}
|
||||||
|
>Apply</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalContent>
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SetDiscordWallpaperModal({ props, onSelect }: Props) {
|
||||||
|
const discordWallpapers: Wallpaper[] = useStateFromStores([ChatWallpaperStore], () => ChatWallpaperStore.wallpapers);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalRoot {...props} size={ModalSize.MEDIUM}>
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/normal" style={{ marginBottom: 8 }}>
|
||||||
|
Choose a Discord Wallpaper
|
||||||
|
</Text>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent>
|
||||||
|
<div className="vc-wpfree-discord-wp-modal">
|
||||||
|
{lodash.chunk(discordWallpapers, 2).map(group => {
|
||||||
|
const main = group[0];
|
||||||
|
return (
|
||||||
|
<div key={main.id} className="vc-wpfree-discord-wp-icon-container">
|
||||||
|
<figure style={{ margin: 0, textAlign: "center" }}>
|
||||||
|
<img
|
||||||
|
className="vc-wpfree-discord-wp-icon-img"
|
||||||
|
src={`https://cdn.discordapp.com/assets/content/${main.default.icon}`}
|
||||||
|
alt={main.label}
|
||||||
|
/>
|
||||||
|
<figcaption>
|
||||||
|
<Text variant="text-md/normal">{main.label}</Text>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<div className="vc-wpfree-discord-set-buttons">
|
||||||
|
{group.map(wp => (
|
||||||
|
<Button
|
||||||
|
key={wp.id}
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
color={Button.Colors.BRAND}
|
||||||
|
onClick={() => {
|
||||||
|
onSelect(`https://cdn.discordapp.com/assets/content/${wp.default.asset}`);
|
||||||
|
props.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{wp.isBlurred ? "Blurred" : "Normal"}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</ModalContent>
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
70
src/equicordplugins/wallpaperFree/components/util.tsx
Normal file
70
src/equicordplugins/wallpaperFree/components/util.tsx
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2025 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { openModal } from "@utils/modal";
|
||||||
|
import { findByCodeLazy, findStoreLazy } from "@webpack";
|
||||||
|
import { Button, FluxDispatcher } from "@webpack/common";
|
||||||
|
|
||||||
|
import { SetCustomWallpaperModal, SetDiscordWallpaperModal } from "./modal";
|
||||||
|
|
||||||
|
export const ChatWallpaperStore = findStoreLazy("ChatWallpaperStore");
|
||||||
|
export const fetchWallpapers = findByCodeLazy('type:"FETCH_CHAT_WALLPAPERS_SUCCESS"');
|
||||||
|
|
||||||
|
export function GlobalDefaultComponent() {
|
||||||
|
const setGlobal = (url?: string) => {
|
||||||
|
FluxDispatcher.dispatch({
|
||||||
|
// @ts-ignore
|
||||||
|
type: "VC_WALLPAPER_FREE_CHANGE_GLOBAL",
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button onClick={() => {
|
||||||
|
openModal(props => <SetCustomWallpaperModal props={props} onSelect={setGlobal} />);
|
||||||
|
}}>Set a global custom wallpaper</Button>
|
||||||
|
|
||||||
|
<Button onClick={async () => {
|
||||||
|
ChatWallpaperStore.shouldFetchWallpapers && await fetchWallpapers();
|
||||||
|
openModal(props => <SetDiscordWallpaperModal props={props} onSelect={setGlobal} />);
|
||||||
|
}}>Set a global Discord wallpaper</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.RED}
|
||||||
|
onClick={() => setGlobal(void 0)}
|
||||||
|
>Remove global default wallpaper</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.RED}
|
||||||
|
onClick={() => {
|
||||||
|
// @ts-ignore
|
||||||
|
FluxDispatcher.dispatch({ type: "VC_WALLPAPER_FREE_RESET" });
|
||||||
|
}}
|
||||||
|
>Reset wallpaper data</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Wallpaper {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
default: Default;
|
||||||
|
variants: Variants;
|
||||||
|
isBlurred: boolean;
|
||||||
|
designGroupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Default {
|
||||||
|
asset: string;
|
||||||
|
icon: string;
|
||||||
|
thumbhash: string;
|
||||||
|
opacity?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Variants {
|
||||||
|
dark: Default;
|
||||||
|
}
|
86
src/equicordplugins/wallpaperFree/index.tsx
Normal file
86
src/equicordplugins/wallpaperFree/index.tsx
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./styles.css";
|
||||||
|
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
import { useStateFromStores } from "@webpack/common";
|
||||||
|
import { Channel } from "discord-types/general";
|
||||||
|
|
||||||
|
import { ChannelContextPatch, GuildContextPatch, UserContextPatch } from "./components/ctxmenu";
|
||||||
|
import { GlobalDefaultComponent, Wallpaper } from "./components/util";
|
||||||
|
import { WallpaperFreeStore } from "./store";
|
||||||
|
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
forceReplace: {
|
||||||
|
description: "If a dm wallpaper is already set, your custom wallpaper will be used instead.",
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
globalDefault: {
|
||||||
|
description: "Set a global default wallpaper for all channels.",
|
||||||
|
type: OptionType.COMPONENT,
|
||||||
|
component: GlobalDefaultComponent
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "WallpaperFree",
|
||||||
|
authors: [Devs.Joona],
|
||||||
|
description: "Use the DM wallpapers anywhere or set a custom wallpaper",
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: ".wallpaperContainer,",
|
||||||
|
group: true,
|
||||||
|
replacement: [
|
||||||
|
{
|
||||||
|
match: /return null==(\i).+?\?null:/,
|
||||||
|
replace: "const vcWpFreeCustom = $self.customWallpaper(arguments[0].channel,$1);return !($1||vcWpFreeCustom)?null:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /,{chatWallpaperState:/,
|
||||||
|
replace: "$&vcWpFreeCustom||"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /(\i=)(.{1,50}""\))/,
|
||||||
|
replace: "$1arguments[0].chatWallpaperState.vcWallpaperUrl||$2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /(\i\.isViewable&&)(null!=\i)/,
|
||||||
|
replace: "$1($2||arguments[0].chatWallpaperState.vcWallpaperUrl)"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
settings,
|
||||||
|
contextMenus: {
|
||||||
|
"user-context": UserContextPatch,
|
||||||
|
"channel-context": ChannelContextPatch,
|
||||||
|
"thread-context": ChannelContextPatch,
|
||||||
|
"guild-context": GuildContextPatch,
|
||||||
|
"gdm-context": ChannelContextPatch,
|
||||||
|
},
|
||||||
|
customWallpaper(channel: Channel, wp: Wallpaper | undefined) {
|
||||||
|
const { forceReplace } = settings.use(["forceReplace"]);
|
||||||
|
const url = useStateFromStores([WallpaperFreeStore], () => WallpaperFreeStore.getUrl(channel));
|
||||||
|
|
||||||
|
if (!forceReplace && wp?.id)
|
||||||
|
return wp;
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
return {
|
||||||
|
wallpaperId: "id",
|
||||||
|
vcWallpaperUrl: url,
|
||||||
|
isViewable: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return void 0;
|
||||||
|
},
|
||||||
|
});
|
82
src/equicordplugins/wallpaperFree/store.ts
Normal file
82
src/equicordplugins/wallpaperFree/store.ts
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { proxyLazy } from "@utils/lazy";
|
||||||
|
import { findByPropsLazy } from "@webpack";
|
||||||
|
import { FluxDispatcher } from "@webpack/common";
|
||||||
|
import { FluxEmitter, FluxStore } from "@webpack/types";
|
||||||
|
import { Channel } from "discord-types/general";
|
||||||
|
|
||||||
|
interface IFlux {
|
||||||
|
PersistedStore: typeof FluxStore;
|
||||||
|
Emitter: FluxEmitter;
|
||||||
|
}
|
||||||
|
const Flux: IFlux = findByPropsLazy("connectStores");
|
||||||
|
|
||||||
|
export const WallpaperFreeStore = proxyLazy(() => {
|
||||||
|
const wallpaperChannelMap: Map<string, string> = new Map();
|
||||||
|
const wallpaperGuildMap: Map<string, string> = new Map();
|
||||||
|
let globalDefault: string | undefined;
|
||||||
|
|
||||||
|
class WallpaperFreeStore extends Flux.PersistedStore {
|
||||||
|
static persistKey = "WallpaperFreeStore";
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
initialize(previous: { guildMap: Map<string, string>, channelMap: Map<string, string>, globalDefault: string; } | undefined) {
|
||||||
|
if (!previous)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wallpaperGuildMap.clear();
|
||||||
|
wallpaperChannelMap.clear();
|
||||||
|
for (const [channel, url] of previous.channelMap) {
|
||||||
|
wallpaperChannelMap.set(channel, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [guild, url] of previous.guildMap) {
|
||||||
|
wallpaperGuildMap.set(guild, url);
|
||||||
|
}
|
||||||
|
globalDefault = previous.globalDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
getState() {
|
||||||
|
return { guildMap: Array.from(wallpaperGuildMap), channelMap: Array.from(wallpaperChannelMap), globalDefault };
|
||||||
|
}
|
||||||
|
|
||||||
|
getUrl(channel: Channel): string | undefined {
|
||||||
|
return (
|
||||||
|
wallpaperChannelMap.get(channel.id) ??
|
||||||
|
wallpaperGuildMap.get(channel.guild_id) ??
|
||||||
|
globalDefault
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = new WallpaperFreeStore(FluxDispatcher, {
|
||||||
|
// @ts-ignore
|
||||||
|
VC_WALLPAPER_FREE_CHANGE({ guildId, channelId, url }: { guildId: string | undefined, channelId: string | undefined, url: string; }) {
|
||||||
|
if (guildId) {
|
||||||
|
wallpaperGuildMap.set(guildId, url);
|
||||||
|
} else if (channelId) {
|
||||||
|
wallpaperChannelMap.set(channelId, url);
|
||||||
|
}
|
||||||
|
store.emitChange();
|
||||||
|
},
|
||||||
|
|
||||||
|
VC_WALLPAPER_FREE_CHANGE_GLOBAL({ url }: { url: string | undefined; }) {
|
||||||
|
globalDefault = url;
|
||||||
|
store.emitChange();
|
||||||
|
},
|
||||||
|
|
||||||
|
VC_WALLPAPER_FREE_RESET() {
|
||||||
|
wallpaperChannelMap.clear();
|
||||||
|
wallpaperGuildMap.clear();
|
||||||
|
globalDefault = void 0;
|
||||||
|
store.emitChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return store;
|
||||||
|
});
|
30
src/equicordplugins/wallpaperFree/styles.css
Normal file
30
src/equicordplugins/wallpaperFree/styles.css
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
.vc-wpfree-discord-wp-modal {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 24px;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-wpfree-discord-wp-icon-container {
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 8px rgb(0 0 0 / 8%);
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-wpfree-discord-wp-icon-img {
|
||||||
|
width: 120px;
|
||||||
|
height: 68px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
border: 1px solid var(--background-modifier-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-wpfree-discord-set-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 12px
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue