forked from trent_larson/crowd-funder-for-time-pwa
docs(PhotoDialog): improve component documentation and error handling
- Add comprehensive JSDoc documentation for component features and capabilities - Fix line wrapping in file-level documentation header - Improve error message formatting for better readability - Remove unused PhotoResult interface - Maintain consistent documentation style with project standards The documentation improvements help developers better understand the component's cross-platform photo handling capabilities and error management approach.
This commit is contained in:
@@ -0,0 +1,222 @@
|
|||||||
|
---
|
||||||
|
description:
|
||||||
|
globs:
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
# Camera Implementation Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document describes how camera functionality is implemented across the TimeSafari application. The application uses cameras for two main purposes:
|
||||||
|
|
||||||
|
1. QR Code scanning
|
||||||
|
2. Photo capture
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### QRScannerDialog.vue
|
||||||
|
|
||||||
|
Primary component for QR code scanning in web browsers.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
- Uses `qrcode-stream` for web-based QR scanning
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Provides real-time camera status feedback
|
||||||
|
- Implements error handling with user-friendly messages
|
||||||
|
- Includes camera switching functionality
|
||||||
|
|
||||||
|
**Camera Access Flow:**
|
||||||
|
|
||||||
|
1. Checks for camera API availability
|
||||||
|
2. Enumerates available video devices
|
||||||
|
3. Requests camera permissions
|
||||||
|
4. Initializes camera stream with preferred settings
|
||||||
|
5. Handles various error conditions with specific messages
|
||||||
|
|
||||||
|
### PhotoDialog.vue
|
||||||
|
|
||||||
|
Component for photo capture and selection.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
- Cross-platform photo capture interface
|
||||||
|
- Image cropping capabilities
|
||||||
|
- File selection fallback
|
||||||
|
- Unified interface for different platforms
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
### QRScanner Services
|
||||||
|
|
||||||
|
#### WebDialogQRScanner
|
||||||
|
|
||||||
|
Web-based implementation of QR scanning.
|
||||||
|
|
||||||
|
**Key Methods:**
|
||||||
|
|
||||||
|
- `checkPermissions()`: Verifies camera permission status
|
||||||
|
- `requestPermissions()`: Requests camera access
|
||||||
|
- `isSupported()`: Checks for camera API support
|
||||||
|
- Handles various error conditions with specific messages
|
||||||
|
|
||||||
|
#### CapacitorQRScanner
|
||||||
|
|
||||||
|
Native implementation using Capacitor's MLKit.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
- Uses `@capacitor-mlkit/barcode-scanning`
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Implements permission management
|
||||||
|
- Provides continuous scanning capability
|
||||||
|
|
||||||
|
### Platform Services
|
||||||
|
|
||||||
|
#### WebPlatformService
|
||||||
|
|
||||||
|
Web-specific implementation of platform features.
|
||||||
|
|
||||||
|
**Camera Capabilities:**
|
||||||
|
|
||||||
|
- Uses HTML5 file input with capture attribute
|
||||||
|
- Falls back to file selection if camera unavailable
|
||||||
|
- Processes captured images for consistent format
|
||||||
|
|
||||||
|
#### CapacitorPlatformService
|
||||||
|
|
||||||
|
Native implementation using Capacitor.
|
||||||
|
|
||||||
|
**Camera Features:**
|
||||||
|
|
||||||
|
- Uses `Camera.getPhoto()` for native camera access
|
||||||
|
- Supports image editing
|
||||||
|
- Configures high-quality image capture
|
||||||
|
- Handles base64 image processing
|
||||||
|
|
||||||
|
#### ElectronPlatformService
|
||||||
|
|
||||||
|
Desktop implementation (currently unimplemented).
|
||||||
|
|
||||||
|
**Status:**
|
||||||
|
|
||||||
|
- Camera functionality not yet implemented
|
||||||
|
- Planned to use Electron's media APIs
|
||||||
|
|
||||||
|
## Platform-Specific Considerations
|
||||||
|
|
||||||
|
### iOS
|
||||||
|
|
||||||
|
- Requires `NSCameraUsageDescription` in Info.plist
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Implements proper permission handling
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
- Requires camera permissions in manifest
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Handles permission requests through Capacitor
|
||||||
|
|
||||||
|
### Web
|
||||||
|
|
||||||
|
- Requires HTTPS for camera access
|
||||||
|
- Implements fallback mechanisms
|
||||||
|
- Handles browser compatibility issues
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Common Error Scenarios
|
||||||
|
|
||||||
|
1. No camera found
|
||||||
|
2. Permission denied
|
||||||
|
3. Camera in use by another application
|
||||||
|
4. HTTPS required
|
||||||
|
5. Browser compatibility issues
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
|
||||||
|
- User-friendly error messages
|
||||||
|
- Troubleshooting tips
|
||||||
|
- Clear instructions for resolution
|
||||||
|
- Platform-specific guidance
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Permission Management
|
||||||
|
|
||||||
|
- Explicit permission requests
|
||||||
|
- Permission state tracking
|
||||||
|
- Graceful handling of denied permissions
|
||||||
|
|
||||||
|
### Data Handling
|
||||||
|
|
||||||
|
- Secure image processing
|
||||||
|
- Proper cleanup of camera resources
|
||||||
|
- No persistent storage of camera data
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Camera Access
|
||||||
|
|
||||||
|
1. Always check for camera availability
|
||||||
|
2. Request permissions explicitly
|
||||||
|
3. Handle all error conditions
|
||||||
|
4. Provide clear user feedback
|
||||||
|
5. Implement proper cleanup
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
1. Optimize camera resolution
|
||||||
|
2. Implement proper resource cleanup
|
||||||
|
3. Handle camera switching efficiently
|
||||||
|
4. Manage memory usage
|
||||||
|
|
||||||
|
### User Experience
|
||||||
|
|
||||||
|
1. Clear status indicators
|
||||||
|
2. Intuitive camera controls
|
||||||
|
3. Helpful error messages
|
||||||
|
4. Smooth camera switching
|
||||||
|
5. Responsive UI feedback
|
||||||
|
|
||||||
|
## Future Improvements
|
||||||
|
|
||||||
|
### Planned Enhancements
|
||||||
|
|
||||||
|
1. Implement Electron camera support
|
||||||
|
2. Add advanced camera features
|
||||||
|
3. Improve error handling
|
||||||
|
4. Enhance user feedback
|
||||||
|
5. Optimize performance
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
|
||||||
|
1. Electron camera implementation pending
|
||||||
|
2. Some browser compatibility limitations
|
||||||
|
3. Platform-specific quirks to address
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
### Key Packages
|
||||||
|
|
||||||
|
- `@capacitor-mlkit/barcode-scanning`
|
||||||
|
- `qrcode-stream`
|
||||||
|
- `vue-picture-cropper`
|
||||||
|
- Platform-specific camera APIs
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Test Scenarios
|
||||||
|
|
||||||
|
1. Permission handling
|
||||||
|
2. Camera switching
|
||||||
|
3. Error conditions
|
||||||
|
4. Platform compatibility
|
||||||
|
5. Performance metrics
|
||||||
|
|
||||||
|
### Test Environment
|
||||||
|
|
||||||
|
- Multiple browsers
|
||||||
|
- iOS and Android devices
|
||||||
|
- Desktop platforms
|
||||||
|
- Various network conditions
|
||||||
217
docs/camera-implementation.md
Normal file
217
docs/camera-implementation.md
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
# Camera Implementation Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document describes how camera functionality is implemented across the TimeSafari application. The application uses cameras for two main purposes:
|
||||||
|
|
||||||
|
1. QR Code scanning
|
||||||
|
2. Photo capture
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### QRScannerDialog.vue
|
||||||
|
|
||||||
|
Primary component for QR code scanning in web browsers.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
- Uses `qrcode-stream` for web-based QR scanning
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Provides real-time camera status feedback
|
||||||
|
- Implements error handling with user-friendly messages
|
||||||
|
- Includes camera switching functionality
|
||||||
|
|
||||||
|
**Camera Access Flow:**
|
||||||
|
|
||||||
|
1. Checks for camera API availability
|
||||||
|
2. Enumerates available video devices
|
||||||
|
3. Requests camera permissions
|
||||||
|
4. Initializes camera stream with preferred settings
|
||||||
|
5. Handles various error conditions with specific messages
|
||||||
|
|
||||||
|
### PhotoDialog.vue
|
||||||
|
|
||||||
|
Component for photo capture and selection.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
- Cross-platform photo capture interface
|
||||||
|
- Image cropping capabilities
|
||||||
|
- File selection fallback
|
||||||
|
- Unified interface for different platforms
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
### QRScanner Services
|
||||||
|
|
||||||
|
#### WebDialogQRScanner
|
||||||
|
|
||||||
|
Web-based implementation of QR scanning.
|
||||||
|
|
||||||
|
**Key Methods:**
|
||||||
|
|
||||||
|
- `checkPermissions()`: Verifies camera permission status
|
||||||
|
- `requestPermissions()`: Requests camera access
|
||||||
|
- `isSupported()`: Checks for camera API support
|
||||||
|
- Handles various error conditions with specific messages
|
||||||
|
|
||||||
|
#### CapacitorQRScanner
|
||||||
|
|
||||||
|
Native implementation using Capacitor's MLKit.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
- Uses `@capacitor-mlkit/barcode-scanning`
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Implements permission management
|
||||||
|
- Provides continuous scanning capability
|
||||||
|
|
||||||
|
### Platform Services
|
||||||
|
|
||||||
|
#### WebPlatformService
|
||||||
|
|
||||||
|
Web-specific implementation of platform features.
|
||||||
|
|
||||||
|
**Camera Capabilities:**
|
||||||
|
|
||||||
|
- Uses HTML5 file input with capture attribute
|
||||||
|
- Falls back to file selection if camera unavailable
|
||||||
|
- Processes captured images for consistent format
|
||||||
|
|
||||||
|
#### CapacitorPlatformService
|
||||||
|
|
||||||
|
Native implementation using Capacitor.
|
||||||
|
|
||||||
|
**Camera Features:**
|
||||||
|
|
||||||
|
- Uses `Camera.getPhoto()` for native camera access
|
||||||
|
- Supports image editing
|
||||||
|
- Configures high-quality image capture
|
||||||
|
- Handles base64 image processing
|
||||||
|
|
||||||
|
#### ElectronPlatformService
|
||||||
|
|
||||||
|
Desktop implementation (currently unimplemented).
|
||||||
|
|
||||||
|
**Status:**
|
||||||
|
|
||||||
|
- Camera functionality not yet implemented
|
||||||
|
- Planned to use Electron's media APIs
|
||||||
|
|
||||||
|
## Platform-Specific Considerations
|
||||||
|
|
||||||
|
### iOS
|
||||||
|
|
||||||
|
- Requires `NSCameraUsageDescription` in Info.plist
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Implements proper permission handling
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
- Requires camera permissions in manifest
|
||||||
|
- Supports both front and back cameras
|
||||||
|
- Handles permission requests through Capacitor
|
||||||
|
|
||||||
|
### Web
|
||||||
|
|
||||||
|
- Requires HTTPS for camera access
|
||||||
|
- Implements fallback mechanisms
|
||||||
|
- Handles browser compatibility issues
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Common Error Scenarios
|
||||||
|
|
||||||
|
1. No camera found
|
||||||
|
2. Permission denied
|
||||||
|
3. Camera in use by another application
|
||||||
|
4. HTTPS required
|
||||||
|
5. Browser compatibility issues
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
|
||||||
|
- User-friendly error messages
|
||||||
|
- Troubleshooting tips
|
||||||
|
- Clear instructions for resolution
|
||||||
|
- Platform-specific guidance
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Permission Management
|
||||||
|
|
||||||
|
- Explicit permission requests
|
||||||
|
- Permission state tracking
|
||||||
|
- Graceful handling of denied permissions
|
||||||
|
|
||||||
|
### Data Handling
|
||||||
|
|
||||||
|
- Secure image processing
|
||||||
|
- Proper cleanup of camera resources
|
||||||
|
- No persistent storage of camera data
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Camera Access
|
||||||
|
|
||||||
|
1. Always check for camera availability
|
||||||
|
2. Request permissions explicitly
|
||||||
|
3. Handle all error conditions
|
||||||
|
4. Provide clear user feedback
|
||||||
|
5. Implement proper cleanup
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
1. Optimize camera resolution
|
||||||
|
2. Implement proper resource cleanup
|
||||||
|
3. Handle camera switching efficiently
|
||||||
|
4. Manage memory usage
|
||||||
|
|
||||||
|
### User Experience
|
||||||
|
|
||||||
|
1. Clear status indicators
|
||||||
|
2. Intuitive camera controls
|
||||||
|
3. Helpful error messages
|
||||||
|
4. Smooth camera switching
|
||||||
|
5. Responsive UI feedback
|
||||||
|
|
||||||
|
## Future Improvements
|
||||||
|
|
||||||
|
### Planned Enhancements
|
||||||
|
|
||||||
|
1. Implement Electron camera support
|
||||||
|
2. Add advanced camera features
|
||||||
|
3. Improve error handling
|
||||||
|
4. Enhance user feedback
|
||||||
|
5. Optimize performance
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
|
||||||
|
1. Electron camera implementation pending
|
||||||
|
2. Some browser compatibility limitations
|
||||||
|
3. Platform-specific quirks to address
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
### Key Packages
|
||||||
|
|
||||||
|
- `@capacitor-mlkit/barcode-scanning`
|
||||||
|
- `qrcode-stream`
|
||||||
|
- `vue-picture-cropper`
|
||||||
|
- Platform-specific camera APIs
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Test Scenarios
|
||||||
|
|
||||||
|
1. Permission handling
|
||||||
|
2. Camera switching
|
||||||
|
3. Error conditions
|
||||||
|
4. Platform compatibility
|
||||||
|
5. Performance metrics
|
||||||
|
|
||||||
|
### Test Environment
|
||||||
|
|
||||||
|
- Multiple browsers
|
||||||
|
- iOS and Android devices
|
||||||
|
- Desktop platforms
|
||||||
|
- Various network conditions
|
||||||
4628
package-lock.json
generated
4628
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,14 @@
|
|||||||
|
/** * PhotoDialog.vue - Cross-platform photo capture and selection component * *
|
||||||
|
This component provides a unified interface for taking photos and selecting
|
||||||
|
images * across different platforms (web, mobile) using the PlatformService. It
|
||||||
|
supports: * - Taking photos using device camera * - Selecting images from device
|
||||||
|
gallery * - Image cropping functionality * - Image upload to server * - Error
|
||||||
|
handling and user feedback * * Features: * - Responsive design with mobile-first
|
||||||
|
approach * - Cross-platform compatibility through PlatformService * - Image
|
||||||
|
cropping with aspect ratio control * - Progress feedback during upload * -
|
||||||
|
Comprehensive error handling * * @author Matthew Raymer * @version 1.0.0 * @file
|
||||||
|
PhotoDialog.vue */
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="dialog-overlay z-[60]">
|
<div v-if="visible" class="dialog-overlay z-[60]">
|
||||||
<div class="dialog relative">
|
<div class="dialog relative">
|
||||||
@@ -90,16 +101,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
/**
|
|
||||||
* PhotoDialog.vue - Cross-platform photo capture and selection component
|
|
||||||
*
|
|
||||||
* This component provides a unified interface for taking photos and selecting images
|
|
||||||
* across different platforms using the PlatformService.
|
|
||||||
*
|
|
||||||
* @author Matthew Raymer
|
|
||||||
* @file PhotoDialog.vue
|
|
||||||
*/
|
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import VuePictureCropper, { cropper } from "vue-picture-cropper";
|
import VuePictureCropper, { cropper } from "vue-picture-cropper";
|
||||||
@@ -113,37 +114,69 @@ import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
|
|||||||
export default class PhotoDialog extends Vue {
|
export default class PhotoDialog extends Vue {
|
||||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||||
|
|
||||||
|
/** Active DID for user authentication */
|
||||||
activeDid = "";
|
activeDid = "";
|
||||||
|
|
||||||
|
/** Current image blob being processed */
|
||||||
blob?: Blob;
|
blob?: Blob;
|
||||||
|
|
||||||
|
/** Type of claim for the image */
|
||||||
claimType = "";
|
claimType = "";
|
||||||
|
|
||||||
|
/** Whether to show cropping interface */
|
||||||
crop = false;
|
crop = false;
|
||||||
|
|
||||||
|
/** Name of the selected file */
|
||||||
fileName?: string;
|
fileName?: string;
|
||||||
|
|
||||||
|
/** Callback function to set image URL after upload */
|
||||||
setImageCallback: (arg: string) => void = () => {};
|
setImageCallback: (arg: string) => void = () => {};
|
||||||
|
|
||||||
|
/** Whether to show retry button */
|
||||||
showRetry = true;
|
showRetry = true;
|
||||||
|
|
||||||
|
/** Upload progress state */
|
||||||
uploading = false;
|
uploading = false;
|
||||||
|
|
||||||
|
/** Dialog visibility state */
|
||||||
visible = false;
|
visible = false;
|
||||||
|
|
||||||
private platformService = PlatformServiceFactory.getInstance();
|
private platformService = PlatformServiceFactory.getInstance();
|
||||||
URL = window.URL || window.webkitURL;
|
URL = window.URL || window.webkitURL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lifecycle hook: Initializes component and retrieves user settings
|
||||||
|
* @throws {Error} When settings retrieval fails
|
||||||
|
*/
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
} catch (err: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error("Error retrieving settings from database:", err);
|
logger.error("Error retrieving settings from database:", error);
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
type: "danger",
|
type: "danger",
|
||||||
title: "Error",
|
title: "Error",
|
||||||
text: err.message || "There was an error retrieving your settings.",
|
text:
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "There was an error retrieving your settings.",
|
||||||
},
|
},
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the photo dialog with specified configuration
|
||||||
|
* @param setImageFn - Callback function to handle image URL after upload
|
||||||
|
* @param claimType - Type of claim for the image
|
||||||
|
* @param crop - Whether to enable cropping
|
||||||
|
* @param blob - Optional existing image blob
|
||||||
|
* @param inputFileName - Optional filename for the image
|
||||||
|
*/
|
||||||
open(
|
open(
|
||||||
setImageFn: (arg: string) => void,
|
setImageFn: (arg: string) => void,
|
||||||
claimType: string,
|
claimType: string,
|
||||||
@@ -170,6 +203,9 @@ export default class PhotoDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the photo dialog and resets state
|
||||||
|
*/
|
||||||
close() {
|
close() {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
const bottomNav = document.querySelector("#QuickNav") as HTMLElement;
|
const bottomNav = document.querySelector("#QuickNav") as HTMLElement;
|
||||||
@@ -179,6 +215,10 @@ export default class PhotoDialog extends Vue {
|
|||||||
this.blob = undefined;
|
this.blob = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures a photo using device camera
|
||||||
|
* @throws {Error} When camera access fails
|
||||||
|
*/
|
||||||
async takePhoto() {
|
async takePhoto() {
|
||||||
try {
|
try {
|
||||||
const result = await this.platformService.takePicture();
|
const result = await this.platformService.takePicture();
|
||||||
@@ -198,6 +238,10 @@ export default class PhotoDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects an image from device gallery
|
||||||
|
* @throws {Error} When gallery access fails
|
||||||
|
*/
|
||||||
async pickPhoto() {
|
async pickPhoto() {
|
||||||
try {
|
try {
|
||||||
const result = await this.platformService.pickImage();
|
const result = await this.platformService.pickImage();
|
||||||
@@ -217,14 +261,27 @@ export default class PhotoDialog extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a blob URL for image preview
|
||||||
|
* @param blob - Image blob to create URL for
|
||||||
|
* @returns {string} Blob URL for the image
|
||||||
|
*/
|
||||||
private createBlobURL(blob: Blob): string {
|
private createBlobURL(blob: Blob): string {
|
||||||
return URL.createObjectURL(blob);
|
return URL.createObjectURL(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the current image selection
|
||||||
|
*/
|
||||||
async retryImage() {
|
async retryImage() {
|
||||||
this.blob = undefined;
|
this.blob = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads the current image to the server
|
||||||
|
* Handles cropping if enabled and manages upload state
|
||||||
|
* @throws {Error} When upload fails or server returns error
|
||||||
|
*/
|
||||||
async uploadImage() {
|
async uploadImage() {
|
||||||
this.uploading = true;
|
this.uploading = true;
|
||||||
|
|
||||||
@@ -339,6 +396,7 @@ export default class PhotoDialog extends Vue {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Dialog overlay styling */
|
||||||
.dialog-overlay {
|
.dialog-overlay {
|
||||||
z-index: 60;
|
z-index: 60;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -353,6 +411,7 @@ export default class PhotoDialog extends Vue {
|
|||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dialog container styling */
|
||||||
.dialog {
|
.dialog {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|||||||
@@ -1,26 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<section id="Content" class="relativew-[100vw] h-[100vh]">
|
<section id="Content" class="relativew-[100vw] h-[100vh]">
|
||||||
<div class="absolute inset-x-0 bottom-0 bg-black/50 p-6">
|
<div class="absolute inset-x-0 bottom-0 bg-black/50 p-6">
|
||||||
<p class="text-center text-white mb-3">
|
<p class="text-center text-white mb-3">
|
||||||
Point your camera at a TimeSafari contact QR code to scan it automatically.
|
Point your camera at a TimeSafari contact QR code to scan it
|
||||||
</p>
|
automatically.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p v-if="error" class="text-center text-rose-300 mb-3">{{ error }}</p>
|
<p v-if="error" class="text-center text-rose-300 mb-3">{{ error }}</p>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<button
|
<button
|
||||||
class="text-center text-white leading-none bg-slate-400 p-2 rounded-full"
|
class="text-center text-white leading-none bg-slate-400 p-2 rounded-full"
|
||||||
@click="$router.back()"
|
@click="$router.back()"
|
||||||
>
|
>
|
||||||
<font-awesome icon="xmark" class="w-[1em]"></font-awesome>
|
<font-awesome icon="xmark" class="w-[1em]"></font-awesome>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center"></div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -423,4 +422,4 @@ export default class ContactQRScan extends Vue {
|
|||||||
.aspect-square {
|
.aspect-square {
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user