summaryrefslogtreecommitdiff
path: root/public/assets
diff options
context:
space:
mode:
Diffstat (limited to 'public/assets')
-rw-r--r--public/assets/css/hootstream.css329
-rw-r--r--public/assets/js/lib/views/stream/hootstream.js82
-rw-r--r--public/assets/js/util/format.js52
3 files changed, 399 insertions, 64 deletions
diff --git a/public/assets/css/hootstream.css b/public/assets/css/hootstream.css
new file mode 100644
index 0000000..efaa989
--- /dev/null
+++ b/public/assets/css/hootstream.css
@@ -0,0 +1,329 @@
+/**
+ * hootstream.css
+ */
+
+#hootstream {
+ margin-top: 3rem;
+ font-size: 16px;
+}
+#hootstream form {
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ align-items: center;
+ flex-direction: row;
+ margin-bottom: 0.75rem;
+}
+#hootstream form input {
+ flex: 1;
+ font-size: 16px;
+ padding: 0.25rem;
+ margin-bottom: 0;
+}
+#hootstream form button {
+ margin: 0;
+ padding: 0.25rem;
+ margin-left: 0.5rem;
+ min-width: 2.5rem;
+}
+#hootevents {
+ font-size: 14px;
+ padding-right: 3rem;
+}
+
+/** HOOT HOOT content */
+
+#hootevents .hoot {
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 0.5rem;
+ width: 100%;
+}
+#hootevents .hootText {
+ max-width: 60rem;
+}
+
+/** metadata */
+
+#hootevents .keywordLink {
+ text-decoration: none;
+ opacity: 0.8;
+ transition: opacity 0.1s;
+ font-size: 13px;
+}
+#hootevents .keywordLink:hover {
+ text-decoration: none;
+ opacity: 1;
+}
+#hootevents .fileCount,
+#hootevents .commentCount,
+#hootevents .age {
+ width: 40px;
+ display: flex;
+ justify-content: flex-end;
+ align-items: flex-start;
+ text-align: right;
+ margin: 0px 0.75rem 0px 0px;
+ font-size: 13px;
+}
+#hootevents .fileCount,
+#hootevents .commentCount {
+}
+#hootevents .fileCount {
+ margin-right: 1.5rem;
+}
+#hootevents .userLink {
+ color: #118;
+ opacity: 0.8;
+ text-align: right;
+ width: 6rem;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-right: 0.5rem;
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ margin-top: 0.175rem;
+}
+#hootevents .avatar {
+ width: 1.5rem;
+ height: 1.5rem;
+ background-size: cover;
+ border-radius: 2px;
+ border: 1px solid #000;
+ margin: 0px 0.5rem 0px 0px;
+ box-shadow: 0 0 1px 1px rgba(128, 128, 128, 0.1);
+ position: relative;
+ top: -0.25rem;
+}
+#hootevents .hoot .text {
+ text-align: left;
+ flex: 1;
+ margin: 0px 0.5rem 0px 0px;
+ white-space: pre-wrap;
+ line-height: 1.5;
+}
+
+#hootevents .hoot.isRecent .threadLink {
+ font-weight: bold;
+ text-shadow: 0 0 3px rgba(192, 192, 192, 0.2);
+}
+#hootevents .hoot .threadLink {
+ color: #38f;
+ font-size: 16px;
+}
+
+/** DiViDErZ */
+
+#hootevents .divider {
+ border-top: 0;
+ border-bottom: 1px solid rgba(88, 88, 88, 0.4);
+ margin: 0 auto;
+ width: 80%;
+ height: 0rem;
+ margin-bottom: 1rem;
+}
+#hootevents .divider.dark {
+ border-top: 1px solid rgba(88, 88, 88, 0.4);
+ border-bottom: 0;
+ height: 1rem;
+ margin-bottom: 0rem;
+ margin-top: 0rem;
+}
+#hootevents .thread {
+ background: linear-gradient(
+ 90deg,
+ rgba(127, 127, 127, 0),
+ rgba(127, 127, 127, 0.05),
+ rgba(127, 127, 127, 0)
+ );
+}
+
+/** LastLog */
+
+#hootevents .hoot.streamLastlog {
+ font-size: 13px;
+ margin-bottom: 1rem;
+ align-items: center;
+}
+#hootevents .hoot.streamLastlog .userLink {
+ margin-top: 0;
+ margin-right: 0.375rem;
+}
+#hootevents .hoot.streamLastlog .text {
+ line-height: 0;
+}
+#hootevents .hoot.streamLastlog .age {
+}
+
+/** Files */
+
+#hootevents .fileList {
+ width: calc(100% - 8.25rem);
+ margin-top: 0.5rem;
+ margin-bottom: 1rem;
+ margin-left: 8rem;
+ margin-bottom: 1rem;
+}
+#hootevents .fileRow {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ position: relative;
+}
+#hootevents .fileRow .age {
+ margin-right: 0;
+}
+#hootevents .fileRow .size {
+ font-size: 13px;
+ padding-right: 1.5rem;
+}
+#hootevents .fileRow .filename {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+#hootevents .fileRow div {
+ color: rgba(64, 64, 64, 1);
+ background: transparent;
+ padding: 0.5rem;
+ white-space: nowrap;
+ transition: opacity 0.1s;
+}
+#hootevents .fileRow::after {
+ content: "";
+ width: 100%;
+ height: 100%;
+ opacity: 0.2;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+#hootevents .fileRow:nth-child(odd)::after {
+ background-color: #448;
+}
+#hootevents .fileRow:nth-child(even)::after {
+ background-color: #88b;
+}
+#hootevents .fileRow:nth-child(even):hover::after,
+#hootevents .fileRow:nth-child(odd):hover::after {
+ background-color: #bbf;
+}
+
+/** Misc */
+#hootevents code,
+#hootevents pre {
+ background: rgba(127, 127, 127, 0.2);
+ border: 1px solid rgba(127, 127, 127, 0.2);
+ max-width: calc(100vw - 12.5rem);
+ margin: 0.25rem;
+ padding: 0.5rem;
+}
+
+/** HOOT FORM */
+
+#hootform {
+ margin-bottom: 0.5rem;
+ padding: 0.5rem;
+}
+#hootform input[type="text"] {
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid rgba(127, 127, 127, 0.5);
+ padding-bottom: 3px;
+ font-size: 14px;
+ font-family: "Trebuchet MS", sans-serif;
+ background: transparent;
+ outline: 0;
+ width: 270px;
+ transition: background 200ms;
+ background: white;
+}
+#hootform input[type="text"]:invalid {
+ background: transparent;
+}
+#hootform input[type="text"]:focus {
+ border-bottom: 1px solid rgba(40, 20, 20, 0.2);
+ border-radius: 2px 2px 0 0;
+ color: #211;
+}
+#hootform input[type="text"]:focus {
+ border-bottom-color: rgba(127, 127, 127, 0.2);
+}
+#hootform input[type="text"]:invalid {
+ caret-color: #888;
+}
+
+/** MEDIA QUERY: DARK MODE */
+@media (prefers-color-scheme: dark) {
+ .search_form input[type="text"]:focus {
+ border-bottom-color: rgba(127, 127, 127, 0.2);
+ }
+ .search_form input[type="text"]:invalid {
+ caret-color: #888;
+ }
+ #hootstream .userLink {
+ color: #def;
+ }
+ #hootevents .fileRow div {
+ color: rgba(192, 192, 192, 1);
+ }
+ #hootevents .fileRow:nth-child(odd)::after {
+ background-color: #88b;
+ }
+ #hootevents .fileRow:nth-child(even)::after {
+ background-color: #448;
+ }
+ #hootevents .fileRow:nth-child(even):hover::after,
+ #hootevents .fileRow:nth-child(odd):hover::after {
+ background-color: #bbf;
+ }
+ #hootevents .hoot .threadLink:hover,
+ .desktop a:hover {
+ color: #2bf;
+ }
+}
+
+/** MEDIA QUERY: PHONE */
+@media (max-width: 700px) {
+ html,
+ body {
+ overflow-x: hidden;
+ }
+ #hootform {
+ margin-bottom: 0rem;
+ }
+ #hootstream {
+ padding-right: 0;
+ margin-top: 1rem;
+ }
+ #hootevents .userLink {
+ display: none;
+ }
+ #hootevents .streamLastlog .userLink {
+ display: block;
+ width: auto;
+ margin-left: 2rem;
+ }
+ #hootevents .avatarLink {
+ margin-left: 0.25rem;
+ }
+ #hootevents .fileList {
+ margin-top: 0.5rem;
+ margin-bottom: 1rem;
+ margin-left: 1.75rem;
+ width: calc(100% - 2rem);
+ }
+ #hootevents code,
+ #hootevents pre {
+ max-width: calc(100vw - 5.75rem);
+ margin-right: 0;
+ padding: 0.25rem 0.25rem 0.75rem 0.25rem;
+ }
+}
diff --git a/public/assets/js/lib/views/stream/hootstream.js b/public/assets/js/lib/views/stream/hootstream.js
index f748417..f4e48c4 100644
--- a/public/assets/js/lib/views/stream/hootstream.js
+++ b/public/assets/js/lib/views/stream/hootstream.js
@@ -7,6 +7,7 @@ var HootStream = View.extend({
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();
},
@@ -64,16 +65,20 @@ var HootStream = View.extend({
hidden,
className,
showAvatar,
+ template,
+ ...options
}) {
- console.log(hoot, comment);
- return this.render(this.hootTemplate, {
+ // 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),
+ hoot:
+ hoot || "<div class='hootText'>" + tidy_urls(comment, true) + "</div>",
age: get_age(date),
age_opacity: get_age_opacity(date),
+ ...options,
});
},
@@ -88,45 +93,34 @@ var HootStream = View.extend({
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, 10)),
- ...this.renderHoots({ hoots: comments.slice(0, 1), tag: "first_post" }),
- ...this.renderHoots({ hoots: comments.slice(1).slice(-5) }),
- "<div class='divider'></div>",
- ];
- // say "in ... "
- // audio player OR recent file list
- // recent 3 comments
- }
+ const postedToday = +new Date() / 1000 - thread.lastmodified < 86400;
+ const age_opacity = get_age_opacity(thread.lastmodified);
+ return [
+ "<div class='divider dark'></div>",
+ this.renderHoot({
+ template: this.threadTemplate,
+ hoot: `<a class="threadLink" href="/details/${thread.id}">${thread.title}</a>`,
+ keyword_link: thread.keyword
+ ? `<a class="keywordLink" href="/stream/${thread.keyword}">${thread.keyword}</a>`
+ : "",
+ 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),
+ }),
+ "<div class='divider'></div>",
+ ];
+ // say "in ... "
+ // audio player OR recent file list
+ // recent 3 comments
},
renderFiles: function (files) {
@@ -154,9 +148,9 @@ var HootStream = View.extend({
age: get_age(file.date),
age_opacity: get_age_opacity(file.date),
date_class,
- // date: datetime[0],
+ date: datetime[0],
// time: datetime[1],
- size_class: size[0],
+ // size_class: size[0],
size: size[1],
});
},
diff --git a/public/assets/js/util/format.js b/public/assets/js/util/format.js
index e6104e5..7058cea 100644
--- a/public/assets/js/util/format.js
+++ b/public/assets/js/util/format.js
@@ -257,28 +257,40 @@ function get_age(t, long) {
age /= 12;
return r(age) + (long ? " years" : "y");
}
-const ages = {
- newest: 60 * 10,
- newer: 60 * 60,
- new: 60 * 60 * 8,
- cool: 60 * 60 * 24,
- cold: 60 * 60 * 24 * 7,
- colder: 60 * 60 * 24 * 7 * 4,
- coldest: 60 * 60 * 24 * 7 * 4 * 12,
-};
+const age_scale = [
+ [0, 1.0],
+ [60 * 10, 1.0],
+ [60 * 60, 0.95],
+ [60 * 60 * 8, 0.9],
+ [60 * 60 * 24, 0.85],
+ [60 * 60 * 24 * 7, 0.65],
+ [60 * 60 * 24 * 7 * 4, 0.55],
+ [60 * 60 * 24 * 7 * 4 * 12, 0.5],
+];
function get_age_opacity(t) {
var age = Math.abs(Date.now() / 1000 - t);
- if (age < ages.newest) return 1;
- if (age < ages.newer)
- return lerp(norm(age, ages.newest, ages.newer), 1.0, 0.95);
- if (age < ages.new) return lerp(norm(age, ages.newer, ages.new), 0.95, 0.9);
- if (age < ages.cool) return lerp(norm(age, ages.new, ages.cool), 0.9, 0.85);
- if (age < ages.cold) return lerp(norm(age, ages.cool, ages.cold), 0.85, 0.6);
- if (age < ages.colder)
- return lerp(norm(age, ages.cold, ages.colder), 0.6, 0.5);
- if (age < ages.coldest)
- return lerp(norm(age, ages.colder, ages.coldest), 0.5, 0.4);
- return 0.39;
+ return get_scale_opacity(age, age_scale);
+}
+const size_scale = [
+ [0, 0.0],
+ [1, 0.7],
+ [5, 0.8],
+ [10, 0.9],
+ [15, 0.95],
+ [20, 0.99],
+];
+function get_size_opacity(n) {
+ return get_scale_opacity(n, size_scale);
+}
+function get_scale_opacity(value, scale) {
+ for (let i = 1; i < scale.length; i++) {
+ const [max_value, max_lerp] = scale[i];
+ if (value < max_value) {
+ const [min_value, min_lerp] = scale[i - 1];
+ return lerp(norm(value, min_value, max_value), min_lerp, max_lerp);
+ }
+ }
+ return scale[scale.length - 1][1];
}
function tidy_urls(s, short_urls) {