Skip to content

Commit

Permalink
✨ Fullscreen image modal
Browse files Browse the repository at this point in the history
  • Loading branch information
BetaHuhn committed Oct 17, 2021
1 parent 4ac8228 commit ada1579
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 44 deletions.
70 changes: 70 additions & 0 deletions client/components/ImageDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<template>
<div class="image-wrapper" :style="{ '--max-height': maxHeight }">
<div class="image" @click.stop="fullscreen">
<img :src="src" :class="!loaded && 'loading'" @error="onError" @load="onLoad">
</div>
</div>
</template>

<script>
export default {
props: {
src: {
type: String,
required: true
},
maxHeight: {
type: String,
default: '300px'
}
},
data() {
return {
imageError: false,
loaded: false
}
},
methods: {
onError() {
this.imageError = true
this.$emit('fail')
},
onLoad() {
this.loaded = true
this.$emit('loaded')
},
fullscreen() {
this.$emit('fullscreen')
this.$modal.show('viewImage', { src: this.src })
}
}
}
</script>

<style lang="scss" scoped>
.image-wrapper {
margin-top: 1rem;
margin-bottom: 1rem;
background: var(--background-2nd);
overflow: hidden;
border-radius: var(--border-radius);
resize: vertical;
height: var(--max-height);
}
.image {
max-width: 100%;
max-height: 100%;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
& img {
width: 100%;
height: 100%;
pointer-events: none;
}
}
</style>
44 changes: 14 additions & 30 deletions client/components/Modal/LinkDetails.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<Modal
class="link-details-modal"
width="1000px"
max-width="1000px"
min-height="250px"
:can-close="canClose"
:can-expand="!$fetchState.pending && link !== undefined"
Expand Down Expand Up @@ -46,11 +46,7 @@
</div>
</div>
<hr>
<div v-if="link.meta && link.meta.image" class="image-wrapper">
<div class="image">
<img :src="imageUrl">
</div>
</div>
<ImageDisplay v-if="link.meta && link.meta.image" :src="imageUrl" />
<LinkEditor v-model="linkDescription" :editable="editable" placeholder="Add some notes …" />
</div>
<p v-else>
Expand Down Expand Up @@ -183,6 +179,9 @@ export default {
},
shareLinkModal() {
return this.$store.state.modal.show && this.$store.state.modal.show.shareLink
},
viewImageModal() {
return this.$store.state.modal.show && this.$store.state.modal.show.viewImage
}
},
watch: {
Expand All @@ -196,6 +195,15 @@ export default {
}, 500)
}
},
viewImageModal(newValue) {
if (newValue === true) {
this.canClose = false
} else {
setTimeout(() => {
this.canClose = true
}, 500)
}
},
linkTitle(value, oldValue) {
if (!value || value === oldValue || !this.editable) return
Expand Down Expand Up @@ -372,30 +380,6 @@ export default {
}
}
.image-wrapper {
margin-top: 1rem;
margin-bottom: 1rem;
background: var(--background-2nd);
overflow: hidden;
border-radius: var(--border-radius);
resize: vertical;
}
.image {
max-width: 100%;
max-height: 300px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
& img {
width: 100%;
height: 100%;
pointer-events: none;
}
}
.top {
display: flex;
align-items: center;
Expand Down
60 changes: 60 additions & 0 deletions client/components/Modal/ViewImage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<Modal
class="image-modal"
max-width="unset"
min-height="unset"
width="unset"
overflow="hidden"
padding="0"
:centered="true"
@close="close"
>
<div>
<img :src="src">
</div>
</Modal>
</template>

<script>
export default {
data() {
return {
canClose: false
}
},
computed: {
src: {
set(value) {
this.$modal.setData({ src: value })
},
get() {
return this.$store.state.modal.data.src
}
}
},
created() {
// Prevent other old click events from closing modal
setTimeout(() => {
this.canClose = true
}, 200)
},
methods: {
close() {
if (this.canClose) {
this.$modal.hide('viewImage')
}
}
}
}
</script>

<style lang="scss" scoped>
.image-modal {
img {
max-width: 85vw;
max-height: 85vh;
height: 100%;
display: block;
}
}
</style>
1 change: 1 addition & 0 deletions client/components/Modal/Wrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ModalShareLink v-if="showModal && showModal.shareLink" />
<ModalBookmarklet v-if="showModal && showModal.bookmarklet" />
<ModalChangelog v-if="showModal && showModal.changelog" />
<ModalViewImage v-if="showModal && showModal.viewImage" />

<ConfirmModal />
</div>
Expand Down
43 changes: 35 additions & 8 deletions client/components/Modal/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="modal-wrapper" :style="{ '--width': width, '--overflow': overflow, '--min-height': minHeight }">
<div v-click-outside="close" v-shortkey="['esc']" class="modal-content" @shortkey="close">
<div class="modal-wrapper" :style="{ '--width': width, '--height': height, '--max-width': maxWidth, '--overflow': overflow, '--min-height': minHeight, '--padding': padding }">
<div v-click-outside="close" v-shortkey="['esc']" class="modal-content" :class="centered && 'centered'" @shortkey="close">
<div v-if="canExpand" class="action-bar">
<p class="hover-button" @click.stop="expand">
<Icon name="expand" size="18px" />Open as page
Expand All @@ -23,10 +23,22 @@ export default {
ClickOutside
},
props: {
width: {
maxWidth: {
type: String,
default: '900px'
},
width: {
type: String,
default: '95%'
},
height: {
type: String,
default: undefined
},
padding: {
type: String,
default: '1.5rem'
},
overflow: {
type: String,
default: 'auto'
Expand All @@ -35,6 +47,10 @@ export default {
type: String,
default: undefined
},
centered: {
type: Boolean,
default: false
},
canClose: {
type: Boolean,
default: true
Expand Down Expand Up @@ -97,32 +113,43 @@ export default {
.modal-content {
background: var(--background);
border-radius: var(--border-radius);
max-width: var(--width);
width: 95%;
max-width: var(--max-width);
max-height: 85%;
min-height: var(--min-height);
width: var(--width);
height: var(--height);
position: absolute;
left: 50%;
top: 10%; // 5rem
transform: translateX(-50%);
padding: 1.5rem;
padding: var(--padding);
overflow-y: var(--overflow);
scrollbar-width: thin;
scrollbar-color: var(--grey) var(--background-2nd);
max-height: 85%;
min-height: var(--min-height);
&.centered {
top: 50%;
transform: translate(-50%, -50%);
}
}
.close-icon {
position: absolute;
top: 0.5rem;
right: 0.5rem;
color: var(--text-light);
z-index: 10;
cursor: pointer;
mix-blend-mode: difference;
}
.expand-icon {
position: absolute;
top: 0.5rem;
left: 0.5rem;
color: var(--text-light);
z-index: 10;
cursor: pointer;
}
.action-bar {
Expand Down
6 changes: 1 addition & 5 deletions client/pages/link/_.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@
</div>
<hr>
<div class="link-content">
<div v-if="link.meta && link.meta.image" class="image-wrapper">
<div class="image">
<img :src="imageUrl">
</div>
</div>
<ImageDisplay v-if="link.meta && link.meta.image" :src="imageUrl" max-height="400px" />
<LinkEditor v-model="linkDescription" :editable="editable" placeholder="Add some notes …" />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion client/store/modal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const modals = [ 'search', 'addLink', 'addCrate', 'addExternalCrate', 'linkDetails', 'confirm', 'copyOutput', 'changeName', 'shareLink', 'bookmarklet', 'changelog' ]
const modals = [ 'search', 'addLink', 'addCrate', 'addExternalCrate', 'linkDetails', 'confirm', 'copyOutput', 'changeName', 'shareLink', 'bookmarklet', 'changelog', 'viewImage' ]

export const state = () => ({
show: undefined,
Expand Down

0 comments on commit ada1579

Please sign in to comment.