diff options
Diffstat (limited to 'public/assets/js/lib/views/stream/hootstream.js')
| -rw-r--r-- | public/assets/js/lib/views/stream/hootstream.js | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/public/assets/js/lib/views/stream/hootstream.js b/public/assets/js/lib/views/stream/hootstream.js new file mode 100644 index 0000000..cdc7acf --- /dev/null +++ b/public/assets/js/lib/views/stream/hootstream.js @@ -0,0 +1,205 @@ +const IMAGE_REGEXP = /(.gif|.jpg|.jpeg|.png)$/gi; + +var HootStream = View.extend({ + el: "#hootstream", + + initialize: function ({ parent }) { + this.parent = parent; + this.$hootevents = this.$("#hootevents"); + this.hootTemplate = this.$(".hootTemplate").html(); + this.lastlogTemplate = this.$(".lastlogTemplate").html(); + this.fileTemplate = this.$(".fileTemplate").html(); + }, + + load: function (data) { + this.$hootevents.empty(); + const { order, threadLookup } = this.agglutinate(data); + console.log(data, threadLookup, order); + const $els = order.map( + function (item) { + return item.type === "thread" + ? this.renderThread(threadLookup[item.thread_id]).reduce( + ($el, $item) => $el.append($item), + $("<div class='thread'>") + ) + : item.type === "hoot" + ? this.renderHoot(item.data) + : item.type === "lastlog" + ? this.renderLastlog(item.data) + : "Unknown item"; + }.bind(this) + ); + this.$hootevents.append($els); + }, + + render: (template, object) => { + const rendered = Object.entries(object).reduce( + (newTemplate, [key, value]) => + newTemplate.replace(new RegExp(`{{${key}}}`, "g"), value), + template + ); + return $(rendered); + }, + + renderLastlog: function ({ username, lastseen }) { + const age = get_age(lastseen); + const age_ago = age === "now" ? age : `${age} ago`; + return this.render(this.lastlogTemplate, { + className: "hoot streamLastlog", + username, + age, + opacity: 0.6, + showAvatar: 0, + hoot: "last seen " + age_ago, + }); + }, + + renderHoot: function ({ + id, + thread, + date, + username, + hoot, + comment, + hidden, + className, + showAvatar, + }) { + return this.render(this.hootTemplate, { + username, + className: className ? `hoot ${className}` : "hoot", + image: profile_image(username), + showAvatar: showAvatar === false ? 0 : 1, + hoot: hoot || tidy_urls(comment, true), + age: get_age(date), + age_opacity: get_age_opacity(date), + }); + }, + + renderHoots: function ({ hoots, className }) { + const els = []; + for (hoot of hoots) { + els.push(this.renderHoot({ ...hoot, className })); + } + return els; + }, + + renderThread: function ({ thread, comments, files, images }) { + thread = thread.shift(); + // console.log(thread, comments, files, images); + const postedToday = +new Date() / 1000 - thread.date < 86400; + + if (postedToday) { + return [ + "<div class='divider dark'></div>", + this.renderHoot({ + hoot: `<a class="threadLink" href="/details/${thread.id}">${thread.title}</a>`, + username: thread.username, + className: "isRecent", + date: thread.lastmodified, + ...this.renderFiles(files), + ...this.renderHoots({ + hoots: comments.slice(0, 1), + tag: "first_post", + }), + ...this.renderHoots({ hoots: comments.slice(1) }), + }), + "<div class='divider'></div>", + ]; + // display very proud headline + // title, avatar, first image, full file list, + } else { + return [ + "<div class='divider dark'></div>", + this.renderHoot({ + hoot: `<a class="threadLink" href="/details/${thread.id}">${thread.title}</a>`, + username: thread.username, + className: "", + date: thread.lastmodified, + }), + this.renderFiles(files.slice(0, 3)), + ...this.renderHoots({ hoots: comments.slice(0, 1), tag: "first_post" }), + ...this.renderHoots({ hoots: comments.slice(1).slice(-3) }), + "<div class='divider'></div>", + ]; + // say "in ... " + // audio player OR recent file list + // recent 3 comments + } + }, + + renderFiles: function (files) { + if (!files.length) { + return null; + } + const $table = $("<table>"); + for (const file of files) { + const $el = this.renderFile(file); + $table.append($el); + } + return $table; + }, + + renderFile: function (file) { + var size = hush_size(file.size); + var datetime = verbose_date(file.date, true); + var date_class = carbon_date(file.date); + var link = make_link(file); + return this.render(this.fileTemplate, { + id: file.id, + username: file.username, + link, + filename: file.filename, + age: get_age(file.date), + date_class, + // date: datetime[0], + // time: datetime[1], + size_class: size[0], + size: size[1], + }); + }, + + agglutinate: ({ threads, comments, files, hootbox, lastlog }) => + [ + ...threads.map((thread) => [ + thread.id, + thread.createdate, + "thread", + thread, + ]), + ...comments + .filter((comment) => comment.thread !== 1) + .map((comment) => [comment.thread, comment.date, "comments", comment]), + ...files.map((file) => [ + file.thread, + file.date, + IMAGE_REGEXP.test(file.filename) ? "images" : "files", + file, + ]), + ...hootbox.map((hoot) => [1, hoot.date, "hoot", hoot]), + ...lastlog.map((user) => [1, user.lastseen, "lastlog", user]), + ] + .sort((a, b) => b[1] - a[1]) + .reduce( + ({ threadLookup, order }, [thread_id, date, type, data]) => { + if (type === "hoot") { + order.push({ type: "hoot", date, data }); + } else if (type === "lastlog") { + order.push({ type: "lastlog", date, data }); + } else if (thread_id !== 1) { + if (!(thread_id in threadLookup)) { + threadLookup[thread_id] = { + thread: [], + comments: [], + files: [], + images: [], + }; + order.push({ type: "thread", date, thread_id }); + } + threadLookup[thread_id][type].push(data); + } + return { threadLookup, order }; + }, + { threadLookup: {}, order: [] } + ), +}); |
