fix app layouts: remove style tags from content fragments, use component classes

This commit is contained in:
2026-01-20 17:40:38 +01:00
parent 4b47611902
commit 82bc0c78fe
25 changed files with 5350 additions and 537 deletions

View File

@@ -0,0 +1,307 @@
-- browser.lua - Web browser functionality
-- Handles URL navigation, tabs, bookmarks, and history
local browser_doc = nil
local tabs = {}
local current_tab_id = 1
local history = {}
local bookmarks = {}
-- Sample page content
local pages = {
["example.com"] = {
title = "Example Domain",
secure = true,
content = [[
<div class="browser-page-title">Example Domain</div>
<div class="browser-page-text">
This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.
</div>
<div class="browser-page-text">
<span class="browser-page-link" onclick="navigateToUrl('iana.org')">More information...</span>
</div>
]]
},
["google.com"] = {
title = "Google",
secure = true,
content = [[
<div style="text-align: center; padding: 60px 20px;">
<div style="font-size: 48px; font-weight: 500; color: #4285F4;">G</div>
<div style="font-size: 48px; font-weight: 500; color: #EA4335;">o</div>
<div style="font-size: 48px; font-weight: 500; color: #FBBC05;">o</div>
<div style="font-size: 48px; font-weight: 500; color: #4285F4;">g</div>
<div style="font-size: 48px; font-weight: 500; color: #34A853;">l</div>
<div style="font-size: 48px; font-weight: 500; color: #EA4335;">e</div>
<div style="margin-top: 32px;">
<input type="text" style="width: 80%; padding: 12px 20px; font-size: 16px; border-radius: 24px; background-color: #f1f3f4; border: none;" placeholder="Search Google"/>
</div>
</div>
]]
},
["mosis.app"] = {
title = "Mosis - Virtual Smartphone for VR",
secure = true,
content = [[
<div class="browser-page-title">Welcome to Mosis</div>
<div class="browser-page-text">
Mosis is a virtual smartphone OS for VR games and applications. Experience a phone-like device inside your virtual reality environment.
</div>
<div style="margin-top: 24px;">
<div class="browser-search-item" onclick="navigateToUrl('mosis.app/apps')">
<div class="browser-search-title">Browse Apps</div>
<div class="browser-search-desc">Discover apps for your virtual phone</div>
</div>
<div class="browser-search-item" onclick="navigateToUrl('mosis.app/developers')">
<div class="browser-search-title">For Developers</div>
<div class="browser-search-desc">Build apps for the Mosis platform</div>
</div>
</div>
]]
},
["default"] = {
title = "Page Not Found",
secure = false,
content = [[
<div style="text-align: center; padding: 60px 20px;">
<div style="font-size: 64px; color: #888888;">:(</div>
<div style="font-size: 24px; color: #333333; margin-top: 24px;">Page Not Found</div>
<div style="font-size: 16px; color: #666666; margin-top: 12px;">The requested page could not be loaded.</div>
</div>
]]
}
}
-- Initialize tabs
local function initTabs()
tabs = {
{id = 1, url = "example.com", title = "Example Domain"}
}
current_tab_id = 1
end
-- Initialize browser
function initBrowser(doc)
print("[Browser] Initializing...")
browser_doc = doc
initTabs()
loadPage(tabs[1].url)
end
-- Get current tab
local function getCurrentTab()
for _, tab in ipairs(tabs) do
if tab.id == current_tab_id then
return tab
end
end
return tabs[1]
end
-- Load a page
function loadPage(url)
if not browser_doc then return end
print("[Browser] Loading: " .. url)
-- Clean URL
url = url:gsub("^https?://", ""):gsub("^www%.", ""):gsub("/$", "")
-- Update current tab
local tab = getCurrentTab()
if tab then
tab.url = url
end
-- Add to history
table.insert(history, 1, {url = url, time = "Just now"})
-- Get page data
local page = pages[url] or pages["default"]
if tab then
tab.title = page.title
end
-- Update URL bar
local url_input = browser_doc:GetElementById("url-input")
if url_input then
url_input.value = url
end
-- Update secure icon
local secure_icon = browser_doc:GetElementById("secure-icon")
if secure_icon then
if page.secure then
secure_icon.inner_rml = "S"
secure_icon.style.color = "#4CAF50"
else
secure_icon.inner_rml = "!"
secure_icon.style.color = "#F44336"
end
end
-- Update page title
local title = browser_doc:GetElementById("page-title")
if title then
title.inner_rml = page.title
end
-- Update content
local content = browser_doc:GetElementById("browser-content")
if content then
content.inner_rml = [[<div class="browser-page">]] .. page.content .. [[</div>]]
end
-- Update tab count
updateTabCount()
end
-- Navigate to URL
function navigateToUrl(url)
loadPage(url)
end
-- Handle URL input
function onUrlSubmit()
if not browser_doc then return end
local input = browser_doc:GetElementById("url-input")
if input then
local url = input.value or ""
if url ~= "" then
loadPage(url)
end
end
end
-- Go back in history
function browserBack()
if #history > 1 then
table.remove(history, 1) -- Remove current page
local prev = history[1]
if prev then
loadPage(prev.url)
end
end
end
-- Go forward (simplified - just reload)
function browserForward()
if showToast then
showToast("No forward history")
end
end
-- Refresh page
function browserRefresh()
local tab = getCurrentTab()
if tab then
loadPage(tab.url)
if showToast then
showToast("Page refreshed")
end
end
end
-- Update tab count display
function updateTabCount()
if not browser_doc then return end
local count = browser_doc:GetElementById("tab-count")
if count then
count.inner_rml = tostring(#tabs)
end
end
-- Open new tab
function newTab()
local new_id = #tabs + 1
table.insert(tabs, {
id = new_id,
url = "mosis.app",
title = "New Tab"
})
current_tab_id = new_id
loadPage("mosis.app")
updateTabCount()
print("[Browser] New tab opened: " .. new_id)
end
-- Show tabs view
function showTabs()
print("[Browser] Show tabs")
if showToast then
showToast(#tabs .. " tab(s) open")
end
end
-- Close current tab
function closeTab()
if #tabs > 1 then
for i, tab in ipairs(tabs) do
if tab.id == current_tab_id then
table.remove(tabs, i)
break
end
end
current_tab_id = tabs[1].id
loadPage(tabs[1].url)
updateTabCount()
else
if showToast then
showToast("Cannot close last tab")
end
end
end
-- Add to bookmarks
function addBookmark()
local tab = getCurrentTab()
if tab then
table.insert(bookmarks, {
url = tab.url,
title = tab.title
})
if showToast then
showToast("Bookmark added")
end
end
end
-- Show bookmarks
function showBookmarks()
print("[Browser] Show bookmarks")
if showToast then
showToast(#bookmarks .. " bookmark(s)")
end
end
-- Show history
function showHistory()
print("[Browser] Show history")
if showToast then
showToast(#history .. " items in history")
end
end
-- Share page
function sharePage()
local tab = getCurrentTab()
if tab then
print("[Browser] Share: " .. tab.url)
if showToast then
showToast("Share: " .. tab.url)
end
end
end
-- Show menu
function showBrowserMenu()
print("[Browser] Show menu")
-- TODO: Show dropdown menu
end
-- Go to home
function browserHome()
loadPage("mosis.app")
end

View File

@@ -6,6 +6,7 @@
<link type="text/rcss" href="../../ui/layout.rcss"/>
<script src="../../scripts/navigation.lua"></script>
<script src="../../scripts/layout.lua"></script>
<script src="browser.lua"></script>
<title>Browser</title>
<style>
.browser-toolbar {
@@ -30,12 +31,17 @@
background-color: rgba(255, 255, 255, 0.1);
}
.browser-nav-btn:active {
background-color: rgba(255, 255, 255, 0.2);
}
.browser-nav-btn img {
width: 28px;
height: 28px;
pointer-events: none;
}
.browser-nav-btn.disabled img {
.browser-nav-btn.disabled {
opacity: 0.3;
}
@@ -46,6 +52,11 @@
padding: 10px 16px;
background-color: #2D2D2D;
border-radius: 20px;
cursor: pointer;
}
.browser-url-bar:hover {
background-color: #3D3D3D;
}
.browser-secure-icon {
@@ -145,12 +156,14 @@
.browser-tab-btn:hover {
color: #FFFFFF;
background-color: rgba(255, 255, 255, 0.05);
}
.browser-tab-btn img {
width: 28px;
height: 28px;
margin-bottom: 4px;
pointer-events: none;
}
.browser-tab-btn span {
@@ -166,7 +179,7 @@
}
</style>
</head>
<body class="app-screen" onload="initLayout(document)" data-model="browser">
<body class="app-screen" onload="initLayout(document); initBrowser(document)" data-model="browser">
<!-- System Status Bar -->
<div class="system-status-bar">
<span id="status-time" class="system-status-time">12:30</span>
@@ -179,66 +192,52 @@
<!-- Browser Toolbar -->
<div class="browser-toolbar">
<div class="browser-nav-btn" onclick="goBack()">
<div class="browser-nav-btn" onclick="browserBack()">
<img src="../../icons/back.tga"/>
</div>
<div class="browser-nav-btn disabled">
<div class="browser-nav-btn" onclick="browserForward()">
<img src="../../icons/forward.tga"/>
</div>
<div class="browser-url-bar">
<span class="browser-secure-icon">S</span>
<input class="browser-url" type="text" value="example.com"/>
<span class="browser-secure-icon" id="secure-icon">S</span>
<input class="browser-url" type="text" value="example.com" id="url-input" onchange="onUrlSubmit()"/>
</div>
<div class="browser-nav-btn">
<div class="browser-nav-btn" onclick="browserRefresh()">
<img src="../../icons/refresh.tga"/>
</div>
<div class="browser-nav-btn">
<div class="browser-nav-btn" onclick="showBrowserMenu()">
<img src="../../icons/more.tga"/>
</div>
</div>
<!-- Browser Content -->
<div class="browser-content">
<div class="browser-content" id="browser-content">
<div class="browser-page">
<div class="browser-page-title">Example Domain</div>
<div class="browser-page-title" id="page-title">Example Domain</div>
<div class="browser-page-text">
This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.
</div>
<div class="browser-page-text">
<span class="browser-page-link">More information...</span>
</div>
<div style="margin-top: 32px; padding-top: 16px; border-top: 1px solid #e0e0e0;">
<div class="browser-page-title" style="font-size: 18px;">Related Links</div>
<div class="browser-search-item">
<div class="browser-search-title">IANA - IANA-managed Reserved Domains</div>
<div class="browser-search-url">www.iana.org > domains > reserved</div>
<div class="browser-search-desc">Certain domains are set aside and unavailable for registration.</div>
</div>
<div class="browser-search-item">
<div class="browser-search-title">RFC 2606 - Reserved Top Level DNS Names</div>
<div class="browser-search-url">tools.ietf.org > html > rfc2606</div>
<div class="browser-search-desc">This document describes domain names reserved for documentation.</div>
</div>
<span class="browser-page-link" onclick="navigateToUrl('iana.org')">More information...</span>
</div>
</div>
</div>
<!-- Bottom Bar -->
<div class="browser-bottom-bar">
<div class="browser-tab-btn" onclick="goHome()">
<div class="browser-tab-btn" onclick="browserHome()">
<img src="../../icons/home.tga"/>
<span>Home</span>
</div>
<div class="browser-tab-btn">
<span class="browser-tabs-indicator">1</span>
<div class="browser-tab-btn" onclick="showTabs()">
<span class="browser-tabs-indicator" id="tab-count">1</span>
<span>Tabs</span>
</div>
<div class="browser-tab-btn">
<div class="browser-tab-btn" onclick="newTab()">
<img src="../../icons/add.tga"/>
<span>New Tab</span>
</div>
<div class="browser-tab-btn">
<div class="browser-tab-btn" onclick="showBrowserMenu()">
<img src="../../icons/menu.tga"/>
<span>Menu</span>
</div>