diff options
| author | julian laplace <julescarbon@gmail.com> | 2022-10-27 16:42:57 +0200 |
|---|---|---|
| committer | julian laplace <julescarbon@gmail.com> | 2022-10-27 16:42:57 +0200 |
| commit | 83c938702eb67bd6d154bb98b632e64e5e7e183f (patch) | |
| tree | 7b2b64a91f68cbcd4d4b2089b3a24b3f40bde88f /public/assets/js | |
| parent | 53644b55eb3a6a355f25e4a30b62c2c78451cd29 (diff) | |
add player and image viewer
Diffstat (limited to 'public/assets/js')
| -rw-r--r-- | public/assets/js/index.js | 2 | ||||
| -rw-r--r-- | public/assets/js/lib/views/details/audio.js | 101 | ||||
| -rw-r--r-- | public/assets/js/lib/views/details/audioPlayer.js | 123 | ||||
| -rw-r--r-- | public/assets/js/lib/views/stream/hootstream.js | 79 |
4 files changed, 224 insertions, 81 deletions
diff --git a/public/assets/js/index.js b/public/assets/js/index.js index 1c8deb5..ef2b8f4 100644 --- a/public/assets/js/index.js +++ b/public/assets/js/index.js @@ -17,6 +17,8 @@ var app = (function () { }; app.ready = function () { + audio.init(); + app.player = new AudioPlayer(); app.router.route(); }; diff --git a/public/assets/js/lib/views/details/audio.js b/public/assets/js/lib/views/details/audio.js index fb72e0b..2329886 100644 --- a/public/assets/js/lib/views/details/audio.js +++ b/public/assets/js/lib/views/details/audio.js @@ -1,26 +1,27 @@ -var audio = (function () { - var audio = {}; +const audio = (function () { + const audio = {}; - var el, - music = [], - current_index = -1; - var links, comment, parent; - var selected = false; - var playing = false; - var built = false; - var initted = false; + let music = []; + let current_index = -1; + let links, parent; + let selected = false; + let playing = false; + let built = false; + let initted = false; + let ui = null; audio.init = function () { if (initted) { audio.index(); return; } - comment = document.querySelector("#comment"); parent = document.querySelector("#audio"); audio.index(); audio.build(); - el.src = music[0]; + if (music.length) { + audio.el.src = music[0]; + } initted = true; }; @@ -32,7 +33,7 @@ var audio = (function () { if (!link.href.match(/\.(mp3|wav|aiff?|m4a|ogg|opus|flac)$/)) return; link.dataset.index = music.length; music.push(link); - if (playing && link.href === el.src) { + if (playing && link.href === audio.el.src) { current_index = parseInt(link.dataset.index); } }); @@ -44,28 +45,55 @@ var audio = (function () { audio.build = function () { if (built) return; built = true; - el = audio.el = document.createElement("audio"); - el.setAttribute("controls", true); - // el.addEventListener("loadeddata", () => { if (selected) el.play() }) - el.addEventListener("ended", audio.next); - parent.appendChild(el); + audio.el = document.createElement("audio"); + audio.el.setAttribute("controls", true); + // audio.el.addEventListener("loadeddata", () => { if (selected) audio.el.play() }) + parent.appendChild(audio.el); document.body.addEventListener("keydown", audio.keydown); }; audio.destroy = function () { - el.pause(); - el = null; - parent.removeChild(el); + audio.el.pause(); + parent.removeChild(audio.el); + audio.el = null; document.body.removeEventListener("keydown", audio.keydown); built = false; }; + audio.listen = function (uiController) { + ui = uiController; + }; + audio.play = function (index) { playing = true; current_index = (parseInt(index) + music.length) % music.length; - el.src = music[current_index].href; - el.play(); + audio.el.src = music[current_index].href; + audio.el.play(); audio.set_cursor(); + if (ui) { + ui.onPlay(music[current_index]); + } + }; + + audio.pause = function () { + audio.el.pause(); + if (ui) { + ui.onPause(); + } + }; + + audio.toggle = function () { + if (audio.el.paused) { + audio.el.play(); + if (ui) { + ui.onPlay(music[current_index]); + } + } else { + audio.el.pause(); + if (ui) { + ui.onPause(); + } + } }; audio.set_cursor = function () { @@ -84,16 +112,11 @@ var audio = (function () { audio.play(current_index + 1); }; - audio.toggle = function () { - if (el.paused) el.play(); - else el.pause(); - }; - - audio.keydown = function (e) { - function element_is_text_input(el) { - var tagName = el.tagName.toLowerCase(); + audio.keydown = function (event) { + function element_is_text_input(element) { + var tagName = element.tagName.toLowerCase(); return ( - (tagName == "input" && el.type == "text") || + (tagName == "input" && element.type == "text") || tagName == "textarea" || tagName == "button" ); @@ -101,24 +124,24 @@ var audio = (function () { if (element_is_text_input(document.activeElement)) { return; } - if (app.typing || e.ctrlKey || e.altKey || e.metaKey) return; - switch (e.keyCode) { + if (app.typing || event.ctrlKey || event.altKey || event.metaKey) return; + switch (event.keyCode) { case 37: // left - if (e.shiftKey) { - el.currentTime -= 10; + if (event.shiftKey) { + audio.el.currentTime -= 10; } else { audio.prev(); } break; case 39: // right - if (e.shiftKey) { - el.currentTime += 10; + if (event.shiftKey) { + audio.el.currentTime += 10; } else { audio.next(); } break; case 32: // spacebar - e.preventDefault(); + event.preventDefault(); audio.toggle(); break; } diff --git a/public/assets/js/lib/views/details/audioPlayer.js b/public/assets/js/lib/views/details/audioPlayer.js new file mode 100644 index 0000000..700daa5 --- /dev/null +++ b/public/assets/js/lib/views/details/audioPlayer.js @@ -0,0 +1,123 @@ +const AudioPlayer = View.extend({ + el: "#audioPlayer", + + events: { + "click .icon": "toggle", + }, + + initialize: function () { + this.$title = this.$(".title"); + + this.icon_el = this.$(".icon").get(0); + this.pos_el = this.$(".pos").get(0); + this.track_el = this.$(".track").get(0); + this.dot_el = this.$(".dot").get(0); + this.time_el = this.$(".time").get(0); + + this.mousedown = this.mousedown.bind(this); + this.mousemove = this.mousemove.bind(this); + this.mouseup = this.mouseup.bind(this); + + if (is_mobile) { + this.pos_el.addEventListener("touchstart", (e) => + this.mousedown(e.touches[0]) + ); + this.pos_el.addEventListener("touchmove", (e) => + this.mousemove(this.e.touches[0]) + ); + window.addEventListener("touchend", this.mouseup.bind); + } else { + this.pos_el.addEventListener("mousedown", this.mousedown); + this.pos_el.addEventListener("mousemove", this.mousemove); + window.addEventListener("mouseup", this.mouseup); + } + this.down = false; + this.mousex = 0; + + audio.listen(this); + audio.el.addEventListener("timeupdate", this.onTimeUpdate.bind(this)); + }, + + /** + * Mouse movements + * */ + mousedown: function (e) { + e.preventDefault && e.preventDefault(); + const track_left = this.pos_el.offsetLeft; + this.down = true; + this.mousex = (e.pageX - track_left) / this.track_el.offsetWidth; + }, + + mousemove: function (e, isTouch) { + if (!this.down) return; + const track_left = this.pos_el.offsetLeft; + this.mousex = Math.min( + Math.max(0, (e.pageX - track_left) / this.track_el.offsetWidth), + 1 + ); + this.dot_el.style.transform = + "translateX(" + this.mousex * this.track_el.offsetWidth + "px)"; + }, + + mouseup: function (e) { + if (!this.down) return; + this.down = false; + var t = this.mousex * (audio.el.duration || 1); + audio.el.currentTime = Math.round(t); + this.dot_el.style.transform = + "translateX(" + this.mousex * this.track_el.offsetWidth + "px)"; + }, + + toggle: function () { + audio.toggle(); + }, + + /** + * Receiving play events + */ + onPlay: function (element) { + if (!this.active) { + this.active = true; + this.$el.addClass("active"); + } + // if (index === music.length) return stop(); + if (!this.icon_el.classList.contains("active")) { + this.icon_el.classList.add("active"); + } + this.onTimeUpdate(); + + if (element) { + const title = element.innerText; + this.$title.html(title); + } + }, + + onPause: function () { + this.icon_el.classList.remove("active"); + }, + + onStop: function () { + this.$el.removeClass("active"); + this.active = false; + }, + + onTimeUpdate: function () { + if (this.down) { + return; + } + let { currentTime, duration } = audio.el; + let t = currentTime / (duration || 1); + this.dot_el.style.transform = + "translateX(" + this.track_el.offsetWidth * t + "px)"; + this.time_el.innerHTML = time(currentTime) + " / " + time(duration); + }, +}); + +function time(n) { + if (!n) return "0:00"; + n = Math.floor(n); + let s = n % 60; + if (s < 10) s = "0" + s; + let m = Math.floor(n / 60); + return m + ":" + s; +} diff --git a/public/assets/js/lib/views/stream/hootstream.js b/public/assets/js/lib/views/stream/hootstream.js index 6c02cc6..777489d 100644 --- a/public/assets/js/lib/views/stream/hootstream.js +++ b/public/assets/js/lib/views/stream/hootstream.js @@ -104,12 +104,14 @@ var HootStream = View.extend({ return true; } if ( - filters.images && - thread.files && - thread.files.some((file) => IMAGE_REGEXP.test(file.filename)) + filters.files && + thread.files.some((file) => !AUDIO_REGEXP.test(file.filename)) ) { return true; } + if (filters.images && thread.images.length) { + return true; + } return false; }) .map( @@ -120,18 +122,15 @@ var HootStream = View.extend({ const thread = threadLookup[thread_id]; const threadData = { ...thread, - files: - filters.images || filters.music - ? thread.files.filter((file) => { - if (AUDIO_REGEXP.test(file.filename)) { - return filters.music; - } - if (IMAGE_REGEXP.test(file.filename)) { - return filters.images; - } - return filters.files; - }) - : [], + images: filters.images ? thread.images : [], + files: filters.music + ? thread.files.filter((file) => { + if (AUDIO_REGEXP.test(file.filename)) { + return filters.music; + } + return filters.files; + }) + : [], comments: filters.hoots ? thread.comments : [], query: data.query, }; @@ -257,38 +256,34 @@ var HootStream = View.extend({ comment_count: `${thread.comment_count || 0} c.`, comment_opacity: age_opacity * get_size_opacity(thread.comment_count), }), - // this.renderImages( - // isViewingThread || postedToday ? images : images.slice(0, 6) - // ), + this.renderImages( + isViewingThread || postedToday ? images : images.slice(0, 6) + ), this.renderFiles( isViewingThread || postedToday ? files : files.slice(0, 10) ), ...this.renderHoots({ - hoots: comments - .slice(0, 1) - .map( - trimComment({ - isViewingThread, - lines: 5, - snippetSize: 512, - cropSize: 256, - }) - ), + hoots: comments.slice(0, 1).map( + trimComment({ + isViewingThread, + lines: 5, + snippetSize: 512, + cropSize: 256, + }) + ), className: "first_post", }), ...this.renderHoots({ hoots: isViewingThread || postedToday - ? comments - .slice(1) - .map( - trimComment({ - isViewingThread, - lines: 1, - snippetSize: 256, - cropSize: 128, - }) - ) + ? comments.slice(1).map( + trimComment({ + isViewingThread, + lines: 1, + snippetSize: 256, + cropSize: 128, + }) + ) : comments .slice(1) .slice(-5) @@ -305,13 +300,13 @@ var HootStream = View.extend({ ]; }, - renderImages: function (files) { - if (!files.length) { + renderImages: function (images) { + if (!images.length) { return null; } const $table = $("<div class='imageList'>"); - for (const file of files) { - const $el = this.renderFile(this.imageTemplate, file); + for (const image of images) { + const $el = this.renderFile(this.imageTemplate, image); $table.append($el); } return $table; |
