Compare commits

..

1 commit

Author SHA1 Message Date
Vendicated
38ee298ce2
improve css of various plugins 2025-02-01 20:32:44 +01:00
31 changed files with 96 additions and 284 deletions

View file

@ -69,7 +69,7 @@ function ReloadRequiredCard({ required }: { required: boolean; }) {
<Forms.FormText className={cl("dep-text")}>
Restart now to apply new plugins and their settings
</Forms.FormText>
<Button onClick={() => location.reload()}>
<Button onClick={() => location.reload()} className={cl("restart-button")}>
Restart
</Button>
</>
@ -158,8 +158,8 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
className={classes(ButtonClasses.button, cl("info-button"))}
>
{plugin.options && !isObjectEmpty(plugin.options)
? <CogWheel />
: <InfoIcon />}
? <CogWheel className={cl("info-icon")} />
: <InfoIcon className={cl("info-icon")} />}
</button>
}
/>

View file

@ -63,10 +63,7 @@
height: 8em;
display: flex;
flex-direction: column;
}
.vc-plugins-info-card div {
line-height: 32px;
gap: 0.25em;
}
.vc-plugins-restart-card {
@ -76,11 +73,11 @@
color: var(--info-warning-text);
}
.vc-plugins-restart-card button {
.vc-plugins-restart-button {
margin-top: 0.5em;
background: var(--info-warning-foreground) !important;
}
.vc-plugins-info-button svg:not(:hover, :focus) {
.vc-plugins-info-icon:not(:hover, :focus) {
color: var(--text-muted);
}

View file

@ -1,179 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { MessageExtra, MessageObject } from "@api/MessageEvents";
import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin from "@utils/types";
import { findLazy } from "@webpack";
const TesseractLogger = new Logger("Tesseract", "#ff9e64");
let worker!: Tesseract.Worker;
function reduceBboxGreatest(acc: Tesseract.Bbox, cur: Tesseract.Bbox): Tesseract.Bbox {
return {
x0: Math.min(acc.x0, cur.x0),
x1: Math.max(acc.x1, cur.x1),
y0: Math.min(acc.y0, cur.y0),
y1: Math.max(acc.y1, cur.y1)
};
}
function findWordLocation(text: Tesseract.Block[], regex: RegExp): Tesseract.Bbox[] {
const locs: Tesseract.Bbox[] = [];
for (let i = 0; i < text.length; i++) {
const block = text[i];
if (block.text.match(regex)) {
const bl = locs.length;
for (let j = 0; j < block.paragraphs.length; j++) {
const paragraph = block.paragraphs[j];
if (paragraph.text.match(regex)) {
const bl = locs.length;
for (let k = 0; k < paragraph.lines.length; k++) {
const line = paragraph.lines[k];
if (line.text.match(regex)) {
const bl = locs.length;
for (let l = 0; l < line.words.length; l++) {
const word = line.words[l];
let matches: RegExpExecArray[];
if ((matches = [...word.text.matchAll(new RegExp(regex, `${regex.flags.replace("g", "")}g`))]).length) {
for (const match of matches) {
const syms = word.symbols
.slice(match.index, match.index + match[0].length)
.map(x => x.bbox)
.reduce(reduceBboxGreatest);
locs.push(syms);
}
}
}
if (locs.length === bl) {
locs.push(line.bbox);
}
}
}
if (locs.length === bl) {
locs.push(paragraph.bbox);
}
}
}
if (locs.length === bl) {
locs.push(block.bbox);
}
}
}
return locs;
}
interface CloudUpload {
new(file: { file: File; isThumbnail: boolean; platform: number; }, channelId: string, showDiaglog: boolean, numCurAttachments: number): CloudUpload;
upload(): void;
}
const CloudUpload: CloudUpload = findLazy(m => m.prototype?.trackUploadFinished);
function getImage(file: File): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = URL.createObjectURL(file);
img.onload = () => resolve(img);
img.onerror = reject;
});
}
function canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {
return new Promise<Blob>(resolve => {
canvas.toBlob(blob => {
if (blob) {
resolve(blob);
} else {
throw new Error("Failed to create Blob");
}
}, "image/png");
});
}
const badRegex = /nix(?:os)?|This ?content ?is|blocked ?by ?this ?server/i;
export default definePlugin({
name: "AntiTessie",
authors: [Devs.sadan],
description: "Scans your messages with ocr for anything that matches the selected regex, and if found, blurs it",
start() {
if (!window?.Tesseract) {
fetch(
"https://unpkg.com/tesseract.js@6.0.0/dist/tesseract.min.js"
)
.then(async r => void (0, eval)(await r.text()))
.then(async () => {
worker = await Tesseract.createWorker("eng", Tesseract.OEM.TESSERACT_LSTM_COMBINED, {
corePath: "https://unpkg.com/tesseract.js-core@6.0.0/tesseract-core-simd-lstm.wasm.js",
workerPath: "https://unpkg.com/tesseract.js@6.0.0/dist/worker.min.js",
});
})
.then(() => {
worker.setParameters({
tessedit_pageseg_mode: Tesseract.PSM.AUTO
});
});
}
},
stop() {
worker.terminate();
},
async onBeforeMessageSend(channelId: string, message: MessageObject, extra: MessageExtra): Promise<void | { cancel: boolean; }> {
if (extra.channel.guild_id !== "1015060230222131221" && extra.channel.guild_id !== "1041012073603289109") {
return;
}
const uploads = extra?.uploads ?? [];
for (let i = 0; i < uploads.length; i++) {
async function convertToFile(canvas: HTMLCanvasElement): Promise<File> {
const blob = await canvasToBlob(canvas);
return new File([blob], `${upload.filename.substring(0, upload.filename.lastIndexOf("."))}.png`, {
type: "image/png"
});
}
const upload = uploads[i];
if (!upload.isImage) continue;
console.log(upload);
const ret = await worker.recognize(upload.item.file, {
}, {
text: true,
blocks: true,
});
if (ret.data.text.match(badRegex)) {
const toBlur = findWordLocation(ret.data.blocks!, badRegex);
const sourceImage = await getImage(upload.item.file);
const width = sourceImage.naturalWidth;
const height = sourceImage.naturalHeight;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d")!;
ctx.canvas.width = width;
ctx.canvas.height = height;
ctx.drawImage(sourceImage, 0, 0, width, height);
for (const { x0, x1, y0, y1 } of toBlur) {
ctx.fillStyle = "black";
ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
}
const newFile = await convertToFile(canvas);
const attachment = new CloudUpload({
file: newFile,
isThumbnail: false,
platform: 1
}, channelId, false, uploads.length);
attachment.upload();
extra.uploads![i] = attachment as any;
}
}
}
});

View file

@ -1,29 +1,29 @@
.client-theme-settings {
.vc-clientTheme-settings {
display: flex;
flex-direction: column;
}
.client-theme-container {
.vc-clientTheme-container {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.client-theme-settings-labels {
.vc-clientTheme-labels {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.client-theme-container > [class^="colorSwatch"] > [class^="swatch"] {
.vc-clientTheme-container [class^="swatch"] {
border: thin solid var(--background-modifier-accent) !important;
}
.client-theme-warning * {
.vc-clientTheme-warning-text {
color: var(--text-danger);
}
.client-theme-contrast-warning {
.vc-clientTheme-contrast-warning {
background-color: var(--background-primary);
padding: 0.5rem;
border-radius: .5rem;

View file

@ -7,6 +7,7 @@
import "./clientTheme.css";
import { definePluginSettings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import { Devs } from "@utils/constants";
import { Margins } from "@utils/margins";
import { classes } from "@utils/misc";
@ -14,6 +15,8 @@ import definePlugin, { OptionType, StartAt } from "@utils/types";
import { findByCodeLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack";
import { Button, Forms, ThemeStore, useStateFromStores } from "@webpack/common";
const cl = classNameFactory("vc-clientTheme-");
const ColorPicker = findComponentByCodeLazy("#{intl::USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR}", ".BACKGROUND_PRIMARY)");
const colorPresets = [
@ -60,9 +63,9 @@ function ThemeSettings() {
}
return (
<div className="client-theme-settings">
<div className="client-theme-container">
<div className="client-theme-settings-labels">
<div className={cl("settings")}>
<div className={cl("container")}>
<div className={cl("settings-labels")}>
<Forms.FormTitle tag="h3">Theme Color</Forms.FormTitle>
<Forms.FormText>Add a color to your Discord client theme</Forms.FormText>
</div>
@ -76,10 +79,10 @@ function ThemeSettings() {
{(contrastWarning || nitroThemeEnabled) && (<>
<Forms.FormDivider className={classes(Margins.top8, Margins.bottom8)} />
<div className={`client-theme-contrast-warning ${contrastWarning ? (isLightTheme ? "theme-dark" : "theme-light") : ""}`}>
<div className="client-theme-warning">
<Forms.FormText>Warning, your theme won't look good:</Forms.FormText>
{contrastWarning && <Forms.FormText>Selected color won't contrast well with text</Forms.FormText>}
{nitroThemeEnabled && <Forms.FormText>Nitro themes aren't supported</Forms.FormText>}
<div className={cl("warning")}>
<Forms.FormText className={cl("warning-text")}>Warning, your theme won't look good:</Forms.FormText>
{contrastWarning && <Forms.FormText className={cl("warning-text")}>Selected color won't contrast well with text</Forms.FormText>}
{nitroThemeEnabled && <Forms.FormText className={cl("warning-text")}>Nitro themes aren't supported</Forms.FormText>}
</div>
{(contrastWarning && fixableContrast) && <Button onClick={() => setTheme(oppositeTheme)} color={Button.Colors.RED}>Switch to {oppositeTheme} mode</Button>}
{(nitroThemeEnabled) && <Button onClick={() => setTheme(theme)} color={Button.Colors.RED}>Disable Nitro Theme</Button>}

View file

@ -121,6 +121,7 @@ function DearrowButton({ component }: { component: Component<Props>; }) {
height="24px"
viewBox="0 0 36 36"
aria-label="Toggle Dearrow"
className="vc-dearrow-icon"
>
<path
fill="#1213BD"

View file

@ -1,4 +1,4 @@
.vc-dearrow-toggle-off svg {
.vc-dearrow-toggle-off .vc-dearrow-icon {
filter: grayscale(1);
}

View file

@ -157,7 +157,7 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea
src={user.getAvatarURL(void 0, void 0, false)}
/>
)}
<Text variant="text-md/normal">
<Text variant="text-md/normal" className={cl("modal-list-item-text")}>
{
permission.type === PermissionType.Role
? role?.name ?? "Unknown Role"

View file

@ -73,7 +73,7 @@
background-color: var(--background-modifier-selected);
}
.vc-permviewer-modal-list-item > div {
.vc-permviewer-modal-list-item-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;

View file

@ -39,7 +39,7 @@ function BlockedUser({ user, isBusy, setIsBusy }: { user: ReviewDBUser; isBusy:
return (
<div className={cl("block-modal-row")}>
<img src={user.profilePhoto} alt="" />
<img className={cl("block-modal-avatar")} src={user.profilePhoto} alt="" />
<Forms.FormText className={cl("block-modal-username")}>{user.username}</Forms.FormText>
<UnblockButton
onClick={isBusy ? undefined : async () => {

View file

@ -65,7 +65,7 @@ function Modal({ modalProps, modalKey, discordId, name, type }: { modalProps: an
</ModalContent>
<ModalFooter className={cl("modal-footer")}>
<div>
<div className={cl("modal-footer-wrapper")}>
{ownReview && (
<ReviewComponent
refetch={refetch}

View file

@ -16,7 +16,7 @@
border: 1px solid var(--profile-message-input-border-color);
}
.vc-rdb-modal-footer > div {
.vc-rdb-modal-footer-wrapper {
width: 100%;
margin: 6px 16px;
}
@ -117,13 +117,13 @@
align-items: center;
}
.vc-rdb-block-modal-row img {
.vc-rdb-block-modal-avatar {
border-radius: 50%;
height: 2em;
width: 2em;
}
.vc-rdb-block-modal img::before {
.vc-rdb-block-modal-avatar::before {
content: "";
display: block;
width: 100%;

View file

@ -68,15 +68,16 @@ function PickerModal({ rootProps, close }: { rootProps: ModalProps, close(): voi
return (
<ModalRoot {...rootProps}>
<ModalHeader className={cl("modal-header")}>
<Forms.FormTitle tag="h2">
<Forms.FormTitle tag="h2" className={cl("modal-title")}>
Timestamp Picker
</Forms.FormTitle>
<ModalCloseButton onClick={close} />
<ModalCloseButton onClick={close} className={cl("modal-close-button")} />
</ModalHeader>
<ModalContent className={cl("modal-content")}>
<input
className={cl("date-picker")}
type="datetime-local"
value={value}
onChange={e => setValue(e.currentTarget.value)}

View file

@ -1,4 +1,4 @@
.vc-st-modal-content input {
.vc-st-date-picker {
background-color: var(--input-background);
color: var(--text-normal);
width: 95%;
@ -29,18 +29,14 @@
place-content: center space-between;
}
.vc-st-modal-header h1 {
.vc-st-modal-title {
margin: 0;
}
.vc-st-modal-header button {
.vc-st-modal-close-button {
padding: 0;
}
.vc-st-preview-text {
margin-bottom: 1em;
}
.vc-st-button svg {
transform: scale(1.1) translateY(1px);
}

View file

@ -94,6 +94,7 @@ function GuildInfoModal({ guild }: GuildProps) {
<div className={cl("header")}>
{iconUrl
? <img
className={cl("icon")}
src={iconUrl}
alt=""
onClick={() => openImageModal({
@ -170,6 +171,7 @@ function Owner(guildId: string, owner: User) {
return (
<div className={cl("owner")}>
<img
className={cl("owner-avatar")}
src={ownerAvatarUrl}
alt=""
onClick={() => openImageModal({

View file

@ -21,7 +21,7 @@
margin: 0.5em;
}
.vc-gp-header img {
.vc-gp-icon {
width: 48px;
height: 48px;
cursor: pointer;
@ -82,7 +82,7 @@
gap: 0.2em;
}
.vc-gp-owner img {
.vc-gp-owner-avatar {
height: 20px;
border-radius: 50%;
cursor: pointer;

View file

@ -84,9 +84,9 @@ export const Code = ({
}
const codeTableRows = lines.map((line, i) => (
<tr key={i}>
<td style={{ color: theme.plainColor }}>{i + 1}</td>
<td>{line}</td>
<tr className={cl("table-row")} key={i}>
<td className={cl("table-cell")} style={{ color: theme.plainColor }}>{i + 1}</td>
<td className={cl("table-cell")}>{line}</td>
</tr>
));

View file

@ -102,7 +102,7 @@ export const Highlighter = ({
color: themeBase.plainColor,
}}
>
<code>
<code className={cl("code")}>
<Header
langName={langName}
useDevIcon={useDevIcon}

View file

@ -1,13 +1,13 @@
.shiki-container {
.vc-shiki-container {
border: 4px;
background-color: var(--background-secondary);
}
.shiki-root {
.vc-shiki-root {
border-radius: 4px;
}
.shiki-root code {
.vc-shiki-root .vc-shiki-code {
display: block;
overflow-x: auto;
padding: 0.5em;
@ -20,16 +20,16 @@
border: none;
}
.shiki-devicon {
.vc-shiki-devicon {
margin-right: 8px;
user-select: none;
}
.shiki-plain code {
.vc-shiki-plain .vc-shiki-code {
padding-top: 8px;
}
.shiki-btns {
.vc-shiki-btns {
font-size: 1em;
position: absolute;
right: 0;
@ -37,25 +37,25 @@
opacity: 0;
}
.shiki-root:hover .shiki-btns {
.vc-shiki-root:hover .vc-shiki-btns {
opacity: 1;
}
.shiki-btn {
.vc-shiki-btn {
border-radius: 4px 4px 0 0;
padding: 4px 8px;
user-select: none;
}
.shiki-btn ~ .shiki-btn {
.vc-shiki-btn ~ .vc-shiki-btn {
margin-left: 4px;
}
.shiki-btn:last-child {
.vc-shiki-btn:last-child {
border-radius: 4px 0;
}
.shiki-spinner-container {
.vc-shiki-spinner-container {
align-items: center;
background-color: rgb(0 0 0 / 60%);
display: flex;
@ -64,11 +64,11 @@
inset: 0;
}
.shiki-preview {
.vc-shiki-preview {
margin-bottom: 2em;
}
.shiki-lang {
.vc-shiki-lang {
padding: 0 5px;
margin-bottom: 6px;
font-weight: bold;
@ -77,24 +77,24 @@
align-items: center;
}
.shiki-table {
.vc-shiki-table {
border-collapse: collapse;
width: 100%;
}
.shiki-table tr {
.vc-shiki-table-row {
height: 19px;
width: 100%;
}
.shiki-root td:first-child {
.vc-shiki-root .vc-shiki-table-cell:first-child {
border-right: 1px solid transparent;
padding-left: 5px;
padding-right: 8px;
user-select: none;
}
.shiki-root td:last-child {
.vc-shiki-root .vc-shiki-table-cell:last-child {
padding-left: 8px;
word-break: break-word;
width: 100%;

View file

@ -23,7 +23,7 @@ import { resolveLang } from "../api/languages";
import { HighlighterProps } from "../components/Highlighter";
import { HljsSetting } from "../types";
export const cl = classNameFactory("shiki-");
export const cl = classNameFactory("vc-shiki-");
export const shouldUseHljs = ({
lang,

View file

@ -33,6 +33,7 @@ export function VerifiedIcon() {
forcedIconColor={forcedIconColor}
size={16}
tooltipText={getIntlMessage("CONNECTION_VERIFIED")}
className="vc-sc-tooltip-icon"
/>
);
}

View file

@ -125,7 +125,7 @@ function CompactConnectionComponent({ connection, theme }: { connection: Connect
<span className="vc-sc-tooltip">
<span className="vc-sc-connection-name">{connection.name}</span>
{connection.verified && <VerifiedIcon />}
<TooltipIcon height={16} width={16} />
<TooltipIcon height={16} width={16} className="vc-sc-tooltip-icon" />
</span>
}
key={connection.id}

View file

@ -14,6 +14,6 @@
word-break: break-all;
}
.vc-sc-tooltip svg {
.vc-sc-tooltip-icon {
min-width: 16px;
}

View file

@ -19,6 +19,7 @@
import "./spotifyStyles.css";
import { Settings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import { Flex } from "@components/Flex";
import { ImageIcon, LinkIcon, OpenExternalIcon } from "@components/Icons";
import { debounce } from "@shared/debounce";
@ -28,7 +29,7 @@ import { ContextMenuApi, FluxDispatcher, Forms, Menu, React, useEffect, useState
import { SpotifyStore, Track } from "./SpotifyStore";
const cl = (className: string) => `vc-spotify-${className}`;
const cl = classNameFactory("vc-spotify-");
function msToHuman(ms: number) {
const minutes = ms / 1000 / 60;
@ -40,7 +41,7 @@ function msToHuman(ms: number) {
function Svg(path: string, label: string) {
return () => (
<svg
className={classes(cl("button-icon"), cl(label))}
className={cl("button-icon", label)}
height="24"
width="24"
viewBox="0 0 24 24"
@ -285,11 +286,12 @@ function Info({ track }: { track: Track; }) {
</>
);
if (coverExpanded && img) return (
<div id={cl("album-expanded-wrapper")}>
{i}
</div>
);
if (coverExpanded && img)
return (
<div id={cl("album-expanded-wrapper")}>
{i}
</div>
);
return (
<div id={cl("info-wrapper")}>

View file

@ -30,22 +30,17 @@
background-color: var(--background-modifier-selected);
}
.vc-spotify-button svg {
.vc-spotify-button-icon {
height: 24px;
width: 24px;
}
[class*="vc-spotify-shuffle"] > svg,
[class*="vc-spotify-repeat"] > svg {
[class*="vc-spotify-shuffle"] .vc-spotify-button-icon,
[class*="vc-spotify-repeat"] .vc-spotify-button-icon {
width: 22px;
height: 22px;
}
.vc-spotify-button svg path {
width: 100%;
height: 100%;
}
/* .vc-spotify-button:hover {
filter: brightness(1.3);
} */
@ -87,12 +82,19 @@
gap: 0.5em;
}
#vc-spotify-info-wrapper img {
#vc-spotify-album-image {
height: 90%;
object-fit: contain;
border-radius: 3px;
transition: filter 0.2s;
}
#vc-spotify-album-expanded-wrapper img {
#vc-spotify-album-image:hover {
filter: brightness(1.2);
cursor: pointer;
}
#vc-spotify-album-expanded-wrapper #vc-spotify-album-image {
width: 100%;
object-fit: contain;
}
@ -137,16 +139,6 @@
cursor: pointer;
}
#vc-spotify-album-image {
border-radius: 3px;
transition: filter 0.2s;
}
#vc-spotify-album-image:hover {
filter: brightness(1.2);
cursor: pointer;
}
#vc-spotify-progress-bar {
position: relative;
color: var(--text-normal);

View file

@ -76,7 +76,7 @@ export function TranslateModal({ rootProps }: { rootProps: ModalProps; }) {
return (
<ModalRoot {...rootProps}>
<ModalHeader className={cl("modal-header")}>
<Forms.FormTitle tag="h2">
<Forms.FormTitle tag="h2" className={cl("modal-title")}>
Translate
</Forms.FormTitle>
<ModalCloseButton onClick={rootProps.onClose} />

View file

@ -55,7 +55,7 @@ export function TranslationAccessory({ message }: { message: Message; }) {
return (
<span className={cl("accessory")}>
<TranslateIcon width={16} height={16} />
<TranslateIcon width={16} height={16} className={cl("accessory-icon")} />
{Parser.parse(translation.text)}
{" "}
(translated from {translation.sourceLanguage} - <Dismiss onDismiss={() => setTranslation(undefined)} />)

View file

@ -6,7 +6,7 @@
place-content: center space-between;
}
.vc-trans-modal-header h1 {
.vc-trans-modal-title {
margin: 0;
}
@ -17,7 +17,7 @@
font-weight: 400;
}
.vc-trans-accessory svg {
.vc-trans-accessory-icon {
margin-right: 0.25em;
}

View file

@ -1,16 +1,16 @@
.vc-toolbox-btn,
.vc-toolbox-btn>svg {
.vc-toolbox-icon {
-webkit-app-region: no-drag;
}
.vc-toolbox-btn>svg {
.vc-toolbox-icon {
color: var(--interactive-normal);
}
.vc-toolbox-btn[class*="selected"]>svg {
.vc-toolbox-btn[class*="selected"] .vc-toolbox-icon {
color: var(--interactive-active);
}
.vc-toolbox-btn:hover>svg {
.vc-toolbox-btn:hover .vc-toolbox-icon {
color: var(--interactive-hover);
}

View file

@ -88,7 +88,7 @@ function VencordPopout(onClose: () => void) {
function VencordPopoutIcon(isShown: boolean) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" width={24} height={24}>
<svg viewBox="0 0 27 27" width={24} height={24} className="vc-toolbox-icon">
<path fill="currentColor" d={isShown ? "M9 0h1v1h1v2h1v2h3V3h1V1h1V0h1v2h1v2h1v7h-1v-1h-3V9h1V6h-1v4h-3v1h1v-1h2v1h3v1h-1v1h-3v2h1v1h1v1h1v3h-1v4h-2v-1h-1v-4h-1v4h-1v1h-2v-4H9v-3h1v-1h1v-1h1v-2H9v-1H8v-1h3V6h-1v3h1v1H8v1H7V4h1V2h1M5 19h2v1h1v1h1v3H4v-1h2v-1H4v-2h1m15-1h2v1h1v2h-2v1h2v1h-5v-3h1v-1h1m4 3h4v1h-4" : "M0 0h7v1H6v1H5v1H4v1H3v1H2v1h5v1H0V6h1V5h1V4h1V3h1V2h1V1H0m13 2h5v1h-1v1h-1v1h-1v1h3v1h-5V7h1V6h1V5h1V4h-3m8 5h1v5h1v-1h1v1h-1v1h1v-1h1v1h-1v3h-1v1h-2v1h-1v1h1v-1h2v-1h1v2h-1v1h-2v1h-1v-1h-1v1h-6v-1h-1v-1h-1v-2h1v1h2v1h3v1h1v-1h-1v-1h-3v-1h-4v-4h1v-2h1v-1h1v-1h1v2h1v1h1v-1h1v1h-1v1h2v-2h1v-2h1v-1h1M8 14h2v1H9v4h1v2h1v1h1v1h1v1h4v1h-6v-1H5v-1H4v-5h1v-1h1v-2h2m17 3h1v3h-1v1h-1v1h-1v2h-2v-2h2v-1h1v-1h1m1 0h1v3h-1v1h-2v-1h1v-1h1"} />
</svg>
);

View file

@ -9,10 +9,6 @@
margin-bottom: 1em;
}
.vc-vmsg-modal audio {
width: 100%;
}
.vc-vmsg-preview {
color: var(--text-normal);
border-radius: 24px;