mobile updates CLOSES #482, CLOSES #553

This commit is contained in:
bryanthaboi
2026-07-31 22:39:01 -04:00
parent 5f855568c8
commit f2a3e5f05b
5 changed files with 235 additions and 14 deletions
+39 -12
View File
@@ -574,10 +574,16 @@ function RomImporter.new(onComplete, opts)
onEditTouchControls = opts.onEditTouchControls,
android = android,
ios = mobileOS == "iOS",
-- One startup poll pass: files dropped through the Files app are swept
-- into the save dir before Lua boots (GRBootstrap), but no love.focus
-- event necessarily follows, so consume them via the first poll tick.
pickPending = mobileOS == "iOS" or nil,
-- One startup poll pass on both mobiles. iOS: files dropped through the
-- Files app are swept into the save dir before Lua boots (GRBootstrap) with
-- no love.focus event necessarily following. Android: the SAF picker is a
-- separate activity, and Android is free to destroy GameActivity while it
-- is up (memory pressure, or "Don't keep activities"), so the app RESTARTS
-- instead of resuming and the love.focus(true) that would have consumed the
-- pick never arrives. The file is sitting in the save dir either way, so
-- boot armed and let the first poll tick consume it, rather than making the
-- player tap Import a second time to trigger the scan by hand (#553).
pickPending = android or nil,
-- Android drag: the launcher is handed no move events at all (main.lua
-- forwards neither touchmoved nor mousemoved while it is up), and its mouse
-- emulation is what "no reliable pointer polling" below refers to.
@@ -1011,6 +1017,7 @@ function RomImporter:chooseMod()
else
self.pickPending = true
self.pickTimer = 0
self.pickElapsed = 0
end
return
end
@@ -1075,6 +1082,7 @@ function RomImporter:chooseSaveImport(version)
else
self.pickPending = true
self.pickTimer = 0
self.pickElapsed = 0
end
return
end
@@ -1113,6 +1121,7 @@ function RomImporter:exportSave(version)
if love.system.createFile and love.system.createFile(suggested) then
self.pickPending = true
self.pickTimer = 0
self.pickElapsed = 0
self.saveNotice[version] = { ok = true,
text = "Pick where to save " .. suggested .. "..." }
else
@@ -1168,6 +1177,7 @@ function RomImporter:choose(version)
else
self.pickPending = true
self.pickTimer = 0
self.pickElapsed = 0
end
return
end
@@ -1202,14 +1212,31 @@ function RomImporter:choose(version)
end
end
-- iOS: the document picker is an in-process modal sheet, so unlike Android's
-- separate SAF activity there is no love.focus(true) when it dismisses.
-- While a pick is outstanding, poll the save dir for the bridge's delivered
-- file (picked_rom.gb / picked_mod.zip / picked_save.sav / export_done.flag)
-- and run the same refocus import path Android uses.
-- Poll the save dir for a delivered pick (picked_rom.gb / picked_mod.zip /
-- picked_save.sav / export_done.flag) and run the same import path a refocus
-- runs. Both mobiles need this, for different reasons:
--
-- iOS the document picker is an in-process modal sheet, so there is no
-- love.focus(true) when it dismisses -- nothing else would consume it.
-- Android the SAF picker IS a separate activity and normally does refocus,
-- but Android may destroy GameActivity while it is up, in which case
-- the app restarts and that focus event never comes. Polling makes
-- the outcome the same either way instead of leaving the pick on disk
-- for the next tap to find, which is what made users import twice and
-- what made it look random: it depends on memory pressure (#553).
--
-- Disarms after PICK_TIMEOUT so a cancelled picker (which delivers nothing,
-- ever) does not leave this scanning the save directory for the whole session.
local PICK_TIMEOUT = 120
function RomImporter:_pollPickedFiles(dt)
if not (self.ios and self.pickPending) then return end
if not self.pickPending then return end
if self.workState == "working" then return end
self.pickElapsed = (self.pickElapsed or 0) + dt
if self.pickElapsed > PICK_TIMEOUT then
self.pickPending, self.pickElapsed = nil, nil
return
end
self.pickTimer = (self.pickTimer or 0) + dt
if self.pickTimer < 0.5 then return end
self.pickTimer = 0
@@ -1219,7 +1246,7 @@ function RomImporter:_pollPickedFiles(dt)
local pickError = love.filesystem.read("pick_error.txt")
if pickError then
love.filesystem.remove("pick_error.txt")
self.pickPending = nil
self.pickPending, self.pickElapsed = nil, nil
self.modNotice = { ok = false, text = pickError }
self.notice = { version = self.chooseVersion or "red",
status = "File import failed:", detail = pickError }
@@ -1236,7 +1263,7 @@ function RomImporter:_pollPickedFiles(dt)
end
end
if found then
self.pickPending = nil
self.pickPending, self.pickElapsed = nil, nil
self:focus(true)
end
end