Use clean icons for updater panel

This commit is contained in:
Zerebos 2024-02-24 21:18:17 -05:00
parent 95492001b0
commit 853c554d4d
5 changed files with 82 additions and 19 deletions

View File

@ -5,6 +5,7 @@
justify-content: center;
align-items: center;
padding: 3px;
margin-right: 4px; /* Align with other icons */
}
.bd-empty-updates {
@ -20,4 +21,33 @@
.bd-empty-updates svg {
fill: #43B581;
margin-bottom: 20px;
}
.bd-button.bd-button-icon svg {
fill: var(--interactive-normal);
}
.bd-button.bd-button-icon:hover svg {
fill: var(--interactive-hover);
}
.bd-button.bd-button-icon.animate {
animation: 500ms linear infinite bd-update-spin;
}
.bd-settings-group-title .bd-button-icon {
margin-left: 3px;
margin-right: -8px;
}
@keyframes bd-update-spin {
0% {
transform: rotate(0);
}
50% {
transform: rotate(180deg)
}
100% {
transform: rotate(360deg)
}
}

View File

@ -1,6 +1,6 @@
import React from "@modules/react";
export default function FullScreen(props) {
export default function Folder(props) {
const size = props.size || "20px";
return <svg className={props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}} onClick={props.onClick}>
<path d="M0 0h24v24H0z" fill="none"/>

View File

@ -0,0 +1,9 @@
import React from "@modules/react";
export default function Sync(props) {
const size = props.size || "24px";
return <svg className={props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}} onClick={props.onClick}>
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/>
</svg>;
}

View File

@ -9,7 +9,7 @@ const {useState, useCallback, useRef} = React;
const baseClassName = "bd-settings-group";
export default function Drawer({name, collapsible, shown = true, showDivider, children, button, onDrawerToggle}) {
export default function Drawer({name, collapsible, shown = true, showDivider, children, titleChildren, onDrawerToggle}) {
const container = useRef(null);
const [collapsed, setCollapsed] = useState(collapsible && !shown);
const toggleCollapse = useCallback(() => {
@ -26,17 +26,13 @@ export default function Drawer({name, collapsible, shown = true, showDivider, ch
}, [collapsed, onDrawerToggle]);
const onClick = useCallback((event) => {
event.stopPropagation();
button?.onClick(...arguments);
}, [button]);
const collapseClass = collapsible ? `collapsible ${collapsed ? "collapsed" : "expanded"}` : "";
const groupClass = `${baseClassName} ${collapseClass}`;
return <div className={groupClass}>
<Title text={name} collapsible={collapsible} onClick={toggleCollapse} button={button ? {...button, onClick} : null} isGroup={true} />
<Title text={name} collapsible={collapsible} onClick={toggleCollapse} isGroup={true}>
{titleChildren}
</Title>
<div className="bd-settings-container" ref={container}>
{children}
</div>

View File

@ -3,22 +3,44 @@ import Config from "@data/config";
import React from "@modules/react";
import Strings from "@modules/strings";
import Events from "@modules/emitter";
import DiscordModules from "@modules/discordmodules";
import Button from "./base/button";
import Drawer from "./settings/drawer";
import SettingItem from "./settings/components/item";
import SettingsTitle from "./settings/title";
import Toasts from "./toasts";
import Button from "@ui/base/button";
import Drawer from "@ui/settings/drawer";
import SettingItem from "@ui/settings/components/item";
import SettingsTitle from "@ui/settings/title";
import Toasts from "@ui/toasts";
import Checkmark from "@ui/icons/check";
import Reload from "@ui/icons/reload";
import Sync from "@ui/icons/sync";
const {useState, useCallback, useEffect} = React;
function makeButton(tooltip, children, action, options = {}) {
const {size = Button.Sizes.ICON, look = Button.Looks.BLANK, color = Button.Colors.TRANSPARENT, className = "", stopAnimation = false} = options;
const onClick = async (event) => {
const button = event.target.closest("button");
button.classList.add("animate");
await action();
if (!stopAnimation) return;
await new Promise(r => setTimeout(r, 500)); // Allow animation to complete at least once.
button?.classList?.remove("animate"); // Stop animation if it hasn't been removed from the DOM
};
return <DiscordModules.Tooltip color="primary" position="top" text={tooltip}>
{(props) => <Button {...props} className={`bd-update-button ${className}`} size={size} look={look} color={color} onClick={onClick}>{children}</Button>}
</DiscordModules.Tooltip>;
}
function CoreUpdaterPanel({hasUpdate, remoteVersion, update}) {
return <Drawer name="BetterDiscord" collapsible={true}>
<SettingItem name={`Core v${Config.version}`} note={hasUpdate ? Strings.Updater.versionAvailable.format({version: remoteVersion}) : Strings.Updater.noUpdatesAvailable} inline={true} id={"core-updater"}>
{!hasUpdate && <div className="bd-filled-checkmark"><Checkmark /></div>}
{hasUpdate && <Button size={Button.Sizes.SMALL} onClick={update}>{Strings.Updater.updateButton}</Button>}
{!hasUpdate && <div className="bd-filled-checkmark"><Checkmark size="18px" /></div>}
{hasUpdate && makeButton(Strings.Updater.updateButton, <Reload />, update)}
</SettingItem>
</Drawer>;
}
@ -32,13 +54,17 @@ function NoUpdates({type}) {
function AddonUpdaterPanel({pending, type, updater, update, updateAll}) {
const filenames = pending;
return <Drawer name={Strings.Panels[type]} collapsible={true} button={filenames.length ? {title: Strings.Updater.updateAll, onClick: () => updateAll(type)} : null}>
return <Drawer
name={Strings.Panels[type]}
collapsible={true}
titleChildren={filenames.length > 1 ? makeButton(Strings.Updater.updateAll, <Reload size="20px" />, () => updateAll(type)) : null}>
{!filenames.length && <NoUpdates type={type} />}
{filenames.map(f => {
const info = updater.cache[f];
const addon = updater.manager.addonList.find(a => a.filename === f);
return <SettingItem name={`${addon.name} v${addon.version}`} note={Strings.Updater.versionAvailable.format({version: info.version})} inline={true} id={addon.name}>
<Button size={Button.Sizes.SMALL} onClick={() => update(type, f)}>{Strings.Updater.updateButton}</Button>
{makeButton(Strings.Updater.updateButton, <Reload />, () => update(type, f))}
{/* <Button size={Button.Sizes.SMALL} onClick={() => update(type, f)}>{Strings.Updater.updateButton}</Button> */}
</SettingItem>;
})}
</Drawer>;
@ -107,7 +133,9 @@ export default function UpdaterPanel({coreUpdater, pluginUpdater, themeUpdater})
}, [updateAddon, updates]);
return [
<SettingsTitle text={Strings.Panels.updates} button={{title: Strings.Updater.checkForUpdates, onClick: checkForUpdates}} />,
<SettingsTitle text={Strings.Panels.updates}>
{makeButton(Strings.Updater.checkForUpdates, <Sync />, checkForUpdates, {className: "bd-update-check", stopAnimation: true})}
</SettingsTitle>,
<CoreUpdaterPanel remoteVersion={coreUpdater.remoteVersion} hasUpdate={hasCoreUpdate} update={updateCore} />,
<AddonUpdaterPanel type="plugins" pending={updates.plugins} update={updateAddon} updateAll={updateAllAddons} updater={pluginUpdater} />,
<AddonUpdaterPanel type="themes" pending={updates.themes} update={updateAddon} updateAll={updateAllAddons} updater={themeUpdater} />,