#๐Ÿงฉ-plugin-development

1 messages ยท Page 80 of 1

bronze dove
#

doenst matter, size={"lg"} it

quick zephyr
#

oh lg not a number

bronze dove
#

you can always look at the function source to figure these things out

quick zephyr
#

I assure you the 10 minutes between my message and your response were spent attempting to figure these things out

#

it's a lot less intuitive when you're not familiar with how it all works

bronze dove
#

true sorry if that was rude

honest stump
#

is this some discord issue or vencord issue where it doesnt add context menus to role icons when theyre expanded

#

i forgot which plugin added it but some did

honest stump
#

i could

quick zephyr
#

Feel like I'm going crazy. Why does this need all 3 parameters? ๐Ÿ˜ญ

root?.render(<QuestIcon size={26} width={26} height={26} />);

just providing one or two doesn't work. needs all 3.

#

oh a size and either height or width works. still weird

#

oh nice this ruins the tooltip fun

quick zephyr
# bronze dove doenst matter, `size={"lg"}` it

can someone explain how im supposed to apply this to icon={QuestIcon} cause anything I try either gets me an "Oh no!" red error box or causes the tooltip to stop working specifically over the quest icon itself.

bronze dove
#

You make an anon function that returns that quest icon with that prop

bronze dove
quick zephyr
#

if I just used size nothing happened

bronze dove
#

What size did you use

quick zephyr
#

10 26 28 30 100 etc anything

bronze dove
quick zephyr
#

I did but that was too big

#

I need a number

quick zephyr
#

i have no clue what that means bro ๐Ÿ˜ญ

bronze dove
quick zephyr
#

since I couldnt get the size to work with icon={QuestIcon} I tried just inserting it into the foriengObject parent which worked

#

it let me change its size

#

but the tooltip stopped working over it

quick zephyr
#

ended up just doing this and it works. trying to use the svg by using findComponentByCodeLazy was a mistake

export function QuestIcon() {
    return (
        <svg
            viewBox="0 0 24 24"
            height="26"
            width="26"
            fill="none"
        >
            <path fill="currentColor" d="..." ></path>
        </svg>
    );
}
bronze dove
#

Alright

quick zephyr
# empty sundial ...root?
const root = foreignObjectChild ? createRoot(foreignObjectChild) : null;
root?.render(<QuestIcon size={26} height={26} />);

this is what I was doing cause I couldnt figure out another way to resize the component

#

kills the tooltip over the svg though

empty sundial
#

๐Ÿ˜ญ

quick zephyr
#

looking better tho imo. closer to the discord logo in size

empty sundial
#

why would you not just try className and changing the size with css but oh well yea just grab the svg its easier and cant just randomly break due to updates

quick zephyr
#

oh goodie I dont need the ListItemContainer component so now im only rely on one findComponentByCodeLazy call need it for the pill smh

white lichen
#
    session.defaultSession.webRequest.onHeadersReceived(
        ({ responseHeaders }, cb) => {
            if (responseHeaders) {
                const cspHeader = findHeader(
                    responseHeaders,
                    "content-security-policy"
                );
                if (cspHeader) delete responseHeaders[cspHeader];

                const cspReportOnlyHeader = findHeader(
                    responseHeaders,
                    "content-security-policy-report-only"
                );
                if (cspReportOnlyHeader)
                    delete responseHeaders[cspReportOnlyHeader];
            }
            cb({ cancel: false, responseHeaders });
        }
    );
    session.defaultSession.webRequest.onHeadersReceived = () => {};
}```
#

if anyone wants an easy way to remove the new csp change

#

replaces initCsp in csp.ts

quick zephyr
#

how do I make a plugin require a restart just for turning it on or off

#

can only find examples for when options are changed

white lichen
quick zephyr
#

added a patch and it worked

#
patches: [{
    find: "",
    replacement: {
        match: "",
        replace: ""
    }
}],

idk if there's any consequences to empty patches

white lichen
#

thats what i was starting to think, thanks for confirming

white lichen
#

maybe make it find something like "require_restart" as a placeholder just in case

cedar olive
quick zephyr
#

I need to load above it

#

so I use startAt: StartAt.Init,

#

that becomes obsolete if you enable it after startup

cedar olive
#

hmm I see

quick zephyr
#

they both use addServerListElement(ServerListRenderPosition.Above, ...);

cedar olive
#

then just do patches: [] for now

quick zephyr
#

didnt work

#

had to fill it

cedar olive
#

should

#

I don't think so

quick zephyr
#

lemme try again

white lichen
#

yea patches: [] by itself doesnt force a restart

cedar olive
#

weird

#

it used to

quick zephyr
#

yep

#

doesnt atm

white lichen
#
        {
            find: "require_restart",
            replacement: {
                match: "",
                replace: "",
            },
        },
    ],``` 

i cant see this going wrong
quick zephyr
quick zephyr
vast karma
#

You'll get a warning in devtools that the find was not found

quick zephyr
#

devtools warns me about a lot of things

#

so many things

swift delta
empty sundial
#

๐Ÿ‘

swift delta
quick zephyr
#

thanks

cedar olive
#

better than one with a find which will never match

quick zephyr
#

holy banger almost have it properly detecting being on the page. just need to get it to work for navigating there manually and not by the shortcut

#

let's go chat we did it

#

hm I wonder if I can access the number of unfinished quests without needing to be on the page

#

QuestsStore exists

#

nice QuestStore.quests

quick zephyr
#
<PillContainer
    selected={onQuestsPage}
>
    <ListItem
        onClick={questButtonClicked}
        className="server-list-button"
        tooltip="Quests"
        icon={QuestIcon}
        selected={onQuestsPage}
    >
    </ListItem>
</PillContainer>

is there an equivalent to selected for the mini-dot (unread) or do I have to do some external handling for that

#

looks like servers have unread: true but doesnt work here. sadge

dull magnet
#

my bad

quick zephyr
#

where's that tutorial for connecting my account to vscode so I can test findComponentByCodeLazy without dozens of reloads

#

ah vencord companion

#

if u steal my token imma be mad

#

does cloning the github not count

dull magnet
#

pnpm build --dev

#

(or better yet use pnpm watch)

quick zephyr
#

yay it worked

#

im never gonna understand findComponentByCodeLazy lmao ๐Ÿ˜ญ

#

arent you just supposed to copy a piece of code the component points you to? how is this failing smh

dull magnet
#

lazy evaluated on first access

#

-Lazy methods are lazy wrappers over the non lazy ones

quick zephyr
#

oh I see what joona did. I hate it

dull magnet
#

non lazy ones search immediately
lazy ones only search when you actually use it

quick zephyr
#

so the problem is the current find is const PillContainer = findComponentByCodeLazy("listItem,ref"); which I guess returns the first pill found? which would be the DMs button pill. problem is that one doesnt support the unread state like the guild ones do but Idk how to get one of the guild ones specifically. pain

#

is there a findComponentByCodeLazyButSkipTheFirstMatch

cedar olive
#

that's not how things work

quick zephyr
#

sad

#

then whats happening here

cedar olive
#

if you are finding the wrong one, then you need to adjust the code you are finding it with

#

if listItem,ref exists in another one, choose another text

quick zephyr
#

thats the only match that works ๐Ÿ˜ญ

#

only way to differentiate them would be by the value of t

#

sigh

cedar olive
#

look for the one that supports unread as you are saying

quick zephyr
#

im looking where the components tab is placing me

quick zephyr
#

then why it aint accepting the unread props

quaint cipher
#

try a breakpoint

quick zephyr
#

it accepts selected fine

#

breakpoint where

cedar olive
#

show an screenshot for what you are looking for

quaint cipher
#

anyway on my client the only prop that seems to be being passed to ListItem is children and then the first child does have selected

quick zephyr
#

when I inspect my pill I see this. when I inspect a guild pill I see this

#

so mine isnt taking the unread prop for some reason

quaint cipher
#

i dont think its taking any of them and those are defaulting

quick zephyr
#

it does take them

quaint cipher
#

eh

quick zephyr
#

selected={onQuestsPage}
and I modify onQuestsPage based on if im on the page

cedar olive
#

are you looking for this

quaint cipher
#

the one on the left i think

quick zephyr
#

im looking for the white dot

quaint cipher
quick zephyr
#

which is 20px high when hovered

#

and 40px high when selected

cedar olive
#

this is the pill

quaint cipher
#

try this
findComponentByCodeLazy(""pill":"empty"")

quick zephyr
#

hm just realized the pill isnt taking any props actually. it's the list item that is

cedar olive
#

listitem is just a wrapper for a list of pills

#

thus the reason it's just a div with children

#

the actual pill is another component, the one I sent the screenshot and the same fres is showing

quick zephyr
#

your pic is hovering over the nitro button though

cedar olive
#

I know

#

but the last one I sent is for the pill you are mentioning

quick zephyr
#

yes ive tried many variations of that exact line

#

it never finds

#

yes

cedar olive
#

findComponentByCodeLazy('"pill":"empty"')

#

do you understand how find by code works?

quick zephyr
#

it uses the code of a component to find the component

cedar olive
#

and what's this

cedar olive
quick zephyr
#

ive tried that line too. but I probably didnt remove the spaces

cedar olive
#

probably

#

you always need to write it as if it is minified code

quick zephyr
#

gave it an unread prop and now it doesnt load fun

#

as in when discord opens the quest button isnt there anymore

shrewd tundraBOT
#

Replaces "Minifed React Error" with the actual error.

Authors

Cynosphere, maisy

quick zephyr
#

oop unnested the listitem from the pill and now it's there, albeit like 40px offset down

#

ok nested the pill in the list item instead of the other way around. almost

#

lost the unread though

#

or it's off screen

#

man why is this so confusing ๐Ÿ˜ญ

#

no errors Sadge

#

I went back to the original nesting

#

cause neither of those 2 worked

#

just inserts a nearly empty div hmm

#

if I move them

<PillContainer
    selected={onQuestsPage}
    unread={true}
>
</PillContainer>
<ListItem
    onClick={questButtonClicked}
    className="server-list-button"
    tooltip="Quests"
    icon={QuestIcon}
    selected={onQuestsPage}
    unread={true}
>
</ListItem>

I end up with

#

oh this is the containerRef

#

one of these really needs to be nested in the other I think

#

I need wrapper inside of listitem

#

I need whats inside of wrapper inside of listitem

#

wrapper is empty

#

im so lost

#

that wrapper yes

#

thats a ghost wrapper

#

the wrapper inside of listitem isnt

#

agony

#

got rid of PillContainer entirely and it's position right now but now there's no pill when I hover or anything

#

the html makes it look like there should be though

#

when I hover a div is made and unmade

#

just nothing visually

#

ok got it working with hover and select. I had to uncomment out

const pill = containerRef?.current?.querySelector('[class*="pill"]');
const wrapper = pill?.querySelector('[class*="wrapper"]');
pill?.classList.add(wrapper ? wrapper.className : "");
#

unread still not working. not sure how to do that

#

this is why I need control of the pill instead of relying on the built in one oof

#

it looks like guild list items do have an unread prop on the list item itself

#

idk why it's not working here

#

on the parent anonymous wrapper whatever that is

#

I had that issue yesterday. gotta delete your extension cache

#

the what

#

experiment from 2021 SKULL_SKELETON what are the odds they just yeet the component at some point

#

so the only solution to have access to an unread prop is to go through html hell?

#

thats what v1 was before I was convinced to use components

#

hmmm

#

im aight at regex just no clue how to patch

#

why cant I seem to just get the icon component itself without the pill prop. whenever I try I just get Oh no!

#

they're siblings

#

but whenever I try anything from N it just dies

quick zephyr
#
function QuestButton() {
    const containerRef = React.useRef<HTMLDivElement>(null);

    React.useEffect(() => {
        if (!document.getElementById("quick-quests-extra-style")) {
            const style = document.createElement("style");
            style.id = "quick-quests-extra-style";
            style.textContent = `
                .quests-container {
                    position: relative;
                }
                .quests-container-unread-pill {
                    position: absolute;
                    top: 0;
                    left: 0;
                    z-index: 1;
                }
                .quests-container-button {
                    position: relative;
                    z-index: 0;
                }
            `;
            document.head.appendChild(style);
        }

        const builtinPill = containerRef?.current?.querySelector('.quests-container-button [class*="pill"]');
        const builtinPillInternalWrapper = builtinPill?.querySelector('[class*="wrapper"]');

        if (builtinPillInternalWrapper) {
            builtinPill?.classList.add(builtinPillInternalWrapper.className);
        }
    }, []);

    return (
        <ErrorBoundary>
            <div ref={containerRef} className="quests-container">
                <PillItem
                    unread={true}
                    className="quests-container-unread-pill"
                />
                <div className="quests-container-button">
                    <ListItem
                        onClick={questButtonClicked}
                        tooltip="Quests"
                        icon={QuestIcon}
                        selected={onQuestsPage}
                    />
                </div>
            </div>
        </ErrorBoundary>
    );
}
#

now can just hookup some js to hide it when needed yippee

#

not really sure how React.useEffect(()) works properly so there might be a more clean way to handle that part of it

#

I just need everything rendered before it runs

#

also not sure why the built-in pill is broken when used this way

#

it's supposed to be .pill .wrapper but instead it's provided by the component as .pill > .wrapper

#

so I have to copy the wrapper class to the parent or the hover/selected effects dont work

#

weirdge

hushed loom
#

useEffect has like 3 different uses based on what's passed to it

quick zephyr
#

looked it up. seems to run one time once the component is rendered

hushed loom
#

there are 3

quick zephyr
#

hopefully the one I'm using it for works every time

#

I was told the other day that the :has CSS selector is laggy. Is it laggy just by existing, or only when its parent div is on the page?

dull magnet
#

don't use has

quick zephyr
#

plz

hushed loom
#

if you're writing a plugin you shouldn't need it

quick zephyr
#

if I cant use has then ill need to move elements around manually

hushed loom
#

sounds like xy tbh

dull magnet
quick zephyr
#

can I just assign an order to each element individually?

dull magnet
#

yes

quick zephyr
#

ok then yeah this is less of an issue

#

I'll have to call QuestsStore.getQuest a ton of times though

#

oh nvm I can just check for the end date div

#

which is what the has was for but this is easier

#

well not easier but easy enough and supposedly not laggy Clueless

hushed loom
#

you will errorboundary.wrap

quick zephyr
#

isnt this making it perma true though

#

I can make a patch rely on a dynamic variable in the rest of my plugin code?

hushed loom
#

use \i for identifiers

quick zephyr
#

yeah I need it tied to a plugin setting and there being unclaimed quests so

#

considering patches force restarts I feel like no

#

same

hushed loom
#

guhhh i haven't really been following

#

but you cant change a patch once it's been applied

#

but other than that, if you can do it in js, yes

quick zephyr
#

can you patch in a function then or something

hushed loom
#

it

hushed loom
quick zephyr
#

it would have to use some global state or smthn tho

hushed loom
#

you can call functions from your plugin

quick zephyr
#

kinda is but discord is a small corpo so please understand

#

im forced to be hacky with it cause the ugly way discord has their components layered

quick zephyr
hushed loom
quick zephyr
#

I need a way to toggle a component visible/invisible. I'll take a look.

#

or I guess with the patch it would be a way to change the prop from true to false and back dynamically

hushed loom
#

guhhhhhh too eepy to read rn blobcatcozy

quick zephyr
#

if there are unclaimed quests and the setting for the indicator is on it would be True and otherwise False

#

but it sounds like that only triggers when you hover it

#

not dynamically

#

what if you set it to a variable and then update that variable in a while loop. does that work

#

well it might not update without hovering

#

might be some react shenanigans you could do

hushed loom
#

@quick zephyr not sure what you want to do, but you might want to take a look at accountPanelServerProfile

quick zephyr
#

bro keeps saying not sure ๐Ÿ˜ญ we've said it like 5 times ๐Ÿ˜ญ will do tho

hushed loom
#

๐Ÿ˜ญ

quick zephyr
#

yeah only updates on hover rn.

#

I think the CSS method I'm using is gonna be the better play tbh.

#

this is feeling even more hacky

#

all the css would really be doing is hiding and unhiding. not that bad

quick zephyr
#

just realized imma run into the same issue of getting the pill to rerender if I wanted to use the unread prop

#

ik it has something to do with state I just dont know enough about react to know what

#

oh got it working. idk if it's a good impl tho lol

#
let setHasUnclaimedQuestsState: React.Dispatch<React.SetStateAction<boolean>> = () => {};
...
function QuestButton() {
    const [hasUnclaimedQuests, setHasUnclaimedQuests] = useState(false);
    const containerRef = React.useRef<HTMLDivElement>(null);

    React.useEffect(() => {
        setHasUnclaimedQuestsState = setHasUnclaimedQuests;
        return () => {
            setHasUnclaimedQuestsState = () => {};
        };
    }, []);
...
start() {
    setInterval(() => {
        setHasUnclaimedQuestsState(prev => !prev);
    }, 1000);
    addServerListElement(ServerListRenderPosition.Above, this.renderQuickQuestsButton);
},
#

boils down to these sections

quick zephyr
#

can I save state between restarts? just a boolean value that I want to keep track of? ๐Ÿค”

#

}).withPrivateSettings<{ interesting

quick zephyr
safe glade
#

image zoom keeps whether the zoom is a square or a circle iirc

quick zephyr
#

thats just a normal setting

#

square boolean

quick zephyr
#

is there an easy way to add a context menu to something that usually doesn't have one ๐Ÿค”

vast karma
#

Same way as you mod anything else

quick zephyr
#

im still not at the point where I know what that means. and I was hoping there'd be a built in function like addServerListElement lol

#

oh I see an onContextMenu perhaps that'll work

vast karma
#

All the existing such hooks are done by patching the corresponding part of discord

quick zephyr
#

woah it worked lol

#

cant get middle clicking to work hmm. looks like something is eating the inputs

quick zephyr
#

nice got it

quick zephyr
#
function questMiddleClicked(event: React.MouseEvent<HTMLDivElement>) {
    if (event.button === 1) {
        event.preventDefault();
        event.stopPropagation();
        SettingsRouter.open("VencordPlugins");

        const start = Date.now();
        const waitForAddonHeaderAndSwitch = () => {
            const addonHeaders = document.querySelectorAll(".vc-addon-header");
            let found = false;

            for (const header of addonHeaders) {
                const title = header.querySelector(".vc-addon-title");

                if (title && title.textContent?.trim() === "QuickQuests") {
                    const switchButton = header.querySelector('button[role="switch"]');

                    if (switchButton) {
                        switchButton.dispatchEvent(new MouseEvent("click", {
                            bubbles: true,
                            cancelable: true,
                            view: window
                        }));

                        found = true;
                        break;
                    }
                }
            }

            if (!found) {
                if (Date.now() - start < 30000) {
                    setTimeout(waitForAddonHeaderAndSwitch, 50);
                }
            }
        };

        waitForAddonHeaderAndSwitch();
    }
}

So I have this and it's working but I would rather not have to simulate a click. I see openPluginModal and that does work, but when used externally like this the onRestartNeeded of the settings is ignored. So I'm wondering if there's some native method I'm missing or if I'm going to have to implement my own alert ๐Ÿค”

vast karma
#

Nope, have to implement your own

quick zephyr
#

agony

vast karma
#

You can check how BetterSettings does it

bronze dove
quick zephyr
#

doesnt help in this case I dont think?

#

PluginSettings uses a changes set

#

I cant access that

#
<PluginCard
    onRestartNeeded={name => changes.handleChange(name)}
    disabled={false}
    plugin={p}
    isNew={newPlugins?.includes(p.name)}
    key={p.name}
/>
bronze dove
#
function openPluginModal(plugin: Plugin, onRestartNeeded?: (pluginName: string) => void): void
quick zephyr
#

oh that was easy

#

just yoinked the onRestartNeeded there

#

function onRestartNeeded() {
    Alerts.show({
        title: "Restart required",
        body: <p>You have changed settings that require a restart.</p>,
        confirmText: "Restart now",
        cancelText: "Later!",
        onConfirm: () => location.reload()
    });
}

function questMiddleClicked(event: React.MouseEvent<HTMLDivElement>) {
    if (event.button === 1) {
        event.preventDefault();
        event.stopPropagation();
        SettingsRouter.open("VencordPlugins");
        openPluginModal(Plugins.QuickQuests, onRestartNeeded);
    }
}
#

becomes this

vast karma
#

Why the settingsrouter?

quick zephyr
#

legacy from thinking opening the settings would make it work

#

and from the simulated click method it was needed

#

well thats enough for tonight. thanks for the help

void ledge
#

Guys, can someone tell me. Where should i find patch funcs? Like usernameSpeaking. Cant understand where it comes from

silk sorrel
#

That's not a function, that's a class. It's being applied conditionally when the condition on the right is met

#

also the patch seems to be targetting some later code

empty sundial
#

go into devtools, then sources, thats the entirety of discord code, you find the piece of code you want to edit & thats your match

quick zephyr
#

is there a built in way to verify uniqueness between different settings which all share an option pool but which need to be different from each other?

hardy adder
#

what??

quick zephyr
#

worked something out

quick zephyr
#

nothing like spending a few hours fumbling cause something you dismissed at the start of the debugging session was the issue

quick zephyr
#

if I wanted to add an option here would that be a patch

vast karma
#

Depends on whether that's a regular context menu

quick zephyr
#

well right clicking doesnt bring it up. gotta click the dots

humble tulip
#

If you inspect it and it has role="menu" and an id, you can probably patch it via the contextMenus api

quick zephyr
#

thank god was not looking forward to figuring out how to patch this

#

once this is done the plugin will be done woohoo

humble tulip
#

Sick

#

If you just search contextMenus: { in the project there's tons of examples of patching them to go off

quick zephyr
#

yeah vscode's project wide search has been helping a ton

#

ive also just realized I made a custom implementation of openPluginModal for no reason smh

#

due to an oversight on my part I thought I needed to dipatch my own flux event when the modal closed

#

agony

#

all working nicely now though :)

tropic ice
quick zephyr
#

oh thats a good idea

#

well

#

the button requires a restart

#

if I want it to be read all messages compatible

#

otherwise it gets inserted below that

#

not sure if theres some way around that though

#

since we're both using addServerListElement(ServerListRenderPosition.Above, ...)

humble tulip
#

Can you not just return null for the component?

#

I assume it'd still hold its place in the list when the component changes

quick zephyr
#

not quite but this worked

return (
    <ErrorBoundary>
        {settings.store.testSetting123 && (
#

neat

#

that was easier to add than I expected

#
return (
    <ErrorBoundary>
        {(!settings.store.onlyWhenUnclaimed || hasUnclaimedUnignoredQuests) && (
            <div

quick zephyr
#

made the mistake of recloning and now none of my discords will open with vencord installed. gray screens of death. fun

#

inject command errors now. agony

#

oh I can access dev tools despite it not loading

#

did discord update within the 5 minutes I recloned and break everything or something man

humble tulip
quick zephyr
#

how do I disable a plugin from console

#

I don't see a stop function on the plugin object

#

stopPlugin doesn't take a string smh

#

oh I can pass it from Plugins.plugins. started again on restart though

humble tulip
#

You can remove it from the settings file

quick zephyr
#

ok disabled console janitor but still won't open smh

#

ah

#

that's why

#

being 244 commits behind tends to cause it to fail to load. the more you know

pearl stag
#

@fallen sandal Did betterNotification's linux implemnentation support images? I couldn't get attachments or avatars working on Ubuntu 24.04 (Gnome) with notify-send 0.8.3

#

Sorry for bothering you here but I cant comment on the pr anymore, since I haven't contributed to vencord

#

Removing --hint=string:desktop-entry:discord seems to fix the issue

fallen sandal
#

looks like gnomes notification server doesn't support image attachments??

#

@dull magnet ur only gnome user ik have you seen notifications with large attachments

dull magnet
#

uhhhh

#

idk bro

fallen sandal
#

use ur stupid brain

dull magnet
#

probably not cause they show screenshots like that

dull magnet
fallen sandal
hushed loom
dull magnet
#

give me notify-send command and ill show u how it looks

fallen sandal
dull magnet
#

you will install gnome

fallen sandal
#

I'm gonna cry

dull magnet
#

i have 3 DEs/WMs installed for testing

#

i have gnome kde and hyprland

fallen sandal
#

i do too but I dont wanna

#

I'm not on laptop

dull magnet
#

im on desktop too

fallen sandal
#

i said not

#

ur soo dumv

fallen sandal
dull magnet
#

doesnt work

pearl stag
#

Discord's implementation seems to pass image-data directly

fallen sandal
#

also try i think its like notify-send -a "VEE IS DUMB APP" -h string:desktop-entry:vesktop "beep" "borp" -h string:image-path:file:///path/to/image.png

dull magnet
#

it put's it up there as app icon

pearl stag
pearl stag
fallen sandal
fallen sandal
#

YOP

#

OK easy fix

dull magnet
#

-i is icon, no?

#

yuh uh

#

black and white vesktop icon lmao

fallen sandal
#

its treated as both in the spec and notif servers do their own yap

#

the image-path hint seems to be the most explicit ig

dull magnet
fallen sandal
#

@pearl stag replace the -i with -h string:image-path:

#

the app icon should still be done properly from the desktop file hint

fallen sandal
dull magnet
#

the desktop entry doesnt work for me

fallen sandal
#

HUSK

#

be fr

dull magnet
#

it justz doesnt send the notif

#

oh cause ur dumb

#

it's Vesktop not vesktop

#

wait no

#

with Vesktop it works but no icon

#

with vesktop it no workie

fallen sandal
#

dont make me turn on my laptop

fallen sandal
#

uh oh

pearl stag
#

yup that seems to work

fallen sandal
dull magnet
#

no response

fallen sandal
#

maybe its insane and taking the icon from the title

dull magnet
#

maybe it checks that the desktop-entry matches the current process

#

so u cant impersonate other apps

fallen sandal
#

maybe

dull magnet
pearl stag
fallen sandal
#

surely it doesn't check the caller process but also parent processes

pearl stag
#

or do you want to commit it yourself

fallen sandal
dull magnet
fallen sandal
#

@pearl stag did you do anything special for the discord icon in that screenshot u sent

#

or base patch

fallen sandal
dull magnet
#

be nice

fallen sandal
#

u first

dull magnet
fallen sandal
#

change -a to "Vesktop"

#

it'll work trust

dull magnet
#

IT DOESNT WORK

fallen sandal
#

ur lying

#

I'm installing gnome again

dull magnet
#

no notif

#

just do

notify-send -a Vesktop -i vesktop
fallen sandal
#

then why did Ruostin get it fine

dull magnet
fallen sandal
#

I'll experiment

dull magnet
#

when someone asks me what @fallen sandal's age is

fallen sandal
#

what number is that?

dull magnet
#

the flatpak one works

#

the non flatpak one doesnt

fallen sandal
#

WHAT IS RHE DESKTOP ENTRY NAME U HAVE

#

tell me rn

#

if its Vesktop.desktop I'll freak

dull magnet
#

nvm now the flatpak one also broke

fallen sandal
#

i think you have cursed fingers

dull magnet
#

also interesting: passing --wait fixes it

#

it's instantly dismissing it or smth

fallen sandal
#

LOL

#

gnome insane defaults

dull magnet
fallen sandal
#

does vesktop.desktop work

dull magnet
#

yes (without .desktop)

#

but also only with --wait

fallen sandal
#

lol okay so that's why it works for the other guy

#

it passed a default action which makes it automatically wait

fallen sandal
dull magnet
#

i mean

#

normally notifs work fine

fallen sandal
#

libnotify people then

dull magnet
#

idk

#

install gnome see if u can repro

fallen sandal
#

evil virus

dull magnet
#
#

no reply

fallen sandal
#

@pearl stag do you need help with commit author stuff

#

I'll just commit it if you dont know how

pearl stag
#

I commited

#

I think

#

yeah

dull magnet
#

interestingly, -a doesn't work when u pass desktop-entry hint

fallen sandal
#

assuming all sorts of yap

dull magnet
#

i mean it makes sense

fallen sandal
#

what if you want a different title but still want the notif governed under the app

#

cope gnome user

#

KDE can do just fine

#

HUSK

#

@pearl stag You removed the file:// prefix

#

don't do that

pearl stag
#

Is it necessary? Just passing the file path seemed to work fine atleast on gnome

fallen sandal
#

it is necessary

#

spec gobbledygook

pearl stag
#

ah

dull magnet
fallen sandal
pearl stag
#

does vencord have a built in method for sanitizing strings?

dull magnet
#

sanitize for what

pearl stag
#

Since the plugin is using notify-send, if the body contains unescaped characters, some bad things can happen

#

Like here's an example of what a command might look like

notify-send DM Example author: helo --action=default=Open --app-name=Discord --hint=string:desktop-entry:discord -h string:image-path:...

#

Someone could replace the body with malicious code

dull magnet
#

what kind of malicious code

#

shell injection?
html?

#

use node apis correctly and there won't be shell injection

dull magnet
dull magnet
#

explode

hushed loom
#

soon

dull magnet
#

if you need more control, you can also use spawn

fallen sandal
#

@pearl stag are you gonna a write the basic html/xml parsing for the Linux notifs like you did for windows

pearl stag
fallen sandal
#

yeah

pearl stag
#

Does that exist for Linux

fallen sandal
#

its in a TODO in the code I pr'd

pearl stag
#

ah true

fallen sandal
#

dont do the img tag though and maybe not hyperlink

pearl stag
#

Yeah

#

I probably need to create a seperate settings component

fallen sandal
#

actually

pearl stag
#

having "windows only" everywhere kind of sucks

fallen sandal
#

probably just bold italic and hyperlink since those are the subset that the xdg portal implements

dull magnet
#

browser has apis for xml (de-)serialisation

fallen sandal
#

no stupuf

#

its constructing it in a hardcoded format

pearl stag
#

I wonder whats the best way to implement the bold and italics

#

probably markdown

#

or more specifically * and **

fallen sandal
#

no

#

its specifically the html tags

pearl stag
fallen sandal
#

ah

#

yeah prob that

#

oo it'd be cool to parse hyperlinks in the message itself

fallen sandal
pearl stag
#

That should be easy*

fallen sandal
#

๐Ÿฅธ

pearl stag
#

I mean the syntax itself is passed, not the output

#

if that makes sense

#
#

instead of just text

fallen sandal
#

also rounded icons on linux

pearl stag
#

Even discord has that by default

fallen sandal
silk sorrel
fallen sandal
pearl stag
fallen sandal
dull magnet
#

(please don't parse discord markdown manually)

fallen sandal
#

@dull magnet can discords image editing slop round images

#

ik it can crop

dull magnet
#

actually

fallen sandal
dull magnet
#

you need to pass some options

#
Parser.parseToAST("@fallen sandal you **stink** [fr](https://google.com)", {
        channelId: message.channel_id,
        messageId: message.id,
        allowLinks: true,
        allowHeading: true,
        allowList: true,
        allowEmojiLinks: true,
        viewingChannelId: SelectedChannelStore.getChannelId(),
})
#

full list

return {
            channelId: t,
            messageId: n,
            allowLinks: !!r.allowLinks,
            allowDevLinks: !!r.allowDevLinks,
            formatInline: !!r.formatInline,
            noStyleAndInteraction: !!r.noStyleAndInteraction,
            allowHeading: !!r.allowHeading,
            allowList: !!r.allowList,
            previewLinkTarget: !!r.previewLinkTarget,
            disableAnimatedEmoji: !!r.disableAnimatedEmoji,
            isInteracting: !!r.isInteracting,
            allowEmojiLinks: !1,
            disableAutoBlockNewlines: !0,
            mentionChannels: [],
            soundboardSounds: [],
            muted: !1,
            unknownUserMentionPlaceholder: false && !0,
            viewingChannelId: r.viewingChannelId,
            forceWhite: !!r.forceWhite
        }
fallen sandal
dull magnet
#

idk bro

#

you can easily edit images with canvas

fallen sandal
#

blehg

dull magnet
#
async function cropImageToCircle(src, size = 128) {
    const { promise: imgLoaded, resolve } = Promise.withResolvers();
    
    const img = new Image();
    img.onload = resolve;
    img.crossOrigin = "anonymous";
    img.src = src;

    await imgLoaded;

    const canvas = document.createElement("canvas");
    canvas.width = canvas.height = size;

    const ctx = canvas.getContext("2d");

    ctx.beginPath();
    ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
    ctx.clip();

    ctx.drawImage(img, 0, 0, size, size);

    return canvas.toDataURL();
}

await cropImageToCircle("https://cdn.discordapp.com/avatars/721853658941227088/bd1051c099643c15a5049506324a01b6.png?size=128")
#

canvas is super powerful

fallen sandal
#

complain at vee do get her to shit out code for you

#

life hack!

dull magnet
#

๐Ÿ”ฅ

fallen sandal
#

EW

dull magnet
pearl stag
dull magnet
#

it does

pearl stag
#

does it

dull magnet
#

the type is missing parseToAst cause i was too lazy to type it

pearl stag
#

ah

fallen sandal
silk sorrel
#

inverse squircle jumpscare

hushed loom
dull magnet
silk sorrel
#

n < 1

dull magnet
#

im not good at geometry

#

i have no clue how any of this works

silk sorrel
#

I think with the proposed superellipse border radius feature in css you'll be able to use custom parameters too

dull magnet
#

@fallen sandal

fallen sandal
dull magnet
#

is it just me or is that circle not smooth

fallen sandal
#

just u

silk sorrel
#

looks alright

dull magnet
#

can u tell a difference

fallen sandal
#

no

dull magnet
#

the first one was drawn with gpu, second one with software

#

they produce slightly different results it's funny

silk sorrel
#

one is slightly more jagged?? but how does the component that drew it make a difference

dull magnet
silk sorrel
#

also the user will definitely never see a difference ๐Ÿ˜ญ

fallen sandal
fallen sandal
#

so itll depend on how the manufacturer implemented whatever its using to draw the circle

silk sorrel
#

ngl my intuition tells me the edge drawing algorithm would be exactly the same but I know nothing about hardware so idk ๐Ÿ˜ญ

dull magnet
#

can u tell a difference now

#

no they're the same lol

#

funny

fallen sandal
#

i couldnt tell a difference before

dull magnet
#

can u tell a difference now

fallen sandal
#

hi i think my internet is lagging

dull magnet
fallen sandal
#

how did u tell it to use gpu vs software

silk sorrel
dull magnet
dull magnet
#

not the same file but have the same contents

fallen sandal
dull magnet
#

well

#

the name of the parameter gives you a hint when you'd use it

fallen sandal
#

i didnt read that

dull magnet
#

if you very frequently need to read the data, it's more expensive to keep copying the data

fallen sandal
#

@dull magnet youre expensive

proud parrotBOT
tropic ice
dull magnet
#

ye

quick zephyr
#

So I think I just found a bug with the Experiments plugin. If you have the Experiments plugin enabled then after a restart all gradient names are permanently flattened until you disable the plugin. I thought it was something wrong with my PR for showMeYourName so I spent ages reinjecting over and over to fix it. But it never worked so I tested @hushed loom and @humble tulip 's PRs and same issue. Then I started disabling plugins in batches til I found the Experiments plugin causing it. I just had a friend test it with a normie install and he confirm it happened to him. I also tested it as the only enabled plugin and still happened.

tldr; If you enable the Experiments plugin all gradient names are perma flattened until you disable the plugin or reinject Vencord, but then it will happen again after the first restart.

Took a look at the plugin code and have no idea what would be causing it. ๐Ÿค”

humble tulip
#

Have you checked if it's an experiment you have enabled/disabled and not the plugin itself?

quick zephyr
#

had no experiments on

#

and my friend enabled it for the first time ever

humble tulip
#

They work for me and I've had the experiments plugin enabled forever suffoPeepoShrug

quick zephyr
#

wtf

#

oh if I close discord fully and start it again it's fixed

#

it only breaks after a ctrl+r reload or a reload induced by enabling the plugin

humble tulip
#

Works fine after ctrl+r, reload from disabling/enabling the plugin and full restart

quick zephyr
#

are you looking at a gradient name

#

thats the only thing it effects

humble tulip
quick zephyr
#

in chat

#

mentions and sidebar dont count

humble tulip
#

It's kinda hard to tell because the gradients in this server are so subtle but it's the only server I'm in that has them

#

Like that after reload I genuinely can't tell lol

quick zephyr
#

and thats with experiments enabled? man this is weird. why would it be effecting me and my friend but not you

humble tulip
#

Yeah, I've had experiments on the whole time, aside from disabling it to test reenabling it

#

I'm on my pr branch atm

quick zephyr
#

yeah checked out to your pr

#

disabled every plugin except showmeyourname and experiments

#

rebuilt

#

reinjected

#

started up > had gradients

#

ctrl + r > gradients gone

#

quit discord and launch it again > gradients back

humble tulip
#

Beats me

#

I'll disable stuff later and see if I have something enabled that fixes it

quick zephyr
#

yeah thats the only thing I can think of, some extra plugin that undoes the damage or smthn ๐Ÿค”

humble tulip
#

I deleted my settings file and restarted, then just enabled the experiments plugin and smyn and they're still fine

quick zephyr
#

every time I think of something and go "oh maybe that's it" I remember my friend who just has it installed the regular way had the same issue hmmmm this sucks

#

ok narrowed it even further

#

it only effects the server I ctrl+r in

#

if I reload in another server then nav to my server with gradients they're there

analog lintel
#

heyo

#

im making a plugin to make searching for messages easier

#

idk how to use native discord components tho

#

so idk how to render messages like how discord does

vast karma
#

Check how discord does it

#

Or any of the hundred-ish plugins

pearl stag
#

I hope these types are accurate enough for the parser result

humble tulip
#

The link title may be [text](https://example.com "this is a title") text

#

Determines what the tooltip says on hover

pearl stag
#

ah

#

I didnt even know that you could specify a tooltip lol

#

I havent gotten hyperlinks to work yet tho

#

probably missing a parser option

#

with ts parser.parseToAST(notificationBody, { channelId: basicNotification.channel_id, messageId: basicNotification.message_id, allowLinks: true, allowDevLinks: true, allowHeading: true, allowList: true, allowEmojiLinks: true, previewLinkTarget: true, viewingChannelId: basicNotification.channel_id, });

quick zephyr
#

Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

this is what hell looks like

humble tulip
#

I dunno why though

quick zephyr
#

how does that possibly cause an error .-.

humble tulip
#

Is there a hook call below that block?

quick zephyr
#

would wrapEmojis count

#

const wrapEmojis = findByCodeLazy(/"span",\{className:\i\.emoji,children:/);

#

I call this a few times in the try block

#

nothing else looks hooky to me

humble tulip
#

Yeah I think they do use a hook in there

#

I had to move the wrap emoji calls to before my ifs as that broke rule of hooks too

quick zephyr
#

so this is your fault

humble tulip
#

You can pass undefined into it and it's fine so moving it up shouldn't affect anything

quick zephyr
#

well it's not an issue anymore

#

after moving that if statement up

#

no clue why

#

๐Ÿค”

#

oh nvm

#

so what I need that call above what

#

all of my early returns?

#

agony

humble tulip
#

Yeah just put it in a place where it'll run on every function call

#

Feels wasteful if you know you don't need it but react is react suffoPeepoShrug

quick zephyr
#

my issue is all the code ill useless be running each time

#

and gonna have to add a bunch of ?.xyz

humble tulip
#

React thumb

quick zephyr
#

ok not breaking the plugin anymore but still getting Rendered more hooks than during the previous render. in console. hm

#

moved the wrapemojis calls out of the try except and it stopped

#

now I practically have nothing in the try except block anyways

#

I might as well get rid of it at this point

#

.-.

#

do I just let error boundary take the wheel

vast karma
#

Do not put hooks, or functions that call hooks, inside conditionals or loops

quick zephyr
#

I didnt consider try except a conditional

vast karma
#

Do not use try/catch either, use errorboundary

#

try/catch doesn't work in react components

quick zephyr
#

I see

#

I am using error boundary

#

I just thought try except was good too

#

hm it's not causing the plugin any issues anymore but console still filled with Rendered more hooks than during the previous render. from WebpackModule ๐Ÿค”

#

well by filled with I mean it posted 4 at startup and then no more

vast karma
#

Do you have code

quick zephyr
#

hm the issue is the wrapEmojis function itself

#

removing it stops them from popping up into console

vast karma
#

Hard to say with no code

#

How are you calling it

quick zephyr
#
const firstValue = wrapEmojis(values[first].value);
const secondValue = second ? wrapEmojis(values[second].value) : null;
const thirdValue = third ? wrapEmojis(values[third].value) : null;
#

oh do those count as conditionals

#

sigh

vast karma
#

Hey look, wrapEmojis inside conditionals

quick zephyr
#

TIL react is ass

humble tulip
vast karma
#

Easiest way around it is to wrap each of those wrapEmojis calls in a separate component

#

If it isn't one already, have you checked that

quick zephyr
#

suffocate says wrapemojis can take null

#

so imma just do that

#

well ""

#
const firstValue = wrapEmojis(values[first].value);
const secondValue = wrapEmojis(second ? values[second].value : "");
const thirdValue = wrapEmojis(third ? values[third].value : "");
pearl stag
#

what's the second second param then?

humble tulip
#

Second param is boolean inline

pearl stag
#

ah

humble tulip
pearl stag
quick zephyr
#

now to figre out why reloading with experiments enabled breaks gradients

#

anyone else with access to a server that has gradient roles willing to test?

humble tulip
#

If it works when you navigate away and back, surely that just means that either it's not rerendering when the gradient colours are fetched or it's not fetching them right away?

quick zephyr
#

no

#

when I navigate away and back it still is flat

#

when I scroll up in that channel all new messages are still flat

#

when I switch channels in that guild all messages are still flat

#

if I switch servers that new server is normal

humble tulip
quick zephyr
#

if I go back the issue is still there on the original server I reloaded on

humble tulip
#

Hmm

quick zephyr
#

also I checked the response of the smyn plugin and it responds with the gradient colors. the problem is it relies on the parent have the correct classes and the correct injected css that discord does on its own

humble tulip
#

Even if I disable the enhanced role colours experiment and reenable it it just puts the gradients back in realtime with no issues

quick zephyr
#

really need another person or two to test cause I'd be fully willing to believe it's just my setup being weird but the fact my friend had the same issue confuses me

#

the difference in the html discord generates

humble tulip
#

We're gonna do all this and find out you two have some other experiment (enabled legitimately on discord's side) that breaks it

#

Although the experiments plugin affecting it is weird in itself

quick zephyr
#
{
    find: 'type:"user",revision',
    replacement: {
        match: /!(\i)&&"CONNECTION_OPEN".+?;/g,
        replace: "$1=!0;"
    }
},

This patch is it though if my testing isnt gaslighting me

#

I comment this one out and it stops happening

pearl stag
#

is anyone here on linux?

pearl stag
vast karma
#

Depends on which notification daemon you use

#

There are hundreds, if not millions

pearl stag
#

just wondering if the common ones support it

#

this isn't the case on ubuntu 24.04 with gnome

pearl stag
#

(unless i'm missing something)

vast karma
#

Pretty sure the sender needs to set a flag that it contains markup

#

Dunno if notify-send sets that by default

fallen sandal
#

gnome might simply be insane

#

they work on KDE

#

also @pearl stag I sent another patch

pearl stag
#

thanks for the contribution

pearl stag
#

I couldn't find anything in the man pages

fallen sandal
#

it doesnt

#

libnotify itself does but its not exposed via the cli

pearl stag
#

ugh

#

I'll just make the setting false by default, and add a warning to the description

fallen sandal
#

you can check $XDG_CURRENT_DESKTOP

pearl stag
#

Wouldn't I also need to know which environments support the markup?

fallen sandal
# pearl stag ugh

can u try notify-send "title" "Example <b>bold text</b>" --hint=boolean:use-body-markup:true

pearl stag
#

still renders the tags as text

fallen sandal
#

does \n work

pearl stag
#

seems to just be removed

fallen sandal
#

hm so what im reading is correct then

pearl stag
#

notify-send "title" "Newline -> \n here"

fallen sandal
#

there is a flag to enable markup like that but i cant find how to pass it

pearl stag
#

can you link the resource you were looking at?

pearl stag
#

thanks

fallen sandal
proud parrotBOT
pearl stag
#

Maybe ubuntu's default notification server just sucks lol

fallen sandal
#

it should be the same

pearl stag
#

I can't really see another reason why markup would work in one de but not in gnome

fallen sandal
#

cause they are different code bases

#

and the markup should be working

#

i think this may be a bug

proud parrotBOT
fallen sandal
#

@dull magnet you gnome user can u notify-send "title" "Example <b>bold text</b>"

dull magnet
#

nope

fallen sandal
#

it is totally a bug

#

sooo husk

dull magnet
#

I'm a baby cookie where is mama

fallen sandal
#

in my belly

#

ur next

quick zephyr
#

horrible choice to open plugin chat rn

humble tulip
#

@pearl stag I see you're manually parsing the ast to html but you can just have simplemarkdown do it if you want

const SimpleMarkdown = findByProps("htmlFor");

SimpleMarkdown.defaultHtmlOutput(SimpleMarkdown.defaultInlineParse('This is **markdown** parsed *to html* via __SimpleMarkdown__'));``` = ```html
This is <strong>markdown</strong> parsed <em>to html</em> via <u>SimpleMarkdown</u>
pearl stag
#

I'll definitely switch to that lol

humble tulip
#

np thumb

#

I did try using Discord's list of rules for it at first but they don't provide html render methods for a lot and it makes it messy, so I just did simplemarkdown's defaults

#

Looks like it has a sanitize text function too, might be useful since you asked about that earlier I think

fallen sandal
#

is there any way to define a plugin setting asynchronously like based on a value fetched from native

dull magnet
#

wdym define

#

do you mean default value

fallen sandal
#

the options n stuff

dull magnet
#

like a select option?

fallen sandal
#

yeag

dull magnet
#

what's this for why does it have to be async

fallen sandal
#

async cause functions n stuff coming out of native is async

dull magnet
#

elaborate a bit cause the answer depends

fallen sandal
#

trying to make betterNotifications options more dynamic

#

i need to get XDG_CURRENT_DESKTOP into renderer

dull magnet
#

just an env variable?

fallen sandal
#

should be

dull magnet
#

ah right, plugin ipc doesnt support sync ipc

#

you need to make your own component

#

OptionType.Component

#

then inside the component useAwaiter() on the promise

fallen sandal
#

okay thanks vee you are so helpful rn

#

u stupid chud

quick zephyr
humble tulip
quick zephyr
quick zephyr
steady cedar
#

oh cool

quick zephyr
#

currently changing how im doing the styling.

steady cedar
quick zephyr
#

im just restyling the quests tab

#

and the button is a quick acces to that tab

quick zephyr
#

does applying classes based on conditions count as "No raw DOM manipulation" under the plugin rules

dull magnet
#

depends

#

if you're conditionally applying classes to your own components in markup that's totally fine and even good, vencord does that too

#

if you're using dom methods to change classes dynamically that's bad

quick zephyr
#

or I guess patch the individual tile? ๐Ÿค”

dull magnet
#

how are u applying the classes

quick zephyr
#

every time I navigate to the quests page or receive a flux event which would update the values I reprocess the divs

dull magnet
#

show code

quick zephyr
#
async function processQuestData() {
    const startTime = Date.now();
    const timeout = 30000;

    if (onQuestsPage) {
        while (Date.now() - startTime < timeout && !cancelQuestProcessing) {
            const questTiles = document.querySelectorAll("[id^='quest-tile-']");

            if (questTiles.length > 0) {
                break;
            }

            await new Promise(resolve => setTimeout(resolve, 50));

            if (cancelQuestProcessing) {
                return;
            }
        }

        const questTiles = document.querySelectorAll("[id^='quest-tile-']");
        questTiles.forEach(tile => { tile.classList.remove("vc-qq-quest-item-reorder-unclaimed", "vc-qq-quest-item-reorder-ignored", "vc-qq-quest-item-restyle-unclaimed", "vc-qq-quest-item-restyle-ignored"); });
    }

    let totalQuests = 0;
    let unclaimedUnignoredQuests = 0;

    const { quests } = QuestStore;
    const { ignoredQuests } = settings.store;
    const ignoredQuestsSet = new Set(ignoredQuests.split("\n").map(line => normalizeQuestName(line)));
    const cleanedIgnoredQuests: string[] = [];

    for (const quest of quests.values()) {
        const questName = normalizeQuestName(quest.config?.messages?.questName || "");
        const tile = document.getElementById(`quest-tile-${quest.id}`);
        totalQuests++;

        const claimedQuest = quest.userStatus?.claimedAt;
        const questExpired = new Date(quest.config.expiresAt) < new Date();
        const questIgnored = ignoredQuestsSet.has(questName);

        if (!claimedQuest && !questExpired) {
            unclaimedUnignoredQuests++;

            if (!questIgnored) {
                tile && settings.store.restyleUnclaimed ? tile.classList?.add("vc-qq-quest-item-restyle-unclaimed") : null;
                tile && settings.store.reorderQuests ? tile.classList?.add("vc-qq-quest-item-reorder-unclaimed") : null;
            }
        }

        if (claimedQuest && !questIgnored) {
            tile && settings.store.restyleClaimed ? tile.classList?.add("vc-qq-quest-item-restyle-claimed") : null;
            tile && settings.store.reorderQuests ? tile.classList?.add("vc-qq-quest-item-reorder-claimed") : null;
        }

        if (questIgnored) {
            if (!questExpired && !claimedQuest) {
                cleanedIgnoredQuests.push(questName);
                tile && settings.store.restyleIgnored ? tile.classList?.add("vc-qq-quest-item-restyle-ignored") : null;
                tile && settings.store.reorderQuests ? tile.classList?.add("vc-qq-quest-item-reorder-ignored") : null;
            }

            continue;
        }
    }

    console.info(`[QuickQuests]: Found ${totalQuests} total quests.`);
    console.info(`[QuickQuests]: Found ${unclaimedUnignoredQuests} unclaimed unignored quests.`);
    updateHasUnclaimedUnignoredQuests(unclaimedUnignoredQuests > 0);
    overwriteIgnoredQuests(cleanedIgnoredQuests.join("\n"));
}
dull magnet
#

yeah that's horrid

#

you should patch the component to add classes directly

quick zephyr
#

right that'll be fun

dull magnet
#

it's not hard

#

the component code will have className: stuff

#

just patch it to be
className: stuff + $self.getExtraClasses()

getExtraClasses just returns foo bar baz to add those 3 classes

#

way easier than what you're doing

#

you can even use react hooks to dynamically update based on store data changing

quick zephyr
#

can I effect the inline style that way ๐Ÿค”

dull magnet
#

yes that too

#

some plugins do that

quick zephyr
#

ok so that will let me make the tile colors a setting like I originally wanted to do

proud parrotBOT
# dull magnet https://github.com/Vendicated/Vencord/blob/bb106b7c49a6f1019194738a66ee75c858468...

index.ts: Lines 38-66

    // add --avatar-url-<resolution> css variable to avatar img elements
    // popout profiles
    {
        find: "#{intl::LABEL_WITH_ONLINE_STATUS}",
        replacement: {
            match: /src:null!=\i\?(\i).{1,50}"aria-hidden":!0/,
            replace: "$&,style:$self.getAvatarStyles($1)"
        }
    },
    // chat avatars
    {
        find: "showCommunicationDisabledStyles",
        replacement: {
            match: /src:(\i),"aria-hidden":!0/,
            replace: "$&,style:$self.getAvatarStyles($1)"
        }
    }
],

getAvatarStyles(src: string | null) {
    if (!src || src.startsWith("data:")) return {};

    return Object.fromEntries(
        [128, 256, 512, 1024, 2048, 4096].map(size => [
            `--avatar-url-${size}`,
            `url(${src.replace(/\d+$/, String(size))})`
        ])
    );
},
dull magnet
#

you can do whatever styles you want

quick zephyr
#

nice

#

while I have your attention can you try out that experiments bug I mentioned earlier to see if it effects you or not. cause it's effecting me and a few friends

dull magnet
#

I'm in bed

quick zephyr
#

f

quick zephyr
quick zephyr
#

ok got inserting the class to the main tile to work. if I want to allow custom colors though I'll need to insert styles on 7 child elements which means 7 patches... maybe ill not implement that after all. can cope with the default colors I pick.

quick zephyr
#

well I have a good bit of refactoring to do to dedupe some logic but the patch is working so it's mostly done \0w0/

cedar olive
#

now add a button to autocomplete quests

quick zephyr
#

horror

tame quiver
#

o/ (smol repost since this the better channel for it)
I'm working on a Plugin that needs to do http reqeusts on arbitrary urls, so I'm trying to edit the CspPolicies map, my current code is this for native.ts

import { logger } from './index';
import { CspPolicies, ConnectSrc } from "@main/csp";

export function addCsp(url: string) {
    CspPolicies[`${url}`] ??= ConnectSrc;
    logger.info(`Added CSP for ${url}`, CspPolicies[`${url}`]);
}

But for some reason any CspPolicies edit (I'm doing it on plugin load) seems to break Discord completely on launch, no window gets created as instead I just get the JS error below...

pearl stag
tame quiver
pearl stag
#

Im guessing logger is in index.ts(x)?

#

I dont think you can import things from the frontend in native.ts

bronze dove
#

you can use VencordNative.csp.requestAddOverride

tame quiver
pearl stag
#

yeah

tame quiver
#

or still native

bronze dove
#

ye index

tame quiver
#

ah tysm <3

silk sorrel
#

How can I find a specific export based on its properties? I am trying to access the appearance/developerMode discord settings option and read its value

bronze dove
#

const DeveloperMode = getUserSettingLazy("appearance", "developerMode")!;

silk sorrel
#

thank you!

dull magnet
#

vp UserSettingsAPI

shrewd tundraBOT
dull magnet
#

oh does it exclude api plugins

#

those last two properties are added by a vencord api

elfin geyser
#

how does getting around the csp policies work?
my websocket doesnt connect anymore :/
i figured it out, i wasnt restarting fully

quick zephyr
# dull magnet you can do whatever styles you want

the quests code is funky. no matter where I tried overwriting styles it only ever accepted the default styles. like if it default had a "color" style, it would only allow overwriting that, not adding any new ones. ๐Ÿค”

tropic ice
#

can you not use css?

quick zephyr
#

that's what I'm already doing. I injected classes which works just fine. but I wanted to allow the user to set a custom highlight color rather than the default ones I pick out and that would require inlining styles

#

not a huge deal cause you're not on the quest page often anyways but just something extra I wanted to try

#

unless you can use the plugin settings in the css file lol

tropic ice
quick zephyr
#

thats... what I said im already doing?

#

a class for unclaimed, a class for claimed, a class for ignored

#

but that still requires me to hard code the colors for them

humble tulip
#

You could use a css var and set the value on a further up parent or root, I dunno how cursed that'd be though

quick zephyr
#

I think I just figured it out. not sure if it'll work on all the elements ill need to inline but I got one to work

hushed loom
quick zephyr
#

that would be easier ๐Ÿค”

#

if it included children

#

if not then not gonna work

humble tulip
#

Yeah that's kinda what I meant

#

Set the colour somewhere you can access via code easily and do the rest with css

hushed loom
quick zephyr
#

so I just style the main container with variables from the plugin settings and then the css file can take it from there interesting

quick zephyr
#

thats certainly better than 7ish patches

quick zephyr
#

if you add variables to an inline style block will those variables work in the inline styles on its children

#

looks like it does

#

neat

humble tulip
#

Yeah you could add them to the html tag and they should still work all the way down provided they don't get overwritten

quick zephyr
#
{
    find: "id:\"quest-tile-\".concat",
    replacement: {
        match: /(concat\((\i)[^}]+},)className:(\i\(\)\([^)]+\)),/,
        replace: "$1className:$self.getQuestTileClasses($3, $2),style:$self.getCustomColorVars(),"
    }
},

nice

humble tulip
#

Not to make it even more complex, but ClientTheme has a colour picker component you could use if you wanted as well

quick zephyr
#

oh that would be much better than having to self validate the input and having no preview

#

will do that after I finish this bit. have to ensure the text doesnt become unreadable no matter the color picked.

humble tulip
#

Good luck lol, auto text contrast for custom themes sucks

#

Make the user pick the text colour too lol

quick zephyr
#

hmmm the inline style set by the component is overriding my css

#

nvm suddenly working. not sure why it had a change of heart

humble tulip
#

Yeah I think inline styles have a higher specificity than css, not sure if !important overrides it though

#

I'm no css wizard

pearl stag
#

yay or nay? Im wondering if I should slightly blur the foreground image's edges

quick zephyr
#

really annoying you apparently cant change an svg's fill with css so I have to hide the watch again icon or patch it SKULL_SKELETON

#

or to correct myself, you can with css, but svgs ignore variables declared above them

#

and I kinda need it to follow the variables if I want it visible lol

humble tulip
#

Have you tried setting color instead of fill?

quick zephyr
#

I was mistaken, the actual issue was that they dont support variables above them not that the css doesnt work

#

oh nvm teehee

#

i think I just typod the variable name

#

5am moment

#

the correct css was fill though

#
.vc-qq-quest-item> :nth-child(2) button>div>div>svg path {
    fill: var(--vc-qq-quest-name);
}
humble tulip
#

Sweet

#

How do you even get to the quests page, is it an a/b thing?

quick zephyr
#

like officially? bottom of your server list > discover > quests

#

programatically?

import { NavigationRouter } from "@webpack/common";
export const questPath = "/discovery/quests";
NavigationRouter.transitionTo(questPath);
humble tulip
#

Ah, thanks

#

I never go in there

quick zephyr
#

yeah it's quite inconvenient for me since im in like 100+ servers

#

that was the original idea behind this plugin

#

just a quick shortcut button

#

but then I got pissed at how they sort quests. it's like purely random

#

completed quests mixed with uncompleted mixed with expired