Add file size to link preview
This commit is contained in:
parent
8a224809dd
commit
95cc9a47fb
34
client/components/LinkPreviewFileSize.vue
Normal file
34
client/components/LinkPreviewFileSize.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<span class="preview-size">({{ previewSize }})</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const constants = require("../js/constants");
|
||||
|
||||
export default {
|
||||
name: "LinkPreviewFileSize",
|
||||
props: {
|
||||
size: Number,
|
||||
},
|
||||
computed: {
|
||||
previewSize() {
|
||||
let size = this.size;
|
||||
|
||||
// Threshold for SI units
|
||||
const thresh = 1024;
|
||||
|
||||
let u = 0;
|
||||
|
||||
do {
|
||||
size /= thresh;
|
||||
++u;
|
||||
} while (size >= thresh && u < constants.sizeUnits.length - 1);
|
||||
|
||||
const displaySize = size.toFixed(1);
|
||||
const unit = constants.sizeUnits[u];
|
||||
|
||||
return `${displaySize} ${unit}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1475,6 +1475,11 @@ background on hover (unless active) */
|
||||
border-left: 1px solid var(--highlight-bg-color);
|
||||
}
|
||||
|
||||
#chat .preview-size {
|
||||
margin-left: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#chat .toggle-content.opened .more-caret, /* Expand/Collapse link previews */
|
||||
#chat .toggle-button.opened, /* Thumbnail toggle */
|
||||
#chat .msg.condensed:not(.closed) .toggle-button { /* Expanded status message toggle */
|
||||
|
@ -27,10 +27,13 @@ const timeFormats = {
|
||||
msgWithSeconds: "HH:mm:ss",
|
||||
};
|
||||
|
||||
const sizeUnits = ["B", "KiB", "MiB", "GiB", "TiB"];
|
||||
|
||||
module.exports = {
|
||||
colorCodeMap,
|
||||
commands: [],
|
||||
condensedTypes,
|
||||
condensedTypesQuery,
|
||||
timeFormats,
|
||||
sizeUnits,
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ const merge = require("./ircmessageparser/merge");
|
||||
const colorClass = require("./colorClass");
|
||||
const emojiMap = require("../fullnamemap.json");
|
||||
const LinkPreviewToggle = require("../../../components/LinkPreviewToggle.vue").default;
|
||||
const LinkPreviewFileSize = require("../../../components/LinkPreviewFileSize.vue").default;
|
||||
const emojiModifiersRegex = /[\u{1f3fb}-\u{1f3ff}]/gu;
|
||||
|
||||
// Create an HTML `span` with styling information for a given fragment
|
||||
@ -96,12 +97,16 @@ module.exports = function parse(createElement, text, message = undefined, networ
|
||||
|
||||
// Wrap these potentially styled fragments with links and channel buttons
|
||||
if (textPart.link) {
|
||||
const preview = message && message.previews.find((p) => p.link === textPart.link);
|
||||
const preview =
|
||||
message &&
|
||||
message.previews &&
|
||||
message.previews.find((p) => p.link === textPart.link);
|
||||
const link = createElement(
|
||||
"a",
|
||||
{
|
||||
attrs: {
|
||||
href: textPart.link,
|
||||
dir: preview ? null : "auto",
|
||||
target: "_blank",
|
||||
rel: "noopener",
|
||||
},
|
||||
@ -113,6 +118,28 @@ module.exports = function parse(createElement, text, message = undefined, networ
|
||||
return link;
|
||||
}
|
||||
|
||||
const linkEls = [link];
|
||||
|
||||
if (preview.size > 0) {
|
||||
linkEls.push(
|
||||
createElement(LinkPreviewFileSize, {
|
||||
props: {
|
||||
size: preview.size,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
linkEls.push(
|
||||
createElement(LinkPreviewToggle, {
|
||||
props: {
|
||||
link: preview,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// We wrap the link, size, and the toggle button into <span dir="auto">
|
||||
// to correctly keep the left-to-right order of these elements
|
||||
return createElement(
|
||||
"span",
|
||||
{
|
||||
@ -120,19 +147,7 @@ module.exports = function parse(createElement, text, message = undefined, networ
|
||||
dir: "auto",
|
||||
},
|
||||
},
|
||||
[
|
||||
link,
|
||||
createElement(
|
||||
LinkPreviewToggle,
|
||||
{
|
||||
class: ["toggle-button", "toggle-preview"],
|
||||
props: {
|
||||
link: preview,
|
||||
},
|
||||
},
|
||||
fragments
|
||||
),
|
||||
]
|
||||
linkEls
|
||||
);
|
||||
} else if (textPart.channel) {
|
||||
return createElement(
|
||||
|
@ -43,6 +43,7 @@ module.exports = function(client, chan, msg) {
|
||||
head: "",
|
||||
body: "",
|
||||
thumb: "",
|
||||
size: -1,
|
||||
link: link.link, // Send original matched link to the client
|
||||
shown: true,
|
||||
};
|
||||
@ -181,8 +182,11 @@ function parseHtmlMedia($, preview, client) {
|
||||
function parse(msg, chan, preview, res, client) {
|
||||
let promise;
|
||||
|
||||
preview.size = res.size;
|
||||
|
||||
switch (res.type) {
|
||||
case "text/html":
|
||||
preview.size = -1;
|
||||
promise = parseHtml(preview, res, client);
|
||||
break;
|
||||
|
||||
|
@ -25,7 +25,7 @@ describe("parse Handlebars helper", () => {
|
||||
{
|
||||
input: "<img onerror='location.href=\"//youtube.com\"'>",
|
||||
expected:
|
||||
'<img onerror=\'location.href="<a href="http://youtube.com" target="_blank" rel="noopener">//youtube.com</a>"\'>',
|
||||
'<img onerror=\'location.href="<a href="http://youtube.com" dir="auto" target="_blank" rel="noopener">//youtube.com</a>"\'>',
|
||||
},
|
||||
{
|
||||
input: '#&">bug',
|
||||
@ -61,14 +61,14 @@ describe("parse Handlebars helper", () => {
|
||||
{
|
||||
input: "irc://freenode.net/thelounge",
|
||||
expected:
|
||||
'<a href="irc://freenode.net/thelounge" target="_blank" rel="noopener">' +
|
||||
'<a href="irc://freenode.net/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
||||
"irc://freenode.net/thelounge" +
|
||||
"</a>",
|
||||
},
|
||||
{
|
||||
input: "www.nooooooooooooooo.com",
|
||||
expected:
|
||||
'<a href="http://www.nooooooooooooooo.com" target="_blank" rel="noopener">' +
|
||||
'<a href="http://www.nooooooooooooooo.com" dir="auto" target="_blank" rel="noopener">' +
|
||||
"www.nooooooooooooooo.com" +
|
||||
"</a>",
|
||||
},
|
||||
@ -76,7 +76,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "look at https://thelounge.chat/ for more information",
|
||||
expected:
|
||||
"look at " +
|
||||
'<a href="https://thelounge.chat/" target="_blank" rel="noopener">' +
|
||||
'<a href="https://thelounge.chat/" dir="auto" target="_blank" rel="noopener">' +
|
||||
"https://thelounge.chat/" +
|
||||
"</a>" +
|
||||
" for more information",
|
||||
@ -85,7 +85,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "use www.duckduckgo.com for privacy reasons",
|
||||
expected:
|
||||
"use " +
|
||||
'<a href="http://www.duckduckgo.com" target="_blank" rel="noopener">' +
|
||||
'<a href="http://www.duckduckgo.com" dir="auto" target="_blank" rel="noopener">' +
|
||||
"www.duckduckgo.com" +
|
||||
"</a>" +
|
||||
" for privacy reasons",
|
||||
@ -93,7 +93,7 @@ describe("parse Handlebars helper", () => {
|
||||
{
|
||||
input: "svn+ssh://example.org",
|
||||
expected:
|
||||
'<a href="svn+ssh://example.org" target="_blank" rel="noopener">' +
|
||||
'<a href="svn+ssh://example.org" dir="auto" target="_blank" rel="noopener">' +
|
||||
"svn+ssh://example.org" +
|
||||
"</a>",
|
||||
},
|
||||
@ -110,7 +110,7 @@ describe("parse Handlebars helper", () => {
|
||||
"bonuspunkt: your URL parser misparses this URL: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx";
|
||||
const correctResult =
|
||||
"bonuspunkt: your URL parser misparses this URL: " +
|
||||
'<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" target="_blank" rel="noopener">' +
|
||||
'<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" dir="auto" target="_blank" rel="noopener">' +
|
||||
"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" +
|
||||
"</a>";
|
||||
|
||||
@ -125,7 +125,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "<https://theos.kyriasis.com/~kyrias/stats/archlinux.html>",
|
||||
expected:
|
||||
"<" +
|
||||
'<a href="https://theos.kyriasis.com/~kyrias/stats/archlinux.html" target="_blank" rel="noopener">' +
|
||||
'<a href="https://theos.kyriasis.com/~kyrias/stats/archlinux.html" dir="auto" target="_blank" rel="noopener">' +
|
||||
"https://theos.kyriasis.com/~kyrias/stats/archlinux.html" +
|
||||
"</a>" +
|
||||
">",
|
||||
@ -134,7 +134,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "abc (www.example.com)",
|
||||
expected:
|
||||
"abc (" +
|
||||
'<a href="http://www.example.com" target="_blank" rel="noopener">' +
|
||||
'<a href="http://www.example.com" dir="auto" target="_blank" rel="noopener">' +
|
||||
"www.example.com" +
|
||||
"</a>" +
|
||||
")",
|
||||
@ -142,14 +142,14 @@ describe("parse Handlebars helper", () => {
|
||||
{
|
||||
input: "http://example.com/Test_(Page)",
|
||||
expected:
|
||||
'<a href="http://example.com/Test_(Page)" target="_blank" rel="noopener">' +
|
||||
'<a href="http://example.com/Test_(Page)" dir="auto" target="_blank" rel="noopener">' +
|
||||
"http://example.com/Test_(Page)" +
|
||||
"</a>",
|
||||
},
|
||||
{
|
||||
input: "www.example.com/Test_(Page)",
|
||||
expected:
|
||||
'<a href="http://www.example.com/Test_(Page)" target="_blank" rel="noopener">' +
|
||||
'<a href="http://www.example.com/Test_(Page)" dir="auto" target="_blank" rel="noopener">' +
|
||||
"www.example.com/Test_(Page)" +
|
||||
"</a>",
|
||||
},
|
||||
@ -386,7 +386,7 @@ describe("parse Handlebars helper", () => {
|
||||
users: ["MaxLeiter, test"],
|
||||
input: "https://www.MaxLeiter.com/test",
|
||||
expected:
|
||||
'<a href="https://www.MaxLeiter.com/test" target="_blank" rel="noopener">' +
|
||||
'<a href="https://www.MaxLeiter.com/test" dir="auto" target="_blank" rel="noopener">' +
|
||||
"https://www.MaxLeiter.com/test" +
|
||||
"</a>",
|
||||
},
|
||||
@ -403,7 +403,7 @@ describe("parse Handlebars helper", () => {
|
||||
{
|
||||
input: "\x02irc\x0f://\x1dfreenode.net\x0f/\x034,8thelounge",
|
||||
expected:
|
||||
'<a href="irc://freenode.net/thelounge" target="_blank" rel="noopener">' +
|
||||
'<a href="irc://freenode.net/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
||||
'<span class="irc-bold">irc</span>' +
|
||||
"://" +
|
||||
'<span class="irc-italic">freenode.net</span>' +
|
||||
@ -470,7 +470,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "https://i.❤️.thelounge.chat",
|
||||
// FIXME: Emoji in text should be `<span class="emoji">❤️</span>`. See https://github.com/thelounge/thelounge/issues/1784
|
||||
expected:
|
||||
'<a href="https://i.❤️.thelounge.chat" target="_blank" rel="noopener">https://i.❤️.thelounge.chat</a>',
|
||||
'<a href="https://i.❤️.thelounge.chat" dir="auto" target="_blank" rel="noopener">https://i.❤️.thelounge.chat</a>',
|
||||
},
|
||||
{
|
||||
name: "wrapped in channels",
|
||||
@ -511,7 +511,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "like..http://example.com",
|
||||
expected:
|
||||
"like.." +
|
||||
'<a href="http://example.com" target="_blank" rel="noopener">' +
|
||||
'<a href="http://example.com" dir="auto" target="_blank" rel="noopener">' +
|
||||
"http://example.com" +
|
||||
"</a>",
|
||||
},
|
||||
@ -519,7 +519,7 @@ describe("parse Handlebars helper", () => {
|
||||
input: "like..HTTP://example.com",
|
||||
expected:
|
||||
"like.." +
|
||||
'<a href="HTTP://example.com" target="_blank" rel="noopener">' +
|
||||
'<a href="HTTP://example.com" dir="auto" target="_blank" rel="noopener">' +
|
||||
"HTTP://example.com" +
|
||||
"</a>",
|
||||
},
|
||||
@ -536,7 +536,7 @@ describe("parse Handlebars helper", () => {
|
||||
{
|
||||
input: "http://example.com/#hash",
|
||||
expected:
|
||||
'<a href="http://example.com/#hash" target="_blank" rel="noopener">' +
|
||||
'<a href="http://example.com/#hash" dir="auto" target="_blank" rel="noopener">' +
|
||||
"http://example.com/#hash" +
|
||||
"</a>",
|
||||
},
|
||||
@ -553,7 +553,7 @@ describe("parse Handlebars helper", () => {
|
||||
const actual = getParsedMessageContents(input);
|
||||
|
||||
expect(actual).to.equal(
|
||||
'Url: <a href="http://example.com/path" target="_blank" rel="noopener">http://example.com/path</a> ' +
|
||||
'Url: <a href="http://example.com/path" dir="auto" target="_blank" rel="noopener">http://example.com/path</a> ' +
|
||||
'Channel: <span role="button" dir="auto" tabindex="0" data-chan="##channel" class="inline-channel">##channel</span>'
|
||||
);
|
||||
});
|
||||
|
@ -45,6 +45,7 @@ describe("Link plugin", function() {
|
||||
head: "",
|
||||
link: url,
|
||||
thumb: "",
|
||||
size: -1,
|
||||
type: "loading",
|
||||
shown: true,
|
||||
},
|
||||
@ -278,6 +279,7 @@ describe("Link plugin", function() {
|
||||
expect(data.preview.thumb).to.equal(
|
||||
"http://localhost:" + port + "/real-test-image.png"
|
||||
);
|
||||
expect(data.preview.size).to.equal(960);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -296,6 +298,7 @@ describe("Link plugin", function() {
|
||||
head: "",
|
||||
link: "http://localhost:" + port + "/one",
|
||||
thumb: "",
|
||||
size: -1,
|
||||
type: "loading",
|
||||
shown: true,
|
||||
},
|
||||
@ -304,6 +307,7 @@ describe("Link plugin", function() {
|
||||
head: "",
|
||||
link: "http://localhost:" + port + "/two",
|
||||
thumb: "",
|
||||
size: -1,
|
||||
type: "loading",
|
||||
shown: true,
|
||||
},
|
||||
@ -496,6 +500,7 @@ describe("Link plugin", function() {
|
||||
head: "",
|
||||
body: "",
|
||||
thumb: "",
|
||||
size: -1,
|
||||
link: "http://localhost:" + port + "",
|
||||
shown: true,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user