Fix settings, tooltips, modals (#1542)
* Lazy load sidebar header * Publish CSS * Swap to standalone header * Fix Tooltip component * Moves internal reference to the centralized DiscordModules.Tooltip component * Adds `BdApi.Components` namespace with the `Tooltip` component. * Add Components namespace to bound api * Fix modal root * Fix ContextMenu, Fix Modals --------- Co-authored-by: Strencher <46447572+Strencher@users.noreply.github.com>
This commit is contained in:
parent
99f8bc29a8
commit
f3b26fbd4d
|
@ -16,15 +16,18 @@ const MenuComponents = (() => {
|
|||
customitem: "Item"
|
||||
};
|
||||
|
||||
// exportKey:()=>identifier
|
||||
const getExportIdentifier = (string, id) => new RegExp(`(\\w+):\\(\\)=>${id}`).exec(string)?.[1];
|
||||
|
||||
try {
|
||||
let contextMenuId = Object.keys(WebpackModules.require.m).find(e => WebpackModules.require.m[e]?.toString().includes("menuitemcheckbox"));
|
||||
const ContextMenuModule = WebpackModules.getModule((m, t, id) => id === contextMenuId);
|
||||
const rawMatches = WebpackModules.require.m[contextMenuId].toString().matchAll(/if\(\w+\.type===\w+\.(\w+)\).+?type:"(.+?)"/g);
|
||||
|
||||
const rawMatches = WebpackModules.require.m[contextMenuId].toString().matchAll(/if\(\w+\.type===(\w+)\)[\s\S]+?type:"(.+?)"/g);
|
||||
const moduleString = WebpackModules.require.m[contextMenuId].toString();
|
||||
out.Menu = Object.values(ContextMenuModule).find(v => v.toString().includes(".isUsingKeyboardNavigation"));
|
||||
|
||||
|
||||
for (const [, identifier, type] of rawMatches) {
|
||||
out[componentMap[type]] = ContextMenuModule[identifier];
|
||||
out[componentMap[type]] = ContextMenuModule[getExportIdentifier(moduleString, identifier)];
|
||||
}
|
||||
|
||||
startupComplete = Object.values(componentMap).every(k => out[k]) && !!out.Menu;
|
||||
|
@ -55,7 +58,7 @@ const ContextMenuActions = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
startupComplete = typeof(out.closeContextMenu) === "function" && typeof(out.openContextMenu) === "function";
|
||||
startupComplete &&= typeof(out.closeContextMenu) === "function" && typeof(out.openContextMenu) === "function";
|
||||
} catch (error) {
|
||||
startupComplete = false;
|
||||
Logger.stacktrace("ContextMenu~Components", "Fatal startup error:", error);
|
||||
|
|
|
@ -12,6 +12,7 @@ import Utils from "./utils";
|
|||
import Webpack from "./webpack";
|
||||
import * as Legacy from "./legacy";
|
||||
import ContextMenu from "./contextmenu";
|
||||
import {DiscordModules} from "modules";
|
||||
|
||||
const bounded = new Map();
|
||||
const PluginAPI = new AddonAPI(PluginManager);
|
||||
|
@ -53,6 +54,9 @@ export default class BdApi {
|
|||
get UI() {return UI;}
|
||||
get ReactUtils() {return ReactUtils;}
|
||||
get ContextMenu() {return ContextMenuAPI;}
|
||||
Components = {
|
||||
get Tooltip() {return DiscordModules.Tooltip;}
|
||||
}
|
||||
}
|
||||
|
||||
// Add legacy functions
|
||||
|
@ -118,5 +122,10 @@ BdApi.DOM = DOMAPI;
|
|||
*/
|
||||
BdApi.ContextMenu = ContextMenuAPI;
|
||||
|
||||
BdApi.Components = {
|
||||
get Tooltip() {return DiscordModules.Tooltip;}
|
||||
};
|
||||
|
||||
Object.freeze(BdApi);
|
||||
Object.freeze(BdApi.prototype);
|
||||
Object.freeze(BdApi.Components);
|
||||
|
|
|
@ -110,4 +110,4 @@ const Webpack = {
|
|||
Object.freeze(Webpack);
|
||||
Object.freeze(Webpack.Filters);
|
||||
|
||||
export default Webpack;
|
||||
export default Webpack;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import Utilities from "./utilities";
|
||||
import WebpackModules from "./webpackmodules";
|
||||
import WebpackModules, {Filters} from "./webpackmodules";
|
||||
|
||||
export default Utilities.memoizeObject({
|
||||
get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
|
||||
|
@ -154,5 +154,12 @@ export default Utilities.memoizeObject({
|
|||
return Object.assign({}, guildsWrapper, guilds, pill, listItem);
|
||||
},
|
||||
|
||||
get LayerStack() {return WebpackModules.getByProps("pushLayer");}
|
||||
get LayerStack() {return WebpackModules.getByProps("pushLayer");},
|
||||
|
||||
get Tooltip() {
|
||||
// Make fallback component just pass children, so it can at least render that.
|
||||
const fallback = props => props.children?.({}) ?? null;
|
||||
|
||||
return WebpackModules.getModule(Filters.byPrototypeFields(["renderTooltip"]), {searchExports: true}) ?? fallback;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import {React, WebpackModules, DiscordModules, Settings} from "modules";
|
||||
import {React, DiscordModules, Settings} from "modules";
|
||||
|
||||
import Checkbox from "./checkbox";
|
||||
|
||||
const Tooltip = WebpackModules.getByPrototypes("renderTooltip");
|
||||
const ThemeStore = DiscordModules.ThemeStore;
|
||||
|
||||
const languages = ["abap", "abc", "actionscript", "ada", "apache_conf", "asciidoc", "assembly_x86", "autohotkey", "batchfile", "bro", "c_cpp", "c9search", "cirru", "clojure", "cobol", "coffee", "coldfusion", "csharp", "csound_document", "csound_orchestra", "csound_score", "css", "curly", "d", "dart", "diff", "dockerfile", "dot", "drools", "dummy", "dummysyntax", "eiffel", "ejs", "elixir", "elm", "erlang", "forth", "fortran", "ftl", "gcode", "gherkin", "gitignore", "glsl", "gobstones", "golang", "graphqlschema", "groovy", "haml", "handlebars", "haskell", "haskell_cabal", "haxe", "hjson", "html", "html_elixir", "html_ruby", "ini", "io", "jack", "jade", "java", "javascript", "json", "jsoniq", "jsp", "jssm", "jsx", "julia", "kotlin", "latex", "less", "liquid", "lisp", "livescript", "logiql", "lsl", "lua", "luapage", "lucene", "makefile", "markdown", "mask", "matlab", "maze", "mel", "mushcode", "mysql", "nix", "nsis", "objectivec", "ocaml", "pascal", "perl", "pgsql", "php", "pig", "powershell", "praat", "prolog", "properties", "protobuf", "python", "r", "razor", "rdoc", "red", "rhtml", "rst", "ruby", "rust", "sass", "scad", "scala", "scheme", "scss", "sh", "sjs", "smarty", "snippets", "soy_template", "space", "sql", "sqlserver", "stylus", "svg", "swift", "tcl", "tex", "text", "textile", "toml", "tsx", "twig", "typescript", "vala", "vbscript", "velocity", "verilog", "vhdl", "wollok", "xml", "xquery", "yaml", "django"];
|
||||
|
@ -108,11 +107,11 @@ export default class CodeEditor extends React.Component {
|
|||
}
|
||||
|
||||
makeButton(button) {
|
||||
return <Tooltip color="primary" position="top" text={button.tooltip}>
|
||||
return <DiscordModules.Tooltip color="primary" position="top" text={button.tooltip}>
|
||||
{props => {
|
||||
return <button {...props} className="btn btn-primary" onClick={(event) => {button.onClick(event, this.value);}}>{button.label}</button>;
|
||||
}}
|
||||
</Tooltip>;
|
||||
</DiscordModules.Tooltip>;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -135,4 +134,4 @@ export default class CodeEditor extends React.Component {
|
|||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,17 +12,17 @@ export default class Modals {
|
|||
|
||||
static get ModalActions() {
|
||||
return this._ModalActions ??= {
|
||||
openModal: WebpackModules.getModule(m => m?.toString().includes("onCloseCallback") && m?.toString().includes("Layer"), {searchExports: true}),
|
||||
closeModal: WebpackModules.getModule(m => m?.toString().includes("onCloseCallback()"), {searchExports: true})
|
||||
openModal: WebpackModules.getModule(m => typeof m === "function" && m?.toString().includes("onCloseCallback") && m?.toString().includes("Layer"), {searchExports: true}),
|
||||
closeModal: WebpackModules.getModule(m => typeof m === "function" && m?.toString().includes("onCloseCallback()"), {searchExports: true})
|
||||
};
|
||||
}
|
||||
static get ModalStack() {return this._ModalStack ??= WebpackModules.getByProps("push", "update", "pop", "popWithKey");}
|
||||
static get ModalComponents() {return this._ModalComponents ??= WebpackModules.getByProps("Header", "Footer");}
|
||||
static get ModalRoot() {return this._ModalRoot ??= WebpackModules.getModule(m => m?.toString?.()?.includes("ENTERING"), {searchExports: true});}
|
||||
static get ModalRoot() {return this._ModalRoot ??= WebpackModules.getModule(m => m?.toString?.()?.includes("ENTERING") && m?.toString?.()?.includes("headerId"), {searchExports: true});}
|
||||
static get ModalClasses() {return this._ModalClasses ??= WebpackModules.getByProps("modal", "content");}
|
||||
static get FlexElements() {return this._FlexElements ??= WebpackModules.getByProps("Child", "Align");}
|
||||
static get TextElement() {return this._TextElement ??= WebpackModules.getModule(m => m?.Sizes?.SIZE_32 && m.Colors);}
|
||||
static get ConfirmationModal() {return this._ConfirmationModal ??= WebpackModules.getModule(m => m?.toString?.()?.includes(".confirmButtonColor"));}
|
||||
static get ConfirmationModal() {return this._ConfirmationModal ??= WebpackModules.getModule(m => m?.toString?.()?.includes(".confirmButtonColor"), {searchExports: true});}
|
||||
static get Markdown() {return this._Markdown ??= WebpackModules.find(m => m?.prototype?.render && m.rules);}
|
||||
static get Buttons() {return this._Buttons ??= WebpackModules.getModule(m => m.BorderColors, {searchExports: true});}
|
||||
static get ModalQueue() {return this._ModalQueue ??= [];}
|
||||
|
@ -30,10 +30,14 @@ export default class Modals {
|
|||
static get hasModalOpen() {return !!document.getElementsByClassName("bd-modal").length;}
|
||||
|
||||
static async initialize() {
|
||||
const names = ["ModalActions", "Markdown", "ModalRoot", "ModalComponents", "Buttons", "TextElement", "FlexElements"];
|
||||
const names = ["ConfirmationModal", "ModalActions", "Markdown", "ModalRoot", "ModalComponents", "Buttons", "TextElement", "FlexElements"];
|
||||
|
||||
for (const name of names) {
|
||||
const value = this[name];
|
||||
let value = this[name];
|
||||
|
||||
if (name === "ModalActions") {
|
||||
value = Object.keys(this.ModalActions).every(k => this.ModalActions[k]);
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
Logger.warn("Modals", `Missing ${name} module!`);
|
||||
|
|
|
@ -25,7 +25,6 @@ const LinkIcons = {
|
|||
patreon: PatreonIcon
|
||||
};
|
||||
|
||||
const Tooltip = WebpackModules.getByPrototypes("renderTooltip");
|
||||
const LayerManager = {
|
||||
pushLayer(component) {
|
||||
DiscordModules.Dispatcher.dispatch({
|
||||
|
@ -149,19 +148,19 @@ export default class AddonCard extends React.Component {
|
|||
}
|
||||
|
||||
makeButton(title, children, action) {
|
||||
return <Tooltip color="primary" position="top" text={title}>
|
||||
return <DiscordModules.Tooltip color="primary" position="top" text={title}>
|
||||
{(props) => {
|
||||
return <div {...props} className="bd-addon-button" onClick={action}>{children}</div>;
|
||||
}}
|
||||
</Tooltip>;
|
||||
</DiscordModules.Tooltip>;
|
||||
}
|
||||
|
||||
makeControlButton(title, children, action, {danger = false, disabled = false} = {}) {
|
||||
return <Tooltip color="primary" position="top" text={title}>
|
||||
return <DiscordModules.Tooltip color="primary" position="top" text={title}>
|
||||
{(props) => {
|
||||
return <button {...props} className={"bd-button bd-addon-button" + (danger ? " bd-button-danger" : "") + (disabled ? " bd-button-disabled" : "")} onClick={action}>{children}</button>;
|
||||
}}
|
||||
</Tooltip>;
|
||||
</DiscordModules.Tooltip>;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -192,4 +191,4 @@ Object.defineProperty(AddonCard.prototype, "render", {
|
|||
configurable: false,
|
||||
set: function() {Logger.warn("AddonCard", "Addon policy for plugins #5 https://github.com/BetterDiscord/BetterDiscord/wiki/Addon-Policies#plugins");},
|
||||
get: () => originalRender
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Logger from "common/logger";
|
||||
import {React, Strings, Events, WebpackModules, DataStore} from "modules";
|
||||
import {React, Strings, Events, DataStore, DiscordModules} from "modules";
|
||||
|
||||
import Modals from "../modals";
|
||||
import SettingsTitle from "./title";
|
||||
|
@ -13,8 +13,6 @@ import GridIcon from "../icons/grid";
|
|||
import NoResults from "../blankslates/noresults";
|
||||
import EmptyImage from "../blankslates/emptyimage";
|
||||
|
||||
const Tooltip = WebpackModules.getByPrototypes("renderTooltip");
|
||||
|
||||
export default class AddonList extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
|
@ -115,11 +113,11 @@ export default class AddonList extends React.Component {
|
|||
}
|
||||
|
||||
makeControlButton(title, children, action, selected = false) {
|
||||
return <Tooltip color="primary" position="top" text={title}>
|
||||
return <DiscordModules.Tooltip color="primary" position="top" text={title}>
|
||||
{(props) => {
|
||||
return <button {...props} className={"bd-button bd-view-button" + (selected ? " selected" : "")} onClick={action}>{children}</button>;
|
||||
}}
|
||||
</Tooltip>;
|
||||
</DiscordModules.Tooltip>;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -213,4 +211,4 @@ Object.defineProperty(AddonList.prototype, "render", {
|
|||
configurable: false,
|
||||
set: function() {Logger.warn("AddonList", "Addon policy for plugins #5 https://github.com/BetterDiscord/BetterDiscord/wiki/Addon-Policies#plugins");},
|
||||
get: () => originalRender
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import {React, WebpackModules} from "modules";
|
||||
|
||||
const TooltipWrapper = WebpackModules.getByPrototypes("renderTooltip");
|
||||
import {DiscordModules, React} from "modules";
|
||||
|
||||
const Checkmark = React.memo((props) => (
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" {...props}>
|
||||
|
@ -73,7 +71,7 @@ export default class Color extends React.Component {
|
|||
|
||||
return <div className="bd-color-picker-container">
|
||||
<div className="bd-color-picker-controls">
|
||||
<TooltipWrapper text="Default" position="bottom">
|
||||
<DiscordModules.Tooltip text="Default" position="bottom">
|
||||
{props => (
|
||||
<div {...props} className="bd-color-picker-default" style={{backgroundColor: resolveColor(defaultValue)}} onClick={() => this.onChange({target: {value: defaultValue}})}>
|
||||
{intValue === resolveColor(defaultValue, false)
|
||||
|
@ -82,15 +80,15 @@ export default class Color extends React.Component {
|
|||
}
|
||||
</div>
|
||||
)}
|
||||
</TooltipWrapper>
|
||||
<TooltipWrapper text="Custom Color" position="bottom">
|
||||
</DiscordModules.Tooltip>
|
||||
<DiscordModules.Tooltip text="Custom Color" position="bottom">
|
||||
{props => (
|
||||
<div className="bd-color-picker-custom">
|
||||
<Dropper color={getContrastColor(resolveColor(this.state.value, true))} />
|
||||
<input {...props} style={{backgroundColor: resolveColor(this.state.value)}} type="color" className="bd-color-picker" value={resolveColor(this.state.value)} onChange={this.onChange} />
|
||||
</div>
|
||||
)}
|
||||
</TooltipWrapper>
|
||||
</DiscordModules.Tooltip>
|
||||
</div>
|
||||
<div className="bd-color-picker-swatch">
|
||||
{
|
||||
|
@ -106,4 +104,4 @@ export default class Color extends React.Component {
|
|||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import {Changelog} from "data";
|
||||
import {React, WebpackModules} from "modules";
|
||||
import {DiscordModules, React} from "modules";
|
||||
import HistoryIcon from "../icons/history";
|
||||
import Modals from "../modals";
|
||||
|
||||
const Tooltip = WebpackModules.getByPrototypes("renderTooltip");
|
||||
|
||||
export default class SettingsTitle extends React.Component {
|
||||
renderHeader() {
|
||||
|
@ -13,13 +12,13 @@ export default class SettingsTitle extends React.Component {
|
|||
render() {
|
||||
return <div className="bd-sidebar-header">
|
||||
{this.renderHeader()}
|
||||
<Tooltip color="primary" position="top" text="Changelog">
|
||||
<DiscordModules.Tooltip color="primary" position="top" text="Changelog">
|
||||
{props =>
|
||||
<div {...props} className="bd-changelog-button" onClick={() => Modals.showChangelogModal(Changelog)}>
|
||||
<HistoryIcon className="bd-icon" size="16px" />
|
||||
</div>
|
||||
}
|
||||
</Tooltip>
|
||||
</DiscordModules.Tooltip>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue