Skip to content

Commit c200d6f

Browse files
committed
finish cross plat support
1 parent fe884a3 commit c200d6f

3 files changed

Lines changed: 98 additions & 24 deletions

File tree

src/app/app.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Component } from '@angular/core';
22

33
import { Platform } from '@ionic/angular';
4-
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
54
import { StatusBar } from '@ionic-native/status-bar/ngx';
5+
import { Plugins } from '@capacitor/core';
6+
const { SplashScreen } = Plugins;
67

78
@Component({
89
selector: 'app-root',
@@ -12,7 +13,6 @@ import { StatusBar } from '@ionic-native/status-bar/ngx';
1213
export class AppComponent {
1314
constructor(
1415
private platform: Platform,
15-
private splashScreen: SplashScreen,
1616
private statusBar: StatusBar
1717
) {
1818
this.initializeApp();
@@ -21,7 +21,8 @@ export class AppComponent {
2121
initializeApp() {
2222
this.platform.ready().then(() => {
2323
this.statusBar.styleDefault();
24-
this.splashScreen.hide();
24+
25+
SplashScreen.hide();
2526
});
2627
}
2728
}

src/app/services/photo.service.ts

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Injectable } from '@angular/core';
22
import { Plugins, CameraResultType, Capacitor, FilesystemDirectory, CameraPhoto, CameraSource } from '@capacitor/core';
3+
import { Platform } from '@ionic/angular';
34

45
const { Camera, Filesystem, Storage } = Plugins;
56

@@ -9,13 +10,30 @@ const { Camera, Filesystem, Storage } = Plugins;
910
export class PhotoService {
1011
public photos: Photo[] = [];
1112
private PHOTO_STORAGE: string = "photos";
13+
private platform: Platform;
1214

13-
constructor() { }
15+
constructor(platform: Platform) {
16+
this.platform = platform;
17+
}
1418

1519
async loadSaved() {
1620
// Retrieve cached photo array data
1721
const photos = await Storage.get({ key: this.PHOTO_STORAGE });
1822
this.photos = JSON.parse(photos.value) || [];
23+
24+
if (this.platform.is('pwa')) {
25+
// Display the photo by reading into base64 format
26+
for (let photo of this.photos) {
27+
// Read each saved photo's data from the Filesystem
28+
const readFile = await Filesystem.readFile({
29+
path: photo.filepath,
30+
directory: FilesystemDirectory.Data
31+
});
32+
33+
// Web platform only: Save the photo into the base64 field
34+
photo.base64 = `data:image/jpeg;base64,${readFile.data}`;
35+
}
36+
}
1937
}
2038

2139
/* Use the device camera to take a photo:
@@ -27,7 +45,7 @@ export class PhotoService {
2745
// Store a reference to all photo filepaths using Storage API:
2846
// https://capacitor.ionicframework.com/docs/apis/storage
2947
*/
30-
public async takePhoto() {
48+
public async addNewToGallery() {
3149
// Take a photo
3250
const capturedPhoto = await Camera.getPhoto({
3351
resultType: CameraResultType.Uri, // file-based data; provides best performance
@@ -38,40 +56,85 @@ export class PhotoService {
3856
const savedImageFile = await this.savePicture(capturedPhoto);
3957

4058
// Add new photo to Photos array
41-
this.photos.unshift({
42-
filepath: savedImageFile,
43-
webviewPath: Capacitor.convertFileSrc(savedImageFile)
44-
});
59+
this.photos.unshift(savedImageFile);
4560

4661
// Cache all photo data for future retrieval
4762
Storage.set({
4863
key: this.PHOTO_STORAGE,
49-
value: JSON.stringify(this.photos)
64+
value: this.platform.is('hybrid')
65+
? JSON.stringify(this.photos)
66+
: JSON.stringify(this.photos.map(p => {
67+
// Don't save the base64 representation of the photo data,
68+
// since it's already saved on the Filesystem
69+
const photoCopy = { ...p };
70+
delete photoCopy.base64;
71+
72+
return photoCopy;
73+
}))
5074
});
5175
}
5276

5377
// Save picture to file on device
5478
private async savePicture(cameraPhoto: CameraPhoto) {
55-
// Read the file into its base64 version
56-
const readFile = await Filesystem.readFile({
57-
path: cameraPhoto.path
58-
});
79+
// Convert photo to base64 format, required by Filesystem API to save
80+
const base64Data = await this.readAsBase64(cameraPhoto);
5981

60-
// Write the file to the data directory (instead of temp storage)
82+
// Write the file to the data directory
6183
const fileName = new Date().getTime() + '.jpeg';
6284
await Filesystem.writeFile({
6385
path: fileName,
64-
data: readFile.data,
86+
data: base64Data,
6587
directory: FilesystemDirectory.Data
6688
});
6789

68-
// Get the new, complete filepath
69-
const fileUri = await Filesystem.getUri({
70-
directory: FilesystemDirectory.Data,
71-
path: fileName
72-
});
90+
// Get platform-specific photo filepaths
91+
return await this.getPhotoFile(cameraPhoto, fileName);
92+
}
7393

74-
return fileUri.uri;
94+
// Read camera photo into base64 format based on the platform the app is running on
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+
// Retrieve the photo metadata based on the platform the app is running on
115+
private async getPhotoFile(cameraPhoto, fileName) {
116+
if (this.platform.is('hybrid')) {
117+
// Get the new, complete filepath of the photo saved on filesystem
118+
const fileUri = await Filesystem.getUri({
119+
directory: FilesystemDirectory.Data,
120+
path: fileName
121+
});
122+
123+
// Display the new image by rewriting the 'file://' path to HTTP
124+
// Details: https://ionicframework.com/docs/building/webview#file-protocol
125+
return {
126+
filepath: fileUri.uri,
127+
webviewPath: Capacitor.convertFileSrc(fileUri.uri),
128+
};
129+
}
130+
else {
131+
// Use webPath to display the new image instead of base64 since it's
132+
// already loaded into memory
133+
return {
134+
filepath: fileName,
135+
webviewPath: cameraPhoto.webPath
136+
};
137+
}
75138
}
76139

77140
// Delete picture by removing it from reference data and the filesystem
@@ -92,9 +155,19 @@ export class PhotoService {
92155
directory: FilesystemDirectory.Data
93156
});
94157
}
158+
159+
convertBlobToBase64 = blob => new Promise((resolve, reject) => {
160+
const reader = new FileReader;
161+
reader.onerror = reject;
162+
reader.onload = () => {
163+
resolve(reader.result);
164+
};
165+
reader.readAsDataURL(blob);
166+
});
95167
}
96168

97169
class Photo {
98170
filepath: string;
99171
webviewPath: string;
172+
base64?: string;
100173
}

src/app/tab2/tab2.page.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
<ion-grid>
1111
<ion-row>
1212
<ion-col size="6" *ngFor="let photo of photoService.photos; index as position">
13-
<ion-img src="{{ photo.webviewPath }}" (click)="showActionSheet(photo, position)"></ion-img>
13+
<ion-img src="{{ photo.base64 ? photo.base64 : photo.webviewPath }}" (click)="showActionSheet(photo, position)"></ion-img>
1414
</ion-col>
1515
</ion-row>
1616
</ion-grid>
1717

1818
<ion-fab vertical="bottom" horizontal="center" slot="fixed">
19-
<ion-fab-button (click)="photoService.takePhoto()">
19+
<ion-fab-button (click)="photoService.addNewToGallery()">
2020
<ion-icon name="camera"></ion-icon>
2121
</ion-fab-button>
2222
</ion-fab>

0 commit comments

Comments
 (0)