added toast notifications
This commit is contained in:
parent
e512862aed
commit
018b4d3b30
|
@ -5,6 +5,7 @@
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel='stylesheet' href='/style.css'>
|
<link rel='stylesheet' href='/style.css'>
|
||||||
|
<link rel='stylesheet' href='/toastify.min.css'>
|
||||||
<link rel='icon' type='image/png' sizes='32x32' href='/favicon-32x32.png'>
|
<link rel='icon' type='image/png' sizes='32x32' href='/favicon-32x32.png'>
|
||||||
<link rel='icon' type='image/png' sizes='16x16' href='/favicon-16x16.png'>
|
<link rel='icon' type='image/png' sizes='16x16' href='/favicon-16x16.png'>
|
||||||
<link rel='icon' type='image/svg' href='/favicon.svg'>
|
<link rel='icon' type='image/svg' href='/favicon.svg'>
|
||||||
|
@ -155,6 +156,7 @@
|
||||||
</footer>
|
</footer>
|
||||||
<script src='/htmx.min.js'></script>
|
<script src='/htmx.min.js'></script>
|
||||||
<script src='/howler.min.js'></script>
|
<script src='/howler.min.js'></script>
|
||||||
|
<script src='/toastify.min.js'></script>
|
||||||
<script src='/radiostasis.js'></script>
|
<script src='/radiostasis.js'></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -101,7 +101,7 @@ var Player = /** @class */ (function () {
|
||||||
this.stopPlaybackAndResetUi();
|
this.stopPlaybackAndResetUi();
|
||||||
this.setPauseButtonUI();
|
this.setPauseButtonUI();
|
||||||
this.episode = episode;
|
this.episode = episode;
|
||||||
this.playlist.removeEpisode(episode);
|
this.playlist.removeEpisode(episode, false, false);
|
||||||
this.updateNowPlayingUI(true);
|
this.updateNowPlayingUI(true);
|
||||||
void fetch("/api/r/".concat(episode.file))
|
void fetch("/api/r/".concat(episode.file))
|
||||||
.then(function (res) { return __awaiter(_this, void 0, void 0, function () {
|
.then(function (res) { return __awaiter(_this, void 0, void 0, function () {
|
||||||
|
@ -111,7 +111,7 @@ var Player = /** @class */ (function () {
|
||||||
switch (_a.label) {
|
switch (_a.label) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
this.setErrorUI("API returned ".concat(res.status));
|
this.setErrorUI("Error fetching episode (".concat(res.status, ")"));
|
||||||
return [2 /*return*/];
|
return [2 /*return*/];
|
||||||
}
|
}
|
||||||
return [4 /*yield*/, res.json()];
|
return [4 /*yield*/, res.json()];
|
||||||
|
@ -139,14 +139,14 @@ var Player = /** @class */ (function () {
|
||||||
_this.stopTicker();
|
_this.stopTicker();
|
||||||
},
|
},
|
||||||
onend: function () { return _this.nextEpisode(); },
|
onend: function () { return _this.nextEpisode(); },
|
||||||
onloaderror: function () { return _this.setErrorUI('Playback error'); },
|
onloaderror: function () { return _this.setErrorUI('Error playing episode.'); },
|
||||||
});
|
});
|
||||||
return [2 /*return*/];
|
return [2 /*return*/];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}); })
|
}); })
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
_this.setErrorUI('Fetch episode error');
|
_this.setErrorUI('Error downloading episode.');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Player.prototype.isPlaying = function () {
|
Player.prototype.isPlaying = function () {
|
||||||
|
@ -157,9 +157,16 @@ var Player = /** @class */ (function () {
|
||||||
};
|
};
|
||||||
Player.prototype.setErrorUI = function (message) {
|
Player.prototype.setErrorUI = function (message) {
|
||||||
this.stopPlaybackAndResetUi();
|
this.stopPlaybackAndResetUi();
|
||||||
this.seriesName.innerHTML = 'Error playing episode';
|
Toastify({
|
||||||
this.episodeName.innerHTML = message;
|
text: message,
|
||||||
this.nowPlaying.classList.add('error');
|
gravity: 'bottom',
|
||||||
|
position: 'right',
|
||||||
|
style: {
|
||||||
|
marginBottom: '10ex',
|
||||||
|
background: '#a00',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
}).showToast();
|
||||||
};
|
};
|
||||||
Player.prototype.playPause = function () {
|
Player.prototype.playPause = function () {
|
||||||
if (this.howl && this.howl.playing())
|
if (this.howl && this.howl.playing())
|
||||||
|
@ -351,28 +358,35 @@ var Playlist = /** @class */ (function () {
|
||||||
for (var _i = 0, episodes_1 = episodes; _i < episodes_1.length; _i++) {
|
for (var _i = 0, episodes_1 = episodes; _i < episodes_1.length; _i++) {
|
||||||
var episode = episodes_1[_i];
|
var episode = episodes_1[_i];
|
||||||
if (this.isQueued(episode))
|
if (this.isQueued(episode))
|
||||||
this.removeEpisode(episode, true);
|
this.removeEpisode(episode, true, false);
|
||||||
var litem = this.createQueueListItem(episode);
|
var litem = this.createQueueListItem(episode);
|
||||||
this.episodes.push([episode, litem]);
|
this.episodes.push([episode, litem]);
|
||||||
this.episodeHash.add(episode.id);
|
this.episodeHash.add(episode.id);
|
||||||
this.queueList.appendChild(litem);
|
this.queueList.appendChild(litem);
|
||||||
}
|
}
|
||||||
|
this.notify(episodes.length == 1
|
||||||
|
? 'Episode added to queue.'
|
||||||
|
: "".concat(episodes.length, " episodes added to queue."));
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
};
|
};
|
||||||
Playlist.prototype.unshiftEpisodes = function (episodes) {
|
Playlist.prototype.unshiftEpisodes = function (episodes) {
|
||||||
for (var i = episodes.length - 1; i >= 0; i--) {
|
for (var i = episodes.length - 1; i >= 0; i--) {
|
||||||
var episode = episodes[i];
|
var episode = episodes[i];
|
||||||
if (this.isQueued(episode))
|
if (this.isQueued(episode))
|
||||||
this.removeEpisode(episode, true);
|
this.removeEpisode(episode, true, false);
|
||||||
var litem = this.createQueueListItem(episode);
|
var litem = this.createQueueListItem(episode);
|
||||||
this.episodes.unshift([episode, litem]);
|
this.episodes.unshift([episode, litem]);
|
||||||
this.episodeHash.add(episode.id);
|
this.episodeHash.add(episode.id);
|
||||||
this.queueList.prepend(litem);
|
this.queueList.prepend(litem);
|
||||||
}
|
}
|
||||||
|
this.notify(episodes.length == 1
|
||||||
|
? 'Episode added to queue.'
|
||||||
|
: "".concat(episodes.length, " episodes added to queue."));
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
};
|
};
|
||||||
Playlist.prototype.removeEpisode = function (episode, ignoreChanged) {
|
Playlist.prototype.removeEpisode = function (episode, ignoreChanged, notify) {
|
||||||
if (ignoreChanged === void 0) { ignoreChanged = false; }
|
if (ignoreChanged === void 0) { ignoreChanged = false; }
|
||||||
|
if (notify === void 0) { notify = true; }
|
||||||
if (this.isQueued(episode)) {
|
if (this.isQueued(episode)) {
|
||||||
var idx = this.episodes.findIndex(function (e) { return e[0].id == episode.id; });
|
var idx = this.episodes.findIndex(function (e) { return e[0].id == episode.id; });
|
||||||
var deleted = this.episodes.splice(idx, 1);
|
var deleted = this.episodes.splice(idx, 1);
|
||||||
|
@ -381,6 +395,8 @@ var Playlist = /** @class */ (function () {
|
||||||
}
|
}
|
||||||
if (!ignoreChanged)
|
if (!ignoreChanged)
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
|
if (notify)
|
||||||
|
this.notify('Episode removed from queue.');
|
||||||
};
|
};
|
||||||
Playlist.prototype.isQueued = function (episode) {
|
Playlist.prototype.isQueued = function (episode) {
|
||||||
return this.episodeHash.has(episode.id);
|
return this.episodeHash.has(episode.id);
|
||||||
|
@ -389,10 +405,14 @@ var Playlist = /** @class */ (function () {
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
};
|
};
|
||||||
Playlist.prototype.clearPlaylist = function () {
|
Playlist.prototype.clearPlaylist = function () {
|
||||||
|
var removed = this.episodes.length;
|
||||||
this.episodes.length = 0;
|
this.episodes.length = 0;
|
||||||
this.episodeHash.clear();
|
this.episodeHash.clear();
|
||||||
this.queueList.innerHTML = '';
|
this.queueList.innerHTML = '';
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
|
if (removed > 0) {
|
||||||
|
this.notify('Playlist cleared.');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Playlist.prototype.playlistChanged = function () {
|
Playlist.prototype.playlistChanged = function () {
|
||||||
for (var _i = 0, _a = this.changedHandlers; _i < _a.length; _i++) {
|
for (var _i = 0, _a = this.changedHandlers; _i < _a.length; _i++) {
|
||||||
|
@ -449,6 +469,18 @@ var Playlist = /** @class */ (function () {
|
||||||
item.appendChild(controls);
|
item.appendChild(controls);
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
Playlist.prototype.notify = function (message) {
|
||||||
|
Toastify({
|
||||||
|
text: message,
|
||||||
|
gravity: 'bottom',
|
||||||
|
position: 'right',
|
||||||
|
style: {
|
||||||
|
marginBottom: '10ex',
|
||||||
|
background: '#090',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
}).showToast();
|
||||||
|
};
|
||||||
return Playlist;
|
return Playlist;
|
||||||
}());
|
}());
|
||||||
var Radiostasis = /** @class */ (function () {
|
var Radiostasis = /** @class */ (function () {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
/**
|
||||||
|
* Minified by jsDelivr using clean-css v5.3.0.
|
||||||
|
* Original file: /npm/toastify-js@1.12.0/src/toastify.css
|
||||||
|
*
|
||||||
|
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
* Toastify js 1.12.0
|
||||||
|
* https://github.com/apvarun/toastify-js
|
||||||
|
* @license MIT licensed
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Varun A P
|
||||||
|
*/
|
||||||
|
.toastify{padding:12px 20px;color:#fff;display:inline-block;box-shadow:0 3px 6px -1px rgba(0,0,0,.12),0 10px 36px -4px rgba(77,96,232,.3);background:-webkit-linear-gradient(315deg,#73a5ff,#5477f5);background:linear-gradient(135deg,#73a5ff,#5477f5);position:fixed;opacity:0;transition:all .4s cubic-bezier(.215, .61, .355, 1);border-radius:2px;cursor:pointer;text-decoration:none;max-width:calc(50% - 20px);z-index:2147483647}.toastify.on{opacity:1}.toast-close{background:0 0;border:0;color:#fff;cursor:pointer;font-family:inherit;font-size:1em;opacity:.4;padding:0 5px}.toastify-right{right:15px}.toastify-left{left:15px}.toastify-top{top:-150px}.toastify-bottom{bottom:-150px}.toastify-rounded{border-radius:25px}.toastify-avatar{width:1.5em;height:1.5em;margin:-7px 5px;border-radius:2px}.toastify-center{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content;max-width:-moz-fit-content}@media only screen and (max-width:360px){.toastify-left,.toastify-right{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content}}
|
||||||
|
/*# sourceMappingURL=/sm/cb4335d1b03e933ed85cb59fffa60cf51f07567ed09831438c60f59afd166464.map */
|
File diff suppressed because one or more lines are too long
|
@ -111,13 +111,13 @@ class Player {
|
||||||
this.stopPlaybackAndResetUi();
|
this.stopPlaybackAndResetUi();
|
||||||
this.setPauseButtonUI();
|
this.setPauseButtonUI();
|
||||||
this.episode = episode;
|
this.episode = episode;
|
||||||
this.playlist.removeEpisode(episode);
|
this.playlist.removeEpisode(episode, false, false);
|
||||||
this.updateNowPlayingUI(true);
|
this.updateNowPlayingUI(true);
|
||||||
|
|
||||||
void fetch(`/api/r/${episode.file}`)
|
void fetch(`/api/r/${episode.file}`)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
this.setErrorUI(`API returned ${res.status}`);
|
this.setErrorUI(`Error fetching episode (${res.status})`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const link = <UrlResponse>await res.json();
|
const link = <UrlResponse>await res.json();
|
||||||
|
@ -142,11 +142,11 @@ class Player {
|
||||||
this.stopTicker();
|
this.stopTicker();
|
||||||
},
|
},
|
||||||
onend: () => this.nextEpisode(),
|
onend: () => this.nextEpisode(),
|
||||||
onloaderror: () => this.setErrorUI('Playback error'),
|
onloaderror: () => this.setErrorUI('Error playing episode.'),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.setErrorUI('Fetch episode error');
|
this.setErrorUI('Error downloading episode.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,9 +159,16 @@ class Player {
|
||||||
|
|
||||||
private setErrorUI(message: string): void {
|
private setErrorUI(message: string): void {
|
||||||
this.stopPlaybackAndResetUi();
|
this.stopPlaybackAndResetUi();
|
||||||
this.seriesName.innerHTML = 'Error playing episode';
|
Toastify({
|
||||||
this.episodeName.innerHTML = message;
|
text: message,
|
||||||
this.nowPlaying.classList.add('error');
|
gravity: 'bottom',
|
||||||
|
position: 'right',
|
||||||
|
style: {
|
||||||
|
marginBottom: '10ex',
|
||||||
|
background: '#a00',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
}).showToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
private playPause(): void {
|
private playPause(): void {
|
||||||
|
|
|
@ -63,28 +63,42 @@ class Playlist {
|
||||||
|
|
||||||
public pushEpisodes(episodes: Array<Episode>): void {
|
public pushEpisodes(episodes: Array<Episode>): void {
|
||||||
for (const episode of episodes) {
|
for (const episode of episodes) {
|
||||||
if (this.isQueued(episode)) this.removeEpisode(episode, true);
|
if (this.isQueued(episode)) this.removeEpisode(episode, true, false);
|
||||||
const litem = this.createQueueListItem(episode);
|
const litem = this.createQueueListItem(episode);
|
||||||
this.episodes.push([episode, litem]);
|
this.episodes.push([episode, litem]);
|
||||||
this.episodeHash.add(episode.id);
|
this.episodeHash.add(episode.id);
|
||||||
this.queueList.appendChild(litem);
|
this.queueList.appendChild(litem);
|
||||||
}
|
}
|
||||||
|
this.notify(
|
||||||
|
episodes.length == 1
|
||||||
|
? 'Episode added to queue.'
|
||||||
|
: `${episodes.length} episodes added to queue.`
|
||||||
|
);
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public unshiftEpisodes(episodes: Array<Episode>): void {
|
public unshiftEpisodes(episodes: Array<Episode>): void {
|
||||||
for (let i = episodes.length - 1; i >= 0; i--) {
|
for (let i = episodes.length - 1; i >= 0; i--) {
|
||||||
const episode = episodes[i];
|
const episode = episodes[i];
|
||||||
if (this.isQueued(episode)) this.removeEpisode(episode, true);
|
if (this.isQueued(episode)) this.removeEpisode(episode, true, false);
|
||||||
const litem = this.createQueueListItem(episode);
|
const litem = this.createQueueListItem(episode);
|
||||||
this.episodes.unshift([episode, litem]);
|
this.episodes.unshift([episode, litem]);
|
||||||
this.episodeHash.add(episode.id);
|
this.episodeHash.add(episode.id);
|
||||||
this.queueList.prepend(litem);
|
this.queueList.prepend(litem);
|
||||||
}
|
}
|
||||||
|
this.notify(
|
||||||
|
episodes.length == 1
|
||||||
|
? 'Episode added to queue.'
|
||||||
|
: `${episodes.length} episodes added to queue.`
|
||||||
|
);
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeEpisode(episode: Episode, ignoreChanged = false): void {
|
public removeEpisode(
|
||||||
|
episode: Episode,
|
||||||
|
ignoreChanged = false,
|
||||||
|
notify = true
|
||||||
|
): void {
|
||||||
if (this.isQueued(episode)) {
|
if (this.isQueued(episode)) {
|
||||||
const idx = this.episodes.findIndex((e) => e[0].id == episode.id);
|
const idx = this.episodes.findIndex((e) => e[0].id == episode.id);
|
||||||
const deleted = this.episodes.splice(idx, 1);
|
const deleted = this.episodes.splice(idx, 1);
|
||||||
|
@ -92,6 +106,7 @@ class Playlist {
|
||||||
deleted[0][1].remove();
|
deleted[0][1].remove();
|
||||||
}
|
}
|
||||||
if (!ignoreChanged) this.playlistChanged();
|
if (!ignoreChanged) this.playlistChanged();
|
||||||
|
if (notify) this.notify('Episode removed from queue.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public isQueued(episode: Episode): boolean {
|
public isQueued(episode: Episode): boolean {
|
||||||
|
@ -103,10 +118,14 @@ class Playlist {
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearPlaylist(): void {
|
public clearPlaylist(): void {
|
||||||
|
const removed = this.episodes.length;
|
||||||
this.episodes.length = 0;
|
this.episodes.length = 0;
|
||||||
this.episodeHash.clear();
|
this.episodeHash.clear();
|
||||||
this.queueList.innerHTML = '';
|
this.queueList.innerHTML = '';
|
||||||
this.playlistChanged();
|
this.playlistChanged();
|
||||||
|
if (removed > 0) {
|
||||||
|
this.notify('Playlist cleared.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private playlistChanged(): void {
|
private playlistChanged(): void {
|
||||||
|
@ -162,4 +181,17 @@ class Playlist {
|
||||||
item.appendChild(controls);
|
item.appendChild(controls);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private notify(message: string): void {
|
||||||
|
Toastify({
|
||||||
|
text: message,
|
||||||
|
gravity: 'bottom',
|
||||||
|
position: 'right',
|
||||||
|
style: {
|
||||||
|
marginBottom: '10ex',
|
||||||
|
background: '#090',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
declare namespace StartToastifyInstance {
|
||||||
|
function reposition(): void;
|
||||||
|
interface Offset {
|
||||||
|
x: number | string;
|
||||||
|
y: number | string;
|
||||||
|
}
|
||||||
|
interface Options {
|
||||||
|
text?: string | undefined;
|
||||||
|
node?: Node | undefined;
|
||||||
|
duration?: number | undefined;
|
||||||
|
selector?: string | Node | undefined;
|
||||||
|
destination?: string | undefined;
|
||||||
|
newWindow?: boolean | undefined;
|
||||||
|
close?: boolean | undefined;
|
||||||
|
gravity?: 'top' | 'bottom' | undefined;
|
||||||
|
position?: 'left' | 'center' | 'right' | undefined;
|
||||||
|
avatar?: string | undefined;
|
||||||
|
className?: string | undefined;
|
||||||
|
stopOnFocus?: boolean | undefined;
|
||||||
|
callback?: (() => void) | undefined;
|
||||||
|
onClick?: (() => void) | undefined;
|
||||||
|
offset?: Offset | undefined;
|
||||||
|
escapeMarkup?: boolean | undefined;
|
||||||
|
style?: { [cssRule: string]: string };
|
||||||
|
oldestFirst?: boolean | undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare class Toastify {
|
||||||
|
readonly options: StartToastifyInstance.Options;
|
||||||
|
readonly toastElement: Element | null;
|
||||||
|
showToast(): void;
|
||||||
|
hideToast(): void;
|
||||||
|
}
|
||||||
|
declare function StartToastifyInstance(options?: Toastify.Options): Toastify;
|
||||||
|
export as namespace Toastify;
|
||||||
|
export = StartToastifyInstance;
|
Loading…
Reference in New Issue