Reduce reliance on internals
This commit is contained in:
parent
815d91e76f
commit
b5ad46a63f
|
@ -1,49 +0,0 @@
|
|||
import Utilities from "./utilities";
|
||||
import ClassName from "../structs/classname";
|
||||
import WebpackModules from "./webpackmodules";
|
||||
|
||||
const combineClasses = function (...props) {
|
||||
return Object.assign({}, ...props.map(prop => WebpackModules.getByProps(...prop)));
|
||||
};
|
||||
|
||||
const DiscordClassModules = Utilities.memoizeObject({
|
||||
get Text() {
|
||||
return combineClasses(
|
||||
["size20", "size12"],
|
||||
["selectable", "colorMuted"]
|
||||
);
|
||||
},
|
||||
get Titles() {
|
||||
return combineClasses(
|
||||
["wrapper", "base"],
|
||||
["defaultColor", "h4"]
|
||||
);
|
||||
},
|
||||
get EmptyImage() {return WebpackModules.getByProps("emptyImage", "emptyHeader");},
|
||||
get Modal() {return WebpackModules.getByProps("content", "root", "header", "close");},
|
||||
get Scrollers() {return WebpackModules.getByProps("thin", "scrollerBase", "content");},
|
||||
get Margins() {return WebpackModules.getByProps("marginXSmall", "marginBottom8");},
|
||||
get Integrations() {return WebpackModules.getByProps("secondaryHeader", "detailsWrapper");},
|
||||
get Card() {return WebpackModules.getByProps("card", "topDivider", "description");},
|
||||
});
|
||||
|
||||
const emptyClassModule = new Proxy({}, {
|
||||
get() {return "";}
|
||||
});
|
||||
|
||||
const DiscordClasses = new Proxy(DiscordClassModules, {
|
||||
get(list, item) {
|
||||
if (list[item] === undefined) return emptyClassModule;
|
||||
if (typeof(list[item]) === "string") return list[item];
|
||||
|
||||
return new Proxy(list[item], {
|
||||
get(obj, prop) {
|
||||
if (!(prop in obj)) return "";
|
||||
|
||||
return new ClassName(obj[prop]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default DiscordClasses;
|
|
@ -11,151 +11,13 @@ import WebpackModules, {Filters} from "./webpackmodules";
|
|||
export default Utilities.memoizeObject({
|
||||
get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
|
||||
get ReactDOM() {return WebpackModules.getByProps("render", "findDOMNode");},
|
||||
get Flux() {return WebpackModules.getByProps("connectStores");},
|
||||
get Events() {return WebpackModules.getByPrototypes("setMaxListeners", "emit");},
|
||||
|
||||
/* Guild Info, Stores, and Utilities */
|
||||
get GuildStore() {return WebpackModules.getByProps("getGuild");},
|
||||
get SortedGuildStore() {return WebpackModules.getByProps("getSortedGuilds");},
|
||||
get SelectedGuildStore() {return WebpackModules.getByProps("getLastSelectedGuildId");},
|
||||
get GuildSync() {return WebpackModules.getByProps("getSyncedGuilds");},
|
||||
get GuildInfo() {return WebpackModules.getByProps("getAcronym");},
|
||||
get GuildChannelsStore() {return WebpackModules.getByProps("getChannels", "getDefaultChannel");},
|
||||
get GuildMemberStore() {return WebpackModules.getByProps("getMember");},
|
||||
get MemberCountStore() {return WebpackModules.getByProps("getMemberCounts");},
|
||||
get GuildEmojiStore() {return WebpackModules.getByProps("getEmojis");},
|
||||
get GuildActions() {return WebpackModules.getByProps("markGuildAsRead");},
|
||||
get GuildPermissions() {return WebpackModules.getByProps("getGuildPermissions");},
|
||||
|
||||
/* Channel Store & Actions */
|
||||
get ChannelStore() {return WebpackModules.getByProps("getChannel", "getDMFromUserId");},
|
||||
get SelectedChannelStore() {return WebpackModules.getByProps("getLastSelectedChannelId");},
|
||||
get ChannelActions() {return WebpackModules.getByProps("selectChannel");},
|
||||
get PrivateChannelActions() {return WebpackModules.getByProps("openPrivateChannel");},
|
||||
get ChannelSelector() {return WebpackModules.getByProps("selectGuild", "selectChannel");},
|
||||
|
||||
/* Current User Info, State and Settings */
|
||||
get UserInfoStore() {return WebpackModules.getByProps("getToken");},
|
||||
get LocaleStore() {return WebpackModules.getByProps("locale", "initialize");},
|
||||
get ThemeStore() {return WebpackModules.getByProps("theme", "initialize");},
|
||||
get AccountManager() {return WebpackModules.getByProps("register", "login");},
|
||||
get UserSettingsUpdater() {return WebpackModules.getByProps("updateRemoteSettings");},
|
||||
get OnlineWatcher() {return WebpackModules.getByProps("isOnline");},
|
||||
get CurrentUserIdle() {return WebpackModules.getByProps("getIdleTime");},
|
||||
get RelationshipStore() {return WebpackModules.getByProps("isBlocked", "getFriendIDs");},
|
||||
get RelationshipManager() {return WebpackModules.getByProps("addRelationship");},
|
||||
get MentionStore() {return WebpackModules.getByProps("getMentions");},
|
||||
|
||||
/* User Stores and Utils */
|
||||
get UserStore() {return WebpackModules.getByProps("getCurrentUser", "getUser");},
|
||||
get UserStatusStore() {return WebpackModules.getByProps("getStatus", "getState");},
|
||||
get UserTypingStore() {return WebpackModules.getByProps("isTyping");},
|
||||
get UserActivityStore() {return WebpackModules.getByProps("getActivity");},
|
||||
get UserNameResolver() {return WebpackModules.getByProps("getName");},
|
||||
get UserNoteStore() {return WebpackModules.getByProps("getNote");},
|
||||
get UserNoteActions() {return WebpackModules.getByProps("updateNote");},
|
||||
|
||||
/* Emoji Store and Utils */
|
||||
get EmojiInfo() {return WebpackModules.getByProps("isEmojiDisabled");},
|
||||
get EmojiUtils() {return WebpackModules.getByProps("getGuildEmoji");},
|
||||
get EmojiStore() {return WebpackModules.getByProps("getByCategory", "EMOJI_NAME_RE");},
|
||||
|
||||
/* Invite Store and Utils */
|
||||
get InviteStore() {return WebpackModules.getByProps("getInvites");},
|
||||
get InviteResolver() {return WebpackModules.getByProps("findInvite");},
|
||||
get InviteActions() {return WebpackModules.getByProps("acceptInvite");},
|
||||
|
||||
/* Discord Objects & Utils */
|
||||
get DiscordConstants() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes");},
|
||||
get DiscordPermissions() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes").Permissions;},
|
||||
get PermissionUtils() {return WebpackModules.getByProps("getHighestRole");},
|
||||
get ColorConverter() {return WebpackModules.getByProps("hex2int");},
|
||||
get ColorShader() {return WebpackModules.getByProps("darken");},
|
||||
get TinyColor() {return WebpackModules.getByPrototypes("toRgb");},
|
||||
get ClassResolver() {return WebpackModules.getByProps("getClass");},
|
||||
get ButtonData() {return WebpackModules.getByProps("ButtonSizes");},
|
||||
get IconNames() {return WebpackModules.getByProps("IconNames");},
|
||||
get NavigationUtils() {return WebpackModules.getByProps("transitionTo", "replaceWith", "getHistory");},
|
||||
|
||||
/* Discord Messages */
|
||||
get MessageStore() {return WebpackModules.getByProps("getMessages");},
|
||||
get MessageActions() {return WebpackModules.getByProps("jumpToMessage", "_sendMessage");},
|
||||
get MessageQueue() {return WebpackModules.getByProps("enqueue");},
|
||||
get MessageParser() {return WebpackModules.getByProps("createMessage", "parse", "unparse");},
|
||||
|
||||
/* Text Processing */
|
||||
get hljs() {return WebpackModules.getByProps("highlight", "highlightBlock");},
|
||||
get SimpleMarkdown() {return WebpackModules.getByProps("parseBlock", "parseInline", "defaultOutput");},
|
||||
|
||||
/* Experiments */
|
||||
get ExperimentStore() {return WebpackModules.getByProps("getExperimentOverrides");},
|
||||
get ExperimentsManager() {return WebpackModules.getByProps("isDeveloper");},
|
||||
get CurrentExperiment() {return WebpackModules.getByProps("getExperimentId");},
|
||||
|
||||
/* Images, Avatars and Utils */
|
||||
get ImageResolver() {return WebpackModules.getByProps("getUserAvatarURL", "getGuildIconURL");},
|
||||
get ImageUtils() {return WebpackModules.getByProps("getSizedImageSrc");},
|
||||
get AvatarDefaults() {return WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");},
|
||||
|
||||
/* Window, DOM, HTML */
|
||||
get WindowInfo() {return WebpackModules.getByProps("isFocused", "windowSize");},
|
||||
get TagInfo() {return WebpackModules.getByProps("VALID_TAG_NAMES");},
|
||||
get DOMInfo() {return WebpackModules.getByProps("canUseDOM");},
|
||||
|
||||
/* Locale/Location and Time */
|
||||
get LocaleManager() {return WebpackModules.getByProps("setLocale");},
|
||||
get Moment() {return WebpackModules.getByProps("parseZone");},
|
||||
get LocationManager() {return WebpackModules.getByProps("createLocation");},
|
||||
get Timestamps() {return WebpackModules.getByProps("fromTimestamp");},
|
||||
get TimeFormatter() {return WebpackModules.getByProps("dateFormat");},
|
||||
|
||||
/* Strings and Utils */
|
||||
get Strings() {return WebpackModules.getByProps("Messages").Messages;},
|
||||
get StringFormats() {return WebpackModules.getByProps("a", "z");},
|
||||
get StringUtils() {return WebpackModules.getByProps("toASCII");},
|
||||
|
||||
/* URLs and Utils */
|
||||
get URLParser() {return WebpackModules.getByProps("Url", "parse");},
|
||||
get ExtraURLs() {return WebpackModules.getByProps("getArticleURL");},
|
||||
|
||||
/* Drag & Drop */
|
||||
get DNDActions() {return WebpackModules.getByProps("beginDrag");},
|
||||
get DNDSources() {return WebpackModules.getByProps("addTarget");},
|
||||
get DNDObjects() {return WebpackModules.getByProps("DragSource");},
|
||||
|
||||
/* Media Stuff (Audio/Video) */
|
||||
get MediaDeviceInfo() {return WebpackModules.getByProps("Codecs", "SUPPORTED_BROWSERS");},
|
||||
get MediaInfo() {return WebpackModules.getByProps("getOutputVolume");},
|
||||
get MediaEngineInfo() {return WebpackModules.getByProps("MediaEngineFeatures");},
|
||||
get VoiceInfo() {return WebpackModules.getByProps("EchoCancellation");},
|
||||
get VideoStream() {return WebpackModules.getByProps("getVideoStream");},
|
||||
get SoundModule() {return WebpackModules.getByProps("playSound");},
|
||||
|
||||
/* Electron & Other Internals with Utils*/
|
||||
get ElectronModule() {return WebpackModules.getByProps("setBadge");},
|
||||
get Dispatcher() {return WebpackModules.getByProps("dispatch", "subscribe", "register");},
|
||||
get PathUtils() {return WebpackModules.getByProps("hasBasename");},
|
||||
get NotificationModule() {return WebpackModules.getByProps("showNotification");},
|
||||
get RouterModule() {return WebpackModules.getByProps("Router");},
|
||||
get APIModule() {return WebpackModules.getByProps("getAPIBaseURL");},
|
||||
get AnalyticEvents() {return WebpackModules.getByProps("AnalyticEventConfigs");},
|
||||
get KeyGenerator() {return WebpackModules.getByRegex(/"binary"/);},
|
||||
get Buffers() {return WebpackModules.getByProps("INSPECT_MAX_BYTES", "kMaxLength");},
|
||||
get DeviceStore() {return WebpackModules.getByProps("getDevices");},
|
||||
get SoftwareInfo() {return WebpackModules.getByProps("os");},
|
||||
get CurrentContext() {return WebpackModules.getByProps("setTagsContext");},
|
||||
|
||||
/* Commonly Used Classes */
|
||||
get GuildClasses() {
|
||||
const guildsWrapper = WebpackModules.getByProps("base", "guilds");
|
||||
const guilds = WebpackModules.getByProps("wrapper", "acronym");
|
||||
const pill = WebpackModules.getByProps("circleIconButton");
|
||||
const listItem = WebpackModules.getModule(m => m.listItem && !m.pill && !m.sidebar);
|
||||
return Object.assign({}, guildsWrapper, guilds, pill, listItem);
|
||||
},
|
||||
|
||||
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;
|
||||
|
|
|
@ -14,5 +14,4 @@ export {default as Patcher} from "./patcher";
|
|||
export {default as LocaleManager} from "./localemanager";
|
||||
export {default as Strings} from "./strings";
|
||||
export {default as IPC} from "./ipc";
|
||||
export {default as Logger} from "common/logger";
|
||||
export {default as DiscordClasses} from "./discordclasses";
|
||||
export {default as Logger} from "common/logger";
|
|
@ -1,50 +0,0 @@
|
|||
// import Selector from "./selector";
|
||||
|
||||
/**
|
||||
* Representation of a Class Name
|
||||
**/
|
||||
class ClassName {
|
||||
/**
|
||||
*
|
||||
* @param {string} name - name of the class to represent
|
||||
*/
|
||||
constructor(name) {
|
||||
this.value = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates new class names to the current one using spaces.
|
||||
* @param {string} classNames - list of class names to add to this class name
|
||||
* @returns {ClassName} returns self to allow chaining
|
||||
*/
|
||||
add(...classNames) {
|
||||
for (let i = 0; i < classNames.length; i++) this.value += " " + classNames[i];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw class name, this is how native function get the value.
|
||||
* @returns {string} raw class name.
|
||||
*/
|
||||
toString() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw class name, this is how native function get the value.
|
||||
* @returns {string} raw class name.
|
||||
*/
|
||||
valueOf() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
get single() {
|
||||
return this.value.split(" ")[0];
|
||||
}
|
||||
|
||||
get first() {
|
||||
return this.value.split(" ")[0];
|
||||
}
|
||||
}
|
||||
|
||||
export default ClassName;
|
|
@ -78,4 +78,16 @@
|
|||
scrollbar-color: var(--background-tertiary) var(--background-secondary);
|
||||
background: var(--background-secondary);
|
||||
border: 1px solid var(--background-tertiary);
|
||||
}
|
||||
|
||||
.bd-addon-error-details {
|
||||
display: flex;
|
||||
flex-grow: 0;
|
||||
justify-content: flex-start;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.bd-addon-error-details-icon {
|
||||
margin-right: 4px;
|
||||
color: var(--interactive-normal);
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
import {React, DiscordClasses} from "modules";
|
||||
import {React, WebpackModules} from "modules";
|
||||
import SimpleMarkdown from "../../structs/markdown";
|
||||
|
||||
const EmptyImageClasses = WebpackModules.getByProps("emptyImage", "emptyHeader") ?? {emptyContainer: "emptyContainer-poti7J", emptyImage: "emptyImage-2pCD2j", emptyHeader: "emptyHeader-2cxTFP"};
|
||||
|
||||
export default function EmptyImage(props) {
|
||||
return <div className={`bd-empty-image-container ${DiscordClasses.EmptyImage.emptyContainer}` + (props.className ? ` ${props.className}` : "")}>
|
||||
<div className={`bd-empty-image ${DiscordClasses.EmptyImage.emptyImage}`}></div>
|
||||
<div className={`bd-empty-image-header ${DiscordClasses.EmptyImage.emptyHeader}`}>
|
||||
return <div className={`bd-empty-image-container ${EmptyImageClasses.emptyContainer}` + (props.className ? ` ${props.className}` : "")}>
|
||||
<div className={`bd-empty-image ${EmptyImageClasses.emptyImage}`}></div>
|
||||
<div className={`bd-empty-image-header ${EmptyImageClasses.emptyHeader}`}>
|
||||
{props.title || "You don't have anything!"}
|
||||
</div>
|
||||
<div className={`bd-empty-image-message`}>
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Config} from "data";
|
|||
import Logger from "common/logger";
|
||||
import {WebpackModules, React, ReactDOM, Settings, Strings, DOMManager} from "modules";
|
||||
import FormattableString from "../structs/string";
|
||||
import AddonErrorModal from "./addonerrormodal";
|
||||
import AddonErrorModal from "./modals/addonerrormodal";
|
||||
import ErrorBoundary from "./errorboundary";
|
||||
import TextElement from "./base/text";
|
||||
import ModalRoot from "./modals/root";
|
||||
|
@ -198,29 +198,15 @@ export default class Modals {
|
|||
static showAddonErrors({plugins: pluginErrors = [], themes: themeErrors = []}) {
|
||||
if (!pluginErrors || !themeErrors || !this.shouldShowAddonErrors) return;
|
||||
if (!pluginErrors.length && !themeErrors.length) return;
|
||||
|
||||
if (this.addonErrorsRef && this.addonErrorsRef.current) {
|
||||
return this.addonErrorsRef.current.refreshTabs(Array.isArray(pluginErrors) ? pluginErrors : [], Array.isArray(themeErrors) ? themeErrors : []);
|
||||
}
|
||||
|
||||
this.addonErrorsRef = React.createRef();
|
||||
this.ModalActions.openModal(props => React.createElement(ErrorBoundary, null, React.createElement(ModalRoot, Object.assign(props, {
|
||||
size: ModalRoot.Sizes.MEDIUM,
|
||||
className: "bd-error-modal",
|
||||
children: [
|
||||
React.createElement(AddonErrorModal, {
|
||||
ref: this.addonErrorsRef,
|
||||
pluginErrors: Array.isArray(pluginErrors) ? pluginErrors : [],
|
||||
themeErrors: Array.isArray(themeErrors) ? themeErrors : [],
|
||||
onClose: props.onClose
|
||||
}),
|
||||
React.createElement(ModalFooter, {
|
||||
className: "bd-error-modal-footer",
|
||||
}, React.createElement(Button, {
|
||||
onClick: props.onClose
|
||||
}, Strings.Modals.okay))
|
||||
]
|
||||
}))));
|
||||
const options = {
|
||||
ref: this.addonErrorsRef,
|
||||
pluginErrors: Array.isArray(pluginErrors) ? pluginErrors : [],
|
||||
themeErrors: Array.isArray(themeErrors) ? themeErrors : []
|
||||
};
|
||||
this.ModalActions.openModal(props => {
|
||||
return React.createElement(ErrorBoundary, null, React.createElement(AddonErrorModal, Object.assign(options, props)));
|
||||
});
|
||||
}
|
||||
|
||||
static showChangelogModal(options = {}) {
|
||||
|
@ -253,7 +239,7 @@ export default class Modals {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) return null;
|
||||
if (this.state.hasError) return React.createElement(TextElement, {color: TextElement.Colors.STATUS_RED}, Strings.Addons.settingsError);
|
||||
const props = {
|
||||
className: "bd-addon-settings-wrap",
|
||||
ref: this.elementRef
|
||||
|
@ -265,22 +251,16 @@ export default class Modals {
|
|||
}
|
||||
if (typeof(child) === "function") child = React.createElement(child);
|
||||
|
||||
const modal = props => {
|
||||
return React.createElement(ErrorBoundary, {}, React.createElement(ModalRoot, Object.assign({size: ModalRoot.Sizes.MEDIUM, className: "bd-addon-modal" + " " + ModalRoot.Sizes.MEDIUM}, props),
|
||||
React.createElement(ModalHeader, null,
|
||||
React.createElement(TextElement, {tag: "h1", size: TextElement.Sizes.SIZE_20, strong: true}, `${name} Settings`)
|
||||
),
|
||||
React.createElement(ModalContent, null,
|
||||
React.createElement(ErrorBoundary, {}, child)
|
||||
),
|
||||
React.createElement(ModalFooter, null,
|
||||
React.createElement(Button, {onClick: props.onClose}, Strings.Modals.done)
|
||||
)
|
||||
));
|
||||
const options = {
|
||||
className: "bd-addon-modal",
|
||||
size: ModalRoot.Sizes.MEDIUM,
|
||||
header: `${name} Settings`,
|
||||
cancelText: null,
|
||||
confirmText: Strings.Modals.done
|
||||
};
|
||||
|
||||
return this.ModalActions.openModal(props => {
|
||||
return React.createElement(ErrorBoundary, null, React.createElement(modal, props));
|
||||
return React.createElement(ErrorBoundary, null, React.createElement(ConfirmationModal, Object.assign(options, props), child));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import {React, Strings, WebpackModules, DiscordClasses} from "modules";
|
||||
import Extension from "./icons/extension";
|
||||
import ThemeIcon from "./icons/theme";
|
||||
import Divider from "./divider";
|
||||
import {React, Strings, WebpackModules} from "modules";
|
||||
import Extension from "../icons/extension";
|
||||
import ThemeIcon from "../icons/theme";
|
||||
import Divider from "../divider";
|
||||
import Text from "../base/text";
|
||||
import Header from "./header";
|
||||
import Content from "./content";
|
||||
import Flex from "../base/flex";
|
||||
import ModalRoot from "./root";
|
||||
import Footer from "./footer";
|
||||
import Button from "../base/button";
|
||||
|
||||
|
||||
const Parser = Object(WebpackModules.getByProps("defaultRules", "parse")).defaultRules;
|
||||
|
@ -30,12 +37,12 @@ function AddonError({err, index}) {
|
|||
{err.type == "plugin" ? <Extension /> : <ThemeIcon />}
|
||||
</div>
|
||||
<div className="bd-addon-error-header-inner">
|
||||
<h3 className={`bd-addon-error-file ${DiscordClasses.Text.colorHeaderPrimary} ${DiscordClasses.Integrations.secondaryHeader} ${DiscordClasses.Text.size16}`}>{err.name}</h3>
|
||||
<div className={`bd-addon-error-details ${DiscordClasses.Integrations.detailsWrapper}`}>
|
||||
<svg className={DiscordClasses.Integrations.detailsIcon} aria-hidden="false" width="16" height="16" viewBox="0 0 12 12">
|
||||
<Text tag="h3" size={Text.Sizes.SIZE_16} color={Text.Colors.HEADER_PRIMARY} strong={true}>{err.name}</Text>
|
||||
<div className="bd-addon-error-details">
|
||||
<svg className="bd-addon-error-details-icon" aria-hidden="false" width="16" height="16" viewBox="0 0 12 12">
|
||||
<path fill="currentColor" d="M6 1C3.243 1 1 3.244 1 6c0 2.758 2.243 5 5 5s5-2.242 5-5c0-2.756-2.243-5-5-5zm0 2.376a.625.625 0 110 1.25.625.625 0 010-1.25zM7.5 8.5h-3v-1h1V6H5V5h1a.5.5 0 01.5.5v2h1v1z"></path>
|
||||
</svg>
|
||||
<div className={`${DiscordClasses.Text.colorHeaderSecondary} ${DiscordClasses.Text.size12}`}>{err.message}</div>
|
||||
<Text color={Text.Colors.HEADER_SECONDARY} size={Text.Sizes.SIZE_12}>{err.message}</Text>
|
||||
</div>
|
||||
</div>
|
||||
<svg className="bd-addon-error-expander" width="24" height="24" viewBox="0 0 24 24">
|
||||
|
@ -51,7 +58,7 @@ function generateTab(id, errors) {
|
|||
return {id, errors, name: Strings.Panels[id]};
|
||||
}
|
||||
|
||||
export default function AddonErrorModal({pluginErrors, themeErrors}) {
|
||||
export default function AddonErrorModal({transitionState, onClose, pluginErrors, themeErrors}) {
|
||||
const tabs = useMemo(() => {
|
||||
return [
|
||||
pluginErrors.length && generateTab("plugins", pluginErrors),
|
||||
|
@ -63,17 +70,22 @@ export default function AddonErrorModal({pluginErrors, themeErrors}) {
|
|||
const switchToTab = useCallback((id) => setTab(id), []);
|
||||
const selectedTab = tabs.find(e => e.id === tabId);
|
||||
|
||||
return <>
|
||||
<div className={`bd-error-modal-header ${DiscordClasses.Modal.header} ${DiscordClasses.Modal.separator}`}>
|
||||
<h4 className={`${DiscordClasses.Titles.defaultColor} ${DiscordClasses.Text.size14} ${DiscordClasses.Titles.h4} ${DiscordClasses.Margins.marginBottom8}`}>{Strings.Modals.addonErrors}</h4>
|
||||
<div className="bd-tab-bar">
|
||||
{tabs.map(tab => <div onClick={() => {switchToTab(tab.id);}} className={joinClassNames("bd-tab-item", tab.id === selectedTab.id && "selected")}>{tab.name}</div>)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`bd-error-modal-content ${DiscordClasses.Modal.content} ${DiscordClasses.Scrollers.thin}`}>
|
||||
<div className="bd-addon-errors">
|
||||
{selectedTab.errors.map((error, index) => <AddonError index={index} err={error} />)}
|
||||
</div>
|
||||
</div>
|
||||
</>;
|
||||
return <ModalRoot transitionState={transitionState} className="bd-error-modal" size={ModalRoot.Sizes.MEDIUM}>
|
||||
<Header className="bd-error-modal-header">
|
||||
<Flex direction={Flex.Direction.VERTICAL}>
|
||||
<Text tag="h1" size={Text.Sizes.SIZE_14} color={Text.Colors.HEADER_PRIMARY} strong={true} style={{"text-transform": "uppercase", "margin-bottom": "8px"}}>{Strings.Modals.addonErrors}</Text>
|
||||
<div className="bd-tab-bar">
|
||||
{tabs.map(tab => <div onClick={() => {switchToTab(tab.id);}} className={joinClassNames("bd-tab-item", tab.id === selectedTab.id && "selected")}>{tab.name}</div>)}
|
||||
</div>
|
||||
</Flex>
|
||||
</Header>
|
||||
<Content className="bd-error-modal-content">
|
||||
<div className="bd-addon-errors">
|
||||
{selectedTab.errors.map((error, index) => <AddonError index={index} err={error} />)}
|
||||
</div>
|
||||
</Content>
|
||||
<Footer className="bd-error-modal-footer">
|
||||
<Button onClick={onClose}>{Strings.Modals.okay}</Button>
|
||||
</Footer>
|
||||
</ModalRoot>;
|
||||
}
|
|
@ -47,7 +47,7 @@ export default function ChangelogModal({transitionState, footer, title, subtitle
|
|||
const entry = changes[c];
|
||||
const type = "bd-changelog-" + entry.type;
|
||||
const margin = c == 0 ? " bd-changelog-first" : "";
|
||||
items.push(<h1 className={`bd-changelog-title ${type}${margin}`}>entry.title</h1>);
|
||||
items.push(<h1 className={`bd-changelog-title ${type}${margin}`}>{entry.title}</h1>);
|
||||
if (entry.description) items.push(<p>{SimpleMarkdownExt.parseToReact(entry.description)}</p>);
|
||||
const list = <ul>{entry.items.map(i => <li>{SimpleMarkdownExt.parseToReact(i)}</li>)}</ul>;
|
||||
items.push(list);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {React} from "modules";
|
||||
import {React, Strings} from "modules";
|
||||
import Root from "./root";
|
||||
import Header from "./header";
|
||||
import Footer from "./footer";
|
||||
|
@ -10,7 +10,7 @@ import Button from "../base/button";
|
|||
const {useRef, useEffect} = React;
|
||||
|
||||
|
||||
export default function ConfirmationModal({transitionState, onClose, header, children, danger = false, onCancel = () => {}, onConfirm = () => {}, cancelText = "Cancel", confirmText = "Okay"}) {
|
||||
export default function ConfirmationModal({transitionState, onClose, className, size = Root.Sizes.SMALL, header, children, danger = false, onCancel = () => {}, onConfirm = () => {}, cancelText = Strings.Modals.cancel, confirmText = Strings.Modals.okay}) {
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => buttonRef?.current?.focus?.(), 0);
|
||||
|
@ -19,8 +19,10 @@ export default function ConfirmationModal({transitionState, onClose, header, chi
|
|||
const buttonRef = useRef(null);
|
||||
|
||||
|
||||
return <Root transitionState={transitionState} size={Root.Sizes.SMALL}>
|
||||
<Header><Text tag="h1" size={Text.Sizes.SIZE_20} color={Text.Colors.HEADER_PRIMARY} strong={true}>{header}</Text></Header>
|
||||
return <Root transitionState={transitionState} size={size} className={className}>
|
||||
<Header>
|
||||
<Text tag="h1" size={Text.Sizes.SIZE_20} color={Text.Colors.HEADER_PRIMARY} strong={true}>{header}</Text>
|
||||
</Header>
|
||||
<Content>{children}</Content>
|
||||
<Footer>
|
||||
{confirmText && <Button
|
||||
|
|
|
@ -2,7 +2,7 @@ import {React, Utilities} from "modules";
|
|||
import Flex from "../base/flex";
|
||||
|
||||
|
||||
export default function Header({id, className, children}) {
|
||||
export default function Footer({id, className, children}) {
|
||||
return <Flex
|
||||
id={id}
|
||||
className={Utilities.className("bd-modal-footer", className)}
|
||||
|
|
Loading…
Reference in New Issue