feat(android): implement file picker for data export

- Add @capawesome/capacitor-file-picker dependency
- Update DataExportSection UI text to reflect new file picker behavior
- Implement file picker in CapacitorPlatformService
- Add debug logging for path handling
- Fix logger to show messages in Capacitor environment

WIP: File path handling still needs refinement
This commit is contained in:
Matthew Raymer
2025-04-09 10:04:03 +00:00
parent 59cfd86d7e
commit a3f7e0e12f
10 changed files with 95 additions and 16 deletions

View File

@@ -5,6 +5,7 @@ import {
} from "../PlatformService";
import { Filesystem, Directory } from "@capacitor/filesystem";
import { Camera, CameraResultType, CameraSource } from "@capacitor/camera";
import { FilePicker } from "@capawesome/capacitor-file-picker";
import { logger } from "../../utils/logger";
/**
@@ -48,17 +49,57 @@ export class CapacitorPlatformService implements PlatformService {
}
/**
* Writes content to a file in the app's data directory.
* @param path - Relative path where to write the file
* Writes content to a file in the user-selected directory.
* Opens a directory picker for the user to choose where to save.
* @param path - Suggested filename
* @param content - Content to write to the file
* @throws Error if write operation fails
*/
async writeFile(path: string, content: string): Promise<void> {
await Filesystem.writeFile({
path,
data: content,
directory: Directory.Data,
});
try {
// Let user pick save location first
const result = await FilePicker.pickDirectory();
logger.log("FilePicker result path:", result.path);
// Handle paths based on platform
let cleanPath = result.path;
if (this.getCapabilities().isIOS) {
// For iOS, keep content: prefix
cleanPath = result.path;
} else {
// For Android, extract the actual path from the content URI
const pathMatch = result.path.match(/tree\/(.*?)(?:\/|$)/);
logger.log("Path match result:", pathMatch);
if (pathMatch) {
const decodedPath = decodeURIComponent(pathMatch[1]);
logger.log("Decoded path:", decodedPath);
// Convert primary:Download to /storage/emulated/0/Download
cleanPath = decodedPath.replace('primary:', '/storage/emulated/0/');
}
}
// For Android, ensure we're using the correct external storage path
if (this.getCapabilities().isMobile && !this.getCapabilities().isIOS) {
logger.log("Before Android path conversion:", cleanPath);
cleanPath = cleanPath.replace('primary:', '/storage/emulated/0/');
logger.log("After Android path conversion:", cleanPath);
}
const finalPath = `${cleanPath}/${path}`;
logger.log("Final path for writeFile:", finalPath);
// Write to the selected directory
await Filesystem.writeFile({
path: finalPath,
data: content,
directory: Directory.External,
recursive: true,
});
} catch (error) {
logger.error("Error saving file:", error);
throw new Error("Failed to save file to selected location");
}
}
/**