diff --git a/site/index.html b/site/index.html index 91b540d..48a9ad2 100644 --- a/site/index.html +++ b/site/index.html @@ -94,7 +94,10 @@

Playlist

-

Up Next:

+
+

Up Next:

+ Clear Playlist +
diff --git a/site/partial/home.html b/site/partial/home.html index 29999c0..8285463 100644 --- a/site/partial/home.html +++ b/site/partial/home.html @@ -5,88 +5,32 @@ Radiostasis -

The home of streaming on-demand Old Time Radio.

-

What is Old Time Radio?

-

Old Time Radio shows are commercial audio programs that were broadcast over the air during the "Golden Age of Radio," an era that spans from the 1920s through the 1950s. Audio shows that were broadcast in the USA prior to 1972 were not subject to federal copyright protections, so as a result many of these old shows are available in the public domain.

-

To give you a concrete example, here are a few of my favorite episodes that you can listen to right now:

-
-
- cover image -
-
    -
  • Sci-Fi
  • -
- -
-
-
- cover image -
-
    -
  • Comedy
  • -
- -
-
-
- cover image -
-
    -
  • Adventure
  • -
  • Western
  • -
- - -
-
-
- cover image -
-
    -
  • Drama
  • -
- - -
-
-
-

What is Radiostasis?

-

Radiostasis started as an Android application back in 2017, but has since been shut down and rebooted here as a web-based Old Time Radio player. All of the episodes have been sourced from the Internet Archive, cataloged, and made available for on-demand playing. Click the All Series link in the sidebar, or select a specific genre to begin exploring the library.

+

Hello and a warm welcome to all of you, beloved radio enthusiasts and curious newcomers alike! We're delighted to have you here at Radiostasis. Our mission is to preserve and celebrate the Golden Age of Radio by offering you free access to a vast collection of old time radio shows that you can stream at your leisure.

+

We know how special these radio shows are to so many of you, and we're proud to provide a one-stop destination for a trip down memory lane. Our diverse library caters to all tastes, spanning from thrilling crime dramas, gripping mysteries and adventures, to side-splitting comedies and touching family sagas. Whether you're reliving cherished moments from your past or discovering the magic of Old Time Radio for the first time, you're sure to find something you love in our extensive collection.

+

We take pride in ensuring that our website is friendly and easy to navigate for users of all ages and abilities. If you require any assistance, please don't hesitate to contact our friendly customer support team, who are more than happy to help at support@radiostasis.com.

+

To begin your journey, simply visit the All Series page, or browse by genre from the menu. Enjoy, and thank you for joining us at Radiostasis!

+

About Radiostasis

+ + + + + + + + + + + + + +
Number of Series:271
Number of Episodes:29,548
Total Playtime:13,551 hours
+

Radiostasis started as an Android application back in 2017, but has since been shut down and rebooted here as a web-based Old Time Radio player. All of the episodes have been sourced from the Internet Archive, cataloged, and made available for on-demand playing.

Radiostasis is an open source passion project by Rudis Muiznieks, a software engineer who happens to love Old Time Radio. Radiostasis is a constant work in progress, with many improvements planned for the future. Currently the site is completely free to use—Rudis foots all the bills to host this site on his own—but premium features may be introduced in future updates to help offset some of the costs.

-

If you have any questions, suggestions, or just want to say hello, feel free to email Rudis at support@radiostasis.com.

+

Please send questions, bug reports, suggestions, or just say hello to Rudis at support@radiostasis.com.

Change Log

+

2023-04-09

+

Added a playlist system and the ability to queue up multiple episodes or entire series to play in order.

+

Also updated the landing page.

2023-04-05

Added series descriptions to the details pages. Descriptions were generated by ChatGPT as summaries of available information on Wikipedia, OTRR write ups on archive.org, the Old Time Radio Catalog, and other websites.

Also added a search field to series list pages, and fixed some bugs that would happen when you use your browser's forward and back buttons to navigate.

diff --git a/site/radiostasis.js b/site/radiostasis.js index 0a3d764..29ee0b4 100644 --- a/site/radiostasis.js +++ b/site/radiostasis.js @@ -149,6 +149,12 @@ var Player = /** @class */ (function () { _this.setErrorUI('Fetch episode error'); }); }; + Player.prototype.isPlaying = function () { + if (this.howl) { + return this.howl.playing(); + } + return false; + }; Player.prototype.setErrorUI = function (message) { this.stopPlaybackAndResetUi(); this.seriesName.innerHTML = 'Error playing episode'; @@ -317,8 +323,11 @@ var Playlist = /** @class */ (function () { this.queueTab = getOrThrow(this.queueContainer.getElementsByTagName('h2').item(0)); this.queueList = getOrThrow(this.queueContainer.getElementsByTagName('ol').item(0)); this.overlay = getOrThrow(document.getElementById('overlay')); + this.clearButton = getOrThrow(document.getElementById('clear-playlist')); + // wire up global playlist controls this.queueTab.addEventListener('click', function () { return _this.toggleQueueUI(); }); this.overlay.addEventListener('click', function () { return _this.toggleQueueUI(); }); + this.clearButton.addEventListener('click', function () { return _this.clearPlaylist(); }); } Playlist.prototype.addPlaylistChangedHandler = function (handler) { this.changedHandlers.push(handler); @@ -379,6 +388,12 @@ var Playlist = /** @class */ (function () { Playlist.prototype.triggerPlaylistChanged = function () { this.playlistChanged(); }; + Playlist.prototype.clearPlaylist = function () { + this.episodes.length = 0; + this.episodeHash.clear(); + this.queueList.innerHTML = ''; + this.playlistChanged(); + }; Playlist.prototype.playlistChanged = function () { for (var _i = 0, _a = this.changedHandlers; _i < _a.length; _i++) { var handler = _a[_i]; @@ -450,6 +465,13 @@ var Radiostasis = /** @class */ (function () { .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(); }); + // 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 = ''; + }); } Radiostasis.prototype.initialize = function () { var path = location.pathname == '/' diff --git a/site/style.css b/site/style.css index d4dedcf..a854a67 100644 --- a/site/style.css +++ b/site/style.css @@ -193,11 +193,6 @@ section img { flex: 1 1 20rem; } -.detail article { - font-size: 1.2rem; - line-height: 120%; -} - .detail article > p:not(:last-child) { margin-bottom: 1rem; } @@ -234,7 +229,7 @@ aside { } section div aside { - font-size: 0.8em; + font-size: 0.8rem; } aside :first-child { @@ -292,6 +287,14 @@ ol > li:not(:last-child) { margin: 0 1ch; } +#queue-container > div { + display: flex; + align-items: baseline; + padding-bottom: 1ex; + margin: 1rem 1rem 0 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.25); +} + #queue-container h2 { cursor: pointer; position: absolute; @@ -321,9 +324,14 @@ ol > li:not(:last-child) { font-family: Avenir, 'Avenir Next LT Pro', Montserrat, Corbel, 'URW Gothic', source-sans-pro, sans-serif; font-size: 1rem; font-weight: 600; - padding-bottom: 1ex; - margin: 1rem 1rem 0 1rem; - border-bottom: 1px solid rgba(0, 0, 0, 0.25); + flex-basis: 100%; +} + +#queue-container > div a { + font-size: 0.8rem; + font-family: ui-rounded, 'Hiragino Maru Gothic ProN', Quicksand, Comfortaa, Manjari, 'Arial Rounded MT Bold', Calibri, source-sans-pro, sans-serif; + white-space: nowrap; + background-image: url('/icon-trash.svg'); } #queue-container ol { @@ -486,15 +494,40 @@ button:disabled, button:active:disabled { margin: 0 auto; } +.home table { + font-family: Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', source-sans-pro, sans-serif; +} + +.home table td { + padding: 0.5rem; +} + +.home table tr:not(:first-child) { + border-top: 1px solid rgba(0, 0, 0, 0.25); +} + +.home table tr td:first-child { + text-align: right; +} + +.home table tr td:last-child { + font-weight: 600; +} + p { font-family: ui-rounded, 'Hiragino Maru Gothic ProN', Quicksand, Comfortaa, Manjari, 'Arial Rounded MT Bold', Calibri, source-sans-pro, sans-serif; - line-height: 150%; + font-size: 1.2rem; + line-height: 120%; } p strong { font-weight: 600; } +p em { + font-style: italic; +} + .home > * + * { margin-block-start: 1.5rem; } @@ -543,14 +576,14 @@ h2 svg { .controls { margin: 0.25rem 0; - font-size: 0.8em; + font-size: 0.8rem; font-family: ui-rounded, 'Hiragino Maru Gothic ProN', Quicksand, Comfortaa, Manjari, 'Arial Rounded MT Bold', Calibri, source-sans-pro, sans-serif; display: flex; flex-wrap: nowrap; gap: 0.5rem; } -.controls a, .playing .controls a:hover { +.controls a, .playing .controls a:hover, #queue-container div a { display: block; padding: 0.25rem 0.5rem 0.25rem 1.25rem; border: 1px solid black; @@ -562,7 +595,7 @@ h2 svg { background-position: 0 50%; } -.controls a:hover { +.controls a:hover, #queue-container div a:hover { text-shadow: none; color: #c50; box-shadow: 0.125rem 0.125rem 0.25rem rgba(0, 0, 0, 0.75); @@ -617,3 +650,4 @@ h2 svg { padding-right: 0.5rem; } } +} diff --git a/src/Player.ts b/src/Player.ts index fb18ca0..bdd0297 100644 --- a/src/Player.ts +++ b/src/Player.ts @@ -150,6 +150,13 @@ class Player { }); } + public isPlaying(): boolean { + if (this.howl) { + return this.howl.playing(); + } + return false; + } + private setErrorUI(message: string): void { this.stopPlaybackAndResetUi(); this.seriesName.innerHTML = 'Error playing episode'; diff --git a/src/Playlist.ts b/src/Playlist.ts index 9409683..c785350 100644 --- a/src/Playlist.ts +++ b/src/Playlist.ts @@ -3,6 +3,8 @@ class Playlist { private readonly queueTab: HTMLElement; private readonly overlay: HTMLElement; private readonly queueList: HTMLOListElement; + private readonly clearButton: HTMLAnchorElement; + private readonly queueInitialHeight: string; private readonly queueExpandedHeight = 'calc(100% - 6ex)'; @@ -26,9 +28,14 @@ class Playlist { this.queueContainer.getElementsByTagName('ol').item(0) ); this.overlay = getOrThrow(document.getElementById('overlay')); + this.clearButton = getOrThrow( + document.getElementById('clear-playlist') + ); + // wire up global playlist controls this.queueTab.addEventListener('click', () => this.toggleQueueUI()); this.overlay.addEventListener('click', () => this.toggleQueueUI()); + this.clearButton.addEventListener('click', () => this.clearPlaylist()); } public addPlaylistChangedHandler(handler: () => void): void { @@ -95,6 +102,13 @@ class Playlist { this.playlistChanged(); } + public clearPlaylist(): void { + this.episodes.length = 0; + this.episodeHash.clear(); + this.queueList.innerHTML = ''; + this.playlistChanged(); + } + private playlistChanged(): void { for (const handler of this.changedHandlers) { handler(); diff --git a/src/Radiostasis.ts b/src/Radiostasis.ts index 9e70e7b..9c038de 100644 --- a/src/Radiostasis.ts +++ b/src/Radiostasis.ts @@ -26,6 +26,13 @@ class Radiostasis { // set up playlist changed handler this.playlist.addPlaylistChangedHandler(() => this.episodeStateChanged()); + + // set up prompt to prevent accidentally leaving the page while playing + window.addEventListener('beforeunload', (e) => { + if (!this.player.isPlaying()) return undefined; + e.preventDefault(); + e.returnValue = ''; + }); } public initialize(): void {