Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

if (typeof response.data !== "object" || !Array.isArray(response.data)) throw "";

if (response.data.filter((i) => i?._id === item._id)) installed.push(user);
if (response.data.find((i) => i?._id === item._id)) installed.push(user);
} catch {
continue;
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
</script>

{#if $expressions[$selectedSource][i].columnName}
<select class="comparison-type" bind:value={$expressions[$selectedSource][i].comparisonType}>
<select
class="comparison-type"
bind:value={$expressions[$selectedSource][i].comparisonType}
onchange={() => ($expressions[$selectedSource][i].comparisonValue = undefined)}
>
{#each QueryComparisonTypes as value}
<option {value} disabled={!value} selected={!value}>{value}</option>
{/each}
Expand Down
4 changes: 1 addition & 3 deletions src/apps/components/multiupdategui/MultiUpdateGui.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@
<img
src={$working && $currentPackage
? StoreItemIcon($currentPackage)
: $done
? process.getIconCached("GoodStatusIcon")
: "UpdateIcon"}
: process.getIconCached($done ? "GoodStatusIcon" : "UpdateIcon")}
alt=""
/>
<div class="info">
Expand Down
6 changes: 3 additions & 3 deletions src/apps/components/securecontext/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ export class SecureContextRuntime extends AppProcess {
if (security.noPassword) return true; // Password field is irrelevant if noPassword is set
if (security.disabled || !Daemon?.username) return false; // 'Reject all elevation requests'

const token = await LoginUser(Daemon!.username, this.password()); // Try to create a token to validate
const tokenResult = await LoginUser(Daemon!.username, this.password()); // Try to create a token to validate

if (!token) {
if (!tokenResult.success) {
await this.passwordIncorrect();
return false;
}

await Daemon?.account!.discontinueToken(token); // Discontinue validated token
await Daemon?.account!.discontinueToken(tokenResult.result); // Discontinue validated token

return true;
}
Expand Down
21 changes: 19 additions & 2 deletions src/apps/components/shell/Shell/StartMenu/RightPane.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type { IShellRuntime } from "$interfaces/shell";
import { Fs, SysDispatch } from "$ts/env";
import { contextProps } from "$ts/ui/context/actions.svelte";
import { contextMenu, contextProps } from "$ts/ui/context/actions.svelte";
import { UserPaths } from "$ts/user/store";
import type { FolderEntry } from "$types/fs";
import type { UserPreferencesStore } from "$types/user";
Expand Down Expand Up @@ -44,7 +44,24 @@

<div class="right-pane">
<UserButton {userPreferences} {username} {process} />
<div class="content">
<div
class="content"
use:contextMenu={[
[
{
caption: "Refresh",
icon: "refresh-cw",
action: () => update(),
},
{
caption: "Open home folder",
icon: "folder-open",
action: () => process.spawnApp("fileManager", process.pid, UserPaths.Home),
},
],
process,
]}
>
{#each dirs as dir}
<button
class="folder"
Expand Down
9 changes: 9 additions & 0 deletions src/apps/components/systemshortcuts/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ export class SystemShortcutsRuntime extends AppProcess {
this.spawnOverlayApp("AcceleratorOverview", +Env.get("shell_pid"));
},
global: true,
},
{
ctrl: true,
alt: true,
key: "Backspace",
action: () => {
this.spawnOverlayApp("processManager", +Env.get("shell_pid"), "Processes");
},
global: true,
}
);
}
Expand Down
41 changes: 36 additions & 5 deletions src/apps/core/initialsetup/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Sleep } from "$ts/sleep";
import { LoginUser, RegisterUser } from "$ts/user/auth";
import { htmlspecialchars } from "$ts/util";
import { MessageBox } from "$ts/util/dialog";
import { UUID } from "$ts/util/uuid";
import { Store } from "$ts/writable";
import type { AppProcessData } from "$types/app";
import CheckInbox from "./InitialSetup/Page/CheckInbox.svelte";
Expand Down Expand Up @@ -342,20 +343,46 @@ export class InitialSetupRuntime extends AppProcess {
return;
}

if (Server?.serverInfo?.noEmailVerify) {
Env.set("DISPATCH_SOCK_ID", UUID());
const tokenResult = await LoginUser(this.newUsername(), this.password());

if (tokenResult.success) {
this.#userDaemon = await Stack.spawn(
UserDaemon,
undefined,
this.#userDaemon?.userInfo?._id,
this.pid,
tokenResult.result!,
this.newUsername()
);

await this.#userDaemon?.account?.getUserInfo();
await this.#userDaemon?.init?.startPreferencesSync();
await this.#userDaemon?.init?.startFilesystemSupplier();

this.#userDaemon?.preferences.update((v) => {
v.isDefault = false;
v.account.displayName = this.displayName();

return v;
});
}
}

this.pageNumber.set(this.pageNumber() + (Server.serverInfo?.noEmailVerify ? 2 : 1));
}

async checkAccountActivation() {
this.Log(`Checking account activation of '${this.newUsername()}'`);

const token = await LoginUser(this.newUsername(), this.password());
const tokenResult = await LoginUser(this.newUsername(), this.password());

if (!token) {
if (!tokenResult.success) {
MessageBox(
{
title: "Did you click the link?",
message:
"Our systems tell me that your account hasn't been activated yet. Are you sure you clicked the link? If you did, and you're still seeing this, please contact support.",
message: `Our systems tell me that your account hasn't been activated yet. Are you sure you clicked the link? If you did, and you're still seeing this, please contact support.<br><br>Details: ${tokenResult.errorMessage ?? "Unknown error"}`,
buttons: [
{
caption: "Okay",
Expand All @@ -379,14 +406,18 @@ export class InitialSetupRuntime extends AppProcess {
undefined,
this.#userDaemon?.userInfo?._id,
this.pid,
token,
tokenResult.result!,
this.newUsername()
);

// set the socket ID to something bogus to fool the backend into thinking we're connected to the websocket
Env.set("DISPATCH_SOCK_ID", UUID());

await this.#userDaemon?.account?.getUserInfo();
await this.#userDaemon?.init?.startPreferencesSync();
await this.#userDaemon?.init?.startFilesystemSupplier();
this.#userDaemon?.preferences.update((v) => {
v.isDefault = false;
v.account.displayName = this.displayName();

return v;
Expand Down
16 changes: 9 additions & 7 deletions src/apps/core/loginapp/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,17 @@ export class LoginAppRuntime extends AppProcess {
this.saveToken(userDaemon);
this.loadingStatus.set("Loading your settings");

const userInfo = await userDaemon.account!.getUserInfo();
const userInfoResult = await userDaemon.account!.getUserInfo();

if (!userInfo) {
if (!userInfoResult.success) {
this.loadingStatus.set("");
this.errorMessage.set("Failed to request user info");
this.errorMessage.set(userInfoResult.errorMessage ?? "Failed to request user info");

return;
}

const userInfo = userInfoResult.result!;

this.profileImage.set(`${this.server.url}/user/pfp/${userInfo._id}${authcode()}`);

if (userInfo.hasTotp && userInfo.restricted) {
Expand Down Expand Up @@ -372,18 +374,18 @@ export class LoginAppRuntime extends AppProcess {

this.loadingStatus.set(`Hi, ${username}!`);

const token = await LoginUser(username, password);
const tokenResult = await LoginUser(username, password);

if (!token) {
if (!tokenResult.success) {
this.loadingStatus.set("");
this.errorMessage.set("Username or password incorrect.");
this.errorMessage.set(tokenResult.errorMessage ?? "Username or password incorrect");

this.updateServerStuff();

return;
}

await this.startDaemon(token, username);
await this.startDaemon(tokenResult.result!, username);
}

private saveToken(userDaemon: IUserDaemon) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
<div class="version current">{migration.version}</div>
<button
class="run-migration"
disabled={upToDate}
onclick={runMigration}
title={upToDate ? "This migration is up to date" : "Click to run this migration now"}
>
Expand Down
5 changes: 3 additions & 2 deletions src/apps/user/mediaplayer/MediaPlayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import type { MediaPlayerRuntime } from "./runtime";

const { process }: { process: MediaPlayerRuntime } = $props();

const { pinControls } = process;

let audio: HTMLVideoElement;
let hideControls = $state<boolean>(false);
let style = $state<string | undefined>();
Expand Down Expand Up @@ -48,7 +49,7 @@
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="container shell-colored colored"
class:hide-controls={hideControls}
class:hide-controls={hideControls && !$pinControls}
{onmousemove}
data-contextmenu={$queue.length && $Loaded ? "player" : ""}
class:is-video={$isVideo && $Loaded}
Expand Down
16 changes: 14 additions & 2 deletions src/apps/user/mediaplayer/MediaPlayer/Controls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import Time from "./Controls/Time.svelte";

const { process }: { process: MediaPlayerRuntime } = $props();
const { windowFullscreen, queue } = process;
const { windowFullscreen, queue, pinControls } = process;
</script>

<div class="media-controls">
Expand All @@ -23,11 +23,23 @@
<Loop {process} />
<Stop {process} />
<Time {process} />
<!-- svelte-ignore a11y_consider_explicit_label -->
{#if $windowFullscreen}
<button
class="lucide pin-toggle"
class:icon-pin={$pinControls}
class:icon-pin-off={!$pinControls}
class:suggested={$pinControls}
aria-label="Pin controls"
title="Pin controls"
onclick={() => ($pinControls = !$pinControls)}
></button>
{/if}
<button
class="lucide fullscreen-toggle"
class:icon-minimize={$windowFullscreen}
class:icon-maximize={!$windowFullscreen}
title="Toggle fullscreen"
aria-label="Toggle fullscreen"
onclick={() => Stack.renderer?.toggleFullscreen(process.pid)}
disabled={!$queue.length}
></button>
Expand Down
12 changes: 11 additions & 1 deletion src/apps/user/mediaplayer/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class MediaPlayerRuntime extends AppProcess {
public isVideo = Store<boolean>(false);
public Loaded = Store<boolean>(false);
public playlistPath = Store<string>();
public pinControls = Store<boolean>(false);
MetadataConfiguration = Store<MetadataConfiguration>({});
CurrentMediaMetadata = Store<AudioFileMetadata | undefined>();
CurrentCoverUrl = Store<string | undefined>();
Expand Down Expand Up @@ -133,8 +134,17 @@ export class MediaPlayerRuntime extends AppProcess {
}

async render({ file }: RenderArgs) {
if (await this.closeIfSecondInstance()) return;
const firstInstance = await this.closeIfSecondInstance();

if (firstInstance) {
if (file) {
if (file.endsWith(".arcpl")) firstInstance.readPlaylist(file);
else firstInstance.readFile([file]);
}

return;
}

if (file) {
if (file.endsWith(".arcpl")) this.readPlaylist(file);
else this.readFile([file]);
Expand Down
4 changes: 4 additions & 0 deletions src/apps/user/processes/ProcessManager/Page/Processes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,9 @@
<ActionButton suggested onclick={() => proc && process.kill(proc)} disabled={!proc}>
Kill {proc && proc instanceof AppProcess ? "App" : "Process"}
</ActionButton>
{#if process.app.data.overlay}
<ActionSeparator />
<ActionButton suggested onclick={() => process.closeWindow()}>Close</ActionButton>
{/if}
{/snippet}
</ActionBar>
6 changes: 5 additions & 1 deletion src/apps/user/processes/ProcessManager/Page/Services.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,16 @@
<ActionButton
className="stop"
disabled={!$selected || !$Services.get(serviceId)?.pid}
onclick={() => process.startService(serviceId)}
onclick={() => process.stopService(serviceId)}
>
Stop
</ActionButton>
<ActionButton className="restart" disabled={!$selected} onclick={() => process.restartService(serviceId)}>
Restart
</ActionButton>
{#if process.app.data.overlay}
<ActionSeparator />
<ActionButton suggested onclick={() => process.closeWindow()}>Close</ActionButton>
{/if}
{/snippet}
</ActionBar>
2 changes: 1 addition & 1 deletion src/css/apps/admin/adminportal/page/viewstoreitem.css
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
}
#AdminPortal div.container.viewStoreItem div.installed-by {
border-bottom: var(--win-border);
min-height: 150px;
min-height: 100px;
}

#AdminPortal div.container.viewStoreItem div.installed-by.empty {
Expand Down
7 changes: 5 additions & 2 deletions src/css/apps/components/fsprogress/bar.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#FsProgress div.bar {
height: 7px;
height: 9px;
width: 100%;
border: var(--button-glass-bg) 1px solid;
border-radius: 3.5px;
border-radius: 4.5px;
background-color: var(--button-glass-bg);
overflow: hidden;
margin-top: auto;
padding: 1px;
}

#FsProgress div.bar div.inner {
--max: 100;
--done: 0;
background-color: var(--accent);
border-radius: 2.5px;
height: 5px;
transition: none;
width: calc(100% / var(--max) * var(--done));
Expand Down
1 change: 1 addition & 0 deletions src/css/apps/components/fsprogress/top.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
gap: 20px;
height: 0;
flex-grow: 1;
min-height: 110px !important;
}
11 changes: 11 additions & 0 deletions src/css/apps/components/multiupdategui.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@

#MultiUpdateGui > div.body div.header h1 {
font-size: 22px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

#MultiUpdateGui > div.body div.header div.info {
width: 0;
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

#MultiUpdateGui > div.body div.header p.sub {
Expand Down
Loading