Move preview toggle buttons next to their respective URLs and switch from ellipsis to caret

This commit is contained in:
Jérémie Astori 2017-07-06 03:35:54 -04:00
parent 64ebe0f437
commit 28200830ed
No known key found for this signature in database
GPG key ID: B9A4F245CD67BDE8
7 changed files with 57 additions and 31 deletions

View file

@ -205,6 +205,7 @@ kbd {
#chat .whois .from:before, #chat .whois .from:before,
#chat .nick .from:before, #chat .nick .from:before,
#chat .action .from:before, #chat .action .from:before,
#chat .toggle-button:after,
.context-menu-item:before, .context-menu-item:before,
#nick button:before { #nick button:before {
font: normal normal normal 14px/1 FontAwesome; font: normal normal normal 14px/1 FontAwesome;
@ -293,6 +294,16 @@ kbd {
content: "\f005"; /* http://fontawesome.io/icon/star/ */ content: "\f005"; /* http://fontawesome.io/icon/star/ */
} }
#chat .toggle-button {
/* These 2 directives are loosely taken from .fa-fw */
width: 1.35em;
text-align: center;
}
#chat .toggle-button:after {
content: "\f0da"; /* http://fontawesome.io/icon/caret-right/ */
}
#chat .count:before { #chat .count:before {
color: #cfcfcf; color: #cfcfcf;
content: "\f002"; /* http://fontawesome.io/icon/search/ */ content: "\f002"; /* http://fontawesome.io/icon/search/ */
@ -1097,17 +1108,18 @@ kbd {
} }
#chat .toggle-button { #chat .toggle-button {
background: #f5f5f5;
border-radius: 2px;
display: inline-block; display: inline-block;
color: #666; color: #666;
height: 1em; transition: color .2s, transform .2s;
line-height: 0;
padding: 0 6px;
} }
#chat .toggle-button:after { #chat .toggle-button.opened {
content: "···"; transform: rotate(90deg);
}
#chat .toggle-button:hover {
/* transform and opacity together glitch, so need to use RGBA transition */
color: rgba(102, 102, 102, .8); /* #666 x .8 opacity */
} }
#chat .toggle-content { #chat .toggle-content {
@ -1118,7 +1130,7 @@ kbd {
font-size: 12px; font-size: 12px;
max-width: 100%; max-width: 100%;
padding: 6px; padding: 6px;
margin-top: 2px; margin: 2px 0;
overflow: hidden; overflow: hidden;
} }

View file

@ -83,6 +83,6 @@ module.exports = function parse(text) {
return fragments; return fragments;
}).join("") + linkParts.map((part) => { }).join("") + linkParts.map((part) => {
const escapedLink = Handlebars.Utils.escapeExpression(part.link); const escapedLink = Handlebars.Utils.escapeExpression(part.link);
return `<div data-url="${escapedLink}"></div>`; return `<div class="preview" data-url="${escapedLink}"></div>`;
}).join(""); }).join("");
}; };

View file

@ -16,7 +16,11 @@ function renderPreview(preview, msg) {
bottom = container.isScrollBottom(); bottom = container.isScrollBottom();
} }
msg.find(`[data-url="${preview.link}"]`) msg.find(`.text a[href="${preview.link}"]`)
.first()
.after(templates.msg_preview_toggle({preview: preview}));
msg.find(`.preview[data-url="${preview.link}"]`)
.first() .first()
.append(templates.msg_preview({preview: preview})); .append(templates.msg_preview({preview: preview}));
@ -30,13 +34,15 @@ function renderPreview(preview, msg) {
$("#chat").on("click", ".toggle-button", function() { $("#chat").on("click", ".toggle-button", function() {
const self = $(this); const self = $(this);
const container = self.closest(".chat"); const container = self.closest(".chat");
const content = self.parent().next(".toggle-content"); const content = self.closest(".text")
.find(`.preview[data-url="${self.data("url")}"] .toggle-content`);
const bottom = container.isScrollBottom(); const bottom = container.isScrollBottom();
if (bottom && !content.hasClass("show")) { if (bottom && !content.hasClass("show")) {
handleImageInPreview(content, container); handleImageInPreview(content, container);
} }
self.toggleClass("opened");
content.toggleClass("show"); content.toggleClass("show");
// If scrollbar was at the bottom before toggling the preview, keep it at the bottom // If scrollbar was at the bottom before toggling the preview, keep it at the bottom

View file

@ -26,6 +26,7 @@ module.exports = {
msg: require("./msg.tpl"), msg: require("./msg.tpl"),
msg_action: require("./msg_action.tpl"), msg_action: require("./msg_action.tpl"),
msg_preview: require("./msg_preview.tpl"), msg_preview: require("./msg_preview.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"),
unread_marker: require("./unread_marker.tpl"), unread_marker: require("./unread_marker.tpl"),

View file

@ -1,7 +1,4 @@
{{#preview}} {{#preview}}
<div>
<button class="toggle-button" aria-label="Toggle prefetched media"></button>
</div>
<a href="{{link}}" target="_blank" rel="noopener" class="toggle-content toggle-type-{{type}}{{#if shown}} show{{/if}}"> <a href="{{link}}" target="_blank" rel="noopener" class="toggle-content toggle-type-{{type}}{{#if shown}} show{{/if}}">
{{#equal type "image"}} {{#equal type "image"}}
<img src="{{link}}"> <img src="{{link}}">

View file

@ -0,0 +1,10 @@
{{#preview}}
<button class="toggle-button {{#if shown}} opened{{/if}}"
data-url="{{link}}"
{{#equal type "image"}}
aria-label="Toggle image preview"
{{else}}
aria-label="Toggle website preview"
{{/equal}}
></button>
{{/preview}}

View file

@ -38,14 +38,14 @@ describe("parse Handlebars helper", () => {
"<a href=\"irc://freenode.net/thelounge\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"irc://freenode.net/thelounge\" target=\"_blank\" rel=\"noopener\">" +
"irc://freenode.net/thelounge" + "irc://freenode.net/thelounge" +
"</a>" + "</a>" +
"<div data-url=\"irc://freenode.net/thelounge\"></div>" "<div class=\"preview\" data-url=\"irc://freenode.net/thelounge\"></div>"
}, { }, {
input: "www.nooooooooooooooo.com", input: "www.nooooooooooooooo.com",
expected: expected:
"<a href=\"http://www.nooooooooooooooo.com\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"http://www.nooooooooooooooo.com\" target=\"_blank\" rel=\"noopener\">" +
"www.nooooooooooooooo.com" + "www.nooooooooooooooo.com" +
"</a>" + "</a>" +
"<div data-url=\"http://www.nooooooooooooooo.com\"></div>" "<div class=\"preview\" data-url=\"http://www.nooooooooooooooo.com\"></div>"
}, { }, {
input: "look at https://thelounge.github.io/ for more information", input: "look at https://thelounge.github.io/ for more information",
expected: expected:
@ -54,7 +54,7 @@ describe("parse Handlebars helper", () => {
"https://thelounge.github.io/" + "https://thelounge.github.io/" +
"</a>" + "</a>" +
" for more information" + " for more information" +
"<div data-url=\"https://thelounge.github.io/\"></div>" "<div class=\"preview\" data-url=\"https://thelounge.github.io/\"></div>"
}, { }, {
input: "use www.duckduckgo.com for privacy reasons", input: "use www.duckduckgo.com for privacy reasons",
expected: expected:
@ -63,14 +63,14 @@ describe("parse Handlebars helper", () => {
"www.duckduckgo.com" + "www.duckduckgo.com" +
"</a>" + "</a>" +
" for privacy reasons" + " for privacy reasons" +
"<div data-url=\"http://www.duckduckgo.com\"></div>" "<div class=\"preview\" data-url=\"http://www.duckduckgo.com\"></div>"
}, { }, {
input: "svn+ssh://example.org", input: "svn+ssh://example.org",
expected: expected:
"<a href=\"svn+ssh://example.org\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"svn+ssh://example.org\" target=\"_blank\" rel=\"noopener\">" +
"svn+ssh://example.org" + "svn+ssh://example.org" +
"</a>" + "</a>" +
"<div data-url=\"svn+ssh://example.org\"></div>" "<div class=\"preview\" data-url=\"svn+ssh://example.org\"></div>"
}, { }, {
input: "https://example.com https://example.org", input: "https://example.com https://example.org",
expected: expected:
@ -80,8 +80,8 @@ describe("parse Handlebars helper", () => {
"<a href=\"https://example.org\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"https://example.org\" target=\"_blank\" rel=\"noopener\">" +
"https://example.org" + "https://example.org" +
"</a>" + "</a>" +
"<div data-url=\"https://example.com\"></div>" + "<div class=\"preview\" data-url=\"https://example.com\"></div>" +
"<div data-url=\"https://example.org\"></div>" "<div class=\"preview\" data-url=\"https://example.org\"></div>"
}]; }];
const actual = testCases.map((testCase) => parse(testCase.input)); const actual = testCases.map((testCase) => parse(testCase.input));
@ -98,7 +98,7 @@ describe("parse Handlebars helper", () => {
"<a href=\"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v&#x3D;vs.85).aspx\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v&#x3D;vs.85).aspx\" target=\"_blank\" rel=\"noopener\">" +
"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v&#x3D;vs.85).aspx" + "https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v&#x3D;vs.85).aspx" +
"</a>" + "</a>" +
"<div data-url=\"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v&#x3D;vs.85).aspx\"></div>"; "<div class=\"preview\" data-url=\"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v&#x3D;vs.85).aspx\"></div>";
const actual = parse(input); const actual = parse(input);
@ -114,7 +114,7 @@ describe("parse Handlebars helper", () => {
"https://theos.kyriasis.com/~kyrias/stats/archlinux.html" + "https://theos.kyriasis.com/~kyrias/stats/archlinux.html" +
"</a>" + "</a>" +
"&gt;" + "&gt;" +
"<div data-url=\"https://theos.kyriasis.com/~kyrias/stats/archlinux.html\"></div>" "<div class=\"preview\" data-url=\"https://theos.kyriasis.com/~kyrias/stats/archlinux.html\"></div>"
}, { }, {
input: "abc (www.example.com)", input: "abc (www.example.com)",
expected: expected:
@ -123,21 +123,21 @@ describe("parse Handlebars helper", () => {
"www.example.com" + "www.example.com" +
"</a>" + "</a>" +
")" + ")" +
"<div data-url=\"http://www.example.com\"></div>" "<div class=\"preview\" data-url=\"http://www.example.com\"></div>"
}, { }, {
input: "http://example.com/Test_(Page)", input: "http://example.com/Test_(Page)",
expected: expected:
"<a href=\"http://example.com/Test_(Page)\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"http://example.com/Test_(Page)\" target=\"_blank\" rel=\"noopener\">" +
"http://example.com/Test_(Page)" + "http://example.com/Test_(Page)" +
"</a>" + "</a>" +
"<div data-url=\"http://example.com/Test_(Page)\"></div>" "<div class=\"preview\" data-url=\"http://example.com/Test_(Page)\"></div>"
}, { }, {
input: "www.example.com/Test_(Page)", input: "www.example.com/Test_(Page)",
expected: expected:
"<a href=\"http://www.example.com/Test_(Page)\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"http://www.example.com/Test_(Page)\" target=\"_blank\" rel=\"noopener\">" +
"www.example.com/Test_(Page)" + "www.example.com/Test_(Page)" +
"</a>" + "</a>" +
"<div data-url=\"http://www.example.com/Test_(Page)\"></div>" "<div class=\"preview\" data-url=\"http://www.example.com/Test_(Page)\"></div>"
}]; }];
const actual = testCases.map((testCase) => parse(testCase.input)); const actual = testCases.map((testCase) => parse(testCase.input));
@ -275,7 +275,7 @@ describe("parse Handlebars helper", () => {
"/" + "/" +
"<span class=\"irc-fg4 irc-bg8\">thelounge</span>" + "<span class=\"irc-fg4 irc-bg8\">thelounge</span>" +
"</a>" + "</a>" +
"<div data-url=\"irc://freenode.net/thelounge\"></div>" "<div class=\"preview\" data-url=\"irc://freenode.net/thelounge\"></div>"
}, { }, {
input: "\x02#\x038,9thelounge", input: "\x02#\x038,9thelounge",
expected: expected:
@ -315,7 +315,7 @@ describe("parse Handlebars helper", () => {
"<a href=\"http://example.com\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"http://example.com\" target=\"_blank\" rel=\"noopener\">" +
"http://example.com" + "http://example.com" +
"</a>" + "</a>" +
"<div data-url=\"http://example.com\"></div>" "<div class=\"preview\" data-url=\"http://example.com\"></div>"
}, { }, {
input: "like..HTTP://example.com", input: "like..HTTP://example.com",
expected: expected:
@ -323,7 +323,7 @@ describe("parse Handlebars helper", () => {
"<a href=\"HTTP://example.com\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"HTTP://example.com\" target=\"_blank\" rel=\"noopener\">" +
"HTTP://example.com" + "HTTP://example.com" +
"</a>" + "</a>" +
"<div data-url=\"HTTP://example.com\"></div>" "<div class=\"preview\" data-url=\"HTTP://example.com\"></div>"
}]; }];
const actual = testCases.map((testCase) => parse(testCase.input)); const actual = testCases.map((testCase) => parse(testCase.input));
@ -340,7 +340,7 @@ describe("parse Handlebars helper", () => {
"<a href=\"http://example.com/#hash\" target=\"_blank\" rel=\"noopener\">" + "<a href=\"http://example.com/#hash\" target=\"_blank\" rel=\"noopener\">" +
"http://example.com/#hash" + "http://example.com/#hash" +
"</a>" + "</a>" +
"<div data-url=\"http://example.com/#hash\"></div>" "<div class=\"preview\" data-url=\"http://example.com/#hash\"></div>"
}]; }];
const actual = testCases.map((testCase) => parse(testCase.input)); const actual = testCases.map((testCase) => parse(testCase.input));
@ -356,7 +356,7 @@ describe("parse Handlebars helper", () => {
expect(actual).to.equal( 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\" target=\"_blank\" rel=\"noopener\">http://example.com/path</a> " +
"Channel: <span class=\"inline-channel\" role=\"button\" tabindex=\"0\" data-chan=\"##channel\">##channel</span>" + "Channel: <span class=\"inline-channel\" role=\"button\" tabindex=\"0\" data-chan=\"##channel\">##channel</span>" +
"<div data-url=\"http://example.com/path\"></div>" "<div class=\"preview\" data-url=\"http://example.com/path\"></div>"
); );
}); });
}); });