- Rename test-apps to base-apps with proper manifest.json for each app - Add is_system_app flag to app discovery and Lua API - Fix icon path resolution for /system/icons/ paths - Add layout.lua and layout.rcss for reusable UI components - Update home screen to dynamically load all apps from manifests - Update all app RML files to use layout components - Comprehensive testing framework documentation with JSON action format - Add tests/ directory structure for automated UI testing
201 lines
7.1 KiB
Lua
201 lines
7.1 KiB
Lua
-- home.lua - Home screen dynamic app rendering
|
|
-- Handles system apps and discovered third-party apps
|
|
|
|
-- System apps with their navigation keys and colors
|
|
local system_apps = {
|
|
-- Row 1
|
|
{name = "Phone", icon = "phone", color = "#4CAF50", nav = "dialer"},
|
|
{name = "Messages", icon = "message", color = "#2196F3", nav = "messages"},
|
|
{name = "Contacts", icon = "contacts", color = "#FF9800", nav = "contacts"},
|
|
{name = "Browser", icon = "browser", color = "#F44336", nav = "browser"},
|
|
-- Row 2
|
|
{name = "Gallery", icon = "gallery", color = "#9C27B0", nav = nil},
|
|
{name = "Camera", icon = "camera", color = "#00BCD4", nav = "camera"},
|
|
{name = "Settings", icon = "settings", color = "#607D8B", nav = "settings"},
|
|
{name = "Music", icon = "music", color = "#E91E63", nav = "music"},
|
|
-- Row 3
|
|
{name = "Calendar", icon = "calendar", color = "#3F51B5", nav = nil},
|
|
{name = "Clock", icon = "clock", color = "#009688", nav = nil},
|
|
{name = "Notes", icon = "notes", color = "#795548", nav = nil},
|
|
{name = "Maps", icon = "maps", color = "#FF5722", nav = nil},
|
|
-- Row 4
|
|
{name = "Store", icon = "store", color = "#8BC34A", nav = "store"},
|
|
{name = "Files", icon = "files", color = "#CDDC39", nav = nil},
|
|
{name = "Calculator", icon = "calculator", color = "#FFC107", nav = nil},
|
|
{name = "Weather", icon = "weather", color = "#673AB7", nav = nil},
|
|
}
|
|
|
|
-- State
|
|
local installed_apps = {}
|
|
local home_document = nil -- Store document reference
|
|
|
|
-- Initialize on load (receives document from onload event)
|
|
function initHome(doc)
|
|
print("[Home] Initializing home screen...")
|
|
home_document = doc
|
|
|
|
-- Get installed third-party apps
|
|
if mosis and mosis.apps then
|
|
installed_apps = mosis.apps.getInstalled() or {}
|
|
print("[Home] Found " .. #installed_apps .. " installed apps")
|
|
|
|
-- Filter to only third-party (non-system) apps
|
|
local third_party = {}
|
|
for _, app in ipairs(installed_apps) do
|
|
if not app.is_system_app then
|
|
table.insert(third_party, app)
|
|
print("[Home] Third-party app: " .. app.name .. " (" .. app.package_id .. ")")
|
|
end
|
|
end
|
|
installed_apps = third_party
|
|
else
|
|
print("[Home] Warning: mosis.apps API not available")
|
|
installed_apps = {}
|
|
end
|
|
|
|
-- Render dynamic apps
|
|
renderThirdPartyApps()
|
|
end
|
|
|
|
-- Generate a color based on package_id
|
|
function getAppColor(package_id)
|
|
local colors = {
|
|
"#BB86FC", "#03DAC6", "#FF9800", "#2196F3",
|
|
"#4CAF50", "#F44336", "#E91E63", "#3F51B5",
|
|
"#009688", "#795548", "#FF5722", "#673AB7"
|
|
}
|
|
|
|
-- Simple hash of package_id to pick a color
|
|
local hash = 0
|
|
for i = 1, #package_id do
|
|
hash = hash + package_id:byte(i)
|
|
end
|
|
|
|
return colors[(hash % #colors) + 1]
|
|
end
|
|
|
|
-- Get first letter for placeholder icon
|
|
function getAppInitial(name)
|
|
return name:sub(1, 1):upper()
|
|
end
|
|
|
|
-- Render third-party apps into the grid
|
|
function renderThirdPartyApps()
|
|
-- Use stored document reference
|
|
if not home_document then
|
|
print("[Home] Could not get document reference")
|
|
return
|
|
end
|
|
|
|
local grid = home_document:GetElementById("third-party-apps")
|
|
if not grid then
|
|
print("[Home] third-party-apps container not found")
|
|
return
|
|
end
|
|
|
|
-- Clear existing content
|
|
grid.inner_rml = ""
|
|
|
|
if #installed_apps == 0 then
|
|
print("[Home] No third-party apps to display")
|
|
return
|
|
end
|
|
|
|
-- Build HTML for each app
|
|
local html = ""
|
|
for _, app in ipairs(installed_apps) do
|
|
local color = getAppColor(app.package_id)
|
|
local initial = getAppInitial(app.name)
|
|
local icon_html
|
|
|
|
-- Check if app has an icon
|
|
if app.icon and app.icon ~= "" then
|
|
local icon_path
|
|
-- Check if icon is already a full path (starts with / or contains :/)
|
|
if app.icon:sub(1, 1) == "/" or app.icon:find(":/") then
|
|
-- Already a full path
|
|
icon_path = app.icon
|
|
elseif app.install_path and app.install_path ~= "" then
|
|
-- Relative filename - construct full path from install_path
|
|
icon_path = app.install_path .. "/" .. app.icon
|
|
else
|
|
icon_path = app.icon
|
|
end
|
|
-- Use file:// prefix for absolute paths to prevent RmlUi URL resolution
|
|
local src_path = icon_path
|
|
if icon_path:sub(1, 1) == "/" then
|
|
src_path = "file://" .. icon_path
|
|
end
|
|
-- Use img tag for actual icon
|
|
icon_html = '<img src="' .. src_path .. '" style="width: 48px; height: 48px;"/>'
|
|
print("[Home] Loading icon: " .. src_path)
|
|
else
|
|
-- Fallback to initial letter
|
|
icon_html = '<span style="font-size: 28px; color: #000000;">' .. initial .. '</span>'
|
|
end
|
|
|
|
html = html .. [[
|
|
<div class="app-icon">
|
|
<div class="app-icon-image" style="background-color: ]] .. color .. [[;"
|
|
onclick="launchThirdPartyApp(']] .. app.package_id .. [[')">
|
|
]] .. icon_html .. [[
|
|
</div>
|
|
<span class="app-icon-label">]] .. app.name .. [[</span>
|
|
</div>
|
|
]]
|
|
end
|
|
|
|
grid.inner_rml = html
|
|
print("[Home] Rendered " .. #installed_apps .. " third-party apps")
|
|
end
|
|
|
|
-- Get app info by package_id
|
|
function getAppInfo(package_id)
|
|
for _, app in ipairs(installed_apps) do
|
|
if app.package_id == package_id then
|
|
return app
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- Launch a third-party app
|
|
function launchThirdPartyApp(package_id)
|
|
print("[Home] Launching app: " .. package_id)
|
|
|
|
if mosis and mosis.apps then
|
|
local success = mosis.apps.launch(package_id)
|
|
if success then
|
|
print("[Home] App sandbox started: " .. package_id)
|
|
|
|
-- Get app info for sandbox switching and UI loading
|
|
local app_info = getAppInfo(package_id)
|
|
if app_info and app_info.install_path and app_info.entry_point then
|
|
-- Switch sandbox context to this app (registers timer, fs, json, crypto APIs)
|
|
if switchAppSandbox then
|
|
switchAppSandbox(package_id, app_info.install_path)
|
|
print("[Home] Sandbox context switched to: " .. package_id)
|
|
end
|
|
|
|
-- Now load the app's UI document
|
|
local entry_path = app_info.install_path .. "/" .. app_info.entry_point
|
|
print("[Home] Loading app screen: " .. entry_path)
|
|
local loaded = loadScreen(entry_path)
|
|
if loaded then
|
|
print("[Home] App UI loaded: " .. package_id)
|
|
else
|
|
print("[Home] Failed to load app UI: " .. entry_path)
|
|
end
|
|
else
|
|
print("[Home] App info missing entry point: " .. package_id)
|
|
end
|
|
else
|
|
print("[Home] Failed to launch app: " .. package_id)
|
|
end
|
|
else
|
|
print("[Home] Cannot launch app: mosis.apps not available")
|
|
end
|
|
end
|
|
|
|
-- initHome() is called via onload in home.rml
|