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.threadTemplate = this.$(".threadTemplate").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, template, ...options }) { // console.log(hoot, comment); return this.render(template || 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), ...options, }); }, 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.lastmodified < 86400; const age_opacity = get_age_opacity(thread.lastmodified); return [ "
", this.renderHoot({ template: this.threadTemplate, hoot: `${thread.title}`, keyword_link: thread.keyword ? `${thread.keyword}` : "", username: thread.username, className: postedToday ? "isRecent" : "", date: thread.lastmodified, file_count: `${files.length || 0} f.`, file_opacity: age_opacity * get_size_opacity(files.length), comment_count: `${comments.length || 0} c.`, comment_opacity: age_opacity * get_size_opacity(files.length), }), this.renderFiles(postedToday ? files : files.slice(0, 10)), ...this.renderHoots({ hoots: comments.slice(0, 1), tag: "first_post" }), ...this.renderHoots({ hoots: postedToday ? comments.slice(1) : comments.slice(1).slice(-5), }), "
", ]; // 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), age_opacity: get_age_opacity(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: [] } ), });