Skip to content

Commit a797070

Browse files
committed
feat: Add router, toaster, and error boundary hook.
1 parent 9830510 commit a797070

File tree

11 files changed

+6186
-6271
lines changed

11 files changed

+6186
-6271
lines changed

pnpm-lock.yaml

Lines changed: 5980 additions & 5977 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

typescript-packages/client/src/hooks/ErrorBoundaryHook.tsx

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -67,36 +67,26 @@ class ErrorBoundaryHook extends Logger {
6767
return;
6868
}
6969

70-
console.log('ERROR BOUNDARY', ErrorBoundary);
70+
console.debug('Patching ErrorBoundary', ErrorBoundary);
7171

7272
this.errorBoundaryPatch = replacePatch(ErrorBoundary.prototype, 'render', function (this: any) {
7373
if (this.state._deckyForceRerender) {
74-
console.log('FORCE RERENDERING', this.state);
75-
this.setState({ ...this.state, _deckyForceRerender: null });
76-
return null;
74+
console.debug('Forcing rerender');
75+
const stateClone = { ...this.state, _deckyForceRerender: null };
76+
this.setState(stateClone);
77+
return;
7778
}
78-
// yoinked from valve error boundary
79-
// if (this.state.error && this.props.errorKey == this.state.lastErrorKey) {
80-
// // const store = Object.getPrototypeOf(this)?.constructor?.sm_ErrorReportingStore || errorReportingStore;
81-
82-
// return void 0 !== this.props.fallback ? (
83-
// 'function' == typeof this.props.fallback ? (
84-
// this.props.fallback(this.state.error.error)
85-
// ) : (
86-
// this.props.fallback
87-
// )
88-
// ) : (
89-
// // <DeckyErrorBoundary
90-
// // error={this.state.error}
91-
// // errorKey={this.props.errorKey}
92-
// // identifier={`${store.product}_${store.version}_${this.state.identifierHash}`}
93-
// // reset={() => this.Reset()}
94-
// // />
95-
// <div>An error occurred while rendering this content</div>
96-
// );
79+
// if (this.state.error) {
80+
// const store = Object.getPrototypeOf(this)?.constructor?.sm_ErrorReportingStore || errorReportingStore;
81+
// return (
82+
// <DeckyErrorBoundary
83+
// error={this.state.error}
84+
// errorKey={this.props.errorKey}
85+
// identifier={`${store.product}_${store.version}_${this.state.identifierHash}`}
86+
// reset={() => this.Reset()}
87+
// />
88+
// );
9789
// }
98-
99-
console.log('returning callOriginal', this.state);
10090
return callOriginal;
10191
});
10292
// Small hack that gives us a lot more flexibility to force rerenders.
@@ -110,7 +100,7 @@ class ErrorBoundaryHook extends Logger {
110100
if (this.disableReportingTimer) {
111101
clearTimeout(this.disableReportingTimer);
112102
}
113-
setTimeout(() => {
103+
this.disableReportingTimer = setTimeout(() => {
114104
this.debug('Reporting re-enabled after 30s timeout.');
115105
this.disableReportingTimer = 0;
116106
}, 30000);

typescript-packages/client/src/hooks/Toaster.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Patch, callOriginal, findModuleExport, injectFCTrampoline, replacePatch } from '..';
1+
import { ErrorBoundary, Patch, callOriginal, findModuleExport, injectFCTrampoline, replacePatch } from '..';
22

33
import Toast from '../components/Toast';
44
import Logger from '../logger';
@@ -62,9 +62,9 @@ class Toaster extends Logger {
6262
this.toastPatch = replacePatch(patchedRenderer, 'component', (args: any[]) => {
6363
if (args?.[0]?.group?.decky || args?.[0]?.group?.notifications?.[0]?.decky) {
6464
return args[0].group.notifications.map((notification: any) => (
65-
// <ErrorBoundary>
66-
<Toast toast={notification.data} newIndicator={notification.bNewIndicator} location={args?.[0]?.location} />
67-
// </ErrorBoundary>
65+
<ErrorBoundary>
66+
<Toast toast={notification.data} newIndicator={notification.bNewIndicator} location={args?.[0]?.location} />
67+
</ErrorBoundary>
6868
));
6969
}
7070
return callOriginal;
@@ -92,8 +92,7 @@ class Toaster extends Logger {
9292
nNotificationID: window.NotificationStore.m_nNextTestNotificationID++,
9393
bNewIndicator: toast.showNewIndicator,
9494
rtCreated: Date.now(),
95-
eType: toast.eType || 12,
96-
eFeature: 0,
95+
eType: toast.eType || 16,
9796
eSource: 1, // Client
9897
nToastDurationMS: toast.duration || (toast.duration = 5e3),
9998
data: toast,

typescript-packages/client/src/init.tsx

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,7 @@ import RouterHook from './hooks/router/RouterHook';
33
import TabsHook from './hooks/TabHook';
44
import Toaster from './hooks/Toaster';
55

6-
export let errorBoundaryHook: ErrorBoundaryHook;
7-
export let tabsHook: TabsHook;
8-
export let routerHook: RouterHook;
9-
export let toaster: Toaster;
10-
11-
setTimeout(() => {
12-
// console.log('Initializing client...');
13-
// errorBoundaryHook = new ErrorBoundaryHook();
14-
// routerHook = new RouterHook();
15-
// Object.assign(tabsHook, new TabsHook());
16-
// Object.assign(toaster, new Toaster());
17-
console.log('Initializing Millennium client...');
18-
toaster = new Toaster();
19-
20-
toaster.toast({
21-
title: 'Welcome to Millennium',
22-
body: 'This is a sample notification.',
23-
icon: <></>,
24-
});
25-
26-
// routerHook.addRoute('/millennium/example', () => <div>Hello</div>);
27-
}, 5000);
6+
export const errorBoundaryHook: ErrorBoundaryHook = new ErrorBoundaryHook();
7+
export const tabsHook: TabsHook = new TabsHook();
8+
export const routerHook: RouterHook = new RouterHook();
9+
export const toaster: Toaster = new Toaster();
Lines changed: 42 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,59 @@
1-
const bgStyle1 = 'background: #8a16a2; color: white;';
2-
const isSharedJSContext = window.location.hostname === 'steamloopback.host';
1+
const bgStyle1 = 'background:rgb(37, 105, 184); color: white;';
32

4-
const moduleName = isSharedJSContext ? "@steambrew/client" : "@steambrew/webkit"
5-
6-
export const log = (name: string, ...args: any[]) => {
7-
console.log(
8-
`%c ${moduleName} %c ${name} %c`,
9-
bgStyle1,
10-
'background: #b11cce; color: white;',
11-
'background: transparent;',
12-
...args,
13-
);
3+
export const log = (moduleName: string, name: string, ...args: any[]) => {
4+
console.log(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background:rgb(28, 135, 206); color: white;', 'background: transparent;', ...args);
145
};
156

16-
export const group = (name: string, ...args: any[]) => {
17-
console.group(
18-
`%c ${moduleName} %c ${name} %c`,
19-
bgStyle1,
20-
'background: #b11cce; color: white;',
21-
'background: transparent;',
22-
...args,
23-
);
7+
export const group = (moduleName: string, name: string, ...args: any[]) => {
8+
console.group(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: rgb(28, 135, 206); color: white;', 'background: transparent;', ...args);
249
};
2510

26-
export const groupEnd = (name: string, ...args: any[]) => {
27-
console.groupEnd();
28-
if (args?.length > 0)
29-
console.log(
30-
`^ %c ${moduleName} %c ${name} %c`,
31-
bgStyle1,
32-
'background: #b11cce; color: white;',
33-
'background: transparent;',
34-
...args,
35-
);
11+
export const groupEnd = (moduleName: string, name: string, ...args: any[]) => {
12+
console.groupEnd();
13+
if (args?.length > 0) console.log(`^ %c ${moduleName} %c ${name} %c`, bgStyle1, 'background: rgb(28, 135, 206); color: white;', 'background: transparent;', ...args);
3614
};
3715

38-
export const debug = (name: string, ...args: any[]) => {
39-
console.debug(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: #1abc9c; color: white;', 'color: blue;', ...args);
16+
export const debug = (moduleName: string, name: string, ...args: any[]) => {
17+
console.debug(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: #1abc9c; color: white;', 'color: blue;', ...args);
4018
};
4119

42-
export const warn = (name: string, ...args: any[]) => {
43-
console.warn(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: #ffbb00; color: white;', 'color: blue;', ...args);
20+
export const warn = (moduleName: string, name: string, ...args: any[]) => {
21+
console.warn(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: #ffbb00; color: white;', 'color: blue;', ...args);
4422
};
4523

46-
export const error = (name: string, ...args: any[]) => {
47-
console.error(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: #FF0000;', 'background: transparent;', ...args);
24+
export const error = (moduleName: string, name: string, ...args: any[]) => {
25+
console.error(`%c ${moduleName} %c ${name} %c`, bgStyle1, 'background: #FF0000;', 'background: transparent;', ...args);
4826
};
4927

5028
class Logger {
51-
constructor(private name: string) {
52-
this.name = name;
53-
}
54-
55-
log(...args: any[]) {
56-
log(this.name, ...args);
57-
}
58-
59-
debug(...args: any[]) {
60-
debug(this.name, ...args);
61-
}
62-
63-
warn(...args: any[]) {
64-
warn(this.name, ...args);
65-
}
66-
67-
error(...args: any[]) {
68-
error(this.name, ...args);
69-
}
70-
71-
group(...args: any[]) {
72-
group(this.name, ...args);
73-
}
74-
75-
groupEnd(...args: any[]) {
76-
groupEnd(this.name, ...args);
77-
}
29+
constructor(private name: string, private moduleName: string = 'Millennium') {
30+
this.name = name;
31+
this.moduleName = moduleName;
32+
}
33+
34+
log(...args: any[]) {
35+
log(this.moduleName, this.name, ...args);
36+
}
37+
38+
debug(...args: any[]) {
39+
debug(this.moduleName, this.name, ...args);
40+
}
41+
42+
warn(...args: any[]) {
43+
warn(this.moduleName, this.name, ...args);
44+
}
45+
46+
error(...args: any[]) {
47+
error(this.moduleName, this.name, ...args);
48+
}
49+
50+
group(...args: any[]) {
51+
group(this.moduleName, this.name, ...args);
52+
}
53+
54+
groupEnd(...args: any[]) {
55+
groupEnd(this.moduleName, this.name, ...args);
56+
}
7857
}
7958

8059
export default Logger;

typescript-packages/client/src/webpack.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,6 @@ export const findModule = (filter: FilterFn) => {
6161
}
6262
};
6363

64-
Object.assign(
65-
window.SP_REACTDOM,
66-
findModule((module) => module.createPortal && module.createRoot && module.flushSync),
67-
);
68-
Object.assign(
69-
window.SP_REACT,
70-
findModule((module) => module.Component && module.PureComponent && module.useLayoutEffect),
71-
);
72-
7364
export const findModuleDetailsByExport = (
7465
filter: ExportFilterFn,
7566
minExports?: number,

typescript-packages/loader/rollup.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export default {
2626
},
2727
plugins: [
2828
del({
29-
targets: ['build/**/*'],
29+
targets: ['build/*', 'build/.*'],
30+
runOnce: true,
3031
}),
3132
resolve(),
3233
commonjs(),
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Millennium } from './millennium-api';
2+
3+
function addStyleSheetFromText(document: Document, innerStyle: string, id?: string) {
4+
if (document.querySelectorAll(`style[id='${id}']`).length) return;
5+
6+
document.head.appendChild(Object.assign(document.createElement('style'), { id: id })).innerText = innerStyle;
7+
}
8+
9+
type SystemColors = Record<string, string>;
10+
11+
export async function appendAccentColor() {
12+
const systemColors: SystemColors = JSON.parse(await Millennium.callServerMethod('core', 'GetSystemColors'));
13+
14+
const entries = Object.entries(systemColors)
15+
.map(([key, value]) => {
16+
const formattedKey = formatCssVarKey(key);
17+
return `--SystemAccentColor${formattedKey}: ${value};`;
18+
})
19+
.join('\n');
20+
21+
addStyleSheetFromText(document, `:root {\n${entries}\n}`, 'SystemAccentColorInject');
22+
}
23+
24+
function formatCssVarKey(key: string) {
25+
// Capitalize first letter and convert "Rgb" to "-RGB"
26+
return key.replace(/Rgb$/, '-RGB').replace(/^./, (c) => c.toUpperCase());
27+
}

0 commit comments

Comments
 (0)