use prototype inheritance for lua screens, rather than functions
this gives us a way to give each screen nice little hooks, like 'onShown' and 'onHidden'. later we can use these hooks to disable bindings for screens that aren't in-use.
This commit is contained in:
+203
-194
@@ -4,6 +4,7 @@ local backstack = require("backstack")
|
||||
local font = require("font")
|
||||
local playback = require("playback")
|
||||
local queue = require("queue")
|
||||
local screen = require("screen")
|
||||
|
||||
local img = {
|
||||
play = "//lua/img/play.png",
|
||||
@@ -18,219 +19,227 @@ local img = {
|
||||
repeat_disabled = "//lua/img/repeat_disabled.png",
|
||||
}
|
||||
|
||||
return function(opts)
|
||||
local screen = {}
|
||||
screen.root = lvgl.Object(nil, {
|
||||
flex = {
|
||||
flex_direction = "column",
|
||||
flex_wrap = "wrap",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.HOR_RES(),
|
||||
h = lvgl.VER_RES(),
|
||||
})
|
||||
screen.root:center()
|
||||
local is_now_playing_shown = false
|
||||
|
||||
screen.status_bar = widgets.StatusBar(screen.root, {
|
||||
back_cb = backstack.pop,
|
||||
transparent_bg = true,
|
||||
})
|
||||
return screen:new {
|
||||
createUi = function(self)
|
||||
self.root = lvgl.Object(nil, {
|
||||
flex = {
|
||||
flex_direction = "column",
|
||||
flex_wrap = "wrap",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.HOR_RES(),
|
||||
h = lvgl.VER_RES(),
|
||||
})
|
||||
self.root:center()
|
||||
|
||||
local info = screen.root:Object {
|
||||
flex = {
|
||||
flex_direction = "column",
|
||||
flex_wrap = "wrap",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
flex_grow = 1,
|
||||
}
|
||||
self.status_bar = widgets.StatusBar(self.root, {
|
||||
back_cb = backstack.pop,
|
||||
transparent_bg = true,
|
||||
})
|
||||
|
||||
local artist = info:Label {
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
text_align = 2,
|
||||
}
|
||||
local info = self.root:Object {
|
||||
flex = {
|
||||
flex_direction = "column",
|
||||
flex_wrap = "wrap",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
flex_grow = 1,
|
||||
}
|
||||
|
||||
local title = info:Label {
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
text = "",
|
||||
text_align = 2,
|
||||
}
|
||||
local artist = info:Label {
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
text_align = 2,
|
||||
}
|
||||
|
||||
local playlist = screen.root:Object {
|
||||
flex = {
|
||||
flex_direction = "row",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
}
|
||||
|
||||
playlist:Object({ w = 3, h = 1 }) -- spacer
|
||||
|
||||
local cur_time = playlist:Label {
|
||||
w = lvgl.SIZE_CONTENT,
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
local title = info:Label {
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
text = "",
|
||||
text_align = 2,
|
||||
}
|
||||
|
||||
playlist:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
local playlist = self.root:Object {
|
||||
flex = {
|
||||
flex_direction = "row",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
}
|
||||
|
||||
local playlist_pos = playlist:Label {
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
playlist:Label {
|
||||
text = "/",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
local playlist_total = playlist:Label {
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
playlist:Object({ w = 3, h = 1 }) -- spacer
|
||||
|
||||
playlist:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
|
||||
local end_time = playlist:Label {
|
||||
w = lvgl.SIZE_CONTENT,
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
align = lvgl.ALIGN.RIGHT_MID,
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
playlist:Object({ w = 3, h = 1 }) -- spacer
|
||||
local cur_time = playlist:Label {
|
||||
w = lvgl.SIZE_CONTENT,
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
|
||||
local scrubber = screen.root:Slider {
|
||||
w = lvgl.PCT(100),
|
||||
h = 5,
|
||||
range = { min = 0, max = 100 },
|
||||
value = 0,
|
||||
}
|
||||
playlist:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
|
||||
scrubber:onevent(lvgl.EVENT.RELEASED, function()
|
||||
playback.position:set(scrubber:value())
|
||||
end)
|
||||
local playlist_pos = playlist:Label {
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
playlist:Label {
|
||||
text = "/",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
local playlist_total = playlist:Label {
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
|
||||
local controls = screen.root:Object {
|
||||
flex = {
|
||||
flex_direction = "row",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
pad_column = 8,
|
||||
pad_all = 2,
|
||||
}
|
||||
playlist:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
|
||||
local end_time = playlist:Label {
|
||||
w = lvgl.SIZE_CONTENT,
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
align = lvgl.ALIGN.RIGHT_MID,
|
||||
text = "",
|
||||
text_font = font.fusion_10,
|
||||
}
|
||||
playlist:Object({ w = 3, h = 1 }) -- spacer
|
||||
|
||||
local scrubber = self.root:Slider {
|
||||
w = lvgl.PCT(100),
|
||||
h = 5,
|
||||
range = { min = 0, max = 100 },
|
||||
value = 0,
|
||||
}
|
||||
|
||||
scrubber:onevent(lvgl.EVENT.RELEASED, function()
|
||||
playback.position:set(scrubber:value())
|
||||
end)
|
||||
|
||||
local controls = self.root:Object {
|
||||
flex = {
|
||||
flex_direction = "row",
|
||||
justify_content = "center",
|
||||
align_items = "center",
|
||||
align_content = "center",
|
||||
},
|
||||
w = lvgl.PCT(100),
|
||||
h = lvgl.SIZE_CONTENT,
|
||||
pad_column = 8,
|
||||
pad_all = 2,
|
||||
}
|
||||
|
||||
|
||||
controls:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
controls:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
|
||||
local repeat_btn = controls:Button {}
|
||||
repeat_btn:onClicked(function()
|
||||
queue.repeat_track:set(not queue.repeat_track:get())
|
||||
end)
|
||||
local repeat_img = repeat_btn:Image { src = img.repeat_enabled }
|
||||
local repeat_btn = controls:Button {}
|
||||
repeat_btn:onClicked(function()
|
||||
queue.repeat_track:set(not queue.repeat_track:get())
|
||||
end)
|
||||
local repeat_img = repeat_btn:Image { src = img.repeat_enabled }
|
||||
|
||||
local prev_btn = controls:Button {}
|
||||
prev_btn:onClicked(queue.previous)
|
||||
local prev_img = prev_btn:Image { src = img.prev_disabled }
|
||||
local prev_btn = controls:Button {}
|
||||
prev_btn:onClicked(queue.previous)
|
||||
local prev_img = prev_btn:Image { src = img.prev_disabled }
|
||||
|
||||
local play_pause_btn = controls:Button {}
|
||||
play_pause_btn:onClicked(function()
|
||||
playback.playing:set(not playback.playing:get())
|
||||
end)
|
||||
play_pause_btn:focus()
|
||||
local play_pause_img = play_pause_btn:Image { src = img.pause }
|
||||
local play_pause_btn = controls:Button {}
|
||||
play_pause_btn:onClicked(function()
|
||||
playback.playing:set(not playback.playing:get())
|
||||
end)
|
||||
play_pause_btn:focus()
|
||||
local play_pause_img = play_pause_btn:Image { src = img.pause }
|
||||
|
||||
local next_btn = controls:Button {}
|
||||
next_btn:onClicked(queue.next)
|
||||
local next_img = next_btn:Image { src = img.next_disabled }
|
||||
local next_btn = controls:Button {}
|
||||
next_btn:onClicked(queue.next)
|
||||
local next_img = next_btn:Image { src = img.next_disabled }
|
||||
|
||||
local shuffle_btn = controls:Button {}
|
||||
shuffle_btn:onClicked(function()
|
||||
queue.random:set(not queue.random:get())
|
||||
end)
|
||||
local shuffle_img = shuffle_btn:Image { src = img.shuffle }
|
||||
local shuffle_btn = controls:Button {}
|
||||
shuffle_btn:onClicked(function()
|
||||
queue.random:set(not queue.random:get())
|
||||
end)
|
||||
local shuffle_img = shuffle_btn:Image { src = img.shuffle }
|
||||
|
||||
controls:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
controls:Object({ flex_grow = 1, h = 1 }) -- spacer
|
||||
|
||||
|
||||
local format_time = function(time)
|
||||
return string.format("%d:%02d", time // 60, time % 60)
|
||||
local format_time = function(time)
|
||||
return string.format("%d:%02d", time // 60, time % 60)
|
||||
end
|
||||
|
||||
self.bindings = {
|
||||
playback.playing:bind(function(playing)
|
||||
if playing then
|
||||
play_pause_img:set_src(img.pause)
|
||||
else
|
||||
play_pause_img:set_src(img.play)
|
||||
end
|
||||
end),
|
||||
playback.position:bind(function(pos)
|
||||
if not pos then return end
|
||||
cur_time:set {
|
||||
text = format_time(pos)
|
||||
}
|
||||
if not scrubber:is_dragged() then
|
||||
scrubber:set { value = pos }
|
||||
end
|
||||
end),
|
||||
playback.track:bind(function(track)
|
||||
if not track then return end
|
||||
end_time:set {
|
||||
text = format_time(track.duration)
|
||||
}
|
||||
title:set { text = track.title }
|
||||
artist:set { text = track.artist }
|
||||
scrubber:set {
|
||||
range = { min = 0, max = track.duration }
|
||||
}
|
||||
end),
|
||||
queue.position:bind(function(pos)
|
||||
if not pos then return end
|
||||
playlist_pos:set { text = tostring(pos) }
|
||||
|
||||
next_img:set_src(
|
||||
pos < queue.size:get() and img.next or img.next_disabled
|
||||
)
|
||||
prev_img:set_src(
|
||||
pos > 1 and img.prev or img.prev_disabled
|
||||
)
|
||||
end),
|
||||
queue.random:bind(function(shuffling)
|
||||
if shuffling then
|
||||
shuffle_img:set_src(img.shuffle)
|
||||
else
|
||||
shuffle_img:set_src(img.shuffle_disabled)
|
||||
end
|
||||
end),
|
||||
queue.repeat_track:bind(function(en)
|
||||
if en then
|
||||
repeat_img:set_src(img.repeat_enabled)
|
||||
else
|
||||
repeat_img:set_src(img.repeat_disabled)
|
||||
end
|
||||
end),
|
||||
queue.size:bind(function(num)
|
||||
if not num then return end
|
||||
playlist_total:set { text = tostring(num) }
|
||||
end),
|
||||
}
|
||||
end,
|
||||
onShown = function() is_now_playing_shown = true end,
|
||||
onHidden = function() is_now_playing_shown = false end,
|
||||
pushIfNotShown = function(self)
|
||||
if not is_now_playing_shown then
|
||||
backstack.push(self:new())
|
||||
end
|
||||
end
|
||||
|
||||
screen.bindings = {
|
||||
playback.playing:bind(function(playing)
|
||||
if playing then
|
||||
play_pause_img:set_src(img.pause)
|
||||
else
|
||||
play_pause_img:set_src(img.play)
|
||||
end
|
||||
end),
|
||||
playback.position:bind(function(pos)
|
||||
if not pos then return end
|
||||
cur_time:set {
|
||||
text = format_time(pos)
|
||||
}
|
||||
if not scrubber:is_dragged() then
|
||||
scrubber:set { value = pos }
|
||||
end
|
||||
end),
|
||||
playback.track:bind(function(track)
|
||||
if not track then return end
|
||||
end_time:set {
|
||||
text = format_time(track.duration)
|
||||
}
|
||||
title:set { text = track.title }
|
||||
artist:set { text = track.artist }
|
||||
scrubber:set {
|
||||
range = { min = 0, max = track.duration }
|
||||
}
|
||||
end),
|
||||
queue.position:bind(function(pos)
|
||||
if not pos then return end
|
||||
playlist_pos:set { text = tostring(pos) }
|
||||
|
||||
next_img:set_src(
|
||||
pos < queue.size:get() and img.next or img.next_disabled
|
||||
)
|
||||
prev_img:set_src(
|
||||
pos > 1 and img.prev or img.prev_disabled
|
||||
)
|
||||
end),
|
||||
queue.random:bind(function(shuffling)
|
||||
if shuffling then
|
||||
shuffle_img:set_src(img.shuffle)
|
||||
else
|
||||
shuffle_img:set_src(img.shuffle_disabled)
|
||||
end
|
||||
end),
|
||||
queue.repeat_track:bind(function(en)
|
||||
if en then
|
||||
repeat_img:set_src(img.repeat_enabled)
|
||||
else
|
||||
repeat_img:set_src(img.repeat_disabled)
|
||||
end
|
||||
end),
|
||||
queue.size:bind(function(num)
|
||||
if not num then return end
|
||||
playlist_total:set { text = tostring(num) }
|
||||
end),
|
||||
}
|
||||
|
||||
return screen
|
||||
end
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user