diff --git a/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock
index 6f5da8a4..c7300913 100644
Binary files a/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/android/.gradle/file-system.probe b/android/.gradle/file-system.probe
index d0da6143..d8388669 100644
Binary files a/android/.gradle/file-system.probe and b/android/.gradle/file-system.probe differ
diff --git a/src/components/PhotoDialog.vue b/src/components/PhotoDialog.vue
index 76fd948a..9ffba49e 100644
--- a/src/components/PhotoDialog.vue
+++ b/src/components/PhotoDialog.vue
@@ -40,11 +40,6 @@
}"
class="max-h-[90vh] max-w-[90vw] object-contain"
/>
-
-
-
-
-
+
+
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -438,12 +304,4 @@ export default class PhotoDialog extends Vue {
width: 100%;
max-width: 700px;
}
-
-.mirror-video {
- transform: scaleX(-1);
- -webkit-transform: scaleX(-1); /* For Safari */
- -moz-transform: scaleX(-1); /* For Firefox */
- -ms-transform: scaleX(-1); /* For IE */
- -o-transform: scaleX(-1); /* For Opera */
-}
diff --git a/src/services/PlatformService.ts b/src/services/PlatformService.ts
index 8cb6c8e4..ab3c0a60 100644
--- a/src/services/PlatformService.ts
+++ b/src/services/PlatformService.ts
@@ -1,3 +1,8 @@
+export interface ImageResult {
+ blob: Blob;
+ fileName: string;
+}
+
export interface PlatformService {
// File system operations
readFile(path: string): Promise;
@@ -6,8 +11,8 @@ export interface PlatformService {
listFiles(directory: string): Promise;
// Camera operations
- takePicture(): Promise;
- pickImage(): Promise;
+ takePicture(): Promise;
+ pickImage(): Promise;
// Platform specific features
isCapacitor(): boolean;
diff --git a/src/services/platforms/CapacitorPlatformService.ts b/src/services/platforms/CapacitorPlatformService.ts
index ae1aa2ab..ad232f3a 100644
--- a/src/services/platforms/CapacitorPlatformService.ts
+++ b/src/services/platforms/CapacitorPlatformService.ts
@@ -1,8 +1,9 @@
-import { PlatformService } from "../PlatformService";
+import { ImageResult, PlatformService } from "../PlatformService";
import { Capacitor } from "@capacitor/core";
import { Filesystem, Directory } from "@capacitor/filesystem";
import { Camera, CameraResultType, CameraSource } from "@capacitor/camera";
import { App } from "@capacitor/app";
+import { logger } from "../../utils/logger";
export class CapacitorPlatformService implements PlatformService {
async readFile(path: string): Promise {
@@ -36,24 +37,64 @@ export class CapacitorPlatformService implements PlatformService {
return result.files;
}
- async takePicture(): Promise {
- const image = await Camera.getPhoto({
- quality: 90,
- allowEditing: true,
- resultType: CameraResultType.Uri,
- source: CameraSource.Camera,
- });
- return image.webPath || "";
+ async takePicture(): Promise {
+ try {
+ const image = await Camera.getPhoto({
+ quality: 90,
+ allowEditing: true,
+ resultType: CameraResultType.Base64,
+ source: CameraSource.Camera,
+ });
+
+ const blob = await this.processImageData(image.base64String);
+ return {
+ blob,
+ fileName: `photo_${Date.now()}.${image.format || 'jpg'}`
+ };
+ } catch (error) {
+ logger.error("Error taking picture with Capacitor:", error);
+ throw new Error("Failed to take picture");
+ }
}
- async pickImage(): Promise {
- const image = await Camera.getPhoto({
- quality: 90,
- allowEditing: true,
- resultType: CameraResultType.Uri,
- source: CameraSource.Photos,
- });
- return image.webPath || "";
+ async pickImage(): Promise {
+ try {
+ const image = await Camera.getPhoto({
+ quality: 90,
+ allowEditing: true,
+ resultType: CameraResultType.Base64,
+ source: CameraSource.Photos,
+ });
+
+ const blob = await this.processImageData(image.base64String);
+ return {
+ blob,
+ fileName: `photo_${Date.now()}.${image.format || 'jpg'}`
+ };
+ } catch (error) {
+ logger.error("Error picking image with Capacitor:", error);
+ throw new Error("Failed to pick image");
+ }
+ }
+
+ private async processImageData(base64String?: string): Promise {
+ if (!base64String) {
+ throw new Error("No image data received");
+ }
+
+ // Convert base64 to blob
+ const byteCharacters = atob(base64String);
+ const byteArrays = [];
+ for (let offset = 0; offset < byteCharacters.length; offset += 512) {
+ const slice = byteCharacters.slice(offset, offset + 512);
+ const byteNumbers = new Array(slice.length);
+ for (let i = 0; i < slice.length; i++) {
+ byteNumbers[i] = slice.charCodeAt(i);
+ }
+ const byteArray = new Uint8Array(byteNumbers);
+ byteArrays.push(byteArray);
+ }
+ return new Blob(byteArrays, { type: 'image/jpeg' });
}
isCapacitor(): boolean {
diff --git a/src/services/platforms/ElectronPlatformService.ts b/src/services/platforms/ElectronPlatformService.ts
index 8595d390..00d41174 100644
--- a/src/services/platforms/ElectronPlatformService.ts
+++ b/src/services/platforms/ElectronPlatformService.ts
@@ -1,28 +1,28 @@
-import { PlatformService } from '../PlatformService';
+import { PlatformService } from "../PlatformService";
export class ElectronPlatformService implements PlatformService {
async readFile(path: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async writeFile(path: string, content: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async deleteFile(path: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async listFiles(directory: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async takePicture(): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async pickImage(): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
isCapacitor(): boolean {
@@ -42,6 +42,6 @@ export class ElectronPlatformService implements PlatformService {
}
async handleDeepLink(url: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
-}
\ No newline at end of file
+}
diff --git a/src/services/platforms/PyWebViewPlatformService.ts b/src/services/platforms/PyWebViewPlatformService.ts
index 4d10a285..907241fe 100644
--- a/src/services/platforms/PyWebViewPlatformService.ts
+++ b/src/services/platforms/PyWebViewPlatformService.ts
@@ -1,28 +1,28 @@
-import { PlatformService } from '../PlatformService';
+import { PlatformService } from "../PlatformService";
export class PyWebViewPlatformService implements PlatformService {
async readFile(path: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async writeFile(path: string, content: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async deleteFile(path: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async listFiles(directory: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async takePicture(): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
async pickImage(): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
isCapacitor(): boolean {
@@ -42,6 +42,6 @@ export class PyWebViewPlatformService implements PlatformService {
}
async handleDeepLink(url: string): Promise {
- throw new Error('Not implemented');
+ throw new Error("Not implemented");
}
-}
\ No newline at end of file
+}
diff --git a/src/services/platforms/WebPlatformService.ts b/src/services/platforms/WebPlatformService.ts
index befb7cbc..9ae1de83 100644
--- a/src/services/platforms/WebPlatformService.ts
+++ b/src/services/platforms/WebPlatformService.ts
@@ -1,4 +1,5 @@
-import { PlatformService } from "../PlatformService";
+import { ImageResult, PlatformService } from "../PlatformService";
+import { logger } from "../../utils/logger";
export class WebPlatformService implements PlatformService {
async readFile(path: string): Promise {
@@ -17,23 +18,28 @@ export class WebPlatformService implements PlatformService {
throw new Error("File system access not available in web platform");
}
- async takePicture(): Promise {
+ async takePicture(): Promise {
return new Promise((resolve, reject) => {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.capture = "environment";
- input.onchange = (e) => {
+ input.onchange = async (e) => {
const file = (e.target as HTMLInputElement).files?.[0];
if (file) {
- const reader = new FileReader();
- reader.onload = (event) => {
- resolve(event.target?.result as string);
- };
- reader.readAsDataURL(file);
+ try {
+ const blob = await this.processImageFile(file);
+ resolve({
+ blob,
+ fileName: file.name || "photo.jpg"
+ });
+ } catch (error) {
+ logger.error("Error processing camera image:", error);
+ reject(new Error("Failed to process camera image"));
+ }
} else {
- reject(new Error("No file selected"));
+ reject(new Error("No image captured"));
}
};
@@ -41,22 +47,27 @@ export class WebPlatformService implements PlatformService {
});
}
- async pickImage(): Promise {
+ async pickImage(): Promise {
return new Promise((resolve, reject) => {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
- input.onchange = (e) => {
+ input.onchange = async (e) => {
const file = (e.target as HTMLInputElement).files?.[0];
if (file) {
- const reader = new FileReader();
- reader.onload = (event) => {
- resolve(event.target?.result as string);
- };
- reader.readAsDataURL(file);
+ try {
+ const blob = await this.processImageFile(file);
+ resolve({
+ blob,
+ fileName: file.name || "photo.jpg"
+ });
+ } catch (error) {
+ logger.error("Error processing picked image:", error);
+ reject(new Error("Failed to process picked image"));
+ }
} else {
- reject(new Error("No file selected"));
+ reject(new Error("No image selected"));
}
};
@@ -64,6 +75,28 @@ export class WebPlatformService implements PlatformService {
});
}
+ private async processImageFile(file: File): Promise {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ const dataUrl = event.target?.result as string;
+ // Convert to blob to ensure consistent format
+ fetch(dataUrl)
+ .then(res => res.blob())
+ .then(blob => resolve(blob))
+ .catch(error => {
+ logger.error("Error converting data URL to blob:", error);
+ reject(error);
+ });
+ };
+ reader.onerror = (error) => {
+ logger.error("Error reading file:", error);
+ reject(error);
+ };
+ reader.readAsDataURL(file);
+ });
+ }
+
isCapacitor(): boolean {
return false;
}