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/228custom
commit
407c2f36f5
@ -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 |
Loading…
Reference in new issue