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