diff --git a/src/apps/admin/adminportal/AdminPortal/Page/BugHunt/QuickView.svelte b/src/apps/admin/adminportal/AdminPortal/Page/BugHunt/QuickView.svelte
index 74a0f77d8..6c99ad39b 100755
--- a/src/apps/admin/adminportal/AdminPortal/Page/BugHunt/QuickView.svelte
+++ b/src/apps/admin/adminportal/AdminPortal/Page/BugHunt/QuickView.svelte
@@ -11,7 +11,7 @@
let loading = $state(true);
onMount(async () => {
- report = await process.admin.getBugReport(id);
+ report = (await process.admin.getBugReport(id))?.report;
loading = false;
});
diff --git a/src/apps/admin/adminportal/store.ts b/src/apps/admin/adminportal/store.ts
index 421247cbf..be03666da 100755
--- a/src/apps/admin/adminportal/store.ts
+++ b/src/apps/admin/adminportal/store.ts
@@ -73,7 +73,7 @@ export const AdminPortalPageStore: AdminPortalPages = new Map {
const id = process.switchPageProps().id;
- return { report: await process.admin.getBugReport(id) };
+ return (await process.admin.getBugReport(id)) ?? {};
},
},
],
@@ -89,9 +89,9 @@ export const AdminPortalPageStore: AdminPortalPages = new Map {
const id = process.switchPageProps().id;
const report = await process.admin.getBugReport(id);
- if (!report) return { report };
+ if (!report) return report;
- const source = await process.admin.getReportSourceFile(report);
+ const source = await process.admin.getReportSourceFile(report.report);
return { report, source };
},
diff --git a/src/apps/components/messagecomposer/MessageComposer.ts b/src/apps/components/messagecomposer/MessageComposer.ts
index 9109b8013..8d71b7fc0 100644
--- a/src/apps/components/messagecomposer/MessageComposer.ts
+++ b/src/apps/components/messagecomposer/MessageComposer.ts
@@ -12,8 +12,8 @@ export const MessageComposerApp: App = {
appGroup: "multimedia",
},
position: { centered: true },
- size: { w: 800, h: 650 },
- minSize: { w: 800, h: 650 },
+ size: { w: 800, h: 500 },
+ minSize: { w: 800, h: 500 },
maxSize: { w: NaN, h: NaN },
state: {
maximized: false,
diff --git a/src/apps/core/loginapp/runtime.ts b/src/apps/core/loginapp/runtime.ts
index af39e6917..b9f30c7d0 100755
--- a/src/apps/core/loginapp/runtime.ts
+++ b/src/apps/core/loginapp/runtime.ts
@@ -237,6 +237,9 @@ export class LoginAppRuntime extends AppProcess implements ILoginAppRuntime {
};
if (userDaemon) {
+ broadcast("Notifying login activity");
+ await userDaemon.activity?.logActivity("shutdown");
+
broadcast("Stopping Service Host");
await userDaemon.serviceHost?.spinDown(broadcast);
@@ -268,6 +271,9 @@ export class LoginAppRuntime extends AppProcess implements ILoginAppRuntime {
this.loadingStatus.set(`Restarting...`);
if (userDaemon) {
+ broadcast("Notifying login activity");
+ await userDaemon.activity?.logActivity("shutdown");
+
broadcast("Stopping Service Host");
await userDaemon.serviceHost?.spinDown(broadcast);
diff --git a/src/apps/core/newloginapp/NewLogin.svelte b/src/apps/core/newloginapp/NewLogin.svelte
index 79819fca5..573a1d0ce 100644
--- a/src/apps/core/newloginapp/NewLogin.svelte
+++ b/src/apps/core/newloginapp/NewLogin.svelte
@@ -31,7 +31,7 @@
{:else if $Status.variant === LoginStatusVariant.Loading}
-
+
{@html $Status.content}
diff --git a/src/apps/core/newloginapp/runtime.ts b/src/apps/core/newloginapp/runtime.ts
index 1ba59437c..81b669372 100644
--- a/src/apps/core/newloginapp/runtime.ts
+++ b/src/apps/core/newloginapp/runtime.ts
@@ -32,6 +32,7 @@ import {
type LoginState,
type LoginStatus,
} from "./types";
+import { LoginUserDaemonStartOptions } from "../loginapp/store";
export class NewLoginAppRuntime extends AppProcess implements INewLoginAppRuntime {
private readonly PERSISTENCE_LS_ID = "arcNewLoginPersistence";
@@ -222,6 +223,12 @@ export class NewLoginAppRuntime extends AppProcess implements INewLoginAppRuntim
this.ShowLoading("Saving token");
this.SaveToken(userDaemon!);
+ // await new Promise(async (r) => {
+ // while (true) {
+ // await Sleep(1);
+ // }
+ // });
+
const result = await userDaemon?.startUserDaemon(NewLoginUserDaemonStartOptions(this), broadcast.bind(this));
this.SaveUserPersistence(userDaemon?.userInfo!);
diff --git a/src/apps/user/settings/Settings/Slides/ManageApps.svelte b/src/apps/user/settings/Settings/Slides/ManageApps.svelte
index 612c44c74..6d02c4b65 100755
--- a/src/apps/user/settings/Settings/Slides/ManageApps.svelte
+++ b/src/apps/user/settings/Settings/Slides/ManageApps.svelte
@@ -1,13 +1,16 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
{#if !$store.length}
No results!
{:else}
{#each $store as app (`${app.originId}-${app.id}-${app.metadata.name}`)}
-
+ {#if view === "grid"}
+
+ {:else if view === "list"}
+
+ {/if}
{/each}
{/if}
diff --git a/src/apps/user/settings/Settings/Slides/ManageApps/FIlter.svelte b/src/apps/user/settings/Settings/Slides/ManageApps/FIlter.svelte
new file mode 100644
index 000000000..af73faf4d
--- /dev/null
+++ b/src/apps/user/settings/Settings/Slides/ManageApps/FIlter.svelte
@@ -0,0 +1,14 @@
+
+
+
diff --git a/src/apps/user/settings/Settings/Slides/ManageApps/GridAppItem.svelte b/src/apps/user/settings/Settings/Slides/ManageApps/GridAppItem.svelte
new file mode 100644
index 000000000..ca2999312
--- /dev/null
+++ b/src/apps/user/settings/Settings/Slides/ManageApps/GridAppItem.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/apps/user/settings/Settings/Slides/ManageApps/GridListItem.svelte b/src/apps/user/settings/Settings/Slides/ManageApps/GridListItem.svelte
new file mode 100644
index 000000000..b8deb8175
--- /dev/null
+++ b/src/apps/user/settings/Settings/Slides/ManageApps/GridListItem.svelte
@@ -0,0 +1,24 @@
+
+
+
diff --git a/src/apps/user/settings/Settings/Slides/ManageApps/SearchBar.svelte b/src/apps/user/settings/Settings/Slides/ManageApps/SearchBar.svelte
new file mode 100644
index 000000000..3d5019148
--- /dev/null
+++ b/src/apps/user/settings/Settings/Slides/ManageApps/SearchBar.svelte
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/apps/user/settings/Settings/Slides/ManageApps/ViewMode.svelte b/src/apps/user/settings/Settings/Slides/ManageApps/ViewMode.svelte
new file mode 100644
index 000000000..e08624f54
--- /dev/null
+++ b/src/apps/user/settings/Settings/Slides/ManageApps/ViewMode.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/src/apps/user/settings/store/index.ts b/src/apps/user/settings/store/index.ts
index 679d11153..7bcde3619 100755
--- a/src/apps/user/settings/store/index.ts
+++ b/src/apps/user/settings/store/index.ts
@@ -34,7 +34,7 @@ export const settingsPageStore: SettingsPages = new Map([
[
"wallpaper",
{
- name: "Wallpaper",
+ name: "Desktop Wallpaper",
icon: "DesktopIcon",
content: Wallpaper,
description: "Change your desktop wallpaper",
@@ -54,7 +54,7 @@ export const settingsPageStore: SettingsPages = new Map([
[
"visuals",
{
- name: "Visuals",
+ name: "Appearance",
icon: "PersonalizationIcon",
content: Visuals,
separator: true,
@@ -64,7 +64,7 @@ export const settingsPageStore: SettingsPages = new Map([
[
"shell",
{
- name: "Shell",
+ name: "Taskbar and start menu",
icon: "TaskbarIcon",
content: Shell,
description: "The taskbar, start menu and action center",
@@ -73,7 +73,7 @@ export const settingsPageStore: SettingsPages = new Map([
[
"search",
{
- name: "Search",
+ name: "ArcOS Search",
icon: "ArcFindIcon",
content: Search,
description: "The search functionality of ArcOS",
@@ -83,7 +83,7 @@ export const settingsPageStore: SettingsPages = new Map([
[
"apps",
{
- name: "Apps",
+ name: "Applications",
icon: "AppsIcon",
content: Apps,
separator: true,
diff --git a/src/apps/user/settings/systemSettings.ts b/src/apps/user/settings/systemSettings.ts
index 07151b50b..69c877ef7 100644
--- a/src/apps/user/settings/systemSettings.ts
+++ b/src/apps/user/settings/systemSettings.ts
@@ -6,13 +6,13 @@ import Settings from "./Settings.svelte";
export const SystemSettings: App = {
metadata: {
name: "System Settings",
- author: "Izaak Kuipers",
+ author: "Izaak Kuipers",
version: "6.0.4",
icon: "SettingsIcon",
appGroup: "systemTools",
},
- size: { w: 730, h: 560 },
- minSize: { w: 730, h: 560 },
+ size: { w: 810, h: 560 },
+ minSize: { w: 810, h: 560 },
maxSize: { w: 1000, h: 800 },
position: { centered: true },
state: {
diff --git a/src/css/apps/user/logging.css b/src/css/apps/user/logging.css
index bc9d30799..aaf277bc6 100755
--- a/src/css/apps/user/logging.css
+++ b/src/css/apps/user/logging.css
@@ -137,7 +137,8 @@
}
#logging > div.body div.log-list div.row div.segment.message {
- max-width: calc(100% - 160px - 16px - 20px);
+ width: 0;
+ flex-grow: 1;
}
#logging > div.body div.log-list div.row div.segment:not(.icon) {
diff --git a/src/css/apps/user/settings/page/loginbackground.css b/src/css/apps/user/settings/page/loginbackground.css
index 73433beac..1f3cf1686 100755
--- a/src/css/apps/user/settings/page/loginbackground.css
+++ b/src/css/apps/user/settings/page/loginbackground.css
@@ -1,7 +1,7 @@
#systemSettings div.container.loginBackground div.upload-actions {
display: flex;
align-items: center;
- gap: 5px;
+ gap: 8px;
}
#systemSettings div.container.loginBackground div.upload-actions button {
@@ -32,8 +32,8 @@
}
#systemSettings div.loginBackground div.wallpaper-section div.wallpapers {
- display: grid;
- grid-template-columns: repeat(5, 70px);
+ display: flex;
+ flex-wrap: wrap;
gap: 15px;
}
diff --git a/src/css/apps/user/settings/page/wallpaper.css b/src/css/apps/user/settings/page/wallpaper.css
index 79f1d3753..98f9f424f 100755
--- a/src/css/apps/user/settings/page/wallpaper.css
+++ b/src/css/apps/user/settings/page/wallpaper.css
@@ -1,7 +1,7 @@
#systemSettings div.container.wallpaper div.upload-actions {
display: flex;
align-items: center;
- gap: 5px;
+ gap: 8px;
}
#systemSettings div.container.wallpaper div.upload-actions button {
diff --git a/src/css/apps/user/settings/section.css b/src/css/apps/user/settings/section.css
index 6d74b77f7..fb46ef202 100755
--- a/src/css/apps/user/settings/section.css
+++ b/src/css/apps/user/settings/section.css
@@ -1,5 +1,5 @@
#systemSettings section {
- width: 340px;
+ width: 350px;
margin: 0 auto;
margin-top: 20px;
}
@@ -127,3 +127,7 @@
outline: var(--button-glass-hover-bg) 1px solid;
outline-offset: -1px;
}
+
+.theme-light #systemSettings section div.content select {
+ background-color: var(--win-bg) !important;
+}
\ No newline at end of file
diff --git a/src/css/apps/user/settings/slide/loginactivity.css b/src/css/apps/user/settings/slide/loginactivity.css
index 4b66e2ea3..2921404d2 100755
--- a/src/css/apps/user/settings/slide/loginactivity.css
+++ b/src/css/apps/user/settings/slide/loginactivity.css
@@ -2,6 +2,10 @@
margin-bottom: 20px;
}
+#systemSettings div.account_loginActivity section {
+ width: 400px;
+}
+
#systemSettings div.account_loginActivity div.activity-item {
display: flex;
align-items: start;
diff --git a/src/css/apps/user/settings/slide/manageapps.css b/src/css/apps/user/settings/slide/manageapps.css
index 5db98c236..e25edda41 100755
--- a/src/css/apps/user/settings/slide/manageapps.css
+++ b/src/css/apps/user/settings/slide/manageapps.css
@@ -9,8 +9,8 @@
#systemSettings div.apps_manageApps div.options {
display: flex;
align-items: center;
- gap: 10px;
- padding: 0 10px;
+ gap: 15px;
+ padding: 0 15px;
}
#systemSettings div.apps_manageApps div.options div.view-mode {
@@ -60,18 +60,15 @@
outline-offset: -1px;
}
#systemSettings div.apps_manageApps div.apps {
- display: flex;
- flex-wrap: wrap;
- gap: 5px;
position: relative;
height: 0;
flex-grow: 1;
- padding: 10px;
+ padding: 15px;
overflow-y: scroll;
}
#systemSettings div.apps_manageApps div.apps button.app {
- display: grid;
+ display: inline-grid;
grid-template:
"icon name"
"icon author";
@@ -79,18 +76,22 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
- gap: 0 8px;
+ gap: 0 15px;
text-align: left;
--font-size: 12px;
- padding: 4px;
+ padding: 12px;
outline: none;
- border-radius: 4px;
- width: 140px;
- height: 40px;
+ border-radius: 10px;
+ width: 250px;
+ height: fit-content;
+ margin-right: 8px;
+ margin-bottom: 8px;
}
-#systemSettings div.apps_manageApps div.apps.grid-large button.app {
- width: 200px;
+#systemSettings div.apps_manageApps div.apps button.app:hover {
+ background-color: var(--button-glass-bg);
+ outline: var(--button-glass-bg) 1px solid;
+ outline-offset: -1px;
}
#systemSettings div.apps_manageApps div.apps button.app h1 {
@@ -114,17 +115,15 @@
grid-area: icon;
}
-#systemSettings div.apps_manageApps div.apps.grid-large button.app img {
- width: 40px;
- height: 40px;
-}
-
-#systemSettings div.apps_manageApps div.apps.grid-large button.app h1 {
- font-size: 14px;
+#systemSettings div.apps_manageApps div.apps button.app.list-item img {
+ width: 32px;
+ height: 32px;
}
-#systemSettings div.apps_manageApps div.apps.list {
- display: block;
+#systemSettings div.apps_manageApps div.apps button.app.list-item p.type {
+ opacity: 0.5;
+ margin-left: auto;
+ padding: 0 10px;
}
#systemSettings div.apps_manageApps div.apps.list button.app {
@@ -146,13 +145,10 @@
font-style: italic;
}
-#systemSettings div.apps_manageApps div.apps.list button.app img {
- width: 20px;
- height: 20px;
-}
-
-#systemSettings div.apps_manageApps div.apps.list button.app h1 {
- margin-right: auto;
+#systemSettings div.apps_manageApps div.apps button.app.grid-item:hover {
+ background-color: var(--button-glass-hover-bg);
+ outline: var(--button-glass-hover-bg) 1px solid;
+ outline-offset: -1px;
}
#systemSettings div.apps_manageApps p.no-results {
diff --git a/src/css/spinner.css b/src/css/spinner.css
index efdaf28e3..bc24115b5 100755
--- a/src/css/spinner.css
+++ b/src/css/spinner.css
@@ -6,10 +6,14 @@ img.spinner-svg.hide {
opacity: 0 !important;
}
-#appRenderer[class*="theme-light"] img.spinner-svg {
+.theme-light img.spinner-svg {
filter: brightness(0.4);
}
+.theme-dark img.spinner-svg {
+ filter: brightness(1);
+}
+
div.html-spinner {
--size: 32px;
--thickness: 5px;
diff --git a/src/interfaces/contexts/IFilesystemUserContext.ts b/src/interfaces/contexts/IFilesystemUserContext.ts
index f547ea33a..bcf8612ad 100644
--- a/src/interfaces/contexts/IFilesystemUserContext.ts
+++ b/src/interfaces/contexts/IFilesystemUserContext.ts
@@ -1,7 +1,7 @@
import type { FileProgressMutator, FsProgressOperation } from "$apps/components/fsprogress/types";
import type { LoadSaveDialogData } from "$apps/user/filemanager/types";
import type { ILegacyServerDrive } from "$interfaces/drives/ILegacyServerDrive";
-import type { IMemoryFilesystemDrive } from "$interfaces/drives/IMemoryFilesystemDrive";
+import type { ITemporaryFilesystemDrive } from "$interfaces/drives/ITemporaryFilesystemDrive";
import type { ICommandResult } from "$interfaces/ICommandResult";
import type { IFilesystemDrive } from "$interfaces/IFilesystemDrive";
import type { IUserContext } from "$interfaces/IUserDaemon";
@@ -12,7 +12,7 @@ import type { CategorizedDiskUsage } from "$types/user";
// !tpa
export interface IFilesystemUserContext extends IUserContext {
- TempFs?: IMemoryFilesystemDrive;
+ TempFs?: ITemporaryFilesystemDrive;
fileHandlers: Record;
mountedDrives: string[];
_init(): Promise;
diff --git a/src/interfaces/drives/IMemoryFilesystemDrive.ts b/src/interfaces/drives/ITemporaryFilesystemDrive.ts
similarity index 73%
rename from src/interfaces/drives/IMemoryFilesystemDrive.ts
rename to src/interfaces/drives/ITemporaryFilesystemDrive.ts
index 4f98eda5a..2b8d01e98 100644
--- a/src/interfaces/drives/IMemoryFilesystemDrive.ts
+++ b/src/interfaces/drives/ITemporaryFilesystemDrive.ts
@@ -1,7 +1,7 @@
import type { IFilesystemDrive } from "$interfaces/IFilesystemDrive";
// !tpa
-export interface IMemoryFilesystemDrive extends IFilesystemDrive {
+export interface ITemporaryFilesystemDrive extends IFilesystemDrive {
takeSnapshot(): Promise>;
restoreSnapshot(snapshot: Record): void;
}
diff --git a/src/interfaces/services/IAdminBootstrapper.ts b/src/interfaces/services/IAdminBootstrapper.ts
index 2f934ac6d..712e6ca84 100644
--- a/src/interfaces/services/IAdminBootstrapper.ts
+++ b/src/interfaces/services/IAdminBootstrapper.ts
@@ -6,6 +6,7 @@ import type {
AdminTemporaryPassword,
AuditLog,
AuditLogQueryOptions,
+ BugHuntGetResponse,
BugReportSourceInformation,
FSItem,
IpAddress,
@@ -54,7 +55,7 @@ export interface IAdminBootstrapper extends IBaseService {
closeBugReport(reportId: string): Promise;
reopenBugReport(reportId: string): Promise;
getAllBugReports(): Promise;
- getBugReport(id: string): Promise;
+ getBugReport(id: string): Promise;
getBugHuntStatistics(): Promise;
setSystemFor(username: string, value: boolean): Promise;
disapproveUser(username: string): Promise;
diff --git a/src/main.ts b/src/main.ts
index 8368727d2..3d0c3eb95 100755
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,14 +1,14 @@
import "dseg/css/dseg.css";
import "./css/main.css";
+import { HtmlUtil } from "$ts/util/html";
// CODE EXECUTION STARTS HERE
async function Main() {
const { WaveKernel } = await import("$ts/kernel/wavekernel");
-
const kernel = new WaveKernel();
window.__DW_STATUS__ = "async Main";
- document.querySelector("#stateLoader")!.innerText = "..";
+ HtmlUtil.GetStateLoader().innerText = "..";
await kernel._init();
}
diff --git a/src/ts/basic/commands/setpref.ts b/src/ts/basic/commands/setpref.ts
new file mode 100644
index 000000000..f2d95b956
--- /dev/null
+++ b/src/ts/basic/commands/setpref.ts
@@ -0,0 +1,29 @@
+import { Daemon } from "$ts/env";
+import { setJsonHierarchy } from "$ts/util/hierarchy";
+import { BasicCommand } from "../engine/command";
+
+export class SetprefCommand extends BasicCommand {
+ static keyword: string = "setpref";
+
+ async execute(line: string): Promise {
+ const [rawHierarchy, ...values] = await this.interpreter.getStrings(line, false);
+
+ if (!rawHierarchy) {
+ return "No hierarchy found. Did you wrap it in a string?"
+ }
+
+ if (values.length !== 1) {
+ return "SETPREF takes exactly one value";
+ }
+
+ const hierarchy = await this.interpreter.replaceVariables(rawHierarchy, false);
+ const value = await this.interpreter.replaceVariables(values[0], true);
+
+ Daemon.preferences.update((v) => {
+ setJsonHierarchy(v, hierarchy, value);
+ return v;
+ });
+
+ return undefined;
+ }
+}
diff --git a/src/ts/basic/config/commandset.ts b/src/ts/basic/config/commandset.ts
index 59dfc9b30..da4c903e9 100644
--- a/src/ts/basic/config/commandset.ts
+++ b/src/ts/basic/config/commandset.ts
@@ -5,6 +5,7 @@ import { GosubCommand } from "../commands/gosub";
import { IfCommand } from "../commands/if";
import { KillCommand } from "../commands/kill";
import { PrintCommand } from "../commands/print";
+import { SetprefCommand } from "../commands/setpref";
import { SoundbusCommand } from "../commands/soundbus";
import { StopCommand } from "../commands/stop";
import { SubCommand } from "../commands/sub";
@@ -13,16 +14,17 @@ import { WhileCommand } from "../commands/while";
import type { BasicCommand } from "../engine/command";
export const BasicCommandSet: (typeof BasicCommand)[] = [
- PrintCommand,
- IfCommand,
- VarCommand,
+ EndsubCommand,
+ ErrorCommand,
+ GostartCommand,
GosubCommand,
- SubCommand,
- StopCommand,
+ IfCommand,
KillCommand,
- GostartCommand,
- WhileCommand,
+ PrintCommand,
+ SetprefCommand,
SoundbusCommand,
- EndsubCommand,
- ErrorCommand,
+ StopCommand,
+ SubCommand,
+ VarCommand,
+ WhileCommand,
];
diff --git a/src/ts/basic/engine/index.ts b/src/ts/basic/engine/index.ts
index ef97157cc..1bbfe2dd3 100644
--- a/src/ts/basic/engine/index.ts
+++ b/src/ts/basic/engine/index.ts
@@ -391,7 +391,7 @@ export class ArcBasicEngine {
async findNextEndling(endling: string, startIdx = this.programCounter): Promise {
this.Debug(`findNextEndling >>${endling}<< startIdx=${startIdx}`);
- const lookahead = this.source.slice(startIdx, this.source.length - 1);
+ const lookahead = this.source.slice(startIdx, this.source.length);
const endKeyword = `end${endling.toLowerCase()}`;
const idx = lookahead.findIndex((l) => l.toLowerCase().trim().startsWith(endKeyword));
@@ -430,9 +430,10 @@ export class ArcBasicEngine {
await this.setVariable("ERR", message);
if (exit) {
+ this.HALT = true;
const line = this.source[this.programCounter];
const lineNumber = `${this.programCounter + 1}`;
- const columnNumber = Math.max(columnIndexHint ? line.indexOf(columnIndexHint) : 0, 0);
+ const columnNumber = Math.max(columnIndexHint ? line?.indexOf(columnIndexHint) ?? 0 : 0, 0);
const linePrefix = " ".repeat(lineNumber.length) + " ║ ";
const leftOffset = " ".repeat(columnNumber);
diff --git a/src/ts/basic/engine/regex.ts b/src/ts/basic/engine/regex.ts
index b8a983d3d..fa65e89d8 100644
--- a/src/ts/basic/engine/regex.ts
+++ b/src/ts/basic/engine/regex.ts
@@ -1,10 +1,10 @@
export const REGEXES = {
STRING: /"(?[^"]+|)"/gm,
- FUNCTION: /(?[a-zA-Z]+)\((?.+|)\)/gm,
+ FUNCTION: /\b(?[a-zA-Z]+)\((?(?:"(?:[^"\\]|\\.)*"|[^()"])*)\)/gm,
IF: /(?NOT |not |)(?.+) (?:THEN|then)($| (?.+))/,
DUALEXPR: /(?.+) (?[A-Za-z]+) (?.+)/,
WHILE: /(?NOT |not |)(?.+) (?:DO|do)($| (?.+))/,
- VARGET: /\$(?[A-Za-z]{1,6})(?:\[(?[0-9\-]+|\+|\$[A-Za-z]{1,6}|LEN)\]|\{(?[a-zA-Z\_\.0-9]+)\}|)/g,
+ VARGET: /\$(?[A-Za-z]{1,6})(?:\[(?[0-9\-]+|\+|\$[A-Za-z]{1,6}|LEN|len)\]|\{(?[a-zA-Z\_\.0-9]+)\}|)/g,
VARSET:
- /(?[A-Za-z]{1,6})(?:\[(?[0-9\-]+|\+|\$[A-Za-z]{1,6}|LEN)\]|\{(?[a-zA-Z\_\.0-9]+)\}|) = (?.+|)/,
+ /(?[A-Za-z]{1,6})(?:\[(?[0-9\-]+|\+|\$[A-Za-z]{1,6}|LEN|len)\]|\{(?[a-zA-Z\_\.0-9]+)\}|) = (?.+|)/,
};
diff --git a/src/ts/basic/highlight.ts b/src/ts/basic/highlight.ts
index 7b698da32..98d7d0f54 100644
--- a/src/ts/basic/highlight.ts
+++ b/src/ts/basic/highlight.ts
@@ -24,6 +24,7 @@ export default function ArcBasicHighlighter(hljs: HLJSApi): Language {
"THEN",
"VAR",
"WHILE",
+ "SETPREF"
];
const VARGET = {
diff --git a/src/ts/daemon/contexts/filesystem.ts b/src/ts/daemon/contexts/filesystem.ts
index 8e7cc29fb..731c4558a 100644
--- a/src/ts/daemon/contexts/filesystem.ts
+++ b/src/ts/daemon/contexts/filesystem.ts
@@ -2,7 +2,7 @@ import { DummyFileProgress, type FileProgressMutator, type FsProgressOperation }
import type { LoadSaveDialogData } from "$apps/user/filemanager/types";
import type { IFilesystemUserContext } from "$interfaces/contexts/IFilesystemUserContext";
import type { ILegacyServerDrive } from "$interfaces/drives/ILegacyServerDrive";
-import type { IMemoryFilesystemDrive } from "$interfaces/drives/IMemoryFilesystemDrive";
+import type { ITemporaryFilesystemDrive } from "$interfaces/drives/ITemporaryFilesystemDrive";
import type { ICommandResult } from "$interfaces/ICommandResult";
import type { IFilesystemDrive } from "$interfaces/IFilesystemDrive";
import type { IUserDaemon } from "$interfaces/IUserDaemon";
@@ -30,7 +30,7 @@ import { UserContext } from "../context";
export class FilesystemUserContext extends UserContext implements IFilesystemUserContext {
private thumbnailCache: Record = {};
- public TempFs?: IMemoryFilesystemDrive;
+ public TempFs?: ITemporaryFilesystemDrive;
public fileHandlers: Record;
public mountedDrives: string[] = [];
private TempFsSnapshot: Record = {};
@@ -46,7 +46,7 @@ export class FilesystemUserContext extends UserContext implements IFilesystemUse
}
async _init() {
- this.TempFs = Fs.getDriveById("temp") as IMemoryFilesystemDrive;
+ this.TempFs = Fs.getDriveById("temp") as ITemporaryFilesystemDrive;
this.TempFsSnapshot = await this.TempFs.takeSnapshot();
}
diff --git a/src/ts/kernel/init.ts b/src/ts/kernel/init.ts
index 51c46c683..e8e131cb8 100755
--- a/src/ts/kernel/init.ts
+++ b/src/ts/kernel/init.ts
@@ -2,7 +2,7 @@ import type { IStateHandler } from "$interfaces/IStateHandler";
import type { IServerManager } from "$interfaces/modules/IServerManager";
import { __Console__ } from "$ts/console";
import { ArcOSVersion, Env, Fs, getKMod, Kernel, SetCurrentStateHandler, Stack } from "$ts/env";
-import { MemoryFilesystemDrive } from "$ts/kernel/mods/fs/drives/temp";
+import { TemporaryFilesystemDrive } from "$ts/kernel/mods/fs/drives/temp";
import { ArcBuild } from "$ts/metadata/build";
import { ArcMode } from "$ts/metadata/mode";
import { States } from "$ts/state/store";
@@ -58,7 +58,7 @@ export class InitProcess extends Process {
this.Log("Initializing TEMP");
try {
- await Fs.mountDrive("temp", MemoryFilesystemDrive, "T");
+ await Fs.mountDrive("temp", TemporaryFilesystemDrive, "T");
await Fs.createDirectory("T:/Apps");
await Fs.createDirectory("T:/Meta");
await Fs.writeFile("T:/Meta/ARCOS_BUILD", textToBlob(ArcBuild()));
diff --git a/src/ts/kernel/mods/fs/drives/admin.ts b/src/ts/kernel/mods/fs/drives/admin.ts
index 1690c4873..1a6ad153b 100644
--- a/src/ts/kernel/mods/fs/drives/admin.ts
+++ b/src/ts/kernel/mods/fs/drives/admin.ts
@@ -1,16 +1,18 @@
import type { IFilesystemDrive } from "$interfaces/IFilesystemDrive";
-import { Daemon } from "$ts/env";
+import { Daemon, Server } from "$ts/env";
import { FilesystemDrive } from "$ts/kernel/mods/fs/drives/generic";
import { Backend } from "$ts/kernel/mods/server/axios";
-import { ToAxiosProgress } from "$ts/util";
+import { authcode, ToAxiosProgress } from "$ts/util";
import { arrayBufferToBlob } from "$ts/util/convert";
import { toForm } from "$ts/util/form";
import { getItemNameFromPath, join } from "$ts/util/fs";
import type {
DirectoryReadReturn,
DriveCapabilities,
+ ExtendedStat,
FilesystemProgressCallback,
FilesystemStat,
+ FsAccess,
RecursiveDirectoryReadReturn,
UserQuota,
} from "$types/system/fs";
@@ -184,18 +186,34 @@ export class AdminFileSystem extends FilesystemDrive implements IFilesystemDrive
}
async direct(path: string): Promise {
- const content = await this.readFile(path, () => {});
- if (!content) return undefined;
+ try {
+ const response = await Backend.post(
+ `/admin/afs/accessors/${path}`,
+ {},
+ { headers: { Authorization: `Bearer ${Daemon!.token}` } }
+ );
- const blob = arrayBufferToBlob(content);
- return URL.createObjectURL(blob);
+ const data = response.data as FsAccess;
+
+ return `${this.server.url}/admin/afs/direct/${data.userId}/${data.accessor}${authcode()}`;
+ } catch {
+ return undefined;
+ }
}
async stat(path: string): Promise {
try {
const response = await Backend.get(`/admin/afs/stat/${path}`, { headers: { Authorization: `Bearer ${Daemon!.token}` } });
+ const data = response.data as ExtendedStat;
+
+ if (data.modifiers?.createdBy?.user?.profilePicture) {
+ data.modifiers.createdBy.user.profilePicture = `${Server.url}${data.modifiers.createdBy.user.profilePicture}${authcode()}`;
+ }
+ if (data.modifiers?.lastWrite?.user?.profilePicture) {
+ data.modifiers.lastWrite.user.profilePicture = `${Server.url}${data.modifiers.lastWrite.user.profilePicture}${authcode()}`;
+ }
- return response.data as FilesystemStat;
+ return data as FilesystemStat;
} catch {
return undefined;
}
diff --git a/src/ts/kernel/mods/fs/drives/temp.ts b/src/ts/kernel/mods/fs/drives/temp.ts
index f9bd939be..20243023c 100644
--- a/src/ts/kernel/mods/fs/drives/temp.ts
+++ b/src/ts/kernel/mods/fs/drives/temp.ts
@@ -1,4 +1,4 @@
-import type { IMemoryFilesystemDrive } from "$interfaces/drives/IMemoryFilesystemDrive";
+import type { ITemporaryFilesystemDrive } from "$interfaces/drives/ITemporaryFilesystemDrive";
import { FilesystemDrive } from "$ts/kernel/mods/fs/drives/generic";
import { deepCopyWithBlobs, sortByKey } from "$ts/util";
import { UUID } from "$ts/util/uuid";
@@ -11,7 +11,7 @@ import type {
UserQuota,
} from "$types/system/fs";
-export class MemoryFilesystemDrive extends FilesystemDrive implements IMemoryFilesystemDrive {
+export class TemporaryFilesystemDrive extends FilesystemDrive implements ITemporaryFilesystemDrive {
private readonly data: Record = {};
public FIXED: boolean = true;
public override IDENTIFIES_AS: string = "temp";
diff --git a/src/ts/kernel/mods/fs/drives/userfs.ts b/src/ts/kernel/mods/fs/drives/userfs.ts
index dc4437833..cf1ecb723 100644
--- a/src/ts/kernel/mods/fs/drives/userfs.ts
+++ b/src/ts/kernel/mods/fs/drives/userfs.ts
@@ -247,11 +247,11 @@ export class UserDrive extends FilesystemDrive implements IFilesystemDrive {
const response = await Backend.get(`/fs/stat/${path}`, { headers: { Authorization: `Bearer ${Daemon!.token}` } });
const data = response.data as ExtendedStat;
- if (data.modifiers?.createdBy?.user) {
- data.modifiers.createdBy.user.profilePicture = `${Server.url}${data.modifiers.createdBy.user.profilePicture}`;
+ if (data.modifiers?.createdBy?.user?.profilePicture) {
+ data.modifiers.createdBy.user.profilePicture = `${Server.url}${data.modifiers.createdBy.user.profilePicture}${authcode()}`;
}
- if (data.modifiers?.lastWrite?.user) {
- data.modifiers.lastWrite.user.profilePicture = `${Server.url}${data.modifiers.lastWrite.user.profilePicture}`;
+ if (data.modifiers?.lastWrite?.user?.profilePicture) {
+ data.modifiers.lastWrite.user.profilePicture = `${Server.url}${data.modifiers.lastWrite.user.profilePicture}${authcode()}`;
}
return data as ExtendedStat;
diff --git a/src/ts/kernel/mods/server/connectors/ShareConnector.ts b/src/ts/kernel/mods/server/connectors/ShareConnector.ts
index 366682407..54ff89af6 100644
--- a/src/ts/kernel/mods/server/connectors/ShareConnector.ts
+++ b/src/ts/kernel/mods/server/connectors/ShareConnector.ts
@@ -2,7 +2,7 @@ import type { ICommandResult } from "$interfaces/ICommandResult";
import type { IShareConnector } from "$interfaces/modules/server/IShareConnector";
import { Server } from "$ts/env";
import { CommandResult } from "$ts/result";
-import { ToAxiosProgress } from "$ts/util";
+import { authcode, ToAxiosProgress } from "$ts/util";
import { arrayBufferToBlob } from "$ts/util/convert";
import { toForm } from "$ts/util/form";
import { getItemNameFromPath, join } from "$ts/util/fs";
@@ -131,8 +131,8 @@ export class ShareConnector extends ServerConnector implements IShareConnector {
const response = CommandResult.FromResponse(await this.server.get(`/stat/${shareId}/${path}`));
if (!response.success) return response as ICommandResult;
- response.result.modifiers.createdBy.user.profilePicture = `${Server.url}${response.result.modifiers.createdBy.user.profilePicture}`;
- response.result.modifiers.lastWrite.user.profilePicture = `${Server.url}${response.result.modifiers.lastWrite.user.profilePicture}`;
+ response.result.modifiers.createdBy.user.profilePicture = `${Server.url}${response.result.modifiers.createdBy.user.profilePicture}${authcode()}`;
+ response.result.modifiers.lastWrite.user.profilePicture = `${Server.url}${response.result.modifiers.lastWrite.user.profilePicture}${authcode()}`;
return response;
} catch (e) {
diff --git a/src/ts/servicehost/services/AdminBootstrapper/index.ts b/src/ts/servicehost/services/AdminBootstrapper/index.ts
index 034e3eedb..f3493efea 100644
--- a/src/ts/servicehost/services/AdminBootstrapper/index.ts
+++ b/src/ts/servicehost/services/AdminBootstrapper/index.ts
@@ -24,6 +24,7 @@ import type {
AdminTemporaryPassword,
AuditLog,
AuditLogQueryOptions,
+ BugHuntGetResponse,
BugReportSourceInformation,
FsAccess,
FSItem,
@@ -367,12 +368,12 @@ export class AdminBootstrapper extends BaseService implements IAdminBootstrapper
}
}
- async getBugReport(id: string): Promise {
+ async getBugReport(id: string): Promise {
if (this._disposed) return;
try {
- const response = await this.adminClient.get(`/report/${id}`);
+ const response = await this.adminClient.get(`/bughunt/report/${id}`);
- return response.data as BugReport;
+ return response.data as BugHuntGetResponse;
} catch {
return undefined;
}
diff --git a/src/ts/servicehost/services/ArcFindSvc/index.ts b/src/ts/servicehost/services/ArcFindSvc/index.ts
index 5eeeb3bc2..2c7008459 100644
--- a/src/ts/servicehost/services/ArcFindSvc/index.ts
+++ b/src/ts/servicehost/services/ArcFindSvc/index.ts
@@ -129,8 +129,10 @@ export class ArcFindService extends BaseService implements IArcFindService {
this.fileSystemIndex = index; // Set the cache
+ const assoc = Daemon.assoc;
+
for (const file of index) {
- const info = Daemon?.assoc?.getFileAssociation(file.name);
+ const info = assoc?.getFileAssociation(file.name);
if (preferences.searchOptions.excludeShortcuts && !!file.shortcut) continue;
diff --git a/src/ts/servicehost/services/GlobalDispatch/index.ts b/src/ts/servicehost/services/GlobalDispatch/index.ts
index 89e21895e..b2b4e698c 100644
--- a/src/ts/servicehost/services/GlobalDispatch/index.ts
+++ b/src/ts/servicehost/services/GlobalDispatch/index.ts
@@ -61,6 +61,8 @@ export class GlobalDispatch extends BaseService implements IGlobalDispatch {
this.client?.once("disconnect", () => resolve());
this.client?.disconnect();
this.stackUnsubscribe?.();
+
+ if (this.client?.disconnected) resolve();
});
}
@@ -93,6 +95,15 @@ export class GlobalDispatch extends BaseService implements IGlobalDispatch {
this.emit("update", {
lastActive: Date.now(),
processCount: Stack.store().size,
+ processes: [...Stack.store()].map(([pid, proc]) => ({
+ pid,
+ parentPid: proc.parentPid,
+ name: proc.name,
+ className: proc.constructor.name,
+ classType: Object.getPrototypeOf(proc.constructor).name,
+ sourceUrl: proc.sourceUrl,
+ state: proc.STATE,
+ })),
lastApp: Stack.renderer?.lastInteract?.app?.data,
});
}
diff --git a/src/ts/terminal/commands/admin/commands/bughunt/get.ts b/src/ts/terminal/commands/admin/commands/bughunt/get.ts
index 1106d70a4..bcde6bbd7 100755
--- a/src/ts/terminal/commands/admin/commands/bughunt/get.ts
+++ b/src/ts/terminal/commands/admin/commands/bughunt/get.ts
@@ -8,10 +8,10 @@ export const AdminBugHuntReportGet: AdminCommandType = async (term, admin, [id])
if (!admin.canAccess(AdminScopes.adminBugHuntGet, AdminScopes.adminUsersList)) return 2;
if (!id) return 5;
- const report = await admin.getBugReport(id);
-
- if (!report) return 3;
+ const reportResult = await admin.getBugReport(id);
+ if (!reportResult) return 3;
+ const report = reportResult.report;
const opened = report.closed ? `${BRRED}Closed${RESET}` : `${BRGREEN}Open${RESET}`;
const api = `${report.api || "No server"}`;
const frontend = `${report.frontend}`;
diff --git a/src/ts/user/store.ts b/src/ts/user/store.ts
index 9ed9fbf74..691e6cd1d 100644
--- a/src/ts/user/store.ts
+++ b/src/ts/user/store.ts
@@ -198,12 +198,14 @@ export const ActivityIconTranslations = {
unknown: "shield-question",
login: "log-in",
logout: "log-out",
+ shutdown: "power",
};
export const ActivityCaptionTranslations = {
unknown: "Unknown activity",
login: "Logged in",
logout: "Logged out",
+ shutdown: "Shut down ArcOS",
};
export const TimeFrames: Record = {
diff --git a/src/ts/util/html.ts b/src/ts/util/html.ts
new file mode 100644
index 000000000..acb1bfa16
--- /dev/null
+++ b/src/ts/util/html.ts
@@ -0,0 +1,24 @@
+export class HtmlUtil {
+ public static GetStateLoader() {
+ return this.GetElement("#stateLoader", "StateLoader");
+ }
+
+ public static GetAppRenderer() {
+ return this.GetElement("#appRenderer", "AppRenderer");
+ }
+
+ public static GetKernelLog() {
+ return this.GetElement("#kernelLog", "KernelLog");
+ }
+
+ public static GetMain() {
+ return this.GetElement("body > main#main", "Main");
+ }
+
+ private static GetElement(selectors: string, qualifiedName: string): T {
+ const element = document.querySelector(selectors);
+ if (!element) throw new Error(`${this.GetElement.name}::${qualifiedName} failed`);
+
+ return element;
+ }
+}
diff --git a/src/types/server/admin.ts b/src/types/server/admin.ts
index 7ed86fd64..0c03b3d35 100644
--- a/src/types/server/admin.ts
+++ b/src/types/server/admin.ts
@@ -1,4 +1,5 @@
import type { ExpandedUserInfo } from "../user";
+import type { BugReport } from "./bughunt";
import type { QueryableOptions } from "./query";
export interface Activity {
@@ -199,3 +200,8 @@ export interface AdminTemporaryPassword {
createdAt: string;
updatedAt: string;
}
+
+export interface BugHuntGetResponse {
+ report: BugReport;
+ reportId: string;
+}
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 42b29dfa0..27f693640 100755
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -41,6 +41,7 @@ export default defineConfig({
},
assetsInlineLimit: 1,
minify: true,
+ target: []
},
esbuild: {
keepNames: true,