mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-05-09 07:46:13 -04:00
Refactor browser extension and mobile app to use const for trash retention duration (#1967)
This commit is contained in:
committed by
Leendert de Borst
parent
4c15c53060
commit
8537fa8a2a
@@ -2,6 +2,7 @@
|
||||
import * as OTPAuth from 'otpauth';
|
||||
import { storage } from 'wxt/utils/storage';
|
||||
|
||||
import { TRASH_RETENTION_DAYS } from '@/utils/constants/vault';
|
||||
import type { EncryptionKeyDerivationParams } from '@/utils/dist/core/models/metadata';
|
||||
import { FieldKey, ItemTypes, createSystemField, type Item } from '@/utils/dist/core/models/vault';
|
||||
import type { Vault, VaultResponse, VaultPostResponse } from '@/utils/dist/core/models/webapi';
|
||||
@@ -762,7 +763,7 @@ export async function handleClearPersistedFormValues(): Promise<void> {
|
||||
|
||||
/**
|
||||
* Upload a new version of the vault to the server using the provided sqlite client.
|
||||
* Prunes expired trash items (older than 30 days) before uploading.
|
||||
* Prunes expired trash items before uploading.
|
||||
*/
|
||||
async function uploadNewVaultToServer(sqliteClient: SqliteClient) : Promise<VaultPostResponse> {
|
||||
let updatedVaultData = sqliteClient.exportToBase64();
|
||||
@@ -775,11 +776,11 @@ async function uploadNewVaultToServer(sqliteClient: SqliteClient) : Promise<Vaul
|
||||
|
||||
/**
|
||||
* Prune expired items from trash before uploading.
|
||||
* Items that have been in trash (DeletedAt set) for more than 30 days
|
||||
* Items that have been in trash (DeletedAt set) longer than TRASH_RETENTION_DAYS
|
||||
* are permanently deleted (IsDeleted = true) as part of the sync process.
|
||||
*/
|
||||
try {
|
||||
const pruneResult = await vaultMergeService.prune(updatedVaultData, 30);
|
||||
const pruneResult = await vaultMergeService.prune(updatedVaultData, TRASH_RETENTION_DAYS);
|
||||
if (pruneResult.success && pruneResult.statementCount > 0) {
|
||||
console.info(`[VaultSync] Pruned expired items from trash (${pruneResult.statementCount} statements)`);
|
||||
updatedVaultData = pruneResult.prunedVaultBase64;
|
||||
|
||||
@@ -2,12 +2,14 @@ import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ConfirmDeleteModal from '@/entrypoints/popup/components/Dialogs/ConfirmDeleteModal';
|
||||
import ItemIcon from '@/entrypoints/popup/components/Items/ItemIcon';
|
||||
import LoadingSpinner from '@/entrypoints/popup/components/LoadingSpinner';
|
||||
import PageTitle from '@/entrypoints/popup/components/PageTitle';
|
||||
import { useDb } from '@/entrypoints/popup/context/DbContext';
|
||||
import { useHeaderButtons } from '@/entrypoints/popup/context/HeaderButtonsContext';
|
||||
import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
|
||||
|
||||
import { TRASH_RETENTION_DAYS } from '@/utils/constants/vault';
|
||||
import type { Item } from '@/utils/dist/core/models/vault';
|
||||
|
||||
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
|
||||
@@ -15,10 +17,10 @@ import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
|
||||
/**
|
||||
* Calculate days remaining until permanent deletion.
|
||||
* @param deletedAt - ISO timestamp when item was deleted
|
||||
* @param retentionDays - Number of days to retain (default 30)
|
||||
* @param retentionDays - Number of days to retain (defaults to TRASH_RETENTION_DAYS)
|
||||
* @returns Number of days remaining, or 0 if already expired
|
||||
*/
|
||||
const getDaysRemaining = (deletedAt: string, retentionDays: number = 30): number => {
|
||||
const getDaysRemaining = (deletedAt: string, retentionDays: number = TRASH_RETENTION_DAYS): number => {
|
||||
const deletedDate = new Date(deletedAt);
|
||||
const expiryDate = new Date(deletedDate.getTime() + retentionDays * 24 * 60 * 60 * 1000);
|
||||
const now = new Date();
|
||||
@@ -162,19 +164,19 @@ const RecentlyDeleted: React.FC = () => {
|
||||
{items.length === 0 ? (
|
||||
<div className="text-gray-500 dark:text-gray-400 space-y-2 mb-10">
|
||||
<p>{t('recentlyDeleted.noItems')}</p>
|
||||
<p className="text-sm">{t('recentlyDeleted.noItemsDescription')}</p>
|
||||
<p className="text-sm">{t('recentlyDeleted.noItemsDescription', { days: TRASH_RETENTION_DAYS })}</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
|
||||
{t('recentlyDeleted.description')}
|
||||
{t('recentlyDeleted.description', { days: TRASH_RETENTION_DAYS })}
|
||||
</p>
|
||||
|
||||
<ul className="space-y-2">
|
||||
{items.map(item => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const deletedAt = (item as any).DeletedAt;
|
||||
const daysRemaining = deletedAt ? getDaysRemaining(deletedAt) : 30;
|
||||
const daysRemaining = deletedAt ? getDaysRemaining(deletedAt) : TRASH_RETENTION_DAYS;
|
||||
|
||||
return (
|
||||
<li key={item.Id} className="relative">
|
||||
@@ -183,13 +185,7 @@ const RecentlyDeleted: React.FC = () => {
|
||||
{/* Item card content (simplified) */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2">
|
||||
{item.Logo && (
|
||||
<img
|
||||
src={`data:image/png;base64,${btoa(String.fromCharCode(...item.Logo))}`}
|
||||
alt=""
|
||||
className="w-6 h-6 rounded"
|
||||
/>
|
||||
)}
|
||||
<ItemIcon item={item} className="w-6 h-6 rounded" />
|
||||
<span className="font-medium text-gray-900 dark:text-white truncate">
|
||||
{item.Name || t('items.untitled')}
|
||||
</span>
|
||||
|
||||
@@ -507,8 +507,8 @@
|
||||
"recentlyDeleted": {
|
||||
"title": "Recently Deleted",
|
||||
"noItems": "No deleted items",
|
||||
"noItemsDescription": "Items you delete will appear here for 30 days before being permanently removed.",
|
||||
"description": "These items will be permanently deleted after 30 days. You can restore them or delete them immediately.",
|
||||
"noItemsDescription": "Items you delete will appear here for {{days}} days before being permanently removed.",
|
||||
"description": "These items will be permanently deleted after {{days}} days. You can restore them or delete them immediately.",
|
||||
"restore": "Restore",
|
||||
"deletePermanently": "Delete Permanently",
|
||||
"emptyAll": "Empty All",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import initSqlJs, { Database, SqlJsStatic, SqlValue } from 'sql.js';
|
||||
import { browser } from 'wxt/browser';
|
||||
|
||||
import { TRASH_RETENTION_DAYS } from '@/utils/constants/vault';
|
||||
|
||||
import init, { getSyncableTableNames, mergeVaults, pruneVault } from './dist/core/rust/aliasvault_core.js';
|
||||
|
||||
/**
|
||||
@@ -244,10 +246,10 @@ export class VaultMergeService {
|
||||
* 5. Export pruned database
|
||||
*
|
||||
* @param vaultBase64 - The vault as base64 SQLite
|
||||
* @param retentionDays - Number of days to keep items in trash (default: 30)
|
||||
* @param retentionDays - Number of days to keep items in trash (defaults to TRASH_RETENTION_DAYS)
|
||||
* @returns PruneResult with the pruned vault as base64
|
||||
*/
|
||||
public async prune(vaultBase64: string, retentionDays: number = 30): Promise<PruneResult> {
|
||||
public async prune(vaultBase64: string, retentionDays: number = TRASH_RETENTION_DAYS): Promise<PruneResult> {
|
||||
try {
|
||||
// Initialize Rust WASM
|
||||
await this.initRust();
|
||||
|
||||
6
apps/browser-extension/src/utils/constants/vault.ts
Normal file
6
apps/browser-extension/src/utils/constants/vault.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Number of days that soft-deleted items stay in the "Recently Deleted" trash
|
||||
* before being permanently pruned during vault sync. Mirrors the server-side
|
||||
* default exposed via Config.TrashRetentionDays in the Blazor client.
|
||||
*/
|
||||
export const TRASH_RETENTION_DAYS = 30;
|
||||
@@ -21,15 +21,16 @@ import { ItemIcon } from '@/components/items/ItemIcon';
|
||||
import { ThemedContainer } from '@/components/themed/ThemedContainer';
|
||||
import { ThemedScrollView } from '@/components/themed/ThemedScrollView';
|
||||
import { ThemedText } from '@/components/themed/ThemedText';
|
||||
import { TRASH_RETENTION_DAYS } from '@/constants/vault';
|
||||
import { useDb } from '@/context/DbContext';
|
||||
|
||||
/**
|
||||
* Calculate days remaining until permanent deletion.
|
||||
* @param deletedAt - ISO timestamp when item was deleted
|
||||
* @param retentionDays - Number of days to retain (default 30)
|
||||
* @param retentionDays - Number of days to retain (defaults to TRASH_RETENTION_DAYS)
|
||||
* @returns Number of days remaining, or 0 if already expired
|
||||
*/
|
||||
const getDaysRemaining = (deletedAt: string, retentionDays: number = 30): number => {
|
||||
const getDaysRemaining = (deletedAt: string, retentionDays: number = TRASH_RETENTION_DAYS): number => {
|
||||
const deletedDate = new Date(deletedAt);
|
||||
const expiryDate = new Date(deletedDate.getTime() + retentionDays * 24 * 60 * 60 * 1000);
|
||||
const now = new Date();
|
||||
@@ -268,7 +269,7 @@ export default function RecentlyDeletedScreen(): React.ReactNode {
|
||||
* Render an item card.
|
||||
*/
|
||||
const renderItem = (item: ItemWithDeletedAt): React.ReactElement => {
|
||||
const daysRemaining = item.DeletedAt ? getDaysRemaining(item.DeletedAt) : 30;
|
||||
const daysRemaining = item.DeletedAt ? getDaysRemaining(item.DeletedAt) : TRASH_RETENTION_DAYS;
|
||||
|
||||
return (
|
||||
<View key={item.Id} style={styles.itemCard}>
|
||||
@@ -343,7 +344,7 @@ export default function RecentlyDeletedScreen(): React.ReactNode {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ThemedText style={styles.headerText}>
|
||||
{t('items.recentlyDeleted.description')}
|
||||
{t('items.recentlyDeleted.description', { days: TRASH_RETENTION_DAYS })}
|
||||
</ThemedText>
|
||||
{items.map(renderItem)}
|
||||
</>
|
||||
@@ -353,7 +354,7 @@ export default function RecentlyDeletedScreen(): React.ReactNode {
|
||||
{t('items.recentlyDeleted.noItems')}
|
||||
</ThemedText>
|
||||
<ThemedText style={styles.emptyDescription}>
|
||||
{t('items.recentlyDeleted.noItemsDescription')}
|
||||
{t('items.recentlyDeleted.noItemsDescription', { days: TRASH_RETENTION_DAYS })}
|
||||
</ThemedText>
|
||||
</View>
|
||||
)}
|
||||
|
||||
6
apps/mobile-app/constants/vault.ts
Normal file
6
apps/mobile-app/constants/vault.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Number of days that soft-deleted items stay in the "Recently Deleted" trash
|
||||
* before being permanently pruned during vault sync. Mirrors the server-side
|
||||
* default exposed via Config.TrashRetentionDays in the Blazor client.
|
||||
*/
|
||||
export const TRASH_RETENTION_DAYS = 30;
|
||||
@@ -518,8 +518,8 @@
|
||||
"recentlyDeleted": {
|
||||
"title": "Recently Deleted",
|
||||
"noItems": "No deleted items",
|
||||
"noItemsDescription": "Items you delete will appear here for 30 days before being permanently removed.",
|
||||
"description": "These items will be permanently deleted after 30 days. You can restore them or delete them immediately.",
|
||||
"noItemsDescription": "Items you delete will appear here for {{days}} days before being permanently removed.",
|
||||
"description": "These items will be permanently deleted after {{days}} days. You can restore them or delete them immediately.",
|
||||
"restore": "Restore",
|
||||
"deletePermanently": "Delete Permanently",
|
||||
"emptyAll": "Empty All",
|
||||
|
||||
Reference in New Issue
Block a user