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:
jacqueline
2024-03-07 10:59:03 +11:00
parent 53c4ea7805
commit ef72b25660
13 changed files with 827 additions and 660 deletions
+105 -111
View File
@@ -6,30 +6,11 @@ local queue = require("queue")
local playing = require("playing")
local theme = require("theme")
local playback = require("playback")
local screen = require("screen")
local browser = {}
function browser.create(opts)
local screen = {}
screen.root = lvgl.Object(nil, {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
justify_content = "flex-start",
align_items = "flex-start",
align_content = "flex-start",
},
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
})
screen.root:center()
screen.status_bar = widgets.StatusBar(screen.root, {
title = opts.title,
})
if opts.breadcrumb then
local header = screen.root:Object {
return screen:new {
createUi = function(self)
self.root = lvgl.Object(nil, {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
@@ -38,100 +19,113 @@ function browser.create(opts)
align_content = "flex-start",
},
w = lvgl.HOR_RES(),
h = lvgl.SIZE_CONTENT,
pad_left = 4,
pad_right = 4,
pad_bottom = 2,
bg_opa = lvgl.OPA(100),
bg_color = "#fafafa",
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF,
}
header:Label {
text = opts.breadcrumb,
text_font = font.fusion_10,
}
local buttons = header:Object({
flex = {
flex_direction = "row",
flex_wrap = "wrap",
justify_content = "flex-end",
align_items = "center",
align_content = "center",
},
w = lvgl.PCT(100),
h = lvgl.SIZE_CONTENT,
pad_column = 4,
h = lvgl.VER_RES(),
})
local original_iterator = opts.iterator:clone()
local enqueue = widgets.IconBtn(buttons, "//lua/img/enqueue.png", "Enqueue")
enqueue:onClicked(function()
queue.add(original_iterator)
playback.playing:set(true)
end)
-- enqueue:add_flag(lvgl.FLAG.HIDDEN)
local play = widgets.IconBtn(buttons, "//lua/img/play_small.png", "Play")
play:onClicked(function()
queue.clear()
queue.add(original_iterator)
playback.playing:set(true)
backstack.push(playing)
end
)
end
self.root:center()
screen.list = lvgl.List(screen.root, {
w = lvgl.PCT(100),
h = lvgl.PCT(100),
flex_grow = 1,
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF,
})
self.status_bar = widgets.StatusBar(self.root, {
title = self.title,
})
local back = screen.list:add_btn(nil, "< Back")
back:onClicked(backstack.pop)
back:add_style(theme.list_item)
if self.breadcrumb then
local header = self.root:Object {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
justify_content = "flex-start",
align_items = "flex-start",
align_content = "flex-start",
},
w = lvgl.HOR_RES(),
h = lvgl.SIZE_CONTENT,
pad_left = 4,
pad_right = 4,
pad_bottom = 2,
bg_opa = lvgl.OPA(100),
bg_color = "#fafafa",
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF,
}
screen.focused_item = 0
screen.last_item = 0
screen.add_item = function(item)
if not item then return end
screen.last_item = screen.last_item + 1
local this_item = screen.last_item
local btn = screen.list:add_btn(nil, tostring(item))
btn:onClicked(function()
local contents = item:contents()
if type(contents) == "userdata" then
backstack.push(function()
return browser.create({
title = opts.title,
iterator = contents,
breadcrumb = tostring(item),
})
end)
else
header:Label {
text = self.breadcrumb,
text_font = font.fusion_10,
}
local buttons = header:Object({
flex = {
flex_direction = "row",
flex_wrap = "wrap",
justify_content = "flex-end",
align_items = "center",
align_content = "center",
},
w = lvgl.PCT(100),
h = lvgl.SIZE_CONTENT,
pad_column = 4,
})
local original_iterator = self.iterator:clone()
local enqueue = widgets.IconBtn(buttons, "//lua/img/enqueue.png", "Enqueue")
enqueue:onClicked(function()
queue.add(original_iterator)
playback.playing:set(true)
end)
-- enqueue:add_flag(lvgl.FLAG.HIDDEN)
local play = widgets.IconBtn(buttons, "//lua/img/play_small.png", "Play")
play:onClicked(function()
queue.clear()
queue.add(contents)
queue.add(original_iterator)
playback.playing:set(true)
backstack.push(playing)
end
end)
btn:onevent(lvgl.EVENT.FOCUSED, function()
screen.focused_item = this_item
if screen.last_item - 5 < this_item then
screen.add_item(opts.iterator())
end
end)
btn:add_style(theme.list_item)
)
end
self.list = lvgl.List(self.root, {
w = lvgl.PCT(100),
h = lvgl.PCT(100),
flex_grow = 1,
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF,
})
local back = self.list:add_btn(nil, "< Back")
back:onClicked(backstack.pop)
back:add_style(theme.list_item)
self.focused_item = 0
self.last_item = 0
self.add_item = function(item)
if not item then return end
self.last_item = self.last_item + 1
local this_item = self.last_item
local btn = self.list:add_btn(nil, tostring(item))
btn:onClicked(function()
local contents = item:contents()
if type(contents) == "userdata" then
backstack.push(require("browser"):new {
title = self.title,
iterator = contents,
breadcrumb = tostring(item),
})
else
queue.clear()
queue.add(contents)
playback.playing:set(true)
backstack.push(playing:new())
end
end)
btn:onevent(lvgl.EVENT.FOCUSED, function()
self.focused_item = this_item
if self.last_item - 5 < this_item then
self.add_item(self.iterator())
end
end)
btn:add_style(theme.list_item)
end
for _ = 1, 8 do
local val = self.iterator()
if not val then break end
self.add_item(val)
end
end
for _ = 1, 8 do
local val = opts.iterator()
if not val then break end
screen.add_item(val)
end
return screen
end
return browser.create
}