Merge pull request #1366 from thelounge/astorije/persist-preview-toggle

Keep track of preview visibility on the server so it persists at page reload
This commit is contained in:
Jérémie Astori 2017-07-26 18:26:12 -04:00 committed by GitHub
commit 8aa89d7da2
9 changed files with 126 additions and 27 deletions

View file

@ -36,10 +36,6 @@ function buildChatMessage(data) {
target = "#chan-" + chat.find(".active").data("id");
}
data.msg.previews.forEach((preview) => {
preview.shown = options.shouldOpenMessagePreview(preview.type);
});
const chan = chat.find(target);
let template = "msg";

View file

@ -2,6 +2,7 @@
const $ = require("jquery");
const options = require("./options");
const socket = require("./socket");
const templates = require("../views");
const input = $("#input");
@ -24,7 +25,7 @@ function renderPreview(preview, msg) {
return;
}
preview.shown = options.shouldOpenMessagePreview(preview.type);
preview.shown = preview.shown && options.shouldOpenMessagePreview(preview.type);
const container = msg.closest(".chat");
let bottom = false;
@ -60,6 +61,16 @@ $("#chat").on("click", ".toggle-button", function() {
self.toggleClass("opened");
content.toggleClass("show");
// Tell the server we're toggling so it remembers at page reload
// TODO Avoid sending many single events when using `/collapse` or `/expand`
// See https://github.com/thelounge/lounge/issues/1377
socket.emit("msg:preview:toggle", {
target: parseInt(self.closest(".chan").data("id"), 10),
msgId: parseInt(self.closest(".msg").attr("id").replace("msg-", ""), 10),
link: self.data("url"),
shown: content.hasClass("show"),
});
// If scrollbar was at the bottom before toggling the preview, keep it at the bottom
if (bottom) {
container.scrollBottom();

View file

@ -93,6 +93,10 @@ Chan.prototype.sortUsers = function(irc) {
});
};
Chan.prototype.findMessage = function(msgId) {
return this.messages.find((message) => message.id === msgId);
};
Chan.prototype.findUser = function(nick) {
return _.find(this.users, {nick: nick});
};

View file

@ -2,6 +2,31 @@
var _ = require("lodash");
var id = 0;
class Msg {
constructor(attr) {
_.defaults(this, attr, {
from: "",
id: id++,
previews: [],
text: "",
type: Msg.Type.MESSAGE,
self: false
});
if (this.time > 0) {
this.time = new Date(this.time);
} else {
this.time = new Date();
}
}
findPreview(link) {
return this.previews.find((preview) => preview.link === link);
}
}
Msg.Type = {
UNHANDLED: "unhandled",
ACTION: "action",
@ -24,22 +49,3 @@ Msg.Type = {
};
module.exports = Msg;
var id = 0;
function Msg(attr) {
_.defaults(this, attr, {
from: "",
id: id++,
previews: [],
text: "",
type: Msg.Type.MESSAGE,
self: false
});
if (this.time > 0) {
this.time = new Date(this.time);
} else {
this.time = new Date();
}
}

View file

@ -32,6 +32,7 @@ module.exports = function(client, chan, msg) {
body: "",
thumb: "",
link: link,
shown: true,
})).slice(0, 5); // Only preview the first 5 URLs in message to avoid abuse
msg.previews.forEach((preview) => {

View file

@ -280,6 +280,26 @@ function init(socket, client) {
client.names(data);
}
);
socket.on("msg:preview:toggle", function(data) {
const networkAndChan = client.find(data.target);
if (!networkAndChan) {
return;
}
const message = networkAndChan.chan.findMessage(data.msgId);
if (!message) {
return;
}
const preview = message.findPreview(data.link);
if (preview) {
preview.shown = data.shown;
}
});
socket.join(client.id);
socket.emit("init", {
active: client.lastActiveChannel,

View file

@ -3,9 +3,30 @@
var expect = require("chai").expect;
var Chan = require("../../src/models/chan");
var Msg = require("../../src/models/msg");
var User = require("../../src/models/user");
describe("Chan", function() {
describe("#findMessage(id)", function() {
const chan = new Chan({
messages: [
new Msg(),
new Msg({
text: "Message to be found"
}),
new Msg()
]
});
it("should find a message in the list of messages", function() {
expect(chan.findMessage(1).text).to.equal("Message to be found");
});
it("should not find a message that does not exist", function() {
expect(chan.findMessage(42)).to.be.undefined;
});
});
describe("#sortUsers(irc)", function() {
var network = {
network: {

37
test/models/msg.js Normal file
View file

@ -0,0 +1,37 @@
"use strict";
const expect = require("chai").expect;
const Msg = require("../../src/models/msg");
describe("Msg", function() {
describe("#findPreview(link)", function() {
const msg = new Msg({
previews: [{
body: "",
head: "Example Domain",
link: "https://example.org/",
thumb: "",
type: "link",
shown: true,
}, {
body: "",
head: "The Lounge",
link: "https://thelounge.github.io/",
thumb: "",
type: "link",
shown: true,
}]
});
it("should find a preview given an existing link", function() {
expect(msg.findPreview("https://thelounge.github.io/").head)
.to.equal("The Lounge");
});
it("should not find a preview that does not exist", function() {
expect(msg.findPreview("https://github.com/thelounge/lounge"))
.to.be.undefined;
});
});
});

View file

@ -39,7 +39,8 @@ describe("Link plugin", function() {
head: "",
link: url,
thumb: "",
type: "loading"
type: "loading",
shown: true,
}]);
this.app.get("/basic", function(req, res) {
@ -193,13 +194,15 @@ describe("Link plugin", function() {
head: "",
link: "http://localhost:9002/one",
thumb: "",
type: "loading"
type: "loading",
shown: true,
}, {
body: "",
head: "",
link: "http://localhost:9002/two",
thumb: "",
type: "loading"
type: "loading",
shown: true,
}]);
this.app.get("/one", function(req, res) {