All checks were successful
Queue Release Build / prepare (push) Successful in 19s
Deploy Web Apps / deploy (push) Successful in 7m55s
Queue Release Build / build-windows (push) Successful in 28m37s
Queue Release Build / build-linux (push) Successful in 47m3s
Queue Release Build / build-android (push) Successful in 20m33s
Queue Release Build / finalize (push) Successful in 3m48s
Expose settings logout on mobile where the title bar is hidden, and enable Capacitor data settings with storage visibility and local erase/sign-out. Co-authored-by: Cursor <cursoragent@cursor.com>
172 lines
7.5 KiB
HTML
172 lines
7.5 KiB
HTML
<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">{{ 'settings.data.localData.title' | translate }}</h4>
|
|
</div>
|
|
<p class="mt-2 text-sm text-muted-foreground">
|
|
@if (supportsMobileLocalDataErase) {
|
|
{{ 'settings.data.localData.descriptionMobile' | translate }}
|
|
} @else {
|
|
{{ 'settings.data.localData.description' | translate }}
|
|
}
|
|
</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"
|
|
/>
|
|
{{ 'settings.data.localData.restartApp' | translate }}
|
|
</button>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
@if (!supportsLocalDataManagement) {
|
|
<section class="rounded-lg border border-border bg-secondary/30 p-5">
|
|
<p class="text-sm text-muted-foreground">{{ 'settings.data.desktopOnly' | translate }}</p>
|
|
</section>
|
|
} @else if (supportsDesktopDataFolderActions) {
|
|
<section class="space-y-4 rounded-lg border border-border bg-card/60 p-5">
|
|
<div>
|
|
<h5 class="text-sm font-semibold text-foreground">{{ 'settings.data.currentFolder.title' | translate }}</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() || ('settings.data.currentFolder.resolving' | translate) }}
|
|
</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' ? ('settings.data.opening' | translate) : ('settings.data.openFolder' | translate) }}
|
|
</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">{{ 'settings.data.export.title' | translate }}</h5>
|
|
<p class="mt-1 text-sm text-muted-foreground">{{ 'settings.data.export.description' | translate }}</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' ? ('settings.data.export.exporting' | translate) : ('settings.data.export.button' | translate) }}
|
|
</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">{{ 'settings.data.import.title' | translate }}</h5>
|
|
<p class="mt-1 text-sm text-muted-foreground">{{ 'settings.data.import.description' | translate }}</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' ? ('settings.data.import.importing' | translate) : ('settings.data.import.button' | translate) }}
|
|
</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">{{ 'settings.data.erase.title' | translate }}</h5>
|
|
<p class="mt-1 text-sm text-muted-foreground">{{ 'settings.data.erase.description' | translate }}</p>
|
|
</div>
|
|
|
|
<button
|
|
type="button"
|
|
data-testid="data-settings-erase-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' ? ('settings.data.erase.erasing' | translate) : ('settings.data.erase.button' | translate) }}
|
|
</button>
|
|
</section>
|
|
} @else if (supportsMobileLocalDataErase) {
|
|
<section class="space-y-4 rounded-lg border border-border bg-card/60 p-5">
|
|
<div>
|
|
<h5 class="text-sm font-semibold text-foreground">{{ 'settings.data.currentFolder.title' | translate }}</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() || ('settings.data.currentFolder.resolving' | translate) }}
|
|
</p>
|
|
<p class="mt-2 text-sm text-muted-foreground">{{ 'settings.data.currentFolder.descriptionMobile' | translate }}</p>
|
|
</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">{{ 'settings.data.erase.title' | translate }}</h5>
|
|
<p class="mt-1 text-sm text-muted-foreground">{{ 'settings.data.erase.descriptionMobile' | translate }}</p>
|
|
</div>
|
|
|
|
<button
|
|
type="button"
|
|
data-testid="data-settings-erase-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' ? ('settings.data.erase.erasing' | translate) : ('settings.data.erase.button' | translate) }}
|
|
</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>
|