Start removing discord modules from the store

This commit is contained in:
Tropical 2022-08-06 16:38:50 -04:00
parent 402d25af32
commit 8db9a22aae
12 changed files with 285 additions and 84 deletions

View File

@ -1,6 +1,6 @@
import {Web} from "data";
import Logger from "common/Logger";
import Logger from "common/logger";
import Utilities from "./utilities";
import Strings from "./strings";

View File

@ -70,7 +70,7 @@
/* Sizes */
.bd-searchbar.small input {
.bd-searchbar.size-small input {
height: 20px;
font-size: 14px;
font-weight: 500;
@ -78,46 +78,46 @@
padding: 0 4px;
}
.bd-searchbar.small .bd-search-icon {
.bd-searchbar.size-small .bd-search-icon {
width: 22px;
height: 22px;
}
.bd-searchbar.small svg {
.bd-searchbar.size-small svg {
width: 16px;
height: 16px;
}
.bd-searchbar.medium input {
.bd-searchbar.size-medium input {
height: 30px;
line-height: 32px;
font-size: 16px;
padding: 0 8px;
}
.bd-searchbar.medium .bd-search-icon {
.bd-searchbar.size-medium .bd-search-icon {
width: 32px;
height: 32px;
}
.bd-searchbar.medium svg {
.bd-searchbar.size-medium svg {
width: 20px;
height: 20px;
}
.bd-searchbar.large input {
.bd-searchbar.size-large input {
height: 38px;
line-height: 40px;
font-size: 20px;
padding: 0 16px;
}
.bd-searchbar.large .bd-search-icon {
.bd-searchbar.size-large .bd-search-icon {
width: 40px;
height: 40px;
}
.bd-searchbar.large svg {
.bd-searchbar.size-large svg {
width: 24px;
height: 24px;
}

View File

@ -1,34 +1,15 @@
.bd-spinner {
width: 32px;
height: 32px;
position: relative;
@keyframes bd-spinner-rotate {
to {
transform: rotate(1turn);
}
}
.bd-cube1,
.bd-cube2 {
background-color: #3E82E5;
width: 10px;
height: 10px;
position: absolute;
top: 0;
left: 0;
animation: bd-sk-cubemove 1.8s infinite ease-in-out;
}
.bd-cube2 {
animation-delay: -0.9s;
}
@keyframes bd-sk-cubemove {
@keyframes bd-spinner-wandering-cubes {
25% {
transform: translateX(22px) rotate(-90deg) scale(0.5);
transform: translateX(22px) rotate(-90deg) scale(.5);
}
50% {
transform: translateX(22px) translateY(22px) rotate(-179deg);
}
50.1% {
transform: translateX(22px) translateY(22px) rotate(-180deg);
}
@ -36,7 +17,191 @@
transform: translateX(0) translateY(22px) rotate(-270deg) scale(0.5);
}
100% {
transform: rotate(-360deg);
to {
transform: rotate(-1turn);
}
}
@keyframes bd-spinner-chasing-dots-bounce {
0%,
to {
transform: scale(0);
}
50% {
transform: scale(1);
}
}
@keyframes bd-spinner-pulsing-ellipsis {
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(0.8);
opacity: 0.3;
}
to {
transform: scale(1);
opacity: 1;
}
}
@keyframes bd-spinner-spinning-circle-dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0
}
50% {
stroke-dasharray: 130, 200
}
to {
stroke-dasharray: 130, 200;
stroke-dashoffset: -124;
}
}
@keyframes bd-spinner-low-motion {
0% {
opacity: 1;
}
50% {
opacity: 0.6
}
to {
opacity: 1;
}
}
.bd-spinner {
display: flex;
justify-content: center;
align-items: center;
}
.bd-spinner-inner {
position: relative;
display: inline-block;
width: 32px;
height: 32px;
contain: paint;
}
.bd-spinner-wandering-cubes .bd-spinner-item {
content: "";
background-color: var(--brand-experiment-400);
width: 10px;
height: 10px;
position: absolute;
top: 0;
left: 0;
animation: bd-spinner-wandering-cubes 1.8s ease-in-out infinite;
}
.bd-spinner-wandering-cubes .bd-spinner-item:last-of-type {
animation-delay: -0.9s;
}
.bd-spinner-chasing-dots .bd-spinner-inner {
animation: bd-spinner-rotate 2s linear infinite;
}
.bd-spinner-chasing-dots .bd-spinner-item {
width: 60%;
height: 60%;
display: inline-block;
position: absolute;
top: 0;
background-color: var(--brand-experiment, hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%));
border-radius: 100%;
animation: bd-spinner-chasing-dots-bounce 2s ease-in-out infinite;
}
.bd-spinner-chasing-dots .bd-spinner-item:last-of-type {
top: auto;
bottom: 0;
animation-delay: -1s;
}
.bd-spinner-pulsing-ellipsis .bd-spinner-inner {
height: auto;
width: 28px;
display: flex;
justify-content: center;
position: relative;
}
.bd-spinner-pulsing-ellipsis .bd-spinner-item,
.bd-spinner-low-motion .bd-spinner-item {
width: 6px;
height: 6px;
margin-right: 2px;
border-radius: 3px;
display: inline-block;
opacity: 0.3;
}
.bd-spinner-pulsing-ellipsis .bd-spinner-item {
animation: bd-spinner-pulsing-ellipsis 1.4s ease-in-out infinite;
background-color: hsl(180, calc(var(--saturation-factor, 1) * 7.7%), 97.5%);
}
.bd-spinner-pulsing-ellipsis .bd-spinner-item:nth-of-type(2) {
animation-delay: 0.2s;
}
.bd-spinner-pulsing-ellipsis .bd-spinner-item:nth-of-type(3) {
animation-delay: 0.4s;
}
.bd-spinner-spinning-circle {
transform: rotate(280deg);
}
.bd-spinner-circular {
animation: bd-spinner-rotate 2s linear infinite;
height: 100%;
width: 100%;
}
.bd-spinner-circular circle {
stroke: var(--brand-experiment, hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%));
animation: bd-spinner-spinning-circle-dash 2s ease-in-out infinite;
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
fill: none;
stroke-width: 6;
stroke-miterlimit: 10;
stroke-linecap: round;
}
.bd-spinner-circular circle:first-of-type {
animation-delay: 0.23s;
stroke: var(--brand-experiment-800, hsl(235, calc(var(--saturation-factor, 1) * 47.5%), 19.4%));
}
.bd-spinner-circular circle:nth-of-type(2) {
opacity: 0.6;
animation-delay: 0.15s;
}
.bd-spinner-low-motion .bd-spinner-item {
background-color: var(--interactive-normal);
animation: bd-spinner-low-motion 1.4s ease-in-out infinite;
}
.bd-spinner-low-motion .bd-spinner-item:nth-of-type(2) {
animation-delay: 0.2s;
}
.bd-spinner-low-motion .bd-spinner-item:nth-of-type(3) {
animation-delay: 0.4s;
}

View File

@ -194,7 +194,7 @@
.bd-addon-store .bd-store-card .bd-card-tags span.selected {
color: #fff;
background-color: var(--brand-experiment, #5865f2);
background-color: var(--brand-experiment, hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%));;
}
.bd-card-tags span:last-child {
@ -385,7 +385,7 @@
.bd-page-item.selected {
color: #fff;
background-color: var(--brand-experiment, #5865f2);
background-color: var(--brand-experiment, hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%));;
}
/* Tags Bar */
@ -427,7 +427,7 @@
.theme-dark .bd-store-tags span.selected,
.theme-light .bd-store-tags span.selected {
background-color: var(--brand-experiment, #5865f2);
background-color: var(--brand-experiment, hsl(235, calc(var(--saturation-factor, 1) * 85.6%), 64.7%));;
color: #fff;
}
@ -578,7 +578,16 @@
}
.bd-installation-name {
font-size: 16px;
font-weight: 600;
line-height: 20px;
color: var(--header-primary);
}
.bd-installation-subtitle {
font-size: 14px;
line-height: 18px;
color: var(--header-secondary);
}
.bd-installation-info {
@ -600,6 +609,10 @@
word-break: break-word;
}
.bd-installation-info li a:hover {
text-decoration: underline;
}
.bd-installation-info li .bd-info-icon {
display: inline-flex;
flex: 0 0 auto;
@ -618,7 +631,7 @@
}
#bd-info-description {
--bd-info-icon-color: var(--brand-experiment-360, #949cf7);
--bd-info-icon-color: var(--brand-experiment-360, hsl(235, calc(var(--saturation-factor, 1) * 86.1%), 77.5%));
}
#bd-info-version {

View File

@ -2,7 +2,7 @@ import {React, Strings, WebpackModules, DiscordClasses, Utilities} from "modules
import Extension from "./icons/extension";
import ThemeIcon from "./icons/theme";
import Divider from "./divider";
import TabBar from "./settings/components/tabbar";
import TabBar from "./tabbar";
const Parser = Object(WebpackModules.getByProps("defaultRules", "parse")).defaultRules;

View File

@ -1,6 +1,7 @@
import {DiscordClasses, React, Strings, Utilities, WebpackModules} from "modules";
import {React, Strings, WebpackModules} from "modules";
import {Web} from "data";
import Spinner from "./spinner";
import Support from "./icons/support";
import Version from "./icons/version";
import Github from "./icons/github";
@ -8,9 +9,7 @@ import Author from "./icons/author";
import Description from "./icons/description";
import Clock from "./icons/clock";
const Anchor = WebpackModules.getByDisplayName("Anchor");
const Button = WebpackModules.getByProps("BorderColors");
const Spinner = WebpackModules.getByDisplayName("Spinner");
const {TooltipContainer: Tooltip} = WebpackModules.getByProps("TooltipContainer");
const {ModalRoot, ModalHeader, ModalContent, ModalCloseButton, ModalFooter} = WebpackModules.getByProps("ModalRoot");
@ -53,8 +52,8 @@ export default class InstallationModal extends React.Component {
<ModalCloseButton onClick={this.props.onClose} className="bd-installation-close"/>
</ModalHeader>
<ModalContent className="bd-installation-content">
<h5 className={Utilities.joinClassNames("bd-installation-name", DiscordClasses.Text.size16, DiscordClasses.Text.colorHeaderPrimary)}>{name}</h5>
<div className={Utilities.joinClassNames(DiscordClasses.Text.size14, DiscordClasses.Text.colorHeaderSecondary)}>
<h5 className="bd-installation-name">{name}</h5>
<div className="bd-installation-subtitle">
{Strings.Store.installConfirmation.format({type})}
</div>
<ul className="bd-installation-info">
@ -71,11 +70,11 @@ export default class InstallationModal extends React.Component {
</InfoItem>
<div className="bd-info-divider" role="separator"></div>
<InfoItem icon={<Github aria-label={Strings.Addons.source} />} id="bd-info-source" label={Strings.Addons.source}>
<Anchor href={Web.ENDPOINTS.githubRedirect(id)} target="_blank" rel="noreferrer noopener">{filename}</Anchor>
<a href={Web.ENDPOINTS.githubRedirect(id)} target="_blank" rel="noreferrer noopener">{filename}</a>
</InfoItem>
<div className="bd-info-divider" role="separator"></div>
<InfoItem icon={<Author aria-label={Strings.Addons.author} />} id="bd-info-author" label={Strings.Addons.uploaded}>
<Anchor href={`${Web.PAGES.developer}/${author.display_name}`} target="_blank" rel="noreferrer noopener">{author.display_name}</Anchor>
<a href={`${Web.PAGES.developer}/${author.display_name}`} target="_blank" rel="noreferrer noopener">{author.display_name}</a>
</InfoItem>
</ul>
</ModalContent>

View File

@ -14,7 +14,7 @@ export default class Modals {
static get ModalStack() {return WebpackModules.getByProps("push", "update", "pop", "popWithKey");}
static get ModalComponents() {return WebpackModules.getByProps("ModalRoot");}
static get ModalClasses() {return WebpackModules.getByProps("modal", "content");}
static get MaskedLink() {return WebpackModules.getByDisplayName("MaskedLink");}
static get MaskedLink() {return WebpackModules.getModule(m => m?.default?.type?.toString()?.includes('default.MASKED_LINK'));;}
static get ImageModal() {return WebpackModules.getByDisplayName("ImageModal");}
static get AlertModal() {return WebpackModules.getByPrototypes("handleCancel", "handleSubmit", "handleMinorConfirm");}
static get FlexElements() {return WebpackModules.getByProps("Child", "Align");}
@ -100,15 +100,14 @@ export default class Modals {
static showImageModal(src, options = {}) {
const {key = undefined, width = undefined, height = undefined} = options;
const ImageModal = this.ImageModal;
const MaskedLink = this.MaskedLink;
if (!this.ModalActions || !this.ModalComponents || !this.ImageModal || !this.MaskedLink) return Logger.warn("Modals", "showImageModal missing modules");
const {ModalRoot, ModalSize} = this.ModalComponents;
return this.ModalActions.openModal(props => {
return React.createElement(ModalRoot, Object.assign({}, props, {
size: ModalSize.DYNAMIC,
className: "bd-image-modal"
}), React.createElement(ImageModal, Object.assign({
}), React.createElement(this.ImageModal, Object.assign({
className: "bd-image-modal-image",
src,
width,
@ -116,7 +115,7 @@ export default class Modals {
placeholder: src,
original: src,
onClickUntrusted: link => link.openHref(),
renderLinkComponent: () => React.createElement(MaskedLink, props)
renderLinkComponent: () => React.createElement("a", props)
}, props)));
}, {modalKey: key});
}

View File

@ -5,7 +5,7 @@ import {shell} from "electron";
import Dropdown from "../components/dropdown";
import SearchBar from "../components/searchbar";
import TabBar from "../components/tabbar";
import TabBar from "../../tabbar";
import Divider from "../../divider";
import SettingsTitle from "../title";
import Reload from "../../icons/reload";
@ -54,7 +54,7 @@ const CONTROLS = {
const PAGES = {
installed: {
get label() {return Strings.Addons.installed},
get label() {return Strings.Addons.installed;},
component: InstalledPage,
defaults: {
sort: "name",
@ -63,7 +63,7 @@ const PAGES = {
}
},
store: {
get label() {return Strings.Addons.store},
get label() {return Strings.Addons.store;},
component: StorePage,
state: {
selectedTag: "all"
@ -91,6 +91,8 @@ export default class AddonList extends React.Component {
super(props);
this.update = this.update.bind(this);
this.reload = this.reload.bind(this);
this.editAddon = this.editAddon.bind(this);
this.events = [`${this.props.type}-loaded`, `${this.props.type}-unloaded`];
this.state = {
query: "",
@ -197,7 +199,7 @@ export default class AddonList extends React.Component {
this.setState({sortStyle: value});
}
editAddon = (id) => this.props.editAddon(id);
editAddon(id) {return this.props.editAddon(id);}
openFolder(folder) {
const open = shell.openItem ?? shell.openPath;
@ -211,16 +213,16 @@ export default class AddonList extends React.Component {
return <React.Fragment>
<div className="bd-addon-list-title">
{storeEnabled ?
<TabBar
{storeEnabled
? <TabBar
value={this.state.page}
onChange={value => this.setState({ page: value })}
onChange={value => this.setState({page: value})}
items={Object.entries(PAGES).map(([id, props]) => ({
name: props.label,
value: id
}))}
>
{showReloadIcon && <Reload className="bd-reload" onClick={this.reload.bind(this)} />}
{showReloadIcon && <Reload className="bd-reload" onClick={this.reload} />}
</TabBar>
: <SettingsTitle key="title" text={this.props.title} otherChildren={showReloadIcon && <Reload className="bd-reload" onClick={this.reload} />} />
}
@ -269,7 +271,7 @@ export default class AddonList extends React.Component {
<Button
size={Button.Sizes.SMALL}
onClick={() => this.openFolder(this.props.folder)}
>{Strings.Addons.openFolder.format({type: _.upperFirst(this.props.type)})}</Button>
>{Strings.Addons.openFolder.format({type: this.props.type})}</Button>
</div>
{this.pageControls}
<Divider className={Utilities.joinClassNames(DiscordClasses.Margins.marginTop20.toString(), DiscordClasses.Margins.marginBottom20.toString())} />

View File

@ -1,6 +1,7 @@
import {React, Strings, Utilities, WebpackModules, DiscordClasses, BdWebApi} from "modules";
import {Web} from "data";
import Spinner from "../../spinner";
import Next from "../../icons/next";
import Previous from "../../icons/previous";
import NoResults from "../../blankslates/noresults";
@ -9,7 +10,6 @@ import Modals from "../../modals";
import Toasts from "../../toasts";
const Button = WebpackModules.getByProps("DropdownSizes");
const Spinner = WebpackModules.getByDisplayName("Spinner");
export default class StorePage extends React.Component {
constructor(props) {
@ -34,7 +34,7 @@ export default class StorePage extends React.Component {
isLoaded: true,
addons: data
});
}).catch((err) => Modals.showConfirmationModal(Strings.Store.connectionError, Strings.Store.connectionErrorMessage, {
}).catch(() => Modals.showConfirmationModal(Strings.Store.connectionError, Strings.Store.connectionErrorMessage, {
cancelText: Strings.Modals.close,
confirmText: Strings.Modals.retry,
onConfirm: () => this.connect()
@ -45,7 +45,7 @@ export default class StorePage extends React.Component {
await BdWebApi.getAddonContents(id).then(contents => {
return this.props.installAddon(contents, filename);
}).catch(err => {
Toasts.error(Strings.Store.downloadError.format({ type: this.props.type }), err);
Toasts.error(Strings.Store.downloadError.format({type: this.props.type}), err);
});
}
@ -70,14 +70,11 @@ export default class StorePage extends React.Component {
.flat(10)
.filter(this.filterTags)
.sort((a, b) => {
try {
const first = a[sort];
const second = b[sort];
if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());
if (first > second) return 1;
if (second > first) return -1;
}
catch {}
const first = a[sort];
const second = b[sort];
if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());
if (first > second) return 1;
if (second > first) return -1;
return 0;
});
if (!this.props.ascending) final.reverse();
@ -125,7 +122,7 @@ export default class StorePage extends React.Component {
})}
onForceInstall={() => this.install(addon.id, addon.file_name)}
onDelete={() => this.props.confirmAddonDelete(addon.file_name)}
onForceDelete={() => manager.deleteAddon(addon.file_name)}
onForceDelete={() => this.props.deleteAddon(addon.file_name)}
/>;
})}
</div>
@ -136,7 +133,7 @@ export default class StorePage extends React.Component {
<Previous />
{Strings.Addons.back}
</Button>
<div class={`bd-page-buttons ${DiscordClasses.Scrollers.thin}`}>
<div className={`bd-page-buttons ${DiscordClasses.Scrollers.thin}`}>
{addons.length
? addons.map((_, index) => <div
role="button"

View File

@ -22,13 +22,6 @@ export default class SearchBar extends React.Component {
static get Sizes() {return Sizes;}
static get defaultProps() {
return {
size: Sizes.SMALL,
disabled: false
};
}
onChange({target: {value}}) {
this.setState({value, hasContent: !!value});
if (typeof(this.props.onChange) === "function") this.props.onChange(value);
@ -37,7 +30,7 @@ export default class SearchBar extends React.Component {
render() {
const {className, size = Sizes.SMALL, placeholder, disabled = false} = this.props;
return <div className={Utilities.joinClassNames("bd-searchbar", className, {disabled}, Sizes[size.toUpperCase()] ?? "SMALL")}>
return <div className={Utilities.joinClassNames("bd-searchbar", className, {disabled}, `size-${size}`)}>
<input onKeyDown={this.props.onKeyDown} onChange={this.onChange} disabled={disabled} type="text" placeholder={placeholder} maxLength="50" value={this.state.value} />
<div onClick={() => this.onChange({target: {value: ""}})} className={Utilities.joinClassNames("bd-search-icon", {clickable: this.state.hasContent})} tabIndex="-1" role="button">
<Close className={Utilities.joinClassNames("bd-search-close", {visible: this.state.hasContent})}/>

View File

@ -0,0 +1,33 @@
import {React, Utilities} from "modules";
export const Type = {
WANDERING_CUBES: "wandering-cubes",
CHASING_DOTS: "chasing-dots",
PULSING_ELLIPSIS: "pulsing-ellipsis",
SPINNING_CIRCLE: "spinning-circle",
LOW_MOTION: "low-motion"
};
export default class Spinner extends React.Component {
static get Type() {return Type;}
renderItems(type) {
if (type !== Type.SPINNING_CIRCLE) {
const itemAmount = type === Type.LOW_MOTION || type === Type.PULSING_ELLIPSIS ? 3 : 2;
return Array.from({length: itemAmount}).map(() => <span className="bd-spinner-item" />);
}
return <svg className="bd-spinner-circular" viewBox="25 25 50 50">
{Array.from({length: 3}).map(() => <circle cx="50" cy="50" r="20" />)}
</svg>;
}
render() {
const {className, type = Type.WANDERING_CUBES, ...props} = this.props;
return <div className={Utilities.joinClassNames("bd-spinner", `bd-spinner-${type}`, className)} {...props}>
<span class="bd-spinner-inner">
{this.renderItems(type)}
</span>
</div>;
}
}