summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-07-03 10:43:54 +1000
committerjacqueline <me@jacqueline.id.au>2024-07-03 10:43:54 +1000
commit88ac96242f0d36e53876ece9f90baf776616f0bc (patch)
tree4a937dd3f5f0178e91d5b797a276187a0fa7b64b /lua
parentcbcf1bea617a8f57fe80264e4b96da9274d133f0 (diff)
downloadtangara-fw-88ac96242f0d36e53876ece9f90baf776616f0bc.tar.gz
Load fonts asynchronously on a bg task
This saves a second or two from bootup; AFAICT this *mostly* reclaims the dynamic fonts boot time regression.
Diffstat (limited to 'lua')
-rw-r--r--lua/font.lua36
-rw-r--r--lua/main.lua115
2 files changed, 99 insertions, 52 deletions
diff --git a/lua/font.lua b/lua/font.lua
index 7afa1e01..c76602ec 100644
--- a/lua/font.lua
+++ b/lua/font.lua
@@ -1,6 +1,36 @@
local lvgl = require("lvgl")
-return {
- fusion_12 = lvgl.Font("//lua/fonts/fusion12"),
- fusion_10 = lvgl.Font("//lua/fonts/fusion10"),
+local fonts = {}
+local fonts_priv = {
+ has_invoked_cb = false,
+ cb = nil,
}
+
+function fonts_priv.has_loaded_all()
+ return fonts.fusion_12 and fonts.fusion_10
+end
+
+function fonts_priv.invoke_cb()
+ if fonts_priv.has_invoked_cb or not fonts_priv.cb then return end
+ if not fonts_priv.has_loaded_all() then return end
+ fonts_priv.has_invoked_cb = true
+ fonts_priv.cb()
+end
+
+lvgl.Font("//lua/fonts/fusion12", function(font)
+ fonts.fusion_12 = font
+ fonts_priv.invoke_cb()
+end)
+
+lvgl.Font("//lua/fonts/fusion10", function(font)
+ fonts.fusion_10 = font
+ fonts_priv.invoke_cb()
+end)
+
+function fonts.on_loaded(cb)
+ fonts_priv.cb = cb
+ fonts_priv.has_invoked_cb = false
+ fonts_priv.invoke_cb()
+end
+
+return fonts
diff --git a/lua/main.lua b/lua/main.lua
index 1540004d..4cd754b6 100644
--- a/lua/main.lua
+++ b/lua/main.lua
@@ -1,4 +1,10 @@
+-- Load fonts first, since they're parsed asynchronously and we can do much of
+-- the other UI setup in parallel.
local font = require("font")
+
+-- require() everything else needed for the main menu + global bindings. Do
+-- this now instead of in init_ui because loading and parsing the scripts can
+-- take a while.
local vol = require("volume")
local theme = require("theme")
local controls = require("controls")
@@ -7,55 +13,66 @@ local sd_card = require("sd_card")
local backstack = require("backstack")
local main_menu = require("main_menu")
-local theme_dark = require("theme_dark")
-theme.set(theme_dark)
+local function init_ui()
+ -- Load the theme within init_ui because the theme needs fonts to be ready.
+ local theme_dark = require("theme_dark")
+ theme.set(theme_dark)
-local lock_time = time.ticks()
+ local lock_time = time.ticks()
--- Set up property bindings that are used across every screen.
-GLOBAL_BINDINGS = {
- -- Show an alert with the current volume whenever the volume changes
- vol.current_pct:bind(function(pct)
- require("alerts").show(function()
- local container = lvgl.Object(nil, {
- w = lvgl.PCT(80),
- h = lvgl.SIZE_CONTENT,
- flex = {
- flex_direction = "column",
- justify_content = "center",
- align_items = "center",
- align_content = "center",
- },
- radius = 8,
- pad_all = 2,
- })
- theme.set_style(container, "pop_up")
- container:Label {
- text = string.format("Volume %i%%", pct),
- text_font = font.fusion_10
- }
- container:Bar {
- w = lvgl.PCT(100),
- h = 8,
- range = { min = 0, max = 100 },
- value = pct,
- }
- container:center()
- end)
- end),
- -- When the device has been locked for a while, default to showing the now
- -- playing screen after unlocking.
- controls.lock_switch:bind(function(locked)
- if locked then
- lock_time = time.ticks()
- elseif time.ticks() - lock_time > 8000 then
- local queue = require("queue")
- if queue.size:get() > 0 then
- require("playing"):pushIfNotShown()
+ -- Set up property bindings that are used across every screen.
+ GLOBAL_BINDINGS = {
+ -- Show an alert with the current volume whenever the volume changes
+ vol.current_pct:bind(function(pct)
+ require("alerts").show(function()
+ local container = lvgl.Object(nil, {
+ w = lvgl.PCT(80),
+ h = lvgl.SIZE_CONTENT,
+ flex = {
+ flex_direction = "column",
+ justify_content = "center",
+ align_items = "center",
+ align_content = "center",
+ },
+ radius = 8,
+ pad_all = 2,
+ })
+ theme.set_style(container, "pop_up")
+ container:Label {
+ text = string.format("Volume %i%%", pct),
+ text_font = font.fusion_10
+ }
+ container:Bar {
+ w = lvgl.PCT(100),
+ h = 8,
+ range = { min = 0, max = 100 },
+ value = pct,
+ }
+ container:center()
+ end)
+ end),
+ -- When the device has been locked for a while, default to showing the now
+ -- playing screen after unlocking.
+ controls.lock_switch:bind(function(locked)
+ if locked then
+ lock_time = time.ticks()
+ elseif time.ticks() - lock_time > 8000 then
+ local queue = require("queue")
+ if queue.size:get() > 0 then
+ require("playing"):pushIfNotShown()
+ end
end
- end
- end),
- sd_card.mounted:bind(function(mounted)
- backstack.reset(main_menu:new())
- end),
-}
+ end),
+ sd_card.mounted:bind(function(mounted)
+ backstack.reset(main_menu:new())
+ end),
+ }
+end
+
+-- Wait for fonts to finish, then show the main menu.
+-- We could show an intermediary Lua-controlled splash/loading UI whilst we
+-- wait, but in practice loading the fonts takes only a few hundred ms longer
+-- than all the other UI init.
+font.on_loaded(function()
+ init_ui()
+end)