feature: improve audio vis a little more
fix: remove some debugging console stuff
This commit is contained in:
parent
0ed013c968
commit
b6b4fefa34
5 changed files with 102 additions and 44 deletions
|
@ -259,6 +259,7 @@ body[data-perms*="rooms.create"] [data-requires-permission="rooms.create"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -286,9 +287,14 @@ body[data-perms*="rooms.create"] [data-requires-permission="rooms.create"] {
|
||||||
.audio-container .audio-controls-container .buttons-container {
|
.audio-container .audio-controls-container .buttons-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-content: center;
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audio-container .audio-controls-container .blank {
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.audio-container .audio-controls-container .volume {
|
.audio-container .audio-controls-container .volume {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -297,11 +303,11 @@ body[data-perms*="rooms.create"] [data-requires-permission="rooms.create"] {
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 480px) {
|
@media screen and (max-width: 480px) {
|
||||||
.audio-container .audio-controls-container .blank {
|
.audio-container .audio-controls-container .blank {
|
||||||
max-width: 0;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audio-container .audio-controls-container .volume {
|
.audio-container .audio-controls-container .volume {
|
||||||
max-width: 60px;
|
max-width: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,6 +510,47 @@ body[data-perms*="rooms.create"] [data-requires-permission="rooms.create"] {
|
||||||
top: 2px;
|
top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ICON - DOWNLOAD */
|
||||||
|
.icon.download {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
transform: scale(var(--ggs, 1));
|
||||||
|
width: 16px;
|
||||||
|
height: 6px;
|
||||||
|
border: 2px solid;
|
||||||
|
border-top: 0;
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
.icon.download::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-left: 2px solid;
|
||||||
|
border-bottom: 2px solid;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
left: 2px;
|
||||||
|
bottom: 4px;
|
||||||
|
}
|
||||||
|
.icon.download::before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 2px;
|
||||||
|
height: 10px;
|
||||||
|
background: currentColor;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ICON - EXCHANGE */
|
/* ICON - EXCHANGE */
|
||||||
.icon.exchange,
|
.icon.exchange,
|
||||||
.icon.exchange::after,
|
.icon.exchange::after,
|
||||||
|
|
|
@ -4,8 +4,10 @@ function human_readable_time(duration) {
|
||||||
return new Date(duration * 1000).toISOString().slice(duration > 3600 ? 11 : 14, 19);
|
return new Date(duration * 1000).toISOString().slice(duration > 3600 ? 11 : 14, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FREQUENCY_SAMPLES = 512;
|
const DISPLAY_WINDOW = 1;
|
||||||
const BAR_WIDTH = 4;
|
const BAR_COUNT = 48;
|
||||||
|
const BAR_GAP = 2;
|
||||||
|
const BAR_CAP_HEIGHT = 8;
|
||||||
const PROGRESS_TICKS = 1000;
|
const PROGRESS_TICKS = 1000;
|
||||||
const MS_BETWEEN_PROGRESS_UPDATES = 200;
|
const MS_BETWEEN_PROGRESS_UPDATES = 200;
|
||||||
|
|
||||||
|
@ -54,12 +56,6 @@ new MutationObserver((mutations) => {
|
||||||
|
|
||||||
player.addEventListener("keydown", (event) => {
|
player.addEventListener("keydown", (event) => {
|
||||||
const key = event.which ?? event.keyCode;
|
const key = event.which ?? event.keyCode;
|
||||||
|
|
||||||
console.dir({
|
|
||||||
key,
|
|
||||||
playing: player.dataset.playing,
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 32: // space
|
case 32: // space
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -145,6 +141,9 @@ new MutationObserver((mutations) => {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
CANVAS = CANVAS ?? player.querySelector("canvas");
|
CANVAS = CANVAS ?? player.querySelector("canvas");
|
||||||
|
CANVAS.height = 255;
|
||||||
|
CANVAS.width = BAR_COUNT * (16 + BAR_GAP);
|
||||||
|
|
||||||
VIZ_RGB = window
|
VIZ_RGB = window
|
||||||
.getComputedStyle(CANVAS)
|
.getComputedStyle(CANVAS)
|
||||||
.color.slice(4, -1)
|
.color.slice(4, -1)
|
||||||
|
@ -155,8 +154,6 @@ new MutationObserver((mutations) => {
|
||||||
|
|
||||||
if (!ANALYSER) {
|
if (!ANALYSER) {
|
||||||
ANALYSER = ACTX.createAnalyser();
|
ANALYSER = ACTX.createAnalyser();
|
||||||
ANALYSER.fftSize = 4 * FREQUENCY_SAMPLES;
|
|
||||||
ANALYSER.smoothingTimeConstant = 0.8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DATA = DATA ?? new Uint8Array(ANALYSER.frequencyBinCount);
|
DATA = DATA ?? new Uint8Array(ANALYSER.frequencyBinCount);
|
||||||
|
@ -174,22 +171,54 @@ new MutationObserver((mutations) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let previous_max_values;
|
||||||
function draw() {
|
function draw() {
|
||||||
|
previous_max_values =
|
||||||
|
previous_max_values ?? new Array(ANALYSER.frequencyBinCount).fill(0);
|
||||||
|
|
||||||
if (!player.dataset.playing) {
|
if (!player.dataset.playing) {
|
||||||
return;
|
if (previous_max_values.all((v) => v === 0)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ANALYSER.getByteFrequencyData(DATA);
|
ANALYSER.getByteFrequencyData(DATA);
|
||||||
|
|
||||||
// draw on the canvas element
|
const gradient = CTX.createLinearGradient(0, 0, 0, CANVAS.height);
|
||||||
|
gradient.addColorStop(
|
||||||
|
0.4,
|
||||||
|
`rgba( ${parseInt(VIZ_RGB[0] / 4)}, ${parseInt(VIZ_RGB[1] / 4)}, ${parseInt(VIZ_RGB[2] / 4)}, 0)`,
|
||||||
|
);
|
||||||
|
gradient.addColorStop(1, `rgba( ${VIZ_RGB[0]}, ${VIZ_RGB[1]}, ${VIZ_RGB[2]}, 0.25)`);
|
||||||
|
|
||||||
|
const bar_width = parseInt(CANVAS.width / BAR_COUNT);
|
||||||
|
const stride = parseInt((DATA.length * DISPLAY_WINDOW) / BAR_COUNT);
|
||||||
|
|
||||||
CTX.clearRect(0, 0, CANVAS.width, CANVAS.height);
|
CTX.clearRect(0, 0, CANVAS.width, CANVAS.height);
|
||||||
|
|
||||||
for (let i = 0; i < DATA.length; i = i + BAR_WIDTH) {
|
for (let i = 0; i < BAR_COUNT; ++i) {
|
||||||
// normalize the value
|
const value = DATA[i * stride];
|
||||||
const value = DATA[i] / 255;
|
|
||||||
const y = CANVAS.height - CANVAS.height * value;
|
const cap_value = value > previous_max_values[i] ? value : previous_max_values[i];
|
||||||
CTX.fillStyle = `rgb(${Math.min(255, parseInt(value * VIZ_RGB[0] + VIZ_RGB[0] * 0.25))}, ${Math.min(255, parseInt(value * VIZ_RGB[1] + VIZ_RGB[1] * 0.25))}, ${Math.min(255, parseInt(value * VIZ_RGB[2] + VIZ_RGB[2] * 0.25))})`;
|
const cap_color_value = 0.33 + cap_value / 255;
|
||||||
CTX.fillRect(i, y, 2, 8);
|
CTX.fillStyle = `rgba(${VIZ_RGB[0]}, ${VIZ_RGB[1]}, ${VIZ_RGB[2]}, 0.8)`;
|
||||||
|
CTX.fillRect(
|
||||||
|
i * (bar_width + BAR_GAP),
|
||||||
|
CANVAS.height - cap_value,
|
||||||
|
bar_width,
|
||||||
|
BAR_CAP_HEIGHT,
|
||||||
|
);
|
||||||
|
|
||||||
|
previous_max_values[i] =
|
||||||
|
value > previous_max_values[i]
|
||||||
|
? value
|
||||||
|
: previous_max_values[i] - BAR_CAP_HEIGHT / 2;
|
||||||
|
|
||||||
|
CTX.fillStyle = gradient;
|
||||||
|
CTX.fillRect(
|
||||||
|
i * (bar_width + BAR_GAP),
|
||||||
|
CANVAS.height - value + BAR_CAP_HEIGHT + BAR_CAP_HEIGHT,
|
||||||
|
bar_width,
|
||||||
|
value,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(draw);
|
requestAnimationFrame(draw);
|
||||||
|
|
|
@ -13,10 +13,6 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
console.dir({
|
|
||||||
user_json,
|
|
||||||
user,
|
|
||||||
});
|
|
||||||
const ids = document.querySelectorAll("[data-bind__user_id]");
|
const ids = document.querySelectorAll("[data-bind__user_id]");
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
const bound_to =
|
const bound_to =
|
||||||
|
@ -29,19 +25,12 @@
|
||||||
|
|
||||||
const avatars = document.querySelectorAll("[data-bind__user_meta_avatar]");
|
const avatars = document.querySelectorAll("[data-bind__user_meta_avatar]");
|
||||||
for (const avatar of avatars) {
|
for (const avatar of avatars) {
|
||||||
console.dir({
|
|
||||||
avatar,
|
|
||||||
});
|
|
||||||
const bound_to =
|
const bound_to =
|
||||||
typeof avatar.dataset["bind__user_meta_avatar"] === "string" &&
|
typeof avatar.dataset["bind__user_meta_avatar"] === "string" &&
|
||||||
avatar.dataset["bind__user_meta_avatar"].length
|
avatar.dataset["bind__user_meta_avatar"].length
|
||||||
? avatar.dataset["bind__user_meta_avatar"]
|
? avatar.dataset["bind__user_meta_avatar"]
|
||||||
: "innerHTML";
|
: "innerHTML";
|
||||||
avatar[bound_to] = user.meta?.avatar ?? DEFAULT_AVATAR_URL;
|
avatar[bound_to] = user.meta?.avatar ?? DEFAULT_AVATAR_URL;
|
||||||
|
|
||||||
console.dir({
|
|
||||||
avatar,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const usernames = document.querySelectorAll("[data-bind__user_username]");
|
const usernames = document.querySelectorAll("[data-bind__user_username]");
|
||||||
|
|
|
@ -98,10 +98,6 @@ const URL_MATCH_HANDLERS = [
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.dir({
|
|
||||||
action,
|
|
||||||
video_id,
|
|
||||||
});
|
|
||||||
return `
|
return `
|
||||||
<div class="embed-container iframe ${action === "shorts" ? "vertical" : "letterbox"} youtube">
|
<div class="embed-container iframe ${action === "shorts" ? "vertical" : "letterbox"} youtube">
|
||||||
<div class="embed-actions-container">
|
<div class="embed-actions-container">
|
||||||
|
@ -159,14 +155,9 @@ const URL_MATCH_HANDLERS = [
|
||||||
// const punycode = get_punycode();
|
// const punycode = get_punycode();
|
||||||
// const punycoded_url = punycode.encode(match[0]);
|
// const punycoded_url = punycode.encode(match[0]);
|
||||||
|
|
||||||
console.dir({
|
|
||||||
link_info,
|
|
||||||
});
|
|
||||||
if (typeof link_info.extension === "string") {
|
if (typeof link_info.extension === "string") {
|
||||||
const mime_types = get_mime_types(link_info.extension);
|
const mime_types = get_mime_types(link_info.extension);
|
||||||
console.dir({
|
|
||||||
mime_types,
|
|
||||||
});
|
|
||||||
if (mime_types.length) {
|
if (mime_types.length) {
|
||||||
if (mime_types.includes("image/gif")) {
|
if (mime_types.includes("image/gif")) {
|
||||||
return `<div class="embed-container image gif"><img src="${link_info.url}" alt="A gif from ${link_info.domain}" /></div>`;
|
return `<div class="embed-container image gif"><img src="${link_info.url}" alt="A gif from ${link_info.domain}" /></div>`;
|
||||||
|
@ -201,7 +192,11 @@ const URL_MATCH_HANDLERS = [
|
||||||
<div class="time-container"><span class="duration">00:00</span></div>
|
<div class="time-container"><span class="duration">00:00</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons-container">
|
<div class="buttons-container">
|
||||||
<div class="audio-control blank"></div>
|
<div class="audio-control blank">
|
||||||
|
<a href="${link_info.url}" download>
|
||||||
|
<div class="icon download"></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div class="audio-control skip-back"><div class="icon skip-back"></div></div>
|
<div class="audio-control skip-back"><div class="icon skip-back"></div></div>
|
||||||
<div class="audio-control play-pause-toggle"><div class="icon play"></div><div class="icon pause"></div></div>
|
<div class="audio-control play-pause-toggle"><div class="icon play"></div><div class="icon pause"></div></div>
|
||||||
<div class="audio-control skip-forward"><div class="icon skip-forward"></div></div>
|
<div class="audio-control skip-forward"><div class="icon skip-forward"></div></div>
|
||||||
|
|
|
@ -115,10 +115,8 @@ Deno.test({
|
||||||
asserts.assert(Array.isArray(long_polled_events));
|
asserts.assert(Array.isArray(long_polled_events));
|
||||||
asserts.assertEquals(long_polled_events.length, 1);
|
asserts.assertEquals(long_polled_events.length, 1);
|
||||||
asserts.assertEquals(long_polled_events[0].data?.i, 12345);
|
asserts.assertEquals(long_polled_events[0].data?.i, 12345);
|
||||||
console.log('done');
|
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
console.log('finally');
|
|
||||||
clear_room_events_cache();
|
clear_room_events_cache();
|
||||||
if (test_server_info) {
|
if (test_server_info) {
|
||||||
await test_server_info.server.stop();
|
await test_server_info.server.stop();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue