diff options
| author | julian laplace <julescarbon@gmail.com> | 2022-10-26 15:50:25 +0200 |
|---|---|---|
| committer | julian laplace <julescarbon@gmail.com> | 2022-10-26 15:50:25 +0200 |
| commit | 8fe5a1cf652fd4bd0b737bd18605a8d4c4028407 (patch) | |
| tree | b1a65a0421020c9f51aabea4401ef0c6f1093520 | |
| parent | 3dc50a84e6ae99d991caf0dae9c3a222ec4a37f1 (diff) | |
update padding still lol hi :)
| -rw-r--r-- | public/assets/css/hootstream.css | 329 | ||||
| -rw-r--r-- | public/assets/js/lib/views/stream/hootstream.js | 82 | ||||
| -rw-r--r-- | public/assets/js/util/format.js | 52 | ||||
| -rw-r--r-- | views/partials/header.ejs | 1 | ||||
| -rw-r--r-- | views/partials/hootstream.ejs | 306 |
5 files changed, 417 insertions, 353 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) { diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 664e236..1be8e7d 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -5,6 +5,7 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> <link rel="stylesheet" href="/assets/css/bucky.css"> +<link rel="stylesheet" href="/assets/css/hootstream.css"> <meta name="_csrf" value="<%= csrfToken %>"> </head> <body class="loading"> diff --git a/views/partials/hootstream.ejs b/views/partials/hootstream.ejs index 755f83c..dfc1ee6 100644 --- a/views/partials/hootstream.ejs +++ b/views/partials/hootstream.ejs @@ -21,6 +21,22 @@ </div> </script> + <script class="threadTemplate" type="text/html"> + <div class="{{className}}"> + <a class="userLink" href="/profile/{{username}}" style="opacity: {{age_opacity}}"> + {{username}} + </a> + <a class="avatarLink" href="/profile/{{username}}" style="opacity: {{age_opacity}}"> + <div class="avatar" title="{{username}}" style="background-image:url({{image}});opacity:{{showAvatar}};"></div> + </a> + <div class="text" style="opacity: {{age_opacity}}">{{hoot}}</div> + <div class="keyword">{{keyword_link}}</div> + <div class="commentCount date" style="opacity: {{comment_opacity}}">{{comment_count}}</div> + <div class="fileCount date" style="opacity: {{file_opacity}}">{{file_count}}</div> + <div class="age date" style="opacity: {{age_opacity}}">{{age}}</div> + </div> + </script> + <script class="lastlogTemplate" type="text/html"> <div class="{{className}}" style="opacity: {{opacity}}"> <a class="userLink" href="/profile/{{username}}"> @@ -36,7 +52,7 @@ <div class="filename" style="opacity: {{age_opacity}}"> <a href="{{link}}" title="{{id}}" class="file">{{filename}}</a> </div> - <div class="size {{size_class}}" style="opacity: {{age_opacity}}"> + <div class="size" style="opacity: {{age_opacity}}"> {{size}} </div> <div class="age {{date_class}}" style="opacity: {{age_opacity}}"> @@ -57,291 +73,3 @@ </div> </div> - -<style> - #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; - } - #hootevents .hoot { - display: flex; - flex-flow: row wrap; - justify-content: space-between; - align-items: flex-start; - margin-bottom: 0.5rem; - width: 100%; - } - #hootevents .age { - width: 40px; - display: flex; - justify-content: flex-end; - align-items: flex-start; - text-align: right; - margin: 0px 0.75rem 0px 0px; - } - #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 #fed; - } - #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.0), rgba(127,127,127,0.05), rgba(127,127,127,0.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 + 1px); - 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; - } - #hootevents .fileRow .age { - margin-right: 0; - } - #hootevents .fileRow .filename { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - } - #hootevents .fileRow div { - color: rgba(64,64,64,1.0); - background: transparent; - padding: 0.5rem; - white-space: nowrap; - position: relative; - transition: opacity 0.1s; - } - #hootevents .fileRow div::after { - content: ''; - width: 100%; - height: 100%; - opacity: 0.2; - position: absolute; - top: 0; - left: 0; - z-index: -1; - } - #hootevents .fileRow:nth-child(odd) div::after { - background-color: #448; - } - #hootevents .fileRow:nth-child(even) div::after { - background-color: #88b; - } - #hootevents .fileRow:nth-child(even):hover div::after, - #hootevents .fileRow:nth-child(odd):hover div::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.0); - } - #hootevents .fileRow:nth-child(odd) div::after { - background-color: #88b; - } - #hootevents .fileRow:nth-child(even) div::after { - background-color: #448; - } - #hootevents .fileRow:nth-child(even):hover div::after, - #hootevents .fileRow:nth-child(odd):hover div::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; - } - } -</style>
\ No newline at end of file |
