Skip to content

Commit 260deb9

Browse files
authored
Merge pull request #236 from ArcOS-Project/dev-izk-configuration-builder
Dev izk configuration builder
2 parents fef921c + f1c44c1 commit 260deb9

21 files changed

Lines changed: 279 additions & 341 deletions

File tree

src/apps/components/apppermissions/AppPermissions.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
99
const { process }: { process: AppPermissionsRuntime } = $props();
1010
const { targetApp } = process;
11-
const { Configuration } = Permissions!;
11+
const { Storage } = Permissions!;
1212
1313
let permissionId = $state<string>("");
1414
1515
onMount(() => {
16-
Configuration.subscribe((permissions) => {
16+
Storage.subscribe((permissions) => {
1717
const reg = permissions?.registration ?? {};
1818
permissionId = Object.keys(reg).find((key) => reg[key] === $targetApp.id) ?? "";
1919
});

src/apps/components/apppermissions/AppPermissions/PermissionRow.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
import { onMount } from "svelte";
55
66
const { id, permissionId }: { id: PermissionString; permissionId: string } = $props();
7-
const { Configuration } = Permissions!;
7+
const { Storage } = Permissions!;
88
99
const options = ["Unset", "Allow", "Deny"] as const;
1010
type Option = (typeof options)[number];
1111
1212
let option = $state<Option>("Unset");
1313
1414
onMount(() => {
15-
Configuration.subscribe((permissions) => {
15+
Storage.subscribe((permissions) => {
1616
const state = permissions.allowed[permissionId]?.includes(id)
1717
? "Allow"
1818
: permissions.denied[permissionId]?.includes(id)

src/apps/components/iconpicker/runtime.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class IconPickerRuntime extends AppProcess {
3737
const iconService = Daemon?.serviceHost?.getService<IconService>("IconService");
3838

3939
if (!iconService) return false;
40-
this.store = iconService.Configuration();
40+
this.store = iconService.Icons();
4141
this.groups = iconService.getGroupedIcons();
4242
}
4343

src/apps/components/wallpaper/Wallpaper/DesktopIcon.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
let movingX = $state<number>();
4141
let movingY = $state<number>();
4242
43-
const { userPreferences, Configuration, selected, orphaned } = process;
43+
const { userPreferences, Positions, selected, orphaned } = process;
4444
4545
async function updatePos() {
46-
const pos = $Configuration[`icon$${identifier}`] as {
46+
const pos = $Positions[`icon$${identifier}`] as {
4747
x: number;
4848
y: number;
4949
};
@@ -64,8 +64,8 @@
6464
6565
const { x, y } = target.getBoundingClientRect();
6666
67-
if (!Object.values($Configuration).filter((pos) => pos.x === x && pos.y === y).length) {
68-
$Configuration[`icon$${identifier}`] = {
67+
if (!Object.values($Positions).filter((pos) => pos.x === x && pos.y === y).length) {
68+
$Positions[`icon$${identifier}`] = {
6969
x,
7070
y,
7171
};
@@ -87,7 +87,7 @@
8787
}
8888
8989
onMount(updatePos);
90-
Configuration.subscribe(updatePos);
90+
Positions.subscribe(updatePos);
9191
</script>
9292

9393
<!-- svelte-ignore event_directive_deprecated -->

src/apps/components/wallpaper/runtime.ts

Lines changed: 13 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { AppProcess } from "$ts/apps/process";
2+
import { ConfigurationBuilder } from "$ts/config";
23
import { Daemon } from "$ts/daemon";
34
import { Env, Fs, SysDispatch } from "$ts/env";
45
import { UserPaths } from "$ts/user/store";
5-
import { arrayBufferToText, textToBlob } from "$ts/util/convert";
66
import { MessageBox } from "$ts/util/dialog";
77
import { getItemNameFromPath, join } from "$ts/util/fs";
8-
import { tryJsonParse } from "$ts/util/json";
98
import { Store } from "$ts/writable";
109
import type { AppContextMenu, AppProcessData } from "$types/app";
1110
import type { DirectoryReadReturn } from "$types/fs";
@@ -23,7 +22,14 @@ export class WallpaperRuntime extends AppProcess {
2322
orphaned = Store<string[]>([]);
2423
loading = Store<boolean>(false);
2524
directory: string;
26-
Configuration = Store<DesktopIcons>({});
25+
Positions = Store<DesktopIcons>({});
26+
Configuration = new ConfigurationBuilder<DesktopIcons>()
27+
.ForProcess(this)
28+
.ReadsFrom(this.Positions)
29+
.WritesTo(this.CONFIG_PATH)
30+
.WithDefaults({})
31+
.WithCooldown(500)
32+
.Build();
2733

2834
public contextMenu: AppContextMenu = WallpaperContextMenu(this);
2935

@@ -45,18 +51,7 @@ export class WallpaperRuntime extends AppProcess {
4551
}
4652

4753
async start() {
48-
const migrated = await this.migrateDesktopIcons();
49-
if (!migrated) await this.loadConfiguration();
50-
51-
let firstSub = false;
52-
53-
this.Configuration.subscribe((v) => {
54-
if (!firstSub) {
55-
firstSub = true;
56-
return;
57-
}
58-
this.writeConfiguration(v);
59-
});
54+
await this.Configuration.initialize();
6055
}
6156

6257
async render() {
@@ -105,7 +100,7 @@ export class WallpaperRuntime extends AppProcess {
105100

106101
findAndDeleteOrphans(contents: DirectoryReadReturn | undefined) {
107102
const orphaned = this.orphaned();
108-
const config = this.Configuration();
103+
const config = this.Positions();
109104
let orphanedCount = 0;
110105

111106
for (const id of Object.keys(config)) {
@@ -123,7 +118,7 @@ export class WallpaperRuntime extends AppProcess {
123118
}
124119
}
125120

126-
if (orphanedCount) this.Configuration.set(config);
121+
if (orphanedCount) this.Positions.set(config);
127122
this.orphaned.set(orphaned);
128123
}
129124

@@ -133,7 +128,7 @@ export class WallpaperRuntime extends AppProcess {
133128
if (!wrapper) return { x: 0, y: 0 };
134129

135130
return new Promise((r) => {
136-
this.Configuration.update((v) => {
131+
this.Positions.update((v) => {
137132
function resolve(x: number, y: number) {
138133
r({ x, y });
139134
v[`icon$${identifier}`] = { x, y };
@@ -247,55 +242,5 @@ export class WallpaperRuntime extends AppProcess {
247242
prog.mutDone(+1);
248243
}
249244

250-
//#endregion
251-
//#region CONFIGURATION
252-
253-
async loadConfiguration() {
254-
this.Log(`Loading configuration`);
255-
256-
try {
257-
const contents = await Fs.readFile(this.CONFIG_PATH);
258-
if (!contents) return await this.writeConfiguration({});
259-
260-
const json = tryJsonParse<DesktopIcons>(arrayBufferToText(contents));
261-
if (!json || typeof json === "string") return await this.writeConfiguration({});
262-
263-
this.Configuration.set(json);
264-
} catch {}
265-
}
266-
267-
async writeConfiguration(data: DesktopIcons) {
268-
this.Log(`Writing configuration`);
269-
270-
await Fs.writeFile(this.CONFIG_PATH, textToBlob(JSON.stringify(data, null, 2)));
271-
272-
return data;
273-
}
274-
275-
// 7.0.5 -> 7.0.6+
276-
// Migration of desktop icons from the preferences to a dedicated file in U:/System
277-
async migrateDesktopIcons() {
278-
this.Log(`migrateDesktopIcons`);
279-
280-
const migrationPath = join(UserPaths.Migrations, "DeskIconMig-706.lock");
281-
const pref = this.userPreferences().appPreferences.desktopIcons;
282-
const migration = await Fs.stat(migrationPath);
283-
284-
if (pref && !migration) {
285-
await this.writeConfiguration(pref);
286-
this.Configuration.set(pref);
287-
288-
this.userPreferences.update((v) => {
289-
delete v.appPreferences.desktopIcons;
290-
return v;
291-
});
292-
293-
await Fs.writeFile(migrationPath, textToBlob(`${Date.now()}`));
294-
return true;
295-
}
296-
297-
return false;
298-
}
299-
300245
//#endregion
301246
}

src/apps/user/filemanager/FileManager/Virtual/MyArcOS/RecentFiles.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
const { process }: { process: FileManagerRuntime } = $props();
99
const { userPreferences } = process;
1010
const service = Daemon.serviceHost?.getService<RecentFilesService>("RecentFilesSvc");
11-
const Configuration = service?.Configuration;
11+
const Rrecents = service?.Recents;
1212
1313
let selected = $state<string>("");
1414
</script>
1515

16-
{#if Configuration}
16+
{#if Rrecents}
1717
<section class="recent-files">
1818
<button
1919
class="expander"
@@ -26,7 +26,7 @@
2626
{
2727
caption: "Clear recents",
2828
icon: "x",
29-
action: () => service.Configuration.set([]),
29+
action: () => service.Recents.set([]),
3030
},
3131
],
3232
process,
@@ -37,10 +37,10 @@
3737
</button>
3838
{#if $userPreferences.appPreferences.fileManager.myExpandRecents}
3939
<div class="content">
40-
{#if !$Configuration?.length}
40+
{#if !$Rrecents?.length}
4141
<p class="empty">The files you open will appear in this list.</p>
4242
{:else}
43-
{#each $Configuration as path (path)}
43+
{#each $Rrecents as path (path)}
4444
<RecentFile {path} {service} {process} bind:selected />
4545
{/each}
4646
{/if}

src/apps/user/iconeditor/runtime.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class IconEditorRuntime extends AppProcess {
2424
async start() {
2525
this.iconService = Daemon?.serviceHost?.getService<IconService>("IconService");
2626
this.setGroups();
27-
this.icons.set({ ...(this.iconService?.Configuration() || {}) });
27+
this.icons.set({ ...(this.iconService?.Icons() || {}) });
2828
this.icons.subscribe(() => {
2929
this.hasChanges.set(true);
3030
this.updateFiltered();
@@ -49,7 +49,7 @@ export class IconEditorRuntime extends AppProcess {
4949
);
5050

5151
if (saveChanges) {
52-
this.iconService?.Configuration.set({ ...this.icons() });
52+
this.iconService?.Icons.set({ ...this.icons() });
5353
this.hasChanges.set(false);
5454
}
5555

@@ -60,7 +60,7 @@ export class IconEditorRuntime extends AppProcess {
6060

6161
revert() {
6262
this.Log(`Reverting changes`);
63-
this.icons.set({ ...(this.iconService?.Configuration() || {}) });
63+
this.icons.set({ ...(this.iconService?.Icons() || {}) });
6464
this.setGroups();
6565
this.selectedIcon.set("");
6666
this.selectedGroup.set("");
@@ -88,7 +88,7 @@ export class IconEditorRuntime extends AppProcess {
8888
async save() {
8989
this.Log(`Saving changes`);
9090

91-
this.iconService?.Configuration.set({ ...this.icons() });
91+
this.iconService?.Icons.set({ ...this.icons() });
9292
this.hasChanges.set(false);
9393
await this.closeWindow();
9494

src/apps/user/mediaplayer/runtime.ts

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { MediaPlayerAltMenu } from "./altmenu";
1919
import TrayPopup from "./MediaPlayer/TrayPopup.svelte";
2020
import { LoopMode, type AudioFileMetadata, type MetadataConfiguration, type PlayerState } from "./types";
2121
import { CommandResult } from "$ts/result";
22+
import { ConfigurationBuilder } from "$ts/config";
2223

2324
export class MediaPlayerRuntime extends AppProcess {
2425
private readonly METADATA_PATH = join(UserPaths.Configuration, "MediaPlayer", "Metadata.json");
@@ -38,6 +39,12 @@ export class MediaPlayerRuntime extends AppProcess {
3839
CurrentCoverUrl = Store<string | undefined>();
3940
LoadingMetadata = Store<boolean>(false);
4041
mediaSpecificAccentColor = Store<string>("");
42+
Configuration = new ConfigurationBuilder()
43+
.ForProcess(this)
44+
.ReadsFrom(this.MetadataConfiguration)
45+
.WritesTo(this.METADATA_PATH)
46+
.WithDefaults({})
47+
.Build();
4148

4249
override contextMenu: AppContextMenu = {
4350
player: [
@@ -111,14 +118,8 @@ export class MediaPlayerRuntime extends AppProcess {
111118
protected async start(): Promise<any> {
112119
await Fs.createDirectory(getParentDirectory(this.METADATA_PATH));
113120
await Fs.createDirectory(this.COVERIMAGES_PATH);
114-
await this.readConfiguration();
121+
await this.Configuration.initialize();
115122

116-
let firstSub = false;
117-
this.MetadataConfiguration.subscribe((v) => {
118-
if (!firstSub) return (firstSub = true);
119-
120-
this.writeConfiguration(v);
121-
});
122123
this.CurrentMediaMetadata.subscribe((v) => {
123124
if (!v?.title) return;
124125

@@ -588,26 +589,6 @@ export class MediaPlayerRuntime extends AppProcess {
588589
//#endregion
589590
//#region METADATA
590591

591-
async readConfiguration() {
592-
try {
593-
const content = await Fs.readFile(this.METADATA_PATH);
594-
if (!content) throw new Error("Failed to read file contents");
595-
596-
const json = tryJsonParse(arrayBufferToText(content));
597-
if (!json || typeof json === "string") throw new Error("File contents could not be parsed as JSON");
598-
599-
this.MetadataConfiguration.set(json);
600-
} catch {
601-
return await this.writeConfiguration({});
602-
}
603-
}
604-
605-
async writeConfiguration(configuration: MetadataConfiguration) {
606-
this.Log(`writeConfiguration`);
607-
608-
await Fs.writeFile(this.METADATA_PATH, textToBlob(JSON.stringify(configuration, null, 2)), undefined, false);
609-
}
610-
611592
async normalizeMetadata(meta: IAudioMetadata): Promise<AudioFileMetadata> {
612593
this.Log(`normalizeMetadata`);
613594

src/interfaces/config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface IConfigurator<T = object> {
2+
readConfiguration(): Promise<T>;
3+
writeConfiguration(configuration?: T): Promise<T>;
4+
initialize(): Promise<void>;
5+
}

src/interfaces/permission.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import type {
88
} from "$types/fs";
99
import type { PermissionStorage } from "$types/permission";
1010
import type { ReadableStore } from "$types/writable";
11+
import type { IConfigurator } from "./config";
1112
import type { IFilesystemDrive } from "./fs";
1213
import type { IProcess } from "./process";
1314

1415
export interface IPermissionHandler {
1516
_criticalProcess: boolean;
16-
Configuration: ReadableStore<PermissionStorage>;
17-
readConfiguration(): Promise<void>;
18-
writeConfiguration(config: PermissionStorage): Promise<void>;
17+
Storage: ReadableStore<PermissionStorage>;
18+
Configuration: IConfigurator<PermissionStorage>;
1919
hasPermission(process: IProcess, permission: PermissionString): boolean;
2020
grantPermission(process: IProcess, permission: PermissionString): void;
2121
revokePermission(process: IProcess, permission: PermissionString): void;

0 commit comments

Comments
 (0)