diff --git a/assets/main.css b/assets/main.css index 3669db7..0350186 100644 --- a/assets/main.css +++ b/assets/main.css @@ -199,22 +199,30 @@ ul#server_selection_list { } .post { - margin: 1em 0; + margin: 1em 0 0.2em; display: grid; grid-template-rows: auto auto; grid-template-columns: auto auto; } +.post.same_author { + margin-top: 0.2em; +} .post:first-child { margin-top: 8px; } .post:last-child { margin-bottom: 8px; } +.post:hover { + background-color: #e4e4e4; +} .post .author { grid-row: 1; grid-column: 1; font-size: 80%; + font-weight: bold; + align-self: end; } .post.same_author .author { display: none; @@ -224,18 +232,32 @@ ul#server_selection_list { text-align: right; grid-row: 1; grid-column: 2; + font-size: 80%; color: #888; + align-self: end; } .post.same_author .create_at { display: none; } .post .message { + line-height: 1.2; grid-row: 2; grid-column-start: 1; grid-column-end: 3; } +.post ul.attachments { + margin: 0; + padding: 0; + list-style: none; + font-size: 80%; +} +.post ul.attachments img { + margin-left: 0.5em; + vertical-align: middle; +} + .channel-contents-message { text-align: center; width: 100%; diff --git a/js/util.js b/js/util.js index e0f18b8..31683dd 100644 --- a/js/util.js +++ b/js/util.js @@ -55,6 +55,44 @@ function extend(obj1, obj2) { } +function padLeft(input, width, padding=" ") { + text = input + ""; + while (text.length < width) { + text = padding + text; + } + return text; +} + +function formatDdddMmYy(date) { + return `${date.getFullYear()}-${padLeft(date.getMonth() + 1, 2, "0")}-${padLeft(date.getDate(), 2, "0")}`; +} + +function formatHhMm(date) { + return `${padLeft(date.getHours(), 2, "0")}:${padLeft(date.getMinutes(), 2, "0")}`; +} + + +const DATE_SIMILARITY = { + none: 0, + year: 1, + month: 2, + date: 3, + hours: 4, + minutes: 5, + seconds: 6 +} +function dateSimilarity(d1, d2) { + if (!d1 || !d2) return DATE_SIMILARITY.none; + if (d1.getFullYear() != d2.getFullYear()) return DATE_SIMILARITY.none; + if (d1.getMonth() != d2.getMonth()) return DATE_SIMILARITY.year; + if (d1.getDate() != d2.getDate()) return DATE_SIMILARITY.month; + if (d1.getHours() != d2.getHours()) return DATE_SIMILARITY.date; + if (d1.getMinutes() != d2.getMinutes()) return DATE_SIMILARITY.hours; + if (d1.getSeconds() != d2.getSeconds()) return DATE_SIMILARITY.minutes; + return DATE_SIMILARITY.seconds; +} + + class AssertionError extends Error {} /** * Throw an AssertionError if the first argument is not true diff --git a/js/view/view.js b/js/view/view.js index 9600084..73635c9 100644 --- a/js/view/view.js +++ b/js/view/view.js @@ -60,6 +60,8 @@ function populateChannelContents(client, contents) { byId("channel_contents").innerHTML = ""; let lastAuthor = null; + let lastTime = null; + let nodes = []; for (let id of contents.order) { const post = contents.posts[id]; @@ -73,7 +75,12 @@ function populateChannelContents(client, contents) { const createAt = new Date(post.create_at); const createAtDiv = document.createElement("time"); createAtDiv.className = "create_at"; - createAtDiv.innerText = createAt.toLocaleString("nl-BE"); + const sim = dateSimilarity(lastTime, createAt); + lastTime = createAt; + let createAtText = ""; + if (sim < DATE_SIMILARITY.date) createAtText += formatDdddMmYy(createAt); + if (sim < DATE_SIMILARITY.minutes) createAtText += " " + formatHhMm(createAt); + createAtDiv.innerText = createAtText; createAtDiv.dateTime = createAt.toISOString(); const authorName = users[post.user_id] ? users[post.user_id].username : post.user_id;