Merge pull request 'Playlist Browser' (#228) from slord/tangara-fw:playlist-browser into main

Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/228
custom
ailurux 2 months ago
commit 407c2f36f5
  1. 5
      lua/file_browser.lua
  2. 25
      lua/main_menu.lua
  3. 94
      lua/playlist_browser.lua
  4. 35
      lua/playlist_iterator.lua
  5. 2
      lua/widgets.lua

@ -8,11 +8,11 @@ local backstack = require("backstack")
local font = require("font")
local queue = require("queue")
local playing = require("playing")
local styles = require("styles")
local playback = require("playback")
local theme = require("theme")
local screen = require("screen")
local filesystem = require("filesystem")
local playlist_iterator = require("playlist_iterator")
return screen:new {
create_ui = function(self)
@ -70,8 +70,7 @@ return screen:new {
breadcrumb = item:filepath()
})
elseif
item:filepath():match("%.playlist$") or
item:filepath():match("%.m3u8?$") then
playlist_iterator:is_playlist(item) then
queue.open_playlist(item:filepath())
playback.playing:set(true)
backstack.push(playing:new())

@ -11,7 +11,6 @@ local browser = require("browser")
local playing = require("playing")
local styles = require("styles")
local filesystem = require("filesystem")
local screen = require("screen")
local font = require("font")
local theme = require("theme")
local img = require("images")
@ -129,6 +128,15 @@ return widgets.MenuScreen:new {
})
end
local playlist_btn = indexes_list:add_btn(nil, "Playlists")
playlist_btn:onClicked(function()
backstack.push(require("playlist_browser"):new {
title = "Playlists",
iterator = filesystem.iterator("/Playlists")
})
end)
playlist_btn:add_style(styles.list_item)
local function show_no_indexes(msg)
indexes_list:add_flag(lvgl.FLAG.HIDDEN)
no_indexes_container:clear_flag(lvgl.FLAG.HIDDEN)
@ -144,6 +152,14 @@ return widgets.MenuScreen:new {
end
end
local function hide_playlist_listing()
playlist_btn:add_flag(lvgl.FLAG.HIDDEN)
end
local function show_playlist_listing()
playlist_btn:clear_flag(lvgl.FLAG.HIDDEN)
end
local function update_visible_indexes()
local has_valid_index = false
for _, idx in ipairs(indexes) do
@ -157,6 +173,13 @@ return widgets.MenuScreen:new {
end
if has_valid_index then
hide_no_indexes()
-- If we have valid indexes, then also check for playlists
if filesystem.iterator("/Playlists/"):next() == nil then
hide_playlist_listing()
else
show_playlist_listing()
end
else
if require("database").updating:get() then
show_no_indexes("The database is updating for the first time. Please wait.")

@ -0,0 +1,94 @@
-- SPDX-FileCopyrightText: 2025 Sam Lord <code@samlord.co.uk>
--
-- SPDX-License-Identifier: GPL-3.0-only
local lvgl = require("lvgl")
local widgets = require("widgets")
local backstack = require("backstack")
local playing = require("playing")
local filesystem = require("filesystem")
local screen = require("screen")
local font = require("font")
local theme = require("theme")
local playback = require("playback")
local queue = require("queue")
local playlist_iterator = require("playlist_iterator")
local img = require("images")
return screen:new {
create_ui = function(self)
self.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()
})
self.root:center()
self.status_bar = widgets.StatusBar(self, {
back_cb = backstack.pop,
title = self.title
})
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,
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF
}
theme.set_subject(header, "header")
if self.breadcrumb then
header:Label {
text = self.breadcrumb,
text_font = font.fusion_10
}
end
local get_icon_func = function(item)
if item:is_directory() then
return img.files
else
return img.enqueue
end
end
widgets.InfiniteList(self.root, playlist_iterator:create(self.iterator), {
focus_first_item = true,
get_icon = get_icon_func,
callback = function(item)
return function()
if item:is_directory() then
backstack.push(
require("playlist_browser"):new {
title = self.title,
iterator = filesystem.iterator(item:filepath()),
breadcrumb = item:filepath()
})
elseif
playlist_iterator:is_playlist(item) then
-- TODO: playlist viewer
queue.open_playlist(item:filepath())
playback.playing:set(true)
backstack.push(playing:new())
end
end
end
})
end
}

@ -0,0 +1,35 @@
local PlaylistIterator = {}
function PlaylistIterator:is_playlist(item)
return item:filepath():match("%.playlist$")
or item:filepath():match("%.m3u8?$")
end
function PlaylistIterator:create(fs_iterator)
local iterator = fs_iterator:clone()
local obj = {};
local find_matching = function(iterate_fn)
local next = iterate_fn(iterator);
while next and (not PlaylistIterator:is_playlist(next) and not next:is_directory()) do
next = iterate_fn();
end
return next;
end
function obj:clone()
return PlaylistIterator:create(iterator)
end
function obj:next()
return find_matching(iterator.next)
end
function obj:prev()
return find_matching(iterator.prev)
end
return obj
end
return PlaylistIterator

@ -361,7 +361,7 @@ function widgets.InfiniteList(parent, iterator, opts)
end
for idx = 0, 8 do
local val = fwd_iterator()
local val = fwd_iterator:next()
if not val then
break
end

Loading…
Cancel
Save