DiscordDevBanner: More Settings

This commit is contained in:
thororen1234 2025-08-03 21:30:59 -04:00
parent 0bfbaa9cb6
commit 1e34d429ad
No known key found for this signature in database
4 changed files with 156 additions and 14 deletions

View file

@ -0,0 +1,71 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { SVGProps } from "react";
export const DiscordIcon = (props: React.PropsWithChildren<SVGProps<SVGSVGElement>>) => (
<svg
{...props}
fill="currentColor"
viewBox="0 0 16 16"
width="14px"
height="14px"
>
<path d="M13.545 2.907a13.227 13.227 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 0 0-3.658 0 8.258 8.258 0 0 0-.412-.833.051.051 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019c.308-.42.582-.863.818-1.329a.05.05 0 0 0-.01-.059.051.051 0 0 0-.018-.011 8.875 8.875 0 0 1-1.248-.595.05.05 0 0 1-.02-.066.051.051 0 0 1 .015-.019c.084-.063.168-.129.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.052.052 0 0 1 .053.007c.08.066.164.132.248.195a.051.051 0 0 1-.004.085 8.254 8.254 0 0 1-1.249.594.05.05 0 0 0-.03.03.052.052 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.235 13.235 0 0 0 4.001-2.02.049.049 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.034.034 0 0 0-.02-.019Zm-8.198 7.307c-.789 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612Zm5.316 0c-.788 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612Z" />
</svg>
);
export const EquicordIcon = (props: React.PropsWithChildren<SVGProps<SVGSVGElement>>) => (
<svg
{...props}
fill="currentColor"
viewBox="0 0 930 930"
width="14px"
height="14px"
>
<path d="M836 465.5C836 670.121 670.121 836 465.5 836C260.879 836 95 670.121 95 465.5C95 260.879 260.879 95 465.5 95C670.121 95 836 260.879 836 465.5ZM242.322 465.5C242.322 588.758 342.242 688.678 465.5 688.678C588.758 688.678 688.678 588.758 688.678 465.5C688.678 342.242 588.758 242.322 465.5 242.322C342.242 242.322 242.322 342.242 242.322 465.5Z" />
<path d="M584.219 465.898C584.219 531.245 531.245 584.219 465.898 584.219C440.35 584.219 416.693 576.122 397.353 562.354L260.937 644.321C451.4 528.542 329.698 492.311 204.538 566.663L348.433 480.202C347.868 475.513 347.577 470.74 347.577 465.898C347.577 400.552 400.552 347.577 465.898 347.577C491.108 347.577 514.477 355.462 533.673 368.899L627.819 312.331C610.898 294.399 591.056 279.324 569.045 267.796C534.72 249.819 496.306 241.088 457.582 242.462C418.858 243.837 381.16 255.27 348.196 275.637C315.232 296.003 288.138 324.6 269.581 358.616C262.856 370.943 257.336 383.828 253.065 397.091C240.595 435.815 209.386 470.244 168.712 470.997C128.037 471.751 93.7099 439.084 101.005 399.061C108.06 360.359 121.262 322.87 140.254 288.06C171.06 231.591 216.039 184.116 270.763 150.306C325.486 116.495 388.07 97.5155 452.356 95.2335C516.641 92.9515 580.413 107.446 637.397 137.29C694.38 167.134 742.612 211.301 777.345 265.444C812.079 319.586 832.118 381.839 835.491 446.076C838.863 510.313 825.452 574.322 796.579 631.804C778.78 667.239 755.483 699.439 727.687 727.279C698.944 756.068 652.543 746.455 629.998 712.591C607.453 678.727 617.982 633.466 642.711 601.164C651.181 590.1 658.628 578.224 664.932 565.676C682.324 531.051 690.402 492.494 688.371 453.799C687.303 433.462 683.462 413.454 677.02 394.312L583.246 450.657C583.889 455.647 584.219 460.734 584.219 465.898ZM260.937 644.321C258.599 645.742 256.214 647.175 253.783 648.619L260.937 644.321Z" />
<path d="M470.711 406.73C493.342 393.132 522.712 400.455 536.311 423.086C549.909 445.718 542.587 475.088 519.955 488.687L253.783 648.619L204.538 566.663L470.711 406.73Z" />
</svg>
);
export const ElectronIcon = (props: React.PropsWithChildren<SVGProps<SVGSVGElement>>) => (
<svg
{...props}
fill="currentColor"
viewBox="0 0 24 24"
width="14px"
height="14px"
>
<path d="M2.648 11.678c-1.038-1.81-1.249-3.504-.511-4.781.988-1.712 3.468-2.31 6.604-1.739a.322.322 0 1 1-.115.633c-2.9-.528-5.111.005-5.932 1.428-.605 1.047-.423 2.509.512 4.14a.322.322 0 1 1-.558.32zm14.92-6.069c1.835.024 3.156.596 3.751 1.626.82 1.419.18 3.595-1.718 5.837a.322.322 0 1 0 .49.416c2.054-2.426 2.771-4.866 1.785-6.575-.726-1.257-2.26-1.92-4.299-1.947a.322.322 0 1 0-.008.643zm-1.854 15.239a.322.322 0 0 0-.442.11c-.934 1.553-2.08 2.399-3.26 2.399-1.642 0-3.208-1.647-4.2-4.418a.322.322 0 1 0-.606.217C8.279 22.154 10.036 24 12.01 24c1.44 0 2.773-.982 3.813-2.71a.322.322 0 0 0-.11-.442zm7.356-2.594a1.54 1.54 0 0 1-2.436 1.25c-2.455 1.445-7.146.71-11.56-1.84-1.88-1.085-3.527-2.392-4.795-3.785a.322.322 0 1 1 .476-.433c1.222 1.343 2.817 2.609 4.64 3.661 4.167 2.406 8.553 3.12 10.797 1.906a1.54 1.54 0 1 1 2.878-.759zm-19.062 0a1.54 1.54 0 1 1-2.285-1.345c-.233-2.877 2.79-6.734 7.36-9.372 1.898-1.096 3.874-1.874 5.731-2.271a.322.322 0 0 1 .135.628c-1.79.384-3.703 1.137-5.545 2.2-4.304 2.485-7.148 6.067-7.048 8.627.038-.003.075-.006.113-.006.85 0 1.54.69 1.54 1.54zM10.472 1.54a1.54 1.54 0 0 1 3.078 0c0 .023-.002.045-.003.067 2.549 1.317 4.32 5.81 4.32 11.003 0 2.135-.298 4.184-.854 5.96a.322.322 0 1 1-.614-.192c.536-1.712.825-3.697.825-5.768 0-4.89-1.626-9.095-3.847-10.363a1.538 1.538 0 0 1-2.905-.707zm1.304 9.981a1.114 1.114 0 1 0 .47 2.178 1.114 1.114 0 0 0-.47-2.178z" /> </svg>
);
export const ChromeIcon = (props: React.PropsWithChildren<SVGProps<SVGSVGElement>>) => (
<svg
{...props}
fill="currentColor"
viewBox="0 0 512 512"
width="14px"
height="14px"
>
<path d="M188.8,255.93A67.2,67.2,0,1,0,256,188.75,67.38,67.38,0,0,0,188.8,255.93Z" />
<path d="M476.75,217.79s0,0,0,.05a206.63,206.63,0,0,0-7-28.84h-.11a202.16,202.16,0,0,1,7.07,29h0a203.5,203.5,0,0,0-7.07-29H314.24c19.05,17,31.36,40.17,31.36,67.05a86.55,86.55,0,0,1-12.31,44.73L231,478.45a2.44,2.44,0,0,1,0,.27V479h0v-.26A224,224,0,0,0,256,480c6.84,0,13.61-.39,20.3-1a222.91,222.91,0,0,0,29.78-4.74C405.68,451.52,480,362.4,480,255.94A225.25,225.25,0,0,0,476.75,217.79Z" />
<path d="M256,345.5c-33.6,0-61.6-17.91-77.29-44.79L76,123.05l-.14-.24A224,224,0,0,0,207.4,474.55l0-.05,77.69-134.6A84.13,84.13,0,0,1,256,345.5Z" />
<path d="M91.29,104.57l77.35,133.25A89.19,89.19,0,0,1,256,166H461.17a246.51,246.51,0,0,0-25.78-43.94l.12.08A245.26,245.26,0,0,1,461.17,166h.17a245.91,245.91,0,0,0-25.66-44,2.63,2.63,0,0,1-.35-.26A223.93,223.93,0,0,0,91.14,104.34l.14.24Z" />
</svg>
);
export const DevBannerIcon = (props: React.PropsWithChildren<SVGProps<SVGSVGElement>>) => (
<svg
{...props}
fill="currentColor"
viewBox="0 0 14 14"
width="14px"
height="14px"
>
<path d="M6.99471698,9.67522659 C8.47108874,9.67522659 9.66792453,8.47748685 9.66792453,7 C9.66792453,5.52251315 8.47108874,4.32477341 6.99471698,4.32477341 C5.51834522,4.32477341 4.32150943,5.52251315 4.32150943,7 C4.32150943,8.47748685 5.51834522,9.67522659 6.99471698,9.67522659 Z M6.99471698,2.67522659 C8.18867925,2.67522659 9.26641509,3.16163142 10.0483019,3.94410876 L11.9396226,2.05135952 C10.6822642,0.782477341 8.92830189,0 6.99471698,0 C3.12754717,0 0,3.14048338 0,7 L2.67320755,7 C2.67320755,4.6102719 4.60679245,2.67522659 6.99471698,2.67522659 Z M11.3267925,7 C11.3267925,9.3897281 9.39320755,11.3247734 7.00528302,11.3247734 C5.81132075,11.3247734 4.73358491,10.8383686 3.94113208,10.0558912 L2.04981132,11.9486405 C3.31773585,13.2175227 5.06113208,14 6.99471698,14 C10.8618868,14 14,10.8595166 14,7 L11.3267925,7 Z" />
</svg>
);

View file

@ -8,10 +8,13 @@ import "./styles.css";
import { EquicordDevs } from "@utils/constants";
import definePlugin from "@utils/types";
import { React } from "@webpack/common";
import SettingsPlugin from "plugins/_core/settings";
import { JSX } from "react";
import gitHash from "~git-hash";
import { ChromeIcon, DevBannerIcon, DiscordIcon, ElectronIcon, EquicordIcon } from "./components";
import { settings } from "./settings";
function getVersion(): string {
@ -23,15 +26,16 @@ function getVersion(): string {
return "";
}
export function transform(state?: string): string {
export function transform(state?: string): string | JSX.Element {
const { RELEASE_CHANNEL, BUILD_NUMBER, VERSION_HASH } = window.GLOBAL_ENV;
const buildChannel: string = names[RELEASE_CHANNEL] || RELEASE_CHANNEL.charAt(0).toUpperCase() + RELEASE_CHANNEL.slice(1);
const { chromiumVersion, electronVersion, } = SettingsPlugin;
const format = settings.store.format ?? "{buildChannel} {buildNumber} ({buildHash}) | {equicordName} {equicordVersion} ({equicordHash})";
const buildChannel = names[RELEASE_CHANNEL] || RELEASE_CHANNEL.charAt(0).toUpperCase() + RELEASE_CHANNEL.slice(1);
const { chromiumVersion, electronVersion } = SettingsPlugin;
const format =
settings.store.format ??
"{devBannerIcon} {buildChannel} {buildNumber} ({buildHash}) | {equicordIcon} {equicordName} {equicordVersion} ({equicordHash})";
const baseFormat = state ?? format;
const formatted = baseFormat
.replace(/{discordName}/g, "Discord")
const replaced = baseFormat
.replace(/{buildChannel}/g, buildChannel)
.replace(/{buildNumber}/g, BUILD_NUMBER)
.replace(/{buildHash}/g, VERSION_HASH.slice(0, 9))
@ -42,9 +46,33 @@ export function transform(state?: string): string {
.replace(/{electronName}/g, "Electron")
.replace(/{electronVersion}/g, electronVersion)
.replace(/{chromiumName}/g, "Chromium")
.replace(/{chromiumVersion}/g, chromiumVersion);
.replace(/{chromiumVersion}/g, chromiumVersion)
.replace(/\\n|{newline}/g, "__NEWLINE__");
return formatted;
if (!replaced.includes("__NEWLINE__") && !/{.*Icon}/.test(baseFormat)) {
return replaced;
}
const parts = replaced.split(/({.*?}|__NEWLINE__)/).filter(Boolean).map((part, i) => {
switch (part) {
case "{discordIcon}":
return <span key={`icon-discord-${i}`} className="vc-discord-dev-banner-icons"><DiscordIcon /></span>;
case "{equicordIcon}":
return <span key={`icon-equicord-${i}`} className="vc-discord-dev-banner-icons"><EquicordIcon /></span>;
case "{electronIcon}":
return <span key={`icon-electron-${i}`} className="vc-discord-dev-banner-icons"><ElectronIcon /></span>;
case "{chromiumIcon}":
return <span key={`icon-chromium-${i}`} className="vc-discord-dev-banner-icons"><ChromeIcon /></span>;
case "{devBannerIcon}":
return <span key={`icon-dev-${i}`} className="vc-discord-dev-banner-icons"><DevBannerIcon /></span>;
case "__NEWLINE__":
return <br key={`br-${i}`} />;
default:
return <React.Fragment key={`text-${i}`}>{part}</React.Fragment>;
}
});
return <div style={{ display: "inline" }}>{parts}</div>;
}
const names: Record<string, string> = {
@ -72,8 +100,8 @@ export default definePlugin({
replace: "$1null;"
},
{
match: /\i\.\i\.format\(.{0,40}\)/,
replace: "$self.transform()"
match: /children:\[.*?\{\}\)\]/g,
replace: "children:$self.transform()"
},
]
}

View file

@ -6,7 +6,7 @@
import { definePluginSettings } from "@api/Settings";
import { OptionType } from "@utils/types";
import { Forms, TextInput, useState } from "@webpack/common";
import { Forms, useState } from "@webpack/common";
import { transform } from ".";
@ -25,18 +25,24 @@ function FormatSetting(setValue) {
const [error, setError] = useState<string | null>(null);
const placeholderInfo = [
"{discordIcon} - Discord icon",
"{discordName} - The word 'Discord'",
"{buildChannel} - Discord build channel (e.g. Stable)",
"{buildNumber} - Discord build number (e.g. 123456)",
"{buildHash} - Discord build hash (e.g. 123456789)",
"{equicordIcon} - Equicord icon",
"{equicordName} - The word 'Equicord'",
"{equicordVersion} - Version of Equicord (e.g. 1.0.0)",
"{equicordHash} - Equicord build hash (e.g. 123456789)",
"{equicordPlatform} - Platform Equicord is running on (e.g. Dev)",
"{electronIcon} - Electron icon",
"{electronName} - The word 'Electron'",
"{electronVersion} - Electron runtime version (e.g. 25.0.0)",
"{chromiumIcon} - Chromium icon",
"{chromiumName} - The word 'Chromium'",
"{chromiumVersion} - Chromium engine version (e.g. 125.0.0.0)",
"{devBannerIcon} - Dev banner icon",
"{newline} or \\n - Newline character"
];
function handleChange(newValue) {
@ -61,13 +67,29 @@ function FormatSetting(setValue) {
{"\n\n"}
</Forms.FormText>
<Forms.FormText className="vc-discord-dev-banner">Preview: {preview}</Forms.FormText>
<TextInput
<Forms.FormText className="vc-discord-dev-banner">Preview:</Forms.FormText>
<Forms.FormText style={{ padding: "2px" }}>{preview}</Forms.FormText>
<textarea
className="vc-discord-dev-banner-input"
value={state}
onChange={handleChange}
onChange={e => handleChange(e.target.value)}
placeholder="{buildChannel} {buildNumber} ({buildHash}) | {equicordName} {equicordVersion} ({equicordHash})"
rows={1}
ref={el => {
if (el) {
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
}
}}
onInput={e => {
const el = e.currentTarget;
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
}}
/>
{error && (
<Forms.FormText className={"vc-discord-dev-banner-error"}>{error}</Forms.FormText>
)}

View file

@ -7,3 +7,24 @@
margin-top: 8px;
color: var(--text-danger);
}
.vc-discord-dev-banner-icons {
display: inline-flex;
align-items: center;
vertical-align: middle;
height: 1em;
width: 1em;
margin-right: 0.25em;
}
.vc-discord-dev-banner-input {
width: 100%;
resize: none;
overflow: hidden;
background-color: var(--background-base-low);
color: var(--text-default);
border: 1px solid var(--border-subtle) !important;
border-radius: 12px;
outline: none;
margin-top: 12px;
}