· 4 years ago · Apr 27, 2021, 06:58 AM
1import { Injectable } from '@angular/core';
2import { Platform } from '@ionic/angular';
3import {
4 Plugins, CameraResultType, Capacitor, FilesystemDirectory,
5 CameraPhoto, CameraSource
6} from '@capacitor/core';
7
8@Injectable({
9 providedIn: 'root'
10})
11
12const { Camera, Filesystem, Storage } = Plugins;
13
14export class PhotoService {
15 public photos: Photo[] = [];
16 private PHOTO_STORAGE: string = "photos";
17 private platform: Platform;
18
19 constructor(platform: Platform) {
20 this.platform = platform;
21 }
22
23 public async addNewToGallery() {
24 // Take a photo
25 const capturedPhoto = await Camera.getPhoto({
26 resultType: CameraResultType.Uri,
27 source: CameraSource.Camera,
28 quality: 100
29 });
30
31 const savedImageFile = await this.savePicture(capturedPhoto);
32 this.photos.unshift(savedImageFile);
33
34 Storage.set({
35 key: this.PHOTO_STORAGE,
36 value: JSON.stringify(this.photos)
37 });
38 }
39
40 public async loadSaved() {
41 // Retrieve cached photo array data
42 const photoList = await Storage.get({ key: this.PHOTO_STORAGE });
43 this.photos = JSON.parse(photoList.value) || [];
44
45 // Easiest way to detect when running on the web:
46 // “when the platform is NOT hybrid, do this”
47 if (!this.platform.is('hybrid')) {
48 // Display the photo by reading into base64 format
49 for (let photo of this.photos) {
50 // Read each saved photo's data from the Filesystem
51 const readFile = await Filesystem.readFile({
52 path: photo.filepath,
53 directory: FilesystemDirectory.Data
54 });
55
56 // Web platform only: Load the photo as base64 data
57 photo.webviewPath = `data:image/jpeg;base64,${readFile.data}`;
58 }
59 }
60 }
61
62 // Save picture to file on device
63 private async savePicture(cameraPhoto: CameraPhoto) {
64 // Convert photo to base64 format, required by Filesystem API to save
65 const base64Data = await this.readAsBase64(cameraPhoto);
66
67 // Write the file to the data directory
68 const fileName = new Date().getTime() + '.jpeg';
69 const savedFile = await Filesystem.writeFile({
70 path: fileName,
71 data: base64Data,
72 directory: FilesystemDirectory.Data
73 });
74
75 if (this.platform.is('hybrid')) {
76 // Display the new image by rewriting the 'file://' path to HTTP
77 // Details: https://ionicframework.com/docs/building/webview#file-protocol
78 return {
79 filepath: savedFile.uri,
80 webviewPath: Capacitor.convertFileSrc(savedFile.uri),
81 };
82 }
83 else {
84 // Use webPath to display the new image instead of base64 since it's
85 // already loaded into memory
86 return {
87 filepath: fileName,
88 webviewPath: cameraPhoto.webPath
89 };
90 }
91 }
92
93 private async readAsBase64(cameraPhoto: CameraPhoto) {
94 // "hybrid" will detect Cordova or Capacitor
95 if (this.platform.is('hybrid')) {
96 // Read the file into base64 format
97 const file = await Filesystem.readFile({
98 path: cameraPhoto.path
99 });
100
101 return file.data;
102 }
103 else {
104 // Fetch the photo, read as a blob, then convert to base64 format
105 const response = await fetch(cameraPhoto.webPath);
106 const blob = await response.blob();
107
108 return await this.convertBlobToBase64(blob) as string;
109 }
110 }
111
112 convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => {
113 const reader = new FileReader;
114 reader.onerror = reject;
115 reader.onload = () => {
116 resolve(reader.result);
117 };
118 reader.readAsDataURL(blob);
119 });
120}
121
122export interface Photo {
123 filepath: string;
124 webviewPath: string;
125}