Skip to content

Commit 45957b4

Browse files
committed
docs(angular): update loading photos page
1 parent b43acd1 commit 45957b4

File tree

1 file changed

+55
-69
lines changed

1 file changed

+55
-69
lines changed
Lines changed: 55 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
---
2+
title: Loading Photos from the Filesystem
23
sidebar_label: Loading Photos
34
---
45

56
# Loading Photos from the Filesystem
67

78
We’ve implemented photo taking and saving to the filesystem. There’s one last piece of functionality missing: the photos are stored in the filesystem, but we need a way to save pointers to each file so that they can be displayed again in the photo gallery.
89

9-
Fortunately, this is easy: we’ll leverage the Capacitor [Preferences API](https://capacitorjs.com/docs/apis/preferences) to store our array of Photos in a key-value store.
10+
Fortunately, this is easy: we’ll leverage the Capacitor [Preferences API](../../native/preferences.md) to store our array of Photos in a key-value store.
1011

1112
## Preferences API
1213

1314
Open `photo.service.ts` and begin by defining a new property in the `PhotoService` class that will act as the key for the store:
1415

15-
```tsx
16+
```ts
1617
export class PhotoService {
1718
public photos: UserPhoto[] = [];
1819

1920
// CHANGE: Add a key for photo storage.
2021
private PHOTO_STORAGE: string = 'photos';
2122

22-
constructor() {}
23-
24-
// other code...
23+
// Same old code from before.
2524
}
2625
```
2726

28-
Next, at the end of the `addNewToGallery` function, add a call to `Preferences.set()` to save the Photos array. By adding it here, the Photos array is stored each time a new photo is taken. This way, it doesn’t matter when the app user closes or switches to a different app - all photo data is saved.
27+
Next, at the end of the `addNewToGallery` method, add a call to `Preferences.set()` to save the `photos` array. By adding it here, the `photos` array is stored each time a new photo is taken. This way, it doesn’t matter when the app user closes or switches to a different app - all photo data is saved.
2928

30-
```tsx
29+
```ts
3130
public async addNewToGallery() {
31+
// Take a photo
3232
const capturedPhoto = await Camera.getPhoto({
3333
resultType: CameraResultType.Uri,
3434
source: CameraSource.Camera,
@@ -47,52 +47,51 @@ public async addNewToGallery() {
4747
}
4848
```
4949

50-
With the photo array data saved, create a new public method in the `PhotoService` class called `loadSaved()` that can retrieve the photo data. We use the same key to retrieve the photos array in JSON format, then parse it into an array:
51-
52-
```tsx
53-
public async addNewToGallery() {
54-
// Same old code from before.
55-
}
50+
With the photo array data saved, create a new public method in the `PhotoService` class called `loadSaved()` that can retrieve the photo data. We use the same key to retrieve the `photos` array in JSON format, then parse it into an array:
5651

57-
// CHANGE: Add the method to load the photo data.
58-
public async loadSaved() {
59-
// Retrieve cached photo array data
60-
const { value } = await Preferences.get({ key: this.PHOTO_STORAGE });
61-
this.photos = (value ? JSON.parse(value) : []) as UserPhoto[];
62-
63-
// more to come...
64-
}
52+
```ts
53+
export class PhotoService {
54+
// Same old code from before.
6555

66-
private async savePicture(photo: Photo) {
67-
// Same old code from before.
56+
// CHANGE: Add the method to load the photo data.
57+
public async loadSaved() {
58+
// Retrieve cached photo array data
59+
const { value } = await Preferences.get({ key: this.PHOTO_STORAGE });
60+
this.photos = (value ? JSON.parse(value) : []) as UserPhoto[];
61+
}
6862
}
6963
```
7064

71-
On mobile (coming up next!), we can directly set the source of an image tag - `<img src="x" />` - to each photo file on the Filesystem, displaying them automatically. On the web, however, we must read each image from the Filesystem into base64 format, using a new `base64` property on the `Photo` object. This is because the Filesystem API uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) under the hood. Add the following code to complete the `loadSaved()` function:
65+
On mobile (coming up next!), we can directly set the source of an image tag - `<img src="x" />` - to each photo file on the `Filesystem`, displaying them automatically. On the web, however, we must read each image from the `Filesystem` into base64 format, using a new `base64` property on the `Photo` object. This is because the `Filesystem` API uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) under the hood. Add the following code to complete the `loadSaved()` method:
7266

73-
```tsx
74-
public async loadSaved() {
75-
// Retrieve cached photo array data
76-
const { value } = await Preferences.get({ key: this.PHOTO_STORAGE });
77-
this.photos = (value ? JSON.parse(value) : []) as UserPhoto[];
67+
```ts
68+
export class PhotoService {
69+
// Same old code from before.
7870

79-
// CHANGE: Display the photo by reading into base64 format.
80-
for (let photo of this.photos) {
81-
// Read each saved photo's data from the Filesystem
82-
const readFile = await Filesystem.readFile({
83-
path: photo.filepath,
84-
directory: Directory.Data,
85-
});
71+
// CHANGE: Update the `loadSaved` method.
72+
public async loadSaved() {
73+
// Retrieve cached photo array data
74+
const { value } = await Preferences.get({ key: this.PHOTO_STORAGE });
75+
this.photos = (value ? JSON.parse(value) : []) as UserPhoto[];
76+
77+
// CHANGE: Display the photo by reading into base64 format.
78+
for (let photo of this.photos) {
79+
// Read each saved photo's data from the Filesystem
80+
const readFile = await Filesystem.readFile({
81+
path: photo.filepath,
82+
directory: Directory.Data,
83+
});
8684

87-
// Web platform only: Load the photo as base64 data
88-
photo.webviewPath = `data:image/jpeg;base64,${readFile.data}`;
85+
// Web platform only: Load the photo as base64 data
86+
photo.webviewPath = `data:image/jpeg;base64,${readFile.data}`;
87+
}
8988
}
9089
}
9190
```
9291

93-
After these updates to the `PhotoService` class, your `photos.service.ts` file should look like this:
92+
`photo.service.ts` should now look like this:
9493

95-
```tsx
94+
```ts
9695
import { Injectable } from '@angular/core';
9796
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
9897
import { Filesystem, Directory } from '@capacitor/filesystem';
@@ -103,48 +102,27 @@ import { Preferences } from '@capacitor/preferences';
103102
})
104103
export class PhotoService {
105104
public photos: UserPhoto[] = [];
106-
private PHOTO_STORAGE = 'photos';
107105

108-
constructor() {}
106+
private PHOTO_STORAGE: string = 'photos';
109107

110108
public async addNewToGallery() {
111109
// Take a photo
112110
const capturedPhoto = await Camera.getPhoto({
113-
resultType: CameraResultType.Uri, // file-based data; provides best performance
114-
source: CameraSource.Camera, // automatically take a new photo with the camera
115-
quality: 100, // highest quality (0 to 100)
111+
resultType: CameraResultType.Uri,
112+
source: CameraSource.Camera,
113+
quality: 100,
116114
});
117115

118116
const savedImageFile = await this.savePicture(capturedPhoto);
119117

120-
// Add new photo to Photos array
121118
this.photos.unshift(savedImageFile);
122119

123-
// Cache all photo data for future retrieval
124120
Preferences.set({
125121
key: this.PHOTO_STORAGE,
126122
value: JSON.stringify(this.photos),
127123
});
128124
}
129125

130-
public async loadSaved() {
131-
// Retrieve cached photo array data
132-
const { value } = await Preferences.get({ key: this.PHOTO_STORAGE });
133-
this.photos = (value ? JSON.parse(value) : []) as UserPhoto[];
134-
135-
// Display the photo by reading into base64 format
136-
for (let photo of this.photos) {
137-
// Read each saved photo's data from the Filesystem
138-
const readFile = await Filesystem.readFile({
139-
path: photo.filepath,
140-
directory: Directory.Data,
141-
});
142-
143-
// Web platform only: Load the photo as base64 data
144-
photo.webviewPath = `data:image/jpeg;base64,${readFile.data}`;
145-
}
146-
}
147-
148126
private async savePicture(photo: Photo) {
149127
// Convert photo to base64 format, required by Filesystem API to save
150128
const base64Data = await this.readAsBase64(photo);
@@ -173,15 +151,22 @@ export class PhotoService {
173151
return (await this.convertBlobToBase64(blob)) as string;
174152
}
175153

176-
private convertBlobToBase64 = (blob: Blob) =>
177-
new Promise((resolve, reject) => {
154+
private convertBlobToBase64(blob: Blob) {
155+
return new Promise((resolve, reject) => {
178156
const reader = new FileReader();
179157
reader.onerror = reject;
180158
reader.onload = () => {
181159
resolve(reader.result);
182160
};
183161
reader.readAsDataURL(blob);
184162
});
163+
}
164+
165+
public async loadSaved() {
166+
// Retrieve cached photo array data
167+
const { value } = await Preferences.get({ key: this.PHOTO_STORAGE });
168+
this.photos = (value ? JSON.parse(value) : []) as UserPhoto[];
169+
}
185170
}
186171

187172
export interface UserPhoto {
@@ -190,11 +175,11 @@ export interface UserPhoto {
190175
}
191176
```
192177

193-
Our `PhotoService` can now load the saved images, but we'll need to update `tab2.page.ts` to put that new code to work. We'll call `loadSaved` within the [ngOnInit](https://angular.dev/guide/components/lifecycle#ngoninit) lifecycle method so that when the user first navigates to Tab 2 (the Photo Gallery), all photos are loaded and displayed on the screen.
178+
Our `PhotoService` can now load the saved images, but we'll need to update `tab2.page.ts` to put that new code to work. We'll call `loadSaved` within the [ngOnInit](https://angular.dev/guide/components/lifecycle#ngoninit) lifecycle method so that when the user first navigates to the Photo Gallery, all photos are loaded and displayed on the screen.
194179

195180
Update `tab2.page.ts` to look like the following:
196181

197-
```tsx
182+
```ts
198183
import { Component } from '@angular/core';
199184
import { PhotoService } from '../services/photo.service';
200185

@@ -223,4 +208,5 @@ If you're seeing broken image links or missing photos after following these step
223208

224209
In localStorage, look for domain `http://localhost:8100` and key `CapacitorStorage.photos`. In IndexedDB, find a store called "FileStorage". Your photos will have a key like `/DATA/123456789012.jpeg`.
225210
:::
211+
226212
That’s it! We’ve built a complete Photo Gallery feature in our Ionic app that works on the web. Next up, we’ll transform it into a mobile app for iOS and Android!

0 commit comments

Comments
 (0)