From 617e1b210e17542ff91d5ff7f849a608a606b1e5 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Mon, 26 Jun 2017 12:01:55 +0300 Subject: [PATCH] Refactor link previews --- client/css/style.css | 8 ++-- client/js/libs/jquery/stickyscroll.js | 2 +- client/js/lounge.js | 19 --------- client/js/render.js | 6 +++ client/js/socket-events/index.js | 2 +- client/js/socket-events/msg.js | 3 +- client/js/socket-events/msg_preview.js | 36 +++++++++++++++++ client/js/socket-events/toggle.js | 24 ------------ client/views/msg.tpl | 18 +++------ client/views/toggle.tpl | 31 ++++++++------- src/plugins/irc-events/link.js | 53 ++++++++++++-------------- 11 files changed, 96 insertions(+), 106 deletions(-) create mode 100644 client/js/socket-events/msg_preview.js delete mode 100644 client/js/socket-events/toggle.js diff --git a/client/css/style.css b/client/css/style.css index 0545646cf5..c312eee90b 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -1110,6 +1110,10 @@ kbd { padding: 0 6px; } +#chat .toggle-button:after { + content: "···"; +} + #chat .toggle-content { background: #f5f5f5; border-radius: 2px; @@ -1122,10 +1126,6 @@ kbd { overflow: hidden; } -#chat .toggle-content a { - color: inherit; -} - #chat .toggle-content img { max-width: 100%; max-height: 128px; diff --git a/client/js/libs/jquery/stickyscroll.js b/client/js/libs/jquery/stickyscroll.js index c3500be590..fa83f68806 100644 --- a/client/js/libs/jquery/stickyscroll.js +++ b/client/js/libs/jquery/stickyscroll.js @@ -37,7 +37,7 @@ import jQuery from "jquery"; lastStick = Date.now(); this.scrollTop = this.scrollHeight; }) - .on("msg.sticky", keepToBottom) + .on("keepToBottom.sticky", keepToBottom) .scrollBottom(); return self; diff --git a/client/js/lounge.js b/client/js/lounge.js index 358f4e6097..27faa8b893 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -681,25 +681,6 @@ $(function() { }); }); - chat.on("click", ".toggle-button", function() { - var self = $(this); - var localChat = self.closest(".chat"); - var bottom = localChat.isScrollBottom(); - var content = self.parent().next(".toggle-content"); - if (bottom && !content.hasClass("show")) { - var img = content.find("img"); - if (img.length !== 0 && !img.width()) { - img.on("load", function() { - localChat.scrollBottom(); - }); - } - } - content.toggleClass("show"); - if (bottom) { - localChat.scrollBottom(); - } - }); - var forms = $("#sign-in, #connect, #change-password"); windows.on("show", "#sign-in", function() { diff --git a/client/js/render.js b/client/js/render.js index 213a3cb895..0901faed94 100644 --- a/client/js/render.js +++ b/client/js/render.js @@ -35,6 +35,12 @@ function buildChatMessage(data) { target = "#chan-" + chat.find(".active").data("id"); } + if (data.msg.preview) { + data.msg.preview.shown = + (options.links && data.msg.preview.type === "link") || + (options.thumbnails && data.msg.preview.type === "image"); + } + const chan = chat.find(target); let template = "msg"; diff --git a/client/js/socket-events/index.js b/client/js/socket-events/index.js index be69a379f9..b6545192e0 100644 --- a/client/js/socket-events/index.js +++ b/client/js/socket-events/index.js @@ -6,6 +6,7 @@ require("./init"); require("./join"); require("./more"); require("./msg"); +require("./msg_preview"); require("./names"); require("./network"); require("./nick"); @@ -13,6 +14,5 @@ require("./open"); require("./part"); require("./quit"); require("./sync_sort"); -require("./toggle"); require("./topic"); require("./users"); diff --git a/client/js/socket-events/msg.js b/client/js/socket-events/msg.js index c05d2cec66..df3dc35ef4 100644 --- a/client/js/socket-events/msg.js +++ b/client/js/socket-events/msg.js @@ -35,7 +35,8 @@ socket.on("msg", function(data) { .trigger("msg", [ target, data - ]); + ]) + .trigger("keepToBottom"); var lastVisible = container.find("div:visible").last(); if (data.msg.self diff --git a/client/js/socket-events/msg_preview.js b/client/js/socket-events/msg_preview.js new file mode 100644 index 0000000000..343c2aac75 --- /dev/null +++ b/client/js/socket-events/msg_preview.js @@ -0,0 +1,36 @@ +"use strict"; + +const $ = require("jquery"); +const socket = require("../socket"); +const templates = require("../../views"); +const options = require("../options"); + +socket.on("msg:preview", function(data) { + data.preview.shown = + (options.links && data.preview.type === "link") || + (options.thumbnails && data.preview.type === "image"); + + const toggle = $("#msg-" + data.id); + toggle.find(".text").append(templates.toggle({preview: data.preview})); + + toggle.parent(".messages").trigger("keepToBottom"); +}); + +$("#chat").on("click", ".toggle-button", function() { + var self = $(this); + var localChat = self.closest(".chat"); + var bottom = localChat.isScrollBottom(); + var content = self.parent().next(".toggle-content"); + if (bottom && !content.hasClass("show")) { + var img = content.find("img"); + if (img.length !== 0 && !img.width()) { + img.on("load", function() { + localChat.scrollBottom(); + }); + } + } + content.toggleClass("show"); + if (bottom) { + localChat.scrollBottom(); + } +}); diff --git a/client/js/socket-events/toggle.js b/client/js/socket-events/toggle.js deleted file mode 100644 index 9e48f72e6c..0000000000 --- a/client/js/socket-events/toggle.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -const $ = require("jquery"); -const socket = require("../socket"); -const templates = require("../../views"); -const options = require("../options"); - -socket.on("toggle", function(data) { - const toggle = $("#toggle-" + data.id); - toggle.parent().after(templates.toggle({toggle: data})); - switch (data.type) { - case "link": - if (options.links) { - toggle.click(); - } - break; - - case "image": - if (options.thumbnails) { - toggle.click(); - } - break; - } -}); diff --git a/client/views/msg.tpl b/client/views/msg.tpl index feb8686d31..fa24448c40 100644 --- a/client/views/msg.tpl +++ b/client/views/msg.tpl @@ -7,17 +7,11 @@ {{> user_name nick=from}} {{/if}} - {{#equal type "toggle"}} - -
- -
- {{#if toggle}} - {{> toggle}} - {{/if}} -
- {{else}} - {{{parse text}}} - {{/equal}} + + {{~{parse text}~}} + {{#if preview}} + {{> toggle}} + {{/if}} + diff --git a/client/views/toggle.tpl b/client/views/toggle.tpl index 2c8f84eb03..03659742bb 100644 --- a/client/views/toggle.tpl +++ b/client/views/toggle.tpl @@ -1,19 +1,18 @@ -{{#toggle}} -
+{{#preview}} +
+ +
+ {{#equal type "image"}} - - - + {{else}} - - {{#if thumb}} - - {{/if}} -
{{head}}
-
- {{body}} -
-
+ {{#if thumb}} + + {{/if}} +
{{head}}
+
+ {{body}} +
{{/equal}} -
-{{/toggle}} + +{{/preview}} diff --git a/src/plugins/irc-events/link.js b/src/plugins/irc-events/link.js index 04e84b759a..06a23232b3 100644 --- a/src/plugins/irc-events/link.js +++ b/src/plugins/irc-events/link.js @@ -8,12 +8,12 @@ const es = require("event-stream"); process.setMaxListeners(0); -module.exports = function(client, chan, originalMsg) { +module.exports = function(client, chan, msg) { if (!Helper.config.prefetch) { return; } - const links = originalMsg.text + const links = msg.text .replace(/\x02|\x1D|\x1F|\x16|\x0F|\x03(?:[0-9]{1,2}(?:,[0-9]{1,2})?)?/g, "") .split(" ") .filter((w) => /^https?:\/\//.test(w)); @@ -22,13 +22,6 @@ module.exports = function(client, chan, originalMsg) { return; } - const msg = new Msg({ - type: Msg.Type.TOGGLE, - time: originalMsg.time, - self: originalMsg.self, - }); - chan.pushMessage(client, msg); - const link = escapeHeader(links[0]); fetch(link, function(res) { if (res === null) { @@ -40,8 +33,7 @@ module.exports = function(client, chan, originalMsg) { }; function parse(msg, url, res, client) { - var toggle = msg.toggle = { - id: msg.id, + const preview = { type: "", head: "", body: "", @@ -52,35 +44,35 @@ function parse(msg, url, res, client) { switch (res.type) { case "text/html": var $ = cheerio.load(res.text); - toggle.type = "link"; - toggle.head = + preview.type = "link"; + preview.head = $("meta[property=\"og:title\"]").attr("content") || $("title").text() || ""; - toggle.body = + preview.body = $("meta[property=\"og:description\"]").attr("content") || $("meta[name=\"description\"]").attr("content") || ""; - toggle.thumb = + preview.thumb = $("meta[property=\"og:image\"]").attr("content") || $("meta[name=\"twitter:image:src\"]").attr("content") || ""; // Make sure thumbnail is a valid url - if (!/^https?:\/\//.test(toggle.thumb)) { - toggle.thumb = ""; + if (!/^https?:\/\//.test(preview.thumb)) { + preview.thumb = ""; } // Verify that thumbnail pic exists and is under allowed size - if (toggle.thumb.length) { - fetch(escapeHeader(toggle.thumb), (resThumb) => { + if (preview.thumb.length) { + fetch(escapeHeader(preview.thumb), (resThumb) => { if (resThumb === null || !(/^image\/.+/.test(resThumb.type)) || resThumb.size > (Helper.config.prefetchMaxImageSize * 1024)) { - toggle.thumb = ""; + preview.thumb = ""; } - emitToggle(client, toggle); + emitPreview(client, msg, preview); }); return; @@ -93,7 +85,7 @@ function parse(msg, url, res, client) { case "image/jpg": case "image/jpeg": if (res.size < (Helper.config.prefetchMaxImageSize * 1024)) { - toggle.type = "image"; + preview.type = "image"; } else { return; } @@ -103,21 +95,26 @@ function parse(msg, url, res, client) { return; } - emitToggle(client, toggle); + emitPreview(client, msg, preview); } -function emitToggle(client, toggle) { +function emitPreview(client, msg, preview) { // If there is no title but there is preview or description, set title // otherwise bail out and show no preview - if (!toggle.head.length) { - if (toggle.thumb.length || toggle.body.length) { - toggle.head = "Untitled page"; + if (!preview.head.length) { + if (preview.thumb.length || preview.body.length) { + preview.head = "Untitled page"; } else { return; } } - client.emit("toggle", toggle); + msg.preview = preview; + + client.emit("msg:preview", { + id: msg.id, + preview: preview + }); } function fetch(url, cb) {