Skip to content

Commit

Permalink
Merge pull request #117 from sgobotta/feature/add-voume-controls
Browse files Browse the repository at this point in the history
feature/add voume controls
  • Loading branch information
sgobotta authored Jan 15, 2024
2 parents eecd030 + 5134cda commit 81b4173
Show file tree
Hide file tree
Showing 35 changed files with 1,725 additions and 179 deletions.
2 changes: 1 addition & 1 deletion assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ if (

const sorter = new Sortable(this.el, {
animation: 400,
delay: 20,
delay: 300,
dragClass: "drag-item",
forceFallback: true,
ghostClass: "drag-ghost",
Expand Down
75 changes: 75 additions & 0 deletions assets/js/youtube/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ const udpateTimeDisplays = (
export default {
backdrop_id: null,
endTimeTrackerId: null,
handleCallbackEvent: async (callbackEvent, args = {}) => {
if (callbackEvent) {
await this.pushEventTo(this.el, callbackEvent, args)
}
},
mounted() {
/**
* on_container_mounted
Expand Down Expand Up @@ -112,6 +117,11 @@ export default {
)
}, 1000)
hookContext.el.dataset['trackTimeInterval'] = trackTimeInterval

const backdrop = document.getElementById(this.backdropId)
backdrop.classList.add('opacity-0')
backdrop.classList.remove('opacity-50')

break
case YT.PlayerState.PAUSED:
console.debug("[Player State :: PAUSED")
Expand Down Expand Up @@ -270,6 +280,71 @@ export default {

scrollToElement(`${player.media_id}-item`)
})

/**
* change_volume
*
* Received when the player should change the volume level
*/
this.handleEvent('change_volume', async ({
volume_level: volumeLevel,
callback_event: callbackEvent = null
}) => {
console.debug('[Player :: change_volume', volumeLevel)
this.player.unMute()
this.player.setVolume(volumeLevel)

await this.handleCallbackEvent(callbackEvent)
})

/**
* mute
*
* Received when the player should mute
*/
this.handleEvent('mute', async ({callback_event: callbackEvent = null}) => {
console.debug('[Player :: mute')
this.player.mute()

await this.handleCallbackEvent(callbackEvent)
})

/**
* unmute
*
* Received when the player should unmute
*/
this.handleEvent('unmute', async ({
callback_event: callbackEvent = null
}) => {
console.debug('[Player :: unmute')
this.player.unMute()

await this.handleCallbackEvent(callbackEvent)
})

/**
* fullscreen
*
* Switches to fullscreen mode
*/
this.handleEvent('fullscreen', () => {
console.debug('[Player :: fullscreen')
const videoIframe = this.player.getIframe()

console.log("iframe", videoIframe)

const requestFullScreen =
videoIframe.requestFullScreen
|| videoIframe.mozRequestFullScreen
|| videoIframe.webkitRequestFullScreen

console.log(requestFullScreen)

if (requestFullScreen) {
requestFullScreen.bind(videoIframe)();
}
})
},
player: null,
playerContainerId: null,
Expand Down
2 changes: 1 addition & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ config :livedj, Livedj.Repo,
config :livedj, LivedjWeb.Endpoint,
# Binding to loopback ipv4 address prevents access from other machines.
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
http: [ip: {127, 0, 0, 1}, port: 4000],
http: [ip: {0, 0, 0, 0}, port: 4000],
check_origin: false,
code_reloader: true,
debug_errors: true,
Expand Down
6 changes: 4 additions & 2 deletions lib/livedj/sessions/channels.ex
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,16 @@ defmodule Livedj.Sessions.Channels do
"""
@spec broadcast_player_play!(binary(), Livedj.Sessions.Player.t()) :: :ok
def broadcast_player_play!(room_id, %Livedj.Sessions.Player{} = player),
do: broadcast!(player_topic(room_id), {player_play_event(), player})
do:
broadcast!(player_topic(room_id), {player_play_event(), room_id, player})

@doc """
Broadcasts a #{@player_pause} message to the player topic.
"""
@spec broadcast_player_pause!(binary(), Livedj.Sessions.Player.t()) :: :ok
def broadcast_player_pause!(room_id, %Livedj.Sessions.Player{} = player),
do: broadcast!(player_topic(room_id), {player_pause_event(), player})
do:
broadcast!(player_topic(room_id), {player_pause_event(), room_id, player})

# ----------------------------------------------------------------------------
# Playlist brodcasting
Expand Down
9 changes: 5 additions & 4 deletions lib/livedj_web/components/custom_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ defmodule LivedjWeb.CustomComponents do
"""
def room_grid(assigns) do
assigns =
with %{modules: %Phoenix.LiveView.LiveStream{}} <- assigns do
with %{modules: _modules} <- assigns do
assign(
assigns,
module_id: assigns.module_id || fn {id, _item} -> id end
module_id: assigns.module_id || fn %{id: id} -> id end
)
end

Expand All @@ -118,8 +118,9 @@ defmodule LivedjWeb.CustomComponents do
class="
group
h-52 w-40 rounded-lg
bg-zinc-50 hover:bg-zinc-200 border-[1px] border-zinc-200 dark:border-0
dark:bg-zinc-800 dark:hover:bg-zinc-700
transition duration-300
bg-zinc-50 hover:brightness-90 border-[1px] border-zinc-200 dark:border-0
dark:bg-zinc-800 dark:hover:bg-zinc-800 dark:hover:brightness-110
"
>
<div
Expand Down
2 changes: 1 addition & 1 deletion lib/livedj_web/components/layouts/app.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<a href="/">
<.livedj_logo theme={@theme} />
</a>
<div>
<div class="cursor-default">
<.version_pill version={Application.spec(:livedj, :vsn)} />
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions lib/livedj_web/components/layouts/session.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<.toggle_theme_button theme={@theme} />
</div>
</div>
<ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
<%!-- <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
<%= if @current_user do %>
<li class="text-[0.8125rem] leading-6">
<.text><%= @current_user.email %></.text>
Expand Down Expand Up @@ -51,7 +51,7 @@
</.link>
</li>
<% end %>
</ul>
</ul> --%>
</header>

<main class="sm:py-10 lg:px-8">
Expand Down
1 change: 1 addition & 0 deletions lib/livedj_web/components/list_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ defmodule LivedjWeb.ListComponent do
<button
type="button"
class="
cursor-default
transition-all duration-300
w-6 h-6 rounded mr-1 flex-none hover:bg-gray-300 hover:dark:bg-gray-700
text-zinc-900 dark:text-zinc-100 hover:text-red-500 hover:dark:text-red-500
Expand Down
45 changes: 45 additions & 0 deletions lib/livedj_web/components/player_preview.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule LivedjWeb.PlayerPreview do
@moduledoc false

use LivedjWeb, :live_component

alias Livedj.Sessions.Player

def render(assigns) do
~H"""
<div class="h-40 w-40 py-2 px-2">
<%= if player?(@player) && @player.media_thumbnail_url != "" do %>
<img
class="h-full w-full rounded-md ring-0 ring-white"
src={get_player_thumbnail(@player)}
/>
<% else %>
<div class={"
h-full w-full rounded-md ring-0 ring-white bg-gray-200 dark:bg-gray-800
flex flex-wrap justify-center content-center
#{if paused?(@player), do: "animate-pulse"}
"}>
<.icon name="hero-musical-note" class="h-12 w-12 text-zinc-500" />
</div>
<% end %>
</div>
"""
end

def update(assigns, socket) do
{:ok,
socket
|> assign(assigns)}
end

defp player?(nil), do: false
defp player?(%Player{}), do: true

defp paused?(%Player{state: :paused}), do: true
defp paused?(_player), do: false

defp get_player_thumbnail(%Livedj.Sessions.Player{
media_thumbnail_url: media_thumbnail_url
}),
do: media_thumbnail_url
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule LivedjWeb.Components.PlayerControls.FullscreenControlComponent do
@moduledoc false

use LivedjWeb, :live_component

@impl true
def render(assigns) do
~H"""
<div phx-click="on_click" phx-target={@myself}>
<%= PhoenixInlineSvg.Helpers.svg_image(
LivedjWeb.Endpoint,
"fullscreen",
"icons/misc",
class: "
h-4 w-4 stroke-2 cursor-pointer
fill-zinc-700 hover:fill-zinc-900 focus:fill-zinc-700 active:fill-zinc-700
dark:fill-zinc-300 dark:hover:fill-zinc-50 dark:focus:fill-zinc-300 dark:active:fill-zinc-300
scale-100 hover:scale-[1.1] focus:scale-100 active:scale-100
"
) %>
</div>
"""
end

@impl true
def update(assigns, socket) do
{:ok, assign(socket, assigns)}
end

@impl true
def handle_event("on_click", _params, socket) do
{:noreply, push_event(socket, "fullscreen", %{})}
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
defmodule LivedjWeb.Components.PlayerControls.VolumeControlComponent do
@moduledoc false

use LivedjWeb, :live_component

@impl true
def render(assigns) do
~H"""
<div class="
hidden sm:inline-flex w-24
fill-zinc-700 hover:fill-zinc-900 focus:fill-zinc-700 active:fill-zinc-700
dark:fill-zinc-300 dark:hover:fill-zinc-50 dark:focus:fill-zinc-300 dark:active:fill-zinc-300
">
<div class="m-2" phx-click="on_volume_click" phx-target={@myself}>
<%= PhoenixInlineSvg.Helpers.svg_image(
LivedjWeb.Endpoint,
get_volume_icon(@muted?, @level),
"icons/volume",
class: "
h-5 w-5
"
) %>
</div>
<div class="self-center">
<.form
:let={f}
for={@player}
id="volume-controls-slider"
class=""
phx-target={@myself}
phx-change="on_volume_change"
>
<.input
field={f[:volume]}
class="seek-bar w-full !m-0 shadow-none !bg-transparent"
id="volume-slider"
value={if @muted?, do: 0, else: @level}
type="range"
min="0"
max="100"
step="1"
phx-debounce={500}
phx-value-key="volume"
/>
</.form>
</div>
</div>
"""
end

@impl true
def mount(socket) do
{:ok,
socket
|> assign(player: to_form(%{}))}
end

@impl true
def update(assigns, socket) do
{:ok,
socket
|> assign(assigns)}
end

@impl true
def handle_event(
"on_volume_click",
_params,
%{assigns: %{muted?: muted?}} = socket
) do
{:noreply,
socket
|> assign(muted?: !muted?)
|> push_event(if(muted?, do: "unmute", else: "mute"), %{})}
end

@impl true
def handle_event("on_volume_change", %{"volume" => volume}, socket) do
{:noreply,
socket
|> assign(
level: String.to_integer(volume),
muted?: false
)
|> push_event("change_volume", %{volume_level: volume})}
end

defp get_volume_icon(true, _volume_level) do
"speaker-0"
end

defp get_volume_icon(_muted?, volume_level) do
get_volume_icon_by_volume_level(volume_level)
end

defp get_volume_icon_by_volume_level(0), do: "speaker-0"

defp get_volume_icon_by_volume_level(volume) when volume <= 10,
do: "speaker-1"

defp get_volume_icon_by_volume_level(volume) when volume <= 30,
do: "speaker-2"

defp get_volume_icon_by_volume_level(volume) when volume <= 70,
do: "speaker-3"

defp get_volume_icon_by_volume_level(_volume), do: "speaker-4"
end
Loading

0 comments on commit 81b4173

Please sign in to comment.