Make track fully controlled

This commit is contained in:
Mikko Ahlroth 2024-03-01 12:24:40 +02:00
parent d067370071
commit 4b9c81d24c
5 changed files with 67 additions and 88 deletions

View file

@ -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

View file

@ -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)
]),
],
)

View file

@ -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)
]),
],
)

View 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) }),
]),
]
}

View file

@ -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);
}
}