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
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ gem "bcrypt", "~> 3.1.7"
group :development do
eval_gemfile "gemfiles/rubocop.gemfile"
end

gem "turbo_power", "~> 0.3.1"
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ GEM
turbo_boost-streams (0.0.8)
rails (>= 6.1)
turbo-rails (>= 1.1)
turbo_power (0.3.1)
turbo-rails (~> 1.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.4.2)
Expand Down Expand Up @@ -362,6 +364,7 @@ DEPENDENCIES
tailwindcss-rails
turbo-rails
turbo_boost-commands
turbo_power (~> 0.3.1)
web-console

RUBY VERSION
Expand Down
13 changes: 13 additions & 0 deletions app/controllers/live_stations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ def play
render turbo_stream: turbo_stream.update("player", partial: "player/player", locals: {station:, track: station.current_track})
end

def pause
station = current_user.live_station
station.update!(live: false)
Turbo::StreamsChannel.broadcast_stream_to station, content: turbo_stream.set_attribute(".player", "data-player-state-value", "paused")
end


def resume
station = current_user.live_station
station.update!(live: true)
Turbo::StreamsChannel.broadcast_stream_to station, content: turbo_stream.set_attribute(".player", "data-player-state-value", "playing")
end

private

def station_params
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import "controllers";
import { createCable } from "@anycable/web";
import { start } from "@anycable/turbo-stream";

import TurboPower from 'turbo_power'
TurboPower.initialize(Turbo.StreamActions)

const logLevel = document.documentElement.classList.contains("debug")
? "debug"
: "error";
Expand Down
30 changes: 28 additions & 2 deletions app/javascript/controllers/player_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function secondsToDuration(num) {
export default class extends Controller {
static targets = ["progress", "time"];
static outlets = ["track"];
static values = { duration: Number, track: String, nextTrackUrl: String };
static values = { duration: Number, track: String, nextTrackUrl: String, state: String, pauseUrl: String , resumeUrl: String };
static classes = ["playing"];

initialize() {
Expand All @@ -36,6 +36,18 @@ export default class extends Controller {
}
}

stateValueChanged() {
if (this.pauseUrlValue) {
return;
}

if (this.playing && this.stateValue === "paused") {
this.pause(false);
} else if (!this.playing && this.stateValue === "playing") {
this.play(false);
}
}

trackOutletConnected(outlet, el) {
outlet.togglePlayingIfMatch(this.trackValue);
}
Expand All @@ -46,7 +58,7 @@ export default class extends Controller {
this.setupAudioListeners();
}

if (this.playing) {
if (this.playing || this.stateValue === "playing") {
this.play();
}
}
Expand All @@ -61,12 +73,16 @@ export default class extends Controller {
this.element.classList.add(this.playingClass);
this.audio.play();
this.playing = true;

if (this.resumeUrlValue) this.broadcastStateChange(this.resumeUrlValue);
}

pause() {
this.element.classList.remove(this.playingClass);
this.audio.pause();
this.playing = false;

if (this.pauseUrlValue) this.broadcastStateChange(this.pauseUrlValue);
}

seek(e) {
Expand Down Expand Up @@ -99,6 +115,16 @@ export default class extends Controller {
}
}

async broadcastStateChange(url) {
const request = new FetchRequest("POST", url, {
responseKind: "turbo-stream",
});
const response = await request.perform();
if (!response.ok) {
console.error("Failed to broadcast pause/resume", response.status);
}
}

updateProgress(currentTime) {
const percent = (currentTime * 100) / this.durationValue;

Expand Down
5 changes: 4 additions & 1 deletion app/views/player/_player.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
data-player-duration-value="<%= track&.duration %>"
data-player-track-value="<%= track&.id %>"
data-player-playing-class="player-playing"
data-player-state-value="playing"
data-player-next-track-url-value="<%= live ? play_next_live_station_path : (!station && play_next_track_path(track))%>"
data-player-pause-url-value="<%= pause_live_station_path if live %>"
data-player-resume-url-value="<%= resume_live_station_path if live %>"
data-player-track-outlet=".track"
>
<% if track %>
<div class="player--timeline" data-action="<%= "click->player#seek" if live || !station %>">
<div class="player--timeline-progress" style="width:0%;" data-player-target="progress"></div>
</div>
<% end %>
<% unless station %>
<% if !station || live %>
<div class="player--controls">
<span class="player-btn" data-action="click->player#play">
<%= render "icons/play" %>
Expand Down
1 change: 1 addition & 0 deletions config/importmap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@
pin "nanoevents", to: "https://ga.jspm.io/npm:nanoevents@7.0.1/index.js"
pin "@anycable/web", to: "https://ga.jspm.io/npm:@anycable/web@0.7.0/index.js"
pin "@turbo-boost/commands", to: "https://ga.jspm.io/npm:@turbo-boost/commands@0.0.11/app/assets/builds/@turbo-boost/commands.js"
pin "turbo_power", to: "https://ga.jspm.io/npm:turbo_power@0.3.1/dist/turbo_power.js"
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
patch :start, on: :member
patch :stop, on: :member
post :play_next, on: :member
post :pause, on: :member
post :resume, on: :member

resources :tracks, only: [:create, :destroy], module: :live_station do
post :play, on: :member
Expand Down