updated mpv code to try and fix invisible cursor
This commit is contained in:
+182
-74
@@ -388,31 +388,52 @@ M._disable_input_section = function(name, reason)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M._sync_uosc_cursor(reason)
|
||||||
|
local why = tostring(reason or 'unknown')
|
||||||
|
|
||||||
|
local function do_sync(suffix)
|
||||||
|
pcall(mp.set_property, 'cursor-autohide', '1000')
|
||||||
|
if ensure_uosc_loaded() then
|
||||||
|
pcall(mp.commandv, 'script-message-to', 'uosc', 'sync-cursor')
|
||||||
|
end
|
||||||
|
M._disable_input_section('input_console', why .. suffix)
|
||||||
|
M._disable_input_section('input_forced_console', why .. suffix)
|
||||||
|
M._disable_input_section('image', why .. suffix)
|
||||||
|
end
|
||||||
|
|
||||||
|
do_sync('@immediate')
|
||||||
|
mp.add_timeout(0.05, function()
|
||||||
|
do_sync('@sync')
|
||||||
|
end)
|
||||||
|
mp.add_timeout(0.20, function()
|
||||||
|
do_sync('@sync2')
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M._close_uosc_menu_and_sync(menu_type, reason)
|
||||||
|
local why = tostring(reason or 'unknown')
|
||||||
|
if ensure_uosc_loaded() then
|
||||||
|
if menu_type and menu_type ~= '' then
|
||||||
|
pcall(mp.commandv, 'script-message-to', 'uosc', 'close-menu', menu_type)
|
||||||
|
else
|
||||||
|
pcall(mp.commandv, 'script-message-to', 'uosc', 'close-menu')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
M._sync_uosc_cursor(why)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
M._reset_uosc_input_state = function(reason)
|
M._reset_uosc_input_state = function(reason)
|
||||||
local why = tostring(reason or 'unknown')
|
local why = tostring(reason or 'unknown')
|
||||||
M._disable_input_section('input_console', why)
|
M._disable_input_section('input_console', why)
|
||||||
M._disable_input_section('input_forced_console', why)
|
M._disable_input_section('input_forced_console', why)
|
||||||
|
M._disable_input_section('image', why)
|
||||||
|
pcall(mp.set_property, 'cursor-autohide', '1000')
|
||||||
if not ensure_uosc_loaded() then
|
if not ensure_uosc_loaded() then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
pcall(mp.commandv, 'script-message-to', 'uosc', 'close-menu')
|
pcall(mp.commandv, 'script-message-to', 'uosc', 'close-menu')
|
||||||
pcall(mp.commandv, 'script-message-to', 'uosc', 'sync-cursor')
|
M._sync_uosc_cursor(why)
|
||||||
M._disable_input_section('input_console', why .. '@immediate')
|
|
||||||
M._disable_input_section('input_forced_console', why .. '@immediate')
|
|
||||||
mp.add_timeout(0.05, function()
|
|
||||||
if ensure_uosc_loaded() then
|
|
||||||
pcall(mp.commandv, 'script-message-to', 'uosc', 'sync-cursor')
|
|
||||||
end
|
|
||||||
M._disable_input_section('input_console', why .. '@sync')
|
|
||||||
M._disable_input_section('input_forced_console', why .. '@sync')
|
|
||||||
end)
|
|
||||||
mp.add_timeout(0.20, function()
|
|
||||||
if ensure_uosc_loaded() then
|
|
||||||
pcall(mp.commandv, 'script-message-to', 'uosc', 'sync-cursor')
|
|
||||||
end
|
|
||||||
M._disable_input_section('input_console', why .. '@sync2')
|
|
||||||
M._disable_input_section('input_forced_console', why .. '@sync2')
|
|
||||||
end)
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -429,6 +450,12 @@ M._open_uosc_menu = function(menu_data, reason)
|
|||||||
_lua_log('menu: open-menu failed reason=' .. why .. ' err=' .. tostring(err))
|
_lua_log('menu: open-menu failed reason=' .. why .. ' err=' .. tostring(err))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
mp.add_timeout(0.03, function()
|
||||||
|
pcall(mp.set_property, 'cursor-autohide', '1000')
|
||||||
|
if ensure_uosc_loaded() then
|
||||||
|
pcall(mp.commandv, 'script-message-to', 'uosc', 'sync-cursor')
|
||||||
|
end
|
||||||
|
end)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -927,6 +954,25 @@ local function _normalize_store_name(store)
|
|||||||
return trim(store)
|
return trim(store)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M._store_name_is_visible_in_mpv(store)
|
||||||
|
store = _normalize_store_name(store)
|
||||||
|
return store ~= '' and store:lower() ~= 'local'
|
||||||
|
end
|
||||||
|
|
||||||
|
function M._visible_store_names()
|
||||||
|
local out = {}
|
||||||
|
if type(_cached_store_names) ~= 'table' then
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
for _, name in ipairs(_cached_store_names) do
|
||||||
|
name = _normalize_store_name(name)
|
||||||
|
if M._store_name_is_visible_in_mpv(name) then
|
||||||
|
out[#out + 1] = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
local function _is_cached_store_name(store)
|
local function _is_cached_store_name(store)
|
||||||
local needle = _normalize_store_name(store)
|
local needle = _normalize_store_name(store)
|
||||||
if needle == '' then
|
if needle == '' then
|
||||||
@@ -1174,17 +1220,25 @@ local HELPER_START_DEBOUNCE = 2.0
|
|||||||
-- Track ready-heartbeat freshness so stale or non-timestamp values don't mask a stopped helper
|
-- Track ready-heartbeat freshness so stale or non-timestamp values don't mask a stopped helper
|
||||||
local _helper_ready_last_value = ''
|
local _helper_ready_last_value = ''
|
||||||
local _helper_ready_last_seen_ts = 0
|
local _helper_ready_last_seen_ts = 0
|
||||||
local HELPER_READY_STALE_SECONDS = 10.0
|
local HELPER_READY_STALE_SECONDS = 120.0
|
||||||
M._lyric_helper_state = M._lyric_helper_state or { last_start_ts = -1000, debounce = 3.0 }
|
M._lyric_helper_state = M._lyric_helper_state or { last_start_ts = -1000, debounce = 3.0 }
|
||||||
M._subtitle_autoselect_state = M._subtitle_autoselect_state or { serial = 0, deadline = 0 }
|
M._subtitle_autoselect_state = M._subtitle_autoselect_state or { serial = 0, deadline = 0 }
|
||||||
|
|
||||||
|
function M._normalize_mpv_user_data_text(value)
|
||||||
|
local text = trim(tostring(value or ''))
|
||||||
|
if text:sub(1, 1) == '"' and text:sub(-1) == '"' and #text >= 2 then
|
||||||
|
text = text:sub(2, -2)
|
||||||
|
end
|
||||||
|
return trim(text)
|
||||||
|
end
|
||||||
|
|
||||||
local function _is_pipeline_helper_ready()
|
local function _is_pipeline_helper_ready()
|
||||||
local helper_version = mp.get_property('user-data/medeia-pipeline-helper-version')
|
local helper_version = mp.get_property('user-data/medeia-pipeline-helper-version')
|
||||||
if helper_version == nil or helper_version == '' then
|
if helper_version == nil or helper_version == '' then
|
||||||
helper_version = mp.get_property_native('user-data/medeia-pipeline-helper-version')
|
helper_version = mp.get_property_native('user-data/medeia-pipeline-helper-version')
|
||||||
end
|
end
|
||||||
helper_version = tostring(helper_version or '')
|
helper_version = M._normalize_mpv_user_data_text(helper_version)
|
||||||
if helper_version ~= '2026-03-23.1' then
|
if helper_version ~= '' and helper_version ~= '2026-03-23.1' then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1197,7 +1251,7 @@ local function _is_pipeline_helper_ready()
|
|||||||
_helper_ready_last_seen_ts = 0
|
_helper_ready_last_seen_ts = 0
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local s = tostring(ready)
|
local s = M._normalize_mpv_user_data_text(ready)
|
||||||
if s == '' or s == '0' then
|
if s == '' or s == '0' then
|
||||||
_helper_ready_last_value = s
|
_helper_ready_last_value = s
|
||||||
_helper_ready_last_seen_ts = 0
|
_helper_ready_last_seen_ts = 0
|
||||||
@@ -1228,6 +1282,9 @@ local function _is_pipeline_helper_ready()
|
|||||||
|
|
||||||
-- Fall back only for non-timestamp values so stale helper timestamps from a
|
-- Fall back only for non-timestamp values so stale helper timestamps from a
|
||||||
-- previous session do not look fresh right after Lua reload.
|
-- previous session do not look fresh right after Lua reload.
|
||||||
|
if helper_version ~= '2026-03-23.1' then
|
||||||
|
return false
|
||||||
|
end
|
||||||
if _helper_ready_last_seen_ts > 0 and (now - _helper_ready_last_seen_ts) <= HELPER_READY_STALE_SECONDS then
|
if _helper_ready_last_seen_ts > 0 and (now - _helper_ready_last_seen_ts) <= HELPER_READY_STALE_SECONDS then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -1236,22 +1293,33 @@ local function _is_pipeline_helper_ready()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function _helper_ready_diagnostics()
|
local function _helper_ready_diagnostics()
|
||||||
local ready = mp.get_property(PIPELINE_READY_PROP)
|
local raw_ready = mp.get_property(PIPELINE_READY_PROP)
|
||||||
if ready == nil or ready == '' then
|
if raw_ready == nil or raw_ready == '' then
|
||||||
ready = mp.get_property_native(PIPELINE_READY_PROP)
|
raw_ready = mp.get_property_native(PIPELINE_READY_PROP)
|
||||||
end
|
end
|
||||||
local helper_version = mp.get_property('user-data/medeia-pipeline-helper-version')
|
local raw_helper_version = mp.get_property('user-data/medeia-pipeline-helper-version')
|
||||||
if helper_version == nil or helper_version == '' then
|
if raw_helper_version == nil or raw_helper_version == '' then
|
||||||
helper_version = mp.get_property_native('user-data/medeia-pipeline-helper-version')
|
raw_helper_version = mp.get_property_native('user-data/medeia-pipeline-helper-version')
|
||||||
end
|
end
|
||||||
|
local ready = M._normalize_mpv_user_data_text(raw_ready)
|
||||||
|
local helper_version = M._normalize_mpv_user_data_text(raw_helper_version)
|
||||||
local now = mp.get_time() or 0
|
local now = mp.get_time() or 0
|
||||||
local age = 'n/a'
|
local age = 'n/a'
|
||||||
if _helper_ready_last_seen_ts > 0 then
|
if _helper_ready_last_seen_ts > 0 then
|
||||||
age = string.format('%.2fs', math.max(0, now - _helper_ready_last_seen_ts))
|
age = string.format('%.2fs', math.max(0, now - _helper_ready_last_seen_ts))
|
||||||
end
|
end
|
||||||
|
local heartbeat_age = 'n/a'
|
||||||
|
local ready_epoch = tonumber(ready)
|
||||||
|
local os_now = (os and os.time) and os.time() or nil
|
||||||
|
if ready_epoch and ready_epoch > 1000000000 and os_now then
|
||||||
|
heartbeat_age = string.format('%.2fs', math.max(0, os_now - ready_epoch))
|
||||||
|
end
|
||||||
return 'ready=' .. tostring(ready or '')
|
return 'ready=' .. tostring(ready or '')
|
||||||
|
.. ' raw_ready=' .. tostring(raw_ready or '')
|
||||||
.. ' helper_version=' .. tostring(helper_version or '')
|
.. ' helper_version=' .. tostring(helper_version or '')
|
||||||
|
.. ' raw_helper_version=' .. tostring(raw_helper_version or '')
|
||||||
.. ' required_version=2026-03-23.1'
|
.. ' required_version=2026-03-23.1'
|
||||||
|
.. ' heartbeat_age=' .. tostring(heartbeat_age)
|
||||||
.. ' last_value=' .. tostring(_helper_ready_last_value or '')
|
.. ' last_value=' .. tostring(_helper_ready_last_value or '')
|
||||||
.. ' last_seen_age=' .. tostring(age)
|
.. ' last_seen_age=' .. tostring(age)
|
||||||
end
|
end
|
||||||
@@ -2327,6 +2395,29 @@ local function _get_current_item_is_image()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M._has_visual_screenshot_source()
|
||||||
|
if _get_current_item_is_image() then
|
||||||
|
return true, 'image'
|
||||||
|
end
|
||||||
|
|
||||||
|
local width = tonumber(mp.get_property_number('width') or 0) or 0
|
||||||
|
local height = tonumber(mp.get_property_number('height') or 0) or 0
|
||||||
|
if width > 0 and height > 0 then
|
||||||
|
return true, 'video'
|
||||||
|
end
|
||||||
|
|
||||||
|
local video_params = mp.get_property_native('video-params')
|
||||||
|
if type(video_params) == 'table' then
|
||||||
|
local params_width = tonumber(video_params.w or video_params.dw or video_params.width or 0) or 0
|
||||||
|
local params_height = tonumber(video_params.h or video_params.dh or video_params.height or 0) or 0
|
||||||
|
if params_width > 0 and params_height > 0 then
|
||||||
|
return true, 'video'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false, ''
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function _set_image_property(value)
|
local function _set_image_property(value)
|
||||||
pcall(mp.set_property_native, 'user-data/mpv/image', value and true or false)
|
pcall(mp.set_property_native, 'user-data/mpv/image', value and true or false)
|
||||||
@@ -2776,6 +2867,7 @@ local function _open_store_picker_for_pending_screenshot()
|
|||||||
|
|
||||||
local function build_items()
|
local function build_items()
|
||||||
local selected = _get_selected_store()
|
local selected = _get_selected_store()
|
||||||
|
local visible_names = M._visible_store_names()
|
||||||
local items = {}
|
local items = {}
|
||||||
|
|
||||||
items[#items + 1] = {
|
items[#items + 1] = {
|
||||||
@@ -2784,8 +2876,8 @@ local function _open_store_picker_for_pending_screenshot()
|
|||||||
value = { 'script-message-to', mp.get_script_name(), 'medeia-image-screenshot-pick-path', '{}' },
|
value = { 'script-message-to', mp.get_script_name(), 'medeia-image-screenshot-pick-path', '{}' },
|
||||||
}
|
}
|
||||||
|
|
||||||
if type(_cached_store_names) == 'table' and #_cached_store_names > 0 then
|
if #visible_names > 0 then
|
||||||
for _, name in ipairs(_cached_store_names) do
|
for _, name in ipairs(visible_names) do
|
||||||
name = trim(tostring(name or ''))
|
name = trim(tostring(name or ''))
|
||||||
if name ~= '' then
|
if name ~= '' then
|
||||||
items[#items + 1] = {
|
items[#items + 1] = {
|
||||||
@@ -2822,6 +2914,16 @@ local function _open_store_picker_for_pending_screenshot()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function _capture_screenshot()
|
local function _capture_screenshot()
|
||||||
|
local screenshot_available = false
|
||||||
|
local screenshot_kind = ''
|
||||||
|
screenshot_available, screenshot_kind = M._has_visual_screenshot_source()
|
||||||
|
if not screenshot_available then
|
||||||
|
_lua_log('screenshot: blocked reason=no visual source')
|
||||||
|
M._sync_uosc_cursor('screenshot-unavailable')
|
||||||
|
mp.osd_message('Screenshot unavailable (no video/image frame)', 2)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local function _format_time_label(seconds)
|
local function _format_time_label(seconds)
|
||||||
local total = math.max(0, math.floor(tonumber(seconds or 0) or 0))
|
local total = math.max(0, math.floor(tonumber(seconds or 0) or 0))
|
||||||
local hours = math.floor(total / 3600)
|
local hours = math.floor(total / 3600)
|
||||||
@@ -2856,6 +2958,11 @@ local function _capture_screenshot()
|
|||||||
end
|
end
|
||||||
local out_path = utils.join_path(temp_dir, filename)
|
local out_path = utils.join_path(temp_dir, filename)
|
||||||
out_path = _normalize_fs_path(out_path)
|
out_path = _normalize_fs_path(out_path)
|
||||||
|
local was_paused = mp.get_property_native('pause') and true or false
|
||||||
|
|
||||||
|
if not was_paused then
|
||||||
|
pcall(mp.set_property_native, 'pause', true)
|
||||||
|
end
|
||||||
|
|
||||||
local function do_screenshot(mode)
|
local function do_screenshot(mode)
|
||||||
mode = mode or 'video'
|
mode = mode or 'video'
|
||||||
@@ -2869,22 +2976,31 @@ local function _capture_screenshot()
|
|||||||
-- try 'window' as fallback.
|
-- try 'window' as fallback.
|
||||||
local ok = do_screenshot('video')
|
local ok = do_screenshot('video')
|
||||||
if not ok then
|
if not ok then
|
||||||
_lua_log('screenshot: video-mode failed; trying window-mode')
|
_lua_log('screenshot: video-mode failed; trying window-mode kind=' .. tostring(screenshot_kind))
|
||||||
ok = do_screenshot('window')
|
ok = do_screenshot('window')
|
||||||
end
|
end
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
_lua_log('screenshot: BOTH video and window modes FAILED')
|
_lua_log('screenshot: BOTH video and window modes FAILED')
|
||||||
|
if not was_paused then
|
||||||
|
pcall(mp.set_property_native, 'pause', false)
|
||||||
|
end
|
||||||
|
M._sync_uosc_cursor('screenshot-failed')
|
||||||
mp.osd_message('Screenshot failed (no frames)', 2)
|
mp.osd_message('Screenshot failed (no frames)', 2)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not was_paused then
|
||||||
|
mp.osd_message('Screenshot captured. Playback paused for review.', 2)
|
||||||
|
end
|
||||||
|
|
||||||
_ensure_selected_store_loaded()
|
_ensure_selected_store_loaded()
|
||||||
|
|
||||||
local function dispatch_screenshot_save()
|
local function dispatch_screenshot_save()
|
||||||
local store_count = (type(_cached_store_names) == 'table') and #_cached_store_names or 0
|
local visible_store_names = M._visible_store_names()
|
||||||
|
local store_count = #visible_store_names
|
||||||
local selected_store = _normalize_store_name(_get_selected_store())
|
local selected_store = _normalize_store_name(_get_selected_store())
|
||||||
if not _is_cached_store_name(selected_store) then
|
if not M._store_name_is_visible_in_mpv(selected_store) then
|
||||||
selected_store = ''
|
selected_store = ''
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2895,7 +3011,7 @@ local function _capture_screenshot()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if selected_store == '' and store_count == 1 then
|
if selected_store == '' and store_count == 1 then
|
||||||
selected_store = _normalize_store_name(_cached_store_names[1])
|
selected_store = _normalize_store_name(visible_store_names[1])
|
||||||
end
|
end
|
||||||
|
|
||||||
if selected_store == '' then
|
if selected_store == '' then
|
||||||
@@ -3616,16 +3732,11 @@ _refresh_store_cache = function(timeout_seconds, on_complete)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local cached_json = mp.get_property('user-data/medeia-store-choices-cached')
|
local cached_json = mp.get_property('user-data/medeia-store-choices-cached')
|
||||||
_lua_log('stores: cache_read cached_json=' .. tostring(cached_json) .. ' len=' .. tostring(cached_json and #cached_json or 0))
|
|
||||||
|
|
||||||
if cached_json and cached_json ~= '' then
|
if cached_json and cached_json ~= '' then
|
||||||
local ok, cached_resp = pcall(utils.parse_json, cached_json)
|
local ok, cached_resp = pcall(utils.parse_json, cached_json)
|
||||||
_lua_log('stores: cache_parse ok=' .. tostring(ok) .. ' resp_type=' .. tostring(type(cached_resp)))
|
|
||||||
if ok then
|
if ok then
|
||||||
if type(cached_resp) == 'string' then
|
if type(cached_resp) == 'string' then
|
||||||
_lua_log('stores: cache_parse returned string, trying again...')
|
|
||||||
ok, cached_resp = pcall(utils.parse_json, cached_resp)
|
ok, cached_resp = pcall(utils.parse_json, cached_resp)
|
||||||
_lua_log('stores: cache_parse retry ok=' .. tostring(ok) .. ' resp_type=' .. tostring(type(cached_resp)))
|
|
||||||
end
|
end
|
||||||
if ok then
|
if ok then
|
||||||
if apply_store_choices(cached_resp, 'cache') then
|
if apply_store_choices(cached_resp, 'cache') then
|
||||||
@@ -3633,10 +3744,8 @@ _refresh_store_cache = function(timeout_seconds, on_complete)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
_lua_log('stores: cache_parse failed ok=' .. tostring(ok) .. ' resp=' .. tostring(cached_resp))
|
_lua_log('stores: cached property parse failed; falling back to direct config')
|
||||||
end
|
end
|
||||||
else
|
|
||||||
_lua_log('stores: cache_empty cached_json=' .. tostring(cached_json))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not _store_cache_retry_pending then
|
if not _store_cache_retry_pending then
|
||||||
@@ -3678,10 +3787,11 @@ local function _open_store_picker()
|
|||||||
_ensure_selected_store_loaded()
|
_ensure_selected_store_loaded()
|
||||||
|
|
||||||
local selected = _get_selected_store()
|
local selected = _get_selected_store()
|
||||||
local cached_count = (type(_cached_store_names) == 'table') and #_cached_store_names or 0
|
local visible_store_names = M._visible_store_names()
|
||||||
|
local cached_count = #visible_store_names
|
||||||
local cached_preview = ''
|
local cached_preview = ''
|
||||||
if type(_cached_store_names) == 'table' and #_cached_store_names > 0 then
|
if cached_count > 0 then
|
||||||
cached_preview = table.concat(_cached_store_names, ', ')
|
cached_preview = table.concat(visible_store_names, ', ')
|
||||||
end
|
end
|
||||||
_lua_log(
|
_lua_log(
|
||||||
'stores: open picker selected='
|
'stores: open picker selected='
|
||||||
@@ -3695,10 +3805,11 @@ local function _open_store_picker()
|
|||||||
local function build_items()
|
local function build_items()
|
||||||
local selected = _get_selected_store()
|
local selected = _get_selected_store()
|
||||||
local current_url = trim(tostring(_current_url_for_web_actions() or _current_target() or ''))
|
local current_url = trim(tostring(_current_url_for_web_actions() or _current_target() or ''))
|
||||||
|
local visible_names = M._visible_store_names()
|
||||||
local items = {}
|
local items = {}
|
||||||
|
|
||||||
if type(_cached_store_names) == 'table' and #_cached_store_names > 0 then
|
if #visible_names > 0 then
|
||||||
for _, name in ipairs(_cached_store_names) do
|
for _, name in ipairs(visible_names) do
|
||||||
name = trim(tostring(name or ''))
|
name = trim(tostring(name or ''))
|
||||||
if name ~= '' then
|
if name ~= '' then
|
||||||
local payload = { store = name }
|
local payload = { store = name }
|
||||||
@@ -3728,25 +3839,13 @@ local function _open_store_picker()
|
|||||||
-- Open immediately with whatever cache we have.
|
-- Open immediately with whatever cache we have.
|
||||||
_uosc_open_list_picker(STORE_PICKER_MENU_TYPE, 'Store', build_items())
|
_uosc_open_list_picker(STORE_PICKER_MENU_TYPE, 'Store', build_items())
|
||||||
|
|
||||||
-- Best-effort refresh; retry briefly to avoid races where the helper isn't
|
mp.add_timeout(0.05, function()
|
||||||
-- ready/observing yet at the exact moment the menu opens.
|
|
||||||
local function attempt_refresh(tries_left)
|
|
||||||
_refresh_store_cache(1.2, function(success, changed)
|
_refresh_store_cache(1.2, function(success, changed)
|
||||||
if success and changed then
|
if success and changed then
|
||||||
_lua_log('stores: reopening menu (store list changed)')
|
_lua_log('stores: reopening menu (store list changed)')
|
||||||
_uosc_open_list_picker(STORE_PICKER_MENU_TYPE, 'Store', build_items())
|
_uosc_open_list_picker(STORE_PICKER_MENU_TYPE, 'Store', build_items())
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if tries_left > 0 then
|
|
||||||
mp.add_timeout(0.25, function()
|
|
||||||
attempt_refresh(tries_left - 1)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
mp.add_timeout(0.05, function()
|
|
||||||
attempt_refresh(6)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -4225,6 +4324,9 @@ end
|
|||||||
_store_status_hint_for_url = function(store, url, fallback)
|
_store_status_hint_for_url = function(store, url, fallback)
|
||||||
store = trim(tostring(store or ''))
|
store = trim(tostring(store or ''))
|
||||||
url = trim(tostring(url or ''))
|
url = trim(tostring(url or ''))
|
||||||
|
if not M._store_name_is_visible_in_mpv(store) then
|
||||||
|
return fallback
|
||||||
|
end
|
||||||
if store == '' or url == '' or not _current_store_url_status_matches(store, url) then
|
if store == '' or url == '' or not _current_store_url_status_matches(store, url) then
|
||||||
return fallback
|
return fallback
|
||||||
end
|
end
|
||||||
@@ -4257,6 +4359,11 @@ _refresh_current_store_url_status = function(reason)
|
|||||||
local url = trim(tostring(target or ''))
|
local url = trim(tostring(target or ''))
|
||||||
local normalized_url = _normalize_url_for_store_lookup(url)
|
local normalized_url = _normalize_url_for_store_lookup(url)
|
||||||
|
|
||||||
|
if not M._store_name_is_visible_in_mpv(store) then
|
||||||
|
_begin_current_store_url_status(store, url, 'idle')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if url == '' or not _is_http_url(url) or _extract_store_hash(url) then
|
if url == '' or not _is_http_url(url) or _extract_store_hash(url) then
|
||||||
_begin_current_store_url_status(store, url, 'idle')
|
_begin_current_store_url_status(store, url, 'idle')
|
||||||
return
|
return
|
||||||
@@ -5167,6 +5274,7 @@ local function _open_save_location_picker_for_pending_download()
|
|||||||
|
|
||||||
local function build_items()
|
local function build_items()
|
||||||
local selected = _get_selected_store()
|
local selected = _get_selected_store()
|
||||||
|
local visible_names = M._visible_store_names()
|
||||||
local items = {
|
local items = {
|
||||||
{
|
{
|
||||||
title = 'Pick folder…',
|
title = 'Pick folder…',
|
||||||
@@ -5175,8 +5283,8 @@ local function _open_save_location_picker_for_pending_download()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if type(_cached_store_names) == 'table' and #_cached_store_names > 0 then
|
if #visible_names > 0 then
|
||||||
for _, name in ipairs(_cached_store_names) do
|
for _, name in ipairs(visible_names) do
|
||||||
name = trim(tostring(name or ''))
|
name = trim(tostring(name or ''))
|
||||||
if name ~= '' then
|
if name ~= '' then
|
||||||
local payload = { store = name }
|
local payload = { store = name }
|
||||||
@@ -5898,10 +6006,13 @@ end
|
|||||||
|
|
||||||
-- Open the command submenu with tailored cmdlets (screenshot, clip, trim prompt)
|
-- Open the command submenu with tailored cmdlets (screenshot, clip, trim prompt)
|
||||||
function M.open_cmd_menu()
|
function M.open_cmd_menu()
|
||||||
|
local screenshot_available, screenshot_kind = M._has_visual_screenshot_source()
|
||||||
|
local screenshot_hint = screenshot_available and ((screenshot_kind == 'image') and 'Capture current image' or 'Capture current frame') or 'Disabled: no video or image frame'
|
||||||
local items = {
|
local items = {
|
||||||
{
|
{
|
||||||
title = 'Screenshot',
|
title = 'Screenshot',
|
||||||
hint = 'Capture a screenshot',
|
hint = screenshot_hint,
|
||||||
|
selectable = screenshot_available,
|
||||||
value = { 'script-message-to', mp.get_script_name(), 'medios-cmd-exec', utils.format_json({ cmd = 'screenshot' }) },
|
value = { 'script-message-to', mp.get_script_name(), 'medios-cmd-exec', utils.format_json({ cmd = 'screenshot' }) },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -6195,19 +6306,15 @@ mp.register_script_message('medios-load-url-event', function(json)
|
|||||||
if not ok or type(event) ~= 'table' then
|
if not ok or type(event) ~= 'table' then
|
||||||
_lua_log('[LOAD-URL] Failed to parse JSON: ' .. tostring(json))
|
_lua_log('[LOAD-URL] Failed to parse JSON: ' .. tostring(json))
|
||||||
mp.osd_message('Failed to parse URL', 2)
|
mp.osd_message('Failed to parse URL', 2)
|
||||||
if ensure_uosc_loaded() then
|
_lua_log('[LOAD-URL] Closing menu due to parse error')
|
||||||
_lua_log('[LOAD-URL] Closing menu due to parse error')
|
M._close_uosc_menu_and_sync(LOAD_URL_MENU_TYPE, 'load-url-parse-error')
|
||||||
mp.commandv('script-message-to', 'uosc', 'close-menu', LOAD_URL_MENU_TYPE)
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
_lua_log('[LOAD-URL] Parsed event: type=' .. tostring(event.type) .. ', query=' .. tostring(event.query))
|
_lua_log('[LOAD-URL] Parsed event: type=' .. tostring(event.type) .. ', query=' .. tostring(event.query))
|
||||||
if event.type ~= 'search' then
|
if event.type ~= 'search' then
|
||||||
_lua_log('[LOAD-URL] Event type is not search: ' .. tostring(event.type))
|
_lua_log('[LOAD-URL] Event type is not search: ' .. tostring(event.type))
|
||||||
if ensure_uosc_loaded() then
|
_lua_log('[LOAD-URL] Closing menu due to type mismatch')
|
||||||
_lua_log('[LOAD-URL] Closing menu due to type mismatch')
|
M._close_uosc_menu_and_sync(LOAD_URL_MENU_TYPE, 'load-url-close')
|
||||||
mp.commandv('script-message-to', 'uosc', 'close-menu', LOAD_URL_MENU_TYPE)
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -6217,10 +6324,8 @@ mp.register_script_message('medios-load-url-event', function(json)
|
|||||||
_lua_log('[LOAD-URL] URL is empty')
|
_lua_log('[LOAD-URL] URL is empty')
|
||||||
_log_all('ERROR', 'Load URL failed: URL is empty')
|
_log_all('ERROR', 'Load URL failed: URL is empty')
|
||||||
mp.osd_message('URL is empty', 2)
|
mp.osd_message('URL is empty', 2)
|
||||||
if ensure_uosc_loaded() then
|
_lua_log('[LOAD-URL] Closing menu due to empty URL')
|
||||||
_lua_log('[LOAD-URL] Closing menu due to empty URL')
|
M._close_uosc_menu_and_sync(LOAD_URL_MENU_TYPE, 'load-url-empty')
|
||||||
mp.commandv('script-message-to', 'uosc', 'close-menu', LOAD_URL_MENU_TYPE)
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -6341,6 +6446,9 @@ function M.show_menu()
|
|||||||
|
|
||||||
local target = _current_target()
|
local target = _current_target()
|
||||||
local selected_store = trim(tostring(_get_selected_store() or ''))
|
local selected_store = trim(tostring(_get_selected_store() or ''))
|
||||||
|
if not M._store_name_is_visible_in_mpv(selected_store) then
|
||||||
|
selected_store = ''
|
||||||
|
end
|
||||||
local download_hint = nil
|
local download_hint = nil
|
||||||
if selected_store ~= '' and target and not _extract_store_hash(tostring(target)) then
|
if selected_store ~= '' and target and not _extract_store_hash(tostring(target)) then
|
||||||
download_hint = _store_status_hint_for_url(selected_store, tostring(target), 'save to ' .. selected_store)
|
download_hint = _store_status_hint_for_url(selected_store, tostring(target), 'save to ' .. selected_store)
|
||||||
|
|||||||
@@ -1123,8 +1123,12 @@ mp.register_script_message('sync-cursor', function()
|
|||||||
local mouse = mp.get_property_native('mouse-pos')
|
local mouse = mp.get_property_native('mouse-pos')
|
||||||
if type(mouse) == 'table' and mouse.hover and mouse.x and mouse.y then
|
if type(mouse) == 'table' and mouse.hover and mouse.x and mouse.y then
|
||||||
cursor:move(mouse.x, mouse.y)
|
cursor:move(mouse.x, mouse.y)
|
||||||
else
|
elseif cursor.x < math.huge and cursor.y < math.huge then
|
||||||
cursor:leave()
|
if cursor.hidden then
|
||||||
|
cursor.hidden = false
|
||||||
|
Elements:trigger('global_mouse_enter')
|
||||||
|
end
|
||||||
|
Elements:update_proximities()
|
||||||
end
|
end
|
||||||
cursor:queue_autohide()
|
cursor:queue_autohide()
|
||||||
request_render()
|
request_render()
|
||||||
|
|||||||
Reference in New Issue
Block a user