diff --git a/packages/core-extensions/src/moonbase/webpackModules/stores.ts b/packages/core-extensions/src/moonbase/webpackModules/stores.ts index 5307469..9daa70a 100644 --- a/packages/core-extensions/src/moonbase/webpackModules/stores.ts +++ b/packages/core-extensions/src/moonbase/webpackModules/stores.ts @@ -1,5 +1,12 @@ import { Config, ExtensionEnvironment, ExtensionLoadSource, ExtensionSettingsAdvice } from "@moonlight-mod/types"; -import { ExtensionState, MoonbaseExtension, MoonbaseNatives, RepositoryManifest, RestartAdvice } from "../types"; +import { + ExtensionState, + MoonbaseExtension, + MoonbaseNatives, + RepositoryManifest, + RestartAdvice, + UpdateState +} from "../types"; import { Store } from "@moonlight-mod/wp/discord/packages/flux"; import Dispatcher from "@moonlight-mod/wp/discord/Dispatcher"; import getNatives from "../native"; @@ -25,6 +32,10 @@ class MoonbaseSettingsStore extends Store { submitting: boolean; installing: boolean; + #updateState = UpdateState.Ready; + get updateState() { + return this.#updateState; + } newVersion: string | null; shouldShowNotice: boolean; @@ -353,7 +364,18 @@ class MoonbaseSettingsStore extends Store { } async updateMoonlight() { - await natives.updateMoonlight(); + this.#updateState = UpdateState.Working; + this.emitChange(); + + await natives + .updateMoonlight() + .then(() => (this.#updateState = UpdateState.Installed)) + .catch((e) => { + logger.error(e); + this.#updateState = UpdateState.Failed; + }); + + this.emitChange(); } getConfigOption(key: K): Config[K] { @@ -381,6 +403,9 @@ class MoonbaseSettingsStore extends Store { } #computeRestartAdvice() { + // If moonlight update needs a restart, always hide advice. + if (this.#updateState === UpdateState.Installed) return RestartAdvice.NotNeeded; + const i = this.initialConfig; // Initial config, from startup const n = this.config; // New config about to be saved @@ -486,7 +511,7 @@ class MoonbaseSettingsStore extends Store { this.modified = false; this.emitChange(); - if (modifiedRepos) this.checkUpdates(); + if (modifiedRepos.length !== 0) this.checkUpdates(); } reset() { diff --git a/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/card.tsx b/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/card.tsx index e2cddb2..fc28434 100644 --- a/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/card.tsx +++ b/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/card.tsx @@ -58,7 +58,7 @@ function PanelLinkButton({ icon, tooltip, link }: { icon: React.ReactNode; toolt ); } -export default function ExtensionCard({ uniqueId }: { uniqueId: number }) { +export default function ExtensionCard({ uniqueId, selectTag }: { uniqueId: number; selectTag: (tag: string) => void }) { const { ext, enabled, busy, update, conflicting } = useStateFromStores([MoonbaseSettingsStore], () => { return { ext: MoonbaseSettingsStore.getExtension(uniqueId), @@ -303,7 +303,7 @@ export default function ExtensionCard({ uniqueId }: { uniqueId: number }) { rowGap: tab === ExtensionPage.Info ? "16px" : undefined }} > - {tab === ExtensionPage.Info && } + {tab === ExtensionPage.Info && } {tab === ExtensionPage.Description && ( {MarkupUtils.parse(description ?? "*No description*", true, { diff --git a/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/index.tsx b/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/index.tsx index 57d73e8..ecad8d4 100644 --- a/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/index.tsx +++ b/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/index.tsx @@ -20,6 +20,8 @@ import HelpMessage from "../HelpMessage"; const SearchBar = spacepack.require("discord/uikit/search/SearchBar").default; +const validTags: string[] = Object.values(ExtensionTag); + export default function ExtensionsPage() { const { extensions, savedFilter } = useStateFromStoresObject([MoonbaseSettingsStore], () => { return { @@ -41,7 +43,17 @@ export default function ExtensionsPage() { filter = filterState[0]; setFilter = filterState[1]; } + const [selectedTags, setSelectedTags] = React.useState(new Set()); + const selectTag = React.useCallback( + (tag: string) => { + const newState = new Set(selectedTags); + if (validTags.includes(tag)) newState.add(tag); + setSelectedTags(newState); + }, + [selectedTags] + ); + const sorted = Object.values(extensions).sort((a, b) => { const aName = a.manifest.meta?.name ?? a.id; const bName = b.manifest.meta?.name ?? b.id; @@ -132,13 +144,13 @@ export default function ExtensionsPage() { )} {filteredWithUpdates.map((ext) => ( - + ))} {filteredWithUpdates.length > 0 && filteredWithoutUpdates.length > 0 && ( )} {filteredWithoutUpdates.map((ext) => ( - + ))} ); diff --git a/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/info.tsx b/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/info.tsx index 58ae1ef..35e38e0 100644 --- a/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/info.tsx +++ b/packages/core-extensions/src/moonbase/webpackModules/ui/extensions/info.tsx @@ -54,12 +54,15 @@ function InfoSection({ title, children }: { title: string; children: React.React function Badge({ color, children, - style = {} + style = {}, + onClick }: { color: string; children: React.ReactNode; style?: React.CSSProperties; + onClick?: () => void; }) { + if (onClick) style.cursor ??= "pointer"; return ( {children} ); } -export default function ExtensionInfo({ ext }: { ext: MoonbaseExtension }) { +export default function ExtensionInfo({ + ext, + selectTag +}: { + ext: MoonbaseExtension; + selectTag: (tag: string) => void; +}) { const authors = ext.manifest?.meta?.authors; const tags = ext.manifest?.meta?.tags; const version = ext.manifest?.version; @@ -148,7 +158,7 @@ export default function ExtensionInfo({ ext }: { ext: MoonbaseExtension }) { } return ( - + selectTag(tag)}> {name} ); diff --git a/packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx b/packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx index 2945b4e..4f1aede 100644 --- a/packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx +++ b/packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx @@ -20,8 +20,6 @@ import { } from "@moonlight-mod/wp/discord/components/common/index"; import MarkupClasses from "@moonlight-mod/wp/discord/modules/messages/web/Markup.css"; -const logger = moonlight.getLogger("moonbase/ui/update"); - const strings: Record = { [UpdateState.Ready]: "A new version of moonlight is available.", [UpdateState.Working]: "Updating moonlight...", @@ -67,8 +65,10 @@ function MoonlightChangelog({ } export default function Update() { - const [state, setState] = React.useState(UpdateState.Ready); - const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion); + const [newVersion, state] = useStateFromStores([MoonbaseSettingsStore], () => [ + MoonbaseSettingsStore.newVersion, + MoonbaseSettingsStore.updateState + ]); if (newVersion == null) return null; @@ -113,14 +113,7 @@ export default function Update() { size={Button.Sizes.TINY} disabled={state !== UpdateState.Ready} onClick={() => { - setState(UpdateState.Working); - - MoonbaseSettingsStore.updateMoonlight() - .then(() => setState(UpdateState.Installed)) - .catch((e) => { - logger.error(e); - setState(UpdateState.Failed); - }); + MoonbaseSettingsStore.updateMoonlight(); }} > Update