refactor: clean up chat and split up embed handling

This commit is contained in:
Andy Burke 2025-09-16 12:25:11 -07:00
parent 03751c6d00
commit 7e4ab72fe6
14 changed files with 352 additions and 274 deletions

48
public/js/embeds/audio.js Normal file
View file

@ -0,0 +1,48 @@
function embed_audio(link_info) {
if (typeof link_info.extension !== "string") {
return;
}
const mime_types = get_mime_types(link_info.extension);
const is_audio = mime_types[0]?.indexOf("audio") === 0;
if (!is_audio) {
return;
}
return `
<div class="audio-container" tabindex="-1">
<audio controls>
<source src="${link_info.url}" type="${mime_types[0].indexOf("audio/mpeg") === 0 ? "audio/mpeg" : mime_types[0]}">
Your browser does not support the audio element.
</audio>
<div class="enhanced-audio-player-container">
<div class="audio-player-display-container">
<canvas class="audio-player-display"></canvas>
</div>
<div class="audio-controls-container">
<div class="progress-container">
<div class="time-container"><span class="current">00:00</span></div>
<div class="slider-container">
<input type="range" name="progress" title="" min="0" max="1000" step="1" value="0" />
<label class="time-container" for="progress"><span class="current">00:00</span></label>
</div>
<div class="time-container"><span class="duration">00:00</span></div>
</div>
<div class="buttons-container">
<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 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 volume">
<input type="range" name="volume" title="Volume" min="0" max="100" step="1" value="" />
</div>
</div>
</div>
</div>
</div>`;
}

13
public/js/embeds/gif.js Normal file
View file

@ -0,0 +1,13 @@
function embed_gif(link_info) {
if (typeof link_info.extension !== "string") {
return;
}
const is_gif = get_mime_types(link_info.extension).includes("image/gif");
if (!is_gif) {
return;
}
return `<div class="embed-container image gif"><img src="${link_info.url}" alt="A gif from ${link_info.domain}" /></div>`;
}

13
public/js/embeds/image.js Normal file
View file

@ -0,0 +1,13 @@
function embed_image(link_info) {
if (typeof link_info.extension !== "string") {
return;
}
const is_image = get_mime_types(link_info.extension).shift()?.indexOf("image") === 0;
if (!is_image) {
return;
}
return `<div class="embed-container image"><img src="${link_info.url}" alt="An image from ${link_info.domain}" /></div>`;
}

3
public/js/embeds/link.js Normal file
View file

@ -0,0 +1,3 @@
function embed_link(link_info) {
return `<a href="${link_info.url}">${link_info.url}</a>`;
}

13
public/js/embeds/mp4.js Normal file
View file

@ -0,0 +1,13 @@
function embed_mp4(link_info) {
if (typeof link_info.extension !== "string") {
return;
}
const is_mp4 = get_mime_types(link_info.extension).includes("video/mp4");
if (!is_mp4) {
return;
}
return `<div class="embed-container image gif letterbox"><video autoplay="true" muted="true" loop="true" playsinline="true"><source src="${link_info.url}" type="video/mp4"><a href="${link_info.url}">${link_info.url}</a></video></div>`;
}

View file

@ -0,0 +1,33 @@
const SPOTIFY_EXTRACTOR =
/^\/(?<item_type>(?:album|artist|episode|playlist|tracks?))\/?(?<item_id>[a-zA-Z0-9]{22})/gi;
function embed_spotify(link_info) {
const is_spotify_link = ["spotify.com"].includes(link_info.domain?.toLowerCase());
if (!is_spotify_link) {
return;
}
SPOTIFY_EXTRACTOR.lastIndex = 0;
const {
groups: { item_type, item_id },
} = SPOTIFY_EXTRACTOR.exec(link_info.path ?? "") ?? { groups: {} };
if (!item_id) {
return;
}
return `
<div class="embed-container iframe ${!item_type || item_type.toLowerCase().indexOf("track") === 0 ? "short" : "square"} spotify rounded">
<div class="embed-actions-container">
<button class="icon plus" onclick="console.log(\"close\");"/>
<button class="icon pause" onclick="console.log(\"stop\");"/>
</div>
<iframe
src="https://open.spotify.com/embed/${item_type ?? "track"}/${item_id}"
allowfullscreen
allow="clipboard-write; encrypted-media; fullscreen; picture-in-picture"
loading="lazy"></iframe>
</div>`;
}

35
public/js/embeds/tidal.js Normal file
View file

@ -0,0 +1,35 @@
const TIDAL_EXTRACTOR =
/^\/(?:(?<action>.*?)\/)?(?<item_type>(?:album|artist|episode|playlist|tracks?))\/(?<item_id>[0-9]+)/gi;
function embed_tidal(link_info) {
const is_tidal_link = ["tidal.com", "tidalhi.fi"].includes(link_info.domain?.toLowerCase());
if (!is_tidal_link) {
return;
}
TIDAL_EXTRACTOR.lastIndex = 0;
const {
groups: { action, item_type, item_id },
} = TIDAL_EXTRACTOR.exec(link_info.path ?? "") ?? { groups: {} };
if (!(item_type && item_id)) {
return;
}
return `
<div class="embed-container iframe ${item_type.toLowerCase().indexOf("track") === 0 ? "short" : "square"} tidal">
<div class="embed-actions-container">
<button class="icon plus" onclick="console.log(\"close\");"/>
<button class="icon pause" onclick="console.log(\"stop\");"/>
</div>
<iframe
src="https://embed.tidal.com/${item_type.at(-1) === "s" ? item_type : `${item_type}s`}/${item_id}"
allow="encrypted-media"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups"
title="TIDAL Embed Player"
loading="lazy"
></iframe>
</div>`;
}

35
public/js/embeds/vimeo.js Normal file
View file

@ -0,0 +1,35 @@
const VIMEO_ID_EXTRACTOR =
/(?<video_domain>vimeo\.com)(?:\/(?<action>video|embed|watch|shorts|v))?.*(?:(?:\/|v=)(?<video_id>[A-Za-z0-9._%-]*))\S*/gi;
function embed_vimeo(link_info) {
const is_vimeo_link = ["vimeo.com"].includes(link_info.domain?.toLowerCase());
if (!is_vimeo_link) {
return;
}
VIMEO_ID_EXTRACTOR.lastIndex = 0;
const {
groups: { video_domain, action, video_id },
} = VIMEO_ID_EXTRACTOR.exec(link_info.url) ?? { groups: {} };
if (!video_id) {
return;
}
return `
<div class="embed-container iframe letterbox vimeo">
<div class="embed-actions-container">
<button class="icon plus" onclick="console.log(\"close\");"/>
<button class="icon pause" onclick="console.log(\"stop\");"/>
</div>
<iframe
src="https://player.vimeo.com/video/${video_id}"
frameborder="0"
allow="fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share"
referrerpolicy="strict-origin-when-cross-origin"
title="Star Trek: Legacy"
loading="lazy"></iframe>
</div>`;
}

View file

@ -0,0 +1,38 @@
const YOUTUBE_ID_EXTRACTOR =
/(?<video_domain>youtu(?:be\.com|\.be|be\.googleapis\.com))(?:\/(?<action>video|embed|watch|shorts|v))?.*(?:(?:\/|v=)(?<video_id>[A-Za-z0-9._%-]*))\S*/gi;
function embed_youtube(link_info) {
const is_youtube_link = ["youtube.com", "youtu.be", "youtube.googleapis.com"].includes(
link_info.domain?.toLowerCase(),
);
if (!is_youtube_link) {
return;
}
YOUTUBE_ID_EXTRACTOR.lastIndex = 0;
const {
groups: { video_domain, action, video_id },
} = YOUTUBE_ID_EXTRACTOR.exec(link_info.url) ?? { groups: {} };
if (!video_id) {
return;
}
return `
<div class="embed-container iframe ${action === "shorts" ? "vertical" : "letterbox"} youtube">
<div class="embed-actions-container">
<button class="icon plus" onclick="console.log(\"close\");"/>
<button class="icon pause" onclick="console.log(\"stop\");"/>
</div>
<iframe
src="https://www.youtube.com/embed/${video_id}"
title="YouTube video player"
allow="clipboard-write; encrypted-media; picture-in-picture; web-share;"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
loading="lazy"
></iframe>
</div>`;
}