summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--osd.lua2
-rw-r--r--rt.lua72
-rw-r--r--state.lua57
3 files changed, 83 insertions, 48 deletions
diff --git a/osd.lua b/osd.lua
index 9ec9dce..cf1b1d8 100644
--- a/osd.lua
+++ b/osd.lua
@@ -175,7 +175,7 @@ function mt:menu_title(menu)
str = str:gsub('<num_total>', #menu.search_options)
end
- if menu.sorted then
+ if menu:is_sorted() then
str = colour.icon_sorted .. icon.sorted .. ' ' .. col .. str
end
diff --git a/rt.lua b/rt.lua
index 1cdf777..9193314 100644
--- a/rt.lua
+++ b/rt.lua
@@ -166,7 +166,7 @@ local function save_favourites()
config.favourites_file, {favourites = state.favourites})
end
-function rt.set_cursor(pos, opts)
+local function set_cursor(pos, opts)
local moved = state:menu():set_cursor(pos, osd:menu_lines(state), opts)
if moved then
osd:dirty()
@@ -174,49 +174,49 @@ function rt.set_cursor(pos, opts)
end
function rt.cursor_up()
- rt.set_cursor(state:menu().cursor - 1, {margin = config.scroll_margin})
+ set_cursor(state:menu().cursor - 1, {margin = config.scroll_margin})
end
function rt.cursor_down()
- rt.set_cursor(state:menu().cursor + 1, {margin = config.scroll_margin})
+ set_cursor(state:menu().cursor + 1, {margin = config.scroll_margin})
end
function rt.cursor_start()
- rt.set_cursor(1)
+ set_cursor(1)
end
function rt.cursor_end()
- rt.set_cursor(#state:menu().options)
+ set_cursor(#state:menu().options)
end
function rt.cursor_page_up()
- rt.set_cursor(
+ set_cursor(
state:menu().cursor - osd:menu_lines(state),
{keep_offset = true, margin = config.scroll_margin})
end
function rt.cursor_page_down()
- rt.set_cursor(
+ set_cursor(
state:menu().cursor + osd:menu_lines(state),
{keep_offset = true, margin = config.scroll_margin})
end
function rt.cursor_wheel_up()
- rt.set_cursor(state:menu().cursor - 1, {keep_offset = true})
+ set_cursor(state:menu().cursor - 1, {keep_offset = true})
end
function rt.cursor_wheel_down()
- rt.set_cursor(state:menu().cursor + 1, {keep_offset = true})
+ set_cursor(state:menu().cursor + 1, {keep_offset = true})
end
function rt.cursor_wheel_page_up()
- rt.set_cursor(
+ set_cursor(
state:menu().cursor - osd:menu_lines(state),
{keep_offset = true})
end
function rt.cursor_wheel_page_down()
- rt.set_cursor(
+ set_cursor(
state:menu().cursor + osd:menu_lines(state),
{keep_offset = true})
end
@@ -224,7 +224,7 @@ end
local function cursor_to_id(id)
for i, v in ipairs(state:menu().options) do
if v.id == id then
- rt.set_cursor(i, {centre = true})
+ set_cursor(i, {centre = true})
return
end
end
@@ -232,13 +232,13 @@ end
local function move_option(pos, opts)
local menu = state:menu()
- if menu.group_id ~= 'favourites' or menu.sorted then
+ if menu.group_id ~= 'favourites' or menu:is_sorted() then
return
end
local prev_cursor = menu.cursor
local opts = opts or {}
- rt.set_cursor(pos, opts)
+ set_cursor(pos, opts)
if menu.cursor == prev_cursor then
return
end
@@ -313,26 +313,26 @@ function rt.push_group_menu(group)
})
end
--- refresh options when navigating up the stack to a previous favourites menu.
--- existing menu options are never removed, even if unfavourited.
-local function refresh_favourites_menu()
+-- refresh menu options from current catalogue state, while keeping existing
+-- options that have been removed. this is designed to update the favourites
+-- menu when navigating up the stack.
+local function merge_refreshed_menu_options()
local menu = state:menu()
- local opt = menu.options[menu.cursor]
- local sorted = menu.sorted
- if sorted then
- menu:set_sort(false)
- end
+ local pos = menu.cursor
+ local top = menu.view_top
+ local opt = menu.options[pos]
- menu.options = util.stable_kmerge(
- menu.options,
+ menu:set_options(util.stable_kmerge(
+ menu:master_options(),
rx.menu_options_group(ctx.catalogue:get(menu.group_id)),
- 'id')
+ 'id'))
- if sorted then
- menu:set_sort(true, rx.sort_menu_options)
- end
if opt then
- cursor_to_id(opt.id)
+ if menu.options[pos].id and menu.options[pos].id == opt.id then
+ set_cursor(pos, {view_top=top})
+ else
+ cursor_to_id(opt.id)
+ end
end
end
@@ -344,7 +344,7 @@ function rt.prev_menu()
rt.push_group_menu(ctx.catalogue:get(state.menus[1].group_id))
else
if state:menu().group_id == 'favourites' then
- refresh_favourites_menu()
+ merge_refreshed_menu_options()
end
end
@@ -411,7 +411,7 @@ function rt.goto_option()
elseif menu.type == 'search' then
state.depth = state.depth - 1
if state:menu().group_id == 'favourites' then
- refresh_favourites_menu()
+ merge_refreshed_menu_options()
end
end
@@ -471,7 +471,7 @@ local function open_option_channel_epg(opt)
type = 'epg',
img_url = opt.img_url,
})
- rt.set_cursor(idx, {centre = true})
+ set_cursor(idx, {centre = true})
osd:dirty()
end
@@ -664,7 +664,7 @@ function rt.toggle_menu_sort()
return
end
- menu:set_sort(not menu.sorted, rx.sort_menu_options)
+ menu:set_sort(not menu:is_sorted() and rx.sort_menu_options or nil)
osd:dirty()
end
@@ -680,7 +680,7 @@ function rt.click_menu()
return
end
- rt.set_cursor(pos)
+ set_cursor(pos)
end
function rt.dbl_click_menu()
@@ -692,7 +692,7 @@ function rt.dbl_click_menu()
-- title
if line < 0 then
if line == -1 then
- rt.set_cursor(1)
+ set_cursor(1)
else
state.depth = state.depth + line + 1
osd:dirty()
@@ -711,7 +711,7 @@ end
function rt.dbl_click_scrollbar()
-- set_cursor handles out-of-bounds moves (when ratio == 1)
- rt.set_cursor(
+ set_cursor(
math.floor(osd.mstate.ratio * #state:menu().options) + 1,
{centre = true})
end
diff --git a/state.lua b/state.lua
index a88fe41..326fa28 100644
--- a/state.lua
+++ b/state.lua
@@ -100,6 +100,8 @@ function menu_mt:set_cursor(pos, lines, opts)
top = pos - math.floor((lines - 1) / 2)
elseif opts and opts.keep_offset then
top = top + pos - self.cursor
+ elseif opts and opts.view_top then
+ top = opts.view_top
elseif margin > 0 then
margin = math.max(0, math.min(
margin,
@@ -120,25 +122,58 @@ function menu_mt:set_cursor(pos, lines, opts)
return true
end
-function menu_mt:set_sort(bool, f)
- if not self.sorted == not bool then
- return
- end
+function menu_mt:options_key()
+ return self.type == 'search' and 'search_options' or 'options'
+end
- local key = self.type == 'search' and 'search_options' or 'options'
- if bool then
- self['orig_' .. key] = self[key]
- self[key] = util.copy_table(self[key])
+function menu_mt:set_sort(f)
+ local key = self:options_key()
+ local orig_key = 'orig_' .. key
+
+ if f then
+ if not self[orig_key] then
+ self[orig_key] = self[key]
+ end
+ self[key] = util.copy_table(self[orig_key])
f(self[key])
+ elseif self.sort_f then
+ self[key] = self[orig_key]
+ self[orig_key] = nil
+ end
+
+ self.sort_f = f
+
+ if self.type == 'search' then
+ self:update_search_matches()
+ end
+end
+
+function menu_mt:is_sorted()
+ return self.sort_f ~= nil
+end
+
+function menu_mt:master_options()
+ local key = self:options_key()
+ return self.sort_f and self['orig_' .. key] or self[key]
+end
+
+function menu_mt:set_options(options)
+ local key = self:options_key()
+ if self.sort_f then
+ self['orig_' .. key] = options
+ self[key] = util.copy_table(options)
+ self.sort_f(self[key])
else
- self[key] = self['orig_' .. key]
- self['orig_' .. key] = nil
+ self[key] = options
end
if self.type == 'search' then
self:update_search_matches()
end
- self.sorted = bool
+
+ -- previous position could have become invalid. reset to top and let
+ -- caller deal with remembering position if it is needed.
+ self:set_cursor(1)
end
function menu_mt:set_search_cursor(pos)