feat: Data management

This commit is contained in:
2026-04-27 03:29:41 +02:00
parent 1b91eacb5b
commit 3858beb28e
13 changed files with 845 additions and 1 deletions

View File

@@ -0,0 +1,135 @@
<div class="space-y-6">
<section class="rounded-lg border border-border bg-card/60 p-5">
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div>
<div class="flex items-center gap-2 text-primary">
<ng-icon
name="lucideDatabase"
class="h-5 w-5"
/>
<h4 class="text-base font-semibold text-foreground">Local data</h4>
</div>
<p class="mt-2 text-sm text-muted-foreground">
Manage the folder that contains local messages, rooms, attachments, avatars, saved themes, and desktop storage.
</p>
</div>
@if (restartRequired()) {
<button
type="button"
(click)="restartApp()"
[disabled]="busyAction() !== null"
class="inline-flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-60"
>
<ng-icon
name="lucideRefreshCw"
class="h-4 w-4"
/>
Restart app
</button>
}
</div>
</section>
@if (!isElectron) {
<section class="rounded-lg border border-border bg-secondary/30 p-5">
<p class="text-sm text-muted-foreground">Data management is only available in the packaged Electron desktop app.</p>
</section>
} @else {
<section class="space-y-4 rounded-lg border border-border bg-card/60 p-5">
<div>
<h5 class="text-sm font-semibold text-foreground">Current data folder</h5>
<p class="mt-2 break-all rounded-lg border border-border bg-secondary/20 px-3 py-2 text-sm text-muted-foreground">
{{ dataPath() || 'Resolving data folder...' }}
</p>
</div>
<button
type="button"
(click)="openDataFolder()"
[disabled]="busyAction() !== null"
class="inline-flex items-center gap-2 rounded-lg border border-border bg-secondary px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-secondary/80 disabled:cursor-not-allowed disabled:opacity-60"
>
<ng-icon
name="lucideFolderOpen"
class="h-4 w-4"
/>
{{ busyAction() === 'open' ? 'Opening...' : 'Open folder' }}
</button>
</section>
<section class="grid gap-4 md:grid-cols-2">
<div class="space-y-4 rounded-lg border border-border bg-card/60 p-5">
<div>
<h5 class="text-sm font-semibold text-foreground">Export data</h5>
<p class="mt-1 text-sm text-muted-foreground">Create a portable .dat archive that can be imported on another client.</p>
</div>
<button
type="button"
(click)="exportData()"
[disabled]="busyAction() !== null"
class="inline-flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-60"
>
<ng-icon
name="lucideDownload"
class="h-4 w-4"
/>
{{ busyAction() === 'export' ? 'Exporting...' : 'Export data' }}
</button>
</div>
<div class="space-y-4 rounded-lg border border-border bg-card/60 p-5">
<div>
<h5 class="text-sm font-semibold text-foreground">Import all data</h5>
<p class="mt-1 text-sm text-muted-foreground">Restore a .dat archive. Existing local data is moved to a backup folder first.</p>
</div>
<button
type="button"
(click)="importData()"
[disabled]="busyAction() !== null"
class="inline-flex items-center gap-2 rounded-lg border border-border bg-secondary px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-secondary/80 disabled:cursor-not-allowed disabled:opacity-60"
>
<ng-icon
name="lucideUpload"
class="h-4 w-4"
/>
{{ busyAction() === 'import' ? 'Importing...' : 'Import data' }}
</button>
</div>
</section>
<section class="space-y-4 rounded-lg border border-destructive/30 bg-destructive/10 p-5">
<div>
<h5 class="text-sm font-semibold text-foreground">Erase user data</h5>
<p class="mt-1 text-sm text-muted-foreground">Remove local app data from this device and recreate an empty database.</p>
</div>
<button
type="button"
(click)="eraseData()"
[disabled]="busyAction() !== null"
class="inline-flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive px-4 py-2 text-sm font-medium text-destructive-foreground transition-colors hover:bg-destructive/90 disabled:cursor-not-allowed disabled:opacity-60"
>
<ng-icon
name="lucideTrash2"
class="h-4 w-4"
/>
{{ busyAction() === 'erase' ? 'Erasing...' : 'Erase user data' }}
</button>
</section>
@if (statusMessage()) {
<section class="rounded-lg border border-primary/30 bg-primary/10 p-4">
<p class="break-words text-sm text-foreground">{{ statusMessage() }}</p>
</section>
}
@if (errorMessage()) {
<section class="rounded-lg border border-destructive/30 bg-destructive/10 p-4">
<p class="break-words text-sm text-foreground">{{ errorMessage() }}</p>
</section>
}
}
</div>