2023-04-08 14:32:17 -05:00
|
|
|
"use strict";
|
|
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
|
|
});
|
|
|
|
};
|
|
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
|
|
function step(op) {
|
|
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
|
|
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
|
|
switch (op[0]) {
|
|
|
|
case 0: case 1: t = op; break;
|
|
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
|
|
default:
|
|
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
|
|
if (t[2]) _.ops.pop();
|
|
|
|
_.trys.pop(); continue;
|
|
|
|
}
|
|
|
|
op = body.call(thisArg, _);
|
|
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
2023-04-07 23:46:30 -05:00
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
};
|
|
|
|
var Player = /** @class */ (function () {
|
2023-04-08 14:47:35 -05:00
|
|
|
function Player(playlist) {
|
2023-04-08 14:32:17 -05:00
|
|
|
var _this = this;
|
2023-04-08 14:47:35 -05:00
|
|
|
this.playlist = playlist;
|
2023-04-09 15:40:40 -05:00
|
|
|
this.playlist.setPlayEpisodeHandler(function (episode) { return _this.playEpisode(episode); });
|
|
|
|
var controls = getOrThrow(document.getElementById('controls'));
|
|
|
|
var timeVolume = getOrThrow(document.getElementById('timeVolume'));
|
|
|
|
this.nowPlaying = getOrThrow(document.getElementById('nowPlaying'));
|
|
|
|
this.rewButton = getOrThrow(controls.getElementsByTagName('button').item(0));
|
|
|
|
this.playButton = getOrThrow(controls.getElementsByTagName('button').item(1));
|
|
|
|
this.playButtonPath = getOrThrow(this.playButton.getElementsByTagName('path').item(0));
|
|
|
|
this.ffwButton = getOrThrow(controls.getElementsByTagName('button').item(2));
|
|
|
|
this.skipButton = getOrThrow(controls.getElementsByTagName('button').item(3));
|
|
|
|
this.cover = getOrThrow(this.nowPlaying.getElementsByTagName('img').item(0));
|
|
|
|
this.seriesName = getOrThrow(this.nowPlaying.getElementsByTagName('span').item(0));
|
|
|
|
this.episodeName = getOrThrow(this.nowPlaying.getElementsByTagName('span').item(1));
|
|
|
|
this.timeDisplay = getOrThrow(timeVolume.getElementsByTagName('span').item(0));
|
|
|
|
this.volumeSlider = getOrThrow(timeVolume.getElementsByTagName('input').item(0));
|
|
|
|
this.progress = getOrThrow(document.getElementById('progress'));
|
2023-04-08 14:32:17 -05:00
|
|
|
this.ticker = null;
|
|
|
|
this.howl = null;
|
|
|
|
this.episode = null;
|
|
|
|
// initialize to stopped state
|
|
|
|
this.stopPlaybackAndResetUi();
|
|
|
|
// wire up static ui elements
|
|
|
|
this.playButton.addEventListener('click', function () { return _this.playPause(); });
|
|
|
|
this.rewButton.addEventListener('click', function () { return _this.rewind(); });
|
|
|
|
this.ffwButton.addEventListener('click', function () { return _this.fastForward(); });
|
2023-04-09 18:05:27 -05:00
|
|
|
this.skipButton.addEventListener('click', function () { return _this.nextEpisode(); });
|
2023-04-08 14:32:17 -05:00
|
|
|
this.volumeSlider.addEventListener('change', function () { return _this.setVolume(); });
|
|
|
|
// wire up mediaSession events
|
|
|
|
if ('mediaSession' in navigator) {
|
|
|
|
navigator.mediaSession.setActionHandler('pause', function () { return _this.playPause(); });
|
|
|
|
navigator.mediaSession.setActionHandler('play', function () { return _this.playPause(); });
|
|
|
|
navigator.mediaSession.setActionHandler('stop', function () {
|
|
|
|
return _this.stopPlaybackAndResetUi();
|
|
|
|
});
|
|
|
|
navigator.mediaSession.setActionHandler('seekforward', function () {
|
|
|
|
return _this.fastForward();
|
|
|
|
});
|
|
|
|
navigator.mediaSession.setActionHandler('seekbackward', function () {
|
|
|
|
return _this.rewind();
|
|
|
|
});
|
2023-04-09 18:05:27 -05:00
|
|
|
navigator.mediaSession.setActionHandler('nexttrack', function () {
|
|
|
|
return _this.nextEpisode();
|
|
|
|
});
|
2023-04-08 14:32:17 -05:00
|
|
|
// don't support previous track yet, queue removes them once finished
|
|
|
|
// wire this up to rewind instead
|
|
|
|
navigator.mediaSession.setActionHandler('previoustrack', function () {
|
|
|
|
return _this.rewind();
|
|
|
|
});
|
|
|
|
}
|
2023-04-08 14:47:35 -05:00
|
|
|
// set up playlist changed handler
|
2023-04-09 15:40:40 -05:00
|
|
|
this.playlist.addPlaylistChangedHandler(function () {
|
2023-04-08 14:47:35 -05:00
|
|
|
_this.skipButton.disabled = !_this.playlist.hasNextEpisode();
|
|
|
|
});
|
2023-03-26 11:37:20 -05:00
|
|
|
}
|
2023-04-09 15:40:40 -05:00
|
|
|
Player.prototype.currentEpisode = function () {
|
|
|
|
return this.episode;
|
2023-04-08 14:32:17 -05:00
|
|
|
};
|
2023-04-09 15:40:40 -05:00
|
|
|
Player.prototype.playEpisode = function (episode, paused) {
|
2023-04-08 14:32:17 -05:00
|
|
|
var _this = this;
|
2023-04-09 15:40:40 -05:00
|
|
|
if (paused === void 0) { paused = false; }
|
2023-04-08 14:32:17 -05:00
|
|
|
this.stopPlaybackAndResetUi();
|
|
|
|
this.setPauseButtonUI();
|
|
|
|
this.episode = episode;
|
2023-04-13 19:51:16 -05:00
|
|
|
this.playlist.removeEpisode(episode, false, false);
|
2023-04-08 14:32:17 -05:00
|
|
|
this.updateNowPlayingUI(true);
|
2023-04-09 15:40:40 -05:00
|
|
|
void fetch("/api/r/".concat(episode.file))
|
|
|
|
.then(function (res) { return __awaiter(_this, void 0, void 0, function () {
|
2023-04-08 14:32:17 -05:00
|
|
|
var link;
|
|
|
|
var _this = this;
|
|
|
|
return __generator(this, function (_a) {
|
|
|
|
switch (_a.label) {
|
|
|
|
case 0:
|
|
|
|
if (!res.ok) {
|
2023-04-13 19:51:16 -05:00
|
|
|
this.setErrorUI("Error fetching episode (".concat(res.status, ")"));
|
2023-04-08 14:32:17 -05:00
|
|
|
return [2 /*return*/];
|
|
|
|
}
|
|
|
|
return [4 /*yield*/, res.json()];
|
|
|
|
case 1:
|
|
|
|
link = _a.sent();
|
|
|
|
this.howl = new Howl({
|
|
|
|
src: "".concat(link.url, "?Authorization=").concat(link.token),
|
|
|
|
html5: true,
|
2023-04-09 15:40:40 -05:00
|
|
|
autoplay: !paused,
|
2023-04-08 14:32:17 -05:00
|
|
|
volume: this.getVolume(),
|
|
|
|
onload: function () {
|
|
|
|
_this.updateTimeUI();
|
|
|
|
_this.sendMediaSessionMetadata();
|
|
|
|
_this.updateNowPlayingUI();
|
|
|
|
_this.sendMediaSessionMetadata();
|
2023-04-09 15:40:40 -05:00
|
|
|
if (paused)
|
|
|
|
_this.setPlayButtonUI();
|
|
|
|
},
|
|
|
|
onplay: function () {
|
2023-04-08 14:32:17 -05:00
|
|
|
_this.setPauseButtonUI();
|
|
|
|
_this.startTicker();
|
|
|
|
},
|
|
|
|
onpause: function () {
|
|
|
|
_this.setPlayButtonUI();
|
|
|
|
_this.stopTicker();
|
|
|
|
},
|
2023-04-09 18:05:27 -05:00
|
|
|
onend: function () { return _this.nextEpisode(); },
|
2023-04-13 19:51:16 -05:00
|
|
|
onloaderror: function () { return _this.setErrorUI('Error playing episode.'); },
|
2023-04-08 14:32:17 -05:00
|
|
|
});
|
|
|
|
return [2 /*return*/];
|
|
|
|
}
|
|
|
|
});
|
2023-04-09 15:40:40 -05:00
|
|
|
}); })
|
|
|
|
.catch(function () {
|
2023-04-13 19:51:16 -05:00
|
|
|
_this.setErrorUI('Error downloading episode.');
|
2023-04-09 15:40:40 -05:00
|
|
|
});
|
|
|
|
};
|
2023-04-09 19:27:47 -05:00
|
|
|
Player.prototype.isPlaying = function () {
|
|
|
|
if (this.howl) {
|
|
|
|
return this.howl.playing();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
2023-04-09 15:40:40 -05:00
|
|
|
Player.prototype.setErrorUI = function (message) {
|
|
|
|
this.stopPlaybackAndResetUi();
|
2023-04-13 19:51:16 -05:00
|
|
|
Toastify({
|
|
|
|
text: message,
|
|
|
|
gravity: 'bottom',
|
|
|
|
position: 'right',
|
|
|
|
style: {
|
|
|
|
marginBottom: '10ex',
|
|
|
|
background: '#a00',
|
|
|
|
color: '#fff',
|
|
|
|
},
|
|
|
|
}).showToast();
|
2023-04-08 14:32:17 -05:00
|
|
|
};
|
|
|
|
Player.prototype.playPause = function () {
|
|
|
|
if (this.howl && this.howl.playing())
|
|
|
|
this.howl.pause();
|
|
|
|
else if (this.howl && !this.howl.playing())
|
|
|
|
this.howl.play();
|
|
|
|
};
|
|
|
|
Player.prototype.rewind = function () {
|
|
|
|
if (this.howl && this.howl.state() === 'loaded') {
|
|
|
|
var newPos = this.howl.seek() - 10;
|
|
|
|
if (newPos < 0)
|
|
|
|
newPos = 0;
|
|
|
|
this.howl.seek(newPos);
|
2023-04-08 14:47:35 -05:00
|
|
|
this.updateTimeUI();
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Player.prototype.fastForward = function () {
|
|
|
|
if (this.howl && this.howl.state() === 'loaded') {
|
|
|
|
var newPos = this.howl.seek() + 30;
|
|
|
|
if (newPos > this.howl.duration())
|
|
|
|
newPos = this.howl.duration();
|
|
|
|
this.howl.seek(newPos);
|
2023-04-08 14:47:35 -05:00
|
|
|
this.updateTimeUI();
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
};
|
2023-04-09 18:05:27 -05:00
|
|
|
Player.prototype.nextEpisode = function () {
|
|
|
|
var next = this.playlist.nextEpisode();
|
|
|
|
if (next)
|
|
|
|
this.playEpisode(next);
|
|
|
|
else {
|
|
|
|
this.stopPlaybackAndResetUi();
|
|
|
|
// manually trigger playlist changed
|
|
|
|
// so that currently playing media gets wiped
|
|
|
|
this.playlist.triggerPlaylistChanged();
|
|
|
|
}
|
|
|
|
};
|
2023-04-08 14:32:17 -05:00
|
|
|
Player.prototype.setPlayButtonUI = function () {
|
|
|
|
this.playButtonPath.setAttribute('d', 'M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM6.79 5.093A.5.5 0 0 0 6 5.5v5a.5.5 0 0 0 .79.407l3.5-2.5a.5.5 0 0 0 0-.814l-3.5-2.5z');
|
|
|
|
};
|
|
|
|
Player.prototype.setPauseButtonUI = function () {
|
|
|
|
this.playButtonPath.setAttribute('d', 'M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM6.25 5C5.56 5 5 5.56 5 6.25v3.5a1.25 1.25 0 1 0 2.5 0v-3.5C7.5 5.56 6.94 5 6.25 5zm3.5 0c-.69 0-1.25.56-1.25 1.25v3.5a1.25 1.25 0 1 0 2.5 0v-3.5C11 5.56 10.44 5 9.75 5z');
|
|
|
|
};
|
|
|
|
Player.prototype.getVolume = function () {
|
|
|
|
return parseFloat(this.volumeSlider.value) / 100;
|
|
|
|
};
|
|
|
|
Player.prototype.setVolume = function () {
|
|
|
|
var _a;
|
|
|
|
(_a = this.howl) === null || _a === void 0 ? void 0 : _a.volume(this.getVolume());
|
|
|
|
};
|
|
|
|
Player.prototype.updateNowPlayingUI = function (loading) {
|
|
|
|
if (loading === void 0) { loading = false; }
|
|
|
|
this.nowPlaying.classList.remove('error');
|
|
|
|
if (this.episode) {
|
|
|
|
this.seriesName.innerHTML = loading
|
|
|
|
? 'Loading episode'
|
|
|
|
: this.episode.series.title;
|
|
|
|
this.episodeName.innerHTML = this.episode.title;
|
2023-04-09 15:40:40 -05:00
|
|
|
this.cover.src = loading ? '/loading.gif' : this.episode.series.cover;
|
2023-04-08 14:32:17 -05:00
|
|
|
this.nowPlaying.title = "".concat(this.episode.series.title, "\n").concat(this.episode.title);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.seriesName.innerHTML = 'No episode playing';
|
|
|
|
this.episodeName.innerHTML = '';
|
|
|
|
this.cover.src = '/transparent.png';
|
|
|
|
this.nowPlaying.title = 'No episode playing';
|
|
|
|
}
|
|
|
|
if (loading || !this.episode) {
|
|
|
|
this.playButton.disabled = true;
|
|
|
|
this.rewButton.disabled = true;
|
|
|
|
this.ffwButton.disabled = true;
|
2023-04-09 18:05:27 -05:00
|
|
|
this.skipButton.disabled = true;
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.playButton.disabled = false;
|
|
|
|
this.rewButton.disabled = false;
|
|
|
|
this.ffwButton.disabled = false;
|
2023-04-09 18:05:27 -05:00
|
|
|
this.skipButton.disabled = !this.playlist.hasNextEpisode();
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Player.prototype.sendMediaSessionMetadata = function () {
|
|
|
|
if ('mediaSession' in navigator) {
|
|
|
|
if (this.episode) {
|
|
|
|
navigator.mediaSession.metadata = new MediaMetadata({
|
|
|
|
title: this.episode.title,
|
|
|
|
album: 'Radiostasis',
|
|
|
|
artist: this.episode.series.title,
|
2023-04-09 15:40:40 -05:00
|
|
|
artwork: [
|
|
|
|
{
|
2023-04-08 14:32:17 -05:00
|
|
|
src: this.episode.series.cover,
|
|
|
|
sizes: '256x256',
|
|
|
|
type: 'image/jpeg',
|
2023-04-09 15:40:40 -05:00
|
|
|
},
|
|
|
|
],
|
2023-04-08 14:32:17 -05:00
|
|
|
});
|
2023-04-05 18:48:21 -05:00
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
else {
|
|
|
|
navigator.mediaSession.metadata = null;
|
2023-04-05 18:48:21 -05:00
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Player.prototype.timeToDisplayString = function (time) {
|
|
|
|
var mins = Math.floor(time / 60);
|
2023-04-09 18:13:56 -05:00
|
|
|
var secs = Math.floor(time - mins * 60);
|
2023-04-08 14:32:17 -05:00
|
|
|
var secStr = secs < 10 ? "0".concat(secs) : secs.toString();
|
|
|
|
return "".concat(mins, ":").concat(secStr);
|
|
|
|
};
|
|
|
|
Player.prototype.updateTimeUI = function () {
|
|
|
|
if (this.howl && this.howl.state() === 'loaded') {
|
|
|
|
var total = this.howl.duration();
|
|
|
|
var current = this.howl.seek();
|
2023-04-09 15:40:40 -05:00
|
|
|
var pct = "".concat(Math.round((current / total) * 1000) / 10, "%");
|
2023-04-08 14:32:17 -05:00
|
|
|
var timeStamp = "".concat(this.timeToDisplayString(current), " / ").concat(this.timeToDisplayString(total));
|
|
|
|
// set the new values if they've changed since the last tick
|
|
|
|
if (this.timeDisplay.innerHTML !== timeStamp)
|
|
|
|
this.timeDisplay.innerHTML = timeStamp;
|
|
|
|
if (this.progress.style.width !== pct)
|
|
|
|
this.progress.style.width = pct;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.timeDisplay.innerHTML = '--:-- / --:--';
|
|
|
|
this.progress.style.width = '0%';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Player.prototype.startTicker = function () {
|
|
|
|
var _this = this;
|
|
|
|
if (!this.ticker) {
|
|
|
|
this.ticker = setInterval(function () { return _this.updateTimeUI(); }, 500);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Player.prototype.stopTicker = function () {
|
|
|
|
if (this.ticker) {
|
|
|
|
clearInterval(this.ticker);
|
|
|
|
this.ticker = null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Player.prototype.stopPlaybackAndResetUi = function () {
|
|
|
|
var _a;
|
|
|
|
(_a = this.howl) === null || _a === void 0 ? void 0 : _a.unload();
|
|
|
|
this.howl = null;
|
|
|
|
this.episode = null;
|
|
|
|
this.setPlayButtonUI();
|
|
|
|
this.updateNowPlayingUI();
|
|
|
|
this.sendMediaSessionMetadata();
|
|
|
|
this.stopTicker();
|
|
|
|
this.updateTimeUI();
|
|
|
|
};
|
|
|
|
return Player;
|
|
|
|
}());
|
|
|
|
var Playlist = /** @class */ (function () {
|
2023-04-08 14:47:35 -05:00
|
|
|
function Playlist() {
|
2023-04-08 14:32:17 -05:00
|
|
|
var _this = this;
|
|
|
|
this.queueExpandedHeight = 'calc(100% - 6ex)';
|
2023-04-09 15:40:40 -05:00
|
|
|
// event handlers
|
|
|
|
this.changedHandlers = [];
|
|
|
|
this.playEpisodeHandler = null;
|
|
|
|
// the actual episode queue
|
|
|
|
this.episodes = [];
|
|
|
|
this.episodeHash = new Set();
|
|
|
|
this.queueContainer = getOrThrow(document.getElementById('queue-container'));
|
2023-04-08 14:32:17 -05:00
|
|
|
this.queueInitialHeight = getComputedStyle(this.queueContainer).height;
|
2023-04-09 15:40:40 -05:00
|
|
|
this.queueTab = getOrThrow(this.queueContainer.getElementsByTagName('h2').item(0));
|
|
|
|
this.queueList = getOrThrow(this.queueContainer.getElementsByTagName('ol').item(0));
|
|
|
|
this.overlay = getOrThrow(document.getElementById('overlay'));
|
2023-04-09 19:27:47 -05:00
|
|
|
this.clearButton = getOrThrow(document.getElementById('clear-playlist'));
|
|
|
|
// wire up global playlist controls
|
2023-04-08 14:32:17 -05:00
|
|
|
this.queueTab.addEventListener('click', function () { return _this.toggleQueueUI(); });
|
|
|
|
this.overlay.addEventListener('click', function () { return _this.toggleQueueUI(); });
|
2023-04-09 19:27:47 -05:00
|
|
|
this.clearButton.addEventListener('click', function () { return _this.clearPlaylist(); });
|
2023-04-05 18:48:21 -05:00
|
|
|
}
|
2023-04-09 15:40:40 -05:00
|
|
|
Playlist.prototype.addPlaylistChangedHandler = function (handler) {
|
|
|
|
this.changedHandlers.push(handler);
|
|
|
|
};
|
|
|
|
Playlist.prototype.setPlayEpisodeHandler = function (handler) {
|
|
|
|
this.playEpisodeHandler = handler;
|
|
|
|
};
|
|
|
|
Playlist.prototype.hasNextEpisode = function () {
|
|
|
|
return this.episodes.length > 0;
|
|
|
|
};
|
|
|
|
Playlist.prototype.nextEpisode = function () {
|
|
|
|
if (this.episodes.length > 0) {
|
|
|
|
return this.episodes[0][0];
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
Playlist.prototype.pushEpisode = function (episode) {
|
2023-04-09 17:50:17 -05:00
|
|
|
this.pushEpisodes([episode]);
|
|
|
|
};
|
|
|
|
Playlist.prototype.pushEpisodes = function (episodes) {
|
|
|
|
for (var _i = 0, episodes_1 = episodes; _i < episodes_1.length; _i++) {
|
|
|
|
var episode = episodes_1[_i];
|
|
|
|
if (this.isQueued(episode))
|
2023-04-13 19:51:16 -05:00
|
|
|
this.removeEpisode(episode, true, false);
|
2023-04-09 15:40:40 -05:00
|
|
|
var litem = this.createQueueListItem(episode);
|
|
|
|
this.episodes.push([episode, litem]);
|
|
|
|
this.episodeHash.add(episode.id);
|
|
|
|
this.queueList.appendChild(litem);
|
|
|
|
}
|
2023-04-13 19:51:16 -05:00
|
|
|
this.notify(episodes.length == 1
|
|
|
|
? 'Episode added to queue.'
|
|
|
|
: "".concat(episodes.length, " episodes added to queue."));
|
2023-04-09 15:40:40 -05:00
|
|
|
this.playlistChanged();
|
|
|
|
};
|
|
|
|
Playlist.prototype.unshiftEpisodes = function (episodes) {
|
|
|
|
for (var i = episodes.length - 1; i >= 0; i--) {
|
|
|
|
var episode = episodes[i];
|
|
|
|
if (this.isQueued(episode))
|
2023-04-13 19:51:16 -05:00
|
|
|
this.removeEpisode(episode, true, false);
|
2023-04-09 15:40:40 -05:00
|
|
|
var litem = this.createQueueListItem(episode);
|
|
|
|
this.episodes.unshift([episode, litem]);
|
|
|
|
this.episodeHash.add(episode.id);
|
|
|
|
this.queueList.prepend(litem);
|
|
|
|
}
|
2023-04-13 19:51:16 -05:00
|
|
|
this.notify(episodes.length == 1
|
|
|
|
? 'Episode added to queue.'
|
|
|
|
: "".concat(episodes.length, " episodes added to queue."));
|
2023-04-09 17:50:17 -05:00
|
|
|
this.playlistChanged();
|
2023-04-09 15:40:40 -05:00
|
|
|
};
|
2023-04-13 19:51:16 -05:00
|
|
|
Playlist.prototype.removeEpisode = function (episode, ignoreChanged, notify) {
|
2023-04-09 17:50:17 -05:00
|
|
|
if (ignoreChanged === void 0) { ignoreChanged = false; }
|
2023-04-13 19:51:16 -05:00
|
|
|
if (notify === void 0) { notify = true; }
|
2023-04-09 15:40:40 -05:00
|
|
|
if (this.isQueued(episode)) {
|
|
|
|
var idx = this.episodes.findIndex(function (e) { return e[0].id == episode.id; });
|
|
|
|
var deleted = this.episodes.splice(idx, 1);
|
|
|
|
this.episodeHash.delete(episode.id);
|
|
|
|
deleted[0][1].remove();
|
|
|
|
}
|
2023-04-09 17:50:17 -05:00
|
|
|
if (!ignoreChanged)
|
|
|
|
this.playlistChanged();
|
2023-04-13 19:51:16 -05:00
|
|
|
if (notify)
|
|
|
|
this.notify('Episode removed from queue.');
|
2023-04-09 15:40:40 -05:00
|
|
|
};
|
|
|
|
Playlist.prototype.isQueued = function (episode) {
|
|
|
|
return this.episodeHash.has(episode.id);
|
|
|
|
};
|
2023-04-09 18:05:27 -05:00
|
|
|
Playlist.prototype.triggerPlaylistChanged = function () {
|
|
|
|
this.playlistChanged();
|
|
|
|
};
|
2023-04-09 19:27:47 -05:00
|
|
|
Playlist.prototype.clearPlaylist = function () {
|
2023-04-13 19:51:16 -05:00
|
|
|
var removed = this.episodes.length;
|
2023-04-09 19:27:47 -05:00
|
|
|
this.episodes.length = 0;
|
|
|
|
this.episodeHash.clear();
|
|
|
|
this.queueList.innerHTML = '';
|
|
|
|
this.playlistChanged();
|
2023-04-13 19:51:16 -05:00
|
|
|
if (removed > 0) {
|
|
|
|
this.notify('Playlist cleared.');
|
|
|
|
}
|
2023-04-09 19:27:47 -05:00
|
|
|
};
|
2023-04-09 15:40:40 -05:00
|
|
|
Playlist.prototype.playlistChanged = function () {
|
|
|
|
for (var _i = 0, _a = this.changedHandlers; _i < _a.length; _i++) {
|
|
|
|
var handler = _a[_i];
|
|
|
|
handler();
|
|
|
|
}
|
|
|
|
};
|
2023-04-08 14:32:17 -05:00
|
|
|
Playlist.prototype.toggleQueueUI = function () {
|
|
|
|
if (this.queueContainer.style.height !== this.queueExpandedHeight) {
|
|
|
|
this.queueContainer.style.height = this.queueExpandedHeight;
|
2023-04-09 15:40:40 -05:00
|
|
|
this.overlay.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
|
2023-04-08 14:32:17 -05:00
|
|
|
this.overlay.style.backdropFilter = 'blur(5px)';
|
|
|
|
this.overlay.style.pointerEvents = 'auto';
|
2023-04-10 09:21:01 -05:00
|
|
|
this.queueTab.innerHTML = 'Close';
|
|
|
|
this.queueTab.classList.add('expanded');
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.queueContainer.style.height = this.queueInitialHeight;
|
|
|
|
this.overlay.style.backgroundColor = 'rgba(255, 255, 255, 0)';
|
|
|
|
this.overlay.style.backdropFilter = 'none';
|
|
|
|
this.overlay.style.pointerEvents = 'none';
|
2023-04-10 09:21:01 -05:00
|
|
|
this.queueTab.innerHTML = 'Playlist';
|
|
|
|
this.queueTab.classList.remove('expanded');
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
};
|
2023-04-09 15:40:40 -05:00
|
|
|
Playlist.prototype.createQueueListItem = function (episode) {
|
|
|
|
var _this = this;
|
|
|
|
var item = document.createElement('li');
|
|
|
|
item.classList.add('episode');
|
|
|
|
item.title = episode.title;
|
|
|
|
var label = document.createElement('label');
|
|
|
|
label.innerHTML = episode.title;
|
|
|
|
var sspan = document.createElement('span');
|
|
|
|
sspan.innerHTML = episode.series.title;
|
|
|
|
var aside = document.createElement('aside');
|
|
|
|
aside.appendChild(sspan);
|
|
|
|
var controls = document.createElement('div');
|
|
|
|
controls.classList.add('controls');
|
|
|
|
var playBtn = document.createElement('a');
|
|
|
|
playBtn.href = '#';
|
|
|
|
playBtn.innerHTML = 'Play Now';
|
|
|
|
playBtn.addEventListener('click', function () {
|
|
|
|
if (_this.playEpisodeHandler)
|
|
|
|
_this.playEpisodeHandler(episode);
|
|
|
|
});
|
|
|
|
var remBtn = document.createElement('a');
|
|
|
|
remBtn.href = '#';
|
|
|
|
remBtn.innerHTML = 'Remove';
|
|
|
|
remBtn.addEventListener('click', function () { return _this.removeEpisode(episode); });
|
|
|
|
controls.appendChild(playBtn);
|
|
|
|
controls.appendChild(remBtn);
|
|
|
|
item.appendChild(label);
|
|
|
|
item.appendChild(aside);
|
|
|
|
item.appendChild(controls);
|
|
|
|
return item;
|
2023-04-08 15:41:55 -05:00
|
|
|
};
|
2023-04-13 19:51:16 -05:00
|
|
|
Playlist.prototype.notify = function (message) {
|
|
|
|
Toastify({
|
|
|
|
text: message,
|
|
|
|
gravity: 'bottom',
|
|
|
|
position: 'right',
|
|
|
|
style: {
|
|
|
|
marginBottom: '10ex',
|
|
|
|
background: '#090',
|
|
|
|
color: '#fff',
|
|
|
|
},
|
|
|
|
}).showToast();
|
|
|
|
};
|
2023-04-08 14:32:17 -05:00
|
|
|
return Playlist;
|
|
|
|
}());
|
|
|
|
var Radiostasis = /** @class */ (function () {
|
|
|
|
function Radiostasis() {
|
|
|
|
var _this = this;
|
2023-04-09 15:40:40 -05:00
|
|
|
var _a;
|
2023-04-08 14:32:17 -05:00
|
|
|
this.lastSearch = null;
|
|
|
|
this.debouncer = null;
|
2023-04-08 14:47:35 -05:00
|
|
|
this.playlist = new Playlist();
|
|
|
|
this.player = new Player(this.playlist);
|
2023-04-09 15:40:40 -05:00
|
|
|
this.main = getOrThrow(document.getElementsByTagName('main').item(0));
|
2023-04-08 14:32:17 -05:00
|
|
|
// set up htmx event handlers
|
2023-04-09 15:40:40 -05:00
|
|
|
document.addEventListener('htmx:historyRestore', function () {
|
|
|
|
return _this.wireLoadedFragment();
|
|
|
|
});
|
|
|
|
(_a = document
|
|
|
|
.getElementsByTagName('main')
|
|
|
|
.item(0)) === null || _a === void 0 ? void 0 : _a.addEventListener('htmx:afterSwap', function () { return _this.wireLoadedFragment(); });
|
|
|
|
// set up playlist changed handler
|
|
|
|
this.playlist.addPlaylistChangedHandler(function () { return _this.episodeStateChanged(); });
|
2023-04-09 19:27:47 -05:00
|
|
|
// set up prompt to prevent accidentally leaving the page while playing
|
|
|
|
window.addEventListener('beforeunload', function (e) {
|
|
|
|
if (!_this.player.isPlaying())
|
|
|
|
return undefined;
|
|
|
|
e.preventDefault();
|
|
|
|
e.returnValue = '';
|
|
|
|
});
|
2023-04-05 18:48:21 -05:00
|
|
|
}
|
2023-04-09 15:40:40 -05:00
|
|
|
Radiostasis.prototype.initialize = function () {
|
|
|
|
var path = location.pathname == '/'
|
|
|
|
? '/partial/home.html'
|
|
|
|
: "/partial/".concat(location.pathname, ".html");
|
|
|
|
htmx.ajax('GET', path, 'main');
|
|
|
|
};
|
2023-04-08 14:32:17 -05:00
|
|
|
Radiostasis.prototype.wireLoadedFragment = function () {
|
|
|
|
var _this = this;
|
2023-04-09 17:50:17 -05:00
|
|
|
var _a, _b, _c, _d, _e;
|
|
|
|
// save a list of all episodes for the series play/queue buttons
|
|
|
|
var seriesEpisodes = [];
|
2023-04-08 14:32:17 -05:00
|
|
|
// episode play and queue buttons
|
|
|
|
var episodes = this.main.getElementsByClassName('episode');
|
|
|
|
var _loop_1 = function (i) {
|
|
|
|
var el = episodes.item(i);
|
2023-04-09 17:50:17 -05:00
|
|
|
if (!el || !el.dataset.episode)
|
|
|
|
return "continue";
|
|
|
|
var episode = JSON.parse(el.dataset.episode);
|
|
|
|
// save and store this model for later use
|
|
|
|
seriesEpisodes.push(episode);
|
2023-04-08 14:32:17 -05:00
|
|
|
// play button
|
2023-04-09 17:50:17 -05:00
|
|
|
(_a = el.getElementsByTagName('a')
|
|
|
|
.item(0)) === null || _a === void 0 ? void 0 : _a.addEventListener('click', function (e) {
|
2023-04-09 15:40:40 -05:00
|
|
|
var _a;
|
|
|
|
if (((_a = _this.player.currentEpisode()) === null || _a === void 0 ? void 0 : _a.id) !== episode.id) {
|
|
|
|
_this.player.playEpisode(episode);
|
|
|
|
}
|
2023-04-08 15:41:55 -05:00
|
|
|
e.preventDefault();
|
|
|
|
});
|
|
|
|
// queue button
|
2023-04-09 17:50:17 -05:00
|
|
|
(_b = el.getElementsByTagName('a')
|
|
|
|
.item(1)) === null || _b === void 0 ? void 0 : _b.addEventListener('click', function (e) {
|
2023-04-09 15:40:40 -05:00
|
|
|
var _a;
|
|
|
|
if (!_this.player.currentEpisode()) {
|
|
|
|
// if nothing is playing, first queued item gets loaded
|
|
|
|
// into the player but does not autoplay
|
|
|
|
_this.player.playEpisode(episode, true);
|
|
|
|
}
|
|
|
|
else if (((_a = _this.player.currentEpisode()) === null || _a === void 0 ? void 0 : _a.id) !== episode.id) {
|
|
|
|
if (_this.playlist.isQueued(episode)) {
|
|
|
|
_this.playlist.removeEpisode(episode);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_this.playlist.pushEpisode(episode);
|
|
|
|
}
|
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
e.preventDefault();
|
|
|
|
});
|
2023-04-09 17:50:17 -05:00
|
|
|
// set playing/queued state
|
|
|
|
this_1.updateEpisodeElementFromState(el, episode);
|
2023-04-08 14:32:17 -05:00
|
|
|
};
|
2023-04-09 15:40:40 -05:00
|
|
|
var this_1 = this;
|
2023-04-08 14:32:17 -05:00
|
|
|
for (var i = 0; i < episodes.length; i++) {
|
|
|
|
_loop_1(i);
|
|
|
|
}
|
2023-04-09 17:50:17 -05:00
|
|
|
// series play and queue buttons
|
|
|
|
var series = (_c = document
|
|
|
|
.getElementsByClassName('seriesDetails')
|
|
|
|
.item(0)) === null || _c === void 0 ? void 0 : _c.getElementsByTagName('section').item(0);
|
|
|
|
if (series) {
|
|
|
|
// play series button
|
|
|
|
(_d = series
|
|
|
|
.getElementsByTagName('a')
|
|
|
|
.item(0)) === null || _d === void 0 ? void 0 : _d.addEventListener('click', function () {
|
|
|
|
var _a;
|
|
|
|
_this.playlist.unshiftEpisodes(seriesEpisodes);
|
|
|
|
if (((_a = _this.player.currentEpisode()) === null || _a === void 0 ? void 0 : _a.id) !== seriesEpisodes[0].id) {
|
|
|
|
_this.player.playEpisode(seriesEpisodes[0]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_this.playlist.removeEpisode(seriesEpisodes[0]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// queue series button
|
|
|
|
(_e = series
|
|
|
|
.getElementsByTagName('a')
|
|
|
|
.item(1)) === null || _e === void 0 ? void 0 : _e.addEventListener('click', function () {
|
|
|
|
var toQueue = seriesEpisodes.filter(function (e) { var _a; return ((_a = _this.player.currentEpisode()) === null || _a === void 0 ? void 0 : _a.id) !== e.id; });
|
|
|
|
_this.playlist.pushEpisodes(toQueue);
|
|
|
|
// if nothing is playing, peel off the first episode and load it
|
|
|
|
// into the player without autoplay
|
|
|
|
if (!_this.player.currentEpisode()) {
|
|
|
|
_this.player.playEpisode(seriesEpisodes[0], true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
// series filter input
|
2023-04-09 15:40:40 -05:00
|
|
|
var filter = (this.main.getElementsByClassName('filter').item(0));
|
2023-04-08 14:32:17 -05:00
|
|
|
if (filter) {
|
|
|
|
if (this.lastSearch) {
|
|
|
|
filter.value = this.lastSearch;
|
|
|
|
this.lastSearch = null;
|
|
|
|
}
|
|
|
|
var allSeries_1 = this.main.getElementsByTagName('section');
|
|
|
|
filter.addEventListener('input', function () {
|
|
|
|
if (_this.debouncer)
|
|
|
|
clearTimeout(_this.debouncer);
|
|
|
|
_this.debouncer = setTimeout(function () {
|
|
|
|
_this.lastSearch = filter.value.toLowerCase();
|
|
|
|
var terms = _this.lastSearch.split(' ');
|
|
|
|
for (var i = 0; i < allSeries_1.length; i++) {
|
2023-04-09 17:50:17 -05:00
|
|
|
var series_1 = allSeries_1.item(i);
|
|
|
|
if (!series_1 || !series_1.dataset.filter)
|
2023-04-09 15:40:40 -05:00
|
|
|
continue;
|
2023-04-08 14:32:17 -05:00
|
|
|
var match = true;
|
|
|
|
for (var _i = 0, terms_1 = terms; _i < terms_1.length; _i++) {
|
|
|
|
var term = terms_1[_i];
|
2023-04-09 17:50:17 -05:00
|
|
|
if (term.length > 0 && series_1.dataset.filter.indexOf(term) < 0) {
|
2023-04-08 14:32:17 -05:00
|
|
|
match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (match)
|
2023-04-09 17:50:17 -05:00
|
|
|
series_1.classList.remove('no-match');
|
2023-04-08 14:32:17 -05:00
|
|
|
else
|
2023-04-09 17:50:17 -05:00
|
|
|
series_1.classList.add('no-match');
|
2023-04-08 14:32:17 -05:00
|
|
|
}
|
|
|
|
}, 499);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2023-04-09 17:50:17 -05:00
|
|
|
Radiostasis.prototype.updateEpisodeElementFromState = function (litem, episode) {
|
2023-04-09 15:40:40 -05:00
|
|
|
var _a;
|
2023-04-09 17:50:17 -05:00
|
|
|
if (((_a = this.player.currentEpisode()) === null || _a === void 0 ? void 0 : _a.id) === episode.id) {
|
|
|
|
litem.classList.add('playing');
|
|
|
|
getOrThrow(litem.getElementsByTagName('a').item(0)).innerHTML = 'Playing';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
litem.classList.remove('playing');
|
|
|
|
getOrThrow(litem.getElementsByTagName('a').item(0)).innerHTML =
|
|
|
|
'Play Episode';
|
|
|
|
}
|
|
|
|
var queueBtn = getOrThrow(litem.getElementsByTagName('a').item(1));
|
|
|
|
if (this.playlist.isQueued(episode)) {
|
|
|
|
queueBtn.classList.add('queued');
|
|
|
|
queueBtn.innerHTML = 'Remove from Queue';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
queueBtn.classList.remove('queued');
|
|
|
|
queueBtn.innerHTML = 'Queue Episode';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Radiostasis.prototype.episodeStateChanged = function () {
|
2023-04-09 15:40:40 -05:00
|
|
|
var episodes = this.main.getElementsByClassName('episode');
|
|
|
|
for (var i = 0; i < episodes.length; i++) {
|
|
|
|
var el = episodes.item(i);
|
2023-04-09 17:50:17 -05:00
|
|
|
if (!el || !el.dataset.episode)
|
2023-04-09 15:40:40 -05:00
|
|
|
continue;
|
2023-04-09 17:50:17 -05:00
|
|
|
var episode = JSON.parse(el.dataset.episode);
|
|
|
|
this.updateEpisodeElementFromState(el, episode);
|
2023-04-09 15:40:40 -05:00
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
};
|
|
|
|
return Radiostasis;
|
|
|
|
}());
|
2023-04-09 15:40:40 -05:00
|
|
|
function getOrThrow(element) {
|
|
|
|
if (!element) {
|
|
|
|
throw new Error("tried to get an element that doesn't exist");
|
|
|
|
}
|
|
|
|
return element;
|
|
|
|
}
|
2023-04-08 14:32:17 -05:00
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
// start application
|
|
|
|
new Radiostasis().initialize();
|
2023-03-26 11:37:20 -05:00
|
|
|
});
|