Skip to content

Commit 273af9e

Browse files
committed
regedit
1 parent d1db89a commit 273af9e

File tree

10 files changed

+327
-9
lines changed

10 files changed

+327
-9
lines changed

dreamlandjs

public/assets/icons/regedit.svg

Lines changed: 25 additions & 0 deletions
Loading
Lines changed: 9 additions & 0 deletions
Loading

public/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
></script>
103103
<script type="text/javascript" src="lib/coreapps/AboutApp.js"></script>
104104
<script type="text/javascript" src="lib/coreapps/Dialog.js"></script>
105+
<script type="text/javascript" src="lib/coreapps/RegEdit.js"></script>
105106
<script
106107
type="text/javascript"
107108
src="lib/libs/NodePolyfills/NodeFS.js"

src/Boot.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ document.addEventListener("anura-login-completed", async () => {
477477
const explore = new ExploreApp();
478478
anura.registerApp(explore);
479479

480+
const regedit = new RegEdit();
481+
anura.registerApp(regedit);
482+
480483
const dialog = new Dialog();
481484
const dialogApp = await anura.registerApp(dialog);
482485
(anura.dialog as any) = dialogApp;

src/api/Settings.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class Settings {
2-
private cache: { [key: string]: any } = {};
2+
cache: { [key: string]: any } = {};
33
fs: AnuraFilesystem;
44
private constructor(fs: AnuraFilesystem, inital: { [key: string]: any }) {
55
this.fs = fs;
@@ -59,6 +59,10 @@ class Settings {
5959
initial["user-xapps"] = [];
6060
}
6161

62+
if (!initial["disable-regedit-warning"]) {
63+
initial["disable-regedit-warning"] = false;
64+
}
65+
6266
try {
6367
const raw = await fs.promises.readFile("/anura_settings.json");
6468
// This Uint8Array is actuallly a buffer, so JSON.parse can handle it
@@ -77,11 +81,16 @@ class Settings {
7781
return prop in this.cache;
7882
}
7983
async set(prop: string, val: any, subprop?: string) {
84+
console.debug("Setting " + prop + " to " + val);
8085
if (subprop) {
8186
this.cache[prop][subprop] = val;
8287
} else {
8388
this.cache[prop] = val;
8489
}
90+
this.save();
91+
}
92+
async save() {
93+
console.debug("Saving settings to fs", this.cache);
8594
await this.fs.promises.writeFile(
8695
"/anura_settings.json",
8796
JSON.stringify(this.cache),
@@ -96,9 +105,6 @@ class Settings {
96105
} else {
97106
delete this.cache[prop];
98107
}
99-
await this.fs.promises.writeFile(
100-
"/anura_settings.json",
101-
JSON.stringify(this.cache),
102-
);
108+
this.save();
103109
}
104110
}

src/coreapps/RegEdit.tsx

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
function hasChildren(entry: any[]) {
2+
return (
3+
Object.entries(entry[1]).filter((setting) => {
4+
return (
5+
setting[1] instanceof Object && !(setting[1] instanceof Array)
6+
);
7+
}).length > 0
8+
);
9+
}
10+
11+
const DisclosureGroup: Component<{
12+
entry: any[];
13+
sel: { [key: string]: any };
14+
level?: number;
15+
}> = function () {
16+
if (!this.level) this.level = 1;
17+
18+
this.css = `
19+
margin-left: ${0.8 * this.level!}em;
20+
`;
21+
22+
return (
23+
<div>
24+
{hasChildren(this.entry) ? (
25+
<details>
26+
<summary>
27+
<span
28+
on:click={(e: MouseEvent) => {
29+
e.preventDefault();
30+
this.sel = this.entry[1];
31+
}}
32+
>
33+
{this.entry[0]}
34+
</span>
35+
</summary>
36+
{Object.entries(this.entry[1])
37+
.filter((setting) => {
38+
return (
39+
setting[1] instanceof Object &&
40+
!(setting[1] instanceof Array)
41+
);
42+
})
43+
.map((item: any) => (
44+
<DisclosureGroup
45+
entry={item}
46+
bind:sel={use(this.sel)}
47+
sel={this.sel}
48+
level={this.level! + 1}
49+
/>
50+
))}
51+
</details>
52+
) : (
53+
<span
54+
on:click={() => {
55+
this.sel = this.entry[1];
56+
}}
57+
>
58+
{this.entry[0]}
59+
</span>
60+
)}
61+
</div>
62+
);
63+
};
64+
65+
class RegEdit extends App {
66+
hidden = false;
67+
constructor() {
68+
super();
69+
this.name = "Registry Editor";
70+
this.icon = "/assets/icons/regedit.svg";
71+
this.package = "anura.regedit";
72+
}
73+
74+
css = css`
75+
display: flex;
76+
border-top: 1px solid var(--theme-border) #pane-left {
77+
width: max(10%, 200px);
78+
border-right: 1px solid var(--theme-border);
79+
overflow: scroll;
80+
text-overflow: nowrap;
81+
white-space: nowrap;
82+
padding-left: 0.5em;
83+
}
84+
85+
#pane-right {
86+
width: calc(100% - max(10%, 200px));
87+
min-width: 400px;
88+
padding-inline: 0.5em;
89+
}
90+
91+
#detail {
92+
width: 100%;
93+
height: 100%;
94+
}
95+
96+
table {
97+
width: 100%;
98+
margin: 0;
99+
}
100+
101+
.value {
102+
overflow: hidden;
103+
text-overflow: ellipsis;
104+
white-space: nowrap;
105+
max-width: 8em;
106+
}
107+
108+
.name {
109+
max-width: 8em;
110+
overflow: hidden;
111+
text-overflow: ellipsis;
112+
white-space: nowrap;
113+
}
114+
`;
115+
state = $state({
116+
selected: anura.settings.cache,
117+
});
118+
119+
page = async () => (
120+
<div
121+
style={{
122+
height: "100%",
123+
width: "100%",
124+
position: "absolute",
125+
color: use(anura.ui.theme.state.foreground),
126+
background: use(anura.ui.theme.state.background),
127+
}}
128+
class={`background ${this.css}`}
129+
>
130+
<div id="pane-left">
131+
<div id="detail">
132+
<details open>
133+
<summary>
134+
<span
135+
on:click={(e: MouseEvent) => {
136+
e.preventDefault();
137+
this.state.selected = anura.settings.cache;
138+
}}
139+
>
140+
System
141+
</span>
142+
</summary>
143+
{Object.entries(anura.settings.cache)
144+
.filter((setting) => {
145+
return (
146+
setting[1] instanceof Object &&
147+
!(setting[1] instanceof Array)
148+
);
149+
})
150+
.map((item: any) => (
151+
<DisclosureGroup
152+
entry={item}
153+
bind:sel={use(this.state.selected)}
154+
sel={this.state.selected}
155+
/>
156+
))}
157+
</details>
158+
</div>
159+
</div>
160+
161+
<div id="pane-right">
162+
{/* someone else can make this resizable, i cba */}
163+
<table>
164+
<tr>
165+
<th>Name</th>
166+
<th>Type</th>
167+
<th>Value</th>
168+
</tr>
169+
{use(this.state.selected, (sel) =>
170+
Object.entries(sel)
171+
.filter((setting) => {
172+
return (
173+
!(setting[1] instanceof Object) ||
174+
setting[1] instanceof Array
175+
);
176+
})
177+
.map((item: any) => (
178+
<tr
179+
on:dblclick={() => {
180+
switch (typeof item[1]) {
181+
case "boolean":
182+
anura.dialog
183+
.confirm(
184+
`The key will be set to ${!item[1]}`,
185+
`Change value of ${item[0]}?`,
186+
)
187+
.then((value) => {
188+
if (value) {
189+
sel[item[0]] =
190+
!item[1];
191+
anura.settings.save();
192+
}
193+
});
194+
break;
195+
case "number":
196+
anura.dialog
197+
.prompt(
198+
`Enter new value for ${item[0]}`,
199+
item[1],
200+
)
201+
.then((value) => {
202+
if (value !== null) {
203+
const val2 = parseInt(
204+
value as string,
205+
);
206+
sel[item[0]] = val2;
207+
anura.settings.save();
208+
}
209+
});
210+
break;
211+
case "object":
212+
// anura.dialog.prompt(`Enter new value for ${item[0]}`, item[1])
213+
// .then((value) => {
214+
// if (value !== null) {
215+
// let val2 = JSON.parse(value as string);
216+
// sel[item[0]] = val2;
217+
// anura.settings.save();
218+
// }
219+
// });
220+
break;
221+
default:
222+
anura.dialog
223+
.prompt(
224+
`Enter new value for ${item[0]}`,
225+
item[1],
226+
)
227+
.then((value) => {
228+
if (value !== null) {
229+
const val2 =
230+
value as string;
231+
sel[item[0]] = val2;
232+
anura.settings.save();
233+
}
234+
});
235+
break;
236+
}
237+
}}
238+
>
239+
<td class="name">{item[0]}</td>
240+
<td class="type">{typeof item[1]}</td>
241+
<td class="value">{item[1]}</td>
242+
</tr>
243+
)),
244+
)}
245+
</table>
246+
</div>
247+
</div>
248+
);
249+
250+
async open(): Promise<WMWindow | undefined> {
251+
const win = anura.wm.create(this, {
252+
title: "Registry Editor",
253+
width: "910px",
254+
height: `${(720 * window.innerHeight) / 1080}px`,
255+
resizable: true,
256+
});
257+
258+
win.content.appendChild(await this.page());
259+
if (!anura.settings.get("disable-regedit-warning")) {
260+
anura.dialog
261+
.confirm(
262+
"Are you sure you want to continue?",
263+
"Editing the registry can cause irreparable damage to your system!",
264+
)
265+
.then((value) => {
266+
if (value === false) {
267+
win.close();
268+
}
269+
});
270+
}
271+
272+
return win;
273+
}
274+
}

src/coreapps/TaskManager.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class TaskManager extends App {
33
constructor() {
44
super();
55
this.name = "Task Manager";
6-
this.icon = "/assets/icons/generic.png";
6+
this.icon = "/assets/icons/system-monitor.svg";
77
this.package = "anura.taskmgr";
88
}
99

x86_image_wizard/twisp

0 commit comments

Comments
 (0)