Browse Source
			
			
			
			
				
		Reviewed-on: https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/pulls/115kb/add-usage-guide
				 18 changed files with 553 additions and 132 deletions
			
			
		| @ -0,0 +1,13 @@ | |||||
|  | // for ephemeral uses, eg. passing a blob from the service worker to the main thread
 | ||||
|  | 
 | ||||
|  | export type Temp = { | ||||
|  |   id: string; | ||||
|  |   blob?: Blob; | ||||
|  | }; | ||||
|  | 
 | ||||
|  | /** | ||||
|  |  * Schema for the Temp table in the database. | ||||
|  |  */ | ||||
|  | export const TempSchema = { | ||||
|  |   temp: "id", | ||||
|  | }; | ||||
| @ -0,0 +1,188 @@ | |||||
|  | <template> | ||||
|  |   <QuickNav /> | ||||
|  |   <!-- CONTENT --> | ||||
|  |   <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto"> | ||||
|  |     <!-- Heading --> | ||||
|  |     <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8"> | ||||
|  |       Image | ||||
|  |     </h1> | ||||
|  |     <div v-if="imageBlob"> | ||||
|  |       <div v-if="uploading" class="text-center mb-4"> | ||||
|  |         <fa icon="spinner" class="fa-spin-pulse" /> | ||||
|  |       </div> | ||||
|  |       <div v-else> | ||||
|  |         <div class="text-center mb-4">Choose how to use this image</div> | ||||
|  |         <div class="grid grid-cols-1 sm:grid-cols-3 gap-4"> | ||||
|  |           <button | ||||
|  |             @click="recordGift" | ||||
|  |             class="text-center text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md" | ||||
|  |           > | ||||
|  |             <fa icon="gift" class="fa-fw" /> | ||||
|  |             Record a Gift | ||||
|  |           </button> | ||||
|  |           <button | ||||
|  |             @click="recordProfile" | ||||
|  |             class="text-center text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md" | ||||
|  |           > | ||||
|  |             <fa icon="circle-user" class="fa-fw" /> | ||||
|  |             Save as Profile Image | ||||
|  |           </button> | ||||
|  |           <button | ||||
|  |             @click="cancel" | ||||
|  |             class="text-center text-md font-bold bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md" | ||||
|  |           > | ||||
|  |             <fa icon="ban" class="fa-fw" /> | ||||
|  |             Cancel | ||||
|  |           </button> | ||||
|  |         </div> | ||||
|  |       </div> | ||||
|  | 
 | ||||
|  |       <div class="flex justify-center"> | ||||
|  |         <img | ||||
|  |           :src="URL.createObjectURL(imageBlob)" | ||||
|  |           alt="Shared Image" | ||||
|  |           class="rounded mt-4" | ||||
|  |         /> | ||||
|  |       </div> | ||||
|  |     </div> | ||||
|  |     <div v-else class="text-center mb-4"> | ||||
|  |       <p>No image found.</p> | ||||
|  |     </div> | ||||
|  |   </section> | ||||
|  | </template> | ||||
|  | 
 | ||||
|  | <script lang="ts"> | ||||
|  | import { Component, Vue } from "vue-facing-decorator"; | ||||
|  | 
 | ||||
|  | import QuickNav from "@/components/QuickNav.vue"; | ||||
|  | import { | ||||
|  |   DEFAULT_IMAGE_API_SERVER, | ||||
|  |   IMAGE_TYPE_PROFILE, | ||||
|  |   NotificationIface, | ||||
|  | } from "@/constants/app"; | ||||
|  | import { db } from "@/db/index"; | ||||
|  | import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; | ||||
|  | import { getIdentity } from "@/libs/util"; | ||||
|  | import { accessToken } from "@/libs/crypto"; | ||||
|  | import axios from "axios"; | ||||
|  | 
 | ||||
|  | @Component({ components: { QuickNav } }) | ||||
|  | export default class SharedPhotoView extends Vue { | ||||
|  |   $notify!: (notification: NotificationIface, timeout?: number) => void; | ||||
|  | 
 | ||||
|  |   activeDid: string | undefined = undefined; | ||||
|  |   imageBlob: Blob | undefined = undefined; | ||||
|  |   imageFileName: string | undefined = undefined; | ||||
|  |   uploading = false; | ||||
|  | 
 | ||||
|  |   URL = window.URL || window.webkitURL; | ||||
|  | 
 | ||||
|  |   // 'created' hook runs when the Vue instance is first created | ||||
|  |   async mounted() { | ||||
|  |     try { | ||||
|  |       await db.open(); | ||||
|  |       const settings = await db.settings.get(MASTER_SETTINGS_KEY); | ||||
|  |       this.activeDid = settings?.activeDid as string; | ||||
|  | 
 | ||||
|  |       const temp = await db.temp.get("shared-photo"); | ||||
|  |       if (temp) { | ||||
|  |         this.imageBlob = temp.blob; | ||||
|  | 
 | ||||
|  |         // clear the temp image | ||||
|  |         db.temp.delete("shared-photo"); | ||||
|  | 
 | ||||
|  |         this.imageFileName = this.$route.query.fileName as string; | ||||
|  |       } | ||||
|  |     } catch (err: unknown) { | ||||
|  |       console.error("Got an error loading an identifier:", err); | ||||
|  |       this.$notify( | ||||
|  |         { | ||||
|  |           group: "alert", | ||||
|  |           type: "danger", | ||||
|  |           title: "Error", | ||||
|  |           text: "Got an error loading this data.", | ||||
|  |         }, | ||||
|  |         -1, | ||||
|  |       ); | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   async recordGift() { | ||||
|  |     await this.sendToImageServer("GiveAction").then((url) => { | ||||
|  |       if (url) { | ||||
|  |         this.$router.push({ | ||||
|  |           name: "gifted-details", | ||||
|  |           query: { | ||||
|  |             destinationNameAfter: "home", | ||||
|  |             hideBackButton: true, | ||||
|  |             imageUrl: url, | ||||
|  |             recipientDid: this.activeDid, | ||||
|  |           }, | ||||
|  |         }); | ||||
|  |       } | ||||
|  |     }); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   async recordProfile() { | ||||
|  |     await this.sendToImageServer(IMAGE_TYPE_PROFILE).then((url) => { | ||||
|  |       if (url) { | ||||
|  |         db.settings.update(MASTER_SETTINGS_KEY, { | ||||
|  |           profileImageUrl: url, | ||||
|  |         }); | ||||
|  |         this.$router.push({ name: "account" }); | ||||
|  |       } | ||||
|  |     }); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   async cancel() { | ||||
|  |     this.imageBlob = undefined; | ||||
|  |     this.imageFileName = undefined; | ||||
|  |     this.$router.push({ name: "home" }); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   async sendToImageServer(imageType: string) { | ||||
|  |     this.uploading = true; | ||||
|  | 
 | ||||
|  |     let result; | ||||
|  |     try { | ||||
|  |       // send the image to the server | ||||
|  |       const identifier = await getIdentity(this.activeDid as string); | ||||
|  |       const token = await accessToken(identifier); | ||||
|  |       const headers = { | ||||
|  |         Authorization: "Bearer " + token, | ||||
|  |       }; | ||||
|  |       const formData = new FormData(); | ||||
|  |       formData.append( | ||||
|  |         "image", | ||||
|  |         this.imageBlob as Blob, | ||||
|  |         this.imageFileName as string, | ||||
|  |       ); | ||||
|  |       formData.append("claimType", imageType); | ||||
|  | 
 | ||||
|  |       const response = await axios.post( | ||||
|  |         DEFAULT_IMAGE_API_SERVER + "/image", | ||||
|  |         formData, | ||||
|  |         { headers }, | ||||
|  |       ); | ||||
|  |       this.imageBlob = undefined; | ||||
|  |       this.imageFileName = undefined; | ||||
|  | 
 | ||||
|  |       this.uploading = false; | ||||
|  |       result = response.data.url as string; | ||||
|  |     } catch (error) { | ||||
|  |       console.error("Error uploading the image", error); | ||||
|  |       this.$notify( | ||||
|  |         { | ||||
|  |           group: "alert", | ||||
|  |           type: "danger", | ||||
|  |           title: "Error", | ||||
|  |           text: "There was an error saving the picture. Please try again.", | ||||
|  |         }, | ||||
|  |         5000, | ||||
|  |       ); | ||||
|  |       this.uploading = false; | ||||
|  |     } | ||||
|  |     return result; | ||||
|  |   } | ||||
|  | } | ||||
|  | </script> | ||||
					Loading…
					
					
				
		Reference in new issue