From 921425ada496c2bcbfa4ecf83890cf912d61ba69 Mon Sep 17 00:00:00 2001 From: 20kdc Date: Wed, 25 Apr 2018 22:57:25 +0100 Subject: [PATCH] Optimize Icecap Nexus The things I have to destroy, the joy in it! For all I remove the more I save, the better it is! Perfection is when there is nothing to take away, and I revel in this task. --- code/apps/sys-icecap.lua | 88 ++++------- code/libs/sys-filedialog.lua | 297 ++++++++++++++++------------------- code/libs/sys-filevfs.lua | 6 +- code/libs/sys-secpolicy.lua | 34 ++-- 4 files changed, 185 insertions(+), 240 deletions(-) diff --git a/code/apps/sys-icecap.lua b/code/apps/sys-icecap.lua index 633e296..206e6dd 100644 --- a/code/apps/sys-icecap.lua +++ b/code/apps/sys-icecap.lua @@ -26,72 +26,41 @@ local function addOnReg(p, f) table.insert(onReg[p], f) end -local function resumeWF(...) - local ok, e = coroutine.resume(...) - if not ok then - e = tostring(e) - neo.emergency(e) - nexus.startDialog(e, "ice") - end - return ok, e -end - nexus = { - createNexusThread = function (f, ...) - local t = coroutine.create(f) - local ok, cbi = resumeWF(t, ...) - if not ok then return end - local early = neo.requestAccess("x.neo.pub.window", theEventHandler) - if early then - local r = onReg["x.neo.pub.window"] - -- r should not be nil here - onReg["x.neo.pub.window"] = nil - for k, v in ipairs(r) do - v() - end - end - return function () - local r = onReg["x.neo.pub.window"] - if not r then return end - for k, v in ipairs(r) do - if v == cbi then - table.remove(r, k) - return - end - end - end - end, - create = function (w, h, t) - local thr = coroutine.running() + create = function (w, h, t, c) local function cb() - coroutine.resume(thr, neo.requestAccess("x.neo.pub.window")) + local e = neo.requestAccess("x.neo.pub.window", theEventHandler) + if e then + if onReg["x.neo.pub.window"] then + neo.emergency("icecap nexus prereg issue") + theEventHandler("k.registration", "x.neo.pub.window") + end + local dw = e(w, h, t) + c(dw) + everestWindows[dw.id] = function (...) + return c(dw, ...) + end + return true + end + end + if not cb() then + addOnReg("x.neo.pub.window", cb) end - addOnReg("x.neo.pub.window", cb) - local everest = coroutine.yield(cb) - local dw = everest(w, h, title) - everestWindows[dw.id] = thr return dw end, + windows = everestWindows, startDialog = function (tx, ti) - local fmt = require("fmttext") - local txl = fmt.fmtText(unicode.safeTextFormat(tx), 40) - fmt = nil - nexus.createNexusThread(function () - local w = nexus.create(40, #txl, ti) - while true do - local ev, a = coroutine.yield() - if ev == "line" then - w.span(1, a, txl[a], 0xFFFFFF, 0) - elseif ev == "close" then - w.close() - return + local txl = require("fmttext").fmtText(unicode.safeTextFormat(tx), 40) + nexus.create(40, #txl, ti, function (w, ev, a) + if ev == "line" then + if not pcall(w.span, 1, a, txl[a], 0xFFFFFF, 0) then + everestWindows[dw.id] = nil end + elseif ev == "close" then + w.close() + everestWindows[dw.id] = nil end end) - end, - close = function (wnd) - wnd.close() - everestWindows[wnd.id] = nil end } @@ -344,10 +313,7 @@ function theEventHandler(...) elseif ev[1] == "x.neo.pub.window" then local v = everestWindows[ev[2]] if v then - resumeWF(v, table.unpack(ev, 3)) - if coroutine.status(v) == "dead" then - everestWindows[ev[2]] = nil - end + v(table.unpack(ev, 3)) end end end diff --git a/code/libs/sys-filedialog.lua b/code/libs/sys-filedialog.lua index a34f463..93275f9 100644 --- a/code/libs/sys-filedialog.lua +++ b/code/libs/sys-filedialog.lua @@ -3,6 +3,7 @@ -- just don't bother with proper indent here return function (event, nexus, retFunc, fs, pkg, mode) + local fmt = require("fmttext") local class = "manage" if mode ~= nil then @@ -13,17 +14,121 @@ if mode ~= nil then end end -local prepareNode +-- State +local w, h, ctrl = 30, 8, false +local l, selection, unknownTx +local node, wnd -local ccb = nil -local function cb(...) - local res, e = pcall(ccb, ...) + +local function prepareNode(n) + node = n + l = node.list() + selection, unknownTx = 1, "" + wnd.setSize(w, h) +end + +local function format(a) + if a <= 1 then + return false, fmt.pad(unicode.safeTextFormat(node.name), w, true, true) + end + local camY = math.max(1, selection - 3) + local idx = a + camY - 2 + local utx = (" "):rep(w) + if node.unknownAvailable and idx == #l + 1 then + utx = "[" .. fmt.pad(unicode.safeTextFormat(unknownTx), w - 6, false, true, true) .. "]" + end + if l[idx] then + utx = "<" .. fmt.pad(unicode.safeTextFormat(l[idx][1]), w - 2, false, true) .. ">" + end + return selection == idx, utx +end + +local function updateLine(a) + local colA, colB = 0xFFFFFF, 0 + local sel, text = format(a) + if sel then + colB, colA = 0xFFFFFF, 0 + end + wnd.span(1, a, text, colA, colB) +end + +local function flush() + for i = 1, h do + updateLine(i) + end +end + +local function key(ka, kc, down) + if kc == 29 then + ctrl = down + end + if not down then return end + if ctrl then + if kc == 200 then + h = math.max(2, h - 1) + elseif kc == 208 then + h = h + 1 + elseif kc == 203 then + w = math.max(6, w - 1) + elseif kc == 205 then + w = w + 1 + else + return + end + wnd.setSize(w, h) + return + elseif (ka == 9) or (kc == 208) then + local lo = selection + selection = selection + 1 + local max = #l + if node.unknownAvailable then + max = max + 1 + end + if selection > max then + selection = 1 + end + elseif kc == 200 then + local lo = selection + selection = selection - 1 + local max = #l + if node.unknownAvailable then + max = max + 1 + end + if selection == 0 then + selection = max + end + elseif ka == 13 then + local aResult, res + if selection ~= #l + 1 then + aResult, res = l[selection][2]() + else + aResult, res = node.selectUnknown(unknownTx) + end + if aResult then + retFunc(res) + nexus.windows[wnd.id] = nil + wnd.close() + else + prepareNode(res) + end + elseif selection == #l + 1 then + if ka == 8 then + unknownTx = unicode.sub(unknownTx, 1, unicode.len(unknownTx) - 1) + elseif ka ~= 0 then + unknownTx = unknownTx .. unicode.char(ka) + end + end + flush() +end + +local function key2(...) + local res, e = pcall(key, ...) if not res then prepareNode({ name = "F.M. Error", list = function () local l = {} - for k, v in ipairs(fmt.fmtText(unicode.safeTextFormat(e), 25)) do + for k, v in ipairs(fmt.fmtText(unicode.safeTextFormat(e), w)) do l[k] = {v, function () return true end} end return l @@ -34,170 +139,44 @@ local function cb(...) end end -local w, h = 30, 8 - -local function prepareNodeI(node) - local l = node.list() - -- Local State - -- Selection. Having this equal to #l + 1 means typing area ('unknown') - local selection = 1 - local unknownTx = "" - -- - local function format(a) - if a <= 1 then - return false, fmt.pad(unicode.safeTextFormat(node.name), w, true, true) - end - local camY = math.max(1, selection - 3) - local idx = a + camY - 2 - local utx = (" "):rep(w) - if node.unknownAvailable and idx == #l + 1 then - utx = "[" .. fmt.pad(unicode.safeTextFormat(unknownTx), w - 6, false, true, true) .. "]" - end - if l[idx] then - utx = "<" .. fmt.pad(unicode.safeTextFormat(l[idx][1]), w - 2, false, true) .. ">" - end - return selection == idx, utx +nexus.create(w, h, class .. " " .. pkg, function (w, ev, a, b, c) + if not wnd then + wnd = w + prepareNode(require("sys-filevfs")(fs, mode)) end - local function updateLine(wnd, a) - local colA, colB = 0xFFFFFF, 0 - local sel, text = format(a) - if sel then - colB, colA = 0xFFFFFF, 0 - end - wnd.span(1, a, text, colA, colB) + if ev == "key" then + key2(a, b, c) end - local function flush(wnd) - for i = 1, h do - updateLine(wnd, i) + if ev == "touch" then + local ns = b + math.max(1, selection - 3) - 2 + local max = #l + if node.unknownAvailable then + max = max + 1 + end + if ns == selection and ((selection ~= #l + 1) or (a <= 4)) then + key2(13, 0, true) + else + selection = math.min(math.max(1, ns), max) + flush() end end - local ctrl = false - local function key(wnd, ka, kc, down) - if kc == 29 then - ctrl = down - end - if not down then return end - if ctrl then - if kc == 200 then - h = math.max(2, h - 1) - elseif kc == 208 then - h = h + 1 - elseif kc == 203 then - w = math.max(6, w - 1) - elseif kc == 205 then - w = w + 1 - else - return - end - wnd.setSize(w, h) - return - end - if (ka == 9) or (kc == 208) then - local lo = selection - selection = selection + 1 - local max = #l - if node.unknownAvailable then - max = max + 1 - end - if selection > max then - selection = 1 - end - flush(wnd) - return - end - if kc == 200 then - local lo = selection - selection = selection - 1 - local max = #l - if node.unknownAvailable then - max = max + 1 - end - if selection == 0 then - selection = max - end - flush(wnd) - return - end - if ka == 13 then - local aResult, res - if selection ~= #l + 1 then - aResult, res = l[selection][2]() - else - aResult, res = node.selectUnknown(unknownTx) - end - if aResult then - retFunc(res) - nexus.close(wnd) - else - prepareNode(res) - end - return - end - if selection == #l + 1 then - if ka == 8 then - unknownTx = unicode.sub(unknownTx, 1, unicode.len(unknownTx) - 1) - flush(wnd) - return - end - if ka ~= 0 then - unknownTx = unknownTx .. unicode.char(ka) - flush(wnd) - end - end + if ev == "line" then + updateLine(a) end - return w, h, function (wnd, evt, a, b, c) - if evt == "key" then - key(wnd, a, b, c) - end - if evt == "touch" then - local ns = b + math.max(1, selection - 3) - 2 - local max = #l - if node.unknownAvailable then - max = max + 1 - end - if ns == selection and ((selection ~= #l + 1) or (a <= 4)) then - key(wnd, 13, 0, true) - else - selection = math.min(math.max(1, ns), max) - flush(wnd) - end - end - if evt == "line" then - updateLine(wnd, a) - end - if evt == "close" then - retFunc(nil) - nexus.close(wnd) - end - end -end - -local text = class .. " " .. pkg -local window - -function prepareNode(node) - local w, h, c = prepareNodeI(node) - ccb = c - window.setSize(w, h) -end - -local closer = nexus.createNexusThread(function () - window = nexus.create(25, 10, text) - prepareNode(require("sys-filevfs")(fs, mode)) - while window do - cb(window, coroutine.yield()) + if ev == "close" then + retFunc(nil) + nexus.windows[wnd.id] = nil + wnd.close() end end) -if not closer then - retFunc() - return -end + return function () retFunc() closer() - if window then - nexus.close(window) - window = nil + if wnd then + nexus.windows[wnd.id] = nil + wnd.close() + wnd = nil end end diff --git a/code/libs/sys-filevfs.lua b/code/libs/sys-filevfs.lua index a658821..3b945e0 100644 --- a/code/libs/sys-filevfs.lua +++ b/code/libs/sys-filevfs.lua @@ -81,17 +81,17 @@ function getFsNode(fs, parent, fsc, path, mode) local t local confirmedDel = false t = { - name = "DIR : " .. va .. path, + name = "DIR: " .. va .. path, list = function () local n = {} n[1] = {"..", function () return nil, parent end} for k, v in ipairs(fsc.list(path)) do - local nm = "[F] " .. v + local nm = "F: " .. v local fp = path .. v if fsc.isDirectory(fp) then - nm = "[D] " .. v + nm = "D: " .. v end n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode) end} end diff --git a/code/libs/sys-secpolicy.lua b/code/libs/sys-secpolicy.lua index d362334..8721c1d 100644 --- a/code/libs/sys-secpolicy.lua +++ b/code/libs/sys-secpolicy.lua @@ -56,31 +56,31 @@ return function (nexus, settings, pkg, pid, perm, rsp, matchesSvc) local buttons = { {"", function (w) rsp(false) - nexus.close(w) + nexus.windows[w.id] = nil + w.close() end}, {"", function (w) if settings then settings.setSetting("perm|" .. pkg .. "|" .. perm, "allow") end rsp(true) - nexus.close(w) + nexus.windows[w.id] = nil + w.close() end}, {"", function (w) rsp(true) - nexus.close(w) + nexus.windows[w.id] = nil + w.close() end} } - nexus.createNexusThread(function () - local window = nexus.create(totalW, #fmt, "security") - local cButton = 0 - local ev, a, b, c - while true do - if not ev then - ev, a, b, c = coroutine.yield() - end + local cButton = 0 + nexus.create(totalW, #fmt, "security", function (window, ev, a, b, c) + while ev do if ev == "line" or ev == "touch" then local cor = b - if ev == "line" then + local iev = ev + ev = nil + if iev == "line" then cor = a if fmt[a] then window.span(1, a, fmt[a], 0xFFFFFF, 0) @@ -89,7 +89,7 @@ return function (nexus, settings, pkg, pid, perm, rsp, matchesSvc) if cor == #fmt then local x = 1 for k, v in ipairs(buttons) do - if ev == "line" then + if iev == "line" then if k ~= cButton + 1 then window.span(x, a, v[1], 0xFFFFFF, 0) else @@ -108,10 +108,10 @@ return function (nexus, settings, pkg, pid, perm, rsp, matchesSvc) end elseif ev == "close" then rsp(false) - nexus.close(window) - return - end - if ev == "key" then + nexus.windows[w.id] = nil + w.close() + ev = nil + elseif ev == "key" then if c and (a == 9 or b == 205) then cButton = (cButton + 1) % #buttons ev = "line"