From 77d123ab1f629de167d79fe5fa730c4d8f809b25 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Mon, 27 Jul 2026 14:02:30 -0400 Subject: [PATCH] feat(appstore): browse cached catalogs offline, drop Wi-Fi after use Also mark Wordle 'present' tiles and keys with an inset ring, since gray shades alone are hard to distinguish on e-ink. --- apps/AppStore/main.lua | 24 ++++++++++++++++++++---- apps/AppStore/manifest.txt | 2 +- apps/Wordle/main.lua | 3 +++ apps/Wordle/manifest.txt | 2 +- catalog.txt | 4 ++-- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/apps/AppStore/main.lua b/apps/AppStore/main.lua index 6968115..2f10355 100644 --- a/apps/AppStore/main.lua +++ b/apps/AppStore/main.lua @@ -412,7 +412,7 @@ local APP_STATE_SUFFIX = { current = " (installed)", update = " (update)" } local function render() if screen == "repositories" then - drawList("Repositories", repositories, function(item) return item.name end) + drawList("Repositories", repositories, function(item) return item.name end, nil, "Refresh") elseif screen == "apps" then drawList("Apps", apps, function(line) local app = catalogEntry(line) @@ -459,6 +459,7 @@ local function startInstall() collectgarbage("collect") if net.wifiStatus() == "connected" then local ok, result = install(detailApp) + net.wifiDisconnect() finishInstall(result) else pendingApp = detailApp @@ -480,15 +481,26 @@ local function deleteApp() finishInstall(ok and (detailApp.id .. " deleted") or tostring(err)) end -local function openRepository() +local function openRepository(forceDownload) detailApp = nil detailMessage = nil currentRepository = repositories[selected] - pendingRepository = currentRepository -- Shed The Stale Catalog Before The Radio - bringing up Wi-Fi allocates tens of KB, and the -- previous repository's entries are dead weight from the moment we leave the list. apps = {} collectgarbage("collect") + + -- Browse Offline - Wi-Fi and TLS cost ~70 KB that stays resident for the whole session, and + -- scrolling a list at that heap level is what aborts the firmware. Serve the cached catalog + -- and bring the radio up only for an explicit refresh or an install. + if not forceDownload and fs.exists(currentRepository.downloadPath) and ensureCatalog() then + selected = 1 + screen = "apps" + needsDraw = true + return + end + + pendingRepository = currentRepository net.wifiConnect() screen = "connecting" needsDraw = true @@ -524,11 +536,13 @@ function draw() local app = pendingApp pendingApp = nil local ok, result = install(app) + net.wifiDisconnect() finishInstall(result) else local repository = pendingRepository pendingRepository = nil local ok, err = loadCatalog(repository) + net.wifiDisconnect() if ok then selected = 1 screen = "apps" @@ -553,7 +567,9 @@ function draw() elseif input.wasPressed("down") and (screen == "apps" or screen == "repositories") then moveSelection(1, screen == "apps" and apps or repositories) elseif input.wasPressed("right") then - if screen == "detail" and installState(detailApp.id, detailApp.manifestHash) ~= "none" then + if screen == "repositories" then + openRepository(true) + elseif screen == "detail" and installState(detailApp.id, detailApp.manifestHash) ~= "none" then detailMessage = nil screen = "confirmDelete" needsDraw = true diff --git a/apps/AppStore/manifest.txt b/apps/AppStore/manifest.txt index 939a8cf..b9d8f0f 100644 --- a/apps/AppStore/manifest.txt +++ b/apps/AppStore/manifest.txt @@ -1,3 +1,3 @@ XTEINK-MANIFEST|1 -main.lua|22282|91eb39358d50a89ac9cc345fe0ef9d84ff595f7a0db60bae84127dac1368f3cc +main.lua|22959|4278fc294944f3b7ef4000ec756668efebc695a89a933aa85fb3eb45a96844c0 repositories.default.txt|108|70e442650788dd8d8632142ef3ff43a4aaee9855da89283facc72a8942e0a7df diff --git a/apps/Wordle/main.lua b/apps/Wordle/main.lua index 158963d..b8955d8 100644 --- a/apps/Wordle/main.lua +++ b/apps/Wordle/main.lua @@ -143,6 +143,8 @@ local function drawTile(letter, status, x, y, size) if status ~= nil then gui.fillRoundedRect(x, y, size, size, 5, fill) end gui.drawRoundedRect(x, y, size, size, 2, 5, COLOR_BLACK) + -- Present Marker - Gray shades alone are hard to tell apart on e-ink, so "in word, wrong spot" also gets an inset ring. + if status == 1 then gui.drawRoundedRect(x + 5, y + 5, size - 10, size - 10, 2, 3, COLOR_BLACK) end if letter ~= "" then centeredText(FONT_NOTOSANS_16, x, y + math.floor(size / 2) - 10, size, letter, textColor, STYLE_BOLD) end @@ -188,6 +190,7 @@ local function drawKeyboard(width, height, top) gui.fillRoundedRect(x, y, keyWidth, keyHeight, 4, fill) gui.drawRoundedRect(x, y, keyWidth, keyHeight, 1, 4, COLOR_BLACK) + if status == 1 then gui.drawRoundedRect(x + 4, y + 4, keyWidth - 8, keyHeight - 8, 1, 3, COLOR_BLACK) end if rowIndex == cursorRow and columnIndex == cursorColumn then gui.drawRoundedRect(x + 2, y + 2, keyWidth - 4, keyHeight - 4, 3, 3, textColor) end diff --git a/apps/Wordle/manifest.txt b/apps/Wordle/manifest.txt index 9bebbcf..ccc4bfd 100644 --- a/apps/Wordle/manifest.txt +++ b/apps/Wordle/manifest.txt @@ -1,3 +1,3 @@ XTEINK-MANIFEST|1 -main.lua|8025|cbdf0cc95761170f0948b76d40d404ce9ae8055c50ae656c7066531228e49a84 +main.lua|8371|df3f7d842dfa2e984644d6d8745f0bb02bfb9aef932c78e942131c10943d50bc words.txt|2814|057281f29400005492e9c891aeda0fbe9a3d3e6060304b71e7083ac02d9b3692 diff --git a/catalog.txt b/catalog.txt index c3d1b2e..1b40eda 100644 --- a/catalog.txt +++ b/catalog.txt @@ -1,6 +1,6 @@ XTEINK-CATALOG|1 2048|Slide and merge tiles to reach 2048|apps/2048/manifest.txt|97|7cc1eee488186698bf294a649fe850164af23e32aaee1cd86754555e282bce04 -AppStore|Install apps from public Xteink repositories|apps/AppStore/manifest.txt|192|1497912a4b9e58e95b4d8b0745a03c98ddea8ef9b47479bb47b5c89635c0b166 +AppStore|Install apps from public Xteink repositories|apps/AppStore/manifest.txt|192|f750574626ff2a5f8a4229ce6627ce98499690455f068443721f4d0e7fcc81c5 BinaryKeyboard|Two-button recursive keyboard experiment|apps/BinaryKeyboard/manifest.txt|97|893867dba0ae2725caca1eb56375c98c4dd00d351134aa129698c51f97e25690 HomeAssistant|Home Assistant status cards|apps/HomeAssistant/manifest.txt|177|b38ca49804444fd383a505ce9c51680ad9b7443950d682ca1b9ef3047bff98a5 -Wordle|Guess the five-letter word in six tries|apps/Wordle/manifest.txt|177|199fafdf0d0f6e77916befc011f6e8466c254867800e1d4a9e67e95a06d0366b +Wordle|Guess the five-letter word in six tries|apps/Wordle/manifest.txt|177|0274df74ba99306f79698ab48c097f9f1d9ac8260f25e39db5b41f90c3f3f6a4