forked from trent_larson/crowd-funder-for-time-pwa
chore: linting; more non-errors need fixing
This commit is contained in:
@@ -1,18 +1,10 @@
|
|||||||
/**
|
/** * Backup Files List Component * * Displays a list of backup files saved by
|
||||||
* Backup Files List Component
|
the app and provides options to: * - View backup files by type (contacts, seed,
|
||||||
*
|
other) * - Open individual files in the device's file viewer * - Access the
|
||||||
* Displays a list of backup files saved by the app and provides options to:
|
backup directory in the device's file explorer * * @component * @displayName
|
||||||
* - View backup files by type (contacts, seed, other)
|
BackupFilesList * @example * ```vue *
|
||||||
* - Open individual files in the device's file viewer
|
<BackupFilesList />
|
||||||
* - Access the backup directory in the device's file explorer
|
* ``` */
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @displayName BackupFilesList
|
|
||||||
* @example
|
|
||||||
* ```vue
|
|
||||||
* <BackupFilesList />
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="backup-files-list">
|
<div class="backup-files-list">
|
||||||
@@ -21,9 +13,9 @@
|
|||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button
|
<button
|
||||||
v-if="platformCapabilities.hasFileSystem"
|
v-if="platformCapabilities.hasFileSystem"
|
||||||
@click="refreshFiles()"
|
|
||||||
class="text-sm bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded"
|
class="text-sm bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
|
@click="refreshFiles()"
|
||||||
>
|
>
|
||||||
<font-awesome
|
<font-awesome
|
||||||
icon="refresh"
|
icon="refresh"
|
||||||
@@ -34,34 +26,34 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="platformCapabilities.hasFileSystem"
|
v-if="platformCapabilities.hasFileSystem"
|
||||||
@click="openBackupDirectory()"
|
|
||||||
class="text-sm bg-green-500 hover:bg-green-600 text-white px-3 py-1 rounded"
|
class="text-sm bg-green-500 hover:bg-green-600 text-white px-3 py-1 rounded"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
|
@click="openBackupDirectory()"
|
||||||
>
|
>
|
||||||
<font-awesome icon="folder-open" class="fa-fw" />
|
<font-awesome icon="folder-open" class="fa-fw" />
|
||||||
Open Directory
|
Open Directory
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="platformCapabilities.hasFileSystem && isDevelopment"
|
v-if="platformCapabilities.hasFileSystem && isDevelopment"
|
||||||
@click="debugFileDiscovery()"
|
|
||||||
class="text-sm bg-yellow-500 hover:bg-yellow-600 text-white px-3 py-1 rounded"
|
class="text-sm bg-yellow-500 hover:bg-yellow-600 text-white px-3 py-1 rounded"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
title="Debug file discovery (development only)"
|
title="Debug file discovery (development only)"
|
||||||
|
@click="debugFileDiscovery()"
|
||||||
>
|
>
|
||||||
<font-awesome icon="bug" class="fa-fw" />
|
<font-awesome icon="bug" class="fa-fw" />
|
||||||
Debug
|
Debug
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="createTestBackup"
|
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
class="px-3 py-1 bg-green-500 text-white rounded text-sm hover:bg-green-600 disabled:opacity-50"
|
class="px-3 py-1 bg-green-500 text-white rounded text-sm hover:bg-green-600 disabled:opacity-50"
|
||||||
|
@click="createTestBackup"
|
||||||
>
|
>
|
||||||
Create Test Backup
|
Create Test Backup
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="testDirectoryContexts"
|
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
class="px-3 py-1 bg-purple-500 text-white rounded text-sm hover:bg-purple-600 disabled:opacity-50"
|
class="px-3 py-1 bg-purple-500 text-white rounded text-sm hover:bg-purple-600 disabled:opacity-50"
|
||||||
|
@click="testDirectoryContexts"
|
||||||
>
|
>
|
||||||
Test Contexts
|
Test Contexts
|
||||||
</button>
|
</button>
|
||||||
@@ -73,21 +65,40 @@
|
|||||||
<p class="mt-2">Loading backup files...</p>
|
<p class="mt-2">Loading backup files...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="backupFiles.length === 0" class="text-center py-4 text-gray-500">
|
<div
|
||||||
|
v-else-if="backupFiles.length === 0"
|
||||||
|
class="text-center py-4 text-gray-500"
|
||||||
|
>
|
||||||
<font-awesome icon="folder-open" class="fa-2x mb-2" />
|
<font-awesome icon="folder-open" class="fa-2x mb-2" />
|
||||||
<p>No backup files found</p>
|
<p>No backup files found</p>
|
||||||
<p class="text-sm mt-1">Create backups using the export functions above</p>
|
<p class="text-sm mt-1">
|
||||||
<div class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg text-left">
|
Create backups using the export functions above
|
||||||
<p class="text-sm font-medium text-blue-800 mb-2">💡 How to create backup files:</p>
|
</p>
|
||||||
|
<div
|
||||||
|
class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg text-left"
|
||||||
|
>
|
||||||
|
<p class="text-sm font-medium text-blue-800 mb-2">
|
||||||
|
💡 How to create backup files:
|
||||||
|
</p>
|
||||||
<ul class="text-xs text-blue-700 space-y-1">
|
<ul class="text-xs text-blue-700 space-y-1">
|
||||||
<li>• Use the "Export Contacts" button above to create contact backups</li>
|
<li>
|
||||||
|
• Use the "Export Contacts" button above to create contact backups
|
||||||
|
</li>
|
||||||
<li>• Use the "Export Seed" button to backup your recovery phrase</li>
|
<li>• Use the "Export Seed" button to backup your recovery phrase</li>
|
||||||
<li>• Backup files are saved to persistent storage that survives app installations</li>
|
<li>
|
||||||
<li v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS" class="text-orange-700">
|
• Backup files are saved to persistent storage that survives app
|
||||||
• On Android: Files are saved to Downloads/TimeSafari or app data directory
|
installations
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS"
|
||||||
|
class="text-orange-700"
|
||||||
|
>
|
||||||
|
• On Android: Files are saved to Downloads/TimeSafari or app data
|
||||||
|
directory
|
||||||
</li>
|
</li>
|
||||||
<li v-if="platformCapabilities.isIOS" class="text-orange-700">
|
<li v-if="platformCapabilities.isIOS" class="text-orange-700">
|
||||||
• On iOS: Files are saved to Documents folder (accessible via Files app)
|
• On iOS: Files are saved to Documents folder (accessible via Files
|
||||||
|
app)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -99,18 +110,20 @@
|
|||||||
<button
|
<button
|
||||||
v-for="type in ['all', 'contacts', 'seed', 'other'] as const"
|
v-for="type in ['all', 'contacts', 'seed', 'other'] as const"
|
||||||
:key="type"
|
:key="type"
|
||||||
@click="selectedType = type"
|
|
||||||
:class="[
|
:class="[
|
||||||
'text-sm px-3 py-1 rounded border',
|
'text-sm px-3 py-1 rounded border',
|
||||||
selectedType === type
|
selectedType === type
|
||||||
? 'bg-blue-500 text-white border-blue-500'
|
? 'bg-blue-500 text-white border-blue-500'
|
||||||
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'
|
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50',
|
||||||
]"
|
]"
|
||||||
|
@click="selectedType = type"
|
||||||
>
|
>
|
||||||
{{ type === 'all' ? 'All' : type.charAt(0).toUpperCase() + type.slice(1) }}
|
{{
|
||||||
<span class="ml-1 text-xs">
|
type === "all"
|
||||||
({{ getFileCountByType(type) }})
|
? "All"
|
||||||
</span>
|
: type.charAt(0).toUpperCase() + type.slice(1)
|
||||||
|
}}
|
||||||
|
<span class="ml-1 text-xs"> ({{ getFileCountByType(type) }}) </span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -118,9 +131,9 @@
|
|||||||
<div class="flex items-center gap-2 mb-2">
|
<div class="flex items-center gap-2 mb-2">
|
||||||
<span v-for="(crumb, idx) in breadcrumbs" :key="idx">
|
<span v-for="(crumb, idx) in breadcrumbs" :key="idx">
|
||||||
<span
|
<span
|
||||||
|
v-if="idx < breadcrumbs.length - 1"
|
||||||
class="text-blue-600 cursor-pointer underline"
|
class="text-blue-600 cursor-pointer underline"
|
||||||
@click="goToBreadcrumb(idx)"
|
@click="goToBreadcrumb(idx)"
|
||||||
v-if="idx < breadcrumbs.length - 1"
|
|
||||||
>
|
>
|
||||||
{{ crumb }}
|
{{ crumb }}
|
||||||
</span>
|
</span>
|
||||||
@@ -129,14 +142,23 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="currentPath.length > 1" class="mb-2">
|
<div v-if="currentPath.length > 1" class="mb-2">
|
||||||
<button @click="goUp" class="text-xs text-blue-500 underline">⬅ Up</button>
|
<button class="text-xs text-blue-500 underline" @click="goUp">
|
||||||
|
⬅ Up
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="checkbox" v-model="debugShowAll" @change="loadDirectory" class="mr-2" />
|
<input
|
||||||
|
v-model="debugShowAll"
|
||||||
|
type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
@change="loadDirectory"
|
||||||
|
/>
|
||||||
<span class="text-xs">Debug: Show all entries as files</span>
|
<span class="text-xs">Debug: Show all entries as files</span>
|
||||||
</label>
|
</label>
|
||||||
<span v-if="debugShowAll" class="text-xs text-red-600 ml-2">[Debug mode: forcibly treating all entries as files]</span>
|
<span v-if="debugShowAll" class="text-xs text-red-600 ml-2"
|
||||||
|
>[Debug mode: forcibly treating all entries as files]</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2 max-h-64 overflow-y-auto">
|
<div class="space-y-2 max-h-64 overflow-y-auto">
|
||||||
<div
|
<div
|
||||||
@@ -148,7 +170,10 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<font-awesome icon="folder" class="fa-fw text-yellow-500" />
|
<font-awesome icon="folder" class="fa-fw text-yellow-500" />
|
||||||
<span class="font-medium">{{ entry.name }}</span>
|
<span class="font-medium">{{ entry.name }}</span>
|
||||||
<span class="text-xs bg-gray-200 text-gray-700 px-2 py-0.5 rounded-full ml-2">Folder</span>
|
<span
|
||||||
|
class="text-xs bg-gray-200 text-gray-700 px-2 py-0.5 rounded-full ml-2"
|
||||||
|
>Folder</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -164,14 +189,18 @@
|
|||||||
<div class="text-sm text-gray-500 mt-1">
|
<div class="text-sm text-gray-500 mt-1">
|
||||||
<span v-if="entry.size">{{ formatFileSize(entry.size) }}</span>
|
<span v-if="entry.size">{{ formatFileSize(entry.size) }}</span>
|
||||||
<span v-else>Size unknown</span>
|
<span v-else>Size unknown</span>
|
||||||
<span v-if="entry.path && !platformCapabilities.isIOS" class="ml-2 text-xs text-blue-600">📁 {{ entry.path }}</span>
|
<span
|
||||||
|
v-if="entry.path && !platformCapabilities.isIOS"
|
||||||
|
class="ml-2 text-xs text-blue-600"
|
||||||
|
>📁 {{ entry.path }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2 ml-3">
|
<div class="flex gap-2 ml-3">
|
||||||
<button
|
<button
|
||||||
@click="openFile(entry.uri, entry.name)"
|
|
||||||
class="text-blue-500 hover:text-blue-700 p-1"
|
class="text-blue-500 hover:text-blue-700 p-1"
|
||||||
title="Open file"
|
title="Open file"
|
||||||
|
@click="openFile(entry.uri, entry.name)"
|
||||||
>
|
>
|
||||||
<font-awesome icon="external-link-alt" class="fa-fw" />
|
<font-awesome icon="external-link-alt" class="fa-fw" />
|
||||||
</button>
|
</button>
|
||||||
@@ -181,15 +210,28 @@
|
|||||||
|
|
||||||
<!-- Summary -->
|
<!-- Summary -->
|
||||||
<div class="text-sm text-gray-500 mt-3 pt-3 border-t">
|
<div class="text-sm text-gray-500 mt-3 pt-3 border-t">
|
||||||
Showing {{ filteredFiles.length }} of {{ backupFiles.length }} backup files
|
Showing {{ filteredFiles.length }} of {{ backupFiles.length }} backup
|
||||||
|
files
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-sm text-gray-600 mb-2">
|
<div class="text-sm text-gray-600 mb-2">
|
||||||
<p>📁 Backup files are saved to persistent storage that survives app installations:</p>
|
<p>
|
||||||
|
📁 Backup files are saved to persistent storage that survives app
|
||||||
|
installations:
|
||||||
|
</p>
|
||||||
<ul class="list-disc list-inside ml-2 mt-1 text-xs">
|
<ul class="list-disc list-inside ml-2 mt-1 text-xs">
|
||||||
<li v-if="platformCapabilities.isIOS">iOS: Documents folder (accessible via Files app)</li>
|
<li v-if="platformCapabilities.isIOS">
|
||||||
<li v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS">Android: Downloads/TimeSafari or external storage (accessible via file managers)</li>
|
iOS: Documents folder (accessible via Files app)
|
||||||
<li v-if="!platformCapabilities.isMobile">Desktop: User's download directory</li>
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS"
|
||||||
|
>
|
||||||
|
Android: Downloads/TimeSafari or external storage (accessible via
|
||||||
|
file managers)
|
||||||
|
</li>
|
||||||
|
<li v-if="!platformCapabilities.isMobile">
|
||||||
|
Desktop: User's download directory
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -222,7 +264,8 @@ export default class BackupFilesList extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Platform service instance for platform-specific operations
|
* Platform service instance for platform-specific operations
|
||||||
*/
|
*/
|
||||||
private platformService: PlatformService = PlatformServiceFactory.getInstance();
|
private platformService: PlatformService =
|
||||||
|
PlatformServiceFactory.getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform capabilities for the current platform
|
* Platform capabilities for the current platform
|
||||||
@@ -234,12 +277,18 @@ export default class BackupFilesList extends Vue {
|
|||||||
/**
|
/**
|
||||||
* List of backup files found on the device
|
* List of backup files found on the device
|
||||||
*/
|
*/
|
||||||
backupFiles: Array<{name: string, uri: string, size?: number, type: 'contacts' | 'seed' | 'other', path?: string}> = [];
|
backupFiles: Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
type: "contacts" | "seed" | "other";
|
||||||
|
path?: string;
|
||||||
|
}> = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently selected file type filter
|
* Currently selected file type filter
|
||||||
*/
|
*/
|
||||||
selectedType: 'all' | 'contacts' | 'seed' | 'other' = 'all';
|
selectedType: "all" | "contacts" | "seed" | "other" = "all";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loading state for file operations
|
* Loading state for file operations
|
||||||
@@ -259,7 +308,13 @@ export default class BackupFilesList extends Vue {
|
|||||||
/**
|
/**
|
||||||
* List of files/folders in the current directory
|
* List of files/folders in the current directory
|
||||||
*/
|
*/
|
||||||
directoryEntries: Array<{name: string, uri: string, size?: number, path: string, type: 'file' | 'folder'}> = [];
|
directoryEntries: Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
path: string;
|
||||||
|
type: "file" | "folder";
|
||||||
|
}> = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporary debug mode to show all entries as files
|
* Temporary debug mode to show all entries as files
|
||||||
@@ -271,25 +326,34 @@ export default class BackupFilesList extends Vue {
|
|||||||
* Returns true if permission is granted, false otherwise.
|
* Returns true if permission is granted, false otherwise.
|
||||||
*/
|
*/
|
||||||
private async ensureStoragePermission(): Promise<boolean> {
|
private async ensureStoragePermission(): Promise<boolean> {
|
||||||
logger.log('[BackupFilesList] ensureStoragePermission called. platformCapabilities:', this.platformCapabilities);
|
logger.log(
|
||||||
|
"[BackupFilesList] ensureStoragePermission called. platformCapabilities:",
|
||||||
|
this.platformCapabilities,
|
||||||
|
);
|
||||||
if (!this.platformCapabilities.hasFileSystem) return true;
|
if (!this.platformCapabilities.hasFileSystem) return true;
|
||||||
// Only relevant for native platforms (Android/iOS)
|
// Only relevant for native platforms (Android/iOS)
|
||||||
const platformService = this.platformService as any;
|
const platformService = this.platformService as any;
|
||||||
if (typeof platformService.checkStoragePermissions === 'function') {
|
if (typeof platformService.checkStoragePermissions === "function") {
|
||||||
try {
|
try {
|
||||||
await platformService.checkStoragePermissions();
|
await platformService.checkStoragePermissions();
|
||||||
logger.log('[BackupFilesList] Storage permission granted.');
|
logger.log("[BackupFilesList] Storage permission granted.");
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[BackupFilesList] Storage permission denied:', error);
|
logger.error("[BackupFilesList] Storage permission denied:", error);
|
||||||
|
|
||||||
// Get specific guidance for the platform
|
// Get specific guidance for the platform
|
||||||
let guidance = "This app needs permission to access your files to list and restore backups.";
|
let guidance =
|
||||||
if (typeof platformService.getStoragePermissionGuidance === 'function') {
|
"This app needs permission to access your files to list and restore backups.";
|
||||||
|
if (
|
||||||
|
typeof platformService.getStoragePermissionGuidance === "function"
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
guidance = await platformService.getStoragePermissionGuidance();
|
guidance = await platformService.getStoragePermissionGuidance();
|
||||||
} catch (guidanceError) {
|
} catch (guidanceError) {
|
||||||
logger.warn('[BackupFilesList] Could not get permission guidance:', guidanceError);
|
logger.warn(
|
||||||
|
"[BackupFilesList] Could not get permission guidance:",
|
||||||
|
guidanceError,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,21 +376,27 @@ export default class BackupFilesList extends Vue {
|
|||||||
* Lifecycle hook to load backup files when component is mounted
|
* Lifecycle hook to load backup files when component is mounted
|
||||||
*/
|
*/
|
||||||
async mounted() {
|
async mounted() {
|
||||||
logger.log('[BackupFilesList] mounted hook called. platformCapabilities:', this.platformCapabilities);
|
logger.log(
|
||||||
|
"[BackupFilesList] mounted hook called. platformCapabilities:",
|
||||||
|
this.platformCapabilities,
|
||||||
|
);
|
||||||
if (this.platformCapabilities.hasFileSystem) {
|
if (this.platformCapabilities.hasFileSystem) {
|
||||||
// Check/request permission before loading
|
// Check/request permission before loading
|
||||||
const hasPermission = await this.ensureStoragePermission();
|
const hasPermission = await this.ensureStoragePermission();
|
||||||
if (hasPermission) {
|
if (hasPermission) {
|
||||||
// Set default root path
|
// Set default root path
|
||||||
if (this.platformCapabilities.isIOS) {
|
if (this.platformCapabilities.isIOS) {
|
||||||
this.currentPath = ['.'];
|
this.currentPath = ["."];
|
||||||
} else {
|
} else {
|
||||||
this.currentPath = ['Download', 'TimeSafari'];
|
this.currentPath = ["Download", "TimeSafari"];
|
||||||
}
|
}
|
||||||
await this.loadDirectory();
|
await this.loadDirectory();
|
||||||
this.refreshInterval = window.setInterval(() => {
|
this.refreshInterval = window.setInterval(
|
||||||
|
() => {
|
||||||
this.loadDirectory();
|
this.loadDirectory();
|
||||||
}, 5 * 60 * 1000);
|
},
|
||||||
|
5 * 60 * 1000,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,12 +416,17 @@ export default class BackupFilesList extends Vue {
|
|||||||
* Note: The 'All' tab count is sometimes too small. Logging for debugging.
|
* Note: The 'All' tab count is sometimes too small. Logging for debugging.
|
||||||
*/
|
*/
|
||||||
get filteredFiles() {
|
get filteredFiles() {
|
||||||
if (this.selectedType === 'all') {
|
if (this.selectedType === "all") {
|
||||||
logger.log('[BackupFilesList] filteredFiles (All):', this.backupFiles);
|
logger.log("[BackupFilesList] filteredFiles (All):", this.backupFiles);
|
||||||
return this.backupFiles;
|
return this.backupFiles;
|
||||||
}
|
}
|
||||||
const filtered = this.backupFiles.filter(file => file.type === this.selectedType);
|
const filtered = this.backupFiles.filter(
|
||||||
logger.log(`[BackupFilesList] filteredFiles (${this.selectedType}):`, filtered);
|
(file) => file.type === this.selectedType,
|
||||||
|
);
|
||||||
|
logger.log(
|
||||||
|
`[BackupFilesList] filteredFiles (${this.selectedType}):`,
|
||||||
|
filtered,
|
||||||
|
);
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,11 +444,18 @@ export default class BackupFilesList extends Vue {
|
|||||||
if (!this.platformCapabilities.hasFileSystem) return;
|
if (!this.platformCapabilities.hasFileSystem) return;
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
try {
|
try {
|
||||||
const path = this.currentPath.join('/') || (this.platformCapabilities.isIOS ? '.' : 'Download/TimeSafari');
|
const path =
|
||||||
this.directoryEntries = await (this.platformService as any).listFilesInDirectory(path, this.debugShowAll);
|
this.currentPath.join("/") ||
|
||||||
logger.log('[BackupFilesList] Loaded directory:', { path, entries: this.directoryEntries });
|
(this.platformCapabilities.isIOS ? "." : "Download/TimeSafari");
|
||||||
|
this.directoryEntries = await (
|
||||||
|
this.platformService as PlatformService
|
||||||
|
).listFilesInDirectory(path, this.debugShowAll);
|
||||||
|
logger.log("[BackupFilesList] Loaded directory:", {
|
||||||
|
path,
|
||||||
|
entries: this.directoryEntries,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[BackupFilesList] Failed to load directory:', error);
|
logger.error("[BackupFilesList] Failed to load directory:", error);
|
||||||
this.directoryEntries = [];
|
this.directoryEntries = [];
|
||||||
} finally {
|
} finally {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
@@ -417,17 +499,17 @@ export default class BackupFilesList extends Vue {
|
|||||||
* Computed property for showing files and folders
|
* Computed property for showing files and folders
|
||||||
*/
|
*/
|
||||||
get folders() {
|
get folders() {
|
||||||
return this.directoryEntries.filter(e => e.type === 'folder');
|
return this.directoryEntries.filter((e) => e.type === "folder");
|
||||||
}
|
}
|
||||||
get files() {
|
get files() {
|
||||||
return this.directoryEntries.filter(e => e.type === 'file');
|
return this.directoryEntries.filter((e) => e.type === "file");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the list of backup files from the device
|
* Refreshes the list of backup files from the device
|
||||||
*/
|
*/
|
||||||
async refreshFiles() {
|
async refreshFiles() {
|
||||||
logger.log('[BackupFilesList] refreshFiles called.');
|
logger.log("[BackupFilesList] refreshFiles called.");
|
||||||
if (!this.platformCapabilities.hasFileSystem) {
|
if (!this.platformCapabilities.hasFileSystem) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -441,29 +523,32 @@ export default class BackupFilesList extends Vue {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
try {
|
try {
|
||||||
this.backupFiles = await this.platformService.listBackupFiles();
|
this.backupFiles = await this.platformService.listBackupFiles();
|
||||||
logger.log('[BackupFilesList] Refreshed backup files:', {
|
logger.log("[BackupFilesList] Refreshed backup files:", {
|
||||||
count: this.backupFiles.length,
|
count: this.backupFiles.length,
|
||||||
files: this.backupFiles.map(f => ({
|
files: this.backupFiles.map((f) => ({
|
||||||
name: f.name,
|
name: f.name,
|
||||||
type: f.type,
|
type: f.type,
|
||||||
path: f.path,
|
path: f.path,
|
||||||
size: f.size
|
size: f.size,
|
||||||
})),
|
})),
|
||||||
platform: this.platformCapabilities.isIOS ? "iOS" : "Android",
|
platform: this.platformCapabilities.isIOS ? "iOS" : "Android",
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
// Debug: Log file type distribution
|
// Debug: Log file type distribution
|
||||||
const typeCounts = {
|
const typeCounts = {
|
||||||
contacts: this.backupFiles.filter(f => f.type === 'contacts').length,
|
contacts: this.backupFiles.filter((f) => f.type === "contacts").length,
|
||||||
seed: this.backupFiles.filter(f => f.type === 'seed').length,
|
seed: this.backupFiles.filter((f) => f.type === "seed").length,
|
||||||
other: this.backupFiles.filter(f => f.type === 'other').length,
|
other: this.backupFiles.filter((f) => f.type === "other").length,
|
||||||
total: this.backupFiles.length
|
total: this.backupFiles.length,
|
||||||
};
|
};
|
||||||
logger.log('[BackupFilesList] File type distribution:', typeCounts);
|
logger.log("[BackupFilesList] File type distribution:", typeCounts);
|
||||||
// Log the full backupFiles array for debugging the 'All' tab count
|
// Log the full backupFiles array for debugging the 'All' tab count
|
||||||
logger.log('[BackupFilesList] backupFiles array for All tab:', this.backupFiles);
|
logger.log(
|
||||||
|
"[BackupFilesList] backupFiles array for All tab:",
|
||||||
|
this.backupFiles,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[BackupFilesList] Failed to refresh backup files:', error);
|
logger.error("[BackupFilesList] Failed to refresh backup files:", error);
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -484,12 +569,12 @@ export default class BackupFilesList extends Vue {
|
|||||||
async createTestBackup() {
|
async createTestBackup() {
|
||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
logger.log('[BackupFilesList] Creating test backup file');
|
logger.log("[BackupFilesList] Creating test backup file");
|
||||||
|
|
||||||
const result = await this.platformService.createTestBackupFile();
|
const result = await this.platformService.createTestBackupFile();
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
logger.log('[BackupFilesList] Test backup file created successfully:', {
|
logger.log("[BackupFilesList] Test backup file created successfully:", {
|
||||||
fileName: result.fileName,
|
fileName: result.fileName,
|
||||||
uri: result.uri,
|
uri: result.uri,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
@@ -511,7 +596,10 @@ export default class BackupFilesList extends Vue {
|
|||||||
throw new Error(result.error || "Failed to create test backup file");
|
throw new Error(result.error || "Failed to create test backup file");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[BackupFilesList] Failed to create test backup file:', error);
|
logger.error(
|
||||||
|
"[BackupFilesList] Failed to create test backup file:",
|
||||||
|
error,
|
||||||
|
);
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -532,11 +620,14 @@ export default class BackupFilesList extends Vue {
|
|||||||
async testDirectoryContexts() {
|
async testDirectoryContexts() {
|
||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
logger.log('[BackupFilesList] Testing directory contexts');
|
logger.log("[BackupFilesList] Testing directory contexts");
|
||||||
|
|
||||||
const debugOutput = await this.platformService.testDirectoryContexts();
|
const debugOutput = await this.platformService.testDirectoryContexts();
|
||||||
|
|
||||||
logger.log('[BackupFilesList] Directory context test results:', debugOutput);
|
logger.log(
|
||||||
|
"[BackupFilesList] Directory context test results:",
|
||||||
|
debugOutput,
|
||||||
|
);
|
||||||
|
|
||||||
// Show the debug output in a notification or alert
|
// Show the debug output in a notification or alert
|
||||||
this.$notify(
|
this.$notify(
|
||||||
@@ -550,12 +641,14 @@ export default class BackupFilesList extends Vue {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Also log the full output to console for easy access
|
// Also log the full output to console for easy access
|
||||||
console.log("=== Directory Context Test Results ===");
|
logger.log("=== Directory Context Test Results ===");
|
||||||
console.log(debugOutput);
|
logger.log(debugOutput);
|
||||||
console.log("=== End Test Results ===");
|
logger.log("=== End Test Results ===");
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[BackupFilesList] Failed to test directory contexts:', error);
|
logger.error(
|
||||||
|
"[BackupFilesList] Failed to test directory contexts:",
|
||||||
|
error,
|
||||||
|
);
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -575,7 +668,7 @@ export default class BackupFilesList extends Vue {
|
|||||||
* This method can be called from parent components
|
* This method can be called from parent components
|
||||||
*/
|
*/
|
||||||
async refreshAfterSave() {
|
async refreshAfterSave() {
|
||||||
logger.log('[BackupFilesList] refreshAfterSave called');
|
logger.log("[BackupFilesList] refreshAfterSave called");
|
||||||
await this.refreshFiles();
|
await this.refreshFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,14 +735,18 @@ export default class BackupFilesList extends Vue {
|
|||||||
* Gets the count of files for a specific type
|
* Gets the count of files for a specific type
|
||||||
* Note: The 'All' tab count is sometimes too small. Logging for debugging.
|
* Note: The 'All' tab count is sometimes too small. Logging for debugging.
|
||||||
*/
|
*/
|
||||||
getFileCountByType(type: 'all' | 'contacts' | 'seed' | 'other'): number {
|
getFileCountByType(type: "all" | "contacts" | "seed" | "other"): number {
|
||||||
let count;
|
let count;
|
||||||
if (type === 'all') {
|
if (type === "all") {
|
||||||
count = this.backupFiles.length;
|
count = this.backupFiles.length;
|
||||||
logger.log('[BackupFilesList] getFileCountByType (All):', count, this.backupFiles);
|
logger.log(
|
||||||
|
"[BackupFilesList] getFileCountByType (All):",
|
||||||
|
count,
|
||||||
|
this.backupFiles,
|
||||||
|
);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
count = this.backupFiles.filter(file => file.type === type).length;
|
count = this.backupFiles.filter((file) => file.type === type).length;
|
||||||
logger.log(`[BackupFilesList] getFileCountByType (${type}):`, count);
|
logger.log(`[BackupFilesList] getFileCountByType (${type}):`, count);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -659,14 +756,14 @@ export default class BackupFilesList extends Vue {
|
|||||||
* @param type - File type
|
* @param type - File type
|
||||||
* @returns FontAwesome icon name
|
* @returns FontAwesome icon name
|
||||||
*/
|
*/
|
||||||
getFileIcon(type: 'contacts' | 'seed' | 'other'): string {
|
getFileIcon(type: "contacts" | "seed" | "other"): string {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'contacts':
|
case "contacts":
|
||||||
return 'address-book';
|
return "address-book";
|
||||||
case 'seed':
|
case "seed":
|
||||||
return 'key';
|
return "key";
|
||||||
default:
|
default:
|
||||||
return 'file-alt';
|
return "file-alt";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,14 +772,14 @@ export default class BackupFilesList extends Vue {
|
|||||||
* @param type - File type
|
* @param type - File type
|
||||||
* @returns CSS color class
|
* @returns CSS color class
|
||||||
*/
|
*/
|
||||||
getFileIconColor(type: 'contacts' | 'seed' | 'other'): string {
|
getFileIconColor(type: "contacts" | "seed" | "other"): string {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'contacts':
|
case "contacts":
|
||||||
return 'text-blue-500';
|
return "text-blue-500";
|
||||||
case 'seed':
|
case "seed":
|
||||||
return 'text-orange-500';
|
return "text-orange-500";
|
||||||
default:
|
default:
|
||||||
return 'text-gray-500';
|
return "text-gray-500";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,14 +788,14 @@ export default class BackupFilesList extends Vue {
|
|||||||
* @param type - File type
|
* @param type - File type
|
||||||
* @returns CSS color class
|
* @returns CSS color class
|
||||||
*/
|
*/
|
||||||
getTypeBadgeColor(type: 'contacts' | 'seed' | 'other'): string {
|
getTypeBadgeColor(type: "contacts" | "seed" | "other"): string {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'contacts':
|
case "contacts":
|
||||||
return 'bg-blue-100 text-blue-800';
|
return "bg-blue-100 text-blue-800";
|
||||||
case 'seed':
|
case "seed":
|
||||||
return 'bg-orange-100 text-orange-800';
|
return "bg-orange-100 text-orange-800";
|
||||||
default:
|
default:
|
||||||
return 'bg-gray-100 text-gray-800';
|
return "bg-gray-100 text-gray-800";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,13 +805,13 @@ export default class BackupFilesList extends Vue {
|
|||||||
* @returns Formatted file size string
|
* @returns Formatted file size string
|
||||||
*/
|
*/
|
||||||
formatFileSize(bytes: number): string {
|
formatFileSize(bytes: number): string {
|
||||||
if (bytes === 0) return '0 Bytes';
|
if (bytes === 0) return "0 Bytes";
|
||||||
|
|
||||||
const k = 1024;
|
const k = 1024;
|
||||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
const sizes = ["Bytes", "KB", "MB", "GB"];
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -730,38 +827,56 @@ export default class BackupFilesList extends Vue {
|
|||||||
|
|
||||||
// Test listing all user files
|
// Test listing all user files
|
||||||
const allFilesResult = await platformService.testListUserFiles();
|
const allFilesResult = await platformService.testListUserFiles();
|
||||||
logger.log("[BackupFilesList] All user files test result:", allFilesResult);
|
logger.log(
|
||||||
|
"[BackupFilesList] All user files test result:",
|
||||||
|
allFilesResult,
|
||||||
|
);
|
||||||
|
|
||||||
// Test listing backup files specifically
|
// Test listing backup files specifically
|
||||||
const backupFilesResult = await platformService.testBackupFiles();
|
const backupFilesResult = await platformService.testBackupFiles();
|
||||||
logger.log("[BackupFilesList] Backup files test result:", backupFilesResult);
|
logger.log(
|
||||||
|
"[BackupFilesList] Backup files test result:",
|
||||||
|
backupFilesResult,
|
||||||
|
);
|
||||||
|
|
||||||
// Test listing all backup files (if available)
|
// Note: testListAllBackupFiles method is not part of the PlatformService interface
|
||||||
if ('testListAllBackupFiles' in platformService) {
|
// It exists only in CapacitorPlatformService implementation
|
||||||
const allBackupFilesResult = await (platformService as any).testListAllBackupFiles();
|
// If needed, this could be added to the interface or called via type assertion
|
||||||
logger.log("[BackupFilesList] All backup files test result:", allBackupFilesResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test debug listing all files without filtering (if available)
|
// Test debug listing all files without filtering (if available)
|
||||||
if ('debugListAllFiles' in platformService) {
|
if ("debugListAllFiles" in platformService) {
|
||||||
const debugAllFiles = await (platformService as any).debugListAllFiles();
|
const debugAllFiles = await (
|
||||||
|
platformService as any
|
||||||
|
).debugListAllFiles();
|
||||||
logger.log("[BackupFilesList] Debug all files (no filtering):", {
|
logger.log("[BackupFilesList] Debug all files (no filtering):", {
|
||||||
count: debugAllFiles.length,
|
count: debugAllFiles.length,
|
||||||
files: debugAllFiles.map((f: any) => ({ name: f.name, path: f.path, size: f.size }))
|
files: debugAllFiles.map((f: any) => ({
|
||||||
|
name: f.name,
|
||||||
|
path: f.path,
|
||||||
|
size: f.size,
|
||||||
|
})),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test comprehensive step-by-step debug (if available)
|
// Test comprehensive step-by-step debug (if available)
|
||||||
if ('debugFileDiscoveryStepByStep' in platformService) {
|
if ("debugFileDiscoveryStepByStep" in platformService) {
|
||||||
const stepByStepDebug = await (platformService as any).debugFileDiscoveryStepByStep();
|
const stepByStepDebug = await (
|
||||||
logger.log("[BackupFilesList] Step-by-step debug output:", stepByStepDebug);
|
platformService as any
|
||||||
|
).debugFileDiscoveryStepByStep();
|
||||||
|
logger.log(
|
||||||
|
"[BackupFilesList] Step-by-step debug output:",
|
||||||
|
stepByStepDebug,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allFiles: allFilesResult,
|
allFiles: allFilesResult,
|
||||||
backupFiles: backupFilesResult,
|
backupFiles: backupFilesResult,
|
||||||
currentBackupFiles: this.backupFiles,
|
currentBackupFiles: this.backupFiles,
|
||||||
debugAllFiles: 'debugListAllFiles' in platformService ? await (platformService as any).debugListAllFiles() : null
|
debugAllFiles:
|
||||||
|
"debugListAllFiles" in platformService
|
||||||
|
? await (platformService as any).debugListAllFiles()
|
||||||
|
: null,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("[BackupFilesList] Debug file discovery failed:", error);
|
logger.error("[BackupFilesList] Debug file discovery failed:", error);
|
||||||
@@ -769,7 +884,7 @@ export default class BackupFilesList extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('platformCapabilities.hasFileSystem', { immediate: true })
|
@Watch("platformCapabilities.hasFileSystem", { immediate: true })
|
||||||
async onFileSystemCapabilityChanged(newVal: boolean) {
|
async onFileSystemCapabilityChanged(newVal: boolean) {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
await this.refreshFiles();
|
await this.refreshFiles();
|
||||||
|
|||||||
@@ -44,19 +44,25 @@ explorer. * * @component * @displayName DataExportSection * @example * ```vue *
|
|||||||
v-if="platformCapabilities.isIOS"
|
v-if="platformCapabilities.isIOS"
|
||||||
class="list-disc list-outside ml-4"
|
class="list-disc list-outside ml-4"
|
||||||
>
|
>
|
||||||
On iOS: Files are saved to Documents folder (accessible via Files app) and persist between app installations.
|
On iOS: Files are saved to Documents folder (accessible via Files app)
|
||||||
|
and persist between app installations.
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS"
|
v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS"
|
||||||
class="list-disc list-outside ml-4"
|
class="list-disc list-outside ml-4"
|
||||||
>
|
>
|
||||||
On Android: Files are saved to Downloads/TimeSafari or external storage (accessible via file managers) and persist between app installations.
|
On Android: Files are saved to Downloads/TimeSafari or external
|
||||||
|
storage (accessible via file managers) and persist between app
|
||||||
|
installations.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Backup Files List -->
|
<!-- Backup Files List -->
|
||||||
<div v-if="platformCapabilities.hasFileSystem" class="mt-6 pt-6 border-t border-gray-300">
|
<div
|
||||||
|
v-if="platformCapabilities.hasFileSystem"
|
||||||
|
class="mt-6 pt-6 border-t border-gray-300"
|
||||||
|
>
|
||||||
<BackupFilesList ref="backupFilesList" />
|
<BackupFilesList ref="backupFilesList" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,8 +182,8 @@ export default class DataExportSection extends Vue {
|
|||||||
{
|
{
|
||||||
allowLocationSelection: true,
|
allowLocationSelection: true,
|
||||||
showLocationSelectionDialog: true,
|
showLocationSelectionDialog: true,
|
||||||
mimeType: "application/json"
|
mimeType: "application/json",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle the result
|
// Handle the result
|
||||||
@@ -202,7 +208,10 @@ export default class DataExportSection extends Vue {
|
|||||||
|
|
||||||
// Refresh the backup files list
|
// Refresh the backup files list
|
||||||
const backupFilesList = this.$refs.backupFilesList as any;
|
const backupFilesList = this.$refs.backupFilesList as any;
|
||||||
if (backupFilesList && typeof backupFilesList.refreshAfterSave === 'function') {
|
if (
|
||||||
|
backupFilesList &&
|
||||||
|
typeof backupFilesList.refreshAfterSave === "function"
|
||||||
|
) {
|
||||||
await backupFilesList.refreshAfterSave();
|
await backupFilesList.refreshAfterSave();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -243,7 +252,10 @@ export default class DataExportSection extends Vue {
|
|||||||
// Ensure permissions are requested and refresh backup files list on mount
|
// Ensure permissions are requested and refresh backup files list on mount
|
||||||
if (this.platformCapabilities.hasFileSystem) {
|
if (this.platformCapabilities.hasFileSystem) {
|
||||||
const backupFilesList = this.$refs.backupFilesList as any;
|
const backupFilesList = this.$refs.backupFilesList as any;
|
||||||
if (backupFilesList && typeof backupFilesList.refreshFiles === 'function') {
|
if (
|
||||||
|
backupFilesList &&
|
||||||
|
typeof backupFilesList.refreshFiles === "function"
|
||||||
|
) {
|
||||||
await backupFilesList.refreshFiles();
|
await backupFilesList.refreshFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export interface PlatformService {
|
|||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
showShareDialog?: boolean;
|
showShareDialog?: boolean;
|
||||||
showLocationSelectionDialog?: boolean;
|
showLocationSelectionDialog?: boolean;
|
||||||
}
|
},
|
||||||
): Promise<{ saved: boolean; uri?: string; shared: boolean; error?: string }>;
|
): Promise<{ saved: boolean; uri?: string; shared: boolean; error?: string }>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -190,14 +190,24 @@ export interface PlatformService {
|
|||||||
* Returns files from Downloads (Android) or Documents (iOS) directories.
|
* Returns files from Downloads (Android) or Documents (iOS) directories.
|
||||||
* @returns Promise resolving to array of file information
|
* @returns Promise resolving to array of file information
|
||||||
*/
|
*/
|
||||||
listUserAccessibleFiles(): Promise<Array<{name: string, uri: string, size?: number}>>;
|
listUserAccessibleFiles(): Promise<
|
||||||
|
Array<{ name: string; uri: string; size?: number }>
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists backup files specifically saved by the app.
|
* Lists backup files specifically saved by the app.
|
||||||
* Filters for files that appear to be TimeSafari backups.
|
* Filters for files that appear to be TimeSafari backups.
|
||||||
* @returns Promise resolving to array of backup file information
|
* @returns Promise resolving to array of backup file information
|
||||||
*/
|
*/
|
||||||
listBackupFiles(): Promise<Array<{name: string, uri: string, size?: number, type: 'contacts' | 'seed' | 'other', path?: string}>>;
|
listBackupFiles(): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
type: "contacts" | "seed" | "other";
|
||||||
|
path?: string;
|
||||||
|
}>
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file in the device's default file viewer/app.
|
* Opens a file in the device's default file viewer/app.
|
||||||
@@ -206,7 +216,10 @@ export interface PlatformService {
|
|||||||
* @param fileName - Name of the file (for display purposes)
|
* @param fileName - Name of the file (for display purposes)
|
||||||
* @returns Promise resolving to success status
|
* @returns Promise resolving to success status
|
||||||
*/
|
*/
|
||||||
openFile(fileUri: string, fileName: string): Promise<{ success: boolean; error?: string }>;
|
openFile(
|
||||||
|
fileUri: string,
|
||||||
|
fileName: string,
|
||||||
|
): Promise<{ success: boolean; error?: string }>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the directory containing backup files in the device's file explorer.
|
* Opens the directory containing backup files in the device's file explorer.
|
||||||
@@ -220,7 +233,12 @@ export interface PlatformService {
|
|||||||
* This is useful for debugging file visibility issues.
|
* This is useful for debugging file visibility issues.
|
||||||
* @returns Promise resolving to success status and file information
|
* @returns Promise resolving to success status and file information
|
||||||
*/
|
*/
|
||||||
createTestBackupFile(): Promise<{ success: boolean; fileName?: string; uri?: string; error?: string }>;
|
createTestBackupFile(): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
fileName?: string;
|
||||||
|
uri?: string;
|
||||||
|
error?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests different directory contexts to see what files are available.
|
* Tests different directory contexts to see what files are available.
|
||||||
@@ -235,7 +253,18 @@ export interface PlatformService {
|
|||||||
* @param debugShowAll - Debug flag to treat all entries as files
|
* @param debugShowAll - Debug flag to treat all entries as files
|
||||||
* @returns Promise resolving to array of directory entries
|
* @returns Promise resolving to array of directory entries
|
||||||
*/
|
*/
|
||||||
listFilesInDirectory(path: string, debugShowAll?: boolean): Promise<Array<{name: string, uri: string, size?: number, path: string, type: 'file' | 'folder'}>>;
|
listFilesInDirectory(
|
||||||
|
path: string,
|
||||||
|
debugShowAll?: boolean,
|
||||||
|
): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
path: string;
|
||||||
|
type: "file" | "folder";
|
||||||
|
}>
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug method to check what's actually in the TimeSafari directory
|
* Debug method to check what's actually in the TimeSafari directory
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -249,12 +249,17 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
showShareDialog?: boolean;
|
showShareDialog?: boolean;
|
||||||
showLocationSelectionDialog?: boolean;
|
showLocationSelectionDialog?: boolean;
|
||||||
}
|
},
|
||||||
): Promise<{ saved: boolean; uri?: string; shared: boolean; error?: string }> {
|
): Promise<{
|
||||||
|
saved: boolean;
|
||||||
|
uri?: string;
|
||||||
|
shared: boolean;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
return {
|
return {
|
||||||
saved: false,
|
saved: false,
|
||||||
shared: false,
|
shared: false,
|
||||||
error: "Not implemented in Electron platform"
|
error: "Not implemented in Electron platform",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +440,9 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
* Not implemented in Electron platform.
|
* Not implemented in Electron platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listUserAccessibleFiles(): Promise<Array<{name: string, uri: string, size?: number}>> {
|
async listUserAccessibleFiles(): Promise<
|
||||||
|
Array<{ name: string; uri: string; size?: number }>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +451,15 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
* Not implemented for Electron platform.
|
* Not implemented for Electron platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listBackupFiles(): Promise<Array<{name: string, uri: string, size?: number, type: 'contacts' | 'seed' | 'other', path?: string}>> {
|
async listBackupFiles(): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
type: "contacts" | "seed" | "other";
|
||||||
|
path?: string;
|
||||||
|
}>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,8 +470,14 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
* @param _fileName - Name of the file (for display purposes)
|
* @param _fileName - Name of the file (for display purposes)
|
||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async openFile(_fileUri: string, _fileName: string): Promise<{ success: boolean; error?: string }> {
|
async openFile(
|
||||||
return { success: false, error: "File opening not implemented in Electron platform" };
|
_fileUri: string,
|
||||||
|
_fileName: string,
|
||||||
|
): Promise<{ success: boolean; error?: string }> {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "File opening not implemented in Electron platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -465,7 +486,10 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async openBackupDirectory(): Promise<{ success: boolean; error?: string }> {
|
async openBackupDirectory(): Promise<{ success: boolean; error?: string }> {
|
||||||
return { success: false, error: "Directory access not implemented in Electron platform" };
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "Directory access not implemented in Electron platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -473,7 +497,18 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
* Not implemented for Electron platform.
|
* Not implemented for Electron platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listFilesInDirectory(path: string, debugShowAll?: boolean): Promise<Array<{name: string, uri: string, size?: number, path: string, type: 'file' | 'folder'}>> {
|
async listFilesInDirectory(
|
||||||
|
_path: string,
|
||||||
|
_debugShowAll?: boolean,
|
||||||
|
): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
path: string;
|
||||||
|
type: "file" | "folder";
|
||||||
|
}>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,10 +526,16 @@ export class ElectronPlatformService implements PlatformService {
|
|||||||
* Not implemented for Electron platform.
|
* Not implemented for Electron platform.
|
||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async createTestBackupFile(): Promise<{ success: boolean; fileName?: string; uri?: string; error?: string }> {
|
async createTestBackupFile(): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
fileName?: string;
|
||||||
|
uri?: string;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: "Electron platform does not support file system access for creating test backup files."
|
error:
|
||||||
|
"Electron platform does not support file system access for creating test backup files.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,9 +140,18 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
showShareDialog?: boolean;
|
showShareDialog?: boolean;
|
||||||
showLocationSelectionDialog?: boolean;
|
showLocationSelectionDialog?: boolean;
|
||||||
}
|
},
|
||||||
): Promise<{ saved: boolean; uri?: string; shared: boolean; error?: string }> {
|
): Promise<{
|
||||||
return { saved: false, shared: false, error: "File sharing not implemented in PyWebView platform" };
|
saved: boolean;
|
||||||
|
uri?: string;
|
||||||
|
shared: boolean;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
|
return {
|
||||||
|
saved: false,
|
||||||
|
shared: false,
|
||||||
|
error: "File sharing not implemented in PyWebView platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,7 +159,9 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
* Not implemented in PyWebView platform.
|
* Not implemented in PyWebView platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listUserAccessibleFiles(): Promise<Array<{name: string, uri: string, size?: number}>> {
|
async listUserAccessibleFiles(): Promise<
|
||||||
|
Array<{ name: string; uri: string; size?: number }>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +170,15 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
* Not implemented for PyWebView platform.
|
* Not implemented for PyWebView platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listBackupFiles(): Promise<Array<{name: string, uri: string, size?: number, type: 'contacts' | 'seed' | 'other', path?: string}>> {
|
async listBackupFiles(): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
type: "contacts" | "seed" | "other";
|
||||||
|
path?: string;
|
||||||
|
}>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,8 +189,14 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
* @param _fileName - Name of the file (for display purposes)
|
* @param _fileName - Name of the file (for display purposes)
|
||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async openFile(_fileUri: string, _fileName: string): Promise<{ success: boolean; error?: string }> {
|
async openFile(
|
||||||
return { success: false, error: "File opening not implemented in PyWebView platform" };
|
_fileUri: string,
|
||||||
|
_fileName: string,
|
||||||
|
): Promise<{ success: boolean; error?: string }> {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "File opening not implemented in PyWebView platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,7 +205,10 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async openBackupDirectory(): Promise<{ success: boolean; error?: string }> {
|
async openBackupDirectory(): Promise<{ success: boolean; error?: string }> {
|
||||||
return { success: false, error: "Directory access not implemented in PyWebView platform" };
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "Directory access not implemented in PyWebView platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,7 +280,18 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
* Not implemented for PyWebView platform.
|
* Not implemented for PyWebView platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listFilesInDirectory(path: string, debugShowAll?: boolean): Promise<Array<{name: string, uri: string, size?: number, path: string, type: 'file' | 'folder'}>> {
|
async listFilesInDirectory(
|
||||||
|
_path: string,
|
||||||
|
_debugShowAll?: boolean,
|
||||||
|
): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
path: string;
|
||||||
|
type: "file" | "folder";
|
||||||
|
}>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,10 +309,16 @@ export class PyWebViewPlatformService implements PlatformService {
|
|||||||
* Not implemented for PyWebView platform.
|
* Not implemented for PyWebView platform.
|
||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async createTestBackupFile(): Promise<{ success: boolean; fileName?: string; uri?: string; error?: string }> {
|
async createTestBackupFile(): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
fileName?: string;
|
||||||
|
uri?: string;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: "PyWebView platform does not support file system access for creating test backup files."
|
error:
|
||||||
|
"PyWebView platform does not support file system access for creating test backup files.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ export class WebPlatformService implements PlatformService {
|
|||||||
return {
|
return {
|
||||||
hasFileSystem: false,
|
hasFileSystem: false,
|
||||||
hasCamera: true, // Through file input with capture
|
hasCamera: true, // Through file input with capture
|
||||||
isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
isMobile:
|
||||||
|
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||||
navigator.userAgent,
|
navigator.userAgent,
|
||||||
),
|
),
|
||||||
isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent),
|
isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent),
|
||||||
@@ -372,12 +373,17 @@ export class WebPlatformService implements PlatformService {
|
|||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
showShareDialog?: boolean;
|
showShareDialog?: boolean;
|
||||||
showLocationSelectionDialog?: boolean;
|
showLocationSelectionDialog?: boolean;
|
||||||
}
|
},
|
||||||
): Promise<{ saved: boolean; uri?: string; shared: boolean; error?: string }> {
|
): Promise<{
|
||||||
|
saved: boolean;
|
||||||
|
uri?: string;
|
||||||
|
shared: boolean;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
return {
|
return {
|
||||||
saved: false,
|
saved: false,
|
||||||
shared: false,
|
shared: false,
|
||||||
error: "File system access not available in web platform"
|
error: "File system access not available in web platform",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +477,9 @@ export class WebPlatformService implements PlatformService {
|
|||||||
* Not supported in web platform.
|
* Not supported in web platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listUserAccessibleFiles(): Promise<Array<{name: string, uri: string, size?: number}>> {
|
async listUserAccessibleFiles(): Promise<
|
||||||
|
Array<{ name: string; uri: string; size?: number }>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +488,15 @@ export class WebPlatformService implements PlatformService {
|
|||||||
* Not supported in web platform.
|
* Not supported in web platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listBackupFiles(): Promise<Array<{name: string, uri: string, size?: number, type: 'contacts' | 'seed' | 'other', path?: string}>> {
|
async listBackupFiles(): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
type: "contacts" | "seed" | "other";
|
||||||
|
path?: string;
|
||||||
|
}>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,8 +507,14 @@ export class WebPlatformService implements PlatformService {
|
|||||||
* @param _fileName - Name of the file (for display purposes)
|
* @param _fileName - Name of the file (for display purposes)
|
||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async openFile(_fileUri: string, _fileName: string): Promise<{ success: boolean; error?: string }> {
|
async openFile(
|
||||||
return { success: false, error: "File opening not available in web platform" };
|
_fileUri: string,
|
||||||
|
_fileName: string,
|
||||||
|
): Promise<{ success: boolean; error?: string }> {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "File opening not available in web platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -501,7 +523,10 @@ export class WebPlatformService implements PlatformService {
|
|||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async openBackupDirectory(): Promise<{ success: boolean; error?: string }> {
|
async openBackupDirectory(): Promise<{ success: boolean; error?: string }> {
|
||||||
return { success: false, error: "Directory access not available in web platform" };
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "Directory access not available in web platform",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -519,7 +544,18 @@ export class WebPlatformService implements PlatformService {
|
|||||||
* Not supported in web platform.
|
* Not supported in web platform.
|
||||||
* @returns Promise resolving to empty array
|
* @returns Promise resolving to empty array
|
||||||
*/
|
*/
|
||||||
async listFilesInDirectory(path: string, debugShowAll?: boolean): Promise<Array<{name: string, uri: string, size?: number, path: string, type: 'file' | 'folder'}>> {
|
async listFilesInDirectory(
|
||||||
|
_path: string,
|
||||||
|
_debugShowAll?: boolean,
|
||||||
|
): Promise<
|
||||||
|
Array<{
|
||||||
|
name: string;
|
||||||
|
uri: string;
|
||||||
|
size?: number;
|
||||||
|
path: string;
|
||||||
|
type: "file" | "folder";
|
||||||
|
}>
|
||||||
|
> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,10 +573,16 @@ export class WebPlatformService implements PlatformService {
|
|||||||
* Not supported in web platform.
|
* Not supported in web platform.
|
||||||
* @returns Promise resolving to error status
|
* @returns Promise resolving to error status
|
||||||
*/
|
*/
|
||||||
async createTestBackupFile(): Promise<{ success: boolean; fileName?: string; uri?: string; error?: string }> {
|
async createTestBackupFile(): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
fileName?: string;
|
||||||
|
uri?: string;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: "Web platform does not support file system access for creating test backup files."
|
error:
|
||||||
|
"Web platform does not support file system access for creating test backup files.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export default { logger };
|
|||||||
* @returns Formatted timestamp string safe for filenames
|
* @returns Formatted timestamp string safe for filenames
|
||||||
*/
|
*/
|
||||||
export function getTimestampForFilename(): string {
|
export function getTimestampForFilename(): string {
|
||||||
return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
return new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -217,7 +217,8 @@
|
|||||||
|
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<h2 class="text-xl font-bold mb-4">File Sharing Test</h2>
|
<h2 class="text-xl font-bold mb-4">File Sharing Test</h2>
|
||||||
Test the new file sharing functionality that saves to user-accessible locations.
|
Test the new file sharing functionality that saves to user-accessible
|
||||||
|
locations.
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="font-bold capitalize bg-slate-500 text-white px-3 py-2 rounded-md mr-2"
|
class="font-bold capitalize bg-slate-500 text-white px-3 py-2 rounded-md mr-2"
|
||||||
@@ -747,7 +748,10 @@ export default class Help extends Vue {
|
|||||||
try {
|
try {
|
||||||
const result = await platformService.testLocationSelectionSilent();
|
const result = await platformService.testLocationSelectionSilent();
|
||||||
this.fileSharingResult = result;
|
this.fileSharingResult = result;
|
||||||
logger.log("Silent Location Selection Test Result:", this.fileSharingResult);
|
logger.log(
|
||||||
|
"Silent Location Selection Test Result:",
|
||||||
|
this.fileSharingResult,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Silent Location Selection Test Error:", error);
|
logger.error("Silent Location Selection Test Error:", error);
|
||||||
this.$notify(
|
this.$notify(
|
||||||
@@ -825,8 +829,10 @@ export default class Help extends Vue {
|
|||||||
public async testFileDiscoveryDebug() {
|
public async testFileDiscoveryDebug() {
|
||||||
const platformService = PlatformServiceFactory.getInstance();
|
const platformService = PlatformServiceFactory.getInstance();
|
||||||
try {
|
try {
|
||||||
if ('debugFileDiscoveryStepByStep' in platformService) {
|
if ("debugFileDiscoveryStepByStep" in platformService) {
|
||||||
const result = await (platformService as any).debugFileDiscoveryStepByStep();
|
const result = await (
|
||||||
|
platformService as any
|
||||||
|
).debugFileDiscoveryStepByStep();
|
||||||
this.fileSharingResult = result;
|
this.fileSharingResult = result;
|
||||||
logger.log("File Discovery Debug Test Result:", this.fileSharingResult);
|
logger.log("File Discovery Debug Test Result:", this.fileSharingResult);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user