From 511b173b6f8b83a3d862fe8a99fe7f0ab5e55c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Astori?= Date: Wed, 12 Jul 2017 02:55:41 -0400 Subject: [PATCH] Add an image viewer for thumbnails and image previews --- client/css/style.css | 85 ++++++++++++++++++++++++++++++++++- client/index.html | 2 + client/js/renderPreview.js | 44 ++++++++++++++++++ client/views/image_viewer.tpl | 13 ++++++ client/views/index.js | 1 + client/views/msg_preview.tpl | 16 ++++--- 6 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 client/views/image_viewer.tpl diff --git a/client/css/style.css b/client/css/style.css index c28b085d..f2f3555c 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -337,6 +337,9 @@ kbd { #wrap { height: 100%; overflow: hidden; + + /* Needed to transition blurred background when image viewer is open */ + transition: filter .2s; } #viewport { @@ -1147,7 +1150,6 @@ kbd { color: #222; font-size: 12px; max-width: 100%; - padding: 6px; margin: 2px 0; overflow: hidden; } @@ -1159,22 +1161,32 @@ kbd { } #chat .toggle-content .thumb { - margin-right: 6px; max-width: 48px; max-height: 32px; } +#chat .toggle-thumbnail { + padding: 6px; +} + #chat .toggle-text { + padding: 6px; min-width: 0; display: flex; flex-direction: column; white-space: nowrap; + color: inherit; +} + +#chat .toggle-text:not(:first-child) { + padding-left: 0; } #chat .toggle-content .head, #chat .toggle-content .body { text-overflow: ellipsis; overflow: hidden; + color: inherit; } #chat .toggle-content .head { @@ -1998,3 +2010,72 @@ kbd { ::-webkit-scrollbar-thumb:vertical:active { 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; +} diff --git a/client/index.html b/client/index.html index 398995a5..4a32be51 100644 --- a/client/index.html +++ b/client/index.html @@ -901,6 +901,8 @@ +
+ diff --git a/client/js/renderPreview.js b/client/js/renderPreview.js index 86fb58c0..c6f6d21d 100644 --- a/client/js/renderPreview.js +++ b/client/js/renderPreview.js @@ -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(); + }); +} diff --git a/client/views/image_viewer.tpl b/client/views/image_viewer.tpl new file mode 100644 index 00000000..5cdc3a50 --- /dev/null +++ b/client/views/image_viewer.tpl @@ -0,0 +1,13 @@ + + + + + + + + {{#equal type "image"}} + Open image + {{else}} + Visit page + {{/equal}} + diff --git a/client/views/index.js b/client/views/index.js index ca571bec..5c9da5dd 100644 --- a/client/views/index.js +++ b/client/views/index.js @@ -29,6 +29,7 @@ module.exports = { msg_preview_toggle: require("./msg_preview_toggle.tpl"), msg_unhandled: require("./msg_unhandled.tpl"), network: require("./network.tpl"), + image_viewer: require("./image_viewer.tpl"), unread_marker: require("./unread_marker.tpl"), user: require("./user.tpl"), user_filtered: require("./user_filtered.tpl"), diff --git a/client/views/msg_preview.tpl b/client/views/msg_preview.tpl index 5f56529c..24f4a599 100644 --- a/client/views/msg_preview.tpl +++ b/client/views/msg_preview.tpl @@ -1,15 +1,19 @@ {{#preview}} - +
{{#equal type "image"}} - + + + {{else}} {{#if thumb}} - + + + {{/if}} - + {{/equal}} - +
{{/preview}}