|
|
@ -3,22 +3,38 @@ |
|
|
|
<Transition name="fade"> |
|
|
|
<div |
|
|
|
v-if="isOpen" |
|
|
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/90" |
|
|
|
@click="close" |
|
|
|
class="fixed inset-0 z-50 flex flex-col bg-black/90" |
|
|
|
> |
|
|
|
<button |
|
|
|
class="absolute top-4 right-4 text-white text-2xl p-2 rounded-full hover:bg-white/10" |
|
|
|
@click="close" |
|
|
|
> |
|
|
|
<fa icon="xmark" /> |
|
|
|
</button> |
|
|
|
|
|
|
|
<img |
|
|
|
:src="imageUrl" |
|
|
|
class="max-h-screen max-w-screen-md w-full object-contain p-4" |
|
|
|
@click.stop |
|
|
|
alt="expanded shared content" |
|
|
|
/> |
|
|
|
<!-- 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> |
|
|
@ -26,15 +42,45 @@ |
|
|
|
|
|
|
|
<script lang="ts"> |
|
|
|
import { Component, Vue, Prop } from "vue-facing-decorator"; |
|
|
|
import { UAParser } from "ua-parser-js"; |
|
|
|
|
|
|
|
@Component |
|
|
|
@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> |
|
|
|
|
|
|
|