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), $("
") ) : 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 [ "
", this.renderHoot({ hoot: `${thread.title}`, 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) }), }), "
", ]; // display very proud headline // title, avatar, first image, full file list, } else { return [ "
", this.renderHoot({ hoot: `${thread.title}`, 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) }), "
", ]; // say "in ... " // audio player OR recent file list // recent 3 comments } }, renderFiles: function (files) { if (!files.length) { return null; } const $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: [] } ), });