Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen1234 2025-12-14 13:11:55 -05:00
commit 7202091567
No known key found for this signature in database
47 changed files with 211 additions and 249 deletions

View file

@ -1,7 +1,7 @@
{
"name": "equicord",
"private": "true",
"version": "1.13.8.2",
"version": "1.13.9",
"description": "The other cutest Discord client mod",
"homepage": "https://github.com/Equicord/Equicord#readme",
"bugs": {
@ -121,4 +121,4 @@
"engines": {
"node": ">=18"
}
}
}

View file

@ -318,14 +318,6 @@ export type Slider = ComponentClass<PropsWithChildren<{
"aria-describedby"?: string;
}>>;
// TODO - type maybe idk probably not that useful other than the constants
export type Flex = ComponentType<PropsWithChildren<any>> & {
Align: Record<"START" | "END" | "CENTER" | "STRETCH" | "BASELINE", string>;
Direction: Record<"VERTICAL" | "HORIZONTAL" | "HORIZONTAL_REVERSE", string>;
Justify: Record<"START" | "END" | "CENTER" | "BETWEEN" | "AROUND", string>;
Wrap: Record<"NO_WRAP" | "WRAP" | "WRAP_REVERSE", string>;
};
declare enum PopoutAnimation {
NONE = "1",
TRANSLATE = "2",

View file

@ -47,13 +47,13 @@
.vc-notification-close-btn {
all: unset;
cursor: pointer;
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
opacity: 0.5;
transition: opacity 0.2s ease-in-out, color 0.2s ease-in-out;
}
.vc-notification-close-btn:hover {
color: var(--interactive-icon-hover, var(--interactive-hover));
color: var(--interactive-icon-hover);
opacity: 1;
}
@ -137,5 +137,5 @@
.vc-notification-log-danger-btn {
color: var(--white-500);
background-color: var(--redesign-button-danger-background, var(--button-danger-background));
}
background-color: var(--redesign-button-danger-background);
}

View file

@ -100,6 +100,10 @@ function isReporterTestable(p: Plugin, part: ReporterTestable) {
: (p.reporterTestable & part) === part;
}
export function pluginRequiresRestart(p: Plugin) {
return p.requiresRestart !== false && (p.requiresRestart || !!p.patches?.length);
}
export const startAllPlugins = traceFunction("startAllPlugins", function startAllPlugins(target: StartAt) {
logger.info(`Starting plugins (stage ${target})`);
for (const name in Plugins) {
@ -128,7 +132,7 @@ export function startDependenciesRecursive(p: Plugin) {
settings[d].enabled = true;
dep.isDependency = true;
if (dep.patches) {
if (pluginRequiresRestart(dep)) {
logger.warn(`Enabling dependency ${d} requires restart.`);
restartNeeded = true;
return;

View file

@ -10,7 +10,7 @@
text-align: start;
transition: 50ms ease-in;
transition-property: background-color, color, border-color, opacity;
background: var(--control-secondary-background-default, var(--control-background-secondary-default));
background: var(--control-secondary-background-default);
color: var(--text-default);
white-space: nowrap;
@ -26,7 +26,7 @@
&:focus-visible {
/* stylelint-disable-next-line custom-property-pattern */
box-shadow: 0 0 0 4px var(--__adaptive-focus-ring-color, var(--border-focus, var(--focus-primary, #00b0f4)));
box-shadow: 0 0 0 4px var(--__adaptive-focus-ring-color, var(--border-focus, #00b0f4));
}
}
@ -63,84 +63,84 @@
}
.vc-btn-primary {
background-color: var(--control-primary-background-default, var(--control-background-primary-default));
border-color: var(--control-primary-border-default, var(--control-border-primary-default));
color: var(--control-primary-text-default, var(--control-text-primary-default));
background-color: var(--control-primary-background-default);
border-color: var(--control-primary-border-default);
color: var(--control-primary-text-default);
&:hover {
background-color: var(--control-primary-background-hover, var(--control-background-primary-hover));
border-color: var(--control-primary-border-hover, var(--control-border-primary-hover));
color: var(--control-primary-text-hover, var(--control-text-primary-hover));
background-color: var(--control-primary-background-hover);
border-color: var(--control-primary-border-hover);
color: var(--control-primary-text-hover);
}
}
.vc-btn-secondary,
.vc-btn-link {
background-color: var(--control-secondary-background-default, var(--control-background-secondary-default));
border-color: var(--control-secondary-border-default, var(--control-border-secondary-default));
color: var(--control-secondary-text-default, var(--control-text-secondary-default));
background-color: var(--control-secondary-background-default);
border-color: var(--control-secondary-border-default);
color: var(--control-secondary-text-default);
&:hover {
background-color: var(--control-secondary-background-hover, var(--control-background-secondary-hover));
border-color: var(--control-secondary-border-hover, var(--control-border-secondary-hover));
color: var(--control-secondary-text-hover, var(--control-text-secondary-hover));
background-color: var(--control-secondary-background-hover);
border-color: var(--control-secondary-border-hover);
color: var(--control-secondary-text-hover);
}
}
.vc-btn-dangerPrimary {
background-color: var(--control-critical-primary-background-default, var(--control-background-critical-primary-default));
border-color: var(--control-critical-primary-border-default, var(--control-border-critical-primary-default));
color: var(--control-critical-primary-text-default, var(--control-text-critical-primary-default));
background-color: var(--control-critical-primary-background-default);
border-color: var(--control-critical-primary-border-default);
color: var(--control-critical-primary-text-default);
&:hover {
background-color: var(--control-critical-primary-background-hover, var(--control-background-critical-primary-hover));
border-color: var(--control-critical-primary-border-hover, var(--control-border-critical-primary-hover));
color: var(--control-critical-primary-text-hover, var(--control-text-critical-primary-hover));
background-color: var(--control-critical-primary-background-hover);
border-color: var(--control-critical-primary-border-hover);
color: var(--control-critical-primary-text-hover);
}
}
.vc-btn-dangerSecondary {
background-color: var(--control-critical-secondary-background-default, var(--control-background-critical-secondary-default));
border-color: var(--control-critical-secondary-border-default, var(--control-border-critical-secondary-default));
color: var(--control-critical-secondary-text-default, var(--control-text-critical-secondary-default));
background-color: var(--control-critical-secondary-background-default);
border-color: var(--control-critical-secondary-border-default);
color: var(--control-critical-secondary-text-default);
&:hover {
background-color: var(--control-critical-secondary-background-hover, var(--control-background-critical-secondary-hover));
border-color: var(--control-critical-secondary-border-hover, var(--control-border-critical-secondary-hover));
color: var(--control-critical-secondary-text-hover, var(--control-text-critical-secondary-hover));
background-color: var(--control-critical-secondary-background-hover);
border-color: var(--control-critical-secondary-border-hover);
color: var(--control-critical-secondary-text-hover);
}
}
.vc-btn-overlayPrimary {
background-color: var(--control-overlay-primary-background-default, var(--control-background-overlay-primary-default));
border-color: var(--control-overlay-primary-border-default, var(--control-border-overlay-primary-default));
color: var(--control-overlay-primary-text-default, var(--control-text-overlay-primary-default));
background-color: var(--control-overlay-primary-background-default);
border-color: var(--control-overlay-primary-border-default);
color: var(--control-overlay-primary-text-default);
&:hover {
background-color: var(--control-overlay-primary-background-hover, var(--control-background-overlay-primary-hover));
border-color: var(--control-overlay-primary-border-hover, var(--control-border-overlay-primary-hover));
color: var(--control-overlay-primary-text-hover, var(--control-text-overlay-primary-hover));
background-color: var(--control-overlay-primary-background-hover);
border-color: var(--control-overlay-primary-border-hover);
color: var(--control-overlay-primary-text-hover);
}
}
.vc-btn-positive {
background-color: var(--redesign-button-positive-background, var(--button-positive-background));
background-color: var(--redesign-button-positive-background);
color: var(--white);
&:hover {
background-color: var(--redesign-button-positive-pressed-background, var(--button-positive-background-hover));
background-color: var(--redesign-button-positive-pressed-background);
}
}
.vc-btn-none {
background-color: transparent;
border-color: transparent;
color: var(--control-icon-only-icon-default, var(--control-icon-icon-only-default));
color: var(--control-icon-only-icon-default);
&:hover {
background-color: var(--control-icon-only-background-hover, var(--control-background-icon-only-hover));
border-color: var(--control-icon-only-border-hover, var(--control-border-icon-only-hover));
color: var(--control-icon-only-icon-hover, var(--control-icon-icon-only-hover));
background-color: var(--control-icon-only-background-hover);
border-color: var(--control-icon-only-border-hover);
color: var(--control-icon-only-icon-hover);
}
}
@ -177,7 +177,7 @@
&:focus-visible {
/* stylelint-disable-next-line custom-property-pattern */
box-shadow: 0 0 0 4px var(--__adaptive-focus-ring-color, var(--border-focus, var(--focus-primary, #00b0f4)));
box-shadow: 0 0 0 4px var(--__adaptive-focus-ring-color, var(--border-focus, #00b0f4));
}
}
@ -190,7 +190,7 @@
}
.vc-text-btn-danger {
color: var(--text-feedback-critical, var(--text-feedback-critical));
color: var(--text-feedback-critical);
}
.vc-text-btn-link {

View file

@ -1,5 +1,5 @@
.vc-card-base {
background: var(--card-background-default, var(--card-primary-bg));
background: var(--card-background-default);
border-radius: var(--radius-sm, 8px)
}
@ -8,11 +8,11 @@
}
.vc-card-warning {
border: 1px solid var(--icon-status-idle, var(--info-warning-foreground));
border: 1px solid var(--icon-status-idle);
}
.vc-card-danger {
border: 1px solid var(--icon-status-dnd, var(--info-danger-foreground));
border: 1px solid var(--icon-status-dnd);
}
.vc-card-defaultPadding {

View file

@ -15,7 +15,7 @@
.vc-switch-checked {
background: var(--brand-500);
border-color: var(--control-primary-border-default, var(--control-border-primary-default));
border-color: var(--control-primary-border-default);
}
.vc-switch-disabled {
@ -25,7 +25,7 @@
.vc-switch-focusVisible {
/* stylelint-disable-next-line custom-property-pattern */
box-shadow: 0 0 0 4px var(--__adaptive-focus-ring-color, var(--border-focus, var(--focus-primary, #00b0f4)));
box-shadow: 0 0 0 4px var(--__adaptive-focus-ring-color, var(--border-focus, #00b0f4));
}
.vc-switch-slider {

View file

@ -1,6 +1,6 @@
.vc-addon-card {
background-color: var(--card-background-default, var(--card-primary-bg));
color: var(--interactive-icon-active, var(--interactive-active));
background-color: var(--card-background-default);
color: var(--interactive-icon-active);
border: 1px solid var(--border-subtle);
border-radius: 8px;
display: block;

View file

@ -14,7 +14,7 @@
.vc-settings-quickActions-pill {
all: unset;
background: var(--redesign-button-secondary-background, var(--button-secondary-background));
background: var(--redesign-button-secondary-background);
color: var(--text-default);
display: flex;
align-items: center;
@ -29,13 +29,13 @@
}
.vc-settings-quickActions-pill:hover {
background: var(--redesign-button-secondary-pressed-background, var(--button-secondary-background-hover));
background: var(--redesign-button-secondary-pressed-background);
transform: translateY(-1px);
box-shadow: var(--elevation-high);
}
.vc-settings-quickActions-pill:focus-visible {
outline: 2px solid var(--border-focus, var(--focus-primary));
outline: 2px solid var(--border-focus);
outline-offset: 2px;
}

View file

@ -74,7 +74,7 @@ export function FullPatchInput({ setFind, setParsedFind, setMatch, setReplacemen
onChange={setPatch}
onBlur={update}
/>
{error !== "" && <Paragraph style={{ color: "var(--text-feedback-critical, var(--text-danger))" }}>{error}</Paragraph>}
{error !== "" && <Paragraph style={{ color: "var(--text-feedback-critical)" }}>{error}</Paragraph>}
</>
);
}

View file

@ -142,7 +142,7 @@ export function PatchPreview({ module, match, replacement, setReplacementError }
)}
{compileResult && (
<Paragraph style={{ color: compileResult[0] ? "var(--status-positive)" : "var(--text-feedback-critical, var(--text-danger))" }}>
<Paragraph style={{ color: compileResult[0] ? "var(--status-positive)" : "var(--text-feedback-critical)" }}>
{compileResult[1]}
</Paragraph>
)}

View file

@ -5,7 +5,7 @@
*/
import { showNotice } from "@api/Notices";
import { isPluginEnabled, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager";
import { isPluginEnabled, pluginRequiresRestart, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager";
import { classNameFactory } from "@api/Styles";
import { CogWheel, InfoIcon } from "@components/Icons";
import { AddonCard } from "@components/settings/AddonCard";
@ -61,8 +61,8 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
}
}
// if the plugin has patches, dont use stopPlugin/startPlugin. Wait for restart to apply changes.
if (plugin.patches?.length) {
// if the plugin requires a restart, don't use stopPlugin/startPlugin. Wait for restart to apply changes.
if (pluginRequiresRestart(plugin)) {
settings.enabled = !wasEnabled;
onRestartNeeded(plugin.name, "enabled");
return;

View file

@ -1,13 +1,13 @@
.vc-plugin-ui-elements-button {
display: flex;
align-items: center;
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
margin-top: 0.5em;
cursor: pointer;
&:hover {
background-color: var(--background-mod-subtle, var(--background-modifier-hover));
color: var(--interactive-icon-hover, var(--interactive-hover));
background-color: var(--background-mod-subtle);
color: var(--interactive-icon-hover);
}
}

View file

@ -31,5 +31,5 @@
}
.vc-plugins-setting-error {
color: var(--text-feedback-critical, var(--text-danger, #FF5C5C));
}
color: var(--text-feedback-critical, #FF5C5C);
}

View file

@ -29,16 +29,16 @@
padding: 0;
background: transparent;
margin-right: 8px;
color: var(--icon-muted, var(--icon-secondary));
color: var(--icon-muted);
transition: background-color .2s ease;
&:hover {
color: var(--interactive-icon-hover, var(--interactive-hover))
color: var(--interactive-icon-hover)
}
}
.vc-plugins-settings-button:hover {
color: var(--interactive-icon-hover, var(--interactive-hover));
color: var(--interactive-icon-hover);
}
.vc-plugins-filter-controls {
@ -78,9 +78,8 @@
.vc-plugins-restart-card {
padding: 1em;
background: var(--icon-status-idle, var(--info-warning-foreground)) !important;
border: 1px solid var(--icon-status-idle, var(--info-warning-foreground)) !important;
;
background: var(--icon-status-idle) !important;
border: 1px solid var(--icon-status-idle) !important;
color: var(--text-status-idle);
}

View file

@ -49,7 +49,7 @@
display: inline-block !important;
color: var(--text-default) !important;
padding: 0.5em 1em;
border: 1px solid var(--input-border-default, var(--input-border));
border: 1px solid var(--input-border-default);
max-height: unset;
background-color: transparent;
box-sizing: border-box;
@ -76,7 +76,7 @@
.vc-cloud-erase-data-danger-btn {
color: var(--white-500);
background-color: var(--redesign-button-danger-background, var(--button-danger-background));
background-color: var(--redesign-button-danger-background);
}
.vc-settings-modal {

View file

@ -4,13 +4,13 @@
}
.vc-toolbox-icon {
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
}
.vc-toolbox-btn[class*="selected"] .vc-toolbox-icon {
color: var(--interactive-icon-active, var(--interactive-active));
color: var(--interactive-icon-active);
}
.vc-toolbox-btn:hover .vc-toolbox-icon {
color: var(--interactive-icon-hover, var(--interactive-hover));
color: var(--interactive-icon-hover);
}

View file

@ -16,7 +16,7 @@
margin: 0 2px;
border-radius: var(--radius-sm);
background: none;
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
padding: 0;
width: 32px;
height: 32px;
@ -26,8 +26,8 @@
}
.vc-spotify-button:hover {
color: var(--interactive-icon-hover, var(--interactive-hover));
background-color: var(--background-mod-strong, var(--background-modifier-selected));
color: var(--interactive-icon-hover);
background-color: var(--background-mod-strong);
}
.vc-spotify-button-icon {
@ -171,7 +171,7 @@
}
#vc-spotify-progress-bar > [class^="slider"] [class^="barFill"] {
background-color: var(--interactive-icon-active, var(--interactive-active));
background-color: var(--interactive-icon-active);
}
#vc-spotify-progress-bar > [class^="slider"]:hover [class^="barFill"] {
@ -184,9 +184,9 @@
width: 16px !important;
margin-top: calc(17px/-2 + var(--bar-offset)/2);
margin-left: -0.5px;
background-color: var(--interactive-icon-active, var(--interactive-active));
border-color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default, var(--interactive-normal));
background-color: var(--interactive-icon-active);
border-color: var(--interactive-icon-default);
color: var(--interactive-icon-default);
opacity: 0;
transition: opacity 0.1s;
}

View file

@ -140,7 +140,7 @@ export default definePlugin({
overflow: "hidden",
borderRadius: "50%",
backgroundColor: "var(--interactive-icon-default, var(--interactive-normal))",
backgroundColor: "var(--interactive-icon-default)",
color: "var(--background-base-lower)",
}}
>

View file

@ -16,7 +16,7 @@
}
.vc-clientTheme-container [class^="swatch"] {
border: thin solid var(--input-border-default, var(--input-border)) !important;
border: thin solid var(--input-border-default) !important;
}
.vc-clientTheme-buttons-container {

View file

@ -1,9 +1,9 @@
.vc-cfc-button {
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
cursor: pointer;
padding-left: 4px;
}
.vc-cfc-button:hover {
color: var(--interactive-icon-hover, var(--interactive-hover));
color: var(--interactive-icon-hover);
}

View file

@ -217,17 +217,20 @@ export default definePlugin({
description: "Add a fully customisable Rich Presence (Game status) to your Discord profile",
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev],
dependencies: ["UserSettingsAPI"],
start: setRpc,
stop: () => setRpc(true),
// This plugin's patch is not important for functionality, so don't require a restart
requiresRestart: false,
settings,
start: setRpc,
stop: () => setRpc(true),
// Discord hides buttons on your own Rich Presence for some reason. This patch disables that behaviour
patches: [
{
find: ".party?(0",
all: true,
find: ".buttons.length)>=1",
replacement: {
match: /\i\.id===\i\.id\?null:/,
replace: ""
match: /.getId\(\)===\i.id/,
replace: "$& && false"
}
}
],
@ -278,7 +281,7 @@ export default definePlugin({
<Divider className={Margins.top8} />
<div style={{ width: "284px", ...profileThemeStyle, marginTop: 8, borderRadius: 8, background: "var(--background-mod-muted, var(--background-mod-faint))" }}>
<div style={{ width: "284px", ...profileThemeStyle, marginTop: 8, borderRadius: 8, background: "var(--background-mod-muted)" }}>
{activity && <ActivityView
activity={activity}
user={UserStore.getCurrentUser()}

View file

@ -27,5 +27,5 @@
}
.vc-customRPC-settings-error {
color: var(--text-feedback-critical, var(--text-danger));
color: var(--text-feedback-critical);
}

View file

@ -1,6 +1,6 @@
.vc-decor-danger-btn {
color: var(--white-500);
background-color: var(--redesign-button-danger-background, var(--button-danger-background));
background-color: var(--redesign-button-danger-background);
}
.vc-decor-change-decoration-modal-content {

View file

@ -24,7 +24,7 @@ import { Devs } from "@utils/constants";
import { getCurrentGuild, getEmojiURL } from "@utils/discord";
import { Logger } from "@utils/Logger";
import definePlugin, { OptionType, Patch } from "@utils/types";
import type { Emoji, Message } from "@vencord/discord-types";
import type { Emoji, Message, Sticker } from "@vencord/discord-types";
import { StickerFormatType } from "@vencord/discord-types/enums";
import { findByCodeLazy, findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack";
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, GuildMemberStore, lodash, OverridePremiumTypeStore, Parser, PermissionsBits, PermissionStore, StickersStore, UploadHandler, UserSettingsActionCreators } from "@webpack/common";
@ -707,8 +707,9 @@ export default definePlugin({
}
},
getStickerLink(stickerId: string) {
return `https://media.discordapp.net/stickers/${stickerId}.png?size=${settings.store.stickerSize}`;
getStickerLink({ format_type, id }: Sticker) {
const ext = format_type === StickerFormatType.GIF ? "gif" : "png";
return `https://media.discordapp.net/stickers/${id}.${ext}?size=${settings.store.stickerSize}`;
},
async sendAnimatedSticker(stickerLink: string, stickerId: string, channelId: string) {
@ -845,14 +846,7 @@ export default definePlugin({
if (sticker.available !== false && (canUseStickers || sticker.guild_id === guildId))
break stickerBypass;
// [12/12/2023]
// Work around an annoying bug where getStickerLink will return StickerType.GIF,
// but will give us a normal non animated png for no reason
// TODO: Remove this workaround when it's not needed anymore
let link = this.getStickerLink(sticker.id);
if (sticker.format_type === StickerFormatType.GIF && link.includes(".png")) {
link = link.replace(".png", ".gif");
}
const link = this.getStickerLink(sticker);
if (sticker.format_type === StickerFormatType.APNG) {
if (!hasAttachmentPerms(channelId)) {

View file

@ -4,6 +4,8 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./styles.css";
import { BaseText } from "@components/BaseText";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
@ -16,7 +18,7 @@ const containerWrapper = findByPropsLazy("memberSinceWrapper");
const container = findByPropsLazy("memberSince");
const getCreatedAtDate = findByCodeLazy('month:"short",day:"numeric"');
const locale = findByPropsLazy("getLocale");
const Section = findComponentByCodeLazy('"auto":"smooth"', ".section");
const Section = findComponentByCodeLazy("headingVariant:", ".section", ".header");
export default definePlugin({
name: "FriendsSince",
@ -55,35 +57,46 @@ export default definePlugin({
const friendsSince = RelationshipStore.getSince(userId);
if (!friendsSince) return null;
if (isSidebar) {
return (
<Section
heading="Friends Since"
headingVariant="text-xs/semibold"
headingColor="text-strong"
>
<BaseText size="sm">
{getCreatedAtDate(friendsSince, locale.getLocale())}
</BaseText>
</Section>
);
}
return (
<Section heading="Friends Since">
{
isSidebar ? (
<Section
heading="Friends Since"
headingVariant="text-xs/medium"
headingColor="text-default"
className="vc-friendsSince-profile-section"
>
<div className={containerWrapper.memberSinceWrapper}>
<div className={container.memberSince}>
{!!getCurrentChannel()?.guild_id && (
<svg
aria-hidden="true"
width="16"
height="16"
viewBox="0 0 24 24"
fill="var(--interactive-icon-default)"
>
<path d="M13 10a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z" />
<path d="M3 5v-.75C3 3.56 3.56 3 4.25 3s1.24.56 1.33 1.25C6.12 8.65 9.46 12 13 12h1a8 8 0 0 1 8 8 2 2 0 0 1-2 2 .21.21 0 0 1-.2-.15 7.65 7.65 0 0 0-1.32-2.3c-.15-.2-.42-.06-.39.17l.25 2c.02.15-.1.28-.25.28H9a2 2 0 0 1-2-2v-2.22c0-1.57-.67-3.05-1.53-4.37A15.85 15.85 0 0 1 3 5Z" />
</svg>
)}
<BaseText size="sm">
{getCreatedAtDate(friendsSince, locale.getLocale())}
</BaseText>
) : (
<div className={containerWrapper.memberSinceWrapper}>
<div className={container.memberSince}>
{!!getCurrentChannel()?.guild_id && (
<svg
aria-hidden="true"
width="16"
height="16"
viewBox="0 0 24 24"
fill="var(--interactive-icon-default, var(--interactive-normal))"
>
<path d="M13 10a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z" />
<path d="M3 5v-.75C3 3.56 3.56 3 4.25 3s1.24.56 1.33 1.25C6.12 8.65 9.46 12 13 12h1a8 8 0 0 1 8 8 2 2 0 0 1-2 2 .21.21 0 0 1-.2-.15 7.65 7.65 0 0 0-1.32-2.3c-.15-.2-.42-.06-.39.17l.25 2c.02.15-.1.28-.25.28H9a2 2 0 0 1-2-2v-2.22c0-1.57-.67-3.05-1.53-4.37A15.85 15.85 0 0 1 3 5Z" />
</svg>
)}
<BaseText size="sm">
{getCreatedAtDate(friendsSince, locale.getLocale())}
</BaseText>
</div>
</div>
)
}
</div>
</div>
</Section>
);
}, { noop: true }),

View file

@ -0,0 +1,3 @@
.vc-friendsSince-profile-section {
gap: 4px;
}

View file

@ -66,7 +66,7 @@ function ToggleActivityComponent(activity: IgnoredActivity, isPlaying = false) {
const { ignoredActivities } = s;
if (ignoredActivities.some(act => act.id === activity.id)) return ToggleIconOff(activity, "var(--status-danger)");
return ToggleIconOn(activity, isPlaying ? "var(--green-300)" : "var(--interactive-icon-default, var(--interactive-normal))");
return ToggleIconOn(activity, isPlaying ? "var(--green-300)" : "var(--interactive-icon-default)");
}
function handleActivityToggle(e: React.MouseEvent<HTMLButtonElement, MouseEvent>, activity: IgnoredActivity) {

View file

@ -47,7 +47,7 @@
.vc-membercount-total-count {
fill: none;
stroke: var(--icon-status-offline, var(--status-offline));
stroke: var(--icon-status-offline);
stroke-width: 4px;
width: 15px;
height: 15px;

View file

@ -1,6 +1,6 @@
.messagelogger-deleted {
--text-default: var(--status-danger, #f04747);
--interactive-icon-default: var(--interactive-normal, var(--status-danger, #f04747));
--interactive-icon-default: var(--status-danger, #f04747);
--text-muted: var(--status-danger, #f04747);
--embed-title: var(--red-460, #be3535);
--text-link: var(--red-460, #be3535);

View file

@ -66,11 +66,11 @@
}
.vc-permviewer-modal-list-item:hover {
background-color: var(--background-mod-subtle, var(--background-modifier-hover));
background-color: var(--background-mod-subtle);
}
.vc-permviewer-modal-list-item-active {
background-color: var(--background-mod-strong, var(--background-modifier-selected));
background-color: var(--background-mod-strong);
}
.vc-permviewer-modal-list-item-text {
@ -100,7 +100,7 @@
.vc-permviewer-modal-divider {
width: 2px;
background-color: var(--background-mod-normal, var(--background-modifier-active));
background-color: var(--background-mod-normal);
}
.vc-permviewer-modal-perms {
@ -114,7 +114,7 @@
align-items: center;
gap: 5px;
padding: 10px 2px 10px 10px;
border-bottom: 2px solid var(--background-mod-normal, var(--background-modifier-active));
border-bottom: 2px solid var(--background-mod-normal);
}
.vc-permviewer-modal-perms-item:last-child {
@ -122,7 +122,7 @@
}
.vc-permviewer-modal-perms-item-icon {
border: 1px solid var(--background-mod-strong, var(--background-modifier-selected));
border: 1px solid var(--background-mod-strong);
width: 24px;
height: 24px;
}
@ -135,13 +135,13 @@
}
.vc-permviewer-modal-perms-item .vc-info-icon:hover {
color: var(--interactive-icon-active, var(--interactive-active));
color: var(--interactive-icon-active);
}
/* copy pasted from discord cause impossible to webpack find */
.vc-permviewer-role-button {
border-radius: var(--radius-sm);
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
border: 1px solid var(--user-profile-border);
/* stylelint-disable-next-line value-no-vendor-prefix */
width: -moz-fit-content;

View file

@ -1,8 +1,8 @@
.vc-pip-button {
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
}
.vc-pip-button:hover {
background-color: var(--background-mod-subtle, var(--background-modifier-hover));
color: var(--interactive-icon-hover, var(--interactive-hover));
}
background-color: var(--background-mod-subtle);
color: var(--interactive-icon-hover);
}

View file

@ -28,7 +28,7 @@
.vc-pindms-collapse-icon {
width: 16px;
height: 16px;
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
transform: rotate(90deg)
}

View file

@ -6,5 +6,5 @@
transform: translateZ(0);
/* The new icons are fully transparent. Add a sane default to match the old behavior */
background-color: color-mix(in oklab, var(--custom-folder-color, var(--badge-background-default, var(--bg-brand))) 40%, transparent);
background-color: color-mix(in oklab, var(--custom-folder-color, var(--badge-background-default)) 40%, transparent);
}

View file

@ -1,5 +1,5 @@
.vc-ranb-button {
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
padding: 0 0.5em;
width: 100%;
font-size: 14px;
@ -8,5 +8,5 @@
}
.vc-ranb-button:hover {
color: var(--interactive-icon-active, var(--interactive-active));
}
color: var(--interactive-icon-active);
}

View file

@ -41,7 +41,7 @@
.vc-rdb-modal-footer .vc-rdb-input {
margin-bottom: 0;
background: var(--input-background-default, var(--input-background));
background: var(--input-background-default);
}
.vc-rdb-modal-footer [class|="pageControlContainer"] {
@ -63,7 +63,7 @@
}
.vc-rdb-review:hover {
background: var(--message-background-hover, var(--background-message-hover)) !important;
background: var(--message-background-hover) !important;
border-radius: 8px;
}

View file

@ -1,11 +1,11 @@
.vc-st-date-picker {
background-color: var(--input-background-default, var(--input-background));
background-color: var(--input-background-default);
color: var(--text-default);
width: 95%;
padding: 8px 8px 8px 12px;
margin: 1em 0;
outline: none;
border: 1px solid var(--input-background-default, var(--input-background));
border: 1px solid var(--input-background-default);
border-radius: 4px;
font-weight: 500;
font-style: inherit;

View file

@ -48,7 +48,7 @@
.vc-gp-tab {
border-bottom: 2px solid transparent;
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
cursor: pointer;
line-height: 14px;
}
@ -58,7 +58,7 @@
}
.vc-gp-tab:where(.vc-gp-selected, :hover, :focus) {
border-bottom-color: var(--interactive-icon-active, var(--interactive-active));
border-bottom-color: var(--interactive-icon-active);
}
.vc-gp-info {
@ -165,5 +165,5 @@
}
.vc-gp-scroller [class^="listRow"]:hover {
background-color: var(--background-mod-subtle, var(--background-modifier-hover));
}
background-color: var(--background-mod-subtle);
}

View file

@ -95,7 +95,7 @@ function renderFindError(find: string) {
return null;
} catch (e) {
return (
<span style={{ color: "var(--text-feedback-critical, var(--text-danger))" }}>
<span style={{ color: "var(--text-feedback-critical)" }}>
{String(e)}
</span>
);

View file

@ -1,5 +1,5 @@
.vc-uvs-speaker {
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
display: flex;
align-items: center;
justify-content: center;
@ -10,7 +10,7 @@
}
.vc-uvs-clickable:hover {
color: var(--interactive-icon-hover, var(--interactive-hover));
color: var(--interactive-icon-hover);
}
.vc-uvs-profile-speaker {

View file

@ -1,12 +1,12 @@
.vc-voice-download {
width: 24px;
height: 24px;
color: var(--interactive-icon-default, var(--interactive-normal));
color: var(--interactive-icon-default);
margin-left: 12px;
cursor: pointer;
position: relative;
}
.vc-voice-download:hover {
color: var(--interactive-icon-active, var(--interactive-active));
}
color: var(--interactive-icon-active);
}

View file

@ -21,7 +21,7 @@
}
.vc-vmsg-preview-indicator {
background: var(--redesign-button-secondary-background, var(--button-secondary-background));
background: var(--redesign-button-secondary-background);
width: 16px;
height: 16px;
border-radius: 50%;
@ -50,5 +50,5 @@
}
.vc-vmsg-error {
color: var(--text-feedback-critical, var(--text-danger, #FF5C5C));
}
color: var(--text-feedback-critical, #FF5C5C);
}

View file

@ -22,21 +22,19 @@ import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, Flux
import { Except } from "type-fest";
import { copyToClipboard } from "./clipboard";
import { runtimeHashMessageKey, runtimeHashMessageKeyLegacy } from "./intlHash";
import { runtimeHashMessageKey } from "./intlHash";
import { Logger } from "./Logger";
import { MediaModalItem, MediaModalProps, openMediaModal } from "./modal";
const IntlManagerLogger = new Logger("IntlManager");
// TODO: remove legacy hashing function once Discord ships new one everywhere for a while
/**
* Get an internationalized message from a non hashed key
* @param key The plain message key
* @param values The values to interpolate, if it's a rich message
*/
export function getIntlMessage(key: string, values?: Record<PropertyKey, any>): any {
return getIntlMessageFromHash(runtimeHashMessageKey(key), values, key) || getIntlMessageFromHash(runtimeHashMessageKeyLegacy(key), values, key);
return getIntlMessageFromHash(runtimeHashMessageKey(key), values, key);
}
/**

View file

@ -50,18 +50,3 @@ export function runtimeHashMessageKey(key: string): string {
BASE64_TABLE[((bytes[3] & 0x03) << 4) | (bytes[4] >> 4)],
].join("");
}
// Old variant for compatibility
// TODO: remove once Discord shipped new one everywhere for a while
export function runtimeHashMessageKeyLegacy(key: string): string {
const hash = h64(key, 0);
const bytes = numberToBytes(hash);
return [
BASE64_TABLE[bytes[0] >> 2],
BASE64_TABLE[((bytes[0] & 0x03) << 4) | (bytes[1] >> 4)],
BASE64_TABLE[((bytes[1] & 0x0f) << 2) | (bytes[2] >> 6)],
BASE64_TABLE[bytes[2] & 0x3f],
BASE64_TABLE[bytes[3] >> 2],
BASE64_TABLE[((bytes[3] & 0x03) << 4) | (bytes[3] >> 4)],
].join("");
}

View file

@ -16,68 +16,36 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { runtimeHashMessageKey, runtimeHashMessageKeyLegacy } from "./intlHash";
import { runtimeHashMessageKey } from "./intlHash";
import { Patch, PatchReplacement, ReplaceFn } from "./types";
// TODO: remove legacy hashing function once Discord ships new one everywhere for a while
// @ts-expect-error "RegExp.escape" is very new and not yet in DOM types
const escapeRegex = RegExp.escape || ((s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
export function getReplacement(isString: boolean, hashed: string, hash: boolean = false) {
const hasSpecialChars = !Number.isNaN(Number(hashed[0])) || hashed.includes("+") || hashed.includes("/");
if (hash) return hashed;
if (hasSpecialChars) {
return isString
? `["${hashed}"]`
: String.raw`(?:\["${hashed}"\])`.replaceAll("+", "\\+");
}
return isString ? `.${hashed}` : String.raw`(?:\.${hashed})`;
}
function getCompatReplacement(key: string) {
const hashed = getReplacement(false, runtimeHashMessageKey(key));
const legacyHashed = getReplacement(false, runtimeHashMessageKeyLegacy(key));
return String.raw`(?:${hashed}|${legacyHashed})`;
}
function canonicalizeMatchCompatString(str: string) {
let result = "";
let lastIndex = 0;
const re = /#{intl::([\w$+/]*)(?:::(\w+))?}/g;
for (const match of str.matchAll(re)) {
result += escapeRegex(str.slice(lastIndex, match.index));
result += match[2] === "raw" ? getReplacement(false, match[1]) : match[2] === "hash" ? getReplacement(false, runtimeHashMessageKey(match[1]), true) : getCompatReplacement(match[1]);
lastIndex = (match.index ?? 0) + match[0].length;
}
result += escapeRegex(str.slice(lastIndex));
return new RegExp(result);
}
export function canonicalizeMatch<T extends RegExp | string>(match: T): T extends RegExp ? RegExp : string | RegExp {
if (typeof match === "string") {
return canonicalizeMatchCompatString(match) as any;
}
export function canonicalizeMatch<T extends RegExp | string>(match: T): T {
let partialCanon = typeof match === "string" ? match : match.source;
partialCanon = partialCanon.replaceAll(/#{intl::([\w$+/]*)(?:::(\w+))?}/g, (_, key, modifier) => {
if (modifier === "raw") return getReplacement(false, key);
if (modifier === "hash") return getReplacement(false, runtimeHashMessageKey(key), true);
return getCompatReplacement(key);
const hashed = modifier === "raw" ? key : runtimeHashMessageKey(key);
if (modifier === "hash") return hashed;
const isString = typeof match === "string";
const hasSpecialChars = !Number.isNaN(Number(hashed[0])) || hashed.includes("+") || hashed.includes("/");
if (hasSpecialChars) {
return isString
? `["${hashed}"]`
: String.raw`(?:\["${hashed}"\])`.replaceAll("+", "\\+");
}
return isString ? `.${hashed}` : String.raw`(?:\.${hashed})`;
});
if (typeof match === "string") {
return partialCanon as any;
return partialCanon as T;
}
const canonSource = partialCanon.replaceAll("\\i", String.raw`(?:[A-Za-z_$][\w$]*)`);
const canonRegex = new RegExp(canonSource, match.flags);
canonRegex.toString = match.toString.bind(match);
return canonRegex as any;
return canonRegex as T;
}
export function canonicalizeReplace<T extends string | ReplaceFn>(replace: T, pluginPath: string): T {

View file

@ -129,6 +129,10 @@ export interface PluginDef {
* Whether this plugin should be enabled by default, but can be disabled
*/
enabledByDefault?: boolean;
/**
* Whether enabling or disabling this plugin requires a restart. Defaults to true if the plugin has patches.
*/
requiresRestart?: boolean;
/**
* When to call the start() method
* @default StartAt.WebpackReady

View file

@ -221,8 +221,7 @@ export const DisplayProfileUtils: t.DisplayProfileUtils = mapMangledModuleLazy(/
export const DateUtils: t.DateUtils = mapMangledModuleLazy("millisecondsInUnit:", {
calendarFormat: filters.byCode("sameElse"),
dateFormat: filters.byCode('":'),
// TODO: the +? are for compat with the old version - Remove them once no longer needed
isSameDay: filters.byCode(/Math\.abs\(\+?\i-\+?\i\)/),
isSameDay: filters.byCode(/Math\.abs\(\i-\i\)/),
diffAsUnits: filters.byCode("days:0", "millisecondsInUnit")
});