Skip to content

Commit 3635891

Browse files
docs(vue): add context to code blocks and small changes to surrounding text
1 parent 6a21dbf commit 3635891

File tree

1 file changed

+131
-4
lines changed

1 file changed

+131
-4
lines changed

docs/vue/your-first-app/5-adding-mobile.md

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,24 @@ Let’s start with making some small code changes - then our app will "just work
66

77
## Platform-specific Logic
88

9-
First, we’ll update the photo saving functionality to support mobile. We'll run slightly different code depending on the platform - mobile or web. Import the `Platform` API from Ionic Vue and `Capacitor` from Capacitor's `core` package:
9+
First, we’ll update the photo saving functionality to support mobile. We'll run slightly different code depending on the platform - mobile or web. At the top of `usePhotoGallery.ts`, import `isPlatform` from Ionic Vue and `Capacitor` from Capacitor's `core` package:
1010

1111
```tsx
12+
import { ref, onMounted, watch } from 'vue';
13+
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
14+
import { Filesystem, Directory } from '@capacitor/filesystem';
15+
import { Preferences } from '@capacitor/preferences';
16+
// CHANGE: Add imports from `@ionic/vue` and `@capcitor/core`.
1217
import { isPlatform } from '@ionic/vue';
1318
import { Capacitor } from '@capacitor/core';
19+
20+
// Same old code from before.
1421
```
1522

16-
In the `savePicture` function, check which platform the app is running on. If it’s "hybrid" (Capacitor, the native runtime), then read the photo file into base64 format using the `readFile` method. Also, return the complete file path to the photo using the Filesystem API. When setting the `webviewPath`, use the special `Capacitor.convertFileSrc` method ([details here](https://capacitorjs.com/docs/basics/utilities#convertfilesrc)). Otherwise, use the same logic as before when running the app on the web.
23+
Next, update the `usePhotoGallery` function's `savePicture` method to check which platform the app is running on. If it’s "hybrid" (Capacitor, the native runtime), then read the photo file into base64 format using the `readFile` method. Also, return the complete file path to the photo using the Filesystem API. When setting the `webviewPath`, use the special `Capacitor.convertFileSrc` method ([details here](https://capacitorjs.com/docs/basics/utilities#convertfilesrc)). Otherwise, use the same logic as before when running the app on the web.
1724

1825
```tsx
26+
// CHANGE: Update the `savePicture` method to include branches for web and native.
1927
const savePicture = async (photo: Photo, fileName: string): Promise<UserPhoto> => {
2028
let base64Data: string | Blob;
2129
// "hybrid" will detect mobile - iOS or Android
@@ -30,6 +38,7 @@ const savePicture = async (photo: Photo, fileName: string): Promise<UserPhoto> =
3038
const blob = await response.blob();
3139
base64Data = (await convertBlobToBase64(blob)) as string;
3240
}
41+
3342
const savedFile = await Filesystem.writeFile({
3443
path: fileName,
3544
data: base64Data,
@@ -54,9 +63,10 @@ const savePicture = async (photo: Photo, fileName: string): Promise<UserPhoto> =
5463
};
5564
```
5665

57-
Next, add a new bit of logic in the `loadSaved` function. On mobile, we can directly point to each photo file on the Filesystem and display them automatically. On the web, however, we must read each image from the Filesystem into base64 format. This is because the Filesystem API uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) under the hood. Update the `loadSaved` function:
66+
Next, add a new bit of logic in the `loadSaved` method. On mobile, we can directly point to each photo file on the Filesystem and display them automatically. On the web, however, we must read each image from the Filesystem into base64 format. This is because the Filesystem API uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) under the hood. Update the `loadSaved` function:
5867

5968
```tsx
69+
// CHANGE: Update the `loadSaved` method to convert to base64 on web platform only.
6070
const loadSaved = async () => {
6171
const photoList = await Preferences.get({ key: PHOTO_STORAGE });
6272
const photosInPreferences = photoList.value ? JSON.parse(photoList.value) : [];
@@ -77,4 +87,121 @@ const loadSaved = async () => {
7787
};
7888
```
7989

80-
Our Photo Gallery now consists of one codebase that runs on the web, Android, and iOS. Next up, the part you’ve been waiting for - deploying the app to a device.
90+
Our Photo Gallery now consists of one codebase that runs on the web, Android, and iOS.
91+
92+
`usePhotoGallery.ts` should now look like this:
93+
94+
```tsx
95+
import { ref, onMounted, watch } from 'vue';
96+
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
97+
import { Filesystem, Directory } from '@capacitor/filesystem';
98+
import { Preferences } from '@capacitor/preferences';
99+
import { isPlatform } from '@ionic/vue';
100+
import { Capacitor } from '@capacitor/core';
101+
102+
export const usePhotoGallery = () => {
103+
const PHOTO_STORAGE = 'photos';
104+
const photos = ref<UserPhoto[]>([]);
105+
106+
const takePhoto = async () => {
107+
const photo = await Camera.getPhoto({
108+
resultType: CameraResultType.Uri,
109+
source: CameraSource.Camera,
110+
quality: 100,
111+
});
112+
const fileName = Date.now() + '.jpeg';
113+
const savedFileImage = await savePicture(photo, fileName);
114+
115+
photos.value = [savedFileImage, ...photos.value];
116+
};
117+
118+
const convertBlobToBase64 = (blob: Blob) =>
119+
new Promise((resolve, reject) => {
120+
const reader = new FileReader();
121+
reader.onerror = reject;
122+
reader.onload = () => {
123+
resolve(reader.result);
124+
};
125+
reader.readAsDataURL(blob);
126+
});
127+
128+
const cachePhotos = () => {
129+
Preferences.set({
130+
key: PHOTO_STORAGE,
131+
value: JSON.stringify(photos.value),
132+
});
133+
};
134+
135+
const savePicture = async (photo: Photo, fileName: string): Promise<UserPhoto> => {
136+
let base64Data: string | Blob;
137+
// "hybrid" will detect mobile - iOS or Android
138+
if (isPlatform('hybrid')) {
139+
const file = await Filesystem.readFile({
140+
path: photo.path!,
141+
});
142+
base64Data = file.data;
143+
} else {
144+
// Fetch the photo, read as a blob, then convert to base64 format
145+
const response = await fetch(photo.webPath!);
146+
const blob = await response.blob();
147+
base64Data = (await convertBlobToBase64(blob)) as string;
148+
}
149+
150+
const savedFile = await Filesystem.writeFile({
151+
path: fileName,
152+
data: base64Data,
153+
directory: Directory.Data,
154+
});
155+
156+
if (isPlatform('hybrid')) {
157+
// Display the new image by rewriting the 'file://' path to HTTP
158+
// Details: https://ionicframework.com/docs/building/webview#file-protocol
159+
return {
160+
filepath: savedFile.uri,
161+
webviewPath: Capacitor.convertFileSrc(savedFile.uri),
162+
};
163+
} else {
164+
// Use webPath to display the new image instead of base64 since it's
165+
// already loaded into memory
166+
return {
167+
filepath: fileName,
168+
webviewPath: photo.webPath,
169+
};
170+
}
171+
};
172+
173+
const loadSaved = async () => {
174+
const photoList = await Preferences.get({ key: PHOTO_STORAGE });
175+
const photosInPreferences = photoList.value ? JSON.parse(photoList.value) : [];
176+
177+
// If running on the web...
178+
if (!isPlatform('hybrid')) {
179+
for (const photo of photosInPreferences) {
180+
const file = await Filesystem.readFile({
181+
path: photo.filepath,
182+
directory: Directory.Data,
183+
});
184+
// Web platform only: Load the photo as base64 data
185+
photo.webviewPath = `data:image/jpeg;base64,${file.data}`;
186+
}
187+
}
188+
189+
photos.value = photosInPreferences;
190+
};
191+
192+
onMounted(loadSaved);
193+
watch(photos, cachePhotos);
194+
195+
return {
196+
photos,
197+
takePhoto
198+
};
199+
};
200+
201+
export interface UserPhoto {
202+
filepath: string;
203+
webviewPath?: string;
204+
}
205+
```
206+
207+
Next up, the part you’ve been waiting for - deploying the app to a device.

0 commit comments

Comments
 (0)