mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 00:55:16 -07:00
fix: clear aborted playback state, fix overlay passthrough, and guard du
- Reset app_managed_playback_pending on lifecycle cleanup to prevent state leak into next item - Record visible overlay action only after command succeeds, not before - Non-native passive overlay now always click-through on re-show (fix isNonNativePassiveOverlay ordering) - Defer activeParsedSubtitleMediaPath assignment until after prefetch completes - Move autoplay gate release into the hide branch of toggleVisibleOverlay - Clear active Jellyfin playback when stopping media that never loaded - Reset managed subtitle delay and delay key when no external tracks are available - Await async removeDir in subtitle cache cleanup - Guard duplicate delete clicks in MediaDetailView and SessionsTab with refs - Escape key in DeleteConfirmDialog now calls stopPropagation and stopImmediatePropagation
This commit is contained in:
@@ -83,10 +83,16 @@ local process = process_module.create({
|
||||
return true
|
||||
end,
|
||||
},
|
||||
environment = {
|
||||
detect_backend = function()
|
||||
return "x11"
|
||||
end,
|
||||
environment = {
|
||||
detect_backend = function()
|
||||
return "x11"
|
||||
end,
|
||||
is_linux = function()
|
||||
return false
|
||||
end,
|
||||
is_subminer_app_running_async = function(callback)
|
||||
callback(false)
|
||||
end,
|
||||
},
|
||||
options_helper = {
|
||||
coerce_bool = function(value, default_value)
|
||||
@@ -125,4 +131,79 @@ for _, timeout_seconds in ipairs(recorded.timeouts) do
|
||||
end
|
||||
assert_true(retry_timeout_seen, "expected shorter bounded retry timeout")
|
||||
|
||||
do
|
||||
local visibility_state = {
|
||||
binary_path = "/tmp/subminer",
|
||||
overlay_running = true,
|
||||
texthooker_running = false,
|
||||
visible_overlay_requested = false,
|
||||
}
|
||||
local visibility_calls = {}
|
||||
local visibility_mp = {}
|
||||
|
||||
function visibility_mp.command_native_async(command, callback)
|
||||
visibility_calls[#visibility_calls + 1] = command
|
||||
if callback then
|
||||
callback(false, { status = 1, stdout = "", stderr = "failed" }, "failed")
|
||||
end
|
||||
end
|
||||
|
||||
local visibility_process = process_module.create({
|
||||
mp = visibility_mp,
|
||||
opts = {
|
||||
backend = "x11",
|
||||
socket_path = "/tmp/subminer.sock",
|
||||
log_level = "debug",
|
||||
texthooker_enabled = true,
|
||||
texthooker_port = 5174,
|
||||
auto_start_visible_overlay = false,
|
||||
},
|
||||
state = visibility_state,
|
||||
binary = {
|
||||
ensure_binary_available = function()
|
||||
return true
|
||||
end,
|
||||
},
|
||||
environment = {
|
||||
detect_backend = function()
|
||||
return "x11"
|
||||
end,
|
||||
is_linux = function()
|
||||
return false
|
||||
end,
|
||||
is_subminer_app_running_async = function(callback)
|
||||
callback(true)
|
||||
end,
|
||||
},
|
||||
options_helper = {
|
||||
coerce_bool = function(value, default_value)
|
||||
if value == true or value == "yes" or value == "true" then
|
||||
return true
|
||||
end
|
||||
if value == false or value == "no" or value == "false" then
|
||||
return false
|
||||
end
|
||||
return default_value
|
||||
end,
|
||||
},
|
||||
log = {
|
||||
subminer_log = function(_level, _scope, line)
|
||||
recorded.logs[#recorded.logs + 1] = line
|
||||
end,
|
||||
show_osd = function(_) end,
|
||||
normalize_log_level = function(value)
|
||||
return value or "info"
|
||||
end,
|
||||
},
|
||||
})
|
||||
|
||||
visibility_process.run_control_command_async("show-visible-overlay")
|
||||
|
||||
assert_true(#visibility_calls == 1, "expected visible overlay command to run")
|
||||
assert_true(
|
||||
visibility_state.visible_overlay_requested == false,
|
||||
"failed visible-overlay command should not update requested visibility state"
|
||||
)
|
||||
end
|
||||
|
||||
print("plugin process retry regression tests: OK")
|
||||
|
||||
@@ -645,6 +645,36 @@ do
|
||||
)
|
||||
end
|
||||
|
||||
do
|
||||
local scenario = {
|
||||
process_list = "",
|
||||
option_overrides = {
|
||||
binary_path = binary_path,
|
||||
auto_start = "yes",
|
||||
auto_start_visible_overlay = "yes",
|
||||
auto_start_pause_until_ready = "yes",
|
||||
socket_path = "/tmp/subminer-socket",
|
||||
},
|
||||
input_ipc_server = "/tmp/subminer-socket",
|
||||
path = "/media/aborted-app-managed.m3u8",
|
||||
media_title = "Aborted App Managed",
|
||||
files = {
|
||||
[binary_path] = true,
|
||||
},
|
||||
}
|
||||
local recorded, err = run_plugin_scenario(scenario)
|
||||
assert_true(recorded ~= nil, "plugin failed to load for aborted app-managed scenario: " .. tostring(err))
|
||||
recorded.script_messages["subminer-managed-subtitles-loading"]()
|
||||
fire_event(recorded, "end-file", { reason = "error" })
|
||||
scenario.path = "/media/next-normal.mkv"
|
||||
scenario.media_title = "Next Normal"
|
||||
fire_event(recorded, "file-loaded")
|
||||
assert_true(
|
||||
count_start_calls(recorded.async_calls) == 1,
|
||||
"aborted app-managed playback should not leak pending state into the next item"
|
||||
)
|
||||
end
|
||||
|
||||
do
|
||||
local scenario = {
|
||||
process_list = "",
|
||||
|
||||
Reference in New Issue
Block a user