mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-02-24 15:35:11 +00:00
Merge branch 'dev' into managed-styles-rewrite (Rename style to managedStyle in PluginDef)
This commit is contained in:
parent
bc1eb3d67e
commit
d766db1002
18 changed files with 109 additions and 69 deletions
|
@ -43,20 +43,21 @@ interface DecoratorProps {
|
|||
export type MemberListDecoratorFactory = (props: DecoratorProps) => JSX.Element | null;
|
||||
type OnlyIn = "guilds" | "dms";
|
||||
|
||||
export const decorators = new Map<string, { render: MemberListDecoratorFactory, onlyIn?: OnlyIn; }>();
|
||||
export const decoratorsFactories = new Map<string, { render: MemberListDecoratorFactory, onlyIn?: OnlyIn; }>();
|
||||
|
||||
export function addMemberListDecorator(identifier: string, render: MemberListDecoratorFactory, onlyIn?: OnlyIn) {
|
||||
decorators.set(identifier, { render, onlyIn });
|
||||
decoratorsFactories.set(identifier, { render, onlyIn });
|
||||
}
|
||||
|
||||
export function removeMemberListDecorator(identifier: string) {
|
||||
decorators.delete(identifier);
|
||||
decoratorsFactories.delete(identifier);
|
||||
}
|
||||
|
||||
export function __getDecorators(props: DecoratorProps): (JSX.Element | null)[] {
|
||||
export function __getDecorators(props: DecoratorProps): JSX.Element {
|
||||
const isInGuild = !!(props.guildId);
|
||||
return Array.from(
|
||||
decorators.entries(),
|
||||
|
||||
const decorators = Array.from(
|
||||
decoratorsFactories.entries(),
|
||||
([key, { render: Decorator, onlyIn }]) => {
|
||||
if ((onlyIn === "guilds" && !isInGuild) || (onlyIn === "dms" && isInGuild))
|
||||
return null;
|
||||
|
@ -68,4 +69,10 @@ export function __getDecorators(props: DecoratorProps): (JSX.Element | null)[] {
|
|||
);
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="vc-member-list-decorators-wrapper">
|
||||
{decorators}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,23 +48,29 @@ export interface MessageDecorationProps {
|
|||
}
|
||||
export type MessageDecorationFactory = (props: MessageDecorationProps) => JSX.Element | null;
|
||||
|
||||
export const decorations = new Map<string, MessageDecorationFactory>();
|
||||
export const decorationsFactories = new Map<string, MessageDecorationFactory>();
|
||||
|
||||
export function addMessageDecoration(identifier: string, decoration: MessageDecorationFactory) {
|
||||
decorations.set(identifier, decoration);
|
||||
decorationsFactories.set(identifier, decoration);
|
||||
}
|
||||
|
||||
export function removeMessageDecoration(identifier: string) {
|
||||
decorations.delete(identifier);
|
||||
decorationsFactories.delete(identifier);
|
||||
}
|
||||
|
||||
export function __addDecorationsToMessage(props: MessageDecorationProps): (JSX.Element | null)[] {
|
||||
return Array.from(
|
||||
decorations.entries(),
|
||||
export function __addDecorationsToMessage(props: MessageDecorationProps): JSX.Element {
|
||||
const decorations = Array.from(
|
||||
decorationsFactories.entries(),
|
||||
([key, Decoration]) => (
|
||||
<ErrorBoundary noop message={`Failed to render ${key} Message Decoration`} key={key}>
|
||||
<Decoration {...props} />
|
||||
</ErrorBoundary>
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="vc-message-decorations-wrapper">
|
||||
{decorations}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,10 +19,15 @@
|
|||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import managedStyle from "./style.css?managed";
|
||||
|
||||
export default definePlugin({
|
||||
name: "MemberListDecoratorsAPI",
|
||||
description: "API to add decorators to member list (both in servers and DMs)",
|
||||
authors: [Devs.TheSun, Devs.Ven],
|
||||
|
||||
managedStyle,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: ".lostPermission)",
|
||||
|
@ -32,7 +37,7 @@ export default definePlugin({
|
|||
replace: "$&vencordProps=$1,"
|
||||
}, {
|
||||
match: /#{intl::GUILD_OWNER}(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/,
|
||||
replace: "$&...(typeof vencordProps=='undefined'?[]:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps)),"
|
||||
replace: "$&(typeof vencordProps=='undefined'?null:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps)),"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -40,8 +45,8 @@ export default definePlugin({
|
|||
find: "PrivateChannel.renderAvatar",
|
||||
replacement: {
|
||||
match: /decorators:(\i\.isSystemDM\(\))\?(.+?):null/,
|
||||
replace: "decorators:[...Vencord.Api.MemberListDecorators.__getDecorators(arguments[0]), $1?$2:null]"
|
||||
replace: "decorators:[Vencord.Api.MemberListDecorators.__getDecorators(arguments[0]),$1?$2:null]"
|
||||
}
|
||||
}
|
||||
],
|
||||
]
|
||||
});
|
11
src/plugins/_api/memberListDecorators/style.css
Normal file
11
src/plugins/_api/memberListDecorators/style.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
.vc-member-list-decorators-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.25em;
|
||||
}
|
||||
|
||||
.vc-member-list-decorators-wrapper:not(:empty) {
|
||||
/* Margin to match default Discord decorators */
|
||||
margin-left: 0.25em;
|
||||
}
|
|
@ -19,17 +19,22 @@
|
|||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import managedStyle from "./style.css?managed";
|
||||
|
||||
export default definePlugin({
|
||||
name: "MessageDecorationsAPI",
|
||||
description: "API to add decorations to messages",
|
||||
authors: [Devs.TheSun],
|
||||
|
||||
managedStyle,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: '"Message Username"',
|
||||
replacement: {
|
||||
match: /#{intl::GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE}.+?}\),\i(?=\])/,
|
||||
replace: "$&,...Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])"
|
||||
replace: "$&,Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])"
|
||||
}
|
||||
}
|
||||
],
|
||||
]
|
||||
});
|
18
src/plugins/_api/messageDecorations/style.css
Normal file
18
src/plugins/_api/messageDecorations/style.css
Normal file
|
@ -0,0 +1,18 @@
|
|||
.vc-message-decorations-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.25em;
|
||||
}
|
||||
|
||||
.vc-message-decorations-wrapper:not(:empty) {
|
||||
/* Margin to match default Discord decorators */
|
||||
margin-left: 0.25em;
|
||||
|
||||
/* Align vertically */
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
top: 0.1rem;
|
||||
height: calc(1rem + 4px);
|
||||
max-height: calc(1rem + 4px)
|
||||
}
|
|
@ -21,12 +21,13 @@ import { setStyleVariables } from "@api/Styles";
|
|||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
import style from "./style.css?managed";
|
||||
import managedStyle from "./style.css?managed";
|
||||
|
||||
export default definePlugin({
|
||||
name: "BlurNSFW",
|
||||
description: "Blur attachments in NSFW channels until hovered",
|
||||
authors: [Devs.Ven],
|
||||
managedStyle,
|
||||
|
||||
patches: [
|
||||
{
|
||||
|
@ -44,14 +45,12 @@ export default definePlugin({
|
|||
description: "Blur Amount (in pixels)",
|
||||
default: 10,
|
||||
onChange(v) {
|
||||
setStyleVariables(style, { blurAmount: v });
|
||||
setStyleVariables(managedStyle, { blurAmount: v });
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
start() {
|
||||
setStyleVariables(style, { blurAmount: this.settings.store.blurAmount });
|
||||
},
|
||||
|
||||
style
|
||||
setStyleVariables(managedStyle, { blurAmount: this.settings.store.blurAmount });
|
||||
}
|
||||
});
|
||||
|
|
|
@ -33,11 +33,11 @@ function getEmojiMarkdown(target: Target, copyUnicode: boolean): string {
|
|||
: `:${emojiName}:`;
|
||||
}
|
||||
|
||||
const extension = target?.firstChild.src.match(
|
||||
/https:\/\/cdn\.discordapp\.com\/emojis\/\d+\.(\w+)/
|
||||
)?.[1];
|
||||
const url = new URL(target.firstChild.src);
|
||||
const hasParam = url.searchParams.get("animated") === "true";
|
||||
const isGif = url.pathname.endsWith(".gif");
|
||||
|
||||
return `<${extension === "gif" ? "a" : ""}:${emojiName.replace(/~\d+$/, "")}:${emojiId}>`;
|
||||
return `<${(hasParam || isGif) ? "a" : ""}:${emojiName.replace(/~\d+$/, "")}:${emojiId}>`;
|
||||
}
|
||||
|
||||
const settings = definePluginSettings({
|
||||
|
@ -55,7 +55,7 @@ export default definePlugin({
|
|||
settings,
|
||||
|
||||
contextMenus: {
|
||||
"expression-picker"(children, { target }: { target: Target }) {
|
||||
"expression-picker"(children, { target }: { target: Target; }) {
|
||||
if (target.dataset.type !== "emoji") return;
|
||||
|
||||
children.push(
|
||||
|
|
|
@ -23,7 +23,7 @@ import { Devs } from "@utils/constants";
|
|||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
|
||||
import style from "./style.css?managed";
|
||||
import managedStyle from "./style.css?managed";
|
||||
|
||||
const Button = findComponentByCodeLazy(".NONE,disabled:", ".PANEL_BUTTON");
|
||||
|
||||
|
@ -89,6 +89,8 @@ export default definePlugin({
|
|||
dependencies: ["UserSettingsAPI"],
|
||||
settings,
|
||||
|
||||
managedStyle,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
|
@ -101,5 +103,4 @@ export default definePlugin({
|
|||
|
||||
GameActivityToggleButton: ErrorBoundary.wrap(GameActivityToggleButton, { noop: true }),
|
||||
|
||||
style
|
||||
});
|
||||
|
|
|
@ -28,7 +28,7 @@ import type { Root } from "react-dom/client";
|
|||
|
||||
import { Magnifier, MagnifierProps } from "./components/Magnifier";
|
||||
import { ELEMENT_ID } from "./constants";
|
||||
import style from "./styles.css?managed";
|
||||
import managedStyle from "./styles.css?managed";
|
||||
|
||||
export const settings = definePluginSettings({
|
||||
saveZoomValues: {
|
||||
|
@ -159,6 +159,8 @@ export default definePlugin({
|
|||
authors: [Devs.Aria],
|
||||
tags: ["ImageUtilities"],
|
||||
|
||||
managedStyle,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: ".contain,SCALE_DOWN:",
|
||||
|
@ -260,7 +262,5 @@ export default definePlugin({
|
|||
// so componenetWillUnMount gets called if Magnifier component is still alive
|
||||
this.root && this.root.unmount();
|
||||
this.element?.remove();
|
||||
},
|
||||
|
||||
style
|
||||
}
|
||||
});
|
||||
|
|
|
@ -255,7 +255,7 @@ export function subscribeAllPluginsFluxEvents(fluxDispatcher: typeof FluxDispatc
|
|||
|
||||
export const startPlugin = traceFunction("startPlugin", function startPlugin(p: Plugin) {
|
||||
const {
|
||||
name, commands, contextMenus, style, userProfileBadge,
|
||||
name, commands, contextMenus, managedStyle, userProfileBadge,
|
||||
onBeforeMessageEdit, onBeforeMessageSend, onMessageClick,
|
||||
renderChatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton
|
||||
} = p;
|
||||
|
@ -299,7 +299,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p:
|
|||
}
|
||||
}
|
||||
|
||||
if (style) enableStyle(style);
|
||||
if (managedStyle) enableStyle(managedStyle);
|
||||
|
||||
if (userProfileBadge) addProfileBadge(userProfileBadge);
|
||||
|
||||
|
@ -318,7 +318,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p:
|
|||
|
||||
export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plugin) {
|
||||
const {
|
||||
name, commands, contextMenus, style, userProfileBadge,
|
||||
name, commands, contextMenus, managedStyle, userProfileBadge,
|
||||
onBeforeMessageEdit, onBeforeMessageSend, onMessageClick,
|
||||
renderChatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton
|
||||
} = p;
|
||||
|
@ -360,7 +360,7 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu
|
|||
}
|
||||
}
|
||||
|
||||
if (style) disableStyle(style);
|
||||
if (managedStyle) disableStyle(managedStyle);
|
||||
|
||||
if (userProfileBadge) removeProfileBadge(userProfileBadge);
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] {
|
|||
}));
|
||||
}
|
||||
|
||||
const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => {
|
||||
const PlatformIndicator = ({ user, small = false }: { user: User; small?: boolean; }) => {
|
||||
if (!user || user.bot) return null;
|
||||
|
||||
ensureOwnStatus(user);
|
||||
|
@ -155,11 +155,7 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
|
|||
return (
|
||||
<span
|
||||
className="vc-platform-indicator"
|
||||
style={{
|
||||
marginLeft: wantMargin ? 4 : 0,
|
||||
top: wantTopMargin ? 2 : 0,
|
||||
gap: 2
|
||||
}}
|
||||
style={{ gap: "2px" }}
|
||||
>
|
||||
{icons}
|
||||
</span>
|
||||
|
@ -190,7 +186,7 @@ const indicatorLocations = {
|
|||
description: "Inside messages",
|
||||
onEnable: () => addMessageDecoration("platform-indicator", props =>
|
||||
<ErrorBoundary noop>
|
||||
<PlatformIndicator user={props.message?.author} wantTopMargin={true} />
|
||||
<PlatformIndicator user={props.message?.author} />
|
||||
</ErrorBoundary>
|
||||
),
|
||||
onDisable: () => removeMessageDecoration("platform-indicator")
|
||||
|
|
|
@ -130,15 +130,13 @@ function VoiceChannelTooltip({ channel, isLocked }: VoiceChannelTooltipProps) {
|
|||
|
||||
interface VoiceChannelIndicatorProps {
|
||||
userId: string;
|
||||
isMessageIndicator?: boolean;
|
||||
isProfile?: boolean;
|
||||
isActionButton?: boolean;
|
||||
shouldHighlight?: boolean;
|
||||
}
|
||||
|
||||
const clickTimers = {} as Record<string, any>;
|
||||
|
||||
export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndicator, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
|
||||
export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
|
||||
const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined);
|
||||
|
||||
const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId);
|
||||
|
@ -182,7 +180,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndi
|
|||
{props => {
|
||||
const iconProps: IconProps = {
|
||||
...props,
|
||||
className: classes(isMessageIndicator && cl("message-indicator"), (!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight),
|
||||
className: classes(isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight),
|
||||
size: isActionButton ? 20 : undefined,
|
||||
onClick
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ export default definePlugin({
|
|||
find: "#{intl::USER_PROFILE_LOAD_ERROR}",
|
||||
replacement: {
|
||||
match: /(\.fetchError.+?\?)null/,
|
||||
replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId,isProfile:true})`
|
||||
replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId})`
|
||||
},
|
||||
predicate: () => settings.store.showInUserProfileModal
|
||||
},
|
||||
|
@ -99,7 +99,7 @@ export default definePlugin({
|
|||
addMemberListDecorator("UserVoiceShow", ({ user }) => user == null ? null : <VoiceChannelIndicator userId={user.id} />);
|
||||
}
|
||||
if (settings.store.showInMessages) {
|
||||
addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : <VoiceChannelIndicator userId={message.author.id} isMessageIndicator />);
|
||||
addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : <VoiceChannelIndicator userId={message.author.id} />);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -13,16 +13,6 @@
|
|||
color: var(--interactive-hover);
|
||||
}
|
||||
|
||||
.vc-uvs-speaker-margin {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.vc-uvs-message-indicator {
|
||||
display: inline-flex;
|
||||
top: 2.5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vc-uvs-tooltip-container {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
|
|
@ -148,13 +148,14 @@ export interface PluginDef {
|
|||
* The key will be used as text for the button
|
||||
*/
|
||||
toolboxActions?: Record<string, () => void>;
|
||||
/**
|
||||
* An imported managed style to be enabled only when the plugin is enabled
|
||||
*/
|
||||
style?: Style;
|
||||
|
||||
tags?: string[];
|
||||
|
||||
/**
|
||||
* Managed style to automatically enable and disable when the plugin is enabled or disabled
|
||||
*/
|
||||
managedStyle?: Style;
|
||||
|
||||
userProfileBadge?: ProfileBadge;
|
||||
|
||||
onMessageClick?: MessageClickListener;
|
||||
|
|
|
@ -57,7 +57,7 @@ export const Heading = waitForComponent<t.Heading>("Heading", filters.componentB
|
|||
export const Select = waitForComponent<t.Select>("Select", filters.componentByCode('.selectPositionTop]:"top"===', '"Escape"==='));
|
||||
export const SearchableSelect = waitForComponent<t.SearchableSelect>("SearchableSelect", filters.componentByCode('.selectPositionTop]:"top"===', ".multi]:"));
|
||||
export const Slider = waitForComponent<t.Slider>("Slider", filters.componentByCode('"markDash".concat('));
|
||||
export const Popout = waitForComponent<t.Popout>("Popout", filters.componentByCode("ref:this.ref,preload:"));
|
||||
export const Popout = waitForComponent<t.Popout>("Popout", filters.componentByCode("ref:this.ref,", "renderPopout:this.renderPopout,"));
|
||||
export const Dialog = waitForComponent<t.Dialog>("Dialog", filters.componentByCode('role:"dialog",tabIndex:-1'));
|
||||
export const TabBar = waitForComponent("TabBar", filters.componentByCode("ref:this.tabBarRef,className:"));
|
||||
export const Paginator = waitForComponent<t.Paginator>("Paginator", filters.componentByCode('rel:"prev",children:'));
|
||||
|
|
|
@ -69,12 +69,12 @@ export const filters = {
|
|||
m.constructor?.displayName === name,
|
||||
|
||||
componentByCode: (...code: CodeFilter): FilterFn => {
|
||||
const filter = filters.byCode(...code);
|
||||
return m => {
|
||||
const byCodeFilter = filters.byCode(...code);
|
||||
const filter = m => {
|
||||
let inner = m;
|
||||
|
||||
while (inner != null) {
|
||||
if (filter(inner)) return true;
|
||||
if (byCodeFilter(inner)) return true;
|
||||
else if (!inner.$$typeof) return false;
|
||||
else if (inner.type) inner = inner.type; // memos
|
||||
else if (inner.render) inner = inner.render; // forwardRefs
|
||||
|
@ -83,6 +83,9 @@ export const filters = {
|
|||
|
||||
return false;
|
||||
};
|
||||
|
||||
filter.$$vencordProps = [...code];
|
||||
return filter;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue