fix app layouts: remove style tags from content fragments, use component classes
This commit is contained in:
307
base-apps/com.mosis.browser/browser.lua
Normal file
307
base-apps/com.mosis.browser/browser.lua
Normal 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
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user