Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

---

## [Unreleased — Community Fork]

### Added
- **18 new themes** — Light, Red, Cyan, Nord, Gruvbox, Tokyo Night, Rosé Pine, Solarized Dark, Monokai, One Dark, Synthwave, Matrix, Sunset, Ocean, Forest, Coffee, Mono, and High Contrast (now 28 themes total).
- **Custom accent color** — Pick any color as the `--accent` override from the Settings modal; persists across sessions and can be cleared with a single click.
- **Expanded playback speed** — Now available for **all** sources (music, podcasts, audiobooks) instead of just podcasts/audiobooks. 11-step preset ladder (0.5× → 3×), plus a fine-grained slider in Settings (0.5× – 3× in 0.05 increments). Pitch preservation is togglable (chipmunk mode).
- **Sleep timer** — Auto-pause after 5/10/15/30/45 min, 1h, 1.5h, 2h, or "end of current track". Live countdown displayed in Settings.
- **A-B repeat loop** — Mark two points on any track (keyboard `B` / `Z`) to loop a section. Useful for practicing parts of a song or a specific passage in an audiobook.
- **Resilient `fetch` utility** — New `fetchWithRetry` / `fetchJsonWithRetry` helpers with exponential backoff, `Retry-After` honoring, and retriable-status detection (408, 425, 429, 5xx).
- **Self-healing error handler** — Global `error` + `unhandledrejection` listeners log context to the console and show rate-limited toasts so users know something hiccupped, without crashing playback.
- **Diagnostics panel** — "Run Diagnostics" button in Settings probes `/api/health`, localStorage, audio element, MediaSession, service worker, and core state integrity, then reports a pass/fail summary.
- **Expanded keyboard shortcuts** — `[` / `]` speed down/up, `\` reset speed, `T` / `Shift+T` cycle themes, `B` set A-B point, `Z` clear A-B, `N` nudge sleep timer +15 min, `/` focus search.
- **Utility helpers** — `debounce` and `throttle` added to `utils.js` for call-rate-limited event handlers across modules.

### Changed
- **Theme handling** — Switched from hard-coded class-removal list to a regex-based scrub of any `theme-*` class, so new themes never break the picker. `applyTheme()` / `cycleTheme()` now exported for reuse.
- **Playback speed UI** — Speed button is always visible (not hidden for music); right-click (context menu) on the speed button now cycles backwards. Saved speed applies immediately on module load, before the first track plays.
- **More menu** — Removed donate link from the "More" menu. Fewer distractions while browsing. (The original Support section in Settings is preserved for existing users.)

### Fixed
- Theme picker previously only removed a fixed list of ~10 theme classes, so any new theme would accumulate stale classes on `body`. Now scrubs *all* `theme-*` classes.
- `playbackRate` / `preservesPitch` setters are now wrapped in `try/catch` so a single browser without support doesn't break audio.
- `<meta name="theme-color">` updates now run inside `requestAnimationFrame` so the accent variable is re-resolved after the class swap.

---

## [1.4.8] - 2026-04-18

### Fixed
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Freedify - Music Streaming Web App

```markdown
*Last updated: March 25, 2026*
```

Stream music and podcasts from anywhere. **Generate smart playlists with AI**, search songs, albums, artists, podcasts or paste URLs from Spotify, SoundCloud, Bandcamp, Archive.org, Phish.in, and more.

> 💖 **Support Freedify!** If you enjoy using Freedify and want to support its ongoing development and new features, please consider making a donation: **[Donate on Pally.gg](https://pally.gg/p/freedify)**. Any amount is incredibly appreciated and helps keep the music playing!
> This is a community fork of [BioHapHazard/Freedify](https://github.com/BioHapHazard/Freedify)
> focused on performance, resilience, and feature polish. See [CHANGELOG.md](CHANGELOG.md) for
> fork-specific changes (new themes, expanded playback speed, sleep timer, A-B repeat,
> self-healing error recovery, resilient `fetch` with retries, keyboard-shortcut expansion,
> custom accent color, and more).

> [!IMPORTANT]
> **New to Freedify?** check out our **[Visual Deployment Guide](https://biohaphazard.github.io/Freedify/guide.html)** for easy step-by-step setup instructions (Localhost, Railway, & Render).
> **New to Freedify?** Check the [deployment options](#-quick-start-docker) below for
> step-by-step setup (Docker, Localhost, Railway, & Render).

## 🐳 Quick Start (Docker)

Expand Down
67 changes: 62 additions & 5 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ <h3>⌨️ Keyboard Shortcuts</h3>
<div class="shortcut"><kbd>L</kbd><span>Lyrics</span></div>
<div class="shortcut"><kbd>V</kbd><span>Music Video</span></div>
<div class="shortcut"><kbd>Shift + S</kbd><span>Sync to Drive</span></div>
<div class="shortcut"><kbd>[</kbd><span>Slower</span></div>
<div class="shortcut"><kbd>]</kbd><span>Faster</span></div>
<div class="shortcut"><kbd>\</kbd><span>Reset speed to 1.0x</span></div>
<div class="shortcut"><kbd>T</kbd><span>Cycle theme</span></div>
<div class="shortcut"><kbd>Shift + T</kbd><span>Cycle theme (reverse)</span></div>
<div class="shortcut"><kbd>B</kbd><span>Set A-B repeat point</span></div>
<div class="shortcut"><kbd>Z</kbd><span>Clear A-B repeat</span></div>
<div class="shortcut"><kbd>N</kbd><span>Sleep timer +15 min</span></div>
<div class="shortcut"><kbd>/</kbd><span>Focus search</span></div>
<div class="shortcut"><kbd>?</kbd><span>This Help</span></div>
</div>
</div>
Expand Down Expand Up @@ -141,21 +150,71 @@ <h3 class="settings-section-title">Local Files</h3>
<h3 class="settings-section-title">Appearance</h3>
<div id="theme-picker" class="settings-theme-grid">
<div class="theme-option" data-theme="">🌙 Default</div>
<div class="theme-option" data-theme="theme-light">☀️ Light</div>
<div class="theme-option" data-theme="theme-purple">💜 Purple</div>
<div class="theme-option" data-theme="theme-blue">💙 Blue</div>
<div class="theme-option" data-theme="theme-green">💚 Green</div>
<div class="theme-option" data-theme="theme-pink">💕 Pink</div>
<div class="theme-option" data-theme="theme-orange">🧡 Orange</div>
<div class="theme-option" data-theme="theme-red">❤️ Red</div>
<div class="theme-option" data-theme="theme-cyan">🩵 Cyan</div>
<div class="theme-option" data-theme="theme-dracula">🧛 Dracula</div>
<div class="theme-option" data-theme="theme-catppuccin">☕ Catppuccin</div>
<div class="theme-option" data-theme="theme-nightowl">🦉 Night Owl</div>
<div class="theme-option" data-theme="theme-nuclear">☢️ Nuclear</div>
<div class="theme-option" data-theme="theme-nord">❄️ Nord</div>
<div class="theme-option" data-theme="theme-gruvbox">🍂 Gruvbox</div>
<div class="theme-option" data-theme="theme-tokyo">🗼 Tokyo Night</div>
<div class="theme-option" data-theme="theme-rose-pine">🌹 Rosé Pine</div>
<div class="theme-option" data-theme="theme-solarized-dark">🌒 Solarized</div>
<div class="theme-option" data-theme="theme-monokai">🎨 Monokai</div>
<div class="theme-option" data-theme="theme-one-dark">🧊 One Dark</div>
<div class="theme-option" data-theme="theme-synthwave">🌆 Synthwave</div>
<div class="theme-option" data-theme="theme-matrix">💾 Matrix</div>
<div class="theme-option" data-theme="theme-sunset">🌅 Sunset</div>
<div class="theme-option" data-theme="theme-ocean">🌊 Ocean</div>
<div class="theme-option" data-theme="theme-forest">🌲 Forest</div>
<div class="theme-option" data-theme="theme-coffee">☕ Coffee</div>
<div class="theme-option" data-theme="theme-mono">⚫ Mono</div>
<div class="theme-option" data-theme="theme-high-contrast">🔲 High Contrast</div>
</div>
<div class="settings-item settings-inline-row">
<label for="custom-accent-input" style="flex:1;">Custom accent</label>
<input type="color" id="custom-accent-input" title="Custom accent color" aria-label="Custom accent color">
<button id="custom-accent-clear" class="settings-chip" title="Reset to theme default">Clear</button>
</div>
</div>
<!-- Support -->
<!-- Advanced Playback -->
<div class="settings-section">
<h3 class="settings-section-title">Support</h3>
<a href="https://pally.gg/p/freedify" target="_blank" rel="noopener noreferrer" class="settings-item" style="text-decoration: none; color: inherit;">Donate</a>
<h3 class="settings-section-title">Advanced Playback</h3>
<div class="settings-item settings-inline-row" title="Default playback speed (music, podcasts, audiobooks)">
<label for="settings-speed-slider" style="flex:1;">Default Speed: <span id="settings-speed-value">1.0x</span></label>
<input type="range" id="settings-speed-slider" min="0.5" max="3" step="0.05" value="1" style="flex:2;">
</div>
<label class="settings-item settings-inline-row" style="cursor:pointer;">
<span style="flex:1;">Preserve pitch when changing speed</span>
<input type="checkbox" id="settings-preserve-pitch">
</label>
<div class="settings-divider"></div>
<div class="settings-item settings-inline-row" title="Auto-pause playback after a set time">
<label style="flex:1;">Sleep timer</label>
<select id="sleep-timer-select">
<option value="0">Off</option>
<option value="5">5 minutes</option>
<option value="10">10 minutes</option>
<option value="15">15 minutes</option>
<option value="30">30 minutes</option>
<option value="45">45 minutes</option>
<option value="60">1 hour</option>
<option value="90">1.5 hours</option>
<option value="120">2 hours</option>
<option value="eot">End of track</option>
</select>
</div>
<div id="sleep-timer-status" class="settings-meta hidden" aria-live="polite"></div>
<div class="settings-divider"></div>
<button class="settings-item" id="shortcuts-help-btn" title="Keyboard shortcuts">⌨️ Keyboard Shortcuts</button>
<button class="settings-item" id="diagnostics-btn" title="Run self-diagnostics">🩺 Run Diagnostics</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -194,8 +253,6 @@ <h3 class="settings-section-title">Support</h3>
<button class="menu-item type-btn-menu" data-type="rec">For You</button>
<button class="menu-item type-btn-menu" data-type="setlist">Setlists</button>
<button class="menu-item" id="concert-search-menu-btn">Concert Search</button>
<div class="menu-divider"></div>
<a href="https://pally.gg/p/freedify" target="_blank" rel="noopener noreferrer" class="menu-item" style="text-decoration: none; color: inherit; display: block;">Donate</a>
</div>
</section>

Expand Down
Loading