Browse Source

Mobile native to use web camera

- Ensure consistent UI experience for uploading photos across mobile web and native
pull/135/head
Jose Olarte III 7 days ago
parent
commit
efc720e47f
  1. 96
      src/components/ImageMethodDialog.vue
  2. 2
      src/views/NewEditProjectView.vue

96
src/components/ImageMethodDialog.vue

@ -379,16 +379,16 @@ export default class ImageMethodDialog extends Vue {
}
open(setImageFn: (arg: string) => void, claimType: string, crop?: boolean) {
logger.debug("ImageMethodDialog.open called");
this.claimType = claimType;
this.crop = !!crop;
this.imageCallback = setImageFn;
this.visible = true;
this.currentFacingMode = this.defaultCameraMode as 'environment' | 'user';
// Start camera preview immediately if not on mobile
if (!this.platformCapabilities.isNativeApp) {
this.startCameraPreview();
}
// Start camera preview immediately
logger.debug("Starting camera preview from open()");
this.startCameraPreview();
}
async uploadImageFile(event: Event) {
@ -457,44 +457,19 @@ export default class ImageMethodDialog extends Vue {
logger.debug("startCameraPreview called");
logger.debug("Current showCameraPreview state:", this.showCameraPreview);
logger.debug("Platform capabilities:", this.platformCapabilities);
logger.debug("MediaDevices available:", !!navigator.mediaDevices);
logger.debug("getUserMedia available:", !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia));
if (this.platformCapabilities.isNativeApp) {
logger.debug("Using platform service for mobile device");
this.cameraState = "initializing";
this.cameraStateMessage = "Using platform camera service...";
try {
const result = await this.platformService.takePicture();
this.blob = result.blob;
this.fileName = result.fileName;
this.cameraState = "ready";
this.cameraStateMessage = "Photo captured successfully";
} catch (error) {
logger.error("Error taking picture:", error);
this.cameraState = "error";
this.cameraStateMessage =
error instanceof Error ? error.message : "Failed to take picture";
this.error =
error instanceof Error ? error.message : "Failed to take picture";
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to take picture. Please try again.",
},
5000,
);
}
return;
}
logger.debug("Starting camera preview for desktop browser");
try {
this.cameraState = "initializing";
this.cameraStateMessage = "Requesting camera access...";
this.showCameraPreview = true;
await this.$nextTick();
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
throw new Error("Camera API not available in this browser");
}
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: this.currentFacingMode },
});
@ -511,10 +486,17 @@ export default class ImageMethodDialog extends Vue {
await new Promise((resolve) => {
videoElement.onloadedmetadata = () => {
videoElement.play().then(() => {
logger.debug("Video element started playing");
resolve(true);
}).catch(error => {
logger.error("Error playing video:", error);
throw error;
});
};
});
} else {
logger.error("Video element not found");
throw new Error("Video element not found");
}
} catch (error) {
logger.error("Error starting camera preview:", error);
@ -538,6 +520,7 @@ export default class ImageMethodDialog extends Vue {
this.cameraState = "error";
this.cameraStateMessage = errorMessage;
this.error = errorMessage;
this.showCameraPreview = false;
this.$notify(
{
group: "alert",
@ -547,7 +530,6 @@ export default class ImageMethodDialog extends Vue {
},
5000,
);
this.showCameraPreview = false;
}
}
@ -600,39 +582,17 @@ export default class ImageMethodDialog extends Vue {
}
async rotateCamera() {
if (this.platformCapabilities.isNativeApp) {
try {
await this.platformService.rotateCamera();
// Take a new picture with the rotated camera
const result = await this.platformService.takePicture();
this.blob = result.blob;
this.fileName = result.fileName;
this.showRetry = true;
} catch (error) {
logger.error("Error rotating camera:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to rotate camera. Please try again.",
},
5000,
);
}
} else {
// For web browsers, toggle between front and back cameras
this.currentFacingMode = this.currentFacingMode === 'environment' ? 'user' : 'environment';
// Stop current stream
if (this.cameraStream) {
this.cameraStream.getTracks().forEach(track => track.stop());
this.cameraStream = null;
}
// Start new stream with updated facing mode
await this.startCameraPreview();
// Toggle between front and back cameras
this.currentFacingMode = this.currentFacingMode === 'environment' ? 'user' : 'environment';
// Stop current stream
if (this.cameraStream) {
this.cameraStream.getTracks().forEach(track => track.stop());
this.cameraStream = null;
}
// Start new stream with updated facing mode
await this.startCameraPreview();
}
private createBlobURL(blob: Blob): string {

2
src/views/NewEditProjectView.vue

@ -50,7 +50,7 @@
/>
</span>
</div>
<ImageMethodDialog ref="imageDialog" />
<ImageMethodDialog ref="imageDialog" default-camera-mode="environment" />
<input
v-model="agentDid"

Loading…
Cancel
Save