Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b531910f6 | |||
| 63c8c060b2 | |||
| 597a645822 | |||
| 340cbb2487 |
+130
@@ -9,6 +9,136 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) — versi
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [1.0.0] — 2026-06-09 — Stability milestone
|
||||||
|
|
||||||
|
The plugin reaches version 1.0.0. **There are no functional changes from 0.7.6.** This release is a deliberate version-number signal that the public API is stable.
|
||||||
|
|
||||||
|
### What 1.0.0 commits to
|
||||||
|
|
||||||
|
From this release forward, the following surfaces are considered the **public API** and will not break in any 1.x release:
|
||||||
|
|
||||||
|
- **`wp_usermeta` storage shape**: `radio_state`, `radio_history`, `radio_favourites` — the key names, the per-user model, and the JSON shape of each entry (artist / title / station / station_id / at).
|
||||||
|
- **The 4-button search URL templates** (`radio_search_urls( $artist, $title )` → spotify / youtube / apple / bandcamp). These have already been ported byte-for-byte to RangerHQ Tuner; locking them here means downstream family members can mirror them indefinitely.
|
||||||
|
- **The Stations registry shape** (`radio_get_stations_flat()` / `radio_get_stations_grouped()` / `radio_find_station( $id )` return shapes). Custom adapter authors can rely on these.
|
||||||
|
- **The dedup rule** (sig = lowered `artist|title|station_id`, dedup against the last entry only). This is what `radio_log_track()` enforces; it's stable.
|
||||||
|
- **The cap rule** (`RADIO_HISTORY_CAP = 500`, FIFO from the front). Stable.
|
||||||
|
- **The `(unknown)` artist skip** (SomaFM dead-air placeholder is silently dropped from history). Stable.
|
||||||
|
|
||||||
|
Breaking changes to any of the above will go in 2.0.0 — not in 1.x.
|
||||||
|
|
||||||
|
### Why ship 1.0.0 now
|
||||||
|
|
||||||
|
Five days after going live on WordPress.org (2026-06-04) the plugin has 50+ downloads and the architecture has been re-used byte-for-byte by **RangerHQ Tuner** (Chrome Web Store, live 2026-06-09) and structurally re-used by **RangerHQ Buddy** (in wp.org review at time of writing). The pattern has crossed three surfaces (WordPress / Chrome browser / family-shared) and held; the public API is no longer changing every release.
|
||||||
|
|
||||||
|
The 0.x version range implicitly meant *"still iterating, might break things."* That is no longer accurate for this codebase. The 1.0.0 number is honest about what the plugin already is in practice: a mature, stable product backed by a proven cross-platform pattern.
|
||||||
|
|
||||||
|
### What 1.0.0 does NOT change
|
||||||
|
|
||||||
|
- No code touched in any source file
|
||||||
|
- No new permissions, settings, or admin UI
|
||||||
|
- No database migration required (storage shape was already locked)
|
||||||
|
- Existing user state (station / volume / history / favourites) survives intact
|
||||||
|
- Existing custom CSS / theme integrations continue to work
|
||||||
|
|
||||||
|
### Family context
|
||||||
|
|
||||||
|
This release ships the same day **Tuner v0.3.0 went LIVE on the Chrome Web Store**. Three RangerHQ family members shipped to or staying-in two marketplaces on 2026-06-09:
|
||||||
|
|
||||||
|
- **Radio** v1.0.0 (this release) — wp.org, live
|
||||||
|
- **Tuner** v0.3.0 — Chrome Web Store, live (the morning of 2026-06-09, ~15.5 hours after submission)
|
||||||
|
- **Buddy** v0.1.5 — wp.org, in round-2 review
|
||||||
|
|
||||||
|
The family pattern is now publicly proven across two platforms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [0.7.6] — 2026-06-03 — Plugin metadata cleanup (wp.org pre-review fix)
|
||||||
|
|
||||||
|
The WordPress.org Plugin Review Team's automated pre-review flagged two issues on 2026-06-03, both metadata-only — none touching the plugin code itself:
|
||||||
|
|
||||||
|
1. **Ownership verification** — the `ir240474@gmail.com` account email couldn't be linked to the "RangerHQ" brand by their automated checks. They explicitly call this out as the standard trap for first-time submitters using gmail with brand-flavoured plugin names: *"A gmail.com account cannot be used as a valid form of identification… You could be you, but you could also be anyone else."*
|
||||||
|
2. **`Plugin URI` returning 404** — the previously declared URL `https://icanhelp.ie/radio` was never published as a real page (it 404'd). Separately, `Author URI: https://rangersmyth.xyz/` was failing DNS resolution entirely (*"Could not resolve host"*).
|
||||||
|
|
||||||
|
Both are fixed in this release. None of the user-facing player behaviour, scoring logic, scheme list, or storage layout has changed — this release is strictly housekeeping to satisfy wp.org's identity checks before the human-reviewer pass.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **`Plugin URI:` header in `radio.php`** — `https://icanhelp.ie/radio` → `https://davidtkeane.com/rangerhq-radio`. The new URL is a real, live, public landing page (Charter serif / moss-green accent / three plugin screenshots / install + source links / recent-changes summary) hosted at the author's personal-brand domain.
|
||||||
|
- **`Author URI:` header in `radio.php`** — `https://rangersmyth.xyz/` → `https://davidtkeane.com`. The previous URL was returning a DNS failure; the new URL resolves to the author's existing WordPress site (live since August 2025) and signals brand consistency between the wp.org username, the plugin's brand name, and the author's domain.
|
||||||
|
- **`Version:` header + `RADIO_VERSION` constant** → `0.7.6`.
|
||||||
|
- **`readme.txt` Stable tag** → `0.7.6`.
|
||||||
|
- **`inc/about.php`** — v0.7.6 in the "latest" slot; v0.7.5 demoted to one-liner in earlier-releases list.
|
||||||
|
|
||||||
|
### Added (ownership verification — domain-side, not in the plugin code)
|
||||||
|
|
||||||
|
- **DNS TXT record at the root of `davidtkeane.com`** containing `wordpressorg-ir240474-verification`. Lives on Cloudflare (which is the authoritative nameserver for the domain). Verified live across multiple public DNS resolvers before this release was prepared.
|
||||||
|
- **wp.org account email changed** from `david.keane.1974@gmail.com` to `david@davidtkeane.com` — domain-matched to the brand. Provides a second, independent ownership proof on top of the DNS TXT record.
|
||||||
|
|
||||||
|
### Why this is the right answer (and the alternatives weren't)
|
||||||
|
|
||||||
|
The wp.org reviewer email offered four resolution paths: change wp.org email, transfer to another account, rename the plugin to not look like an entity, or DNS-TXT verify. We took the **DNS-TXT + email-change combination** because:
|
||||||
|
|
||||||
|
- Renaming the plugin/slug would lose the "RangerHQ family" branding we'd already locked in at v0.7.5 (the slug is also irrevocable post-approval, so changing it AGAIN would have been costly).
|
||||||
|
- Transferring to another account would have lost the `ir240474` continuity and existing review thread.
|
||||||
|
- The author already controls `davidtkeane.com` (locked as the canonical RangerHQ brand domain in May 2026), and Cloudflare-managed DNS for the same domain — adding a TXT record there was a 5-minute operation.
|
||||||
|
- Setting up `david@davidtkeane.com` and switching the wp.org email to it gave a second independent proof and means all future reviewer correspondence lands at a brand-domain inbox.
|
||||||
|
|
||||||
|
The combination gives wp.org's identity bot two independent corroborating signals (DNS proves domain control, branded email proves brand operation). Future RangerHQ-family submissions (a-buddy, a-logbook, rangerhq-spatial, rangerhq-glyph) will skip this round-trip entirely because the trust relationship is now established at the wp.org account level.
|
||||||
|
|
||||||
|
### Files changed
|
||||||
|
|
||||||
|
`radio.php` · `readme.txt` · `inc/about.php` · `CHANGELOG.md`. Zero changes to `assets/css/radio.css`, `assets/js/radio.js`, or any `inc/*.php` other than `about.php`.
|
||||||
|
|
||||||
|
### Migration
|
||||||
|
|
||||||
|
None. v0.7.5 installs receive v0.7.6 as a normal update; all user state (`radio_state`, `radio_history`, `radio_favourites`) survives the upgrade unchanged because the metadata changes don't touch storage or scoring logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [0.7.5] — 2026-05-30 — WordPress.org slug rename: `a-radio` → `rangerhq-radio`
|
||||||
|
|
||||||
|
A third-party AI-driven naming-check tool (run via Plugin Check's Claude AI connector against the v0.7.4 build) flagged the slug as too generic for the wp.org Plugin Directory:
|
||||||
|
|
||||||
|
> The display name "a-radio" is too generic. The term "radio" is a broadly used, common functional word, and the single-letter prefix "a-" does not add meaningful distinctiveness or describe what the plugin actually does. With 60,000+ plugins in the directory, a name this short and generic makes it hard for users to identify the plugin and distinguish it from others.
|
||||||
|
|
||||||
|
The verdict was advisory (not the official wp.org reviewer) but defensible — single-word generic slugs are increasingly rejected by human reviewers as the directory grows. Better to fix it preemptively than face a rejection at submission time.
|
||||||
|
|
||||||
|
The new slug `rangerhq-radio` matches the public display name "RangerHQ Radio" (which is unchanged) and lines up with the rest of the RangerHQ plugin family: `rangerhq-spatial`, `rangerhq-glyph`, now `rangerhq-radio`. Consistent prefix, distinctive enough for the directory, descriptive of what the plugin does.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Plugin slug** `a-radio` → `rangerhq-radio`. The slug is the plugin's folder name + the URL fragment at `wordpress.org/plugins/<slug>/`. Folder renamed on disk; Gitea repository moved from `ranger/a-radio` to `ranger/rangerhq-radio` (history + tags + issues preserved by Gitea's rename).
|
||||||
|
- **Text Domain** `a-radio` → `rangerhq-radio` to match the slug (wp.org best practice + PCP `textdomain_mismatch` requirement). All 125 i18n call sites updated via in-place `sed` across every `*.php` file: `__()`, `_e()`, `esc_html__()`, `esc_html_e()`, `esc_attr__()`, `esc_attr_e()`, and the translator-comment arguments. PHP lint clean post-rename.
|
||||||
|
- **`Text Domain:` plugin header** in `radio.php` line 15 updated to match.
|
||||||
|
- **`RADIO_GITEA_URL` constant** value updated from `https://git.davidtkeane.com/ranger/a-radio` to `https://git.davidtkeane.com/ranger/rangerhq-radio` to follow the Gitea repo rename. The constant name stays the same (internal naming; no churn).
|
||||||
|
- **Install URL in root `README.md`** — repo link in the install step updated.
|
||||||
|
- **Gitea issue link in `readme.txt` FAQ** — updated to the new repo URL.
|
||||||
|
- **`readme.txt` Stable tag** → `0.7.5`.
|
||||||
|
- **`inc/about.php` Version history** — v0.7.5 rotated into the "latest" slot; v0.7.4 demoted to a one-liner in the earlier-releases list.
|
||||||
|
|
||||||
|
### Unchanged (deliberately — would have been pure churn)
|
||||||
|
- **Plugin Name header** (`RangerHQ Radio`) — already correct, distinctive, and brand-aligned.
|
||||||
|
- **Plugin URI** (`https://icanhelp.ie/radio`).
|
||||||
|
- **Internal PHP constants** (`RADIO_VERSION`, `RADIO_FILE`, `RADIO_PATH`, `RADIO_URL`, `RADIO_BASENAME`, `RADIO_GITEA_URL`, `RADIO_SUPPORT_URL`, `RADIO_META_KEY`). Constants don't have to match the slug; renaming them would have rippled through every PHP file for zero functional benefit.
|
||||||
|
- **User-meta keys** (`radio_state`, `radio_history`, `radio_favourites`). Renaming would have orphaned every existing user's settings + history + favourites on upgrade.
|
||||||
|
- **HTML `data-radio-*` attributes** in the player markup (`data-radio-play`, `data-radio-viz`, `data-radio-station`, etc.) — these are the JS controller's element selectors in `radio.js`, not slug-related. They share the word "radio" by coincidence; renaming would have required corresponding `radio.js` changes for zero benefit.
|
||||||
|
- **CSS class names** (`radio-player`, `radio-player__*`, `radio-about-*`, etc.) — same reasoning. Internal scoping.
|
||||||
|
- **Main plugin file name** (`radio.php`). WordPress doesn't require the main file to be named after the slug; it just has to exist in the slug folder. Many plugins ship with `<slug>/<short-name>.php`. Keeping `radio.php` saved a rename + a corresponding update to every git reference.
|
||||||
|
|
||||||
|
### Migration
|
||||||
|
- **wp.org installs** (once accepted): no migration — wp.org will accept the plugin under the new slug from day one.
|
||||||
|
- **Existing Gitea-installed copies** (the local dev install at `/Users/ranger/Local Sites/plugin-test/.../a-radio/` was renamed in-place to `.../rangerhq-radio/` as part of this release; M5 or other Gitea installs would need the same): deactivate the plugin in WP admin (so WP releases its hold on `a-radio/radio.php`), rename the folder on disk, reactivate via the new entry at `rangerhq-radio/radio.php`. WordPress's `active_plugins` option in `wp_options` is keyed on the basename (`folder/file.php`), so a folder rename appears to WP as an uninstall + a new install — but no data is lost because all user-facing state lives in `user_meta` under unchanged keys (`radio_state` / `radio_history` / `radio_favourites`).
|
||||||
|
- **Tags + git history**: preserved across the Gitea repo rename. The annotated tag for v0.7.5 was pushed AFTER the Gitea repo rename so it lives in the new URL space from the start.
|
||||||
|
|
||||||
|
### Why the slug matters even though "RangerHQ Radio" is fine
|
||||||
|
WordPress.org reviewers evaluate two strings independently — the **display name** (Plugin Name header, what users see in their admin) and the **slug** (folder name, what appears in the URL at `wordpress.org/plugins/<slug>/`). They have to be distinct enough that:
|
||||||
|
- Users can find the plugin via wp.org search.
|
||||||
|
- The URL is recognisable and not easily confused with other plugins.
|
||||||
|
- The slug doesn't collide with an already-registered plugin name.
|
||||||
|
|
||||||
|
"RangerHQ Radio" was always fine as the display name. The slug `a-radio` was the weak link — short, generic, with a non-descriptive prefix. `rangerhq-radio` is none of those things.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [0.7.4] — 2026-05-30 — WordPress.org submission cleanup (updater out, LICENSE in)
|
## [0.7.4] — 2026-05-30 — WordPress.org submission cleanup (updater out, LICENSE in)
|
||||||
|
|
||||||
Walks back the Update URI guard pattern from v0.7.3 and replaces it with the simpler, actually-correct answer: just remove the custom updater entirely. The WordPress.org Plugin Check tool (PCP) raised `plugin_updater_detected` on the v0.7.3 build with the message *"Including An Update Checker / Changing Updates functionality. Plugin Updater detected. Use of the Update URI header is not allowed in plugins hosted on WordPress.org."* PCP scans the source as-shipped, not as-distributed, so the build-time `sed` strip we relied on in v0.7.3 never had a chance to run before the scan — and the scanner flagged both the header and the `inc/updater.php` file itself. Two options remained: (a) keep dancing around PCP with branches and build scripts, or (b) accept that WordPress.org is the canonical update channel once a plugin is hosted there and drop the custom system. We went with (b).
|
Walks back the Update URI guard pattern from v0.7.3 and replaces it with the simpler, actually-correct answer: just remove the custom updater entirely. The WordPress.org Plugin Check tool (PCP) raised `plugin_updater_detected` on the v0.7.3 build with the message *"Including An Update Checker / Changing Updates functionality. Plugin Updater detected. Use of the Update URI header is not allowed in plugins hosted on WordPress.org."* PCP scans the source as-shipped, not as-distributed, so the build-time `sed` strip we relied on in v0.7.3 never had a chance to run before the scan — and the scanner flagged both the header and the `inc/updater.php` file itself. Two options remained: (a) keep dancing around PCP with branches and build scripts, or (b) accept that WordPress.org is the canonical update channel once a plugin is hosted there and drop the custom system. We went with (b).
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
# Radio — SomaFM player for your WordPress dashboard
|
# 📻 RangerHQ Radio — SomaFM player for your WordPress dashboard
|
||||||
|
|
||||||
|
[](https://wordpress.org/plugins/rangerhq-radio/)
|
||||||
|
[](https://wordpress.org/plugins/rangerhq-radio/)
|
||||||
|
[](https://wordpress.org/plugins/rangerhq-radio/)
|
||||||
|
[](https://wordpress.org/plugins/rangerhq-radio/)
|
||||||
|
[](readme.txt)
|
||||||
|
[](LICENSE)
|
||||||
|
[](https://git.davidtkeane.com/ranger/rangerhq-radio/commits/branch/main)
|
||||||
|
[](https://git.davidtkeane.com/ranger/rangerhq-radio/wiki/Stations)
|
||||||
|
[](https://git.davidtkeane.com/ranger/rangerhq-radio/wiki/Privacy)
|
||||||
|
[](https://davidtkeane.com)
|
||||||
|
|
||||||
A small, focused, free WordPress plugin that drops a SomaFM radio player into your admin dashboard. 44 hand-curated stations across 10 genres — ambient, electronic, lounge, rock, metal, jazz, world, reggae, holiday, and specials.
|
A small, focused, free WordPress plugin that drops a SomaFM radio player into your admin dashboard. 44 hand-curated stations across 10 genres — ambient, electronic, lounge, rock, metal, jazz, world, reggae, holiday, and specials.
|
||||||
|
|
||||||
@@ -12,7 +23,7 @@ A small, focused, free WordPress plugin that drops a SomaFM radio player into yo
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Download the latest release `.zip` from [git.davidtkeane.com/ranger/a-radio/releases](https://git.davidtkeane.com/ranger/a-radio/releases)
|
1. Download the latest release `.zip` from [git.davidtkeane.com/ranger/rangerhq-radio/releases](https://git.davidtkeane.com/ranger/rangerhq-radio/releases)
|
||||||
2. WP Admin → Plugins → Add New → Upload Plugin
|
2. WP Admin → Plugins → Add New → Upload Plugin
|
||||||
3. Activate
|
3. Activate
|
||||||
4. Look at **WP Admin → Dashboard** for the mini-player, or **WP Admin → Radio**
|
4. Look at **WP Admin → Dashboard** for the mini-player, or **WP Admin → Radio**
|
||||||
|
|||||||
+33
-31
@@ -14,48 +14,48 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
|
|||||||
|
|
||||||
function radio_render_about_page() {
|
function radio_render_about_page() {
|
||||||
if ( ! current_user_can( 'read' ) ) {
|
if ( ! current_user_can( 'read' ) ) {
|
||||||
wp_die( esc_html__( 'You do not have permission to view this page.', 'a-radio' ) );
|
wp_die( esc_html__( 'You do not have permission to view this page.', 'rangerhq-radio' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$count = count( radio_get_stations_flat() );
|
$count = count( radio_get_stations_flat() );
|
||||||
?>
|
?>
|
||||||
<div class="wrap radio-about-wrap">
|
<div class="wrap radio-about-wrap">
|
||||||
<h1><?php esc_html_e( 'About Radio', 'a-radio' ); ?></h1>
|
<h1><?php esc_html_e( 'About Radio', 'rangerhq-radio' ); ?></h1>
|
||||||
|
|
||||||
<!-- ── Top row: three short cards (What / Who / Credits) ── -->
|
<!-- ── Top row: three short cards (What / Who / Credits) ── -->
|
||||||
<div class="radio-about-grid">
|
<div class="radio-about-grid">
|
||||||
|
|
||||||
<div class="radio-about-card">
|
<div class="radio-about-card">
|
||||||
<h2><?php esc_html_e( 'What Radio does', 'a-radio' ); ?></h2>
|
<h2><?php esc_html_e( 'What Radio does', 'rangerhq-radio' ); ?></h2>
|
||||||
<p>
|
<p>
|
||||||
<?php
|
<?php
|
||||||
printf(
|
printf(
|
||||||
/* translators: %d = station count */
|
/* translators: %d = station count */
|
||||||
esc_html__( 'Adds a small, focused radio player to your WordPress dashboard. %d hand-curated SomaFM stations across 10 genres — ambient, electronic, lounge, rock, metal, jazz, world, reggae, holiday and specials. Plays in your admin pages while you work. Your chosen station + volume persist per user.', 'a-radio' ),
|
esc_html__( 'Adds a small, focused radio player to your WordPress dashboard. %d hand-curated SomaFM stations across 10 genres — ambient, electronic, lounge, rock, metal, jazz, world, reggae, holiday and specials. Plays in your admin pages while you work. Your chosen station + volume persist per user.', 'rangerhq-radio' ),
|
||||||
(int) $count
|
(int) $count
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<?php esc_html_e( 'Audio plays directly in your browser via HTML5 — no server-side proxy, no extra services to host, no third-party tracking. Just an <audio> element pointed at SomaFM\'s public streams.', 'a-radio' ); ?>
|
<?php esc_html_e( 'Audio plays directly in your browser via HTML5 — no server-side proxy, no extra services to host, no third-party tracking. Just an <audio> element pointed at SomaFM\'s public streams.', 'rangerhq-radio' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-about-card">
|
<div class="radio-about-card">
|
||||||
<h2><?php esc_html_e( 'Who Radio is for', 'a-radio' ); ?></h2>
|
<h2><?php esc_html_e( 'Who Radio is for', 'rangerhq-radio' ); ?></h2>
|
||||||
<p>
|
<p>
|
||||||
<?php esc_html_e( 'Anyone who likes background music while working in the WordPress admin. Coders, writers, support agents, content editors. The 44 SomaFM stations cover a wide enough range that there\'s something for any mood — from coding-focus ambient (Groove Salad, Drone Zone) to drive-time electronic (DEF CON Radio, Beat Blender) to mellow lounge (Lush, Secret Agent) to specifically-quirky picks (SF 10-33 mixes ambient with San Francisco public-safety radio).', 'a-radio' ); ?>
|
<?php esc_html_e( 'Anyone who likes background music while working in the WordPress admin. Coders, writers, support agents, content editors. The 44 SomaFM stations cover a wide enough range that there\'s something for any mood — from coding-focus ambient (Groove Salad, Drone Zone) to drive-time electronic (DEF CON Radio, Beat Blender) to mellow lounge (Lush, Secret Agent) to specifically-quirky picks (SF 10-33 mixes ambient with San Francisco public-safety radio).', 'rangerhq-radio' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-about-card">
|
<div class="radio-about-card">
|
||||||
<h2><?php esc_html_e( 'Credits + thanks', 'a-radio' ); ?></h2>
|
<h2><?php esc_html_e( 'Credits + thanks', 'rangerhq-radio' ); ?></h2>
|
||||||
<p>
|
<p>
|
||||||
<?php
|
<?php
|
||||||
printf(
|
printf(
|
||||||
wp_kses(
|
wp_kses(
|
||||||
/* translators: %s = link to somafm.com */
|
/* translators: %s = link to somafm.com */
|
||||||
__( 'All stations and streams are provided by %s — an independent, listener-supported, commercial-free internet radio network broadcasting from San Francisco since 2000. Radio is just a small WordPress wrapper around their public streams. If you enjoy this plugin, please consider donating to SomaFM directly.', 'a-radio' ),
|
__( 'All stations and streams are provided by %s — an independent, listener-supported, commercial-free internet radio network broadcasting from San Francisco since 2000. Radio is just a small WordPress wrapper around their public streams. If you enjoy this plugin, please consider donating to SomaFM directly.', 'rangerhq-radio' ),
|
||||||
array( 'a' => array( 'href' => true, 'target' => true, 'rel' => true ) )
|
array( 'a' => array( 'href' => true, 'target' => true, 'rel' => true ) )
|
||||||
),
|
),
|
||||||
'<a href="https://somafm.com/support/" target="_blank" rel="noopener">SomaFM</a>'
|
'<a href="https://somafm.com/support/" target="_blank" rel="noopener">SomaFM</a>'
|
||||||
@@ -63,11 +63,11 @@ function radio_render_about_page() {
|
|||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<?php esc_html_e( 'Plugin author: David Keane. Part of the RangerHQ plugin family. GPL v2 or later. Source on Gitea.', 'a-radio' ); ?>
|
<?php esc_html_e( 'Plugin author: David Keane. Part of the RangerHQ plugin family. GPL v2 or later. Source on Gitea.', 'rangerhq-radio' ); ?>
|
||||||
</p>
|
</p>
|
||||||
<?php if ( defined( 'RADIO_SUPPORT_URL' ) && RADIO_SUPPORT_URL ) : ?>
|
<?php if ( defined( 'RADIO_SUPPORT_URL' ) && RADIO_SUPPORT_URL ) : ?>
|
||||||
<a class="radio-support-link" href="<?php echo esc_url( RADIO_SUPPORT_URL ); ?>" target="_blank" rel="noopener">
|
<a class="radio-support-link" href="<?php echo esc_url( RADIO_SUPPORT_URL ); ?>" target="_blank" rel="noopener">
|
||||||
<?php esc_html_e( 'Like Radio? If You fancy to buy me a coffee →', 'a-radio' ); ?>
|
<?php esc_html_e( 'Like Radio? If You fancy to buy me a coffee →', 'rangerhq-radio' ); ?>
|
||||||
</a>
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,38 +76,40 @@ function radio_render_about_page() {
|
|||||||
|
|
||||||
<!-- ── Version history: latest in full, earlier as one-liners ── -->
|
<!-- ── Version history: latest in full, earlier as one-liners ── -->
|
||||||
<div class="radio-about-versions">
|
<div class="radio-about-versions">
|
||||||
<h2><?php esc_html_e( 'Version history', 'a-radio' ); ?></h2>
|
<h2><?php esc_html_e( 'Version history', 'rangerhq-radio' ); ?></h2>
|
||||||
|
|
||||||
<div class="radio-about-versions__latest">
|
<div class="radio-about-versions__latest">
|
||||||
<span class="ver">v0.7.4</span> — 30 May 2026 <span class="latest"><?php esc_html_e( 'latest', 'a-radio' ); ?></span>
|
<span class="ver">v0.7.6</span> — 3 June 2026 <span class="latest"><?php esc_html_e( 'latest', 'rangerhq-radio' ); ?></span>
|
||||||
<p>
|
<p>
|
||||||
<?php esc_html_e( 'WordPress.org submission cleanup. Removed the self-hosted Gitea updater (`inc/updater.php`) and the `Update URI` header from `radio.php` — WordPress.org explicitly disallows both for hosted plugins (Plugin Check `plugin_updater_detected`). Updates now flow through WordPress.org as the canonical channel. Added a top-level LICENSE file with the full GPL v2 text and GPL header blocks to the CSS and JS assets so the licensing of every shipped file is explicit. No user-visible behaviour changes for the player — only the small `Updates` panel that used to sit at the bottom of Radio → Settings is gone.', 'a-radio' ); ?>
|
<?php esc_html_e( 'Plugin metadata cleanup following the wp.org pre-review feedback. Plugin URI header updated to https://davidtkeane.com/rangerhq-radio (the canonical project landing page, now live). Author URI header updated to https://davidtkeane.com (both old URLs were returning DNS errors or 404). Ownership of the davidtkeane.com domain verified to wp.org via DNS TXT record and a domain-matched account email. No code changes, no user-visible behaviour changes — metadata only.', 'rangerhq-radio' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3><?php esc_html_e( 'Earlier releases', 'a-radio' ); ?></h3>
|
<h3><?php esc_html_e( 'Earlier releases', 'rangerhq-radio' ); ?></h3>
|
||||||
<ul class="radio-about-versions__earlier">
|
<ul class="radio-about-versions__earlier">
|
||||||
<li><span class="ver">v0.7.3</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Privacy section in readme + SomaFM terms-of-use link (Update URI guard pattern from this release was walked back in v0.7.4 — Plugin Check disallows it for wp.org-hosted plugins regardless of header value)', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.7.5</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'WordPress.org slug rename: a-radio → rangerhq-radio for family-pattern consistency', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.7.2</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Screenshots + correct wp.org contributor handle (ir240474)', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.7.4</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'wp.org submission cleanup — removed self-hosted updater + Update URI header (PCP plugin_updater_detected); added LICENSE file + per-asset GPL headers', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.7.1</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Plugin Check follow-up — Tested-up-to bumped to 7.0, .DS_Store re-cleanup', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.7.3</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Privacy section in readme + SomaFM terms-of-use link (Update URI guard pattern from this release was walked back in v0.7.4 — Plugin Check disallows it for wp.org-hosted plugins regardless of header value)', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.7.0</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'WordPress.org submission prep — full Plugin Check clean (169 → 4 issues, branding, textdomain, security, popup refactor, readme.txt)', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.7.2</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Screenshots + correct wp.org contributor handle (ir240474)', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.6.3</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Discreet buy-me-a-coffee support link (Updates panel + Credits card)', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.7.1</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Plugin Check follow-up — Tested-up-to bumped to 7.0, .DS_Store re-cleanup', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.6.2</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Current version badge on the Settings page', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.7.0</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'WordPress.org submission prep — full Plugin Check clean (169 → 4 issues, branding, textdomain, security, popup refactor, readme.txt)', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.6.1</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'About page restructure — balanced 3-card top row + compact version history', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.6.3</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Discreet buy-me-a-coffee support link (Updates panel + Credits card)', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.6.0</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Pop-out mini-player — continuous background play across admin navigation', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.6.2</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Current version badge on the Settings page', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.5.0</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Track history + favourites (Spotify / YouTube / Apple Music / Bandcamp search links)', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.6.1</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'About page restructure — balanced 3-card top row + compact version history', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.4.0</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Now-playing indicator — dancing bars + Web Audio frequency visualizer', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.6.0</span> <span class="ver-date">30 May 2026</span> — <?php esc_html_e( 'Pop-out mini-player — continuous background play across admin navigation', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.3.2</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Play-button glyph baseline fix (dashicon → Unicode ▶ / ‖)', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.5.0</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Track history + favourites (Spotify / YouTube / Apple Music / Bandcamp search links)', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.3.1</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'My Radio layout polish + dropped dark-auto', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.4.0</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Now-playing indicator — dancing bars + Web Audio frequency visualizer', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.3.0</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Dark theme + mute + OS media keys + SomaFM current-track display', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.3.2</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Play-button glyph baseline fix (dashicon → Unicode ▶ / ‖)', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.2.0</span> <span class="ver-date">26 May 2026</span> — <?php esc_html_e( 'UI rebuilt to WordPress admin standards', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.3.1</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'My Radio layout polish + dropped dark-auto', 'rangerhq-radio' ); ?></li>
|
||||||
<li><span class="ver">v0.1.0</span> <span class="ver-date">26 May 2026</span> — <?php esc_html_e( 'First release — 44 SomaFM stations, dashboard widget + dedicated admin page, per-user state, self-hosted Gitea updater', 'a-radio' ); ?></li>
|
<li><span class="ver">v0.3.0</span> <span class="ver-date">29 May 2026</span> — <?php esc_html_e( 'Dark theme + mute + OS media keys + SomaFM current-track display', 'rangerhq-radio' ); ?></li>
|
||||||
|
<li><span class="ver">v0.2.0</span> <span class="ver-date">26 May 2026</span> — <?php esc_html_e( 'UI rebuilt to WordPress admin standards', 'rangerhq-radio' ); ?></li>
|
||||||
|
<li><span class="ver">v0.1.0</span> <span class="ver-date">26 May 2026</span> — <?php esc_html_e( 'First release — 44 SomaFM stations, dashboard widget + dedicated admin page, per-user state, self-hosted Gitea updater', 'rangerhq-radio' ); ?></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<a class="radio-about-changelog-link"
|
<a class="radio-about-changelog-link"
|
||||||
href="<?php echo esc_url( RADIO_GITEA_URL . '/src/branch/main/CHANGELOG.md' ); ?>"
|
href="<?php echo esc_url( RADIO_GITEA_URL . '/src/branch/main/CHANGELOG.md' ); ?>"
|
||||||
target="_blank" rel="noopener">
|
target="_blank" rel="noopener">
|
||||||
<?php esc_html_e( 'View the full CHANGELOG.md →', 'a-radio' ); ?>
|
<?php esc_html_e( 'View the full CHANGELOG.md →', 'rangerhq-radio' ); ?>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+12
-12
@@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
|
|||||||
|
|
||||||
function radio_render_main_page() {
|
function radio_render_main_page() {
|
||||||
if ( ! current_user_can( 'read' ) ) {
|
if ( ! current_user_can( 'read' ) ) {
|
||||||
wp_die( esc_html__( 'You do not have permission to view this page.', 'a-radio' ) );
|
wp_die( esc_html__( 'You do not have permission to view this page.', 'rangerhq-radio' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$state = radio_get_state();
|
$state = radio_get_state();
|
||||||
@@ -21,13 +21,13 @@ function radio_render_main_page() {
|
|||||||
$count = count( radio_get_stations_flat() );
|
$count = count( radio_get_stations_flat() );
|
||||||
?>
|
?>
|
||||||
<div class="wrap radio-wrap">
|
<div class="wrap radio-wrap">
|
||||||
<h1><?php esc_html_e( 'Radio', 'a-radio' ); ?></h1>
|
<h1><?php esc_html_e( 'Radio', 'rangerhq-radio' ); ?></h1>
|
||||||
|
|
||||||
<p class="radio-intro">
|
<p class="radio-intro">
|
||||||
<?php
|
<?php
|
||||||
printf(
|
printf(
|
||||||
/* translators: %d = number of stations */
|
/* translators: %d = number of stations */
|
||||||
esc_html__( 'A tab of background music for your WordPress admin. %d hand-curated SomaFM stations across 10 genres — free, no ads, no tracking.', 'a-radio' ),
|
esc_html__( 'A tab of background music for your WordPress admin. %d hand-curated SomaFM stations across 10 genres — free, no ads, no tracking.', 'rangerhq-radio' ),
|
||||||
(int) $count
|
(int) $count
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
@@ -35,7 +35,7 @@ function radio_render_main_page() {
|
|||||||
|
|
||||||
<div class="postbox">
|
<div class="postbox">
|
||||||
<div class="postbox-header">
|
<div class="postbox-header">
|
||||||
<h2 class="hndle"><?php esc_html_e( 'Player', 'a-radio' ); ?></h2>
|
<h2 class="hndle"><?php esc_html_e( 'Player', 'rangerhq-radio' ); ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="inside">
|
<div class="inside">
|
||||||
<div class="radio-player" data-radio-surface="main">
|
<div class="radio-player" data-radio-surface="main">
|
||||||
@@ -45,7 +45,7 @@ function radio_render_main_page() {
|
|||||||
<span class="radio-player__bars"><span></span><span></span><span></span><span></span></span>
|
<span class="radio-player__bars"><span></span><span></span><span></span><span></span></span>
|
||||||
<canvas class="radio-player__viz" data-radio-viz hidden></canvas>
|
<canvas class="radio-player__viz" data-radio-viz hidden></canvas>
|
||||||
</span>
|
</span>
|
||||||
<span class="radio-player__label"><?php esc_html_e( 'Now Playing', 'a-radio' ); ?></span>
|
<span class="radio-player__label"><?php esc_html_e( 'Now Playing', 'rangerhq-radio' ); ?></span>
|
||||||
<span class="radio-player__station-name" data-radio-name><?php echo esc_html( $station['name'] ); ?></span>
|
<span class="radio-player__station-name" data-radio-name><?php echo esc_html( $station['name'] ); ?></span>
|
||||||
<span class="radio-player__station-genre" data-radio-genre><?php echo esc_html( $station['genre'] ); ?></span>
|
<span class="radio-player__station-genre" data-radio-genre><?php echo esc_html( $station['genre'] ); ?></span>
|
||||||
<p class="radio-player__station-desc" data-radio-desc><?php echo esc_html( $station['description'] ); ?></p>
|
<p class="radio-player__station-desc" data-radio-desc><?php echo esc_html( $station['description'] ); ?></p>
|
||||||
@@ -55,24 +55,24 @@ function radio_render_main_page() {
|
|||||||
<div class="radio-player__controls">
|
<div class="radio-player__controls">
|
||||||
<button type="button" class="button button-primary radio-player__play" data-radio-play>
|
<button type="button" class="button button-primary radio-player__play" data-radio-play>
|
||||||
<span class="radio-player__play-glyph" data-radio-play-glyph aria-hidden="true">▶</span>
|
<span class="radio-player__play-glyph" data-radio-play-glyph aria-hidden="true">▶</span>
|
||||||
<span data-radio-play-label><?php esc_html_e( 'Play', 'a-radio' ); ?></span>
|
<span data-radio-play-label><?php esc_html_e( 'Play', 'rangerhq-radio' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="button radio-player__popout" data-radio-popout title="<?php esc_attr_e( 'Open in a pop-out window — keeps playing while you navigate the admin', 'a-radio' ); ?>">
|
<button type="button" class="button radio-player__popout" data-radio-popout title="<?php esc_attr_e( 'Open in a pop-out window — keeps playing while you navigate the admin', 'rangerhq-radio' ); ?>">
|
||||||
<span aria-hidden="true">↗</span> <?php esc_html_e( 'Pop out', 'a-radio' ); ?>
|
<span aria-hidden="true">↗</span> <?php esc_html_e( 'Pop out', 'rangerhq-radio' ); ?>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="radio-player__volume">
|
<div class="radio-player__volume">
|
||||||
<button type="button" class="radio-player__mute" data-radio-mute aria-label="<?php esc_attr_e( 'Mute', 'a-radio' ); ?>">
|
<button type="button" class="radio-player__mute" data-radio-mute aria-label="<?php esc_attr_e( 'Mute', 'rangerhq-radio' ); ?>">
|
||||||
<span class="dashicons dashicons-controls-volumeon" aria-hidden="true"></span>
|
<span class="dashicons dashicons-controls-volumeon" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<input type="range" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" data-radio-volume aria-label="<?php esc_attr_e( 'Volume', 'a-radio' ); ?>">
|
<input type="range" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" data-radio-volume aria-label="<?php esc_attr_e( 'Volume', 'rangerhq-radio' ); ?>">
|
||||||
<span class="radio-player__volume-pct" data-radio-volume-pct><?php echo esc_html( (int) round( $state['volume'] * 100 ) ); ?>%</span>
|
<span class="radio-player__volume-pct" data-radio-volume-pct><?php echo esc_html( (int) round( $state['volume'] * 100 ) ); ?>%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-player__station-select">
|
<div class="radio-player__station-select">
|
||||||
<label for="radio-station-main"><?php esc_html_e( 'Station', 'a-radio' ); ?></label>
|
<label for="radio-station-main"><?php esc_html_e( 'Station', 'rangerhq-radio' ); ?></label>
|
||||||
<select id="radio-station-main" data-radio-station>
|
<select id="radio-station-main" data-radio-station>
|
||||||
<?php foreach ( $stations as $genre => $entries ) :
|
<?php foreach ( $stations as $genre => $entries ) :
|
||||||
if ( empty( $entries ) ) { continue; }
|
if ( empty( $entries ) ) { continue; }
|
||||||
@@ -100,7 +100,7 @@ function radio_render_main_page() {
|
|||||||
printf(
|
printf(
|
||||||
wp_kses(
|
wp_kses(
|
||||||
/* translators: %s = link to somafm.com */
|
/* translators: %s = link to somafm.com */
|
||||||
__( 'Stations and streams provided by %s — an independent, listener-supported, commercial-free internet radio network. Please consider supporting them.', 'a-radio' ),
|
__( 'Stations and streams provided by %s — an independent, listener-supported, commercial-free internet radio network. Please consider supporting them.', 'rangerhq-radio' ),
|
||||||
array( 'a' => array( 'href' => true, 'target' => true, 'rel' => true ) )
|
array( 'a' => array( 'href' => true, 'target' => true, 'rel' => true ) )
|
||||||
),
|
),
|
||||||
'<a href="https://somafm.com/" target="_blank" rel="noopener">SomaFM</a>'
|
'<a href="https://somafm.com/" target="_blank" rel="noopener">SomaFM</a>'
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function radio_register_dashboard_widget() {
|
|||||||
|
|
||||||
wp_add_dashboard_widget(
|
wp_add_dashboard_widget(
|
||||||
'radio_dashboard_widget',
|
'radio_dashboard_widget',
|
||||||
__( 'Radio', 'a-radio' ),
|
__( 'Radio', 'rangerhq-radio' ),
|
||||||
'radio_render_dashboard_widget'
|
'radio_render_dashboard_widget'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ function radio_render_dashboard_widget() {
|
|||||||
<span class="radio-player__bars"><span></span><span></span><span></span><span></span></span>
|
<span class="radio-player__bars"><span></span><span></span><span></span><span></span></span>
|
||||||
<canvas class="radio-player__viz" data-radio-viz hidden></canvas>
|
<canvas class="radio-player__viz" data-radio-viz hidden></canvas>
|
||||||
</span>
|
</span>
|
||||||
<span class="radio-player__label"><?php esc_html_e( 'Now Playing', 'a-radio' ); ?></span>
|
<span class="radio-player__label"><?php esc_html_e( 'Now Playing', 'rangerhq-radio' ); ?></span>
|
||||||
<span class="radio-player__station-name" data-radio-name><?php echo esc_html( $station['name'] ); ?></span>
|
<span class="radio-player__station-name" data-radio-name><?php echo esc_html( $station['name'] ); ?></span>
|
||||||
<span class="radio-player__station-genre" data-radio-genre><?php echo esc_html( $station['genre'] ); ?></span>
|
<span class="radio-player__station-genre" data-radio-genre><?php echo esc_html( $station['genre'] ); ?></span>
|
||||||
<p class="radio-player__station-desc" data-radio-desc><?php echo esc_html( $station['description'] ); ?></p>
|
<p class="radio-player__station-desc" data-radio-desc><?php echo esc_html( $station['description'] ); ?></p>
|
||||||
@@ -48,24 +48,24 @@ function radio_render_dashboard_widget() {
|
|||||||
<div class="radio-player__controls">
|
<div class="radio-player__controls">
|
||||||
<button type="button" class="button button-primary radio-player__play" data-radio-play>
|
<button type="button" class="button button-primary radio-player__play" data-radio-play>
|
||||||
<span class="radio-player__play-glyph" data-radio-play-glyph aria-hidden="true">▶</span>
|
<span class="radio-player__play-glyph" data-radio-play-glyph aria-hidden="true">▶</span>
|
||||||
<span data-radio-play-label><?php esc_html_e( 'Play', 'a-radio' ); ?></span>
|
<span data-radio-play-label><?php esc_html_e( 'Play', 'rangerhq-radio' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="button radio-player__popout" data-radio-popout title="<?php esc_attr_e( 'Open in a pop-out window — keeps playing while you navigate', 'a-radio' ); ?>">
|
<button type="button" class="button radio-player__popout" data-radio-popout title="<?php esc_attr_e( 'Open in a pop-out window — keeps playing while you navigate', 'rangerhq-radio' ); ?>">
|
||||||
<span aria-hidden="true">↗</span> <?php esc_html_e( 'Pop out', 'a-radio' ); ?>
|
<span aria-hidden="true">↗</span> <?php esc_html_e( 'Pop out', 'rangerhq-radio' ); ?>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="radio-player__volume">
|
<div class="radio-player__volume">
|
||||||
<button type="button" class="radio-player__mute" data-radio-mute aria-label="<?php esc_attr_e( 'Mute', 'a-radio' ); ?>">
|
<button type="button" class="radio-player__mute" data-radio-mute aria-label="<?php esc_attr_e( 'Mute', 'rangerhq-radio' ); ?>">
|
||||||
<span class="dashicons dashicons-controls-volumeon" aria-hidden="true"></span>
|
<span class="dashicons dashicons-controls-volumeon" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<input type="range" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" data-radio-volume aria-label="<?php esc_attr_e( 'Volume', 'a-radio' ); ?>">
|
<input type="range" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" data-radio-volume aria-label="<?php esc_attr_e( 'Volume', 'rangerhq-radio' ); ?>">
|
||||||
<span class="radio-player__volume-pct" data-radio-volume-pct><?php echo esc_html( (int) round( $state['volume'] * 100 ) ); ?>%</span>
|
<span class="radio-player__volume-pct" data-radio-volume-pct><?php echo esc_html( (int) round( $state['volume'] * 100 ) ); ?>%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-player__station-select">
|
<div class="radio-player__station-select">
|
||||||
<label for="radio-station-widget"><?php esc_html_e( 'Station', 'a-radio' ); ?></label>
|
<label for="radio-station-widget"><?php esc_html_e( 'Station', 'rangerhq-radio' ); ?></label>
|
||||||
<select id="radio-station-widget" data-radio-station>
|
<select id="radio-station-widget" data-radio-station>
|
||||||
<?php foreach ( $stations as $genre => $entries ) :
|
<?php foreach ( $stations as $genre => $entries ) :
|
||||||
if ( empty( $entries ) ) { continue; }
|
if ( empty( $entries ) ) { continue; }
|
||||||
@@ -90,7 +90,7 @@ function radio_render_dashboard_widget() {
|
|||||||
printf(
|
printf(
|
||||||
wp_kses(
|
wp_kses(
|
||||||
/* translators: %s = link to somafm.com */
|
/* translators: %s = link to somafm.com */
|
||||||
__( 'Powered by %s', 'a-radio' ),
|
__( 'Powered by %s', 'rangerhq-radio' ),
|
||||||
array( 'a' => array( 'href' => true, 'target' => true, 'rel' => true ) )
|
array( 'a' => array( 'href' => true, 'target' => true, 'rel' => true ) )
|
||||||
),
|
),
|
||||||
'<a href="https://somafm.com/" target="_blank" rel="noopener">SomaFM</a>'
|
'<a href="https://somafm.com/" target="_blank" rel="noopener">SomaFM</a>'
|
||||||
|
|||||||
+16
-16
@@ -133,7 +133,7 @@ function radio_search_urls( $artist, $title ) {
|
|||||||
/** Render the History admin page (tabs: History / Favourites). */
|
/** Render the History admin page (tabs: History / Favourites). */
|
||||||
function radio_render_history_page() {
|
function radio_render_history_page() {
|
||||||
if ( ! current_user_can( 'read' ) ) {
|
if ( ! current_user_can( 'read' ) ) {
|
||||||
wp_die( esc_html__( 'You do not have permission to view this page.', 'a-radio' ) );
|
wp_die( esc_html__( 'You do not have permission to view this page.', 'rangerhq-radio' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'history'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab-switch only, no state change
|
$tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'history'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- tab-switch only, no state change
|
||||||
@@ -163,15 +163,15 @@ function radio_render_history_page() {
|
|||||||
$nonce = wp_create_nonce( 'radio_history' );
|
$nonce = wp_create_nonce( 'radio_history' );
|
||||||
?>
|
?>
|
||||||
<div class="wrap radio-history-wrap">
|
<div class="wrap radio-history-wrap">
|
||||||
<h1><?php esc_html_e( 'Radio — Track history', 'a-radio' ); ?></h1>
|
<h1><?php esc_html_e( 'Radio — Track history', 'rangerhq-radio' ); ?></h1>
|
||||||
|
|
||||||
<h2 class="nav-tab-wrapper">
|
<h2 class="nav-tab-wrapper">
|
||||||
<a href="<?php echo esc_url( $hist_url ); ?>" class="nav-tab <?php echo $tab === 'history' ? 'nav-tab-active' : ''; ?>">
|
<a href="<?php echo esc_url( $hist_url ); ?>" class="nav-tab <?php echo $tab === 'history' ? 'nav-tab-active' : ''; ?>">
|
||||||
<?php esc_html_e( 'History', 'a-radio' ); ?>
|
<?php esc_html_e( 'History', 'rangerhq-radio' ); ?>
|
||||||
<span class="radio-tab-count">(<?php echo (int) count( $all_history ); ?>)</span>
|
<span class="radio-tab-count">(<?php echo (int) count( $all_history ); ?>)</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="<?php echo esc_url( $fav_url ); ?>" class="nav-tab <?php echo $tab === 'favourites' ? 'nav-tab-active' : ''; ?>">
|
<a href="<?php echo esc_url( $fav_url ); ?>" class="nav-tab <?php echo $tab === 'favourites' ? 'nav-tab-active' : ''; ?>">
|
||||||
★ <?php esc_html_e( 'Favourites', 'a-radio' ); ?>
|
★ <?php esc_html_e( 'Favourites', 'rangerhq-radio' ); ?>
|
||||||
<span class="radio-tab-count">(<?php echo (int) count( $all_favourites ); ?>)</span>
|
<span class="radio-tab-count">(<?php echo (int) count( $all_favourites ); ?>)</span>
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
@@ -179,24 +179,24 @@ function radio_render_history_page() {
|
|||||||
<?php if ( empty( $entries ) ) : ?>
|
<?php if ( empty( $entries ) ) : ?>
|
||||||
<p class="radio-history-empty">
|
<p class="radio-history-empty">
|
||||||
<?php if ( $tab === 'favourites' ) : ?>
|
<?php if ( $tab === 'favourites' ) : ?>
|
||||||
<?php esc_html_e( 'No favourites yet — star a track on the History tab to save it here.', 'a-radio' ); ?>
|
<?php esc_html_e( 'No favourites yet — star a track on the History tab to save it here.', 'rangerhq-radio' ); ?>
|
||||||
<?php else : ?>
|
<?php else : ?>
|
||||||
<?php esc_html_e( 'No tracks logged yet. Play some music in the Radio player — tracks will appear here as they play.', 'a-radio' ); ?>
|
<?php esc_html_e( 'No tracks logged yet. Play some music in the Radio player — tracks will appear here as they play.', 'rangerhq-radio' ); ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
<?php else : ?>
|
<?php else : ?>
|
||||||
|
|
||||||
<div class="radio-history-toolbar">
|
<div class="radio-history-toolbar">
|
||||||
<input type="search" id="radio-history-search" placeholder="<?php esc_attr_e( 'Filter by artist or title…', 'a-radio' ); ?>" />
|
<input type="search" id="radio-history-search" placeholder="<?php esc_attr_e( 'Filter by artist or title…', 'rangerhq-radio' ); ?>" />
|
||||||
<select id="radio-history-station">
|
<select id="radio-history-station">
|
||||||
<option value=""><?php esc_html_e( 'All stations', 'a-radio' ); ?></option>
|
<option value=""><?php esc_html_e( 'All stations', 'rangerhq-radio' ); ?></option>
|
||||||
<?php foreach ( $stations_in_list as $sid => $sname ) : ?>
|
<?php foreach ( $stations_in_list as $sid => $sname ) : ?>
|
||||||
<option value="<?php echo esc_attr( $sid ); ?>"><?php echo esc_html( $sname ); ?></option>
|
<option value="<?php echo esc_attr( $sid ); ?>"><?php echo esc_html( $sname ); ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<?php if ( $tab === 'history' ) : ?>
|
<?php if ( $tab === 'history' ) : ?>
|
||||||
<button type="button" id="radio-history-clear" class="button radio-history-clear" data-nonce="<?php echo esc_attr( $nonce ); ?>">
|
<button type="button" id="radio-history-clear" class="button radio-history-clear" data-nonce="<?php echo esc_attr( $nonce ); ?>">
|
||||||
🗑 <?php esc_html_e( 'Clear history', 'a-radio' ); ?>
|
🗑 <?php esc_html_e( 'Clear history', 'rangerhq-radio' ); ?>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@@ -204,11 +204,11 @@ function radio_render_history_page() {
|
|||||||
<table class="widefat radio-history-table">
|
<table class="widefat radio-history-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="when"><?php esc_html_e( 'When', 'a-radio' ); ?></th>
|
<th class="when"><?php esc_html_e( 'When', 'rangerhq-radio' ); ?></th>
|
||||||
<th class="station"><?php esc_html_e( 'Station', 'a-radio' ); ?></th>
|
<th class="station"><?php esc_html_e( 'Station', 'rangerhq-radio' ); ?></th>
|
||||||
<th class="track"><?php esc_html_e( 'Artist — Title', 'a-radio' ); ?></th>
|
<th class="track"><?php esc_html_e( 'Artist — Title', 'rangerhq-radio' ); ?></th>
|
||||||
<th class="search"><?php esc_html_e( 'Search', 'a-radio' ); ?></th>
|
<th class="search"><?php esc_html_e( 'Search', 'rangerhq-radio' ); ?></th>
|
||||||
<th class="fav"><span class="screen-reader-text"><?php esc_html_e( 'Favourite', 'a-radio' ); ?></span>★</th>
|
<th class="fav"><span class="screen-reader-text"><?php esc_html_e( 'Favourite', 'rangerhq-radio' ); ?></span>★</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -222,7 +222,7 @@ function radio_render_history_page() {
|
|||||||
<td class="when" title="<?php echo esc_attr( wp_date( 'j M Y, H:i', (int) $e['at'] ) ); ?>">
|
<td class="when" title="<?php echo esc_attr( wp_date( 'j M Y, H:i', (int) $e['at'] ) ); ?>">
|
||||||
<?php
|
<?php
|
||||||
/* translators: %s = human-readable time difference, e.g. "2 minutes" */
|
/* translators: %s = human-readable time difference, e.g. "2 minutes" */
|
||||||
printf( esc_html__( '%s ago', 'a-radio' ), esc_html( $ago ) );
|
printf( esc_html__( '%s ago', 'rangerhq-radio' ), esc_html( $ago ) );
|
||||||
?>
|
?>
|
||||||
</td>
|
</td>
|
||||||
<td class="station"><?php echo esc_html( $e['station'] ); ?></td>
|
<td class="station"><?php echo esc_html( $e['station'] ); ?></td>
|
||||||
@@ -243,7 +243,7 @@ function radio_render_history_page() {
|
|||||||
data-station="<?php echo esc_attr( $e['station'] ); ?>"
|
data-station="<?php echo esc_attr( $e['station'] ); ?>"
|
||||||
data-station-id="<?php echo esc_attr( $e['station_id'] ); ?>"
|
data-station-id="<?php echo esc_attr( $e['station_id'] ); ?>"
|
||||||
data-nonce="<?php echo esc_attr( $nonce ); ?>"
|
data-nonce="<?php echo esc_attr( $nonce ); ?>"
|
||||||
aria-label="<?php echo $is_fav ? esc_attr__( 'Remove from favourites', 'a-radio' ) : esc_attr__( 'Add to favourites', 'a-radio' ); ?>">
|
aria-label="<?php echo $is_fav ? esc_attr__( 'Remove from favourites', 'rangerhq-radio' ) : esc_attr__( 'Add to favourites', 'rangerhq-radio' ); ?>">
|
||||||
<?php echo $is_fav ? '★' : '☆'; ?>
|
<?php echo $is_fav ? '★' : '☆'; ?>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
+14
-14
@@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
|
|||||||
|
|
||||||
function radio_render_settings_page() {
|
function radio_render_settings_page() {
|
||||||
if ( ! current_user_can( 'read' ) ) {
|
if ( ! current_user_can( 'read' ) ) {
|
||||||
wp_die( esc_html__( 'You do not have permission to view this page.', 'a-radio' ) );
|
wp_die( esc_html__( 'You do not have permission to view this page.', 'rangerhq-radio' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle form submission.
|
// Handle form submission.
|
||||||
@@ -38,7 +38,7 @@ function radio_render_settings_page() {
|
|||||||
$state['hide_dashboard_widget'] = $hide_widget ? 1 : 0;
|
$state['hide_dashboard_widget'] = $hide_widget ? 1 : 0;
|
||||||
update_user_meta( $user_id, RADIO_META_KEY, $state );
|
update_user_meta( $user_id, RADIO_META_KEY, $state );
|
||||||
|
|
||||||
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Settings saved.', 'a-radio' ) . '</p></div>';
|
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Settings saved.', 'rangerhq-radio' ) . '</p></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$state = radio_get_state();
|
$state = radio_get_state();
|
||||||
@@ -47,7 +47,7 @@ function radio_render_settings_page() {
|
|||||||
?>
|
?>
|
||||||
<div class="wrap radio-settings-wrap">
|
<div class="wrap radio-settings-wrap">
|
||||||
<h1>
|
<h1>
|
||||||
<?php esc_html_e( 'Radio — Settings', 'a-radio' ); ?>
|
<?php esc_html_e( 'Radio — Settings', 'rangerhq-radio' ); ?>
|
||||||
<span class="radio-version-badge">v<?php echo esc_html( RADIO_VERSION ); ?></span>
|
<span class="radio-version-badge">v<?php echo esc_html( RADIO_VERSION ); ?></span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ function radio_render_settings_page() {
|
|||||||
<table class="form-table" role="presentation">
|
<table class="form-table" role="presentation">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
<label for="default_station"><?php esc_html_e( 'Default station', 'a-radio' ); ?></label>
|
<label for="default_station"><?php esc_html_e( 'Default station', 'rangerhq-radio' ); ?></label>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<select id="default_station" name="default_station">
|
<select id="default_station" name="default_station">
|
||||||
@@ -74,14 +74,14 @@ function radio_render_settings_page() {
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
<?php esc_html_e( 'The station that loads when you open Radio in a fresh tab.', 'a-radio' ); ?>
|
<?php esc_html_e( 'The station that loads when you open Radio in a fresh tab.', 'rangerhq-radio' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
<label for="default_volume"><?php esc_html_e( 'Default volume', 'a-radio' ); ?></label>
|
<label for="default_volume"><?php esc_html_e( 'Default volume', 'rangerhq-radio' ); ?></label>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input type="range" id="default_volume" name="default_volume" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" aria-describedby="default_volume_label">
|
<input type="range" id="default_volume" name="default_volume" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" aria-describedby="default_volume_label">
|
||||||
@@ -91,34 +91,34 @@ function radio_render_settings_page() {
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
<label for="theme"><?php esc_html_e( 'Theme', 'a-radio' ); ?></label>
|
<label for="theme"><?php esc_html_e( 'Theme', 'rangerhq-radio' ); ?></label>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<select id="theme" name="theme">
|
<select id="theme" name="theme">
|
||||||
<option value="auto" <?php selected( $state['theme'], 'auto' ); ?>><?php esc_html_e( 'Auto (match WP admin colour scheme)', 'a-radio' ); ?></option>
|
<option value="auto" <?php selected( $state['theme'], 'auto' ); ?>><?php esc_html_e( 'Auto (match WP admin colour scheme)', 'rangerhq-radio' ); ?></option>
|
||||||
<option value="light" <?php selected( $state['theme'], 'light' ); ?>><?php esc_html_e( 'Light', 'a-radio' ); ?></option>
|
<option value="light" <?php selected( $state['theme'], 'light' ); ?>><?php esc_html_e( 'Light', 'rangerhq-radio' ); ?></option>
|
||||||
<option value="dark" <?php selected( $state['theme'], 'dark' ); ?>><?php esc_html_e( 'Dark', 'a-radio' ); ?></option>
|
<option value="dark" <?php selected( $state['theme'], 'dark' ); ?>><?php esc_html_e( 'Dark', 'rangerhq-radio' ); ?></option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
<?php esc_html_e( 'Dashboard widget', 'a-radio' ); ?>
|
<?php esc_html_e( 'Dashboard widget', 'rangerhq-radio' ); ?>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="hide_dashboard_widget" value="1" <?php checked( $hide_widget ); ?>>
|
<input type="checkbox" name="hide_dashboard_widget" value="1" <?php checked( $hide_widget ); ?>>
|
||||||
<?php esc_html_e( 'Hide the Radio widget from the WordPress Dashboard', 'a-radio' ); ?>
|
<?php esc_html_e( 'Hide the Radio widget from the WordPress Dashboard', 'rangerhq-radio' ); ?>
|
||||||
</label>
|
</label>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
<?php esc_html_e( 'When checked, Radio is only accessible from the dedicated admin page (WP Admin → Radio → My Radio).', 'a-radio' ); ?>
|
<?php esc_html_e( 'When checked, Radio is only accessible from the dedicated admin page (WP Admin → Radio → My Radio).', 'rangerhq-radio' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<?php submit_button( __( 'Save Changes', 'a-radio' ), 'primary', 'radio_settings_submit' ); ?>
|
<?php submit_button( __( 'Save Changes', 'rangerhq-radio' ), 'primary', 'radio_settings_submit' ); ?>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
* RangerHQ Radio — a small, focused internet radio player for your WP dashboard.
|
* RangerHQ Radio — a small, focused internet radio player for your WP dashboard.
|
||||||
*
|
*
|
||||||
* Plugin Name: RangerHQ Radio
|
* Plugin Name: RangerHQ Radio
|
||||||
* Plugin URI: https://icanhelp.ie/radio
|
* Plugin URI: https://davidtkeane.com/rangerhq-radio
|
||||||
* Description: A small, focused internet radio player for your WordPress admin. 44 hand-curated stations from SomaFM across 10 genres — ambient, electronic, lounge, rock, metal, jazz, world, reggae, holiday, specials. Plays via HTML5 audio; per-user station + volume + history + favourites; pop-out window for continuous background play.
|
* Description: A small, focused internet radio player for your WordPress admin. 44 hand-curated stations from SomaFM across 10 genres — ambient, electronic, lounge, rock, metal, jazz, world, reggae, holiday, specials. Plays via HTML5 audio; per-user station + volume + history + favourites; pop-out window for continuous background play.
|
||||||
* Version: 0.7.4
|
* Version: 1.0.0
|
||||||
* Requires at least: 5.3
|
* Requires at least: 5.3
|
||||||
* Requires PHP: 7.4
|
* Requires PHP: 7.4
|
||||||
* Author: David Keane
|
* Author: David Keane
|
||||||
* Author URI: https://rangersmyth.xyz/
|
* Author URI: https://davidtkeane.com
|
||||||
* License: GPL v2 or later
|
* License: GPL v2 or later
|
||||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
* Text Domain: a-radio
|
* Text Domain: rangerhq-radio
|
||||||
*
|
*
|
||||||
* @package RangerHQ_Radio
|
* @package RangerHQ_Radio
|
||||||
*
|
*
|
||||||
@@ -27,12 +27,12 @@
|
|||||||
if ( ! defined( 'ABSPATH' ) ) { exit; }
|
if ( ! defined( 'ABSPATH' ) ) { exit; }
|
||||||
|
|
||||||
// Plugin coordinates.
|
// Plugin coordinates.
|
||||||
if ( ! defined( 'RADIO_VERSION' ) ) { define( 'RADIO_VERSION', '0.7.4' ); }
|
if ( ! defined( 'RADIO_VERSION' ) ) { define( 'RADIO_VERSION', '1.0.0' ); }
|
||||||
if ( ! defined( 'RADIO_FILE' ) ) { define( 'RADIO_FILE', __FILE__ ); }
|
if ( ! defined( 'RADIO_FILE' ) ) { define( 'RADIO_FILE', __FILE__ ); }
|
||||||
if ( ! defined( 'RADIO_PATH' ) ) { define( 'RADIO_PATH', plugin_dir_path( __FILE__ ) ); }
|
if ( ! defined( 'RADIO_PATH' ) ) { define( 'RADIO_PATH', plugin_dir_path( __FILE__ ) ); }
|
||||||
if ( ! defined( 'RADIO_URL' ) ) { define( 'RADIO_URL', plugin_dir_url( __FILE__ ) ); }
|
if ( ! defined( 'RADIO_URL' ) ) { define( 'RADIO_URL', plugin_dir_url( __FILE__ ) ); }
|
||||||
if ( ! defined( 'RADIO_BASENAME' ) ) { define( 'RADIO_BASENAME', plugin_basename( __FILE__ ) ); }
|
if ( ! defined( 'RADIO_BASENAME' ) ) { define( 'RADIO_BASENAME', plugin_basename( __FILE__ ) ); }
|
||||||
if ( ! defined( 'RADIO_GITEA_URL' ) ) { define( 'RADIO_GITEA_URL', 'https://git.davidtkeane.com/ranger/a-radio' ); }
|
if ( ! defined( 'RADIO_GITEA_URL' ) ) { define( 'RADIO_GITEA_URL', 'https://git.davidtkeane.com/ranger/rangerhq-radio' ); }
|
||||||
if ( ! defined( 'RADIO_SUPPORT_URL' ) ) { define( 'RADIO_SUPPORT_URL', 'https://buymeacoffee.com/davidtkeane' ); }
|
if ( ! defined( 'RADIO_SUPPORT_URL' ) ) { define( 'RADIO_SUPPORT_URL', 'https://buymeacoffee.com/davidtkeane' ); }
|
||||||
|
|
||||||
// Includes — each file owns one concern.
|
// Includes — each file owns one concern.
|
||||||
@@ -52,8 +52,8 @@ require_once RADIO_PATH . 'inc/history.php'; // Track history + favouri
|
|||||||
add_action( 'admin_menu', 'radio_register_admin_menu' );
|
add_action( 'admin_menu', 'radio_register_admin_menu' );
|
||||||
function radio_register_admin_menu() {
|
function radio_register_admin_menu() {
|
||||||
add_menu_page(
|
add_menu_page(
|
||||||
__( 'Radio', 'a-radio' ),
|
__( 'Radio', 'rangerhq-radio' ),
|
||||||
__( 'Radio', 'a-radio' ),
|
__( 'Radio', 'rangerhq-radio' ),
|
||||||
'read', // any logged-in user with read access has their own radio
|
'read', // any logged-in user with read access has their own radio
|
||||||
'radio',
|
'radio',
|
||||||
'radio_render_main_page',
|
'radio_render_main_page',
|
||||||
@@ -67,8 +67,8 @@ function radio_register_admin_menu() {
|
|||||||
// form gotcha).
|
// form gotcha).
|
||||||
add_submenu_page(
|
add_submenu_page(
|
||||||
'radio',
|
'radio',
|
||||||
__( 'My Radio', 'a-radio' ),
|
__( 'My Radio', 'rangerhq-radio' ),
|
||||||
__( 'My Radio', 'a-radio' ),
|
__( 'My Radio', 'rangerhq-radio' ),
|
||||||
'read',
|
'read',
|
||||||
'radio',
|
'radio',
|
||||||
''
|
''
|
||||||
@@ -76,8 +76,8 @@ function radio_register_admin_menu() {
|
|||||||
|
|
||||||
add_submenu_page(
|
add_submenu_page(
|
||||||
'radio',
|
'radio',
|
||||||
__( 'Settings', 'a-radio' ),
|
__( 'Settings', 'rangerhq-radio' ),
|
||||||
__( 'Settings', 'a-radio' ),
|
__( 'Settings', 'rangerhq-radio' ),
|
||||||
'manage_options',
|
'manage_options',
|
||||||
'radio-settings',
|
'radio-settings',
|
||||||
'radio_render_settings_page'
|
'radio_render_settings_page'
|
||||||
@@ -85,8 +85,8 @@ function radio_register_admin_menu() {
|
|||||||
|
|
||||||
add_submenu_page(
|
add_submenu_page(
|
||||||
'radio',
|
'radio',
|
||||||
__( 'Track history', 'a-radio' ),
|
__( 'Track history', 'rangerhq-radio' ),
|
||||||
__( 'History', 'a-radio' ),
|
__( 'History', 'rangerhq-radio' ),
|
||||||
'read',
|
'read',
|
||||||
'radio-history',
|
'radio-history',
|
||||||
'radio_render_history_page'
|
'radio_render_history_page'
|
||||||
@@ -94,8 +94,8 @@ function radio_register_admin_menu() {
|
|||||||
|
|
||||||
add_submenu_page(
|
add_submenu_page(
|
||||||
'radio',
|
'radio',
|
||||||
__( 'About', 'a-radio' ),
|
__( 'About', 'rangerhq-radio' ),
|
||||||
__( 'About', 'a-radio' ),
|
__( 'About', 'rangerhq-radio' ),
|
||||||
'read',
|
'read',
|
||||||
'radio-about',
|
'radio-about',
|
||||||
'radio_render_about_page'
|
'radio_render_about_page'
|
||||||
@@ -140,19 +140,19 @@ function radio_enqueue_admin_assets( $hook ) {
|
|||||||
'nonce' => wp_create_nonce( 'radio_save_state' ),
|
'nonce' => wp_create_nonce( 'radio_save_state' ),
|
||||||
'popoutUrl' => admin_url( 'admin-post.php?action=radio_popout' ),
|
'popoutUrl' => admin_url( 'admin-post.php?action=radio_popout' ),
|
||||||
'strings' => array(
|
'strings' => array(
|
||||||
'play' => __( 'Play', 'a-radio' ),
|
'play' => __( 'Play', 'rangerhq-radio' ),
|
||||||
'pause' => __( 'Pause', 'a-radio' ),
|
'pause' => __( 'Pause', 'rangerhq-radio' ),
|
||||||
'loading' => __( 'Loading…', 'a-radio' ),
|
'loading' => __( 'Loading…', 'rangerhq-radio' ),
|
||||||
'error' => __( 'Stream error — try another station.', 'a-radio' ),
|
'error' => __( 'Stream error — try another station.', 'rangerhq-radio' ),
|
||||||
'saveError' => __( 'Preferences not saved — check your connection.', 'a-radio' ),
|
'saveError' => __( 'Preferences not saved — check your connection.', 'rangerhq-radio' ),
|
||||||
'mute' => __( 'Mute', 'a-radio' ),
|
'mute' => __( 'Mute', 'rangerhq-radio' ),
|
||||||
'unmute' => __( 'Unmute', 'a-radio' ),
|
'unmute' => __( 'Unmute', 'rangerhq-radio' ),
|
||||||
'nowPlaying' => __( 'Now Playing', 'a-radio' ),
|
'nowPlaying' => __( 'Now Playing', 'rangerhq-radio' ),
|
||||||
'volume' => __( 'Volume', 'a-radio' ),
|
'volume' => __( 'Volume', 'rangerhq-radio' ),
|
||||||
'station' => __( 'Station', 'a-radio' ),
|
'station' => __( 'Station', 'rangerhq-radio' ),
|
||||||
'addFav' => __( 'Add to favourites', 'a-radio' ),
|
'addFav' => __( 'Add to favourites', 'rangerhq-radio' ),
|
||||||
'removeFav' => __( 'Remove from favourites', 'a-radio' ),
|
'removeFav' => __( 'Remove from favourites', 'rangerhq-radio' ),
|
||||||
'clearConfirm' => __( 'Clear all track history? (Favourites are kept.)', 'a-radio' ),
|
'clearConfirm' => __( 'Clear all track history? (Favourites are kept.)', 'rangerhq-radio' ),
|
||||||
),
|
),
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
@@ -241,7 +241,7 @@ function radio_ajax_clear_history() {
|
|||||||
add_action( 'admin_post_radio_popout', 'radio_render_popout_page' );
|
add_action( 'admin_post_radio_popout', 'radio_render_popout_page' );
|
||||||
function radio_render_popout_page() {
|
function radio_render_popout_page() {
|
||||||
if ( ! current_user_can( 'read' ) ) {
|
if ( ! current_user_can( 'read' ) ) {
|
||||||
wp_die( esc_html__( 'You do not have permission to view this page.', 'a-radio' ) );
|
wp_die( esc_html__( 'You do not have permission to view this page.', 'rangerhq-radio' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$state = radio_get_state();
|
$state = radio_get_state();
|
||||||
@@ -258,16 +258,16 @@ function radio_render_popout_page() {
|
|||||||
'popoutUrl' => '', // already in popout — no further popouts
|
'popoutUrl' => '', // already in popout — no further popouts
|
||||||
'autoPlay' => isset( $_GET['play'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- query flag only, no state change
|
'autoPlay' => isset( $_GET['play'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- query flag only, no state change
|
||||||
'strings' => array(
|
'strings' => array(
|
||||||
'play' => __( 'Play', 'a-radio' ),
|
'play' => __( 'Play', 'rangerhq-radio' ),
|
||||||
'pause' => __( 'Pause', 'a-radio' ),
|
'pause' => __( 'Pause', 'rangerhq-radio' ),
|
||||||
'loading' => __( 'Loading…', 'a-radio' ),
|
'loading' => __( 'Loading…', 'rangerhq-radio' ),
|
||||||
'error' => __( 'Stream error — try another station.', 'a-radio' ),
|
'error' => __( 'Stream error — try another station.', 'rangerhq-radio' ),
|
||||||
'saveError' => __( 'Preferences not saved — check your connection.', 'a-radio' ),
|
'saveError' => __( 'Preferences not saved — check your connection.', 'rangerhq-radio' ),
|
||||||
'mute' => __( 'Mute', 'a-radio' ),
|
'mute' => __( 'Mute', 'rangerhq-radio' ),
|
||||||
'unmute' => __( 'Unmute', 'a-radio' ),
|
'unmute' => __( 'Unmute', 'rangerhq-radio' ),
|
||||||
'nowPlaying' => __( 'Now Playing', 'a-radio' ),
|
'nowPlaying' => __( 'Now Playing', 'rangerhq-radio' ),
|
||||||
'volume' => __( 'Volume', 'a-radio' ),
|
'volume' => __( 'Volume', 'rangerhq-radio' ),
|
||||||
'station' => __( 'Station', 'a-radio' ),
|
'station' => __( 'Station', 'rangerhq-radio' ),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -289,15 +289,15 @@ function radio_render_popout_page() {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title><?php
|
<title><?php
|
||||||
/* translators: %s = currently playing station name */
|
/* translators: %s = currently playing station name */
|
||||||
printf( esc_html__( 'Radio — %s', 'a-radio' ), esc_html( $station['name'] ) );
|
printf( esc_html__( 'Radio — %s', 'rangerhq-radio' ), esc_html( $station['name'] ) );
|
||||||
?></title>
|
?></title>
|
||||||
<?php wp_print_styles(); /* dashicons + radio.css; popup-specific overrides scoped under body.radio-popout in radio.css */ ?>
|
<?php wp_print_styles(); /* dashicons + radio.css; popup-specific overrides scoped under body.radio-popout in radio.css */ ?>
|
||||||
</head>
|
</head>
|
||||||
<body class="radio-popout radio-theme-<?php echo esc_attr( $theme ); ?>">
|
<body class="radio-popout radio-theme-<?php echo esc_attr( $theme ); ?>">
|
||||||
|
|
||||||
<div class="radio-popout-header">
|
<div class="radio-popout-header">
|
||||||
<h1><?php esc_html_e( 'Radio', 'a-radio' ); ?></h1>
|
<h1><?php esc_html_e( 'Radio', 'rangerhq-radio' ); ?></h1>
|
||||||
<button type="button" class="radio-popout-close" onclick="window.close()" title="<?php esc_attr_e( 'Close', 'a-radio' ); ?>">✕</button>
|
<button type="button" class="radio-popout-close" onclick="window.close()" title="<?php esc_attr_e( 'Close', 'rangerhq-radio' ); ?>">✕</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-popout-wrap">
|
<div class="radio-popout-wrap">
|
||||||
@@ -308,7 +308,7 @@ function radio_render_popout_page() {
|
|||||||
<span class="radio-player__bars"><span></span><span></span><span></span><span></span></span>
|
<span class="radio-player__bars"><span></span><span></span><span></span><span></span></span>
|
||||||
<canvas class="radio-player__viz" data-radio-viz hidden></canvas>
|
<canvas class="radio-player__viz" data-radio-viz hidden></canvas>
|
||||||
</span>
|
</span>
|
||||||
<span class="radio-player__label"><?php esc_html_e( 'Now Playing', 'a-radio' ); ?></span>
|
<span class="radio-player__label"><?php esc_html_e( 'Now Playing', 'rangerhq-radio' ); ?></span>
|
||||||
<span class="radio-player__station-name" data-radio-name><?php echo esc_html( $station['name'] ); ?></span>
|
<span class="radio-player__station-name" data-radio-name><?php echo esc_html( $station['name'] ); ?></span>
|
||||||
<span class="radio-player__station-genre" data-radio-genre><?php echo esc_html( $station['genre'] ); ?></span>
|
<span class="radio-player__station-genre" data-radio-genre><?php echo esc_html( $station['genre'] ); ?></span>
|
||||||
<p class="radio-player__station-desc" data-radio-desc><?php echo esc_html( $station['description'] ); ?></p>
|
<p class="radio-player__station-desc" data-radio-desc><?php echo esc_html( $station['description'] ); ?></p>
|
||||||
@@ -318,19 +318,19 @@ function radio_render_popout_page() {
|
|||||||
<div class="radio-player__controls">
|
<div class="radio-player__controls">
|
||||||
<button type="button" class="button button-primary radio-player__play" data-radio-play>
|
<button type="button" class="button button-primary radio-player__play" data-radio-play>
|
||||||
<span class="radio-player__play-glyph" data-radio-play-glyph aria-hidden="true">▶</span>
|
<span class="radio-player__play-glyph" data-radio-play-glyph aria-hidden="true">▶</span>
|
||||||
<span data-radio-play-label><?php esc_html_e( 'Play', 'a-radio' ); ?></span>
|
<span data-radio-play-label><?php esc_html_e( 'Play', 'rangerhq-radio' ); ?></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="radio-player__volume">
|
<div class="radio-player__volume">
|
||||||
<button type="button" class="radio-player__mute" data-radio-mute aria-label="<?php esc_attr_e( 'Mute', 'a-radio' ); ?>">
|
<button type="button" class="radio-player__mute" data-radio-mute aria-label="<?php esc_attr_e( 'Mute', 'rangerhq-radio' ); ?>">
|
||||||
<span class="dashicons dashicons-controls-volumeon" aria-hidden="true"></span>
|
<span class="dashicons dashicons-controls-volumeon" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<input type="range" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" data-radio-volume aria-label="<?php esc_attr_e( 'Volume', 'a-radio' ); ?>">
|
<input type="range" min="0" max="100" value="<?php echo esc_attr( (int) round( $state['volume'] * 100 ) ); ?>" data-radio-volume aria-label="<?php esc_attr_e( 'Volume', 'rangerhq-radio' ); ?>">
|
||||||
<span class="radio-player__volume-pct" data-radio-volume-pct><?php echo esc_html( (int) round( $state['volume'] * 100 ) ); ?>%</span>
|
<span class="radio-player__volume-pct" data-radio-volume-pct><?php echo esc_html( (int) round( $state['volume'] * 100 ) ); ?>%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="radio-player__station-select">
|
<div class="radio-player__station-select">
|
||||||
<label for="radio-station-popout"><?php esc_html_e( 'Station', 'a-radio' ); ?></label>
|
<label for="radio-station-popout"><?php esc_html_e( 'Station', 'rangerhq-radio' ); ?></label>
|
||||||
<select id="radio-station-popout" data-radio-station>
|
<select id="radio-station-popout" data-radio-station>
|
||||||
<?php foreach ( $stations as $genre => $entries ) :
|
<?php foreach ( $stations as $genre => $entries ) :
|
||||||
if ( empty( $entries ) ) { continue; }
|
if ( empty( $entries ) ) { continue; }
|
||||||
|
|||||||
+20
-2
@@ -4,7 +4,7 @@ Donate link: https://buymeacoffee.com/davidtkeane
|
|||||||
Tags: radio, music, audio, internet radio, background music
|
Tags: radio, music, audio, internet radio, background music
|
||||||
Requires at least: 5.3
|
Requires at least: 5.3
|
||||||
Tested up to: 7.0
|
Tested up to: 7.0
|
||||||
Stable tag: 0.7.4
|
Stable tag: 1.0.0
|
||||||
Requires PHP: 7.4
|
Requires PHP: 7.4
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
@@ -62,7 +62,7 @@ No — RangerHQ Radio is admin-only. It adds a player to the WordPress dashboard
|
|||||||
|
|
||||||
= Can I add my own stations? =
|
= Can I add my own stations? =
|
||||||
|
|
||||||
Not via the admin yet. The station list is hard-coded in `inc/stations.php` (44 SomaFM stations). If you'd like to add custom stations or other internet radio sources, please open an issue on the [Gitea repo](https://git.davidtkeane.com/ranger/a-radio).
|
Not via the admin yet. The station list is hard-coded in `inc/stations.php` (44 SomaFM stations). If you'd like to add custom stations or other internet radio sources, please open an issue on the [Gitea repo](https://git.davidtkeane.com/ranger/rangerhq-radio).
|
||||||
|
|
||||||
= The pop-out window doesn't open. =
|
= The pop-out window doesn't open. =
|
||||||
|
|
||||||
@@ -86,6 +86,15 @@ SomaFM's track-info endpoint (`somafm.com/songs/{station}.json`) is fetched best
|
|||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.0.0 =
|
||||||
|
* Stability milestone. Same code as 0.7.6, no functional changes — but the version number now signals what the wp.org listing already shows in practice: the architecture (per-user `wp_usermeta` storage shape, 4-button search URL templates, station catalogue format, history dedup rule) is stable. From 1.0.0 forwards, breaking changes go in 2.0.0; everything in 1.x will preserve the public API. Released after five days live on wp.org, 50+ downloads, and the family pattern (per-user storage, four-button search) proven and ported to RangerHQ Tuner (Chrome Web Store) and RangerHQ Buddy (in wp.org review).
|
||||||
|
|
||||||
|
= 0.7.6 =
|
||||||
|
* Plugin metadata cleanup following the wp.org pre-review feedback. `Plugin URI` header updated from `https://icanhelp.ie/radio` to `https://davidtkeane.com/rangerhq-radio` (the canonical project page, now live). `Author URI` header updated from `https://rangersmyth.xyz/` to `https://davidtkeane.com` (both old URLs were returning DNS errors or 404). Ownership of the davidtkeane.com domain has been verified to wp.org via DNS TXT record and a domain-matched account email. No code changes, no user-visible behaviour changes — metadata only.
|
||||||
|
|
||||||
|
= 0.7.5 =
|
||||||
|
* WordPress.org slug rename: `a-radio` → `rangerhq-radio`. The previous slug was flagged as too generic for the wp.org Plugin Directory (single common functional word, no distinguishing prefix). The new slug matches the public display name "RangerHQ Radio" and lines up with the rest of the RangerHQ plugin family (`rangerhq-spatial`, `rangerhq-glyph`). Text Domain renamed to match — all 125 i18n call sites updated. Gitea repository moved to https://git.davidtkeane.com/ranger/rangerhq-radio. No user-visible behaviour change in the player; this is a packaging change only. Plugin Name stays "RangerHQ Radio"; internal constants (`RADIO_*`) and user-meta keys (`radio_state` / `radio_history` / `radio_favourites`) are unchanged so settings + history + favourites all survive intact.
|
||||||
|
|
||||||
= 0.7.4 =
|
= 0.7.4 =
|
||||||
* WordPress.org submission cleanup. Removed the self-hosted Gitea updater (`inc/updater.php`) and the `Update URI` header from `radio.php`. WordPress.org explicitly disallows both for hosted plugins (Plugin Check `plugin_updater_detected`), so updates now flow through WordPress.org as the canonical channel. Added a top-level `LICENSE` file with the full GPL v2 text and explicit GPL header blocks to `assets/css/radio.css` and `assets/js/radio.js` so the licensing of every shipped file is unambiguous. The small `Updates` panel that used to sit at the bottom of Radio → Settings is gone; player behaviour is unchanged.
|
* WordPress.org submission cleanup. Removed the self-hosted Gitea updater (`inc/updater.php`) and the `Update URI` header from `radio.php`. WordPress.org explicitly disallows both for hosted plugins (Plugin Check `plugin_updater_detected`), so updates now flow through WordPress.org as the canonical channel. Added a top-level `LICENSE` file with the full GPL v2 text and explicit GPL header blocks to `assets/css/radio.css` and `assets/js/radio.js` so the licensing of every shipped file is unambiguous. The small `Updates` panel that used to sit at the bottom of Radio → Settings is gone; player behaviour is unchanged.
|
||||||
|
|
||||||
@@ -130,6 +139,15 @@ SomaFM's track-info endpoint (`somafm.com/songs/{station}.json`) is fetched best
|
|||||||
|
|
||||||
== Upgrade Notice ==
|
== Upgrade Notice ==
|
||||||
|
|
||||||
|
= 1.0.0 =
|
||||||
|
Stability milestone — same code as 0.7.6, version number now signals what the plugin already is in practice: mature. From 1.0.0 onwards the public API (storage shape, search URL templates, station data format) is locked; breaking changes will go in 2.0.0. No behaviour change in this update.
|
||||||
|
|
||||||
|
= 0.7.6 =
|
||||||
|
Metadata-only update: Plugin URI + Author URI updated to davidtkeane.com following wp.org pre-review feedback. No code changes, no behaviour change.
|
||||||
|
|
||||||
|
= 0.7.5 =
|
||||||
|
WordPress.org slug renamed `a-radio` → `rangerhq-radio` (lines up with display name "RangerHQ Radio" and the family pattern). Text Domain matches. No player behaviour change. Existing user state (station / volume / history / favourites) survives intact.
|
||||||
|
|
||||||
= 0.7.4 =
|
= 0.7.4 =
|
||||||
WordPress.org submission cleanup — removes the disallowed self-hosted updater + `Update URI` header. Adds LICENSE file + per-asset GPL headers. The `Updates` panel in Settings is gone (WordPress.org handles updates now). No player behaviour changes.
|
WordPress.org submission cleanup — removes the disallowed self-hosted updater + `Update URI` header. Adds LICENSE file + per-asset GPL headers. The `Updates` panel in Settings is gone (WordPress.org handles updates now). No player behaviour changes.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user