Browse Source
			
			
			
			
				
		Reviewed-on: https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/pulls/125
				 6 changed files with 161 additions and 17 deletions
			
			
		| @ -0,0 +1,97 @@ | |||
| <template> | |||
|   <Teleport to="body"> | |||
|     <Transition name="fade"> | |||
|       <div | |||
|         v-if="isOpen" | |||
|         class="fixed inset-0 z-50 flex flex-col bg-black/90" | |||
|       > | |||
|         <!-- Header bar - fixed height to prevent overlap --> | |||
|         <div class="h-16 flex justify-between items-center px-4 bg-black"> | |||
|           <button | |||
|             class="text-white text-2xl p-2 rounded-full hover:bg-white/10" | |||
|             @click="close" | |||
|           > | |||
|             <fa icon="xmark" /> | |||
|           </button> | |||
| 
 | |||
|           <!-- Mobile share button --> | |||
|           <button | |||
|             v-if="isMobile" | |||
|             class="text-white text-xl p-2 rounded-full hover:bg-white/10" | |||
|             @click="handleShare" | |||
|           > | |||
|             <fa icon="ellipsis" /> | |||
|           </button> | |||
|         </div> | |||
| 
 | |||
|         <!-- Image container - fill remaining space --> | |||
|         <div class="flex-1 flex items-center justify-center p-2"> | |||
|           <div class="w-full h-full flex items-center justify-center"> | |||
|             <img | |||
|               :src="imageUrl" | |||
|               class="max-h-[calc(100vh-5rem)] w-full h-full object-contain" | |||
|               @click.stop | |||
|               alt="expanded shared content" | |||
|             /> | |||
|           </div> | |||
|         </div> | |||
|       </div> | |||
|     </Transition> | |||
|   </Teleport> | |||
| </template> | |||
| 
 | |||
| <script lang="ts"> | |||
| import { Component, Vue, Prop } from "vue-facing-decorator"; | |||
| import { UAParser } from "ua-parser-js"; | |||
| 
 | |||
| @Component({ emits: ["update:isOpen"] }) | |||
| export default class ImageViewer extends Vue { | |||
|   @Prop() imageUrl!: string; | |||
|   @Prop() imageData!: Blob | null; | |||
|   @Prop() isOpen!: boolean; | |||
| 
 | |||
|   userAgent = new UAParser(); | |||
| 
 | |||
|   get isMobile() { | |||
|     const os = this.userAgent.getOS().name; | |||
|     return os === "iOS" || os === "Android"; | |||
|   } | |||
| 
 | |||
|   close() { | |||
|     this.$emit("update:isOpen", false); | |||
|   } | |||
| 
 | |||
|   async handleShare() { | |||
|     const os = this.userAgent.getOS().name; | |||
| 
 | |||
|     try { | |||
|       if (os === "iOS" || os === "Android") { | |||
|         if (navigator.share) { | |||
|           // Always share the URL since it's more reliable across platforms | |||
|           await navigator.share({ | |||
|             url: this.imageUrl | |||
|           }); | |||
|         } else { | |||
|           // Fallback for browsers without share API | |||
|           window.open(this.imageUrl, "_blank"); | |||
|         } | |||
|       } | |||
|     } catch (error) { | |||
|       console.warn("Share failed, opening in new tab:", error); | |||
|       window.open(this.imageUrl, "_blank"); | |||
|     } | |||
|   } | |||
| } | |||
| </script> | |||
| 
 | |||
| <style scoped> | |||
| .fade-enter-active, | |||
| .fade-leave-active { | |||
|   transition: opacity 0.2s ease; | |||
| } | |||
| 
 | |||
| .fade-enter-from, | |||
| .fade-leave-to { | |||
|   opacity: 0; | |||
| } | |||
| </style> | |||
					Loading…
					
					
				
		Reference in new issue