From 05d6ecfff0d38c08b753065e4eb99d6de1a4b280 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Mon, 31 Mar 2025 12:13:14 -0500 Subject: [PATCH] media player updates --- src/webpage/contextmenu.ts | 7 ++++- src/webpage/media.ts | 57 +++++++++++++++++++++++++++++++++++++- src/webpage/settings.ts | 4 ++- src/webpage/style.css | 5 ++++ translations/en.json | 7 ++++- 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/webpage/contextmenu.ts b/src/webpage/contextmenu.ts index a51508a..57e6e63 100644 --- a/src/webpage/contextmenu.ts +++ b/src/webpage/contextmenu.ts @@ -183,13 +183,18 @@ class Contextmenu { other: y, touchDrag: (x: number, y: number) => unknown = () => {}, touchEnd: (x: number, y: number) => unknown = () => {}, + click: "right" | "left" = "right", ) { const func = (event: MouseEvent) => { event.preventDefault(); event.stopImmediatePropagation(); this.makemenu(event.clientX, event.clientY, addinfo, other); }; - obj.addEventListener("contextmenu", func); + if (click === "right") { + obj.addEventListener("contextmenu", func); + } else { + obj.addEventListener("click", func); + } //NOTE not sure if this code is correct, seems fine at least for now if (mobile) { let hold: NodeJS.Timeout | undefined; diff --git a/src/webpage/media.ts b/src/webpage/media.ts index 3ffe50e..8909667 100644 --- a/src/webpage/media.ts +++ b/src/webpage/media.ts @@ -1,5 +1,50 @@ +import {Contextmenu} from "./contextmenu.js"; import {I18n} from "./i18n.js"; +import {Dialog} from "./settings.js"; +const menu = new Contextmenu("media"); +menu.addButton( + () => I18n.media.download(), + function () { + const a = document.createElement("a"); + a.href = this.src; + a.download = this.filename; + a.click(); + }, +); +menu.addButton( + () => I18n.media.moreInfo(), + async function () { + const di = new Dialog(this.title); + const options = di.float.options; + if (this.img) { + const img = document.createElement("img"); + img.classList.add("media-medium"); + img.src = this.img.url; + if (this.img.description) img.alt = this.img.description; + options.addHTMLArea(img); + } + if (this.artist) { + options.addText(I18n.media.artist(this.artist)); + } + if (this.composer) { + options.addText(I18n.media.composer(this.composer)); + } + { + const mins = Math.floor((await this.length) / 60000); + const seconds = Math.round(((await this.length) - mins * 60000) / 1000); + options.addText(I18n.media.length(mins + "", seconds + "")); + } + di.show(); + if (this.copyright) { + const text = options.addText(this.copyright); + const txt = text.elm.deref(); + if (txt) { + txt.classList.add("timestamp"); + } + } + }, +); type mediaEvents = | { type: "play"; @@ -66,6 +111,14 @@ function makePlayBox(mor: string | media, player: MediaPlayer, ctime = 0) { span.textContent = I18n.media.notFound(); return; } + menu.bindContextmenu( + more, + thing, + undefined, + () => {}, + () => {}, + "left", + ); player.addListener(thing.src, followUpdates, div); let int = setInterval((_) => {}, 1000); if (mor instanceof Object) { @@ -183,6 +236,7 @@ function makePlayBox(mor: string | media, player: MediaPlayer, ctime = 0) { interface media { src: string; + filename: string; img?: { url: string; description?: string; @@ -489,6 +543,7 @@ class MediaPlayer { } catch (e) { console.error(e); } finally { + output.filename = url.split("/").at(-1); controller.abort(); if (!output.length) { output.length = new Promise(async (res) => { @@ -504,7 +559,7 @@ class MediaPlayer { }); } if (!output.title) { - output.title = url.split("/").at(-1); + output.title = output.filename; } } resMedio(output as media); diff --git a/src/webpage/settings.ts b/src/webpage/settings.ts index 9e52657..d894b62 100644 --- a/src/webpage/settings.ts +++ b/src/webpage/settings.ts @@ -876,6 +876,7 @@ class Options implements OptionsElement { container.classList.add(this.ltr ? "flexltr" : "flexttb", "flexspace"); this.generateContainter(); div.append(container); + console.log(div); return div; } generateName(): (HTMLElement | string)[] { @@ -908,7 +909,8 @@ class Options implements OptionsElement { (this.owner instanceof Options && this.owner.subOptions !== this) || (this.owner instanceof Form && this.owner.owner.subOptions !== this.owner) || this.owner instanceof Settings || - this.owner instanceof Buttons + this.owner instanceof Buttons || + this.owner instanceof Float ); } generateContainter() { diff --git a/src/webpage/style.css b/src/webpage/style.css index edd95b6..56a114a 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -1337,6 +1337,11 @@ span.instanceStatus { margin-top: 4px; border-radius: 4px; } +.media-medium { + max-width: 1.2in !important; + max-height: 1in; + object-fit: contain; +} .media-small { max-width: 0.6in !important; max-height: 0.4in; diff --git a/translations/en.json b/translations/en.json index 6aec589..d4cfa3b 100644 --- a/translations/en.json +++ b/translations/en.json @@ -12,7 +12,12 @@ "copymessageid": "Copy message id", "media": { "notFound": "Media could not be found", - "loading": "Loading" + "loading": "Loading", + "download": "Download media", + "moreInfo": "More info", + "artist": "Artist: $1", + "composer": "Composer: $1", + "length": "Length: $1 minutes and $2 seconds" }, "permissions": { "descriptions": {