diff --git a/renderer/src/styles/ui/updater.css b/renderer/src/styles/ui/updater.css index 816e699c..87614ccb 100644 --- a/renderer/src/styles/ui/updater.css +++ b/renderer/src/styles/ui/updater.css @@ -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) + } } \ No newline at end of file diff --git a/renderer/src/ui/icons/folder.jsx b/renderer/src/ui/icons/folder.jsx index 32d56a8d..69827677 100644 --- a/renderer/src/ui/icons/folder.jsx +++ b/renderer/src/ui/icons/folder.jsx @@ -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 diff --git a/renderer/src/ui/icons/sync.jsx b/renderer/src/ui/icons/sync.jsx new file mode 100644 index 00000000..182413c3 --- /dev/null +++ b/renderer/src/ui/icons/sync.jsx @@ -0,0 +1,9 @@ +import React from "@modules/react"; + +export default function Sync(props) { + const size = props.size || "24px"; + return + + + ; +} diff --git a/renderer/src/ui/settings/drawer.jsx b/renderer/src/ui/settings/drawer.jsx index 957df5d1..0c348a9c 100644 --- a/renderer/src/ui/settings/drawer.jsx +++ b/renderer/src/ui/settings/drawer.jsx @@ -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
- + <Title text={name} collapsible={collapsible} onClick={toggleCollapse} isGroup={true}> + {titleChildren} +
{children}
diff --git a/renderer/src/ui/updater.jsx b/renderer/src/ui/updater.jsx index dc81d024..d9945ee8 100644 --- a/renderer/src/ui/updater.jsx +++ b/renderer/src/ui/updater.jsx @@ -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 + {(props) => } + ; +} + function CoreUpdaterPanel({hasUpdate, remoteVersion, update}) { return - {!hasUpdate &&
} - {hasUpdate && } + {!hasUpdate &&
} + {hasUpdate && makeButton(Strings.Updater.updateButton, , update)}
; } @@ -32,13 +54,17 @@ function NoUpdates({type}) { function AddonUpdaterPanel({pending, type, updater, update, updateAll}) { const filenames = pending; - return updateAll(type)} : null}> + return 1 ? makeButton(Strings.Updater.updateAll, , () => updateAll(type)) : null}> {!filenames.length && } {filenames.map(f => { const info = updater.cache[f]; const addon = updater.manager.addonList.find(a => a.filename === f); return - + {makeButton(Strings.Updater.updateButton, , () => update(type, f))} + {/* */} ; })} ; @@ -107,7 +133,9 @@ export default function UpdaterPanel({coreUpdater, pluginUpdater, themeUpdater}) }, [updateAddon, updates]); return [ - , + + {makeButton(Strings.Updater.checkForUpdates, , checkForUpdates, {className: "bd-update-check", stopAnimation: true})} + , , , ,