this repo has no description

moonbase: initial crash screen with moonlight updater

Changed files
+198 -2
packages
core-extensions
src
moonbase
+32 -1
packages/core-extensions/src/moonbase/index.tsx
···
-
import { ExtensionWebpackModule } from "@moonlight-mod/types";
export const webpackModules: Record<string, ExtensionWebpackModule> = {
stores: {
···
moonbase: {
dependencies: [{ ext: "moonbase", id: "stores" }]
}
};
···
+
import { ExtensionWebpackModule, Patch } from "@moonlight-mod/types";
+
+
export const patches: Patch[] = [
+
{
+
find: "window.DiscordErrors=",
+
replace: [
+
// replace reporting line with update status
+
{
+
match: /,(\(0,.\.jsx\))\("p",{children:.\.[a-zA-Z]+\.Messages.ERRORS_ACTION_TO_TAKE}\)/,
+
replacement: (_, createElement) =>
+
`,${createElement}(require("moonbase_crashScreen").UpdateText,{state:this.state,setState:this.setState.bind(this)})`
+
},
+
+
// wrap actions field to display error details
+
{
+
match: /action:(.),className:/,
+
replacement: (_, action) => `action:require("moonbase_crashScreen").wrapAction(${action},this.state),className:`
+
},
+
+
// add update button
+
{
+
match: /(?<=\.ERRORS_RELOAD}\),(\(0,.\.jsx\))\(.,{}\))/,
+
replacement: (_, createElement) =>
+
`,${createElement}(require("moonbase_crashScreen").UpdateButton,{state:this.state,setState:this.setState.bind(this)})`
+
}
+
]
+
}
+
];
export const webpackModules: Record<string, ExtensionWebpackModule> = {
stores: {
···
moonbase: {
dependencies: [{ ext: "moonbase", id: "stores" }]
+
},
+
+
crashScreen: {
+
dependencies: [{ id: "react" }]
}
};
+64 -1
packages/core-extensions/src/moonbase/style.css
···
--moonbase-fg: #fffba6;
}
-
.moonbase-settings > :first-child {
margin-top: 0px;
}
···
flex-direction: row;
gap: 8px;
}
···
--moonbase-fg: #fffba6;
}
+
.moonbase-settings> :first-child {
margin-top: 0px;
}
···
flex-direction: row;
gap: 8px;
}
+
+
/* crash screen */
+
.moonbase-crash-wrapper>[class^="buttons_"] {
+
gap: 1rem;
+
}
+
+
.moonbase-crash-wrapper {
+
display: flex;
+
flex-direction: column;
+
align-items: center;
+
gap: 1rem;
+
max-height: 50%;
+
}
+
+
.moonbase-crash-details-wrapper {
+
overflow-y: scroll;
+
color: var(--text-normal);
+
background: var(--background-secondary);
+
border: 1px solid var(--background-tertiary);
+
border-radius: 4px;
+
padding: 0.5em;
+
+
&::-webkit-scrollbar {
+
width: 8px;
+
height: 8px;
+
}
+
+
&::-webkit-scrollbar-thumb {
+
background-clip: padding-box;
+
border: 2px solid transparent;
+
border-radius: 4px;
+
background-color: var(--scrollbar-thin-thumb);
+
min-height: 40px;
+
}
+
+
&::-webkit-scrollbar-track {
+
border: 2px solid var(--scrollbar-thin-track);
+
background-color: var(--scrollbar-thin-track);
+
border-color: var(--scrollbar-thin-track);
+
}
+
}
+
+
.moonbase-crash-details {
+
box-sizing: border-box;
+
padding: 0;
+
font-family: var(--font-code);
+
font-size: .75rem;
+
line-height: 1rem;
+
margin: 6px;
+
max-width: 50vw;
+
white-space: pre-wrap;
+
background-clip: border-box;
+
+
&>code {
+
font-size: .875rem;
+
line-height: 1.125rem;
+
text-indent: 0;
+
white-space: pre-wrap;
+
text-size-adjust: none;
+
display: block;
+
user-select: text;
+
}
+
}
+102
packages/core-extensions/src/moonbase/webpackModules/crashScreen.tsx
···
···
+
import React from "@moonlight-mod/wp/react";
+
import * as Components from "@moonlight-mod/wp/discord/components/common/index";
+
import { useStateFromStores } from "@moonlight-mod/wp/discord/packages/flux";
+
import { MoonbaseSettingsStore } from "@moonlight-mod/wp/moonbase_stores";
+
+
const { Button, ButtonSizes } = Components;
+
+
const logger = moonlight.getLogger("moonbase/crashScreen");
+
+
type ErrorState = {
+
error: Error;
+
info: {
+
componentStack: string;
+
};
+
__moonlight_update?: UpdateState;
+
};
+
+
enum UpdateState {
+
Ready,
+
Working,
+
Installed,
+
Failed
+
}
+
+
const updateStrings: Record<UpdateState, string> = {
+
[UpdateState.Ready]: "A new version of moonlight is available.",
+
[UpdateState.Working]: "Updating moonlight...",
+
[UpdateState.Installed]: "Updated moonlight. Click Reload to apply changes.",
+
[UpdateState.Failed]: "Failed to update moonlight. Please use the installer."
+
};
+
const buttonStrings: Record<UpdateState, string> = {
+
[UpdateState.Ready]: "Update moonlight",
+
[UpdateState.Working]: "Updating moonlight...",
+
[UpdateState.Installed]: "",
+
[UpdateState.Failed]: "Update failed"
+
};
+
+
export function wrapAction(action: React.ReactNode, { error, info }: ErrorState) {
+
return (
+
<div className="moonbase-crash-wrapper">
+
{action}
+
<div className="moonbase-crash-details-wrapper">
+
<pre className="moonbase-crash-details">
+
<code>
+
{error.stack}
+
{"\n\nComponent stack:"}
+
{info.componentStack}
+
</code>
+
</pre>
+
</div>
+
</div>
+
);
+
}
+
+
export function UpdateText({ state, setState }: { state: ErrorState; setState: (state: ErrorState) => void }) {
+
if (!state.__moonlight_update) {
+
setState({
+
...state,
+
__moonlight_update: UpdateState.Ready
+
});
+
}
+
const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion);
+
+
return newVersion == null ? null : (
+
<p>{state.__moonlight_update !== undefined ? updateStrings[state.__moonlight_update] : ""}</p>
+
);
+
}
+
+
export function UpdateButton({ state, setState }: { state: ErrorState; setState: (state: ErrorState) => void }) {
+
const newVersion = useStateFromStores([MoonbaseSettingsStore], () => MoonbaseSettingsStore.newVersion);
+
return newVersion == null ||
+
state.__moonlight_update === UpdateState.Installed ||
+
state.__moonlight_update === undefined ? null : (
+
<Button
+
size={ButtonSizes.LARGE}
+
disabled={state.__moonlight_update !== UpdateState.Ready}
+
onClick={() => {
+
setState({
+
...state,
+
__moonlight_update: UpdateState.Working
+
});
+
+
MoonbaseSettingsStore.updateMoonlight()
+
.then(() => {
+
setState({
+
...state,
+
__moonlight_update: UpdateState.Installed
+
});
+
})
+
.catch((e) => {
+
logger.error(e);
+
setState({
+
...state,
+
__moonlight_update: UpdateState.Failed
+
});
+
});
+
}}
+
>
+
{state.__moonlight_update !== undefined ? buttonStrings[state.__moonlight_update] : ""}
+
</Button>
+
);
+
}