Merge pull request #1325 from thelounge/astorije/image-viewer

An image viewer popup for thumbnails and image previews
This commit is contained in:
Jérémie Astori 2017-07-18 00:09:21 -04:00 committed by GitHub
commit ce0e460368
6 changed files with 155 additions and 8 deletions

View File

@ -137,12 +137,14 @@ kbd {
text-transform: uppercase; text-transform: uppercase;
transition: background .2s, border-color .2s, color .2s; transition: background .2s, border-color .2s, color .2s;
word-spacing: 3px; word-spacing: 3px;
cursor: pointer; /* This is useful for `<button>` elements */
} }
.btn:disabled, .btn:disabled,
.btn:hover { .btn:hover {
background: #84ce88; background: #84ce88;
color: #fff; color: #fff;
opacity: 1;
} }
.btn:active { .btn:active {
@ -335,6 +337,9 @@ kbd {
#wrap { #wrap {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
/* Needed to transition blurred background when image viewer is open */
transition: filter .2s;
} }
#viewport { #viewport {
@ -1145,7 +1150,6 @@ kbd {
color: #222; color: #222;
font-size: 12px; font-size: 12px;
max-width: 100%; max-width: 100%;
padding: 6px;
margin: 2px 0; margin: 2px 0;
overflow: hidden; overflow: hidden;
} }
@ -1157,22 +1161,32 @@ kbd {
} }
#chat .toggle-content .thumb { #chat .toggle-content .thumb {
margin-right: 6px;
max-width: 48px; max-width: 48px;
max-height: 32px; max-height: 32px;
} }
#chat .toggle-thumbnail {
padding: 6px;
}
#chat .toggle-text { #chat .toggle-text {
padding: 6px;
min-width: 0; min-width: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
white-space: nowrap; white-space: nowrap;
color: inherit;
}
#chat .toggle-text:not(:first-child) {
padding-left: 0;
} }
#chat .toggle-content .head, #chat .toggle-content .head,
#chat .toggle-content .body { #chat .toggle-content .body {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
color: inherit;
} }
#chat .toggle-content .head { #chat .toggle-content .head {
@ -1996,3 +2010,72 @@ kbd {
::-webkit-scrollbar-thumb:vertical:active { ::-webkit-scrollbar-thumb:vertical:active {
background: rgba(0, 0, 0, .6); background: rgba(0, 0, 0, .6);
} }
/* Image viewer */
#image-viewer,
#image-viewer .close-btn {
/* Vertically and horizontally center stuff */
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#image-viewer {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .8);
visibility: hidden;
opacity: 0;
transition: opacity .2s, visibility .2s;
z-index: 999;
}
.image-viewer-opened #wrap {
filter: blur(4px);
}
.image-viewer-opened #image-viewer {
visibility: visible;
opacity: 1;
}
#image-viewer .close-btn {
position: fixed;
top: 0;
right: 0;
width: 2em;
height: 2em;
font-size: 36px;
color: white;
z-index: 1001;
opacity: .6;
transition: .2s opacity;
}
#image-viewer .close-btn:hover {
opacity: 1;
}
#image-viewer .image-link {
margin: 10px;
}
#image-viewer .image-link:hover {
opacity: 1;
}
#image-viewer .image-link img {
max-width: 100%;
/* Top/Bottom margins + button height + image/button margin */
max-height: calc(100vh - 2 * 10px - 37px - 10px);
}
#image-viewer .open-btn {
margin: 0 auto 10px;
}

View File

@ -901,6 +901,8 @@
<ul id="context-menu"></ul> <ul id="context-menu"></ul>
</div> </div>
<div id="image-viewer"></div>
<script src="js/bundle.vendor.js"></script> <script src="js/bundle.vendor.js"></script>
<script src="js/bundle.js"></script> <script src="js/bundle.js"></script>

View File

@ -61,3 +61,47 @@ function handleImageInPreview(content, container) {
}); });
} }
} }
/* Image viewer */
// FIXME Remove #input focus when this is open
// See https://github.com/thelounge/lounge/issues/1342
$("#viewport").on("click", ".toggle-thumbnail", function() {
const link = $(this);
openImageViewer(link);
// Prevent the link to open a new page since we're opening the image viewer,
// but keep it a link to allow for Ctrl/Cmd+click
return false;
});
$("#image-viewer").on("click", function() {
closeImageViewer();
});
$(document).keydown(function(e) {
switch (e.keyCode ? e.keyCode : e.which) {
case 27: // Escape
closeImageViewer();
break;
}
});
function openImageViewer(link) {
$("#image-viewer").html(templates.image_viewer({
image: link.find("img").attr("src"),
link: link.attr("href"),
type: link.parent().hasClass("toggle-type-image") ? "image" : "link"
}));
$(document.body).addClass("image-viewer-opened");
}
function closeImageViewer() {
$(document.body)
.removeClass("image-viewer-opened")
.one("transitionend", function() {
$("#image-viewer").empty();
});
}

View File

@ -0,0 +1,13 @@
<button class="close-btn" aria-label="Close">×</button>
<a class="image-link" href="{{link}}" target="_blank">
<img src="{{image}}">
</a>
<a class="btn open-btn" href="{{link}}" target="_blank">
{{#equal type "image"}}
Open image
{{else}}
Visit page
{{/equal}}
</a>

View File

@ -29,6 +29,7 @@ module.exports = {
msg_preview_toggle: require("./msg_preview_toggle.tpl"), msg_preview_toggle: require("./msg_preview_toggle.tpl"),
msg_unhandled: require("./msg_unhandled.tpl"), msg_unhandled: require("./msg_unhandled.tpl"),
network: require("./network.tpl"), network: require("./network.tpl"),
image_viewer: require("./image_viewer.tpl"),
unread_marker: require("./unread_marker.tpl"), unread_marker: require("./unread_marker.tpl"),
user: require("./user.tpl"), user: require("./user.tpl"),
user_filtered: require("./user_filtered.tpl"), user_filtered: require("./user_filtered.tpl"),

View File

@ -1,15 +1,19 @@
{{#preview}} {{#preview}}
<a href="{{link}}" target="_blank" rel="noopener" class="toggle-content toggle-type-{{type}}{{#if shown}} show{{/if}}"> <div class="toggle-content toggle-type-{{type}}{{#if shown}} show{{/if}}">
{{#equal type "image"}} {{#equal type "image"}}
<a class="toggle-thumbnail" href="{{link}}" target="_blank" rel="noopener">
<img src="{{link}}"> <img src="{{link}}">
</a>
{{else}} {{else}}
{{#if thumb}} {{#if thumb}}
<a class="toggle-thumbnail" href="{{link}}" target="_blank" rel="noopener">
<img src="{{thumb}}" class="thumb"> <img src="{{thumb}}" class="thumb">
</a>
{{/if}} {{/if}}
<div class="toggle-text"> <a class="toggle-text" href="{{link}}" target="_blank" rel="noopener">
<div class="head" title="{{head}}">{{head}}</div> <div class="head" title="{{head}}">{{head}}</div>
<div class="body" title="{{body}}">{{body}}</div> <div class="body" title="{{body}}">{{body}}</div>
</div> </a>
{{/equal}} {{/equal}}
</a> </div>
{{/preview}} {{/preview}}