Make track fully controlled
This commit is contained in:
parent
d067370071
commit
4b9c81d24c
5 changed files with 67 additions and 88 deletions
|
@ -148,10 +148,9 @@ pub fn update(model: Model, msg) {
|
|||
effect.none(),
|
||||
)
|
||||
actions.SelectPosition(actions.Commit) -> {
|
||||
let pos = current_track_position()
|
||||
skip_to_time(pos)
|
||||
skip_to_time(model.position)
|
||||
|
||||
#(Model(..model, position: pos), effect.none())
|
||||
#(model, effect.none())
|
||||
}
|
||||
actions.SelectPosition(actions.Ephemeral) -> {
|
||||
let pos = current_track_position()
|
||||
|
@ -193,7 +192,6 @@ pub fn update(model: Model, msg) {
|
|||
True -> #(model, effect.none())
|
||||
False -> {
|
||||
let pos = float.truncate(time)
|
||||
set_track_to(pos)
|
||||
|
||||
case
|
||||
position.make_position_state(
|
||||
|
@ -361,9 +359,6 @@ fn skip_to_time(time: Int) -> Nil
|
|||
@external(javascript, "../../../player_ffi.mjs", "currentTrackPosition")
|
||||
fn current_track_position() -> Int
|
||||
|
||||
@external(javascript, "../../../player_ffi.mjs", "setTrackTo")
|
||||
fn set_track_to(pos: Int) -> Nil
|
||||
|
||||
@external(javascript, "../../../player_ffi.mjs", "createAudioContext")
|
||||
fn create_audio_context() -> AudioContext
|
||||
|
||||
|
|
|
@ -2,28 +2,21 @@ import gleam/int
|
|||
import gleam/float
|
||||
import gleam/option
|
||||
import lustre/element.{text}
|
||||
import lustre/element/html.{div, input, p}
|
||||
import lustre/element/html.{div, p}
|
||||
import lustre/attribute
|
||||
import lustre/event
|
||||
import elekf/utils/lustre
|
||||
import elekf/web/components/icon.{Alt, icon}
|
||||
import elekf/web/components/track_length.{track_length}
|
||||
import elekf/web/components/button_group
|
||||
import elekf/web/components/button
|
||||
import elekf/web/components/link
|
||||
import elekf/web/components/thumbnail
|
||||
import elekf/web/components/player/actions.{
|
||||
Commit, EndUserSkip, Ephemeral, NextTrack, Pause, Play, PrevTrack,
|
||||
SelectPosition, StartUserSkip,
|
||||
}
|
||||
import elekf/web/components/player/actions.{NextTrack, Pause, Play, PrevTrack}
|
||||
import elekf/web/components/player/model.{type Model}
|
||||
import elekf/web/components/player/track
|
||||
|
||||
pub fn view(model: Model) {
|
||||
let is_playing = model.state == model.Playing
|
||||
let current_time_padding = case model.track.length > 3600 {
|
||||
True -> track_length.Hours
|
||||
False -> track_length.Auto
|
||||
}
|
||||
|
||||
div(
|
||||
[
|
||||
|
@ -96,33 +89,7 @@ pub fn view(model: Model) {
|
|||
[icon("arrows-angle-contract", Alt("Small player"))],
|
||||
),
|
||||
]),
|
||||
p(
|
||||
[
|
||||
attribute.id("player-time-elapsed"),
|
||||
attribute.class("player-time"),
|
||||
attribute.attribute("aria-label", "Time elapsed"),
|
||||
],
|
||||
[track_length(model.position, current_time_padding)],
|
||||
),
|
||||
p(
|
||||
[
|
||||
attribute.id("player-time-total"),
|
||||
attribute.class("player-time"),
|
||||
attribute.attribute("aria-label", "Total time"),
|
||||
],
|
||||
[track_length(model.track.length, track_length.Auto)],
|
||||
),
|
||||
input([
|
||||
attribute.id("player-track"),
|
||||
attribute.type_("range"),
|
||||
attribute.min("0"),
|
||||
attribute.max(int.to_string(model.track.length)),
|
||||
attribute.attribute("aria-label", "Track position"),
|
||||
event.on("change", fn(_) { Ok(SelectPosition(Commit)) }),
|
||||
event.on_mouse_down(StartUserSkip),
|
||||
event.on_mouse_up(EndUserSkip),
|
||||
event.on_input(fn(_) { SelectPosition(Ephemeral) }),
|
||||
]),
|
||||
..track.view(model)
|
||||
]),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -1,28 +1,20 @@
|
|||
import gleam/int
|
||||
import gleam/option
|
||||
import lustre/element.{text}
|
||||
import lustre/element/html.{div, input, p}
|
||||
import lustre/element/html.{div, p}
|
||||
import lustre/attribute
|
||||
import lustre/event
|
||||
import elekf/web/components/icon.{Alt, icon}
|
||||
import elekf/web/components/track_length.{track_length}
|
||||
import elekf/web/components/button_group
|
||||
import elekf/web/components/button
|
||||
import elekf/web/components/link
|
||||
import elekf/web/components/thumbnail
|
||||
import elekf/web/components/player/actions.{
|
||||
Commit, EndUserSkip, Ephemeral, NextTrack, Pause, Play, PrevTrack,
|
||||
SelectPosition, StartUserSkip,
|
||||
}
|
||||
import elekf/web/components/player/actions.{NextTrack, Pause, Play, PrevTrack}
|
||||
import elekf/web/components/player/model.{type Model}
|
||||
import elekf/web/components/player/track
|
||||
import elekf/web/router
|
||||
|
||||
pub fn view(model: Model) {
|
||||
let is_playing = model.state == model.Playing
|
||||
let current_time_padding = case model.track.length > 3600 {
|
||||
True -> track_length.Hours
|
||||
False -> track_length.Auto
|
||||
}
|
||||
|
||||
div(
|
||||
[
|
||||
|
@ -78,33 +70,7 @@ pub fn view(model: Model) {
|
|||
[icon("arrows-angle-expand", Alt("Full screen player"))],
|
||||
),
|
||||
]),
|
||||
p(
|
||||
[
|
||||
attribute.id("player-time-elapsed"),
|
||||
attribute.class("player-time"),
|
||||
attribute.attribute("aria-label", "Time elapsed"),
|
||||
],
|
||||
[track_length(model.position, current_time_padding)],
|
||||
),
|
||||
p(
|
||||
[
|
||||
attribute.id("player-time-total"),
|
||||
attribute.class("player-time"),
|
||||
attribute.attribute("aria-label", "Total time"),
|
||||
],
|
||||
[track_length(model.track.length, track_length.Auto)],
|
||||
),
|
||||
input([
|
||||
attribute.id("player-track"),
|
||||
attribute.type_("range"),
|
||||
attribute.min("0"),
|
||||
attribute.max(int.to_string(model.track.length)),
|
||||
attribute.attribute("aria-label", "Track position"),
|
||||
event.on("change", fn(_) { Ok(SelectPosition(Commit)) }),
|
||||
event.on_mouse_down(StartUserSkip),
|
||||
event.on_mouse_up(EndUserSkip),
|
||||
event.on_input(fn(_) { SelectPosition(Ephemeral) }),
|
||||
]),
|
||||
..track.view(model)
|
||||
]),
|
||||
],
|
||||
)
|
||||
|
|
55
src/elekf/web/components/player/track.gleam
Normal file
55
src/elekf/web/components/player/track.gleam
Normal file
|
@ -0,0 +1,55 @@
|
|||
//// A track for visualising the current song's progress and skipping it back
|
||||
//// and forth, and additional timestamps.
|
||||
|
||||
import gleam/int
|
||||
import gleam/dynamic
|
||||
import lustre/element/html.{input, p}
|
||||
import lustre/attribute
|
||||
import lustre/event
|
||||
import elekf/web/components/track_length.{track_length}
|
||||
import elekf/web/components/player/model
|
||||
import elekf/web/components/player/actions.{
|
||||
Commit, EndUserSkip, Ephemeral, SelectPosition, StartUserSkip,
|
||||
}
|
||||
|
||||
pub fn view(model: model.Model) {
|
||||
let current_time_padding = case model.track.length > 3600 {
|
||||
True -> track_length.Hours
|
||||
False -> track_length.Auto
|
||||
}
|
||||
|
||||
let track_pos = dynamic.from(int.to_string(model.position))
|
||||
|
||||
[
|
||||
p(
|
||||
[
|
||||
attribute.id("player-time-elapsed"),
|
||||
attribute.class("player-time"),
|
||||
attribute.attribute("aria-label", "Time elapsed"),
|
||||
],
|
||||
[track_length(model.position, current_time_padding)],
|
||||
),
|
||||
p(
|
||||
[
|
||||
attribute.id("player-time-total"),
|
||||
attribute.class("player-time"),
|
||||
attribute.attribute("aria-label", "Total time"),
|
||||
],
|
||||
[track_length(model.track.length, track_length.Auto)],
|
||||
),
|
||||
input([
|
||||
attribute.id("player-track"),
|
||||
attribute.type_("range"),
|
||||
attribute.min("0"),
|
||||
attribute.max(int.to_string(model.track.length)),
|
||||
attribute.value(track_pos),
|
||||
attribute.attribute("aria-label", "Track position"),
|
||||
event.on("change", fn(_) { Ok(SelectPosition(Commit)) }),
|
||||
event.on_mouse_down(StartUserSkip),
|
||||
event.on_mouse_up(EndUserSkip),
|
||||
event.on("touchstart", fn(_) { Ok(StartUserSkip) }),
|
||||
event.on("touchend", fn(_) { Ok(EndUserSkip) }),
|
||||
event.on_input(fn(_) { SelectPosition(Ephemeral) }),
|
||||
]),
|
||||
]
|
||||
}
|
|
@ -41,11 +41,6 @@ export function currentTrackPosition() {
|
|||
return track.valueAsNumber;
|
||||
}
|
||||
|
||||
export function setTrackTo(pos) {
|
||||
getTrack();
|
||||
track.value = String(pos);
|
||||
}
|
||||
|
||||
export function createAudioContext() {
|
||||
return new globalThis.AudioContext();
|
||||
}
|
||||
|
@ -75,7 +70,8 @@ function getPlayer() {
|
|||
}
|
||||
|
||||
function getTrack() {
|
||||
if (track === undefined) {
|
||||
// Track element might not be fetched yet, or it might have been removed from the DOM
|
||||
if (track === undefined || !track.isConnected) {
|
||||
track = document.getElementById(track_id);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue