340cbb24870576d5ccd9bfacc713a5c5ab3d1548
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
340cbb2487 |
v0.7.5 — WordPress.org slug rename: a-radio → rangerhq-radio
A third-party AI-driven naming check flagged `a-radio` as too generic for the wp.org Plugin Directory (single common functional word, no distinguishing prefix). The verdict was advisory but defensible — short generic slugs are increasingly rejected as the directory grows past 60K plugins. Fixing it preemptively is cheaper than facing a rejection at submission time. The new slug `rangerhq-radio` matches the public display name "RangerHQ Radio" (unchanged) and lines up with the rest of the RangerHQ plugin family: `rangerhq-spatial`, `rangerhq-glyph`, now `rangerhq-radio`. Changes (packaging only — no player behaviour change): * Text Domain `a-radio` → `rangerhq-radio` across all 125 i18n call sites via in-place sed (esc_html__, _e, __, esc_attr_e and their friends). PHP lint clean post-rename. * `Text Domain:` plugin header in radio.php line 15 → `rangerhq-radio`. * `RADIO_GITEA_URL` constant value → new Gitea repo URL. * README.md install link → new repo URL. * readme.txt FAQ Gitea link → new repo URL. * readme.txt Stable tag → 0.7.5. * inc/about.php — v0.7.5 in "latest" slot; v0.7.4 demoted. Unchanged deliberately (would have been pure churn): * Plugin Name header "RangerHQ Radio" — already correct. * Plugin URI. * Internal constants `RADIO_*` — don't have to match slug. * User-meta keys `radio_state` / `radio_history` / `radio_favourites` — renaming would orphan every existing user's settings on upgrade. * HTML `data-radio-*` attributes — JS controller's element selectors in radio.js, not slug-related. * CSS class names `radio-player`, `radio-about-*` — internal scoping. * Main plugin file name `radio.php`. Migration: existing Gitea-installed copies need their folder renamed on disk (a-radio → rangerhq-radio) + reactivation in WP admin. No data loss because all user-facing state lives in user_meta under unchanged keys. This commit is the file content for v0.7.5; the annotated tag and push will follow the Gitea repo rename (ranger/a-radio → ranger/rangerhq-radio) so the new tag lives in the new URL space from the start. |
||
|
|
09b61cc950 |
feat(0.7.0): WordPress.org submission prep — full Plugin Check clean
Ran the official Plugin Check (PCP) against v0.6.3 — surfaced 169
issues. This release closes all of them so the plugin is submission-
ready for the WordPress.org plugin directory.
Branding
- Plugin Name renamed: "Radio" → "RangerHQ Radio". Removes the
trademarked "SomaFM" from the plugin name surface (PCP
trademarked_term). Lines up with the RangerHQ plugin family.
SomaFM credited in Description + About as the data source.
Folder/slug stays `a-radio` — no install path changes; existing
user_meta keys (radio_state / radio_history / radio_favourites)
untouched.
- Text Domain header renamed: `radio` → `a-radio` (matches slug).
- Requires at least bumped: 5.0 → 5.3 (matches wp_date() usage).
- File docstring header dropped "SomaFM" from prominent line.
Code (mass-mechanical)
- 134 i18n call sites rewritten from `'radio'` text domain to
`'a-radio'` across 7 PHP files. Single sed pass on the unique
pattern `, 'radio' )` — the 6 menu-slug `'radio'` references in
add_*_page() were correctly left alone (those are URL slugs).
Security
- 8 × MissingUnslash + 8 × InputNotSanitized in the v0.5.0 history
endpoints (radio_ajax_log_track, radio_ajax_toggle_favourite).
All four $_POST['artist|title|station|station_id'] access points
are now wrapped sanitize_text_field( wp_unslash( $_POST['…'] ) )
(or sanitize_key for station_id) at the access point.
Translator comments
- 6 × printf / sprintf calls with placeholders now carry
/* translators: ... */ comments.
Pop-out window refactor
- Inline <link> stylesheets, <style> block, and <script> tag in
radio_render_popout_page() replaced with wp_enqueue_style() +
wp_enqueue_script() + wp_localize_script() registered before HTML
output, then wp_print_styles() in <head> and wp_print_footer_
scripts() at end of <body>.
- Popup-specific CSS moved out of inline <style> and into radio.css
under body.radio-popout scope so it only fires inside the popup.
Removed
- .DS_Store files (root + assets/). PCP hidden_files.
Distribution
- New readme.txt in proper WordPress.org format: Plugin headers,
Contributors, Donate link, Tags, Requires-at-least, Tested-up-to,
Stable Tag, Requires-PHP, License, Description, Installation,
FAQ, Screenshots, Changelog, Upgrade Notice.
Compat
- No behaviour change for users; user_meta preserved.
- Displayed Plugin Name in Plugins → Installed changes from "Radio"
to "RangerHQ Radio" — only visible difference on update.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
0dc3a220d9 |
feat(0.6.0): pop-out mini-player — continuous background play across admin nav
Until v0.5.0 the audio cut every time you navigated between WP admin
pages — every navigation is a full page reload, which destroys the
<audio> element. v0.6.0 fixes the background-music use case by letting
you pop the player out into a separate browser window that persists
across the parent tab's navigation.
Pop-out window
- Small "↗ Pop out" button beside the Play button on both the main
Radio page and the Dashboard widget.
- Opens a 380×560 standalone window via window.open() with a window
name of `radio_popout` so a second click re-focuses the existing
popup rather than spawning a new one.
- Popup renders at admin-post.php?action=radio_popout&play=1 — a new
admin_post_radio_popout hook outputs a full standalone HTML page
(custom DOCTYPE / head / body, no WP admin chrome).
- Theme follows radio_state['theme'] via body class radio-theme-{...}.
- Includes the full player (now-playing block with dancing bars +
Web Audio visualizer, play, mute, volume, station dropdown, error
slot). Close button calls window.close().
Auto-resume + single-stream invariant
- cfg.autoPlay is true when the popup URL carries &play=1. radio.js
auto-calls audio.play() 200 ms after init. Same-origin user-gesture
popups are exempt from autoplay-blocking on every modern browser.
- On pop-out click, every other audio surface in the parent tab is
paused so there is only ever one stream playing.
State stays in sync
- Popup uses the SAME radio_save_state AJAX + track-logging endpoint.
Station / volume changes persist to user_meta; track history keeps
accumulating from whichever surface is playing.
Edge cases
- Inside the popup, cfg.popoutUrl is '' so bindPopOut hides any
Pop-out button it finds (would be infinite otherwise).
- Popup blocked by browser → clear alert tells the user to allow
popups for this site.
Files
- radio.php (version, popoutUrl in localized config, admin_post
handler + full standalone HTML renderer)
- inc/admin-page.php + inc/dashboard-widget.php (Pop-out button
beside Play)
- assets/css/radio.css (.radio-player__popout styling)
- assets/js/radio.js (bindPopOut function; autoPlay branch in
bindPlayer)
- inc/about.php + CHANGELOG.md (history entries)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f5feca7dfa |
feat(0.4.0): now-playing indicator — dancing bars + Web Audio visualizer
Two-layer "this is playing right now" visual:
(1) CSS dancing bars — four tiny vertical bars next to the "Now Playing"
label, staggered `@keyframes` pulse while audio plays. Pure CSS, no
JS dependency, tints to the user's WP admin colour scheme via
var(--wp-admin-theme-color). Driven by a single `.is-playing` class
on `.radio-player` toggled from the existing play/pause/error
handlers. Always works.
(2) Web Audio frequency visualizer (progressive upgrade) — on first play,
builds AudioContext + AnalyserNode + canvas drawing pipeline. When
the analyser starts returning real (non-zero) data, hides the bars
and shows the canvas with live frequency bars. Falls back to bars
if AudioContext is unavailable, createMediaElementSource throws, or
the analyser returns all-zeros for >2s (CORS silently blocking).
State machine on player._vizState: no-webaudio / init-failed /
cors-blocked / ok.
`<audio>` element gained `crossorigin="anonymous"` so Web Audio can read
the stream data (SomaFM serves the CORS headers).
Files: radio.php (version), inc/admin-page.php + inc/dashboard-widget.php
(.radio-player__indicator with .radio-player__bars + canvas; crossorigin
on audio), assets/css/radio.css (indicator, bars, radio-bars-dance
keyframes, canvas size), assets/js/radio.js (tryVisualizer,
startVizLoop, stopVizLoop; play/pause/error handlers wire the loop and
toggle is-playing), inc/about.php (history entry).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a56fd7aff7 |
fix(0.3.2): play-button glyph baseline — drop dashicon for Unicode ▶ / ‖
The dashicon used for the play/pause icon was rendering visibly below the button text — dashicon font metrics sit the glyph low inside its own box, so even with `inline-flex` centering the symbol looked like it was on a separate row from the word "Play". Swap dashicons-controls-play / dashicons-controls-pause for plain Unicode glyphs (▶ / ‖) which render on the text baseline like any other character. Flex container changed to align-items: baseline. font-variant-emoji: text on the glyph span to keep platforms that might otherwise pick up an emoji variant of ▶ as monochrome text. Files: radio.php (version), inc/admin-page.php + inc/dashboard-widget.php (dashicon span → glyph span), assets/css/radio.css (drop dashicon-sizing rule, add .radio-player__play-glyph, baseline alignment), assets/js/radio.js (setPlayIcon swaps glyph textContent instead of dashicon className), inc/about.php (history entry). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c5a4b28b29 |
feat(0.3.0): dark theme, mute, media keys, current-track + 2nd-look fixes
Closes the gaps from a UI review of v0.2.0. Added - Mute toggle: speaker icon is now a button; remembers prior volume. - MediaSession API: OS media keys / headphone buttons / lock-screen widget play/pause the radio. Metadata exposes station + SomaFM + genre. - Current-track display: polls https://somafm.com/songs/{code}.json every 30s while playing; shown as `♪ Title — Artist` under the description. Best-effort — silently hidden if CORS-blocked / unreachable. Fixed (2nd-look) - Dark theme now actually renders. v0.2.0 saved the dropdown but had no CSS — add `admin_body_class` filter + `radio-theme-{auto,light,dark}` CSS for the player + about-cards. `auto` follows OS prefers-color-scheme. - Settings-page volume slider: removed inline `oninput`; wired in radio.js via `bindSettingsSlider()`. Cleaner under strict CSP. - Save errors surface as a transient notice instead of being swallowed. - Gitea changelog URL moved into `RADIO_GITEA_URL` constant. - Genre badge restyled as an inline pill (was using `margin-left: auto` which wrapped poorly on narrow widget widths). Files - radio.php (version, constant, strings, body-class filter) - inc/about.php (use constant, add 0.3.0 history entry) - inc/settings.php (drop inline oninput) - inc/admin-page.php + inc/dashboard-widget.php (mute button, track slot) - assets/css/radio.css (pill, mute, track, dark-theme rules) - assets/js/radio.js (rewrite: mute, MediaSession, track polling, settings slider, save-error surfacing) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
3e6994461e |
feat: v0.2.0 — UI rebuilt to WordPress admin standards
v0.1.0 worked but felt like a third-party React widget bolted on
top of WordPress. v0.2.0 makes the player visually native to the
WP admin: postbox container, standard Play/Pause button with text
label, admin-colour-scheme aware accents, dashboard widget no
longer renders a card inside a card.
CHANGES
- inc/admin-page.php: main page now wraps the player in a
.postbox > .postbox-header (with h2.hndle) > .inside structure.
Custom rounded card / shadow stripped.
- inc/dashboard-widget.php: bare .radio-player content; WP already
wraps dashboard widgets in a postbox, was double-card before.
- inc/about.php: version-history card promotes v0.2.0 to latest,
demotes v0.1.0.
- assets/css/radio.css: rewrite. Strip custom shadows + oversized
typography. Adopt WP body-text defaults. Use
var(--wp-admin-theme-color, #2271b1) for volume-slider accent +
link colours so the plugin picks up whichever admin colour
scheme the user has chosen. About-page cards now use the
postbox-style gray header + 1px border pattern.
- assets/js/radio.js: setPlayIcon() also flips the visible text
label ("Play" ↔ "Pause"), not just the icon class. mirrorSelection()
also updates the [data-radio-genre] element so the genre label
stays in sync across surfaces.
- radio.php: Version: 0.1.0 -> 0.2.0; BUDDY_VERSION constant
bumped likewise.
- CHANGELOG.md: new [0.2.0] entry explaining the visual overhaul.
NET EFFECT
- Same 44 stations, same audio path, same persistence, same
updater, same AJAX endpoint. Pure visual change.
- The plugin now looks like part of WordPress admin instead of a
guest widget.
- Closer to WP.org submission criteria — plugin reviewers look
for native-styled plugins.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a22ddfb6d3 |
chore: initial commit — Radio v0.1.0 (Phase A complete)
First release of a-radio — a free, focused SomaFM player for the
WordPress admin. Extracted-and-rebuilt from RangerPlex's RadioPlayer
component, simplified along the way (no Node CORS proxy needed; the
browser plays SomaFM streams directly).
Phase A deliverables — all in this commit:
PLAYER SURFACES
- Dashboard widget on WP Admin → Dashboard (compact: play/pause +
station select + volume).
- Dedicated admin page at WP Admin → Radio → My Radio (larger
layout, station genre badge, volume %% display).
- Both surfaces share the same JS — picking a station on one mirrors
to the other within the same admin session.
STATIONS
- 44 SomaFM stations grouped by 10 genres (Ambient / Electronic /
Lounge / Rock / Metal / Jazz / World / Reggae / Holiday / Specials).
- Ported verbatim from RangerPlex's RadioPlayer.tsx.
- Default station: Groove Salad (most popular SomaFM channel, safe
ambient/coding pick).
STATE
- Per-user state stored in user_meta under key `radio_state`:
{ station_id, volume, theme, last_played_at }.
- Settings page lets the user pick default station, default volume,
theme (auto/light/dark), and hide the dashboard widget.
- AJAX endpoint `radio_save_state` persists changes without a page
reload. Nonce-protected, capability-checked, only known keys
accepted, station validated against the list, volume clamped to
[0,1].
UPDATES
- Self-hosted updater wired to Gitea (ranger/a-radio) from commit 1.
- Direct port of Buddy's inc/updater.php with BUDDY_* → RADIO_* and
buddy_* → radio_* renames. Same 12h-success / 1h-error caching.
ARCHITECTURE
- No `wp` prefix (trademark policy).
- GPL v2+ public Gitea repo from day one.
- Vanilla JS only — no React, no webpack, no minified-only files.
- CSS-only animations, all assets local.
- Single H1 per admin page.
- Direct HTML5 <audio> playback (SomaFM has CORS headers; no PHP
audio proxy needed). This is the key simplification vs RangerPlex.
COMPLIANCE
- "Powered by SomaFM" credit displayed on both player surfaces with
link to somafm.com. About page invites users to donate to SomaFM
directly.
PHASE PROGRESSION (not in this commit)
- Phase B — Settings polish + retry on transient stream errors +
README.md formatted for WP.org submission.
- Phase C — Now-playing metadata via SomaFM's per-station song
history endpoint (this is where the RangerPlex proxy logic ports
to — server-side, for metadata not audio).
- Phase D — [ranger_radio] shortcode for frontend embedding.
- Phase E — Favorites system.
- Phase F — Multi-provider (Radio Paradise / NTS / KEXP / BBC).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|