fix some script
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @name Rion Zaphkiel (Pywal Integrated)
|
||||
* @version 1.2.1
|
||||
* @version 1.3.2
|
||||
* @description A custom theme for BetterDiscord that integrates with Pywal by pasting the color cache.
|
||||
* @author Rion
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
:root {
|
||||
/* -- Theme Accent Colors (Mapped to Pywal) -- */
|
||||
--main-color: var(--color1); /* Main accent color */
|
||||
--hover-color: var(--color3); /* Hover accent color */
|
||||
--hover-color: var(--color5); /* Hover accent color */
|
||||
--success-color: #43b581; /* Keeping static for clarity */
|
||||
--danger-color: #982929; /* Keeping static for clarity */
|
||||
--warning-color: #fff;
|
||||
@@ -67,7 +67,7 @@
|
||||
--text-muted: var(--color7) !important;
|
||||
--interactive-normal: var(--color7) !important;
|
||||
--interactive-hover: var(--color15) !important;
|
||||
--interactive-active: var(--color1) !important; /* Black text for active elements */
|
||||
--interactive-active: var(--color1) !important;
|
||||
--background-modifier-accent: rgba(255, 255, 255, 0.06) !important;
|
||||
--scrollbar-auto-thumb: var(--main-color) !important;
|
||||
--scrollbar-auto-track: transparent !important;
|
||||
@@ -161,7 +161,7 @@
|
||||
5. Component Styles
|
||||
========================================================================== */
|
||||
.info__2debe::after {
|
||||
content: "Rion Zaphkiel" " " "1.2.1";
|
||||
content: "Rion Zaphkiel" " " "1.3.2";
|
||||
color: var(--text-muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.3333333333;
|
||||
@@ -179,7 +179,7 @@
|
||||
filter: drop-shadow(0 0 5px var(--hsl-main-color));
|
||||
}
|
||||
.visual-refresh:not(.platform-osx) .leading_c38106::after {
|
||||
content: "1.2.1";
|
||||
content: "1.3.2";
|
||||
position: static;
|
||||
margin-top: -5px;
|
||||
margin-left: 5px;
|
||||
|
||||
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.12.7",
|
||||
"version": "1.12.8",
|
||||
"addonlistControls": {
|
||||
"plugin": {
|
||||
"view": "grid"
|
||||
@@ -14,7 +14,8 @@
|
||||
"window": true,
|
||||
"addons": true,
|
||||
"store": true,
|
||||
"editor": false
|
||||
"editor": false,
|
||||
"developer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"all": {
|
||||
"changeLogs": {
|
||||
"BDFDB": "4.2.7",
|
||||
"BDFDB": "4.3.6",
|
||||
"BetterFriendList": "1.6.3",
|
||||
"EditUsers": "5.0.7",
|
||||
"ImageUtilities": "5.6.3",
|
||||
@@ -18,8 +18,8 @@
|
||||
"useChromium": false
|
||||
},
|
||||
"hashes": {
|
||||
"0BDFDB.data.json": "a9d07bfced7360491909f31e25262dead289759c",
|
||||
"0BDFDB.raw.css": "d0b50a89fc20f5eda9939f0aaf13664ed2b920d0"
|
||||
"0BDFDB.data.json": "58a58732f32aa581fda80294aa968d3a06a1d78d",
|
||||
"0BDFDB.raw.css": "92b08d02d2935f9afc99b54b04ab3e11ea6aa012"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
* @name BDFDB
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 4.2.8
|
||||
* @version 4.3.6
|
||||
* @description Required Library for DevilBro's Plugins
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
@@ -768,7 +768,7 @@ module.exports = (_ => {
|
||||
customIcon: `<svg width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M 15.46875 0.859375 C 15.772992 1.030675 16.059675 1.2229406 16.326172 1.4316406 C 17.134815 2.0640406 17.768634 2.8677594 18.208984 3.8183594 C 18.665347 4.8050594 18.913286 5.9512625 18.945312 7.2265625 L 18.945312 7.2421875 L 18.945312 7.2597656 L 18.945312 16.753906 L 18.945312 16.769531 L 18.945312 16.785156 C 18.914433 18.060356 18.666491 19.206759 18.208984 20.193359 C 17.768634 21.144059 17.135961 21.947578 16.326172 22.580078 C 16.06768 22.782278 15.790044 22.967366 15.496094 23.134766 L 16.326172 23.134766 C 20.285895 23.158766 24 20.930212 24 15.820312 L 24 8.3535156 C 24.021728 3.1431156 20.305428 0.86132812 16.345703 0.86132812 L 15.46875 0.859375 z M 0 0.8671875 L 0 10.064453 L 4.4492188 15.191406 L 4.4492188 5.4394531 L 8.4394531 5.4394531 C 11.753741 5.4394531 11.753741 9.8828125 8.4394531 9.8828125 L 7.0234375 9.8828125 L 7.0234375 14.126953 L 8.4394531 14.126953 C 11.753741 14.126953 11.753741 18.568359 8.4394531 18.568359 L 0 18.568359 L 0 23.138672 L 8.3457031 23.138672 C 12.647637 23.138672 15.987145 21.3021 16.105469 16.75 C 16.105469 14.6555 15.567688 13.090453 14.621094 12.001953 C 15.567688 10.914853 16.105469 9.3502594 16.105469 7.2558594 C 15.988351 2.7036594 12.648845 0.8671875 8.3457031 0.8671875 L 0 0.8671875 z"/></svg>`,
|
||||
buttons: [{
|
||||
className: BDFDB.disCN.noticeupdatebuttonall,
|
||||
contents: BDFDB.LanguageUtils.LanguageStrings.FORM_LABEL_ALL,
|
||||
contents: BDFDB.LanguageUtils.LanguageStrings.ALL,
|
||||
onClick: _ => {for (let notice of updateNotice.querySelectorAll(BDFDB.dotCN.noticeupdateentry)) notice.click();}
|
||||
}],
|
||||
onClose: _ => vanishObserver.disconnect()
|
||||
@@ -1907,7 +1907,7 @@ module.exports = (_ => {
|
||||
}
|
||||
};
|
||||
|
||||
if (!("Notification" in window)) {}
|
||||
if (!("Notification" in window)) {BDFDB.NotificationUtils.toast(content, config);}
|
||||
else if (Notification.permission === "granted") queue();
|
||||
else if (Notification.permission !== "denied") Notification.requestPermission(function (response) {if (response === "granted") queue();});
|
||||
};
|
||||
@@ -2108,7 +2108,7 @@ module.exports = (_ => {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltipmutetext),
|
||||
size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
|
||||
color: Internal.LibraryComponents.TextElement.Colors.MUTED,
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.VOICE_CHANNEL_MUTED
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.MUTED
|
||||
}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.GuildTooltipMutedText, {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltipmutetext),
|
||||
muteConfig: muteConfig
|
||||
@@ -2551,12 +2551,21 @@ module.exports = (_ => {
|
||||
});
|
||||
}
|
||||
};
|
||||
const LanguageStores = BDFDB.ModuleUtils.find(m => m[InternalData.LanguageStringHashes.DISCORD] && m, {all: true, defaultExport: false});
|
||||
LibraryModules.LanguageStore = (LanguageStores.find(n => n && n.exports && n.exports[InternalData.LanguageStringHashes.DISCORD]) || LanguageStores.find(n => n && n.exports && n.exports.default && n.exports.default[InternalData.LanguageStringHashes.DISCORD]) || {}).exports || {};
|
||||
const hasDiscordStringHash = m => {
|
||||
return m && [InternalData.LanguageStringHashes.DISCORD].flat(10).some(hash => m[hash] && typeof m[hash] != "function");
|
||||
};
|
||||
const LanguageStores = BDFDB.ModuleUtils.find(m => (hasDiscordStringHash(m) || hasDiscordStringHash(m.default)) && m, {all: true, defaultExport: false});
|
||||
|
||||
LibraryModules.EngLanguageStore = (LanguageStores.find(n => n && n.exports && hasDiscordStringHash(n.exports.default)) || {}).exports || {};
|
||||
LibraryModules.EngLanguageStore = LibraryModules.EngLanguageStore.default || LibraryModules.EngLanguageStore;
|
||||
|
||||
LibraryModules.LanguageStore = (LanguageStores.find(n => n && hasDiscordStringHash(n.exports)) || LanguageStores.find(n => n && n.exports && hasDiscordStringHash(n.exports.default)) || {}).exports || {};
|
||||
LibraryModules.LanguageStore = LibraryModules.LanguageStore.default || LibraryModules.LanguageStore;
|
||||
|
||||
LibraryModules.React = BDFDB.ModuleUtils.findByProperties("createElement", "cloneElement");
|
||||
LibraryModules.ReactDOM = BDFDB.ModuleUtils.findByProperties("render", "findDOMNode", {noWarnings: true}) || BDFDB.ModuleUtils.findByProperties("createRoot");
|
||||
LibraryModules.ReactPortal = BDFDB.ModuleUtils.findByProperties("flushSync", "createPortal");
|
||||
|
||||
Internal.LibraryModules = new Proxy(LibraryModules, {
|
||||
get: function (_, item) {
|
||||
if (LibraryModules[item]) return LibraryModules[item];
|
||||
@@ -4593,8 +4602,12 @@ module.exports = (_ => {
|
||||
});
|
||||
|
||||
const LanguageStringsObj = Internal.LibraryModules.LanguageStore && Internal.LibraryModules.LanguageStore.Messages || Internal.LibraryModules.LanguageStore || {};
|
||||
const EngLanguageStringsObj = Internal.LibraryModules.EngLanguageStore && Internal.LibraryModules.EngLanguageStore.Messages || Internal.LibraryModules.EngLanguageStore || {};
|
||||
const LanguageStringFormatter = Internal.LibraryModules.LanguageIntlUtils && Internal.LibraryModules.LanguageIntlUtils.formatToPlainString;
|
||||
const LanguageStringFormattersObj = BDFDB.ModuleUtils.findByString("use strict", "createLoader:", "de:", {exportsFilter: m => !m.messagesLoader, all: true}).find(n => n && n.Z && LanguageStringFormatter(n.Z[InternalData.LanguageStringHashes.FRIENDS_ONLINE_HEADER], {online: 0})).Z;
|
||||
const LanguageStringFormattersObj = (BDFDB.ModuleUtils.findByString("use strict", "createLoader:", {exportsFilter: m => !m.messagesLoader, all: true}).find(n => n && n.Z && [InternalData.LanguageStringHashes.DISCORD].flat(10).some(hash => LanguageStringFormatter(n.Z[hash]))) || {}).Z || {};
|
||||
|
||||
const LanguageHashes = {};
|
||||
for (let hash of Object.keys(EngLanguageStringsObj)) LanguageHashes[(typeof EngLanguageStringsObj[hash] == "string" ? [EngLanguageStringsObj[hash]] : EngLanguageStringsObj[hash]).map(n => typeof n == "string" ? n : "PLACEHOLDER").join(" ").toUpperCase().replace(/[^a-zA-Z0-9 ]/g, "").split(" ").filter(n => n).join(" ").trim().replace(/ /g, "_")] = hash;
|
||||
|
||||
const LibraryStrings = Object.assign({}, InternalData.LibraryStrings);
|
||||
BDFDB.LanguageUtils = {};
|
||||
@@ -4613,20 +4626,20 @@ module.exports = (_ => {
|
||||
if (language.name.startsWith("Discord")) return language.name.slice(0, -1) + (language.ownlang && (BDFDB.LanguageUtils.languages[language.id] || {}).name != language.ownlang ? ` / ${language.ownlang}` : "") + ")";
|
||||
else return language.name + (language.ownlang && language.name != language.ownlang ? ` / ${language.ownlang}` : "");
|
||||
};
|
||||
BDFDB.LanguageUtils.LanguageStrings = new Proxy(InternalData.LanguageStringHashes, {
|
||||
BDFDB.LanguageUtils.LanguageStrings = new Proxy(LanguageHashes, {
|
||||
get: function (list, item) {
|
||||
let stringObj = LanguageStringsObj[item] || LanguageStringsObj[InternalData.LanguageStringHashes[item]];
|
||||
let stringObj = LanguageStringsObj[item] || LanguageStringsObj[LanguageHashes[item]];
|
||||
if (!stringObj) BDFDB.LogUtils.warn([item, "not found in BDFDB.LanguageUtils.LanguageStrings"]);
|
||||
else {
|
||||
if (stringObj && typeof stringObj == "object" && typeof stringObj.format == "function" || BDFDB.ArrayUtils.is(stringObj)) return BDFDB.LanguageUtils.LanguageStringsFormat(item);
|
||||
else return stringObj;
|
||||
else return (stringObj || "").replace(/[?!:\.]$/, "");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
BDFDB.LanguageUtils.LanguageStringsCheck = new Proxy(InternalData.LanguageStringHashes, {
|
||||
BDFDB.LanguageUtils.LanguageStringsCheck = new Proxy(LanguageHashes, {
|
||||
get: function (list, item) {
|
||||
return !!(LanguageStringsObj[item] || LanguageStringsObj[InternalData.LanguageStringHashes[item]]);
|
||||
return !!(LanguageStringsObj[item] || LanguageStringsObj[LanguageHashes[item]]);
|
||||
}
|
||||
});
|
||||
let parseLanguageStringObj = obj => {
|
||||
@@ -4638,17 +4651,17 @@ module.exports = (_ => {
|
||||
else if (obj.props) string += parseLanguageStringObj(obj.props);
|
||||
}
|
||||
else if (BDFDB.ArrayUtils.is(obj)) for (let ele of obj) string += parseLanguageStringObj(ele);
|
||||
return string;
|
||||
return (string || "").replace(/[?!:\.]$/, "");
|
||||
};
|
||||
BDFDB.LanguageUtils.LanguageStringsFormat = function (item, ...values) {
|
||||
if (item) {
|
||||
let stringObj = LanguageStringsObj[item] || LanguageStringsObj[InternalData.LanguageStringHashes[item]];
|
||||
let stringObj = LanguageStringsObj[item] || LanguageStringsObj[LanguageHashes[item]];
|
||||
if (stringObj && typeof stringObj == "object" && typeof stringObj.format == "function" || BDFDB.ArrayUtils.is(stringObj)) {
|
||||
let i = 0, returnvalue, formatVars = {};
|
||||
let error = "\n";
|
||||
while (!returnvalue && i < 10) {
|
||||
i++;
|
||||
try {returnvalue = BDFDB.ArrayUtils.is(stringObj) ? LanguageStringFormatter(LanguageStringFormattersObj[InternalData.LanguageStringHashes[item]], formatVars) : stringObj.format(formatVars, false);}
|
||||
try {returnvalue = BDFDB.ArrayUtils.is(stringObj) ? LanguageStringFormatter(LanguageStringFormattersObj[LanguageHashes[item]], formatVars) : stringObj.format(formatVars, false);}
|
||||
catch (err) {
|
||||
error += "Error 1 " + err + "\n";
|
||||
returnvalue = null;
|
||||
@@ -4968,7 +4981,7 @@ module.exports = (_ => {
|
||||
onMouseLeave: this.handleMouseLeave.bind(this),
|
||||
children: BDFDB.ReactUtils.createElement("span", {
|
||||
className: BDFDB.disCN.bottagtext,
|
||||
children: this.props.tag || BDFDB.LanguageUtils.LanguageStrings.BOT_TAG_BOT
|
||||
children: this.props.tag || BDFDB.LanguageUtils.LanguageStrings.BOT
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -4982,22 +4995,23 @@ module.exports = (_ => {
|
||||
handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
|
||||
handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
|
||||
render() {
|
||||
let processingAndListening = (this.props.disabled || this.props.submitting) && (null != this.props.onMouseEnter || null != this.props.onMouseLeave);
|
||||
if (!this.state) this.state = {disabled: this.props.disabled};
|
||||
let processingAndListening = (this.state.disabled || this.props.submitting) && (null != this.props.onMouseEnter || null != this.props.onMouseLeave);
|
||||
let props = BDFDB.ObjectUtils.exclude(this.props, "look", "color", "hover", "size", "fullWidth", "grow", "disabled", "submitting", "type", "style", "wrapperClassName", "className", "innerClassName", "onClick", "onContextMenu", "onMouseDown", "onMouseUp", "onMouseEnter", "onMouseLeave", "children", "rel");
|
||||
let button = BDFDB.ReactUtils.createElement("button", Object.assign({}, !this.props.disabled && !this.props.submitting && props, {
|
||||
let button = BDFDB.ReactUtils.createElement("button", Object.assign({}, !this.state.disabled && !this.props.submitting && props, {
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.button, this.props.look != null ? this.props.look : Internal.LibraryComponents.Button.Looks.FILLED, this.props.color != null ? this.props.color : Internal.LibraryComponents.Button.Colors.BRAND, this.props.hover, this.props.size != null ? this.props.size : Internal.LibraryComponents.Button.Sizes.MEDIUM, processingAndListening && this.props.wrapperClassName, this.props.fullWidth && BDFDB.disCN.buttonfullwidth, (this.props.grow === undefined || this.props.grow) && BDFDB.disCN.buttongrow, this.props.submitting && BDFDB.disCN.buttonsubmitting),
|
||||
onClick: (this.props.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleClick.bind(this),
|
||||
onContextMenu: (this.props.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleContextMenu.bind(this),
|
||||
onMouseUp: !this.props.disabled && this.handleMouseDown.bind(this),
|
||||
onMouseDown: !this.props.disabled && this.handleMouseUp.bind(this),
|
||||
onClick: (this.state.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleClick.bind(this),
|
||||
onContextMenu: (this.state.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleContextMenu.bind(this),
|
||||
onMouseUp: !this.state.disabled && this.handleMouseDown.bind(this),
|
||||
onMouseDown: !this.state.disabled && this.handleMouseUp.bind(this),
|
||||
onMouseEnter: this.handleMouseEnter.bind(this),
|
||||
onMouseLeave: this.handleMouseLeave.bind(this),
|
||||
type: !this.props.type ? "button" : this.props.type,
|
||||
disabled: this.props.disabled,
|
||||
disabled: this.state.disabled,
|
||||
style: this.props.style,
|
||||
rel: this.props.rel,
|
||||
children: [
|
||||
this.props.submitting && !this.props.disabled ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SpinnerComponents.Spinner, {
|
||||
this.props.submitting && !this.state.disabled ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SpinnerComponents.Spinner, {
|
||||
type: Internal.LibraryComponents.SpinnerComponents.Types.PULSING_ELLIPSIS,
|
||||
className: BDFDB.disCN.buttonspinner,
|
||||
itemClassName: BDFDB.disCN.buttonspinneritem
|
||||
@@ -5034,6 +5048,10 @@ module.exports = (_ => {
|
||||
!this.props.noRemove ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
|
||||
"aria-label": BDFDB.LanguageUtils.LanguageStrings.REMOVE,
|
||||
className: BDFDB.disCNS.hovercardbutton + BDFDB.disCNS.hovercardremovebutton + BDFDB.disCN.hovercardremovebuttondefault,
|
||||
children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
|
||||
nativeClass: true,
|
||||
name: Internal.LibraryComponents.SvgIcon.Names.REMOVE
|
||||
}),
|
||||
onClick: e => {
|
||||
if (typeof this.props.onRemove == "function") this.props.onRemove(e, this);
|
||||
BDFDB.ListenerUtils.stopEvent(e);
|
||||
@@ -5277,9 +5295,9 @@ module.exports = (_ => {
|
||||
};
|
||||
if (CustomComponents.Checkbox) {
|
||||
CustomComponents.Checkbox.Types = {
|
||||
DEFAULT: "DEFAULT",
|
||||
GHOST: "GHOST",
|
||||
INVERTED: "INVERTED"
|
||||
DEFAULT: "DEFAULT",
|
||||
GHOST: "GHOST",
|
||||
INVERTED: "INVERTED"
|
||||
};
|
||||
CustomComponents.Checkbox.Shapes = {
|
||||
BOX: "box",
|
||||
@@ -6062,11 +6080,11 @@ module.exports = (_ => {
|
||||
.replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"}))
|
||||
.replace(/\$dayS/g, timeObj.toLocaleDateString(language, {weekday: "short"}))
|
||||
.replace(/\$day/g, timeObj.toLocaleDateString(language, {weekday: "long"}))
|
||||
.replace(/\$agoAmount/g, daysAgo < 0 || daysAgo > 1 ? Internal.DiscordObjects.Timestamp(timeObj.getTime()).fromNow() : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`])
|
||||
.replace(/\$agoWeekdayS/g, daysAgo < 0 || daysAgo > 1 ? timeObj.toLocaleDateString(language, {weekday: "short"}) : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`])
|
||||
.replace(/\$agoWeekday/g, daysAgo < 0 || daysAgo > 1 ? timeObj.toLocaleDateString(language, {weekday: "long"}) : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`])
|
||||
.replace(/\$agoDays/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.LanguageUtils.LanguageStringsFormat(`GAME_LIBRARY_LAST_PLAYED_DAYS`, daysAgo) : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`])
|
||||
.replace(/\$agoDate/g, daysAgo < 0 || daysAgo > 1 ? date : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`])
|
||||
.replace(/\$agoAmount/g, daysAgo < 0 || daysAgo > 1 ? Internal.DiscordObjects.Timestamp(timeObj.getTime()).fromNow() : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
|
||||
.replace(/\$agoWeekdayS/g, daysAgo < 0 || daysAgo > 1 ? timeObj.toLocaleDateString(language, {weekday: "short"}) : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
|
||||
.replace(/\$agoWeekday/g, daysAgo < 0 || daysAgo > 1 ? timeObj.toLocaleDateString(language, {weekday: "long"}) : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
|
||||
.replace(/\$agoDays/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.LanguageUtils.LanguageStringsFormat(`LAST_PLAYED_PLACEHOLDER`, daysAgo) : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
|
||||
.replace(/\$agoDate/g, daysAgo < 0 || daysAgo > 1 ? date : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
|
||||
.replace(/\(\)|\[\]/g, "").replace(/,\s*$|^\s*,/g, "").replace(/ +/g, " ").trim();
|
||||
};
|
||||
CustomComponents.DateInput.formatDate = function (data, time) {
|
||||
@@ -6197,7 +6215,7 @@ module.exports = (_ => {
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.pageimagetext,
|
||||
children: this.props.text || BDFDB.LanguageUtils.LanguageStrings.AUTOCOMPLETE_NO_RESULTS_HEADER
|
||||
children: this.props.text || BDFDB.LanguageUtils.LanguageStrings.NO_RESULTS
|
||||
})
|
||||
]
|
||||
});
|
||||
@@ -6286,6 +6304,19 @@ module.exports = (_ => {
|
||||
}
|
||||
};
|
||||
|
||||
CustomComponents.FormTitle = reactInitialized && class BDFDB_FormTitle extends Internal.LibraryModules.React.Component {
|
||||
render() {
|
||||
return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.FormTitle, this.props);
|
||||
}
|
||||
};
|
||||
CustomComponents.FormTitle.Title = CustomComponents.FormTitle;
|
||||
CustomComponents.FormTitle.Tags = new Proxy({}, {
|
||||
get: function (_, item) {
|
||||
let tag = item && item.toLowerCase();
|
||||
return tag.startsWith("h") && tag.length == 2 ? tag : "h5";
|
||||
}
|
||||
});
|
||||
|
||||
CustomComponents.GuildSummaryItem = reactInitialized && class BDFDB_GuildSummaryItem extends Internal.LibraryModules.React.Component {
|
||||
defaultRenderGuild(guild, isLast) {
|
||||
if (!guild) return BDFDB.ReactUtils.createElement("div", {
|
||||
@@ -7203,51 +7234,65 @@ module.exports = (_ => {
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName, BDFDB.disCN.marginreset),
|
||||
tag: this.props.tag,
|
||||
children: this.props.label
|
||||
}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName),
|
||||
mini: this.props.mini,
|
||||
label: this.props.label
|
||||
}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
|
||||
size: Internal.LibraryComponents.TextElement.Sizes.SIZE_16,
|
||||
children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName),
|
||||
mini: this.props.mini,
|
||||
label: this.props.label
|
||||
})
|
||||
})) : null;
|
||||
let margin = this.props.margin != null ? this.props.margin : (this.props.mini ? 0 : 8);
|
||||
return BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrow, BDFDB.disCN.settingsrowcontainer, this.state.disabled && BDFDB.disCN.settingsrowdisabled, margin != null && (InternalData.DiscordClasses[`marginbottom${margin}`] && BDFDB.disCN[`marginbottom${margin}`] || margin == 0 && BDFDB.disCN.marginreset)),
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrowcontainer, margin != null && (InternalData.DiscordClasses[`marginbottom${margin}`] && BDFDB.disCN[`marginbottom${margin}`] || margin == 0 && BDFDB.disCN.marginreset)),
|
||||
id: this.props.id,
|
||||
children: [
|
||||
this.props.dividerTop ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormDivider, {
|
||||
className: this.props.mini ? BDFDB.disCN.marginbottom4 : BDFDB.disCN.marginbottom8
|
||||
}) : null,
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.settingsrowlabel,
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingsrow, this.state.disabled && BDFDB.disCN.settingsrowdisabled),
|
||||
"data-layout": "horizontal",
|
||||
children: [
|
||||
label && !this.props.basis ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
|
||||
grow: 1,
|
||||
shrink: 1,
|
||||
wrap: true,
|
||||
children: label
|
||||
}) : label,
|
||||
this.props.labelChildren,
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.settingsrowlabel,
|
||||
children: [
|
||||
label && !this.props.basis ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
|
||||
grow: 1,
|
||||
shrink: 1,
|
||||
wrap: true,
|
||||
children: label
|
||||
}) : label,
|
||||
typeof this.props.note == "string" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
|
||||
className: BDFDB.disCN.settingsrownote,
|
||||
children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
|
||||
size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
|
||||
children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {
|
||||
speed: 2,
|
||||
children: this.props.note
|
||||
})
|
||||
})
|
||||
}) : null
|
||||
].flat(10).filter(n => n)
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
|
||||
className: BDFDB.disCNS.settingsrowcontrol + BDFDB.disCN.flexchild,
|
||||
grow: 0,
|
||||
shrink: this.props.basis ? 0 : 1,
|
||||
basis: this.props.basis,
|
||||
wrap: true,
|
||||
children: BDFDB.ReactUtils.createElement(childComponent, BDFDB.ObjectUtils.exclude(Object.assign(BDFDB.ObjectUtils.exclude(this.props, "className", "id", "type"), this.props.childProps, {
|
||||
disabled: this.state.disabled,
|
||||
onChange: this.handleChange.bind(this),
|
||||
onValueChange: this.handleChange.bind(this)
|
||||
}), "basis", "margin", "dividerBottom", "dividerTop", "label", "labelClassName", "labelChildren", "tag", "mini", "note", "childProps"))
|
||||
style: {"flex-direction": "row", "align-items": "center"},
|
||||
children: [
|
||||
this.props.labelChildren,
|
||||
BDFDB.ReactUtils.createElement(childComponent, BDFDB.ObjectUtils.exclude(Object.assign(BDFDB.ObjectUtils.exclude(this.props, "className", "id", "type"), this.props.childProps, {
|
||||
disabled: this.state.disabled,
|
||||
onChange: this.handleChange.bind(this),
|
||||
onValueChange: this.handleChange.bind(this)
|
||||
}), "basis", "margin", "dividerBottom", "dividerTop", "label", "labelClassName", "labelChildren", "tag", "mini", "note", "childProps"))
|
||||
].flat(10).filter(n => n)
|
||||
})
|
||||
].flat(10).filter(n => n)
|
||||
]
|
||||
}),
|
||||
typeof this.props.note == "string" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
|
||||
className: BDFDB.disCN.settingsrownote,
|
||||
children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormText.Text, {
|
||||
disabled: this.state.disabled,
|
||||
type: Internal.LibraryComponents.FormText.Types.DESCRIPTION,
|
||||
children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {speed: 2, children: this.props.note})
|
||||
})
|
||||
}) : null,
|
||||
this.props.dividerBottom ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormDivider, {
|
||||
className: this.props.mini ? BDFDB.disCN.margintop4 : BDFDB.disCN.margintop8
|
||||
}) : null
|
||||
@@ -7259,10 +7304,10 @@ module.exports = (_ => {
|
||||
CustomComponents.SettingsLabel = reactInitialized && class BDFDB_SettingsLabel extends Internal.LibraryModules.React.Component {
|
||||
render() {
|
||||
return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrowtitle, this.props.mini && BDFDB.disCN.settingsrowtitlemini, BDFDB.disCN.cursordefault),
|
||||
speed: 2,
|
||||
children: this.props.label
|
||||
});
|
||||
className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrowtitle, this.props.mini && BDFDB.disCN.settingsrowtitlemini, BDFDB.disCN.cursordefault),
|
||||
speed: 2,
|
||||
children: this.props.label
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7354,7 +7399,7 @@ module.exports = (_ => {
|
||||
})).flat(10).filter(n => n)
|
||||
})
|
||||
]
|
||||
}), "title", "data", "settings", "renderLabel", "cardClassName", "cardStyle", "checkboxColor", "getCheckboxColor", "getCheckboxValue", "onCheckboxChange", "configWidth", "biggestWidth", "pagination"));
|
||||
}), "title", "data", "settings", "renderLabel", "cardClassName", "cardStyle", "checkboxColor", "getCheckboxColor", "getCheckboxValue", "onCheckboxChange", "configWidth", "biggestWidth", "pagination"));
|
||||
}
|
||||
render() {
|
||||
this.props.settings = BDFDB.ArrayUtils.is(this.props.settings) ? this.props.settings : [];
|
||||
@@ -7779,7 +7824,7 @@ module.exports = (_ => {
|
||||
}
|
||||
};
|
||||
|
||||
CustomComponents.TextElement = reactInitialized && class BDFDB_TextScroller extends Internal.LibraryModules.React.Component {
|
||||
CustomComponents.TextElement = reactInitialized && class BDFDB_TextElement extends Internal.LibraryModules.React.Component {
|
||||
render() {
|
||||
let color = this.props.color != undefined ? this.props.color && Internal.DiscordConstants.ColorsCSS[this.props.color] : Internal.DiscordConstants.ColorsCSS[CustomComponents.TextElement.Colors.STANDARD];
|
||||
return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Text, {
|
||||
@@ -8234,7 +8279,6 @@ module.exports = (_ => {
|
||||
after: [
|
||||
"DiscordTag",
|
||||
"NameContainerAvatar",
|
||||
"UserHeaderAvatar",
|
||||
"UserPanelHeader",
|
||||
"UserProfileHeader"
|
||||
],
|
||||
@@ -8374,10 +8418,6 @@ module.exports = (_ => {
|
||||
Internal.processSearchBar = function (e) {
|
||||
if (typeof e.instance.props.query != "string") e.instance.props.query = "";
|
||||
};
|
||||
Internal.processUserHeaderAvatar = function (e) {
|
||||
if (!e.instance.props.user) return;
|
||||
e.returnvalue = Internal._processAvatarRender(e.instance.props.user, e.returnvalue) || e.returnvalue;
|
||||
};
|
||||
Internal.processUserPanelHeader = function (e) {
|
||||
if (!e.instance.props.user) return;
|
||||
let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {filter: n => n && n.props && n.props.src && n.props.size});
|
||||
|
||||
@@ -87,10 +87,7 @@ img:not([src]), img[src=""], img[src="null"] {
|
||||
[REPLACE_CLASS_settingsrowcontainer][REPLACE_CLASS_marginbottom40] {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
[REPLACE_CLASS_settingsrowcontainer][REPLACE_CLASS_marginbottom60] {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
[REPLACE_CLASS_settingsrowcontainer] [REPLACE_CLASS_settingsrowlabel] {
|
||||
[REPLACE_CLASS_settingsrowcontainer] [REPLACE_CLASS_settingsrow] {
|
||||
align-items: center;
|
||||
}
|
||||
[REPLACE_CLASS_settingsrowcontainer] [REPLACE_CLASS_settingsrowcontrol] {
|
||||
@@ -101,6 +98,9 @@ img:not([src]), img[src=""], img[src="null"] {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
[REPLACE_CLASS_settingspanel] [REPLACE_CLASS_settingsrowtitle] {
|
||||
color: var(--text-default);
|
||||
}
|
||||
[REPLACE_CLASS_h5][REPLACE_CLASS_marginreset] {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
@@ -158,12 +158,13 @@ img:not([src]), img[src=""], img[src="null"] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
order: 1;
|
||||
}
|
||||
[REPLACE_CLASS_collapsecontainertitle]:hover {
|
||||
color: var(--text-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
[REPLACE_CLASS_collapsecontainertitle]::before {
|
||||
content: "";
|
||||
|
||||
@@ -1,587 +0,0 @@
|
||||
/**
|
||||
* @name BetterFolders
|
||||
* @version 3.6.2
|
||||
* @author Zerthox
|
||||
* @authorLink https://github.com/Zerthox
|
||||
* @description Adds new functionality to server folders. Custom Folder Icons. Close other folders on open.
|
||||
* @website https://github.com/Zerthox/BetterDiscord-Plugins
|
||||
* @source https://github.com/Zerthox/BetterDiscord-Plugins/tree/master/src/BetterFolders
|
||||
**/
|
||||
|
||||
/*@cc_on @if (@_jscript)
|
||||
var pluginName = WScript.ScriptName.split(".")[0];
|
||||
var shell = WScript.CreateObject("WScript.Shell");
|
||||
shell.Popup(
|
||||
"Do NOT run scripts from the internet with the Windows Script Host!\nMove this file to your BetterDiscord plugins folder.",
|
||||
0,
|
||||
pluginName + ": Warning!",
|
||||
0x1030
|
||||
);
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var pluginsPath = shell.expandEnvironmentStrings("%appdata%\\BetterDiscord\\plugins");
|
||||
if (!fso.FolderExists(pluginsPath)) {
|
||||
var popup = shell.Popup(
|
||||
"Unable to find BetterDiscord on your computer.\nOpen the download page of BetterDiscord?",
|
||||
0,
|
||||
pluginName + ": BetterDiscord not found",
|
||||
0x34
|
||||
);
|
||||
if (popup === 6) {
|
||||
shell.Exec("explorer \"https://betterdiscord.app\"");
|
||||
}
|
||||
} else if (WScript.ScriptFullName === pluginsPath + "\\" + WScript.ScriptName) {
|
||||
shell.Popup(
|
||||
"This plugin is already in the correct folder.\nNavigate to the \"Plugins\" settings tab in Discord and enable it there.",
|
||||
0,
|
||||
pluginName,
|
||||
0x40
|
||||
);
|
||||
} else {
|
||||
var popup = shell.Popup(
|
||||
"Open the BetterDiscord plugins folder?",
|
||||
0,
|
||||
pluginName,
|
||||
0x34
|
||||
);
|
||||
if (popup === 6) {
|
||||
shell.Exec("explorer " + pluginsPath);
|
||||
}
|
||||
}
|
||||
WScript.Quit();
|
||||
@else @*/
|
||||
|
||||
'use strict';
|
||||
|
||||
let meta = null;
|
||||
const getMeta = () => {
|
||||
if (meta) {
|
||||
return meta;
|
||||
}
|
||||
else {
|
||||
throw Error("Accessing meta before initialization");
|
||||
}
|
||||
};
|
||||
const setMeta = (newMeta) => {
|
||||
meta = newMeta;
|
||||
};
|
||||
|
||||
const load = (key) => BdApi.Data.load(getMeta().name, key);
|
||||
const save = (key, value) => BdApi.Data.save(getMeta().name, key, value);
|
||||
|
||||
const checkObjectValues = (target) => target !== window && target instanceof Object && target.constructor?.prototype !== target;
|
||||
const byEntry = (filter, every = false) => {
|
||||
return ((target, ...args) => {
|
||||
if (checkObjectValues(target)) {
|
||||
const values = Object.values(target);
|
||||
return values.length > 0 && values[every ? "every" : "some"]((value) => filter(value, ...args));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
const byName$1 = (name) => {
|
||||
return (target) => (target?.displayName ?? target?.constructor?.displayName) === name;
|
||||
};
|
||||
const byKeys$1 = (...keys) => {
|
||||
return (target) => target instanceof Object && keys.every((key) => key in target);
|
||||
};
|
||||
const byProtos = (...protos) => {
|
||||
return (target) => target instanceof Object && target.prototype instanceof Object && protos.every((proto) => proto in target.prototype);
|
||||
};
|
||||
const bySource$1 = (...fragments) => {
|
||||
return (target) => {
|
||||
while (target instanceof Object && "$$typeof" in target) {
|
||||
target = target.render ?? target.type;
|
||||
}
|
||||
if (target instanceof Function) {
|
||||
const source = target.toString();
|
||||
const renderSource = target.prototype?.render?.toString();
|
||||
return fragments.every((fragment) => typeof fragment === "string" ? (source.includes(fragment) || renderSource?.includes(fragment)) : (fragment(source) || renderSource && fragment(renderSource)));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const confirm = (title, content, options = {}) => BdApi.UI.showConfirmationModal(title, content, options);
|
||||
const mappedProxy = (target, mapping) => {
|
||||
const map = new Map(Object.entries(mapping));
|
||||
return new Proxy(target, {
|
||||
get(target, prop) {
|
||||
return target[map.get(prop) ?? prop];
|
||||
},
|
||||
set(target, prop, value) {
|
||||
target[map.get(prop) ?? prop] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, prop) {
|
||||
delete target[map.get(prop) ?? prop];
|
||||
map.delete(prop);
|
||||
return true;
|
||||
},
|
||||
has(target, prop) {
|
||||
return map.has(prop) || prop in target;
|
||||
},
|
||||
ownKeys() {
|
||||
return [...map.keys(), ...Object.keys(target)];
|
||||
},
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
return Object.getOwnPropertyDescriptor(target, map.get(prop) ?? prop);
|
||||
},
|
||||
defineProperty(target, prop, attributes) {
|
||||
Object.defineProperty(target, map.get(prop) ?? prop, attributes);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const find = (filter, { resolve = true, entries = false } = {}) => BdApi.Webpack.getModule(filter, {
|
||||
defaultExport: resolve,
|
||||
searchExports: entries
|
||||
});
|
||||
const byName = (name, options) => find(byName$1(name), options);
|
||||
const byKeys = (keys, options) => find(byKeys$1(...keys), options);
|
||||
const bySource = (contents, options) => find(bySource$1(...contents), options);
|
||||
const resolveKey = (target, filter) => [target, Object.entries(target ?? {}).find(([, value]) => filter(value))?.[0]];
|
||||
const findWithKey = (filter) => resolveKey(find(byEntry(filter)), filter);
|
||||
const demangle = (mapping, required, proxy = false) => {
|
||||
const req = required ?? Object.keys(mapping);
|
||||
const found = find((target) => (checkObjectValues(target)
|
||||
&& req.every((req) => Object.values(target).some((value) => mapping[req](value)))));
|
||||
return proxy ? mappedProxy(found, Object.fromEntries(Object.entries(mapping).map(([key, filter]) => [
|
||||
key,
|
||||
Object.entries(found ?? {}).find(([, value]) => filter(value))?.[0]
|
||||
]))) : Object.fromEntries(Object.entries(mapping).map(([key, filter]) => [
|
||||
key,
|
||||
Object.values(found ?? {}).find((value) => filter(value))
|
||||
]));
|
||||
};
|
||||
let controller = new AbortController();
|
||||
const waitFor = (filter, { resolve = true, entries = false } = {}) => BdApi.Webpack.waitForModule(filter, {
|
||||
signal: controller.signal,
|
||||
defaultExport: resolve,
|
||||
searchExports: entries
|
||||
});
|
||||
const abort = () => {
|
||||
controller.abort();
|
||||
controller = new AbortController();
|
||||
};
|
||||
|
||||
const COLOR = "#3a71c1";
|
||||
const print = (output, ...data) => output(`%c[${getMeta().name}] %c${getMeta().version ? `(v${getMeta().version})` : ""}`, `color: ${COLOR}; font-weight: 700;`, "color: #666; font-size: .8em;", ...data);
|
||||
const log = (...data) => print(console.log, ...data);
|
||||
const warn = (...data) => print(console.warn, ...data);
|
||||
const error = (...data) => print(console.error, ...data);
|
||||
|
||||
const patch = (type, object, method, callback, options) => {
|
||||
const original = object?.[method];
|
||||
if (!(original instanceof Function)) {
|
||||
throw TypeError(`patch target ${original} is not a function`);
|
||||
}
|
||||
const cancel = BdApi.Patcher[type](getMeta().name, object, method, options.once ? (...args) => {
|
||||
const result = callback(cancel, original, ...args);
|
||||
cancel();
|
||||
return result;
|
||||
} : (...args) => callback(cancel, original, ...args));
|
||||
if (!options.silent) {
|
||||
log(`Patched ${options.name ?? String(method)}`);
|
||||
}
|
||||
return cancel;
|
||||
};
|
||||
const instead = (object, method, callback, options = {}) => patch("instead", object, method, (cancel, original, context, args) => callback({ cancel, original, context, args }), options);
|
||||
const after = (object, method, callback, options = {}) => patch("after", object, method, (cancel, original, context, args, result) => callback({ cancel, original, context, args, result }), options);
|
||||
let menuPatches = [];
|
||||
const unpatchAll = () => {
|
||||
if (menuPatches.length + BdApi.Patcher.getPatchesByCaller(getMeta().name).length > 0) {
|
||||
for (const cancel of menuPatches) {
|
||||
cancel();
|
||||
}
|
||||
menuPatches = [];
|
||||
BdApi.Patcher.unpatchAll(getMeta().name);
|
||||
log("Unpatched all");
|
||||
}
|
||||
};
|
||||
|
||||
const inject = (styles) => {
|
||||
if (typeof styles === "string") {
|
||||
BdApi.DOM.addStyle(getMeta().name, styles);
|
||||
}
|
||||
};
|
||||
const clear = () => BdApi.DOM.removeStyle(getMeta().name);
|
||||
|
||||
const ClientActions = /* @__PURE__ */ byKeys(["toggleGuildFolderExpand"]);
|
||||
|
||||
const { useStateFromStores } = /* @__PURE__ */ demangle({
|
||||
default: byKeys$1("Store", "connectStores"),
|
||||
Dispatcher: byProtos("dispatch"),
|
||||
Store: byProtos("emitChange"),
|
||||
BatchedStoreListener: byProtos("attach", "detach"),
|
||||
useStateFromStores: bySource$1("useStateFromStores")
|
||||
}, ["Store", "Dispatcher", "useStateFromStores"]);
|
||||
|
||||
const SortedGuildStore = /* @__PURE__ */ byName("SortedGuildStore");
|
||||
const ExpandedGuildFolderStore = /* @__PURE__ */ byName("ExpandedGuildFolderStore");
|
||||
|
||||
const { React } = BdApi;
|
||||
const classNames = /* @__PURE__ */ find((exports) => exports instanceof Object && exports.default === exports && Object.keys(exports).length === 1);
|
||||
|
||||
const Button = /* @__PURE__ */ byKeys(["Colors", "Link"], { entries: true });
|
||||
|
||||
const Flex = /* @__PURE__ */ byKeys(["Child", "Justify", "Align"], { entries: true });
|
||||
|
||||
const { FormSection, FormItem, FormText,
|
||||
FormDivider, FormSwitch} = /* @__PURE__ */ demangle({
|
||||
FormSection: bySource$1("titleClassName:", ".sectionTitle"),
|
||||
FormItem: bySource$1("titleClassName:", "required:"),
|
||||
FormTitle: bySource$1("faded:", "required:"),
|
||||
FormText: (target) => target.Types?.INPUT_PLACEHOLDER,
|
||||
FormDivider: bySource$1(".divider", "style:"),
|
||||
FormSwitch: bySource$1("tooltipNote:"),
|
||||
FormNotice: bySource$1("imageData:", ".formNotice")
|
||||
}, ["FormSection", "FormItem", "FormDivider"]);
|
||||
|
||||
const margins = /* @__PURE__ */ byKeys(["marginBottom40", "marginTop4"]);
|
||||
|
||||
const RadioGroup = /* @__PURE__ */ bySource(["radioPosition:", "radioItemClassName:", "options:"], { entries: true });
|
||||
|
||||
const ImageInput = /* @__PURE__ */ find((target) => typeof target.defaultProps?.multiple === "boolean" && typeof target.defaultProps?.maxFileSizeBytes === "number");
|
||||
|
||||
const replaceElement = (target, replace) => {
|
||||
target.type = replace.type;
|
||||
target.key = replace.key ?? target.key;
|
||||
target.props = replace.props;
|
||||
};
|
||||
const queryTree = (node, predicate) => {
|
||||
const worklist = [node].flat();
|
||||
while (worklist.length !== 0) {
|
||||
const node = worklist.shift();
|
||||
if (React.isValidElement(node)) {
|
||||
if (predicate(node)) {
|
||||
return node;
|
||||
}
|
||||
const children = node?.props?.children;
|
||||
if (children) {
|
||||
worklist.push(...[children].flat());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const getFiber = (node) => {
|
||||
const key = Object.keys(node).find((key) => key.startsWith("__reactFiber"));
|
||||
return node?.[key];
|
||||
};
|
||||
const queryFiber = (fiber, predicate, direction = "up" , depth = 30) => {
|
||||
if (depth < 0) {
|
||||
return null;
|
||||
}
|
||||
if (predicate(fiber)) {
|
||||
return fiber;
|
||||
}
|
||||
if (direction === "up" || direction === "both" ) {
|
||||
let count = 0;
|
||||
let parent = fiber.return;
|
||||
while (parent && count < depth) {
|
||||
if (predicate(parent)) {
|
||||
return parent;
|
||||
}
|
||||
count++;
|
||||
parent = parent.return;
|
||||
}
|
||||
}
|
||||
if (direction === "down" || direction === "both" ) {
|
||||
let child = fiber.child;
|
||||
while (child) {
|
||||
const result = queryFiber(child, predicate, "down" , depth - 1);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
child = child.sibling;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const findOwner = (fiber, depth = 50) => {
|
||||
return queryFiber(fiber, (node) => node?.stateNode instanceof React.Component, "up" , depth);
|
||||
};
|
||||
const forceFullRerender = (fiber) => new Promise((resolve) => {
|
||||
const owner = findOwner(fiber);
|
||||
if (owner) {
|
||||
const { stateNode } = owner;
|
||||
instead(stateNode, "render", () => null, { once: true, silent: true });
|
||||
stateNode.forceUpdate(() => stateNode.forceUpdate(() => resolve(true)));
|
||||
}
|
||||
else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
|
||||
const SettingsContainer = ({ name, children, onReset }) => (React.createElement(FormSection, null,
|
||||
children,
|
||||
onReset ? (React.createElement(React.Fragment, null,
|
||||
React.createElement(FormDivider, { className: classNames(margins.marginTop20, margins.marginBottom20) }),
|
||||
React.createElement(Flex, { justify: Flex.Justify.END },
|
||||
React.createElement(Button, { size: Button.Sizes.SMALL, onClick: () => confirm(name, "Reset all settings?", {
|
||||
onConfirm: () => onReset()
|
||||
}) }, "Reset")))) : null));
|
||||
|
||||
class SettingsStore {
|
||||
constructor(defaults, onLoad) {
|
||||
this.listeners = new Set();
|
||||
this.update = (settings) => {
|
||||
Object.assign(this.current, typeof settings === "function" ? settings(this.current) : settings);
|
||||
this._dispatch(true);
|
||||
};
|
||||
this.addReactChangeListener = this.addListener;
|
||||
this.removeReactChangeListener = this.removeListener;
|
||||
this.defaults = defaults;
|
||||
this.onLoad = onLoad;
|
||||
}
|
||||
load() {
|
||||
this.current = { ...this.defaults, ...load("settings") };
|
||||
this.onLoad?.();
|
||||
this._dispatch(false);
|
||||
}
|
||||
_dispatch(save$1) {
|
||||
for (const listener of this.listeners) {
|
||||
listener(this.current);
|
||||
}
|
||||
if (save$1) {
|
||||
save("settings", this.current);
|
||||
}
|
||||
}
|
||||
reset() {
|
||||
this.current = { ...this.defaults };
|
||||
this._dispatch(true);
|
||||
}
|
||||
delete(...keys) {
|
||||
for (const key of keys) {
|
||||
delete this.current[key];
|
||||
}
|
||||
this._dispatch(true);
|
||||
}
|
||||
useCurrent() {
|
||||
return useStateFromStores([this], () => this.current, undefined, () => false);
|
||||
}
|
||||
useSelector(selector, deps, compare) {
|
||||
return useStateFromStores([this], () => selector(this.current), deps, compare);
|
||||
}
|
||||
useState() {
|
||||
return useStateFromStores([this], () => [
|
||||
this.current,
|
||||
this.update
|
||||
]);
|
||||
}
|
||||
useStateWithDefaults() {
|
||||
return useStateFromStores([this], () => [
|
||||
this.current,
|
||||
this.defaults,
|
||||
this.update
|
||||
]);
|
||||
}
|
||||
useListener(listener, deps) {
|
||||
React.useEffect(() => {
|
||||
this.addListener(listener);
|
||||
return () => this.removeListener(listener);
|
||||
}, deps ?? [listener]);
|
||||
}
|
||||
addListener(listener) {
|
||||
this.listeners.add(listener);
|
||||
return listener;
|
||||
}
|
||||
removeListener(listener) {
|
||||
this.listeners.delete(listener);
|
||||
}
|
||||
removeAllListeners() {
|
||||
this.listeners.clear();
|
||||
}
|
||||
}
|
||||
const createSettings = (defaults, onLoad) => new SettingsStore(defaults, onLoad);
|
||||
|
||||
const createPlugin = (plugin) => (meta) => {
|
||||
setMeta(meta);
|
||||
const { start, stop, styles, Settings, SettingsPanel } = (plugin instanceof Function ? plugin(meta) : plugin);
|
||||
Settings?.load();
|
||||
return {
|
||||
start() {
|
||||
log("Enabled");
|
||||
inject(styles);
|
||||
start?.();
|
||||
},
|
||||
stop() {
|
||||
abort();
|
||||
unpatchAll();
|
||||
clear();
|
||||
stop?.();
|
||||
log("Disabled");
|
||||
},
|
||||
getSettingsPanel: SettingsPanel ? () => (React.createElement(SettingsContainer, { name: meta.name, onReset: Settings ? () => Settings.reset() : null },
|
||||
React.createElement(SettingsPanel, null))) : null
|
||||
};
|
||||
};
|
||||
|
||||
const Settings = createSettings({
|
||||
closeOnOpen: false,
|
||||
folders: {}
|
||||
});
|
||||
|
||||
const css = ".customIcon-BetterFolders {\n box-sizing: border-box;\n border-radius: var(--radius-lg);\n width: var(--guildbar-folder-size);\n height: var(--guildbar-folder-size);\n padding: var(--custom-folder-preview-padding);\n background-size: contain;\n background-position: center;\n background-repeat: no-repeat;\n}";
|
||||
const styles = {
|
||||
customIcon: "customIcon-BetterFolders"
|
||||
};
|
||||
|
||||
const folderStyles = byKeys(["folderIcon", "folderIconWrapper", "folderPreviewWrapper"]);
|
||||
const renderIcon = (data) => (React.createElement("div", { className: styles.customIcon, style: { backgroundImage: data?.icon ? `url(${data.icon})` : null } }));
|
||||
const BetterFolderIcon = ({ data, childProps, FolderIcon }) => {
|
||||
if (FolderIcon) {
|
||||
const result = FolderIcon(childProps);
|
||||
if (data?.icon) {
|
||||
const replace = renderIcon(data);
|
||||
const iconWrapper = queryTree(result, (node) => node?.props?.className === folderStyles.folderIconWrapper);
|
||||
if (iconWrapper) {
|
||||
replaceElement(iconWrapper, replace);
|
||||
}
|
||||
else {
|
||||
error("Failed to find folderIconWrapper element");
|
||||
}
|
||||
if (data.always) {
|
||||
const previewWrapper = queryTree(result, (node) => node?.props?.className === folderStyles.folderPreviewWrapper);
|
||||
if (previewWrapper) {
|
||||
replaceElement(previewWrapper, replace);
|
||||
}
|
||||
else {
|
||||
error("Failed to find folderPreviewWrapper element");
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const compareFolderData = (a, b) => a?.icon === b?.icon && a?.always === b?.always;
|
||||
const ConnectedBetterFolderIcon = ({ folderId, ...props }) => {
|
||||
const data = Settings.useSelector((current) => current.folders[folderId], [folderId], compareFolderData);
|
||||
return React.createElement(BetterFolderIcon, { data: data, ...props });
|
||||
};
|
||||
|
||||
const BetterFolderUploader = ({ icon, always, onChange }) => (React.createElement(React.Fragment, null,
|
||||
React.createElement(Flex, { align: Flex.Align.CENTER },
|
||||
React.createElement(Button, { color: Button.Colors.WHITE, look: Button.Looks.OUTLINED },
|
||||
"Upload Image",
|
||||
React.createElement(ImageInput, { onChange: (img) => onChange({ icon: img, always }) })),
|
||||
React.createElement(FormText, { type: "description", style: { margin: "0 10px 0 40px" } }, "Preview:"),
|
||||
renderIcon({ icon})),
|
||||
React.createElement(FormSwitch, { hideBorder: true, className: margins.marginTop8, value: always, onChange: (checked) => onChange({ icon, always: checked }) }, "Always display icon")));
|
||||
|
||||
const folderModalPatch = ({ context, result }) => {
|
||||
const { folderId } = context.props;
|
||||
const { state } = context;
|
||||
const form = queryTree(result, (node) => node?.type === "form");
|
||||
if (!form) {
|
||||
warn("Unable to find form");
|
||||
return;
|
||||
}
|
||||
if (!state.iconType) {
|
||||
const { icon = null, always = false } = Settings.current.folders[folderId] ?? {};
|
||||
Object.assign(state, {
|
||||
iconType: icon ? "custom" : "default" ,
|
||||
icon,
|
||||
always
|
||||
});
|
||||
}
|
||||
const { children } = form.props;
|
||||
const { className } = children[0].props;
|
||||
children.push(React.createElement(FormItem, { title: "Icon", className: className },
|
||||
React.createElement(RadioGroup, { value: state.iconType, options: [
|
||||
{ value: "default" , name: "Default Icon" },
|
||||
{ value: "custom" , name: "Custom Icon" }
|
||||
], onChange: ({ value }) => context.setState({ iconType: value }) })));
|
||||
if (state.iconType === "custom" ) {
|
||||
const tree = SortedGuildStore.getGuildsTree();
|
||||
children.push(React.createElement(FormItem, { title: "Custom Icon", className: className },
|
||||
React.createElement(BetterFolderUploader, { icon: state.icon, always: state.always, folderNode: tree.nodes[folderId], onChange: ({ icon, always }) => context.setState({ icon, always }) })));
|
||||
}
|
||||
const button = queryTree(result, (node) => node?.props?.type === "submit");
|
||||
const original = button.props.onClick;
|
||||
button.props.onClick = (...args) => {
|
||||
original(...args);
|
||||
const { folders } = Settings.current;
|
||||
if (state.iconType === "custom" && state.icon) {
|
||||
folders[folderId] = { icon: state.icon, always: state.always };
|
||||
Settings.update({ folders });
|
||||
}
|
||||
else if ((state.iconType === "default" || !state.icon) && folders[folderId]) {
|
||||
delete folders[folderId];
|
||||
Settings.update({ folders });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const guildStyles = byKeys(["guilds", "base"]);
|
||||
const getGuildsOwner = () => findOwner(getFiber(document.getElementsByClassName(guildStyles.guilds)?.[0]));
|
||||
const triggerRerender = async (guildsFiber) => {
|
||||
if (await forceFullRerender(guildsFiber)) {
|
||||
log("Rerendered guilds");
|
||||
}
|
||||
else {
|
||||
warn("Unable to rerender guilds");
|
||||
}
|
||||
};
|
||||
const index = createPlugin({
|
||||
start() {
|
||||
let FolderIcon = null;
|
||||
const guildsOwner = getGuildsOwner();
|
||||
const FolderIconWrapper = findWithKey(bySource$1("folderIconWrapper"));
|
||||
after(...FolderIconWrapper, ({ args: [props], result }) => {
|
||||
const icon = queryTree(result, (node) => node?.props?.folderNode);
|
||||
if (!icon) {
|
||||
return error("Unable to find FolderIcon component");
|
||||
}
|
||||
if (!FolderIcon) {
|
||||
log("Found FolderIcon component");
|
||||
FolderIcon = icon.type;
|
||||
}
|
||||
const replace = React.createElement(ConnectedBetterFolderIcon, { folderId: props.folderNode.id, childProps: icon.props, FolderIcon: FolderIcon });
|
||||
replaceElement(icon, replace);
|
||||
}, { name: "FolderIconWrapper" });
|
||||
triggerRerender(guildsOwner);
|
||||
after(ClientActions, "toggleGuildFolderExpand", ({ original, args: [folderId] }) => {
|
||||
if (Settings.current.closeOnOpen) {
|
||||
for (const id of ExpandedGuildFolderStore.getExpandedFolders()) {
|
||||
if (id !== folderId) {
|
||||
original(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
waitFor(bySource$1(".folderName", ".onClose"), { entries: true }).then((FolderSettingsModal) => {
|
||||
if (FolderSettingsModal) {
|
||||
after(FolderSettingsModal.prototype, "render", folderModalPatch, { name: "GuildFolderSettingsModal" });
|
||||
}
|
||||
});
|
||||
},
|
||||
stop() {
|
||||
triggerRerender(getGuildsOwner());
|
||||
},
|
||||
styles: css,
|
||||
Settings,
|
||||
SettingsPanel: () => {
|
||||
const [{ closeOnOpen }, setSettings] = Settings.useState();
|
||||
return (React.createElement(FormSwitch, { note: "Close other folders when opening a new folder", hideBorder: true, value: closeOnOpen, onChange: (checked) => {
|
||||
if (checked) {
|
||||
for (const id of Array.from(ExpandedGuildFolderStore.getExpandedFolders()).slice(1)) {
|
||||
ClientActions.toggleGuildFolderExpand(id);
|
||||
}
|
||||
}
|
||||
setSettings({ closeOnOpen: checked });
|
||||
} }, "Close on open"));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = index;
|
||||
|
||||
/*@end @*/
|
||||
@@ -1,901 +0,0 @@
|
||||
/**
|
||||
* @name BetterFriendList
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 1.6.3
|
||||
* @description Adds extra Controls to the Friends Page, for example sort by Name/Status, Search and Amount Numbers, new Tabs
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/BetterFriendList/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var rerenderTimeout, sortKey, sortReversed;
|
||||
|
||||
const customSections = {
|
||||
BLOCKED: "BLOCKED",
|
||||
FAVORITES: "FAVORIZED_FRIENDS",
|
||||
HIDDEN: "HIDDEN_FRIENDS",
|
||||
IGNORED: "IGNORED"
|
||||
};
|
||||
const placeHolderId = "PLACEHOLDER_BETTERFRIENDLIST";
|
||||
|
||||
var favorizedFriends = [], hiddenFriends = [];
|
||||
var currentSection = null;
|
||||
|
||||
const statusSortOrder = {
|
||||
online: 0,
|
||||
streaming: 1,
|
||||
idle: 2,
|
||||
dnd: 3,
|
||||
offline: 4,
|
||||
invisible: 5,
|
||||
unknown: 6
|
||||
};
|
||||
|
||||
return class BetterFriendList extends Plugin {
|
||||
onLoad () {
|
||||
this.defaults = {
|
||||
general: {
|
||||
addTotalAmount: {value: true, description: "Adds total Amount for All/Requested/Blocked"},
|
||||
addBlockedCategory: {value: true, description: "Adds Blocked Category"},
|
||||
addIgnoredCategory: {value: true, description: "Adds Ignored Category"},
|
||||
addFavorizedCategory: {value: true, description: "Adds Favorites Category"},
|
||||
addHiddenCategory: {value: true, description: "Adds Hidden Category"},
|
||||
addSortOptions: {value: true, description: "Adds Sort Options"},
|
||||
addMutualGuild: {value: true, description: "Adds mutual Servers in Friend List"}
|
||||
}
|
||||
};
|
||||
|
||||
this.modulePatches = {
|
||||
before: [
|
||||
"AnalyticsContext",
|
||||
"PeopleListSectionedLazy",
|
||||
"PeopleListSectionedNonLazy",
|
||||
"TabBar"
|
||||
],
|
||||
after: [
|
||||
"PeopleListItem",
|
||||
"TabBar"
|
||||
],
|
||||
componentDidMount: [
|
||||
"PeopleListItem"
|
||||
],
|
||||
componentWillUnmount: [
|
||||
"PeopleListItem"
|
||||
]
|
||||
};
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCNS.peoplestabbar + BDFDB.dotCN.peoplesbadge} {
|
||||
background-color: var(--background-accent);
|
||||
margin-left: 6px;
|
||||
}
|
||||
${BDFDB.dotCN._betterfriendlisttitle} {
|
||||
width: 200px;
|
||||
}
|
||||
${BDFDB.dotCN._betterfriendlistnamecell} {
|
||||
width: 200px;
|
||||
}
|
||||
${BDFDB.dotCNS.peoplespeoplecolumn + BDFDB.dotCN.searchbar} {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
${BDFDB.dotCN.peoplesuser} {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
${BDFDB.dotCN.peoplesactions} {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
${BDFDB.dotCN._betterfriendlistmutualguilds} {
|
||||
flex: 0 0 200px;
|
||||
margin-left: 13px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
sortKey = null;
|
||||
sortReversed = false;
|
||||
currentSection = null;
|
||||
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
|
||||
for (let key in this.defaults.general) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["general", key],
|
||||
label: this.defaults.general[key].description,
|
||||
value: this.settings.general[key]
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSettingsClosed () {
|
||||
if (this.SettingsUpdated) {
|
||||
delete this.SettingsUpdated;
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
forceUpdateAll () {
|
||||
favorizedFriends = BDFDB.DataUtils.load(this, "favorizedFriends");
|
||||
favorizedFriends = !BDFDB.ArrayUtils.is(favorizedFriends) ? [] : favorizedFriends;
|
||||
hiddenFriends = BDFDB.DataUtils.load(this, "hiddenFriends");
|
||||
hiddenFriends = !BDFDB.ArrayUtils.is(hiddenFriends) ? [] : hiddenFriends;
|
||||
|
||||
BDFDB.PatchUtils.forceAllUpdates(this);
|
||||
this.rerenderList();
|
||||
}
|
||||
|
||||
onUserContextMenu (e) {
|
||||
if (!e.instance.props.user || !BDFDB.LibraryStores.RelationshipStore.isFriend(e.instance.props.user.id)) return;
|
||||
let favorized = favorizedFriends.indexOf(e.instance.props.user.id) > -1;
|
||||
let hidden = hiddenFriends.indexOf(e.instance.props.user.id) > -1;
|
||||
let [children, index] = BDFDB.ContextMenuUtils.findItem(e.returnvalue, {id: "remove-friend"});
|
||||
if (index > -1) children.splice(index + 1, 0, this.settings.general.addFavorizedCategory && BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: favorized ? this.labels.context_unfavorizefriend : this.labels.context_favorizefriend,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(this.name, favorized ? "unfavorize-friend" : "favorize-friend"),
|
||||
action: _ => {
|
||||
if (favorized) BDFDB.ArrayUtils.remove(favorizedFriends, e.instance.props.user.id, true);
|
||||
else {
|
||||
favorizedFriends.push(e.instance.props.user.id);
|
||||
BDFDB.ArrayUtils.remove(hiddenFriends, e.instance.props.user.id, true);
|
||||
}
|
||||
BDFDB.DataUtils.save(favorizedFriends, this, "favorizedFriends");
|
||||
BDFDB.DataUtils.save(hiddenFriends, this, "hiddenFriends");
|
||||
this.rerenderList();
|
||||
}
|
||||
}), this.settings.general.addHiddenCategory && BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: hidden ? this.labels.context_unhidefriend : this.labels.context_hidefriend,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(this.name, hidden ? "unhide-friend" : "hide-friend"),
|
||||
action: _ => {
|
||||
if (hidden) BDFDB.ArrayUtils.remove(hiddenFriends, e.instance.props.user.id, true);
|
||||
else {
|
||||
BDFDB.ArrayUtils.remove(favorizedFriends, e.instance.props.user.id, true);
|
||||
hiddenFriends.push(e.instance.props.user.id);
|
||||
}
|
||||
BDFDB.DataUtils.save(favorizedFriends, this, "favorizedFriends");
|
||||
BDFDB.DataUtils.save(hiddenFriends, this, "hiddenFriends");
|
||||
this.rerenderList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
processTabBar (e) {
|
||||
if (e.instance.props.children && e.instance.props.children.some(c => c && c.props && c.props.id == BDFDB.DiscordConstants.FriendsSections.ADD_FRIEND)) {
|
||||
let relationships = BDFDB.LibraryStores.RelationshipStore.getMutableRelationships(), relationshipCount = {};
|
||||
for (let type in BDFDB.DiscordConstants.RelationshipTypes) relationshipCount[type] = 0;
|
||||
relationships.forEach((type, id) => {
|
||||
if (!this.settings.general.addHiddenCategory || (hiddenFriends.indexOf(id) == -1 || type != BDFDB.DiscordConstants.RelationshipTypes.FRIEND)) relationshipCount[type]++;
|
||||
});
|
||||
relationshipCount.IGNORED = BDFDB.LibraryStores.RelationshipStore.getIgnoredIDs().length;
|
||||
currentSection = e.instance.props.selectedItem;
|
||||
let hasFriends = relationshipCount[BDFDB.DiscordConstants.RelationshipTypes.FRIEND] > 0;
|
||||
if (!e.returnvalue) {
|
||||
e.instance.props.children = e.instance.props.children.filter(c => c && c.props.id != customSections.FAVORITES && c.props.id != customSections.HIDDEN);
|
||||
if (this.settings.general.addFavorizedCategory && hasFriends) e.instance.props.children.splice(e.instance.props.children.findIndex(c => c && c.props.id == BDFDB.DiscordConstants.FriendsSections.ONLINE) + 1, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TabBar.Item, {
|
||||
id: customSections.FAVORITES,
|
||||
className: BDFDB.disCN.peoplestabbaritem,
|
||||
children: this.labels.favorites
|
||||
}));
|
||||
let index = e.instance.props.children.findIndex(c => c && c.props.id == BDFDB.DiscordConstants.FriendsSections.PENDING);
|
||||
if (index == -1) index = e.instance.props.children.findIndex(c => c && c.props.id == customSections.FAVORITES);
|
||||
if (index == -1) index = e.instance.props.children.findIndex(c => c && c.props.id == BDFDB.DiscordConstants.FriendsSections.ONLINE);
|
||||
if (this.settings.general.addHiddenCategory && hasFriends) e.instance.props.children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TabBar.Item, {
|
||||
id: customSections.HIDDEN,
|
||||
className: BDFDB.disCN.peoplestabbaritem,
|
||||
children: this.labels.hidden
|
||||
}));
|
||||
if (this.settings.general.addIgnoredCategory) e.instance.props.children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TabBar.Item, {
|
||||
id: customSections.IGNORED,
|
||||
className: BDFDB.disCN.peoplestabbaritem,
|
||||
children: this.labels.ignored
|
||||
}));
|
||||
if (this.settings.general.addBlockedCategory) e.instance.props.children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TabBar.Item, {
|
||||
id: customSections.BLOCKED,
|
||||
className: BDFDB.disCN.peoplestabbaritem,
|
||||
children: this.labels.blocked
|
||||
}));
|
||||
}
|
||||
else {
|
||||
if (this.settings.general.addTotalAmount) {
|
||||
for (let child of e.returnvalue.props.children) if (child && child.props.id != BDFDB.DiscordConstants.FriendsSections.ADD_FRIEND) {
|
||||
let newChildren = [child.props.children].flat().filter(n => !n || !n.props || n.props.count == undefined);
|
||||
switch (child.props.id) {
|
||||
case BDFDB.DiscordConstants.FriendsSections.ALL:
|
||||
newChildren.push(this.createBadge(relationshipCount[BDFDB.DiscordConstants.RelationshipTypes.FRIEND]));
|
||||
break;
|
||||
case customSections.FAVORITES:
|
||||
newChildren.push(this.createBadge(favorizedFriends.filter(id => relationships.get(id) == BDFDB.DiscordConstants.RelationshipTypes.FRIEND).length));
|
||||
break;
|
||||
case BDFDB.DiscordConstants.FriendsSections.ONLINE:
|
||||
newChildren.push(this.createBadge(Array.from(relationships).filter(n => n[1] == BDFDB.DiscordConstants.RelationshipTypes.FRIEND && !(this.settings.general.addHiddenCategory && hiddenFriends.indexOf(n[0]) > -1) && BDFDB.LibraryStores.PresenceStore.getStatus(n[0]) != BDFDB.LibraryComponents.StatusComponents.Types.OFFLINE).length));
|
||||
break;
|
||||
case BDFDB.DiscordConstants.FriendsSections.PENDING:
|
||||
newChildren.push(this.createBadge(relationshipCount[BDFDB.DiscordConstants.RelationshipTypes.PENDING_INCOMING], this.labels.incoming, relationshipCount[BDFDB.DiscordConstants.RelationshipTypes.PENDING_INCOMING] > 0));
|
||||
newChildren.push(this.createBadge(relationshipCount[BDFDB.DiscordConstants.RelationshipTypes.PENDING_OUTGOING], this.labels.outgoing));
|
||||
break;
|
||||
case customSections.BLOCKED:
|
||||
newChildren.push(this.createBadge(relationshipCount[BDFDB.DiscordConstants.RelationshipTypes.BLOCKED]));
|
||||
break;
|
||||
case customSections.IGNORED:
|
||||
newChildren.push(this.createBadge(relationshipCount.IGNORED));
|
||||
break;
|
||||
case customSections.HIDDEN:
|
||||
newChildren.push(this.createBadge(hiddenFriends.filter(id => relationships.get(id) == BDFDB.DiscordConstants.RelationshipTypes.FRIEND).length));
|
||||
break;
|
||||
}
|
||||
child.props.children = newChildren;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processAnalyticsContext (e) {
|
||||
if (e.instance.props.section != BDFDB.DiscordConstants.AnalyticsSections.FRIENDS_LIST) return;
|
||||
let body = BDFDB.ReactUtils.findChild(e.instance, {filter: n => n && n.props && n.props.renderRow && n.props.rows});
|
||||
if (!body) return;
|
||||
let users = body.props.rows.flat(10);
|
||||
let filteredUsers = users;
|
||||
if (this.settings.general.addFavorizedCategory && currentSection == customSections.FAVORITES) filteredUsers = filteredUsers.filter(n => n && n.user && favorizedFriends.indexOf(n.user.id) > -1);
|
||||
if (this.settings.general.addHiddenCategory) {
|
||||
if (currentSection == customSections.HIDDEN) filteredUsers = filteredUsers.filter(n => n && n.user && hiddenFriends.indexOf(n.user.id) > -1);
|
||||
else filteredUsers = filteredUsers.filter(n => n && n.user && hiddenFriends.indexOf(n.user.id) == -1);
|
||||
}
|
||||
if (this.settings.general.addBlockedCategory && currentSection == customSections.BLOCKED || this.settings.general.addIgnoredCategory && currentSection == customSections.IGNORED) {
|
||||
filteredUsers = currentSection == customSections.IGNORED ? BDFDB.LibraryStores.RelationshipStore.getIgnoredIDs() : this.getBlockedIDs();
|
||||
for (let className of [BDFDB.disCN.peopleslistsearchbar, BDFDB.disCN.peopleslistempty]) {
|
||||
let [children, index] = BDFDB.ReactUtils.findParent(e.instance, {props: [["className", className]]});
|
||||
if (index > -1) children[index] = null;
|
||||
}
|
||||
body.props.hasSearchQuery = false;
|
||||
}
|
||||
if (this.settings.general.addBlockedCategory || this.settings.general.addIgnoredCategory) {
|
||||
let [children, index] = BDFDB.ReactUtils.findParent(e.instance, {filter: n => n.type && n.type.toLocaleString().indexOf("blockedIgnoredSettingsNotice") > -1});
|
||||
if (index > -1) children[index] = null;
|
||||
}
|
||||
let renderSection = body.props.renderSection;
|
||||
body.props.renderSection = BDFDB.TimeUtils.suppress((...args) => {
|
||||
let returnValue = renderSection(...args);
|
||||
let title = returnValue.props.children.props.title, customTitle = null;
|
||||
if (this.settings.general.addFavorizedCategory && currentSection == customSections.FAVORITES) customTitle = this.labels.favorites;
|
||||
else if (this.settings.general.addHiddenCategory && currentSection == customSections.HIDDEN) customTitle = this.labels.hidden;
|
||||
else if (this.settings.general.addBlockedCategory && currentSection == customSections.BLOCKED) customTitle = this.labels.blocked;
|
||||
else if (this.settings.general.addIgnoredCategory && currentSection == customSections.IGNORED) customTitle = this.labels.ignored;
|
||||
returnValue.props.children.props.title = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN._betterfriendlisttitle,
|
||||
children: customTitle ? `${customTitle} - ${filteredUsers.filter(u => u && u.key != placeHolderId).length}` : title.replace(users.length, filteredUsers.filter(u => u && u.key != placeHolderId).length)
|
||||
}),
|
||||
this.settings.general.addSortOptions && [
|
||||
{key: "nicknameLower", label: BDFDB.LanguageUtils.LanguageStrings.USER_SETTINGS_LABEL_USERNAME},
|
||||
{key: "statusIndex", label: BDFDB.LanguageUtils.LibraryStrings.status}
|
||||
].filter(n => n).map(data => BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tableheadercellwrapper, BDFDB.disCN.tableheadercell, BDFDB.disCN._betterfriendlistnamecell, sortKey == data.key && BDFDB.disCN.tableheadercellsorted, BDFDB.disCN.tableheadercellclickable),
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.tableheadercellcontent,
|
||||
children: [
|
||||
data.label,
|
||||
sortKey == data.key && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
className: BDFDB.disCN.tableheadersorticon,
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names[sortReversed ? "ARROW_UP" : "ARROW_DOWN"]
|
||||
})
|
||||
].filter(n => n)
|
||||
}),
|
||||
onClick: event => {
|
||||
if (sortKey == data.key) {
|
||||
if (!sortReversed) sortReversed = true;
|
||||
else {
|
||||
sortKey = null;
|
||||
sortReversed = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sortKey = data.key;
|
||||
sortReversed = false;
|
||||
}
|
||||
this.rerenderList();
|
||||
}
|
||||
}))
|
||||
].flat(10).filter(n => n)
|
||||
});
|
||||
return returnValue;
|
||||
}, "Error in Section Render of PeopleList!", this);
|
||||
}
|
||||
|
||||
processPeopleListSectionedLazy (e) {
|
||||
this.processPeopleListSectionedNonLazy(e);
|
||||
}
|
||||
|
||||
processPeopleListSectionedNonLazy (e) {
|
||||
if (this.settings.general.addFavorizedCategory && currentSection == customSections.FAVORITES) e.instance.props.rows = [].concat(e.instance.props.rows).map(section => [].concat(section).filter(entry => entry && entry.user && favorizedFriends.indexOf(entry.user.id) > -1));
|
||||
if (this.settings.general.addHiddenCategory) {
|
||||
if (currentSection == customSections.HIDDEN) e.instance.props.rows = [].concat(e.instance.props.rows).map(section => [].concat(section).filter(entry => entry && entry.user && hiddenFriends.indexOf(entry.user.id) > -1));
|
||||
else if (([].concat(e.instance.props.rows).flat(10)[0] || {}).type == BDFDB.DiscordConstants.RelationshipTypes.FRIEND) e.instance.props.rows = [].concat(e.instance.props.rows).map(section => [].concat(section).filter(entry => entry && entry.user && hiddenFriends.indexOf(entry.user.id) == -1));
|
||||
}
|
||||
if (this.settings.general.addBlockedCategory && currentSection == customSections.BLOCKED || this.settings.general.addIgnoredCategory && currentSection == customSections.IGNORED) {
|
||||
let ignoredSection = currentSection == customSections.IGNORED;
|
||||
let userIDs = ignoredSection ? BDFDB.LibraryStores.RelationshipStore.getIgnoredIDs() : this.getBlockedIDs();
|
||||
let RelationshipConstructor = e.instance.props.rows.flat(10)[0] && e.instance.props.rows.flat(10)[0].constructor || class RelationshipConstructor {
|
||||
get comparator() {
|
||||
return [this.type, 1, this.nickname || this.user && this.user.global && this.user.global.toLowerCase() || this.usernameLower]
|
||||
}
|
||||
constructor(e) {
|
||||
for (let prop of Object.keys(e)) this[prop] = e[prop];
|
||||
}
|
||||
};
|
||||
e.instance.props.rows = [userIDs.map(id => {
|
||||
let user = BDFDB.LibraryStores.UserStore.getUser(id);
|
||||
return new RelationshipConstructor({
|
||||
activities: [],
|
||||
applicationId: undefined,
|
||||
applicationStream: null,
|
||||
giftIntentType: undefined,
|
||||
ignoredUser: ignoredSection,
|
||||
isGameRelationship: false,
|
||||
isMobile: false,
|
||||
key: id,
|
||||
mutualGuilds: [],
|
||||
mutualGuildsLength: 0,
|
||||
nickname: undefined,
|
||||
spam: false,
|
||||
status: BDFDB.UserUtils.getStatus(id) || "offline",
|
||||
type: BDFDB.DiscordConstants.RelationshipTypes.BLOCKED,
|
||||
user: user ? user : new BDFDB.DiscordObjects.User({id: id, username: BDFDB.LanguageUtils.LanguageStrings.UNKNOWN_USER}),
|
||||
userId: id,
|
||||
usernameLower: user ? user.username.toLowerCase() : BDFDB.LanguageUtils.LanguageStrings.UNKNOWN_USER
|
||||
});
|
||||
})];
|
||||
}
|
||||
if (sortKey && e.instance.props.rows.flat(10).length) e.instance.props.rows = [].concat(e.instance.props.rows).map(section => {
|
||||
let newSection = [].concat(section);
|
||||
newSection = BDFDB.ArrayUtils.keySort(newSection.map(entry => Object.assign({}, entry, {
|
||||
statusIndex: statusSortOrder[entry.status],
|
||||
nicknameLower: entry.nickname ? entry.nickname.toLowerCase() : entry.usernameLower
|
||||
})), sortKey);
|
||||
if (sortReversed) newSection.reverse();
|
||||
if (!newSection.length) {
|
||||
let placeholder = new BDFDB.DiscordObjects.User({
|
||||
id: placeHolderId,
|
||||
username: placeHolderId
|
||||
});
|
||||
if (placeholder) newSection.push(new BDFDB.DiscordObjects.Relationship({
|
||||
activities: [],
|
||||
applicationStream: null,
|
||||
isMobile: false,
|
||||
key: placeHolderId,
|
||||
mutualGuilds: [],
|
||||
mutualGuildsLength: 0,
|
||||
status: "offline",
|
||||
type: BDFDB.DiscordConstants.RelationshipTypes.NONE,
|
||||
user: placeholder,
|
||||
usernameLower: placeholder.usernameNormalized
|
||||
}));
|
||||
}
|
||||
return newSection;
|
||||
});
|
||||
}
|
||||
|
||||
processPeopleListItem (e) {
|
||||
if (e.node) {
|
||||
BDFDB.TimeUtils.clear(rerenderTimeout);
|
||||
rerenderTimeout = BDFDB.TimeUtils.timeout(_ => BDFDB.PatchUtils.forceAllUpdates(this, "TabBar"), 1000);
|
||||
}
|
||||
else {
|
||||
if (e.instance.props.user.id == placeHolderId) return null;
|
||||
let childrenRender = e.returnvalue.props.children;
|
||||
e.returnvalue.props.children = BDFDB.TimeUtils.suppress((...args) => {
|
||||
let returnValue = childrenRender(...args);
|
||||
if (BDFDB.LibraryStores.RelationshipStore.isBlocked(e.instance.props.user.id) || BDFDB.LibraryStores.RelationshipStore.isIgnored(e.instance.props.user.id)) {
|
||||
let actions = BDFDB.ReactUtils.findChild(returnValue, {props: [["className", BDFDB.disCN.peoplesactions]]});
|
||||
if (actions) actions.props.children.pop();
|
||||
}
|
||||
if (this.settings.general.addMutualGuild) {
|
||||
let mutualGuilds = BDFDB.ArrayUtils.removeCopies([].concat(BDFDB.LibraryStores.GuildMemberStore.memberOf(e.instance.props.user.id), (BDFDB.LibraryStores.UserProfileStore.getMutualGuilds(e.instance.props.user.id) || []).map(n => n && n.guild && n.guild.id)).flat()).filter(n => n);
|
||||
if (mutualGuilds && mutualGuilds.length) {
|
||||
let guildsIds = BDFDB.LibraryStores.SortedGuildStore.getFlattenedGuildIds();
|
||||
let [children, index] = BDFDB.ReactUtils.findParent(returnValue, {filter: n => n && n.props && n.props.subText && n.props.user});
|
||||
if (index > -1) children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.GuildSummaryItem, {
|
||||
className: BDFDB.disCN._betterfriendlistmutualguilds,
|
||||
guilds: mutualGuilds.sort((x, y) => guildsIds.indexOf(x) < guildsIds.indexOf(y) ? -1 : 1).map(BDFDB.LibraryStores.GuildStore.getGuild),
|
||||
showTooltip: true,
|
||||
max: 10
|
||||
}, true));
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}, "Error in PeopleListItem Render!", this);
|
||||
}
|
||||
}
|
||||
|
||||
createBadge (amount, text, red) {
|
||||
let badge = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Badges.NumberBadge, {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.peoplesbadge),
|
||||
count: amount,
|
||||
disableColor: !red
|
||||
});
|
||||
return text ? BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
|
||||
text: text,
|
||||
tooltipConfig: {
|
||||
type: "bottom"
|
||||
},
|
||||
children: badge
|
||||
}) : badge;
|
||||
}
|
||||
|
||||
getBlockedIDs () {
|
||||
return Array.from(BDFDB.LibraryStores.RelationshipStore.getMutableRelationships()).filter(n => n[1] == BDFDB.DiscordConstants.RelationshipTypes.BLOCKED).map(n => n[0]);
|
||||
}
|
||||
|
||||
rerenderList () {
|
||||
let selectedButton = document.querySelector(BDFDB.dotCNS.dmchannel + BDFDB.dotCNS.namecontainerselected + "a");
|
||||
if (selectedButton) selectedButton.click();
|
||||
}
|
||||
|
||||
setLabelsByLanguage () {
|
||||
switch (BDFDB.LanguageUtils.getLanguage().id) {
|
||||
case "bg": // Bulgarian
|
||||
return {
|
||||
blocked: "Блокиран",
|
||||
context_favorizefriend: "Добавете приятел към любими",
|
||||
context_hidefriend: "Скрий приятел",
|
||||
context_unfavorizefriend: "Премахване на приятел от любимите",
|
||||
context_unhidefriend: "Разкрий приятел",
|
||||
favorites: "Любими",
|
||||
hidden: "Скрити",
|
||||
ignored: "Игнориран",
|
||||
incoming: "Входящи",
|
||||
outgoing: "Изходящи"
|
||||
};
|
||||
case "cs": // Czech
|
||||
return {
|
||||
blocked: "Blokované",
|
||||
context_favorizefriend: "Přidat přítele do oblíbených",
|
||||
context_hidefriend: "Skrýt přítele",
|
||||
context_unfavorizefriend: "Odebrat přítele z oblíbených",
|
||||
context_unhidefriend: "Odkrýt přítele",
|
||||
favorites: "Oblíbené",
|
||||
hidden: "Skrytý",
|
||||
ignored: "Ignorováno",
|
||||
incoming: "Přicházející",
|
||||
outgoing: "Odchozí"
|
||||
};
|
||||
case "da": // Danish
|
||||
return {
|
||||
blocked: "Blokeret",
|
||||
context_favorizefriend: "Føj ven til favoritter",
|
||||
context_hidefriend: "Skjul ven",
|
||||
context_unfavorizefriend: "Fjern ven fra favoritter",
|
||||
context_unhidefriend: "Skjul ven",
|
||||
favorites: "Favoritter",
|
||||
hidden: "Skjult",
|
||||
ignored: "Ignoreret",
|
||||
incoming: "Indgående",
|
||||
outgoing: "Udgående"
|
||||
};
|
||||
case "de": // German
|
||||
return {
|
||||
blocked: "Blockiert",
|
||||
context_favorizefriend: "Freund zu Favoriten hinzufügen",
|
||||
context_hidefriend: "Freund ausblenden",
|
||||
context_unfavorizefriend: "Freund aus Favoriten entfernen",
|
||||
context_unhidefriend: "Freund einblenden",
|
||||
favorites: "Favoriten",
|
||||
hidden: "Versteckt",
|
||||
ignored: "Ignoriert",
|
||||
incoming: "Eingehend",
|
||||
outgoing: "Ausgehend"
|
||||
};
|
||||
case "el": // Greek
|
||||
return {
|
||||
blocked: "Μπλοκαρισμένος",
|
||||
context_favorizefriend: "Προσθήκη φίλου στους αγαπημένους",
|
||||
context_hidefriend: "Απόκρυψη φίλου",
|
||||
context_unfavorizefriend: "Κατάργηση φίλου από τούς αγαπημένους",
|
||||
context_unhidefriend: "Επανεμφάνιση φίλου",
|
||||
favorites: "Αγαπημένοι",
|
||||
hidden: "Σε απόκρυψη",
|
||||
ignored: "Αγνοημένος",
|
||||
incoming: "Εισερχόμενος",
|
||||
outgoing: "Εξερχόμενος"
|
||||
};
|
||||
case "es": // Spanish
|
||||
return {
|
||||
blocked: "Obstruido",
|
||||
context_favorizefriend: "Agregar amigo a favoritos",
|
||||
context_hidefriend: "Ocultar amigo",
|
||||
context_unfavorizefriend: "Quitar amigo de favoritos",
|
||||
context_unhidefriend: "Mostrar amigo",
|
||||
favorites: "Favoritos",
|
||||
hidden: "Oculto",
|
||||
ignored: "Ignorado",
|
||||
incoming: "Entrante",
|
||||
outgoing: "Saliente"
|
||||
};
|
||||
case "es-419": // Spanish (Latin America)
|
||||
return {
|
||||
blocked: "Obstruido",
|
||||
context_favorizefriend: "Agregar amigo a los favoritos",
|
||||
context_hidefriend: "Esconder a amigo",
|
||||
context_unfavorizefriend: "Eliminar amigo de los favoritos",
|
||||
context_unhidefriend: "Amigo dehide",
|
||||
favorites: "Favoritos",
|
||||
hidden: "Oculto",
|
||||
ignored: "Ignorado",
|
||||
incoming: "Entrante",
|
||||
outgoing: "Extrovertido"
|
||||
};
|
||||
case "fi": // Finnish
|
||||
return {
|
||||
blocked: "Estetty",
|
||||
context_favorizefriend: "Lisää ystävä suosikkeihin",
|
||||
context_hidefriend: "Piilota ystävä",
|
||||
context_unfavorizefriend: "Poista ystävä suosikeista",
|
||||
context_unhidefriend: "Näytä ystävä",
|
||||
favorites: "Suosikit",
|
||||
hidden: "Piilotettu",
|
||||
ignored: "Sivuutettu",
|
||||
incoming: "Saapuva",
|
||||
outgoing: "Lähtevä"
|
||||
};
|
||||
case "fr": // French
|
||||
return {
|
||||
blocked: "Bloqué",
|
||||
context_favorizefriend: "Ajouter un ami aux favoris",
|
||||
context_hidefriend: "Masquer l'ami",
|
||||
context_unfavorizefriend: "Supprimer un ami des favoris",
|
||||
context_unhidefriend: "Afficher l'ami",
|
||||
favorites: "Favoris",
|
||||
hidden: "Caché",
|
||||
ignored: "Ignoré",
|
||||
incoming: "Entrant",
|
||||
outgoing: "Sortant"
|
||||
};
|
||||
case "hi": // Hindi
|
||||
return {
|
||||
blocked: "अवरोधित",
|
||||
context_favorizefriend: "मित्र को पसंदीदा में जोड़ें",
|
||||
context_hidefriend: "दोस्त छुपाएं",
|
||||
context_unfavorizefriend: "मित्र को पसंदीदा से हटाएं",
|
||||
context_unhidefriend: "मित्र दिखाएँ",
|
||||
favorites: "पसंदीदा",
|
||||
hidden: "छिपा हुआ",
|
||||
ignored: "अवहेलना करना",
|
||||
incoming: "आने वाली",
|
||||
outgoing: "निवर्तमान"
|
||||
};
|
||||
case "hr": // Croatian
|
||||
return {
|
||||
blocked: "Blokiran",
|
||||
context_favorizefriend: "Dodaj prijatelja u favorite",
|
||||
context_hidefriend: "Sakrij prijatelja",
|
||||
context_unfavorizefriend: "Ukloni prijatelja iz omiljenih",
|
||||
context_unhidefriend: "Otkrij prijatelja",
|
||||
favorites: "Favoriti",
|
||||
hidden: "Skriven",
|
||||
ignored: "Zanemaren",
|
||||
incoming: "Dolazni",
|
||||
outgoing: "Odlazni"
|
||||
};
|
||||
case "hu": // Hungarian
|
||||
return {
|
||||
blocked: "Zárolt",
|
||||
context_favorizefriend: "Ismerős hozzáadása a kedvencekhez",
|
||||
context_hidefriend: "Barát elrejtése",
|
||||
context_unfavorizefriend: "Ismerős eltávolítása a kedvencekből",
|
||||
context_unhidefriend: "Barát megjelenítése",
|
||||
favorites: "Kedvencek",
|
||||
hidden: "Rejtett",
|
||||
ignored: "Figyelmen kívül hagyott",
|
||||
incoming: "Beérkező",
|
||||
outgoing: "Kimenő"
|
||||
};
|
||||
case "it": // Italian
|
||||
return {
|
||||
blocked: "Bloccato",
|
||||
context_favorizefriend: "Aggiungi amico ai preferiti",
|
||||
context_hidefriend: "Nascondi amico",
|
||||
context_unfavorizefriend: "Rimuovi amico dai preferiti",
|
||||
context_unhidefriend: "Scopri amico",
|
||||
favorites: "Preferiti",
|
||||
hidden: "Nascosto",
|
||||
ignored: "Ignorato",
|
||||
incoming: "In arrivo",
|
||||
outgoing: "Estroverso"
|
||||
};
|
||||
case "ja": // Japanese
|
||||
return {
|
||||
blocked: "ブロックされています",
|
||||
context_favorizefriend: "お気に入りに友達を追加する",
|
||||
context_hidefriend: "友達を隠す",
|
||||
context_unfavorizefriend: "お気に入りから友達を削除する",
|
||||
context_unhidefriend: "友達を再表示",
|
||||
favorites: "お気に入り",
|
||||
hidden: "隠し",
|
||||
ignored: "無視した",
|
||||
incoming: "着信",
|
||||
outgoing: "発信"
|
||||
};
|
||||
case "ko": // Korean
|
||||
return {
|
||||
blocked: "막힌",
|
||||
context_favorizefriend: "즐겨찾기에 친구 추가",
|
||||
context_hidefriend: "친구 숨기기",
|
||||
context_unfavorizefriend: "즐겨찾기에서 친구 제거",
|
||||
context_unhidefriend: "친구 숨기기 해제",
|
||||
favorites: "즐겨찾기",
|
||||
hidden: "숨겨진",
|
||||
ignored: "무시했습니다",
|
||||
incoming: "들어오는",
|
||||
outgoing: "나가는"
|
||||
};
|
||||
case "lt": // Lithuanian
|
||||
return {
|
||||
blocked: "Užblokuotas",
|
||||
context_favorizefriend: "Pridėti draugą prie mėgstamiausių",
|
||||
context_hidefriend: "Slėpti draugą",
|
||||
context_unfavorizefriend: "Pašalinti draugą iš mėgstamiausių",
|
||||
context_unhidefriend: "Nerodyti draugo",
|
||||
favorites: "Mėgstamiausi",
|
||||
hidden: "Paslėpta",
|
||||
ignored: "Ignoruojamas",
|
||||
incoming: "Gaunamasis",
|
||||
outgoing: "Išeinantis"
|
||||
};
|
||||
case "nl": // Dutch
|
||||
return {
|
||||
blocked: "Geblokkeerd",
|
||||
context_favorizefriend: "Vriend toevoegen aan favorieten",
|
||||
context_hidefriend: "Vriend verbergen",
|
||||
context_unfavorizefriend: "Vriend uit favorieten verwijderen",
|
||||
context_unhidefriend: "Vriend zichtbaar maken",
|
||||
favorites: "Favorieten",
|
||||
hidden: "Verborgen",
|
||||
ignored: "Genegeerd",
|
||||
incoming: "Inkomend",
|
||||
outgoing: "Uitgaand"
|
||||
};
|
||||
case "no": // Norwegian
|
||||
return {
|
||||
blocked: "Blokkert",
|
||||
context_favorizefriend: "Legg til en venn i favoritter",
|
||||
context_hidefriend: "Skjul venn",
|
||||
context_unfavorizefriend: "Fjern venn fra favoritter",
|
||||
context_unhidefriend: "Skjul venn",
|
||||
favorites: "Favoritter",
|
||||
hidden: "Skjult",
|
||||
ignored: "Ignorert",
|
||||
incoming: "Innkommende",
|
||||
outgoing: "Utgående"
|
||||
};
|
||||
case "pl": // Polish
|
||||
return {
|
||||
blocked: "Zablokowany",
|
||||
context_favorizefriend: "Dodaj znajomego do ulubionych",
|
||||
context_hidefriend: "Ukryj znajomego",
|
||||
context_unfavorizefriend: "Usuń znajomego z ulubionych",
|
||||
context_unhidefriend: "Pokaż znajomego",
|
||||
favorites: "Ulubione",
|
||||
hidden: "Ukryci",
|
||||
ignored: "Ignorowane",
|
||||
incoming: "Przychodzące",
|
||||
outgoing: "Wychodzące"
|
||||
};
|
||||
case "pt-BR": // Portuguese (Brazil)
|
||||
return {
|
||||
blocked: "Bloqueado",
|
||||
context_favorizefriend: "Adicionar amigo aos favoritos",
|
||||
context_hidefriend: "Esconder Amigo",
|
||||
context_unfavorizefriend: "Remover amigo dos favoritos",
|
||||
context_unhidefriend: "Reexibir amigo",
|
||||
favorites: "Favoritos",
|
||||
hidden: "Escondido",
|
||||
ignored: "Ignorado",
|
||||
incoming: "Entrada",
|
||||
outgoing: "Extrovertido"
|
||||
};
|
||||
case "ro": // Romanian
|
||||
return {
|
||||
blocked: "Blocat",
|
||||
context_favorizefriend: "Adaugă prieten la favorite",
|
||||
context_hidefriend: "Ascunde prietenul",
|
||||
context_unfavorizefriend: "Scoateți prietenul din favorite",
|
||||
context_unhidefriend: "Afișează prietenul",
|
||||
favorites: "Favorite",
|
||||
hidden: "Ascuns",
|
||||
ignored: "Ignorat",
|
||||
incoming: "Primite",
|
||||
outgoing: "De ieșire"
|
||||
};
|
||||
case "ru": // Russian
|
||||
return {
|
||||
blocked: "Заблокированный",
|
||||
context_favorizefriend: "Добавить друга в избранное",
|
||||
context_hidefriend: "Скрыть друга",
|
||||
context_unfavorizefriend: "Удалить друга из избранного",
|
||||
context_unhidefriend: "Показать друга",
|
||||
favorites: "Избранное",
|
||||
hidden: "Скрытый",
|
||||
ignored: "Игнорируется",
|
||||
incoming: "Входящий",
|
||||
outgoing: "Исходящий"
|
||||
};
|
||||
case "sv": // Swedish
|
||||
return {
|
||||
blocked: "Blockerad",
|
||||
context_favorizefriend: "Lägg till vän till favoriter",
|
||||
context_hidefriend: "Dölj vän",
|
||||
context_unfavorizefriend: "Ta bort vän från favoriter",
|
||||
context_unhidefriend: "Göm din vän",
|
||||
favorites: "Favoriter",
|
||||
hidden: "Dold",
|
||||
ignored: "Ignorerad",
|
||||
incoming: "Inkommande",
|
||||
outgoing: "Utgående"
|
||||
};
|
||||
case "th": // Thai
|
||||
return {
|
||||
blocked: "ที่ถูกปิดกั้น",
|
||||
context_favorizefriend: "เพิ่มเพื่อนในรายการโปรด",
|
||||
context_hidefriend: "ซ่อนเพื่อน",
|
||||
context_unfavorizefriend: "ลบเพื่อนออกจากรายการโปรด",
|
||||
context_unhidefriend: "เลิกซ่อนเพื่อน",
|
||||
favorites: "รายการโปรด",
|
||||
hidden: "ซ่อนเร้น",
|
||||
ignored: "เพิกเฉย",
|
||||
incoming: "ขาเข้า",
|
||||
outgoing: "ขาออก"
|
||||
};
|
||||
case "tr": // Turkish
|
||||
return {
|
||||
blocked: "Engellenmiş",
|
||||
context_favorizefriend: "Favorilere arkadaş ekle",
|
||||
context_hidefriend: "Arkadaşı Gizle",
|
||||
context_unfavorizefriend: "Arkadaşını favorilerden kaldır",
|
||||
context_unhidefriend: "Arkadaşı Göster",
|
||||
favorites: "Favoriler",
|
||||
hidden: "Gizli",
|
||||
ignored: "Göz ardı edilen",
|
||||
incoming: "Gelen",
|
||||
outgoing: "Dışa dönük"
|
||||
};
|
||||
case "uk": // Ukrainian
|
||||
return {
|
||||
blocked: "Заблокований",
|
||||
context_favorizefriend: "Додати друга у вибране",
|
||||
context_hidefriend: "Сховати друга",
|
||||
context_unfavorizefriend: "Видалити друга з вибраного",
|
||||
context_unhidefriend: "Показати друга",
|
||||
favorites: "Вибране",
|
||||
hidden: "Прихований",
|
||||
ignored: "Ігнорований",
|
||||
incoming: "Вхідні",
|
||||
outgoing: "Вихідний"
|
||||
};
|
||||
case "vi": // Vietnamese
|
||||
return {
|
||||
blocked: "Bị chặn",
|
||||
context_favorizefriend: "Thêm bạn bè vào danh sách yêu thích",
|
||||
context_hidefriend: "Ẩn bạn bè",
|
||||
context_unfavorizefriend: "Xóa bạn bè khỏi danh sách yêu thích",
|
||||
context_unhidefriend: "Bỏ ẩn bạn bè",
|
||||
favorites: "Yêu thích",
|
||||
hidden: "Ẩn",
|
||||
ignored: "Bỏ qua",
|
||||
incoming: "Mới đến",
|
||||
outgoing: "Hướng ngoaị"
|
||||
};
|
||||
case "zh-CN": // Chinese (China)
|
||||
return {
|
||||
blocked: "阻止",
|
||||
context_favorizefriend: "添加好友到收藏夹",
|
||||
context_hidefriend: "隐藏好友",
|
||||
context_unfavorizefriend: "从收藏夹中移除好友",
|
||||
context_unhidefriend: "取消隐藏好友",
|
||||
favorites: "收藏夹",
|
||||
hidden: "隐藏",
|
||||
ignored: "被忽略",
|
||||
incoming: "导入",
|
||||
outgoing: "导出"
|
||||
};
|
||||
case "zh-TW": // Chinese (Taiwan)
|
||||
return {
|
||||
blocked: "阻止",
|
||||
context_favorizefriend: "新增好友到我的最愛",
|
||||
context_hidefriend: "隱藏好友",
|
||||
context_unfavorizefriend: "從我的最愛中移除好友",
|
||||
context_unhidefriend: "取消隱藏好友",
|
||||
favorites: "我的最愛",
|
||||
hidden: "隱藏",
|
||||
ignored: "被忽略",
|
||||
incoming: "匯入",
|
||||
outgoing: "匯出"
|
||||
};
|
||||
default: // English
|
||||
return {
|
||||
blocked: "Blocked",
|
||||
context_favorizefriend: "Add Friend to Favorites",
|
||||
context_hidefriend: "Hide Friend",
|
||||
context_unfavorizefriend: "Remove Friend from Favorites",
|
||||
context_unhidefriend: "Unhide Friend",
|
||||
favorites: "Favorites",
|
||||
hidden: "Hidden",
|
||||
ignored: "Ignored",
|
||||
incoming: "Incoming",
|
||||
outgoing: "Outgoing"
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,365 +0,0 @@
|
||||
/**
|
||||
* @name Hide Channels
|
||||
* @author Farcrada
|
||||
* @version 2.2.13
|
||||
* @description Hide channel list from view.
|
||||
*
|
||||
* @invite qH6UWCwfTu
|
||||
* @website https://github.com/Farcrada/DiscordPlugins
|
||||
* @source https://github.com/Farcrada/DiscordPlugins/edit/master/Hide-Channels/HideChannels.plugin.js
|
||||
* @updateUrl https://raw.githubusercontent.com/Farcrada/DiscordPlugins/master/Hide-Channels/HideChannels.plugin.js
|
||||
*/
|
||||
|
||||
/** @type {typeof import("react")} */
|
||||
const React = BdApi.React;
|
||||
|
||||
const { Webpack, Webpack: { Filters }, Data, DOM, Patcher } = BdApi,
|
||||
|
||||
config = {
|
||||
constants: {
|
||||
//The names we need for CSS
|
||||
cssStyle: "HideChannelsStyle",
|
||||
hideElementsName: "hideChannelElement",
|
||||
buttonID: "toggleChannels",
|
||||
buttonHidden: "channelsHidden",
|
||||
buttonVisible: "channelsVisible",
|
||||
avatarOverlap: "avatarOverlap",
|
||||
panelsButtonHidden: "panelsButtonHidden"
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = class HideChannels {
|
||||
constructor(meta) { config.info = meta; }
|
||||
|
||||
start() {
|
||||
try {
|
||||
console.log(config)
|
||||
//React components for settings
|
||||
this.WindowInfoStore = Webpack.getModule(Filters.byKeys("isFocused", "isElementFullScreen"));
|
||||
|
||||
this.KeybindToCombo = Webpack.getModule(Filters.byStrings("numpad plus"), { searchExports: true });
|
||||
this.KeybindToString = Webpack.getModule(Filters.byStrings(".join(\"+\")"), { searchExports: true });
|
||||
|
||||
this.FormSwitch = Webpack.getModule(Filters.byStrings('labelRow', 'checked'), { searchExports: true });
|
||||
this.FormItem = Webpack.getModule(m => Filters.byStrings('titleId', 'errorId', 'setIsFocused')(m?.render), { searchExports: true });
|
||||
|
||||
//The sidebar to "minimize"/hide
|
||||
this.sidebarClass = Webpack.getModule(Filters.byKeys("container", "base")).sidebarList;
|
||||
this.headerBarClass = Webpack.getModule(Filters.byKeys("chat", "title")).title;
|
||||
this.baseClass = Webpack.getModule(Filters.byKeys("container", "base")).base;
|
||||
this.avatarWrapper = Webpack.getModule(Filters.byKeys("avatarWrapper")).avatarWrapper;
|
||||
this.panelsButton = Webpack.getModule(Filters.byKeys("avatarWrapper")).buttons;
|
||||
|
||||
//And the keybind
|
||||
this.animation = Data.load(config.info.slug, "animation") ?? true;
|
||||
this.keybindSetting = this.checkKeybindLoad(Data.load(config.info.slug, "keybind"));
|
||||
this.keybind = this.keybindSetting.split('+');
|
||||
|
||||
//Predefine for the eventlistener
|
||||
this.currentlyPressed = {};
|
||||
|
||||
this.generateCSS();
|
||||
|
||||
//Render the button and we're off to the races!
|
||||
const filter = f => f?.Icon && f.Title,
|
||||
modules = Webpack.getModule(m => Object.values(m).some(filter), { first: false });
|
||||
for (const module of modules) {
|
||||
const HeaderBar = [module, Object.keys(module).find(k => filter(module[k]))];
|
||||
this.patchTitleBar(HeaderBar);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
try {
|
||||
console.error("Attempting to stop after starting error...", err)
|
||||
this.stop();
|
||||
}
|
||||
catch (err) {
|
||||
console.error(config.info.name + ".stop()", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSettingsPanel() {
|
||||
//Settings window is lazy loaded so we need to cache this after it's been loaded (i.e. open settings).
|
||||
//This also allows for a (delayed) call to retrieve a way to prompt a Form
|
||||
if (!this.KeybindRecorder)
|
||||
this.KeybindRecorder = Webpack.getModule(m => m.prototype?.cleanUp);
|
||||
|
||||
//Return our keybind settings wrapped in a form item
|
||||
return () => {
|
||||
const [animation, setanimation] = React.useState(this.animation);
|
||||
|
||||
return [
|
||||
React.createElement(this.FormSwitch, {
|
||||
value: animation,
|
||||
note: "Enable the hide animation. Useful if the animation is \"unstatisfactory\".",
|
||||
onChange: (newState) => {
|
||||
//Save new state
|
||||
this.animation = newState;
|
||||
Data.save(config.info.slug, "animation", newState);
|
||||
setanimation(newState);
|
||||
|
||||
//Update CSS to reflect new settings.
|
||||
this.generateCSS()
|
||||
}
|
||||
}, "Enable Hide Animation"),
|
||||
React.createElement(this.FormItem, {
|
||||
//tag: "h5",
|
||||
title: "Toggle by keybind:"
|
||||
},
|
||||
//Containing a keybind recorder.
|
||||
React.createElement(this.KeybindRecorder, {
|
||||
//The `keyup` and `keydown` events register the Ctrl key different
|
||||
//We need to accomodate for that
|
||||
defaultValue: this.KeybindToCombo(this.keybindSetting.replace("control", "ctrl")),
|
||||
onChange: (e) => {
|
||||
//Convert the keybind to current locale
|
||||
//Once again accomodate for event differences
|
||||
const keybindString = this.KeybindToString(e).toLowerCase().replace("ctrl", "control");
|
||||
|
||||
//Set the keybind and save it.
|
||||
Data.save(config.info.slug, "keybind", keybindString);
|
||||
//And the keybindSetting
|
||||
this.keybindSetting = keybindString;
|
||||
this.keybind = keybindString.split('+');
|
||||
}
|
||||
}))];
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
Patcher.unpatchAll(config.info.slug);
|
||||
|
||||
//Our CSS
|
||||
DOM.removeStyle(config.constants.cssStyle);
|
||||
|
||||
//And if there are remnants of css left,
|
||||
//make sure we remove the class from the sidebar to ensure visual confirmation.
|
||||
let sidebar = document.querySelector(`.${this.sidebarClass}`);
|
||||
if (sidebar?.classList.contains(config.constants.hideElementsName))
|
||||
sidebar.classList.remove(config.constants.hideElementsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object[]} headerBar The module and the export's name (as a string) that contains it
|
||||
*/
|
||||
patchTitleBar(headerBar) {
|
||||
Patcher.before(config.info.slug, ...headerBar, (thisObject, methodArguments, returnValue) => {
|
||||
//When elements are being re-rendered we need to check if there actually is a place for us.
|
||||
//Along with that we need to check if what we're adding to is an array.
|
||||
if (Array.isArray(methodArguments[0]?.children))
|
||||
if (methodArguments[0].children.some?.(child =>
|
||||
//Make sure we're on the "original" headerbar and not that of a Voice channel's chat, or thread.
|
||||
child?.props?.channel ||
|
||||
//Group chat
|
||||
child?.props?.children?.some?.(child => child?.props?.channel !== undefined) ||
|
||||
//The friends page
|
||||
child?.type?.Header ||
|
||||
//The Nitro page
|
||||
child?.props?.children === "Nitro" ||
|
||||
//The Shop page
|
||||
child?.props?.children?.some?.(child => child?.props?.children === "Shop") ||
|
||||
//Home page of certain servers. This is gonna be broken next update, calling it.
|
||||
child?.props?.children?.some?.(grandChild => typeof grandChild === 'string')))
|
||||
|
||||
//Make sure our component isn't already present.
|
||||
if (!methodArguments[0].children.some?.(child => child?.key === config.info.slug))
|
||||
//And since we want to be on the most left of the header bar for style we unshift into the array.
|
||||
methodArguments[0].children.unshift?.(React.createElement(this.hideChannelComponent, { key: config.info.slug }));
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* React component for our button.
|
||||
* @returns React element
|
||||
*/
|
||||
hideChannelComponent = () => {
|
||||
//Only fetch the sidebar on a rerender.
|
||||
const sidebarNode = document.querySelector(`.${this.sidebarClass}`),
|
||||
//When a state updates, it rerenders.
|
||||
[hidden, setHidden] = React.useState(
|
||||
//Check on a rerender where our side bar is so we can correctly reflect this.
|
||||
sidebarNode?.classList.contains(config.constants.hideElementsName));
|
||||
//Avatar wrapper element
|
||||
const sidebarAvatar = document.querySelector(`.${this.avatarWrapper}`);
|
||||
const panelsButton = document.querySelector(`.${this.panelsButton}`);
|
||||
|
||||
/**
|
||||
* Use this to make a despensable easy to use listener with React.
|
||||
* @param {string} eventName The name of the event to listen for.
|
||||
* @param {callback} callback Function to call when said event is triggered.
|
||||
* @param {boolean} bubbling Handle bubbling or not
|
||||
* @param {object} [target] The object to attach our listener to.
|
||||
*/
|
||||
function useListener(eventName, callback, bubbling, target = window) {
|
||||
React.useEffect(() => {
|
||||
//ComponentDidMount
|
||||
target.addEventListener(eventName, callback, bubbling);
|
||||
//ComponentWillUnmount
|
||||
return () => target.removeEventListener(eventName, callback, bubbling);
|
||||
});
|
||||
}
|
||||
|
||||
function useWindowChangeListener(windowStore, callback) {
|
||||
React.useEffect(() => {
|
||||
windowStore.addChangeListener(callback);
|
||||
return () => windowStore.removeChangeListener(callback);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} sidebar Sidebar node we want to toggle.
|
||||
* @returns The passed state in reverse.
|
||||
*/
|
||||
function toggleSidebar(sidebar) {
|
||||
/**
|
||||
* Adds and removes our CSS to make our sidebar appear and disappear.
|
||||
* @param {boolean} state State that determines the toggle.
|
||||
* @returns The passed state in reverse.
|
||||
*/
|
||||
return state => {
|
||||
//If it is showing, we need to hide it.
|
||||
if (!state) {
|
||||
//We hide it through CSS by adding a class.
|
||||
sidebar?.classList.add(config.constants.hideElementsName);
|
||||
sidebarAvatar?.classList.add(config.constants.avatarOverlap);
|
||||
panelsButton?.classList.add(config.constants.panelsButtonHidden);
|
||||
} else {
|
||||
//If it is hidden, we need to show it.
|
||||
sidebar?.classList.remove(config.constants.hideElementsName);
|
||||
sidebarAvatar?.classList.remove(config.constants.avatarOverlap);
|
||||
panelsButton?.classList.remove(config.constants.panelsButtonHidden);
|
||||
}
|
||||
return !state;
|
||||
};
|
||||
}
|
||||
|
||||
//Keydown event
|
||||
useListener("keydown", e => {
|
||||
//Since we made this an object,
|
||||
//we can make new properties with `[]`
|
||||
if (e?.key?.toLowerCase)
|
||||
this.currentlyPressed[e.key.toLowerCase()] = true;
|
||||
|
||||
//Account for bubbling
|
||||
}, true);
|
||||
|
||||
//Keyup event
|
||||
useListener("keyup", e => {
|
||||
//Check if every currentlyPessed is in our saved keybind.
|
||||
if (this.keybind.every(key => this.currentlyPressed[key.toLowerCase()] === true))
|
||||
//Toggle the sidebar and rerender on toggle; change the state
|
||||
setHidden(toggleSidebar(sidebarNode));
|
||||
|
||||
//Current key goes up, so...
|
||||
this.currentlyPressed[e.key.toLowerCase()] = false;
|
||||
|
||||
//Account for bubbling
|
||||
}, true);
|
||||
|
||||
//Lose focus event
|
||||
useWindowChangeListener(this.WindowInfoStore, () => {
|
||||
//Clear when it gets back into focus
|
||||
if (this.WindowInfoStore.isFocused())
|
||||
this.currentlyPressed = {};
|
||||
});
|
||||
|
||||
//Return our element.
|
||||
return React.createElement("div", {
|
||||
//Styling
|
||||
id: config.constants.buttonID,
|
||||
//The icon
|
||||
className: hidden ? config.constants.buttonHidden : config.constants.buttonVisible,
|
||||
//Toggle the sidebar and rerender on toggle; change the state.
|
||||
onClick: () => setHidden(toggleSidebar(sidebarNode))
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given keybind for validity. If not valid returns a default keybind.
|
||||
* @param {String|Array.<number>|Array.<Array.<number>>} keybindToLoad The keybind to filter and load in.
|
||||
* @param {String} [defaultKeybind] A default keybind to fall back on in case of invalidity.
|
||||
* @returns Will return the keybind or return a default keybind.
|
||||
*/
|
||||
checkKeybindLoad(keybindToLoad, defaultKeybind = "control+h") {
|
||||
defaultKeybind = defaultKeybind.toLowerCase().replace("ctrl", "control");
|
||||
|
||||
//If no keybind
|
||||
if (!keybindToLoad)
|
||||
return defaultKeybind;
|
||||
|
||||
//Error sensitive, so just plump it into a try-catch
|
||||
try {
|
||||
//If it's already a string, double check it
|
||||
if (typeof (keybindToLoad) === typeof (defaultKeybind)) {
|
||||
keybindToLoad = keybindToLoad.toLowerCase().replace("control", "ctrl");
|
||||
//Does it go into a combo? (i.e.: is it the correct format?)
|
||||
if (this.KeybindToCombo(keybindToLoad))
|
||||
return keybindToLoad.replace("ctrl", "control");
|
||||
else
|
||||
return defaultKeybind;
|
||||
}
|
||||
else
|
||||
//If it's not a string, check if it's a combo.
|
||||
if (this.KeybindToString(keybindToLoad))
|
||||
return this.KeybindToString(keybindToLoad).toLowerCase().replace("ctrl", "control");
|
||||
}
|
||||
catch (e) { return defaultKeybind; }
|
||||
}
|
||||
|
||||
generateCSS() {
|
||||
//Check if there is any CSS we have already, and remove it.
|
||||
DOM.removeStyle(config.constants.cssStyle);
|
||||
|
||||
//Now inject our (new) CSS
|
||||
DOM.addStyle(config.constants.cssStyle, `
|
||||
/* Button CSS */
|
||||
#${config.constants.buttonID} {
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
background-position: center !important;
|
||||
background-size: 100% !important;
|
||||
opacity: 0.8;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* How the button looks */
|
||||
.theme-dark #${config.constants.buttonID}.${config.constants.buttonVisible} {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2ZmZiIgd2lkdGg9IjE4cHgiIGhlaWdodD0iMThweCI+PHBhdGggZD0iTTE4LjQxIDE2LjU5TDEzLjgyIDEybDQuNTktNC41OUwxNyA2bC02IDYgNiA2ek02IDZoMnYxMkg2eiIvPjxwYXRoIGQ9Ik0yNCAyNEgwVjBoMjR2MjR6IiBmaWxsPSJub25lIi8+PC9zdmc+) no-repeat;
|
||||
}
|
||||
.theme-dark #${config.constants.buttonID}.${config.constants.buttonHidden} {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2ZmZiIgd2lkdGg9IjE4cHgiIGhlaWdodD0iMThweCI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTUuNTkgNy40MUwxMC4xOCAxMmwtNC41OSA0LjU5TDcgMThsNi02LTYtNnpNMTYgNmgydjEyaC0yeiIvPjwvc3ZnPg==) no-repeat;
|
||||
}
|
||||
/* In light theme */
|
||||
.theme-light #${config.constants.buttonID}.${config.constants.buttonVisible} {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzRmNTY2MCIgd2lkdGg9IjE4cHgiIGhlaWdodD0iMThweCI+PHBhdGggZD0iTTE4LjQxIDE2LjU5TDEzLjgyIDEybDQuNTktNC41OUwxNyA2bC02IDYgNiA2ek02IDZoMnYxMkg2eiIvPjxwYXRoIGQ9Ik0yNCAyNEgwVjBoMjR2MjR6IiBmaWxsPSJub25lIi8+PC9zdmc+) no-repeat;
|
||||
}
|
||||
.theme-light #${config.constants.buttonID}.${config.constants.buttonHidden} {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzRmNTY2MCIgd2lkdGg9IjE4cHgiIGhlaWdodD0iMThweCI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTUuNTkgNy40MUwxMC4xOCAxMmwtNC41OSA0LjU5TDcgMThsNi02LTYtNnpNMTYgNmgydjEyaC0yeiIvPjwvc3ZnPg==) no-repeat;
|
||||
}
|
||||
|
||||
/* Attached CSS to sidebar */
|
||||
html .${config.constants.hideElementsName}.${config.constants.hideElementsName} {
|
||||
width: 0 !important;
|
||||
}
|
||||
html .${config.constants.avatarOverlap}.${config.constants.avatarOverlap}{
|
||||
z-index: 1;
|
||||
}
|
||||
html .${config.constants.panelsButtonHidden}.${config.constants.panelsButtonHidden}{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Don't have square border at top left when channels are hidden */
|
||||
.${this.baseClass} {
|
||||
border-radius: 8px 0 0 !important;
|
||||
}
|
||||
|
||||
/* Set animations */
|
||||
.${this.sidebarClass} {
|
||||
${this.animation ? "transition: width 400ms ease;" : ""}
|
||||
overflow: hidden;
|
||||
}`);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name ImageUtilities
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 5.6.3
|
||||
* @version 5.6.4
|
||||
* @description Adds several Utilities for Images/Videos (Gallery, Download, Reverse Search, Zoom, Copy, etc.)
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
@@ -223,7 +223,7 @@ module.exports = (_ => {
|
||||
pixelMode: {value: false, label: "Uses Pixel Lens instead of a Blur Lens"},
|
||||
clickMode: {value: false, label: "Click Image to zoom instead of holding the Mouse Button"},
|
||||
lensSize: {value: 200, digits: 0, minValue: 50, maxValue: 5000, unit: "px", label: "context_lenssize"},
|
||||
zoomLevel: {value: 2, digits: 1, minValue: 1, maxValue: 20, unit: "x", label: "ACCESSIBILITY_ZOOM_LEVEL_LABEL"},
|
||||
zoomLevel: {value: 2, digits: 1, minValue: 1, maxValue: 20, unit: "x", label: "ZOOM_LEVEL"},
|
||||
zoomSpeed: {value: 0.1, digits: 2, minValue: 0.01, maxValue: 1, unit: "", label: "context_zoomspeed"}
|
||||
},
|
||||
rescaleSettings: {
|
||||
@@ -244,7 +244,7 @@ module.exports = (_ => {
|
||||
emojis: {value: true, description: "Custom Emojis/Emotes"}
|
||||
},
|
||||
engines: {
|
||||
_all: {value: true, name: BDFDB.LanguageUtils.LanguageStrings.FORM_LABEL_ALL, url: null},
|
||||
_all: {value: true, name: BDFDB.LanguageUtils.LanguageStrings.ALL, url: null},
|
||||
Baidu: {value: true, name: "Baidu", url: "http://image.baidu.com/pcdutu?queryImageUrl="},
|
||||
Bing: {value: true, name: "Bing", url: "https://www.bing.com/images/search?view=detailv2&iss=sbi&FORM=IRSBIQ&q=imgurl:"},
|
||||
Google: {value: true, name: "Google", url: "https://www.google.com/searchbyimage?sbisrc=cr_1&image_url="},
|
||||
@@ -866,7 +866,7 @@ module.exports = (_ => {
|
||||
|
||||
createSubMenus (data) {
|
||||
return data.urls.length == 1 ? this.createUrlMenu(data.instance, data.urls[0], data.target) : data.urls.map((urlData, i) => BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: [urlData.isGuildSpecific && BDFDB.LanguageUtils.LanguageStrings.CHANGE_IDENTITY_SERVER_PROFILE, data.prefix, urlData.fileType.toUpperCase()].filter(n => n).join(" "),
|
||||
label: [urlData.isGuildSpecific && BDFDB.LanguageUtils.LanguageStrings.SERVER_PROFILE, data.prefix, urlData.fileType.toUpperCase()].filter(n => n).join(" "),
|
||||
id: BDFDB.ContextMenuUtils.createItemId(this.name, "subitem", i),
|
||||
children: this.createUrlMenu(data.instance, urlData, data.target)
|
||||
}));
|
||||
@@ -1455,14 +1455,14 @@ module.exports = (_ => {
|
||||
children: validUrls.length == 1 ? this.createSubMenus({
|
||||
instance: {},
|
||||
urls: validUrls,
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.USER_SETTINGS_PROFILE_BANNER
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.PROFILE_BANNER
|
||||
}) : BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: this.labels.context_imageactions,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(this.name, "main-subitem"),
|
||||
children: this.createSubMenus({
|
||||
instance: {},
|
||||
urls: validUrls,
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.USER_SETTINGS_PROFILE_BANNER
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.PROFILE_BANNER
|
||||
})
|
||||
})
|
||||
}));
|
||||
|
||||
@@ -1,581 +0,0 @@
|
||||
/**
|
||||
* @name StaffTag
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 1.6.9
|
||||
* @description Adds a Crown/Tag to Server Owners (or Admins/Management)
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/StaffTag/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/StaffTag/StaffTag.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
const userTypes = {
|
||||
NONE: 0,
|
||||
MANAGEMENT: 1,
|
||||
ADMIN: 2,
|
||||
FORUM_CREATOR: 3,
|
||||
THREAD_CREATOR: 3,
|
||||
GROUP_OWNER: 5,
|
||||
OWNER: 6
|
||||
};
|
||||
|
||||
const labelMap = {
|
||||
[userTypes.NONE]: "",
|
||||
[userTypes.MANAGEMENT]: "management",
|
||||
[userTypes.ADMIN]: "admin",
|
||||
[userTypes.FORUM_CREATOR]: "forumCreator",
|
||||
[userTypes.THREAD_CREATOR]: "threadCreator",
|
||||
[userTypes.GROUP_OWNER]: "groupOwner",
|
||||
[userTypes.OWNER]: "owner"
|
||||
};
|
||||
|
||||
const classNameMap = {
|
||||
[userTypes.NONE]: "",
|
||||
[userTypes.MANAGEMENT]: "_stafftagmanagementicon",
|
||||
[userTypes.ADMIN]: "_stafftagadminicon",
|
||||
[userTypes.FORUM_CREATOR]: "_stafftagforumcreatoricon",
|
||||
[userTypes.THREAD_CREATOR]: "_stafftagthreadcreatoricon",
|
||||
[userTypes.GROUP_OWNER]: "_stafftaggroupownericon",
|
||||
[userTypes.OWNER]: "_stafftagownericon"
|
||||
};
|
||||
|
||||
return class StaffTag extends Plugin {
|
||||
onLoad () {
|
||||
|
||||
this.modulePatches = {
|
||||
before: [
|
||||
"MessageUsername"
|
||||
],
|
||||
after: [
|
||||
"NameContainerDecorators",
|
||||
"UserHeaderUsername",
|
||||
"VoiceUser"
|
||||
]
|
||||
};
|
||||
|
||||
this.defaults = {
|
||||
general: {
|
||||
useCrown: {value: true, description: "Uses the Crown Icon instead of the Bot Tag Style"},
|
||||
useRoleColor: {value: true, description: "Uses the Role Color instead of the default Blurple"},
|
||||
useBlackFont: {value: false, description: "Uses black Font instead of darkening the Role Color on bright Colors"},
|
||||
ignoreBots: {value: false, description: "Doesn't add the Owner/Admin/Management Tag for Bots"},
|
||||
ignoreMyself: {value: false, description: "Doesn't add the Owner/Admin/Management Tag for yourself"}
|
||||
},
|
||||
tagTypes: {
|
||||
owners: {value: true, description: "Server Owner Tag"},
|
||||
groupOwners: {value: true, description: "Group Owner Tag"},
|
||||
threadCreators: {value: true, description: "Thread Creator Tag"},
|
||||
forumCreators: {value: true, description: "Forum Creator Tag"},
|
||||
admins: {value: true, description: "Admin Tag (Admin Permissions)"},
|
||||
managementG: {value: true, description: "Management Tag (Server Management)"},
|
||||
managementC: {value: true, description: "Management Tag (Channel Management)"},
|
||||
managementT: {value: true, description: "Management Tag (Threads Management)"},
|
||||
managementE: {value: true, description: "Management Tag (Events Management)"},
|
||||
managementR: {value: true, description: "Management Tag (Role Management)"},
|
||||
managementU: {value: true, description: "Management Tag (User Management 'Kick/Ban')"},
|
||||
managementV: {value: true, description: "Management Tag (Voice Management 'Mute/Deafen/Move')"},
|
||||
managementM: {value: true, description: "Management Tag (Message Management)"}
|
||||
},
|
||||
tagPlaces: {
|
||||
chat: {value: true, description: "Messages"},
|
||||
memberList: {value: true, description: "Member List"},
|
||||
voiceList: {value: true, description: "Voice User List"},
|
||||
userPopout: {value: true, description: "User Popouts"},
|
||||
userProfile: {value: true, description: "User Profile Modal"},
|
||||
},
|
||||
customTitles: {
|
||||
owner: {value: "", placeholder: "Owner", description: "Server Owner Tags"},
|
||||
groupOwner: {value: "", placeholder: "Group Owner", description: "Group Owner Tags"},
|
||||
forumCreator: {value: "", placeholder: "Creator", description: "Forum Creator Tags"},
|
||||
threadCreator: {value: "", placeholder: "Creator", description: "Thread Creator Tags"},
|
||||
admin: {value: "", placeholder: "Admin", description: "Admin Tags"},
|
||||
management: {value: "", placeholder: "Management", description: "Management Tags"}
|
||||
}
|
||||
};
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCN.memberownericon + BDFDB.dotCN._stafftagadminicon} {
|
||||
color: #aaa9ad;
|
||||
}
|
||||
${BDFDB.dotCN.memberownericon + BDFDB.dotCN._stafftagmanagementicon} {
|
||||
color: #88540b;
|
||||
}
|
||||
${BDFDB.dotCN.memberownericon + BDFDB.dotCN._stafftagforumcreatoricon},
|
||||
${BDFDB.dotCN.memberownericon + BDFDB.dotCN._stafftagthreadcreatoricon} {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
${BDFDB.dotCN.memberownericon} {
|
||||
top: 0px;
|
||||
}
|
||||
${BDFDB.dotCN.memberownericon} + ${BDFDB.dotCN.memberownericon} {
|
||||
display: none;
|
||||
}
|
||||
${BDFDB.dotCNS.message + BDFDB.dotCN.memberownericon} {
|
||||
top: 2px;
|
||||
}
|
||||
${BDFDB.dotCNS.messagecompact + BDFDB.dotCN.memberownericon} {
|
||||
top: 1px;
|
||||
margin-left: 0;
|
||||
margin-right: 4px;
|
||||
}
|
||||
${BDFDB.dotCNS.messagerepliedmessage + BDFDB.dotCN.memberownericon},
|
||||
${BDFDB.dotCNS.messagethreadaccessory + BDFDB.dotCN.memberownericon} {
|
||||
top: 0px;
|
||||
margin-left: 0;
|
||||
margin-right: 4px;
|
||||
}
|
||||
${BDFDB.dotCNS.voiceuser + BDFDB.dotCN.memberownericon}:last-child {
|
||||
margin-right: 4px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Settings",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(this.defaults.general).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
key: key,
|
||||
keys: ["general", key],
|
||||
label: this.defaults.general[key].description,
|
||||
value: this.settings.general[key]
|
||||
}))
|
||||
}));
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Tag Settings",
|
||||
collapseStates: collapseStates,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, {
|
||||
title: "Add Tags for:",
|
||||
dividerBottom: true,
|
||||
children: Object.keys(this.defaults.tagTypes).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["tagTypes", key],
|
||||
label: this.defaults.tagTypes[key].description,
|
||||
value: this.settings.tagTypes[key]
|
||||
}))
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, {
|
||||
title: "Add Tags in:",
|
||||
children: Object.keys(this.defaults.tagPlaces).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["tagPlaces", key],
|
||||
label: this.defaults.tagPlaces[key].description,
|
||||
value: this.settings.tagPlaces[key]
|
||||
}))
|
||||
})
|
||||
]
|
||||
}));
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Custom Title Settings",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(this.defaults.customTitles).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "TextInput",
|
||||
plugin: this,
|
||||
keys: ["customTitles", key],
|
||||
label: this.defaults.customTitles[key].description,
|
||||
basis: "50%",
|
||||
value: this.settings.customTitles[key],
|
||||
placeholder: this.defaults.customTitles[key].placeholder
|
||||
}))
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSettingsClosed () {
|
||||
if (this.SettingsUpdated) {
|
||||
delete this.SettingsUpdated;
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
forceUpdateAll () {
|
||||
BDFDB.PatchUtils.forceAllUpdates(this);
|
||||
BDFDB.MessageUtils.rerenderAll();
|
||||
}
|
||||
|
||||
processNameContainerDecorators (e) {
|
||||
if (!e.instance.props.user) return;
|
||||
let channelId = e.instance.props.channel && e.instance.props.channel.id || BDFDB.LibraryStores.SelectedChannelStore.getChannelId();
|
||||
let userType = this.getUserType(e.instance.props.user, channelId);
|
||||
if (userType && this.settings.tagPlaces.memberList) {
|
||||
this.injectStaffTag(e.returnvalue.props.children, e.instance.props.user, userType, 1, {
|
||||
channelId: channelId,
|
||||
tagClass: BDFDB.disCN.bottagmember
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
processMessageUsername (e) {
|
||||
if (!e.instance.props.message || !this.settings.tagPlaces.chat || !e.instance.props.decorations) return;
|
||||
const author = e.instance.props.userOverride || e.instance.props.message.author;
|
||||
let userType = this.getUserType(author, e.instance.props.message.channel_id);
|
||||
if (!userType) return;
|
||||
if (!BDFDB.ArrayUtils.is(e.instance.props.decorations[0])) e.instance.props.decorations[0] = [e.instance.props.decorations[0]].filter(n => n);
|
||||
this.injectStaffTag(e.instance.props.decorations[0], author, userType, 0, {
|
||||
channelId: e.instance.props.message.channel_id,
|
||||
tagClass: e.instance.props.compact ? BDFDB.disCN.messagebottagcompact : BDFDB.disCN.messagebottagcozy,
|
||||
useRem: true
|
||||
});
|
||||
}
|
||||
|
||||
processVoiceUser (e) {
|
||||
if (e.instance.props.user && this.settings.tagPlaces.voiceList) {
|
||||
let userType = this.getUserType(e.instance.props.user, e.instance.props.channel && e.instance.props.channel.id);
|
||||
if (!userType) return;
|
||||
let content = BDFDB.ReactUtils.findChild(e.returnvalue, {props: [["className", BDFDB.disCN.voicecontent]]});
|
||||
if (content) this.injectStaffTag(content.props.children, e.instance.props.user, userType, 3, {
|
||||
channelId: e.instance.props.channel && e.instance.props.channel.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
processNameTag (e) {
|
||||
if (!e.instance.props.user || !e.instance.props.className) return;
|
||||
let userType = this.getUserType(e.instance.props.user);
|
||||
if (!userType) return;
|
||||
let inject = false, tagClass = "";
|
||||
if (e.instance.props.className.indexOf(BDFDB.disCN.userpopoutheadertagwithnickname) > -1) {
|
||||
inject = this.settings.tagPlaces.userPopout;
|
||||
tagClass = BDFDB.disCNS.userpopoutheaderbottag + BDFDB.disCN.bottagnametag;
|
||||
}
|
||||
else if (e.instance.props.className.indexOf(BDFDB.disCN.userprofilenametag) > -1) {
|
||||
inject = this.settings.tagPlaces.userProfile;
|
||||
tagClass = BDFDB.disCN.bottagnametag;
|
||||
}
|
||||
if (inject) this.injectStaffTag(e.returnvalue.props.children, e.instance.props.user, userType, 2, {
|
||||
tagClass: tagClass,
|
||||
useRem: e.instance.props.useRemSizes,
|
||||
inverted: e.instance.props.invertBotTagColor
|
||||
});
|
||||
}
|
||||
|
||||
processUserHeaderUsername (e) {
|
||||
let themeType = BDFDB.ObjectUtils.get(e.instance, "props.tags.props.themeType");
|
||||
if (!e.instance.props.user || (themeType == BDFDB.DiscordConstants.ProfileTypes.POPOUT || themeType == BDFDB.DiscordConstants.ProfileTypes.SIDEBAR) && !this.settings.tagPlaces.userPopout || (themeType == BDFDB.DiscordConstants.ProfileTypes.MODAL || themeType == BDFDB.DiscordConstants.ProfileTypes.MODAL_V2) && !this.settings.tagPlaces.userProfile) return;
|
||||
let userType = this.getUserType(e.instance.props.user, e.instance.props.channel && e.instance.props.channel.id);
|
||||
if (!userType) return;
|
||||
let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {props: [["className", BDFDB.disCN.userheadernickname]]});
|
||||
if (index > -1) {
|
||||
if (!BDFDB.ArrayUtils.is(children[index].props.children)) children[index].props.children = [children[index].props.children].flat(10);
|
||||
this.injectStaffTag(children[index].props.children, e.instance.props.user, userType, 2, {
|
||||
tagClass: BDFDB.disCNS.userheaderbottag + BDFDB.disCN.bottagnametag,
|
||||
inverted: typeof e.instance.getMode == "function" && e.instance.getMode() !== "Normal"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
injectStaffTag (children, user, userType, insertIndex, config = {}) {
|
||||
if (!BDFDB.ArrayUtils.is(children) || !user) return;
|
||||
let [_, index] = BDFDB.ReactUtils.findParent(children, {props: [["text", [BDFDB.LanguageUtils.LanguageStrings.GROUP_OWNER, BDFDB.LanguageUtils.LanguageStrings.GUILD_OWNER]]]});
|
||||
if (index > -1) children[index] = null;
|
||||
let channel = BDFDB.LibraryStores.ChannelStore.getChannel(config.channelId || BDFDB.LibraryStores.SelectedChannelStore.getChannelId());
|
||||
let member = channel && this.settings.general.useRoleColor ? (BDFDB.LibraryStores.GuildMemberStore.getMember(channel.guild_id, user.id) || {}) : {};
|
||||
|
||||
let fallbackLabel = this.settings.general.useCrown && this.getLabelFallback(userType);
|
||||
let label = this.getLabel(userType, fallbackLabel);
|
||||
let labelExtra = userType == userTypes.FORUM_CREATOR ? BDFDB.LanguageUtils.LanguageStrings.BOT_TAG_FORUM_ORIGINAL_POSTER_TOOLTIP : userType == userTypes.MANAGEMENT && this.getManagementLabel(user);
|
||||
|
||||
let tag = null;
|
||||
if (this.settings.general.useCrown) tag = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
|
||||
text: labelExtra ? `${label} (${labelExtra})` : label,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.memberownericon, classNameMap[userType] && BDFDB.disCN[classNameMap[userType]]),
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.CROWN,
|
||||
"aria-label": fallbackLabel
|
||||
})
|
||||
});
|
||||
else {
|
||||
let tagColor = BDFDB.ColorUtils.convert(member.colorString, "RGBA");
|
||||
let isBright = BDFDB.ColorUtils.isBright(tagColor);
|
||||
tagColor = isBright ? (this.settings.general.useBlackFont ? tagColor : BDFDB.ColorUtils.change(tagColor, -0.3)) : tagColor;
|
||||
tag = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.BotTag, {
|
||||
className: config.tagClass,
|
||||
useRemSizes: config.useRem,
|
||||
invertColor: config.inverted,
|
||||
style: {
|
||||
backgroundColor: config.inverted ? (isBright && this.settings.general.useBlackFont ? "black" : null) : tagColor,
|
||||
color: !config.inverted ? (isBright && this.settings.general.useBlackFont ? "black" : null) : tagColor
|
||||
},
|
||||
tag: label
|
||||
});
|
||||
if (labelExtra) tag = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
|
||||
text: labelExtra,
|
||||
children: tag
|
||||
});
|
||||
}
|
||||
children.splice(insertIndex, 0, tag);
|
||||
}
|
||||
|
||||
getLabelFallback (userType) {
|
||||
switch (userType) {
|
||||
case userTypes.OWNER: return BDFDB.LanguageUtils.LanguageStrings.GUILD_OWNER;
|
||||
case userTypes.GROUP_OWNER: return BDFDB.LanguageUtils.LanguageStrings.GROUP_OWNER;
|
||||
case userTypes.FORUM_CREATOR: return BDFDB.LanguageUtils.LanguageStrings.BOT_TAG_FORUM_ORIGINAL_POSTER;
|
||||
case userTypes.THREAD_CREATOR: return this.labels.creator.replace("{{var0}}", BDFDB.LanguageUtils.LanguageStrings.THREAD);
|
||||
case userTypes.ADMIN: return BDFDB.LanguageUtils.LanguageStrings.ADMINISTRATOR;
|
||||
case userTypes.MANAGEMENT: return this.labels.management;
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
getLabel (userType, fallback) {
|
||||
let type = labelMap[userType];
|
||||
if (!type) return fallback || "";
|
||||
else if (!fallback) return this.settings.customTitles[type] || this.defaults.customTitles[type].placeholder;
|
||||
else return this.settings.customTitles[type] && this.settings.customTitles[type].toLowerCase() != this.defaults.customTitles[type].placeholder.toLowerCase() ? this.settings.customTitles[type] : fallback;
|
||||
}
|
||||
|
||||
getManagementLabel (user) {
|
||||
return [
|
||||
this.settings.tagTypes.managementG && BDFDB.UserUtils.can("MANAGE_GUILD", user.id) && BDFDB.LanguageUtils.LibraryStrings.server,
|
||||
this.settings.tagTypes.managementC && BDFDB.UserUtils.can("MANAGE_CHANNELS", user.id) && BDFDB.LanguageUtils.LanguageStrings.CHANNELS,
|
||||
this.settings.tagTypes.managementT && BDFDB.UserUtils.can("MANAGE_THREADS", user.id) && BDFDB.LanguageUtils.LanguageStrings.THREADS,
|
||||
this.settings.tagTypes.managementE && BDFDB.UserUtils.can("MANAGE_EVENTS", user.id) && BDFDB.LanguageUtils.LanguageStrings.GUILD_EVENTS,
|
||||
this.settings.tagTypes.managementR && BDFDB.UserUtils.can("MANAGE_ROLES", user.id) && BDFDB.LanguageUtils.LanguageStrings.ROLES,
|
||||
this.settings.tagTypes.managementU && (BDFDB.UserUtils.can("BAN_MEMBERS", user.id) || BDFDB.UserUtils.can("KICK_MEMBERS", user.id)) && BDFDB.LanguageUtils.LanguageStrings.MEMBERS,
|
||||
this.settings.tagTypes.managementV && (BDFDB.UserUtils.can("MUTE_MEMBERS", user.id) || BDFDB.UserUtils.can("DEAFEN_MEMBERS", user.id) || BDFDB.UserUtils.can("MOVE_MEMBERS", user.id)) && BDFDB.LanguageUtils.LanguageStrings.VOICE_AND_VIDEO,
|
||||
this.settings.tagTypes.managementM && BDFDB.UserUtils.can("MANAGE_MESSAGES", user.id) && BDFDB.LanguageUtils.LanguageStrings.MESSAGES
|
||||
].filter(n => n).join(", ");
|
||||
}
|
||||
|
||||
getUserType (user, channelId) {
|
||||
if (!user || this.settings.general.ignoreBots && user.bot || this.settings.general.ignoreMyself && user.id == BDFDB.UserUtils.me.id) return userTypes.NONE;
|
||||
const channel = BDFDB.LibraryStores.ChannelStore.getChannel(channelId || BDFDB.LibraryStores.SelectedChannelStore.getChannelId());
|
||||
if (!channel) return userTypes.NONE;
|
||||
const guild = BDFDB.LibraryStores.GuildStore.getGuild(channel.guild_id);
|
||||
|
||||
if (this.settings.tagTypes.owners && guild && guild.ownerId == user.id) return userTypes.OWNER;
|
||||
else if (this.settings.tagTypes.groupOwners && channel.ownerId == user.id && channel.isGroupDM()) return userTypes.GROUP_OWNER;
|
||||
else if (this.settings.tagTypes.forumCreators && channel.ownerId == user.id && BDFDB.ChannelUtils.isForumPost(channel)) return userTypes.FORUM_CREATOR;
|
||||
else if (this.settings.tagTypes.threadCreators && channel.ownerId == user.id && BDFDB.ChannelUtils.isThread(channel) && !BDFDB.ChannelUtils.isForumPost(channel)) return userTypes.THREAD_CREATOR;
|
||||
else if (this.settings.tagTypes.admins && BDFDB.UserUtils.can("ADMINISTRATOR", user.id)) return userTypes.ADMIN;
|
||||
else if (this.settings.tagTypes.managementG && BDFDB.UserUtils.can("MANAGE_GUILD", user.id) || this.settings.tagTypes.managementC && BDFDB.UserUtils.can("MANAGE_CHANNELS", user.id) || this.settings.tagTypes.managementR && BDFDB.UserUtils.can("MANAGE_ROLES", user.id) || this.settings.tagTypes.managementU && (BDFDB.UserUtils.can("BAN_MEMBERS", user.id) || BDFDB.UserUtils.can("KICK_MEMBERS", user.id)) || this.settings.tagTypes.managementM && BDFDB.UserUtils.can("MANAGE_MESSAGES", user.id)) return userTypes.MANAGEMENT;
|
||||
return userTypes.NONE;
|
||||
}
|
||||
|
||||
setLabelsByLanguage () {
|
||||
switch (BDFDB.LanguageUtils.getLanguage().id) {
|
||||
case "bg": // Bulgarian
|
||||
return {
|
||||
management: "Управление",
|
||||
creator: "Cъздател {{var0}}"
|
||||
};
|
||||
case "cs": // Czech
|
||||
return {
|
||||
management: "Řízení",
|
||||
creator: "{{var0}} autor"
|
||||
};
|
||||
case "da": // Danish
|
||||
return {
|
||||
management: "Ledelse",
|
||||
creator: "{{var0}} skaber"
|
||||
};
|
||||
case "de": // German
|
||||
return {
|
||||
management: "Verwaltung",
|
||||
creator: "{{var0}}ersteller"
|
||||
};
|
||||
case "el": // Greek
|
||||
return {
|
||||
management: "Διαχείριση",
|
||||
creator: "{{var0}} δημιουργός"
|
||||
};
|
||||
case "es": // Spanish
|
||||
return {
|
||||
management: "Administración",
|
||||
creator: "{{var0}} creador"
|
||||
};
|
||||
case "fi": // Finnish
|
||||
return {
|
||||
management: "Johto",
|
||||
creator: "{{var0}} luoja"
|
||||
};
|
||||
case "fr": // French
|
||||
return {
|
||||
management: "La gestion",
|
||||
creator: "{{var0}}créateur"
|
||||
};
|
||||
case "hi": // Hindi
|
||||
return {
|
||||
management: "प्रबंध",
|
||||
creator: "{{var0}}निर्माता"
|
||||
};
|
||||
case "hr": // Croatian
|
||||
return {
|
||||
management: "Upravljanje",
|
||||
creator: "{{var0}} kreator"
|
||||
};
|
||||
case "hu": // Hungarian
|
||||
return {
|
||||
management: "Menedzsment",
|
||||
creator: "{{var0}} alkotója"
|
||||
};
|
||||
case "it": // Italian
|
||||
return {
|
||||
management: "Gestione",
|
||||
creator: "{{var0}}creatore"
|
||||
};
|
||||
case "ja": // Japanese
|
||||
return {
|
||||
management: "管理",
|
||||
creator: "{{var0}}作成者"
|
||||
};
|
||||
case "ko": // Korean
|
||||
return {
|
||||
management: "조치",
|
||||
creator: "{{var0}}창조자"
|
||||
};
|
||||
case "lt": // Lithuanian
|
||||
return {
|
||||
management: "Valdymas",
|
||||
creator: "{{var0}} kūrėjas"
|
||||
};
|
||||
case "nl": // Dutch
|
||||
return {
|
||||
management: "Beheer",
|
||||
creator: "{{var0}}maker"
|
||||
};
|
||||
case "no": // Norwegian
|
||||
return {
|
||||
management: "Ledelse",
|
||||
creator: "{{var0}} skaperen"
|
||||
};
|
||||
case "pl": // Polish
|
||||
return {
|
||||
management: "Zarządzanie",
|
||||
creator: "{{var0}}twórca"
|
||||
};
|
||||
case "pt-BR": // Portuguese (Brazil)
|
||||
return {
|
||||
management: "Gestão",
|
||||
creator: "{{var0}} criador"
|
||||
};
|
||||
case "ro": // Romanian
|
||||
return {
|
||||
management: "Administrare",
|
||||
creator: "{{var0}} creator"
|
||||
};
|
||||
case "ru": // Russian
|
||||
return {
|
||||
management: "Управление",
|
||||
creator: "Cоздатель {{var0}}"
|
||||
};
|
||||
case "sv": // Swedish
|
||||
return {
|
||||
management: "Förvaltning",
|
||||
creator: "{{var0}} skapare"
|
||||
};
|
||||
case "th": // Thai
|
||||
return {
|
||||
management: "การจัดการ",
|
||||
creator: "{{var0}}ผู้สร้าง"
|
||||
};
|
||||
case "tr": // Turkish
|
||||
return {
|
||||
management: "Yönetim",
|
||||
creator: "{{var0}}yaratıcı"
|
||||
};
|
||||
case "uk": // Ukrainian
|
||||
return {
|
||||
management: "Управління",
|
||||
creator: "{{var0}} творець"
|
||||
};
|
||||
case "vi": // Vietnamese
|
||||
return {
|
||||
management: "Sự quản lý",
|
||||
creator: "Người tạo {{var0}}"
|
||||
};
|
||||
case "zh-CN": // Chinese (China)
|
||||
return {
|
||||
management: "管理",
|
||||
creator: "{{var0}} 创建者"
|
||||
};
|
||||
case "zh-TW": // Chinese (Taiwan)
|
||||
return {
|
||||
management: "管理",
|
||||
creator: "{{var0}} 建立者"
|
||||
};
|
||||
default: // English
|
||||
return {
|
||||
management: "Management",
|
||||
creator: "{{var0}} Creator"
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -1,12 +1,47 @@
|
||||
/**
|
||||
* @name ViewProfilePicture
|
||||
* @description Adds a button to the user popout and profile that allows you to view the Avatar and banner.
|
||||
* @version 1.3.0
|
||||
* @version 1.3.1
|
||||
* @author Skamt
|
||||
* @website https://github.com/Skamt/BDAddons/tree/main/ViewProfilePicture
|
||||
* @source https://raw.githubusercontent.com/Skamt/BDAddons/main/ViewProfilePicture/ViewProfilePicture.plugin.js
|
||||
*/
|
||||
|
||||
// config:@Config
|
||||
var Config_default = {
|
||||
"info": {
|
||||
"name": "ViewProfilePicture",
|
||||
"version": "1.3.1",
|
||||
"description": "Adds a button to the user popout and profile that allows you to view the Avatar and banner.",
|
||||
"source": "https://raw.githubusercontent.com/Skamt/BDAddons/main/ViewProfilePicture/ViewProfilePicture.plugin.js",
|
||||
"github": "https://github.com/Skamt/BDAddons/tree/main/ViewProfilePicture",
|
||||
"authors": [{
|
||||
"name": "Skamt"
|
||||
}]
|
||||
},
|
||||
"settings": {
|
||||
"showOnHover": false,
|
||||
"bannerColor": false
|
||||
}
|
||||
};
|
||||
|
||||
// common/Api.js
|
||||
var Api = new BdApi(Config_default.info.name);
|
||||
var UI = /* @__PURE__ */ (() => Api.UI)();
|
||||
var DOM = /* @__PURE__ */ (() => Api.DOM)();
|
||||
var Data = /* @__PURE__ */ (() => Api.Data)();
|
||||
var React = /* @__PURE__ */ (() => Api.React)();
|
||||
var Patcher = /* @__PURE__ */ (() => Api.Patcher)();
|
||||
var Logger = /* @__PURE__ */ (() => Api.Logger)();
|
||||
var Webpack = /* @__PURE__ */ (() => Api.Webpack)();
|
||||
var findInTree = /* @__PURE__ */ (() => Api.Utils.findInTree)();
|
||||
|
||||
// common/Utils/Logger.js
|
||||
Logger.patchError = (patchId) => {
|
||||
console.error(`%c[${Config_default.info.name}] %cCould not find module for %c[${patchId}]`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;");
|
||||
};
|
||||
var Logger_default = Logger;
|
||||
|
||||
// common/Utils/EventEmitter.js
|
||||
var EventEmitter_default = class {
|
||||
constructor() {
|
||||
@@ -43,7 +78,7 @@ var EventEmitter_default = class {
|
||||
try {
|
||||
listener.apply(null, payload);
|
||||
} catch (err) {
|
||||
console.error(`Could not run listener for ${event}`, err);
|
||||
Logger_default.error(`Could not run listener for ${event}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,35 +98,6 @@ var Plugin_default = new class extends EventEmitter_default {
|
||||
}
|
||||
}();
|
||||
|
||||
// config:@Config
|
||||
var Config_default = {
|
||||
"info": {
|
||||
"name": "ViewProfilePicture",
|
||||
"version": "1.3.0",
|
||||
"description": "Adds a button to the user popout and profile that allows you to view the Avatar and banner.",
|
||||
"source": "https://raw.githubusercontent.com/Skamt/BDAddons/main/ViewProfilePicture/ViewProfilePicture.plugin.js",
|
||||
"github": "https://github.com/Skamt/BDAddons/tree/main/ViewProfilePicture",
|
||||
"authors": [{
|
||||
"name": "Skamt"
|
||||
}]
|
||||
},
|
||||
"settings": {
|
||||
"showOnHover": false,
|
||||
"bannerColor": false
|
||||
}
|
||||
};
|
||||
|
||||
// common/Api.js
|
||||
var Api = new BdApi(Config_default.info.name);
|
||||
var UI = /* @__PURE__ */ (() => Api.UI)();
|
||||
var DOM = /* @__PURE__ */ (() => Api.DOM)();
|
||||
var Data = /* @__PURE__ */ (() => Api.Data)();
|
||||
var React = /* @__PURE__ */ (() => Api.React)();
|
||||
var Patcher = /* @__PURE__ */ (() => Api.Patcher)();
|
||||
var Logger = /* @__PURE__ */ (() => Api.Logger)();
|
||||
var Webpack = /* @__PURE__ */ (() => Api.Webpack)();
|
||||
var findInTree = /* @__PURE__ */ (() => Api.Utils.findInTree)();
|
||||
|
||||
// common/Utils/StylesLoader.js
|
||||
var styleLoader = {
|
||||
_styles: [],
|
||||
@@ -110,7 +116,7 @@ var StylesLoader_default = styleLoader;
|
||||
// src/ViewProfilePicture/styles.css
|
||||
StylesLoader_default.push(`/* View Profile Button */
|
||||
.VPP-Button {
|
||||
background: hsl(var(--black-500-hsl) / 0.7);
|
||||
background: rgb(1 0 1 / 54%);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
border-radius: 50%;
|
||||
@@ -141,7 +147,7 @@ StylesLoader_default.push(`/* View Profile Button */
|
||||
}
|
||||
|
||||
.VPP-Button:hover {
|
||||
background: hsl(var(--black-500-hsl) / 0.85);
|
||||
background: rgb(1 0 1 / 64%);
|
||||
}
|
||||
|
||||
/* div replacement if No banner */
|
||||
@@ -258,8 +264,13 @@ function getImageDimensions(url) {
|
||||
});
|
||||
}
|
||||
|
||||
// common/React.jsx
|
||||
var useState = /* @__PURE__ */ (() => React.useState)();
|
||||
var useMemo = /* @__PURE__ */ (() => React.useMemo)();
|
||||
var React_default = /* @__PURE__ */ (() => React)();
|
||||
|
||||
// common/Components/ErrorBoundary/index.jsx
|
||||
var ErrorBoundary = class extends React.Component {
|
||||
var ErrorBoundary = class extends React_default.Component {
|
||||
state = { hasError: false, error: null, info: null };
|
||||
componentDidCatch(error, info) {
|
||||
this.setState({ error, info, hasError: true });
|
||||
@@ -269,10 +280,10 @@ var ErrorBoundary = class extends React.Component {
|
||||
`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;", errorMessage);
|
||||
}
|
||||
renderErrorBoundary() {
|
||||
return /* @__PURE__ */ React.createElement("div", { style: { background: "#292c2c", padding: "20px", borderRadius: "10px" } }, /* @__PURE__ */ React.createElement("b", { style: { color: "#e0e1e5" } }, "An error has occured while rendering ", /* @__PURE__ */ React.createElement("span", { style: { color: "orange" } }, this.props.id)));
|
||||
return /* @__PURE__ */ React_default.createElement("div", { style: { background: "#292c2c", padding: "20px", borderRadius: "10px" } }, /* @__PURE__ */ React_default.createElement("b", { style: { color: "#e0e1e5" } }, "An error has occured while rendering ", /* @__PURE__ */ React_default.createElement("span", { style: { color: "orange" } }, this.props.id)));
|
||||
}
|
||||
renderFallback() {
|
||||
if (React.isValidElement(this.props.fallback)) {
|
||||
if (React_default.isValidElement(this.props.fallback)) {
|
||||
if (this.props.passMetaProps)
|
||||
this.props.fallback.props = {
|
||||
id: this.props.id,
|
||||
@@ -281,7 +292,7 @@ var ErrorBoundary = class extends React.Component {
|
||||
};
|
||||
return this.props.fallback;
|
||||
}
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
this.props.fallback, {
|
||||
id: this.props.id,
|
||||
plugin: Config_default?.info?.name || "Unknown Plugin"
|
||||
@@ -314,12 +325,6 @@ var ErrorIcon_default = (props) => /* @__PURE__ */ React.createElement("div", {
|
||||
React.createElement("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" })
|
||||
));
|
||||
|
||||
// common/Utils/Logger.js
|
||||
Logger.patchError = (patchId) => {
|
||||
console.error(`%c[${Config_default.info.name}] %cCould not find module for %c[${patchId}]`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;");
|
||||
};
|
||||
var Logger_default = Logger;
|
||||
|
||||
// common/Webpack.js
|
||||
var getModule = /* @__PURE__ */ (() => Webpack.getModule)();
|
||||
var Filters = /* @__PURE__ */ (() => Webpack.Filters)();
|
||||
@@ -341,11 +346,6 @@ function getModuleAndKey(filter, options) {
|
||||
return { module: module2, key };
|
||||
}
|
||||
|
||||
// common/React.js
|
||||
var useState = /* @__PURE__ */ (() => React.useState)();
|
||||
var useMemo = /* @__PURE__ */ (() => React.useMemo)();
|
||||
var React_default = /* @__PURE__ */ (() => React)();
|
||||
|
||||
// common/DiscordModules/zustand.js
|
||||
var { zustand } = getMangled(Filters.bySource("useSyncExternalStoreWithSelector", "useDebugValue", "subscribe"), {
|
||||
_: Filters.byStrings("subscribe"),
|
||||
@@ -401,17 +401,20 @@ StylesLoader_default.push(`.transparent-background.transparent-background{
|
||||
border:unset;
|
||||
}`);
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/ModalRoot
|
||||
var ModalRoot_default = getModule(Filters.byStrings("rootWithShadow", "MODAL"), { searchExports: true });
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/ModalSize
|
||||
var ModalSize_default = getModule(Filters.byKeys("DYNAMIC", "SMALL", "LARGE"), { searchExports: true });
|
||||
|
||||
// common/Utils/Modals/index.jsx
|
||||
var ModalActions = /* @__PURE__ */ getMangled("onCloseRequest:null!=", {
|
||||
openModal: /* @__PURE__ */ Filters.byStrings("onCloseRequest:null!="),
|
||||
closeModal: /* @__PURE__ */ Filters.byStrings(".setState", ".getState()[")
|
||||
});
|
||||
var Modals = /* @__PURE__ */ getMangled( /* @__PURE__ */ Filters.bySource("root", "headerIdIsManaged"), {
|
||||
ModalRoot: /* @__PURE__ */ Filters.byStrings("rootWithShadow"),
|
||||
ModalFooter: /* @__PURE__ */ Filters.byStrings(".footer"),
|
||||
ModalContent: /* @__PURE__ */ Filters.byStrings(".content"),
|
||||
ModalHeader: /* @__PURE__ */ Filters.byStrings(".header", "separator"),
|
||||
Animations: (a) => a.SUBTLE,
|
||||
Sizes: (a) => a.DYNAMIC,
|
||||
ModalCloseButton: Filters.byStrings(".close]:")
|
||||
});
|
||||
var openModal = (children, tag, { className, ...modalRootProps } = {}) => {
|
||||
const id = `${tag ? `${tag}-` : ""}modal`;
|
||||
return ModalActions.openModal((props) => {
|
||||
@@ -422,11 +425,11 @@ var openModal = (children, tag, { className, ...modalRootProps } = {}) => {
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React.createElement(
|
||||
ModalRoot_default, {
|
||||
Modals.ModalRoot, {
|
||||
onClick: props.onClose,
|
||||
transitionState: props.transitionState,
|
||||
className: concateClassNames("transparent-background", className),
|
||||
size: ModalSize_default.DYNAMIC,
|
||||
size: Modals.Sizes.DYNAMIC,
|
||||
...modalRootProps
|
||||
},
|
||||
React.cloneElement(children, { ...props })
|
||||
@@ -592,22 +595,22 @@ function resolveColor() {
|
||||
}
|
||||
|
||||
function copyColor(type, color) {
|
||||
let c = color;
|
||||
let c2 = color;
|
||||
try {
|
||||
switch (type) {
|
||||
case "hex":
|
||||
c = Color_default(color).hex();
|
||||
c2 = Color_default(color).hex();
|
||||
break;
|
||||
case "rgba":
|
||||
c = Color_default(color).css("rgba");
|
||||
c2 = Color_default(color).css("rgba");
|
||||
break;
|
||||
case "hsla":
|
||||
c = Color_default(color).css("hsla");
|
||||
c2 = Color_default(color).css("hsla");
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
copy(c);
|
||||
Toast_default.success(`${c} Copied!`);
|
||||
copy(c2);
|
||||
Toast_default.success(`${c2} Copied!`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,7 +763,7 @@ Plugin_default.on(Events.START, () => {
|
||||
var FormSwitch_default = getModule(Filters.byStrings("note", "tooltipNote"), { searchExports: true });
|
||||
|
||||
// common/Components/Switch/index.jsx
|
||||
var Switch_default = FormSwitch_default || function SwitchComponentFallback(props) {
|
||||
var Switch_default = getModule(Filters.byStrings('"data-toggleable-component":"switch"', 'layout:"horizontal"'), { searchExports: true }) || function SwitchComponentFallback(props) {
|
||||
return /* @__PURE__ */ React.createElement("div", { style: { color: "#fff" } }, props.children, /* @__PURE__ */ React.createElement(
|
||||
"input", {
|
||||
type: "checkbox",
|
||||
@@ -771,26 +774,88 @@ var Switch_default = FormSwitch_default || function SwitchComponentFallback(prop
|
||||
};
|
||||
|
||||
// common/Components/SettingSwtich/index.jsx
|
||||
function SettingSwtich({ settingKey, note, onChange = nop, hideBorder = false, description, ...rest }) {
|
||||
function SettingSwtich({ settingKey, note, onChange = nop, description, ...rest }) {
|
||||
const [val, set] = Settings_default.useSetting(settingKey);
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
Switch_default, {
|
||||
...rest,
|
||||
value: val,
|
||||
note,
|
||||
hideBorder,
|
||||
checked: val,
|
||||
label: description || settingKey,
|
||||
description: note,
|
||||
onChange: (e) => {
|
||||
set(e);
|
||||
onChange(e);
|
||||
}
|
||||
},
|
||||
description || settingKey
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// common/Components/FieldSet/styles.css
|
||||
StylesLoader_default.push(`.fieldset-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.fieldset-label {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.fieldset-description {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.fieldset-label + .fieldset-description{
|
||||
margin-top:-8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.fieldset-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
`);
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/Heading
|
||||
var Heading_default = getModule((a) => a?.render?.toString().includes("data-excessive-heading-level"), { searchExports: true });
|
||||
|
||||
// common/Utils/css.js
|
||||
var classNameFactory = (prefix = "", connector = "-") => (...args) => {
|
||||
const classNames = /* @__PURE__ */ new Set();
|
||||
for (const arg of args) {
|
||||
if (arg && typeof arg === "string") classNames.add(arg);
|
||||
else if (Array.isArray(arg)) arg.forEach((name) => classNames.add(name));
|
||||
else if (arg && typeof arg === "object") Object.entries(arg).forEach(([name, value]) => value && classNames.add(name));
|
||||
}
|
||||
return Array.from(classNames, (name) => `${prefix}${connector}${name}`).join(" ");
|
||||
};
|
||||
|
||||
// common/Components/FieldSet/index.jsx
|
||||
var c = classNameFactory("fieldset");
|
||||
|
||||
function FieldSet({ label, description, children, contentGap = 16 }) {
|
||||
return /* @__PURE__ */ React_default.createElement("fieldset", { className: c("container") }, label && /* @__PURE__ */ React_default.createElement(
|
||||
Heading_default, {
|
||||
className: c("label"),
|
||||
tag: "legend",
|
||||
variant: "text-lg/medium"
|
||||
},
|
||||
label
|
||||
), description && /* @__PURE__ */ React_default.createElement(
|
||||
Heading_default, {
|
||||
className: c("description"),
|
||||
variant: "text-sm/normal",
|
||||
color: "text-secondary"
|
||||
},
|
||||
description
|
||||
), /* @__PURE__ */ React_default.createElement("div", { className: c("content"), style: { gap: contentGap } }, children));
|
||||
}
|
||||
|
||||
// src/ViewProfilePicture/components/SettingComponent.jsx
|
||||
function SettingComponent() {
|
||||
return [{
|
||||
return /* @__PURE__ */ React_default.createElement(FieldSet, { contentGap: 8 }, [{
|
||||
settingKey: "showOnHover",
|
||||
note: "By default hide ViewProfilePicture button and show on hover.",
|
||||
description: "Show on hover"
|
||||
@@ -800,7 +865,7 @@ function SettingComponent() {
|
||||
note: "Always include banner color in carousel, even if a banner is present.",
|
||||
description: "Include banner color."
|
||||
}
|
||||
].map(SettingSwtich);
|
||||
].map(SettingSwtich));
|
||||
}
|
||||
|
||||
// src/ViewProfilePicture/index.jsx
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
~/.dotfiles/.script/discord-pywalsync.sh
|
||||
~/.dotfiles/.script/cava-pywalsync.sh
|
||||
~/.dotfiles/.script/wlogout-pywalsync.sh
|
||||
~/.local/bin/discord-pywalsync.sh
|
||||
~/.local/bin/cava-pywalsync.sh
|
||||
~/.local/bin/wlogout-pywalsync.sh
|
||||
~/.local/bin/pywalfox update
|
||||
1
.config/wlogout/colors.css
Symbolic link
1
.config/wlogout/colors.css
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/rionzaphkiel/.cache/wal/colors-waybar.css
|
||||
@@ -1,4 +1,4 @@
|
||||
@import url("file:///home/rionzaphkiel/.cache/wal/colors-waybar.css");
|
||||
@import url("colors.css");
|
||||
|
||||
* {
|
||||
background-image: none;
|
||||
|
||||
1
.config/wofi/colors.css
Symbolic link
1
.config/wofi/colors.css
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/rionzaphkiel/.cache/wal/colors-waybar.css
|
||||
@@ -1,4 +1,4 @@
|
||||
@import url("file:///home/rionzaphkiel/.cache/wal/colors-waybar.css");
|
||||
@import url("./.config/wofi/colors.css");
|
||||
|
||||
/* === Global === */
|
||||
* {
|
||||
|
||||
@@ -5,8 +5,8 @@ CAVA_CONFIG="$HOME/.config/cava/config"
|
||||
WAL_COLORS="$HOME/.cache/wal/colors.json"
|
||||
|
||||
# Take colors from pywal
|
||||
COLOR1=$(jq -r '.colors.color8' "$WAL_COLORS")
|
||||
COLOR2=$(jq -r '.colors.color1' "$WAL_COLORS")
|
||||
COLOR1=$(jq -r '.colors.color1' "$WAL_COLORS")
|
||||
COLOR2=$(jq -r '.colors.color5' "$WAL_COLORS")
|
||||
|
||||
# Update colors in CAVA
|
||||
sed -i "s|^gradient_color_1 = '.*'|gradient_color_1 = '$COLOR1'|" "$CAVA_CONFIG"
|
||||
|
||||
@@ -6,7 +6,7 @@ CACHE_DIR="$HOME/.cache/wallpaper-picker"
|
||||
THUMB_WIDTH="250"
|
||||
THUMB_HEIGHT="141"
|
||||
THEMES="$HOME/.config/wal/themes"
|
||||
WAL_BIN="$HOME/.local/bin/wal"
|
||||
WAL_BIN="/usr/local/bin/wal"
|
||||
HOOKS="$HOME/.config/wal/hooks/hooks.sh"
|
||||
FASTFETCH_CFG="$HOME/.config/fastfetch/config.jsonc"
|
||||
|
||||
@@ -105,4 +105,3 @@ touch "$HOME/.config/fastfetch/.reload_flag"
|
||||
|
||||
# Run pywal hooks
|
||||
$HOOKS
|
||||
$HOME/.local/bin/pywalfox update
|
||||
5
.zshrc
5
.zshrc
@@ -114,8 +114,11 @@ source $ZSH/oh-my-zsh.sh
|
||||
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
|
||||
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
|
||||
|
||||
# Muat warna dari Pywal di bagian paling akhir
|
||||
[ -f ~/.cache/wal/sequences ] && cat ~/.cache/wal/sequences
|
||||
|
||||
alias ffa='~/.local/bin/fastfetch_auto.sh'
|
||||
alias reales='~/.realesrgan/realesrgan-ncnn-vulkan'
|
||||
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
|
||||
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
|
||||
|
||||
Reference in New Issue
Block a user