feat(UrlHighlighter): add plugin (#535)
* feat(UrlHighlighter): add plugin * Update index.tsx --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
parent
90b1360aa7
commit
8d9062f90a
2 changed files with 196 additions and 0 deletions
149
src/equicordplugins/urlHighlighter/index.tsx
Normal file
149
src/equicordplugins/urlHighlighter/index.tsx
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { classNameFactory } from "@api/Styles";
|
||||
import { Button } from "@components/Button";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Heading } from "@components/Heading";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
import { ColorPicker, TextInput } from "@webpack/common";
|
||||
|
||||
interface PatternEntry {
|
||||
pattern: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
const DEFAULT_COLOR = "#eb7396";
|
||||
|
||||
const cl = classNameFactory("vc-url-hl-");
|
||||
|
||||
const TrashIcon = findComponentByCodeLazy("2.81h8.36a3");
|
||||
const PlusIcon = findComponentByCodeLazy("0v-5h5a1");
|
||||
|
||||
const hexToInt = (hex: string): number => parseInt(hex.replace("#", ""), 16);
|
||||
const intToHex = (n: number): string => "#" + n.toString(16).padStart(6, "0");
|
||||
|
||||
const PatternsComponent = ErrorBoundary.wrap(() => {
|
||||
const { patterns } = settings.store;
|
||||
|
||||
return (
|
||||
<section>
|
||||
<Heading>URL Patterns</Heading>
|
||||
{patterns.map((entry, i) => (
|
||||
<div key={i} className={cl("pattern-wrapper")}>
|
||||
<TextInput
|
||||
value={entry.pattern}
|
||||
onChange={v => {
|
||||
patterns[i].pattern = v;
|
||||
settings.store.patterns = patterns;
|
||||
}}
|
||||
placeholder="*.example.com"
|
||||
/>
|
||||
<div className={cl("color-picker")}>
|
||||
<ColorPicker
|
||||
color={hexToInt(entry.color)}
|
||||
onChange={(c: number) => {
|
||||
patterns[i].color = intToHex(c);
|
||||
settings.store.patterns = patterns;
|
||||
}}
|
||||
showEyeDropper={false}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
className={cl("remove-button")}
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
patterns.splice(i, 1);
|
||||
settings.store.patterns = patterns;
|
||||
}}
|
||||
>
|
||||
<TrashIcon className={cl("icon")} />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
<Button
|
||||
onClick={() => settings.store.patterns.push({ pattern: "", color: DEFAULT_COLOR })}
|
||||
className={cl("add-button")}
|
||||
variant="secondary"
|
||||
size="small"
|
||||
>
|
||||
<PlusIcon className={cl("icon")} /> Add New
|
||||
</Button>
|
||||
</section>
|
||||
);
|
||||
}, { noop: true });
|
||||
|
||||
const settings = definePluginSettings({
|
||||
patterns: {
|
||||
type: OptionType.COMPONENT,
|
||||
description: "URL patterns to highlight using glob patterns.",
|
||||
default: [] as PatternEntry[],
|
||||
component: PatternsComponent
|
||||
},
|
||||
boldUrls: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Make highlighted URLs bold.",
|
||||
default: false
|
||||
},
|
||||
highlightEmbeds: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Also highlight URLs in embed content.",
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
function globToRegex(glob: string): RegExp {
|
||||
const escaped = glob
|
||||
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
||||
.replace(/\*/g, ".*")
|
||||
.replace(/\?/g, ".");
|
||||
return new RegExp(escaped, "i");
|
||||
}
|
||||
|
||||
function getMatchingPattern(url: string): PatternEntry | null {
|
||||
for (const entry of settings.store.patterns) {
|
||||
const pattern = entry.pattern.trim();
|
||||
if (!pattern) continue;
|
||||
if (globToRegex(pattern).test(url)) return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "UrlHighlighter",
|
||||
description: "Highlights URLs in messages that match your patterns.",
|
||||
authors: [EquicordDevs.Prism],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: '"messageId","channelId"',
|
||||
replacement: {
|
||||
match: /,children:null!=\i\?\i:\i/,
|
||||
replace: "$&,...$self.getProps(arguments[0])"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
getProps(props: { href?: string; title?: string; }) {
|
||||
if (!props.href) return {};
|
||||
if (!settings.store.highlightEmbeds && props.href !== props.title) return {};
|
||||
|
||||
const match = getMatchingPattern(props.href);
|
||||
if (!match) return {};
|
||||
|
||||
return {
|
||||
className: cl(settings.store.boldUrls ? "marked" : "highlight"),
|
||||
style: { "--vc-url-hl-color": match.color } as React.CSSProperties
|
||||
};
|
||||
}
|
||||
});
|
||||
47
src/equicordplugins/urlHighlighter/styles.css
Normal file
47
src/equicordplugins/urlHighlighter/styles.css
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
.vc-url-hl-highlight {
|
||||
color: var(--vc-url-hl-color) !important;
|
||||
}
|
||||
|
||||
.vc-url-hl-marked {
|
||||
color: var(--vc-url-hl-color) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.vc-url-hl-pattern-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.vc-url-hl-color-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vc-url-hl-color-picker [class^="swatch"] {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.vc-url-hl-remove-button {
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
min-width: 36px !important;
|
||||
min-height: 36px !important;
|
||||
padding: 0 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vc-url-hl-add-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.vc-url-hl-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue