Skip to content

Commit dc25751

Browse files
committed
docs: add more advanced playground example
1 parent d8b3f68 commit dc25751

11 files changed

Lines changed: 361 additions & 55 deletions

File tree

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
- PWA support with [`nuxt-pwa-module`](https://github.com/kevinmarrec/nuxt-pwa-module)
2222
- Works out-of-the-box with [Capacitor](https://capacitorjs.com/) to build mobile apps
2323

24+
**In progress**
25+
26+
-[ ] PWA Elements
27+
2428
## Quick setup
2529

2630
1. Add `nuxt-ionic` dependency to your project
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script setup lang="ts">
2+
defineProps({ name: String })
3+
</script>
4+
5+
<template>
6+
<divid="container">
7+
<strong>{{ name }}</strong>
8+
<p>Explore <atarget="_blank"rel="noopener noreferrer"href="https://ionicframework.com/docs/components">UI Components</a></p>
9+
</div>
10+
</template>
11+
12+
<style scoped>
13+
#container {
14+
text-align: center;
15+
position: absolute;
16+
left: 0;
17+
right: 0;
18+
top: 50%;
19+
transform: translateY(-50%);
20+
}
21+
22+
#containerstrong {
23+
font-size: 20px;
24+
line-height: 26px;
25+
}
26+
27+
#containerp {
28+
font-size: 16px;
29+
line-height: 22px;
30+
color: #8c8c8c;
31+
margin: 0;
32+
}
33+
34+
#containera {
35+
text-decoration: none;
36+
}
37+
</style>
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import{Capacitor}from'@capacitor/core'
2+
import{
3+
Camera,
4+
CameraSource,
5+
CameraResultType,
6+
Photo,
7+
}from'@capacitor/camera'
8+
import{Filesystem,Directory}from'@capacitor/filesystem'
9+
import{Storage}from'@capacitor/storage'
10+
11+
exportfunctionusePhotoGallery(){
12+
constphotos=ref<UserPhoto[]>([])
13+
constPHOTO_STORAGE='photos'
14+
15+
constloadSaved=async()=>{
16+
constphotoList=awaitStorage.get({key: PHOTO_STORAGE})
17+
constphotosInStorage=photoList.value ? JSON.parse(photoList.value) : []
18+
19+
// If running on the web...
20+
if(!isPlatform('hybrid')){
21+
for(constphotoofphotosInStorage){
22+
constfile=awaitFilesystem.readFile({
23+
path: photo.filepath,
24+
directory: Directory.Data,
25+
})
26+
// Web platform only: Load the photo as base64 data
27+
photo.webviewPath=`data:image/jpeg;base64,${file.data}`
28+
}
29+
}
30+
31+
photos.value=photosInStorage
32+
}
33+
34+
constconvertBlobToBase64=(blob: Blob)=>
35+
newPromise((resolve,reject)=>{
36+
constreader=newFileReader()
37+
reader.onerror=reject
38+
reader.onload=()=>{
39+
resolve(reader.result)
40+
}
41+
reader.readAsDataURL(blob)
42+
})
43+
44+
constsavePicture=async(
45+
photo: Photo,
46+
fileName: string
47+
): Promise<UserPhoto>=>{
48+
letbase64Data: string
49+
// "hybrid" will detect Cordova or Capacitor;
50+
if(isPlatform('hybrid')){
51+
constfile=awaitFilesystem.readFile({
52+
// eslint-disable-next-line
53+
path: photo.path!,
54+
})
55+
base64Data=file.data
56+
}else{
57+
// Fetch the photo, read as a blob, then convert to base64 format
58+
// eslint-disable-next-line
59+
constresponse=awaitfetch(photo.webPath!)
60+
constblob=awaitresponse.blob()
61+
base64Data=(awaitconvertBlobToBase64(blob))asstring
62+
}
63+
constsavedFile=awaitFilesystem.writeFile({
64+
path: fileName,
65+
data: base64Data,
66+
directory: Directory.Data,
67+
})
68+
69+
if(isPlatform('hybrid')){
70+
// Display the new image by rewriting the 'file://' path to HTTP
71+
// Details: https://ionicframework.com/docs/building/webview#file-protocol
72+
return{
73+
filepath: savedFile.uri,
74+
webviewPath: Capacitor.convertFileSrc(savedFile.uri),
75+
}
76+
}else{
77+
// Use webPath to display the new image instead of base64 since it's
78+
// already loaded into memory
79+
return{
80+
filepath: fileName,
81+
webviewPath: photo.webPath,
82+
}
83+
}
84+
}
85+
86+
consttakePhoto=async()=>{
87+
constphoto=awaitCamera.getPhoto({
88+
resultType: CameraResultType.Uri,
89+
source: CameraSource.Camera,
90+
quality: 100,
91+
})
92+
constfileName=newDate().getTime()+'.jpeg'
93+
constsavedFileImage=awaitsavePicture(photo,fileName)
94+
95+
photos.value=[savedFileImage, ...photos.value]
96+
}
97+
98+
constdeletePhoto=async(photo: UserPhoto)=>{
99+
// Remove this photo from the Photos reference data array
100+
photos.value=photos.value.filter(p=>p.filepath!==photo.filepath)
101+
102+
// delete photo file from filesystem
103+
constfilename=photo.filepath.substr(photo.filepath.lastIndexOf('/')+1)
104+
awaitFilesystem.deleteFile({
105+
path: filename,
106+
directory: Directory.Data,
107+
})
108+
}
109+
110+
constcachePhotos=()=>{
111+
Storage.set({
112+
key: PHOTO_STORAGE,
113+
value: JSON.stringify(photos.value),
114+
})
115+
}
116+
117+
onMounted(loadSaved)
118+
119+
watch(photos,cachePhotos)
120+
121+
return{
122+
photos,
123+
takePhoto,
124+
deletePhoto,
125+
}
126+
}
127+
128+
exportinterfaceUserPhoto{
129+
filepath: string
130+
webviewPath?: string
131+
}

‎playground/package.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"@capacitor/ios": "^3.6.0",
1717
"@capacitor/keyboard": "1.2.3",
1818
"@capacitor/status-bar": "1.0.8",
19+
"@capacitor/camera": "^1.0.0",
20+
"@capacitor/filesystem": "^1.0.0",
21+
"@capacitor/storage": "^1.0.0",
1922
"nuxt": "^3.0.0-rc.4",
2023
"nuxt-ionic": "latest"
2124
},

‎playground/pages/index.vue‎

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,6 @@
1-
<template>
2-
<ion-page>
3-
<ion-headertranslucent>
4-
<ion-toolbarclass="toolbar">
5-
<ion-thumbnailslot="start">
6-
<ion-imgsrc="/icon.png" />
7-
</ion-thumbnail>
8-
<ion-title> Nuxt Ionic </ion-title>
9-
</ion-toolbar>
10-
</ion-header>
11-
12-
<ion-content:fullscreen="true">
13-
<ion-headercollapse="condense">
14-
<ion-toolbar>
15-
<ion-titlesize="large"> Blank </ion-title>
16-
</ion-toolbar>
17-
</ion-header>
18-
19-
<ion-list>
20-
<ion-item>
21-
<ion-checkboxslot="start" />
22-
<ion-label>
23-
<h1>Create Idea</h1>
24-
<ion-note>Run Idea By Brandy</ion-note>
25-
</ion-label>
26-
<ion-badgeslot="end"color="success"> 5 Days </ion-badge>
27-
</ion-item>
28-
</ion-list>
29-
30-
<ion-fabvertical="bottom"horizontal="end"slot="fixed">
31-
<ion-fab-buttonrouter-link="/new">
32-
<ion-icon:icon="add"></ion-icon>
33-
</ion-fab-button>
34-
</ion-fab>
35-
</ion-content>
36-
</ion-page>
37-
</template>
38-
391
<script setup>
40-
import { add } from'ionicons/icons'
41-
useHead({
42-
title:'Nuxt Ionic',
43-
})
2+
constrouter=useIonRouter()
3+
awaitrouter.push('/tabs/tab1')
444
</script>
5+
6+
<template><ion-page /></template>

‎playground/pages/new.vue‎

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎playground/pages/tabs.vue‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import { images, square, triangle } from'ionicons/icons'
3+
useHead({
4+
title: 'Nuxt Ionic',
5+
})
6+
</script>
7+
8+
<template>
9+
<ion-page>
10+
<ion-content>
11+
<ion-tabs>
12+
<ion-router-outlet />
13+
<ion-tab-barslot="bottom">
14+
<ion-tab-buttontab="tab1"href="/tabs/tab1">
15+
<ion-icon:icon="triangle" />
16+
<ion-label>Tab 1</ion-label>
17+
</ion-tab-button>
18+
19+
<ion-tab-buttontab="tab2"href="/tabs/tab2">
20+
<ion-icon:icon="images" />
21+
<ion-label>Photos</ion-label>
22+
</ion-tab-button>
23+
24+
<ion-tab-buttontab="tab3"href="/tabs/tab3">
25+
<ion-icon:icon="square" />
26+
<ion-label>Tab 3</ion-label>
27+
</ion-tab-button>
28+
</ion-tab-bar>
29+
</ion-tabs>
30+
</ion-content>
31+
</ion-page>
32+
</template>

‎playground/pages/tabs/tab1.vue‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script setup lang="ts">
2+
import { add } from'ionicons/icons'
3+
4+
definePageMeta({
5+
alias: ['/', '/tabs'],
6+
})
7+
</script>
8+
9+
<template>
10+
<ion-page>
11+
<ion-headertranslucent>
12+
<ion-toolbarclass="toolbar">
13+
<ion-thumbnailslot="start">
14+
<ion-imgsrc="/icon.png" />
15+
</ion-thumbnail>
16+
<ion-title> Nuxt Ionic </ion-title>
17+
</ion-toolbar>
18+
</ion-header>
19+
<ion-content:fullscreen="true">
20+
<ion-headercollapse="condense">
21+
<ion-toolbar>
22+
<ion-titlesize="large">Tab 1</ion-title>
23+
</ion-toolbar>
24+
</ion-header>
25+
26+
<ion-list>
27+
<ion-item>
28+
<ion-checkboxslot="start" />
29+
<ion-label>
30+
<h1>Create Idea</h1>
31+
<ion-note>Run Idea By Brandy</ion-note>
32+
</ion-label>
33+
<ion-badgeslot="end"color="success"> 5 Days </ion-badge>
34+
</ion-item>
35+
</ion-list>
36+
</ion-content>
37+
</ion-page>
38+
</template>

‎playground/pages/tabs/tab2.vue‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script setup lang="ts">
2+
import { actionSheetController } from'@ionic/vue'
3+
import { camera, trash, close } from'ionicons/icons'
4+
const { photos, takePhoto, deletePhoto } =usePhotoGallery()
5+
6+
const showActionSheet =async (photo:UserPhoto) => {
7+
const actionSheet =awaitactionSheetController.create({
8+
header: 'Photos',
9+
buttons: [
10+
{
11+
text: 'Delete',
12+
role: 'destructive',
13+
icon: trash,
14+
handler: () => {
15+
deletePhoto(photo)
16+
},
17+
},
18+
{
19+
text: 'Cancel',
20+
icon: close,
21+
role: 'cancel',
22+
handler: () => {
23+
// Nothing to do, action sheet is automatically closed
24+
},
25+
},
26+
],
27+
})
28+
awaitactionSheet.present()
29+
}
30+
</script>
31+
32+
<template>
33+
<ion-page>
34+
<ion-header>
35+
<ion-toolbar>
36+
<ion-title>Photo Gallery</ion-title>
37+
</ion-toolbar>
38+
</ion-header>
39+
<ion-content:fullscreen="true">
40+
<ion-headercollapse="condense">
41+
<ion-toolbar>
42+
<ion-titlesize="large">Photo Gallery</ion-title>
43+
</ion-toolbar>
44+
</ion-header>
45+
<ion-grid>
46+
<ion-row>
47+
<ion-colsize="6":key="photo"v-for="photo in photos">
48+
<ion-img
49+
:src="photo.webviewPath"
50+
@click="showActionSheet(photo)"
51+
></ion-img>
52+
</ion-col>
53+
</ion-row>
54+
</ion-grid>
55+
56+
<ion-fabvertical="bottom"horizontal="center"slot="fixed">
57+
<ion-fab-button@click="takePhoto()">
58+
<ion-icon:icon="camera"></ion-icon>
59+
</ion-fab-button>
60+
</ion-fab>
61+
</ion-content>
62+
</ion-page>
63+
</template>

0 commit comments

Comments
 (0)