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

@@ -1,11 +1,138 @@
<!-- Browser App Content Fragment -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-header">
<span class="app-header-title">Browser</span>
<!-- URL bar -->
<div class="app-bar" style="padding: 8px 12px;">
<div class="btn-icon" onclick="browserBack()" style="width: 40px; height: 40px;">
<img src="../../icons/back.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="search-bar" style="flex: 1; margin: 0 8px; padding: 8px 16px;">
<span style="color: #4CAF50; margin-right: 8px;">S</span>
<input type="text" id="url-input" style="flex: 1; background-color: transparent; color: #FFFFFF; font-size: 14px;" value="mosis.app"/>
</div>
<div class="btn-icon" onclick="browserRefresh()" style="width: 40px; height: 40px;">
<img src="../../icons/refresh.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="btn-icon" onclick="showTabs()" style="width: 40px; height: 40px;">
<span style="font-size: 14px; color: #FFFFFF; font-weight: bold;">1</span>
</div>
</div>
<div class="app-body">
<span class="placeholder-text">Browser App</span>
<!-- Page content -->
<div style="flex: 1; overflow: auto; background-color: #FFFFFF; padding: 24px;">
<div style="text-align: center;">
<div style="font-size: 48px; font-weight: bold; color: #BB86FC; margin-bottom: 24px;">Mosis</div>
<div class="search-bar" style="margin-bottom: 32px; background-color: #f1f3f4;">
<input type="text" style="flex: 1; background-color: transparent; color: #333333; font-size: 16px; text-align: center;" placeholder="Search or enter URL"/>
</div>
<div style="display: flex; flex-wrap: wrap; justify-content: center; gap: 16px;">
<div onclick="navigateTo('google.com')" style="cursor: pointer; width: 80px; display: flex; flex-direction: column; align-items: center;">
<div style="width: 48px; height: 48px; border-radius: 8px; background-color: #4285F4; display: flex; align-items: center; justify-content: center; color: #FFFFFF; font-size: 20px; margin-bottom: 8px;">G</div>
<span style="font-size: 12px; color: #666666;">Google</span>
</div>
<div onclick="navigateTo('youtube.com')" style="cursor: pointer; width: 80px; display: flex; flex-direction: column; align-items: center;">
<div style="width: 48px; height: 48px; border-radius: 8px; background-color: #FF0000; display: flex; align-items: center; justify-content: center; color: #FFFFFF; font-size: 20px; margin-bottom: 8px;">Y</div>
<span style="font-size: 12px; color: #666666;">YouTube</span>
</div>
<div onclick="navigateTo('github.com')" style="cursor: pointer; width: 80px; display: flex; flex-direction: column; align-items: center;">
<div style="width: 48px; height: 48px; border-radius: 8px; background-color: #333333; display: flex; align-items: center; justify-content: center; color: #FFFFFF; font-size: 20px; margin-bottom: 8px;">G</div>
<span style="font-size: 12px; color: #666666;">GitHub</span>
</div>
<div onclick="navigateTo('reddit.com')" style="cursor: pointer; width: 80px; display: flex; flex-direction: column; align-items: center;">
<div style="width: 48px; height: 48px; border-radius: 8px; background-color: #FF4500; display: flex; align-items: center; justify-content: center; color: #FFFFFF; font-size: 20px; margin-bottom: 8px;">R</div>
<span style="font-size: 12px; color: #666666;">Reddit</span>
</div>
</div>
</div>
</div>
<!-- Bottom bar -->
<div class="bottom-nav">
<div class="bottom-nav-item" onclick="browserBack()">
<img src="../../icons/back.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="bottom-nav-item" onclick="browserForward()">
<img src="../../icons/forward.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="bottom-nav-item" onclick="browserHome()">
<img src="../../icons/home.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="bottom-nav-item" onclick="addBookmark()">
<img src="../../icons/star.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="bottom-nav-item" onclick="showBrowserMenu()">
<img src="../../icons/menu.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
</div>
<script>
local current_url = "mosis.app"
function navigateTo(url)
print("[Browser] Navigating to: " .. url)
current_url = url
local doc = shell_document
if doc then
local url_input = doc:GetElementById("url-input")
if url_input then
url_input.value = url
end
end
if showToast then
showToast("Loading " .. url)
end
end
function browserBack()
print("[Browser] Back")
if showToast then
showToast("Back")
end
end
function browserForward()
print("[Browser] Forward")
if showToast then
showToast("No forward history")
end
end
function browserRefresh()
print("[Browser] Refresh")
if showToast then
showToast("Page refreshed")
end
end
function browserHome()
print("[Browser] Home")
navigateTo("mosis.app")
end
function showTabs()
print("[Browser] Show tabs")
if showToast then
showToast("1 tab open")
end
end
function addBookmark()
print("[Browser] Add bookmark")
if showToast then
showToast("Bookmark added")
end
end
function showBrowserMenu()
print("[Browser] Menu")
if showToast then
showToast("Browser menu")
end
end
print("[Browser] Content loaded")
</script>

View File

@@ -1,44 +1,281 @@
<!-- Camera App Content Fragment -->
<!-- Loaded into shell's #app-container -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from shell.rml -->
<div class="camera-content">
<!-- Top Bar -->
<div class="camera-top-bar">
<div class="camera-btn" onclick="showToast('Flash: Auto')">
<img src="../../icons/flash.tga"/>
<div style="display: flex; gap: 12px;">
<div class="camera-btn" id="flash-btn" onclick="toggleFlash()">
<img src="../../icons/flash.tga" style="width: 24px; height: 24px;"/>
</div>
<div class="camera-btn" onclick="toggleTimer()">
<img src="../../icons/timer.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="camera-btn">
<img src="../../icons/timer.tga"/>
</div>
<div class="camera-btn" onclick="showToast('Settings')">
<img src="../../icons/settings.tga"/>
<span id="flash-indicator" style="font-size: 12px; color: #FFFFFF; background-color: rgba(0, 0, 0, 0.4); padding: 6px 12px; border-radius: 16px;">Flash: Auto</span>
<div class="camera-btn" onclick="openCameraSettings()">
<img src="../../icons/settings.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<!-- Recording Indicator -->
<div id="recording-indicator" style="position: absolute; top: 80px; left: 50%; display: none; align-items: center; gap: 8px; background-color: rgba(0, 0, 0, 0.6); padding: 8px 16px; border-radius: 20px;">
<div style="width: 12px; height: 12px; border-radius: 6px; background-color: #F44336;"></div>
<span id="recording-time" style="font-size: 14px; color: #FFFFFF; font-weight: bold;">00:00</span>
</div>
<!-- Viewfinder -->
<div class="viewfinder-container">
<div class="viewfinder">
<span class="viewfinder-text">Camera Preview</span>
<div class="viewfinder-container" onclick="tapToFocus()">
<div class="viewfinder" id="viewfinder">
<span style="font-size: 64px; color: #444444; margin-bottom: 16px;">C</span>
<span style="color: #666666; font-size: 18px;">Camera Preview</span>
<span style="font-size: 14px; color: #555555; margin-top: 8px;">Tap to focus</span>
</div>
<div class="focus-indicator"></div>
<div id="focus-indicator" style="position: absolute; width: 80px; height: 80px; border-radius: 8px; opacity: 0;"></div>
</div>
<!-- Zoom Controls -->
<div style="position: absolute; bottom: 180px; left: 50%; display: flex; gap: 16px;">
<div onclick="setZoom(0.5)" style="width: 40px; height: 40px; border-radius: 20px; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; color: #FFFFFF; font-size: 12px; font-weight: bold; cursor: pointer;">0.5x</div>
<div id="zoom-1x" onclick="setZoom(1)" style="width: 40px; height: 40px; border-radius: 20px; background-color: #FFFFFF; display: flex; align-items: center; justify-content: center; color: #000000; font-size: 12px; font-weight: bold; cursor: pointer;">1x</div>
<div onclick="setZoom(2)" style="width: 40px; height: 40px; border-radius: 20px; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; color: #FFFFFF; font-size: 12px; font-weight: bold; cursor: pointer;">2x</div>
</div>
<!-- Mode Selector -->
<div class="mode-selector">
<span class="mode-item">Video</span>
<span class="mode-item active">Photo</span>
<span class="mode-item">Portrait</span>
<div class="camera-mode-selector">
<span class="camera-mode" id="mode-night" onclick="switchMode('night')">Night</span>
<span class="camera-mode" id="mode-portrait" onclick="switchMode('portrait')">Portrait</span>
<span class="camera-mode active" id="mode-photo" onclick="switchMode('photo')">Photo</span>
<span class="camera-mode" id="mode-video" onclick="switchMode('video')">Video</span>
</div>
<!-- Bottom Controls -->
<div class="camera-bottom-bar">
<div class="gallery-preview"></div>
<div class="shutter-btn" onclick="showToast('Photo captured!', 'success')">
<div class="shutter-btn-inner"></div>
<div class="camera-gallery-preview" onclick="openGallery()"></div>
<div class="camera-shutter-btn" id="shutter-btn" onclick="capture()">
<div id="shutter-inner" class="camera-shutter-inner"></div>
</div>
<div class="switch-camera-btn" onclick="showToast('Switched camera')">
<img src="../../icons/switch-camera.tga"/>
<div class="camera-switch-btn" onclick="switchCamera()">
<img src="../../icons/switch-camera.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
</div>
<script>
local current_mode = "photo"
local flash_mode = "auto"
local timer_mode = "off"
local is_front = false
local is_recording = false
local record_time = 0
local record_timer = nil
local zoom_level = 1
local function getDoc()
return shell_document
end
function switchMode(mode)
current_mode = mode
local doc = getDoc()
if not doc then return end
local modes = {"night", "portrait", "photo", "video"}
for _, m in ipairs(modes) do
local el = doc:GetElementById("mode-" .. m)
if el then
el:SetClass("active", m == mode)
end
end
local inner = doc:GetElementById("shutter-inner")
if inner then
if mode == "video" then
inner:SetClass("camera-shutter-inner", false)
inner:SetClass("camera-shutter-video", true)
else
inner:SetClass("camera-shutter-video", false)
inner:SetClass("camera-shutter-inner", true)
end
end
print("[Camera] Mode: " .. mode)
if showToast then
showToast(mode:sub(1,1):upper() .. mode:sub(2) .. " mode")
end
end
function toggleFlash()
if flash_mode == "auto" then
flash_mode = "on"
elseif flash_mode == "on" then
flash_mode = "off"
else
flash_mode = "auto"
end
local doc = getDoc()
if doc then
local indicator = doc:GetElementById("flash-indicator")
if indicator then
indicator.inner_rml = "Flash: " .. flash_mode:sub(1,1):upper() .. flash_mode:sub(2)
end
end
print("[Camera] Flash: " .. flash_mode)
end
function toggleTimer()
if timer_mode == "off" then
timer_mode = "3s"
elseif timer_mode == "3s" then
timer_mode = "10s"
else
timer_mode = "off"
end
print("[Camera] Timer: " .. timer_mode)
if showToast then
showToast("Timer: " .. timer_mode)
end
end
function setZoom(level)
zoom_level = level
print("[Camera] Zoom: " .. level .. "x")
if showToast then
showToast(level .. "x zoom")
end
end
function switchCamera()
is_front = not is_front
local doc = getDoc()
if doc then
local vf = doc:GetElementById("viewfinder")
if vf then
if is_front then
vf.inner_rml = [[
<span style="font-size: 64px; color: #444444; margin-bottom: 16px;">F</span>
<span style="color: #666666; font-size: 18px;">Front Camera</span>
<span style="font-size: 14px; color: #555555; margin-top: 8px;">Tap to focus</span>
]]
else
vf.inner_rml = [[
<span style="font-size: 64px; color: #444444; margin-bottom: 16px;">C</span>
<span style="color: #666666; font-size: 18px;">Camera Preview</span>
<span style="font-size: 14px; color: #555555; margin-top: 8px;">Tap to focus</span>
]]
end
end
end
print("[Camera] Switched to " .. (is_front and "front" or "back") .. " camera")
if showToast then
showToast(is_front and "Front camera" or "Back camera")
end
end
function capture()
if current_mode == "video" then
if is_recording then
stopRecording()
else
startRecording()
end
else
takePhoto()
end
end
function takePhoto()
print("[Camera] Photo captured!")
if showToast then
showToast("Photo saved")
end
end
function startRecording()
is_recording = true
record_time = 0
local doc = getDoc()
if doc then
local indicator = doc:GetElementById("recording-indicator")
if indicator then
indicator.style.display = "flex"
end
local inner = doc:GetElementById("shutter-inner")
if inner then
inner:SetClass("camera-shutter-video", false)
inner:SetClass("camera-shutter-stop", true)
end
end
if setInterval then
record_timer = setInterval(function()
record_time = record_time + 1
local mins = math.floor(record_time / 60)
local secs = record_time % 60
local doc = getDoc()
if doc then
local time_el = doc:GetElementById("recording-time")
if time_el then
time_el.inner_rml = string.format("%02d:%02d", mins, secs)
end
end
end, 1000)
end
print("[Camera] Recording started")
end
function stopRecording()
is_recording = false
if record_timer and clearInterval then
clearInterval(record_timer)
record_timer = nil
end
local doc = getDoc()
if doc then
local indicator = doc:GetElementById("recording-indicator")
if indicator then
indicator.style.display = "none"
end
local inner = doc:GetElementById("shutter-inner")
if inner then
inner:SetClass("camera-shutter-stop", false)
inner:SetClass("camera-shutter-video", true)
end
end
local mins = math.floor(record_time / 60)
local secs = record_time % 60
print("[Camera] Recording stopped: " .. string.format("%02d:%02d", mins, secs))
if showToast then
showToast(string.format("Video saved (%02d:%02d)", mins, secs))
end
end
function tapToFocus()
print("[Camera] Tap to focus")
end
function openGallery()
print("[Camera] Opening gallery")
if showToast then
showToast("Gallery")
end
end
function openCameraSettings()
print("[Camera] Camera settings")
if showToast then
showToast("Camera settings")
end
end
print("[Camera] Content loaded")
</script>

View File

@@ -1,11 +1,143 @@
<!-- Contacts App Content Fragment -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-header">
<span class="app-header-title">Contacts</span>
<div class="app-bar">
<span class="app-bar-title">Contacts</span>
</div>
<div class="app-body">
<span class="placeholder-text">Contacts App</span>
<div class="search-bar">
<img src="../../icons/search.tga" style="width: 24px; height: 24px; margin-right: 12px; opacity: 0.6;"/>
<span class="search-input">Search contacts</span>
</div>
<div class="list" style="flex: 1; overflow: auto;">
<div class="list-header">A</div>
<div class="list-item" onclick="openContact('Alice Johnson')">
<div class="list-item-avatar" style="background-color: #4CAF50;">A</div>
<div class="list-item-content">
<span class="list-item-title">Alice Johnson</span>
<span class="list-item-subtitle">+1 555-0101</span>
</div>
<div class="btn-icon" onclick="callContact('Alice Johnson'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">B</div>
<div class="list-item" onclick="openContact('Bob Williams')">
<div class="list-item-avatar" style="background-color: #2196F3;">B</div>
<div class="list-item-content">
<span class="list-item-title">Bob Williams</span>
<span class="list-item-subtitle">+1 555-0102</span>
</div>
<div class="btn-icon" onclick="callContact('Bob Williams'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">C</div>
<div class="list-item" onclick="openContact('Carol Davis')">
<div class="list-item-avatar" style="background-color: #9C27B0;">C</div>
<div class="list-item-content">
<span class="list-item-title">Carol Davis</span>
<span class="list-item-subtitle">+1 555-0103</span>
</div>
<div class="btn-icon" onclick="callContact('Carol Davis'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">D</div>
<div class="list-item" onclick="openContact('David Miller')">
<div class="list-item-avatar" style="background-color: #FF9800;">D</div>
<div class="list-item-content">
<span class="list-item-title">David Miller</span>
<span class="list-item-subtitle">+1 555-0104</span>
</div>
<div class="btn-icon" onclick="callContact('David Miller'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">E</div>
<div class="list-item" onclick="openContact('Emma Wilson')">
<div class="list-item-avatar" style="background-color: #E91E63;">E</div>
<div class="list-item-content">
<span class="list-item-title">Emma Wilson</span>
<span class="list-item-subtitle">+1 555-0105</span>
</div>
<div class="btn-icon" onclick="callContact('Emma Wilson'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">J</div>
<div class="list-item" onclick="openContact('John Smith')">
<div class="list-item-avatar" style="background-color: #3F51B5;">J</div>
<div class="list-item-content">
<span class="list-item-title">John Smith</span>
<span class="list-item-subtitle">+1 555-0109</span>
</div>
<div class="btn-icon" onclick="callContact('John Smith'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">M</div>
<div class="list-item" onclick="openContact('Mom')">
<div class="list-item-avatar" style="background-color: #E91E63;">M</div>
<div class="list-item-content">
<span class="list-item-title">Mom</span>
<span class="list-item-subtitle">+1 555-0110</span>
</div>
<div class="btn-icon" onclick="callContact('Mom'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
<div class="list-header">S</div>
<div class="list-item" onclick="openContact('Sarah')">
<div class="list-item-avatar" style="background-color: #9C27B0;">S</div>
<div class="list-item-content">
<span class="list-item-title">Sarah</span>
<span class="list-item-subtitle">+1 555-0111</span>
</div>
<div class="btn-icon" onclick="callContact('Sarah'); event.stopPropagation();">
<img src="../../icons/phone.tga" style="width: 24px; height: 24px;"/>
</div>
</div>
</div>
<div class="btn-fab" onclick="addContact()">
<img src="../../icons/add.tga" style="width: 32px; height: 32px;"/>
</div>
</div>
<script>
function openContact(name)
print("[Contacts] Opening contact: " .. name)
if showToast then
showToast("Contact: " .. name)
end
end
function callContact(name)
print("[Contacts] Calling: " .. name)
if showToast then
showToast("Calling " .. name .. "...")
end
if shellNavigateTo then
shellNavigateTo("calling")
end
end
function addContact()
print("[Contacts] Add new contact")
if showToast then
showToast("Add new contact")
end
end
print("[Contacts] Content loaded")
</script>

View File

@@ -0,0 +1,468 @@
<!-- Calling Screen Content Fragment -->
<!-- In-call interface with controls -->
<style>
.calling-content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
}
.calling-info {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.calling-avatar {
width: 120px;
height: 120px;
border-radius: 60px;
background-color: #BB86FC;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
color: #FFFFFF;
font-weight: 500;
margin-bottom: 24px;
}
.calling-name {
font-size: 32px;
color: #FFFFFF;
font-weight: 500;
margin-bottom: 8px;
}
.calling-status {
font-size: 18px;
color: #B0B0B0;
margin-bottom: 8px;
}
.calling-timer {
font-size: 24px;
color: #FFFFFF;
font-weight: 300;
}
/* Call controls */
.call-controls {
padding: 32px 24px 48px;
}
.controls-row {
display: flex;
justify-content: center;
gap: 32px;
margin-bottom: 32px;
}
.control-btn {
width: 64px;
height: 64px;
border-radius: 32px;
background-color: rgba(255, 255, 255, 0.15);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
}
.control-btn:hover {
background-color: rgba(255, 255, 255, 0.25);
}
.control-btn.active {
background-color: #FFFFFF;
}
.control-btn.active img {
filter: invert(1);
}
.control-btn img {
width: 28px;
height: 28px;
}
.control-label {
font-size: 12px;
color: #FFFFFF;
margin-top: 8px;
text-align: center;
}
.control-btn.active .control-label {
color: #000000;
}
/* End call button */
.end-call-row {
display: flex;
justify-content: center;
}
.end-call-btn {
width: 72px;
height: 72px;
border-radius: 36px;
background-color: #F44336;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.end-call-btn:hover {
background-color: #E53935;
}
.end-call-btn img {
width: 36px;
height: 36px;
transform: rotate(135deg);
}
/* Dialpad overlay */
.dialpad-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: #1a1a1a;
padding: 24px;
border-radius: 24px 24px 0 0;
display: none;
}
.dialpad-overlay.visible {
display: block;
}
.dialpad-row {
display: flex;
justify-content: center;
gap: 24px;
margin-bottom: 16px;
}
.dialpad-key {
width: 64px;
height: 64px;
border-radius: 32px;
background-color: #2d2d2d;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
}
.dialpad-key:hover {
background-color: #3d3d3d;
}
.dialpad-digit {
font-size: 24px;
color: #FFFFFF;
}
.dialpad-letters {
font-size: 10px;
color: #888888;
}
.dialpad-close {
text-align: center;
padding: 16px;
color: #BB86FC;
font-size: 16px;
cursor: pointer;
}
</style>
<div class="calling-content">
<div class="calling-info">
<div id="calling-avatar" class="calling-avatar">J</div>
<div id="calling-name" class="calling-name">John Smith</div>
<div id="calling-status" class="calling-status">Calling...</div>
<div id="calling-timer" class="calling-timer"></div>
</div>
<div class="call-controls">
<div class="controls-row">
<div class="control-btn" id="btn-mute" onclick="toggleMute()">
<img src="../../icons/mic.tga"/>
<span class="control-label">Mute</span>
</div>
<div class="control-btn" id="btn-keypad" onclick="toggleKeypad()">
<img src="../../icons/keypad.tga"/>
<span class="control-label">Keypad</span>
</div>
<div class="control-btn" id="btn-speaker" onclick="toggleSpeaker()">
<img src="../../icons/speaker.tga"/>
<span class="control-label">Speaker</span>
</div>
</div>
<div class="controls-row">
<div class="control-btn" id="btn-add" onclick="addCall()">
<img src="../../icons/add.tga"/>
<span class="control-label">Add call</span>
</div>
<div class="control-btn" id="btn-hold" onclick="toggleHold()">
<img src="../../icons/pause.tga"/>
<span class="control-label">Hold</span>
</div>
<div class="control-btn" id="btn-video" onclick="toggleVideo()">
<img src="../../icons/camera.tga"/>
<span class="control-label">Video</span>
</div>
</div>
<div class="end-call-row">
<div class="end-call-btn" onclick="endCall()">
<img src="../../icons/phone.tga"/>
</div>
</div>
</div>
<!-- Dialpad overlay -->
<div id="dialpad-overlay" class="dialpad-overlay">
<div class="dialpad-row">
<div class="dialpad-key" onclick="dialDTMF('1')">
<span class="dialpad-digit">1</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('2')">
<span class="dialpad-digit">2</span>
<span class="dialpad-letters">ABC</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('3')">
<span class="dialpad-digit">3</span>
<span class="dialpad-letters">DEF</span>
</div>
</div>
<div class="dialpad-row">
<div class="dialpad-key" onclick="dialDTMF('4')">
<span class="dialpad-digit">4</span>
<span class="dialpad-letters">GHI</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('5')">
<span class="dialpad-digit">5</span>
<span class="dialpad-letters">JKL</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('6')">
<span class="dialpad-digit">6</span>
<span class="dialpad-letters">MNO</span>
</div>
</div>
<div class="dialpad-row">
<div class="dialpad-key" onclick="dialDTMF('7')">
<span class="dialpad-digit">7</span>
<span class="dialpad-letters">PQRS</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('8')">
<span class="dialpad-digit">8</span>
<span class="dialpad-letters">TUV</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('9')">
<span class="dialpad-digit">9</span>
<span class="dialpad-letters">WXYZ</span>
</div>
</div>
<div class="dialpad-row">
<div class="dialpad-key" onclick="dialDTMF('*')">
<span class="dialpad-digit">*</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('0')">
<span class="dialpad-digit">0</span>
<span class="dialpad-letters">+</span>
</div>
<div class="dialpad-key" onclick="dialDTMF('#')">
<span class="dialpad-digit">#</span>
</div>
</div>
<div class="dialpad-close" onclick="toggleKeypad()">Hide</div>
</div>
</div>
<script>
-- Calling state
local call_state = {
is_muted = false,
is_speaker = false,
is_hold = false,
is_connected = false,
call_duration = 0,
keypad_visible = false
}
local timer_id = nil
local function getDoc()
return shell_document
end
-- Simulate call connection
local function simulateConnection()
if setTimeout then
setTimeout(function()
call_state.is_connected = true
local doc = getDoc()
if doc then
local status = doc:GetElementById("calling-status")
if status then
status.inner_rml = "Connected"
end
end
startCallTimer()
end, 2000)
end
end
-- Start call timer
function startCallTimer()
if setInterval then
timer_id = setInterval(function()
call_state.call_duration = call_state.call_duration + 1
updateTimerDisplay()
end, 1000)
end
end
-- Update timer display
function updateTimerDisplay()
local doc = getDoc()
if not doc then return end
local timer = doc:GetElementById("calling-timer")
if timer then
local mins = math.floor(call_state.call_duration / 60)
local secs = call_state.call_duration % 60
timer.inner_rml = string.format("%02d:%02d", mins, secs)
end
end
-- Toggle mute
function toggleMute()
call_state.is_muted = not call_state.is_muted
local doc = getDoc()
if doc then
local btn = doc:GetElementById("btn-mute")
if btn then
btn:SetClass("active", call_state.is_muted)
end
end
if showToast then
showToast(call_state.is_muted and "Muted" or "Unmuted")
end
print("[Calling] Mute: " .. tostring(call_state.is_muted))
end
-- Toggle speaker
function toggleSpeaker()
call_state.is_speaker = not call_state.is_speaker
local doc = getDoc()
if doc then
local btn = doc:GetElementById("btn-speaker")
if btn then
btn:SetClass("active", call_state.is_speaker)
end
end
if showToast then
showToast(call_state.is_speaker and "Speaker on" or "Speaker off")
end
print("[Calling] Speaker: " .. tostring(call_state.is_speaker))
end
-- Toggle hold
function toggleHold()
call_state.is_hold = not call_state.is_hold
local doc = getDoc()
if doc then
local btn = doc:GetElementById("btn-hold")
if btn then
btn:SetClass("active", call_state.is_hold)
end
local status = doc:GetElementById("calling-status")
if status then
if call_state.is_hold then
status.inner_rml = "On Hold"
elseif call_state.is_connected then
status.inner_rml = "Connected"
end
end
end
if showToast then
showToast(call_state.is_hold and "Call on hold" or "Call resumed")
end
print("[Calling] Hold: " .. tostring(call_state.is_hold))
end
-- Toggle keypad
function toggleKeypad()
call_state.keypad_visible = not call_state.keypad_visible
local doc = getDoc()
if doc then
local overlay = doc:GetElementById("dialpad-overlay")
if overlay then
overlay:SetClass("visible", call_state.keypad_visible)
end
end
print("[Calling] Keypad: " .. tostring(call_state.keypad_visible))
end
-- Dial DTMF tone
function dialDTMF(digit)
print("[Calling] DTMF: " .. digit)
if showToast then
showToast("DTMF: " .. digit)
end
end
-- Add call
function addCall()
if showToast then
showToast("Add call not available")
end
end
-- Toggle video
function toggleVideo()
if showToast then
showToast("Video call not available")
end
end
-- End call
function endCall()
print("[Calling] Ending call")
-- Stop timer
if timer_id and clearInterval then
clearInterval(timer_id)
timer_id = nil
end
if showToast then
local mins = math.floor(call_state.call_duration / 60)
local secs = call_state.call_duration % 60
showToast(string.format("Call ended (%02d:%02d)", mins, secs))
end
-- Navigate back
if shellGoBack then
shellGoBack()
end
end
-- Initialize on load
simulateConnection()
print("[Calling] Content loaded")
</script>

View File

@@ -1,11 +1,261 @@
<!-- Dialer App Content Fragment -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-header">
<span class="app-header-title">Phone</span>
<!-- Tabs -->
<div class="bottom-nav" style="height: 56px; position: relative; top: 0;">
<div id="tab-keypad" class="bottom-nav-item active" onclick="switchDialerTab('keypad')">
<span style="font-size: 14px; font-weight: 600;">Keypad</span>
</div>
<div id="tab-recent" class="bottom-nav-item" onclick="switchDialerTab('recent')">
<span style="font-size: 14px; font-weight: 600;">Recent</span>
</div>
<div id="tab-contacts" class="bottom-nav-item" onclick="switchDialerTab('contacts')">
<span style="font-size: 14px; font-weight: 600;">Contacts</span>
</div>
</div>
<div class="app-body">
<span class="placeholder-text">Dialer App</span>
<!-- Keypad View -->
<div id="view-keypad" style="flex: 1; display: flex; flex-direction: column;">
<div class="dial-display" id="dialer-number"></div>
<div class="dial-pad">
<div class="dial-key" onclick="dialDigit('1')">
<span class="dial-key-number">1</span>
<span class="dial-key-letters"></span>
</div>
<div class="dial-key" onclick="dialDigit('2')">
<span class="dial-key-number">2</span>
<span class="dial-key-letters">ABC</span>
</div>
<div class="dial-key" onclick="dialDigit('3')">
<span class="dial-key-number">3</span>
<span class="dial-key-letters">DEF</span>
</div>
<div class="dial-key" onclick="dialDigit('4')">
<span class="dial-key-number">4</span>
<span class="dial-key-letters">GHI</span>
</div>
<div class="dial-key" onclick="dialDigit('5')">
<span class="dial-key-number">5</span>
<span class="dial-key-letters">JKL</span>
</div>
<div class="dial-key" onclick="dialDigit('6')">
<span class="dial-key-number">6</span>
<span class="dial-key-letters">MNO</span>
</div>
<div class="dial-key" onclick="dialDigit('7')">
<span class="dial-key-number">7</span>
<span class="dial-key-letters">PQRS</span>
</div>
<div class="dial-key" onclick="dialDigit('8')">
<span class="dial-key-number">8</span>
<span class="dial-key-letters">TUV</span>
</div>
<div class="dial-key" onclick="dialDigit('9')">
<span class="dial-key-number">9</span>
<span class="dial-key-letters">WXYZ</span>
</div>
<div class="dial-key" onclick="dialDigit('*')">
<span class="dial-key-number">*</span>
<span class="dial-key-letters"></span>
</div>
<div class="dial-key" onclick="dialDigit('0')">
<span class="dial-key-number">0</span>
<span class="dial-key-letters">+</span>
</div>
<div class="dial-key" onclick="dialDigit('#')">
<span class="dial-key-number">#</span>
<span class="dial-key-letters"></span>
</div>
</div>
<div class="dial-actions">
<div class="btn-icon" onclick="openVideoCall()">
<img src="../../icons/camera.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="dial-call-btn" onclick="makeCall()">
<img src="../../icons/phone.tga" style="width: 36px; height: 36px;"/>
</div>
<div class="btn-icon" onclick="deleteDigit()">
<img src="../../icons/back.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
</div>
<!-- Recent Calls View -->
<div id="view-recent" style="flex: 1; overflow: auto; display: none;">
<div class="list">
<div class="list-item" onclick="callContact('Mom')">
<div class="list-item-avatar" style="background-color: #E91E63;">M</div>
<div class="list-item-content">
<span class="list-item-title">Mom</span>
<span class="list-item-subtitle" style="color: #4CAF50;">Outgoing - 5 min</span>
</div>
<span style="font-size: 14px; color: #888888;">10:30 AM</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="callContact('John Smith')">
<div class="list-item-avatar" style="background-color: #2196F3;">J</div>
<div class="list-item-content">
<span class="list-item-title">John Smith</span>
<span class="list-item-subtitle" style="color: #F44336;">Missed</span>
</div>
<span style="font-size: 14px; color: #888888;">Yesterday</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="callContact('Work')">
<div class="list-item-avatar" style="background-color: #FF9800;">W</div>
<div class="list-item-content">
<span class="list-item-title">Work</span>
<span class="list-item-subtitle">Incoming - 12 min</span>
</div>
<span style="font-size: 14px; color: #888888;">Yesterday</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="callContact('Sarah')">
<div class="list-item-avatar" style="background-color: #9C27B0;">S</div>
<div class="list-item-content">
<span class="list-item-title">Sarah</span>
<span class="list-item-subtitle" style="color: #4CAF50;">Outgoing - 23 min</span>
</div>
<span style="font-size: 14px; color: #888888;">Monday</span>
</div>
</div>
</div>
<!-- Contacts View -->
<div id="view-contacts" style="flex: 1; overflow: auto; display: none;">
<div class="search-bar">
<img src="../../icons/search.tga" style="width: 24px; height: 24px; margin-right: 12px; opacity: 0.6;"/>
<span style="color: #B3B3B3;">Search contacts</span>
</div>
<div class="list">
<div class="list-item" onclick="callContact('Alice Johnson')">
<div class="list-item-avatar" style="background-color: #4CAF50;">A</div>
<span class="list-item-title">Alice Johnson</span>
</div>
<div class="list-item" onclick="callContact('Bob Williams')">
<div class="list-item-avatar" style="background-color: #2196F3;">B</div>
<span class="list-item-title">Bob Williams</span>
</div>
<div class="list-item" onclick="callContact('Carol Davis')">
<div class="list-item-avatar" style="background-color: #9C27B0;">C</div>
<span class="list-item-title">Carol Davis</span>
</div>
<div class="list-item" onclick="callContact('David Miller')">
<div class="list-item-avatar" style="background-color: #FF9800;">D</div>
<span class="list-item-title">David Miller</span>
</div>
<div class="list-item" onclick="callContact('Emma Wilson')">
<div class="list-item-avatar" style="background-color: #E91E63;">E</div>
<span class="list-item-title">Emma Wilson</span>
</div>
</div>
</div>
</div>
<script>
local dialed_number = ""
local current_tab = "keypad"
local function getDoc()
return shell_document
end
function switchDialerTab(tab)
current_tab = tab
local doc = getDoc()
if not doc then return end
local tabs = {"keypad", "recent", "contacts"}
for _, t in ipairs(tabs) do
local tab_el = doc:GetElementById("tab-" .. t)
local view_el = doc:GetElementById("view-" .. t)
if tab_el then
if t == tab then
tab_el:SetClass("active", true)
else
tab_el:SetClass("active", false)
end
end
if view_el then
if t == tab then
view_el.style.display = "flex"
else
view_el.style.display = "none"
end
end
end
print("[Dialer] Switched to tab: " .. tab)
end
function dialDigit(digit)
dialed_number = dialed_number .. digit
updateDisplay()
print("[Dialer] Dialed: " .. digit .. " -> " .. dialed_number)
end
function deleteDigit()
if #dialed_number > 0 then
dialed_number = dialed_number:sub(1, -2)
updateDisplay()
print("[Dialer] Deleted digit -> " .. dialed_number)
end
end
function updateDisplay()
local doc = getDoc()
if not doc then return end
local display = doc:GetElementById("dialer-number")
if display then
local formatted = dialed_number
if #dialed_number > 6 then
formatted = dialed_number:sub(1, 3) .. "-" .. dialed_number:sub(4, 6) .. "-" .. dialed_number:sub(7)
elseif #dialed_number > 3 then
formatted = dialed_number:sub(1, 3) .. "-" .. dialed_number:sub(4)
end
display.inner_rml = formatted
end
end
function makeCall()
if #dialed_number > 0 then
print("[Dialer] Calling: " .. dialed_number)
if showToast then
showToast("Calling " .. dialed_number .. "...")
end
if shellNavigateTo then
shellNavigateTo("calling")
end
else
if showToast then
showToast("Enter a number to call")
end
end
end
function callContact(name)
print("[Dialer] Calling contact: " .. name)
if showToast then
showToast("Calling " .. name .. "...")
end
if shellNavigateTo then
shellNavigateTo("calling")
end
end
function openVideoCall()
if #dialed_number > 0 then
if showToast then
showToast("Video call to " .. dialed_number)
end
else
if showToast then
showToast("Enter a number for video call")
end
end
end
print("[Dialer] Content loaded")
</script>

View File

@@ -0,0 +1,117 @@
<!-- Chat Content Fragment -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-bar">
<div class="app-bar-nav" onclick="goBackToMessages()">
<img src="../../icons/back.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-avatar" id="chat-avatar" style="background-color: #9C27B0; width: 40px; height: 40px; margin-right: 12px;">S</div>
<div class="list-item-content" style="flex: 1;">
<span class="list-item-title" id="chat-name">Sarah</span>
<span class="list-item-subtitle" style="color: #4CAF50;">Online</span>
</div>
<div class="btn-icon" onclick="startCall()">
<img src="../../icons/phone.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
<!-- Messages Area -->
<div class="chat-container" id="messages-area" style="flex: 1; overflow: auto;">
<div class="chat-timestamp">Today</div>
<div class="chat-bubble chat-bubble-received">
Hey! How are you doing?
</div>
<div class="chat-bubble chat-bubble-sent">
I'm good! Just finished some work.
</div>
<div class="chat-bubble chat-bubble-received">
Nice! Are you coming to the party tonight?
</div>
<div class="chat-bubble chat-bubble-sent">
Yeah, I'll be there around 8pm
</div>
<div class="chat-bubble chat-bubble-received">
Perfect! Can't wait to see you there!
</div>
<div class="chat-bubble chat-bubble-sent">
Same here! Should I bring anything?
</div>
<div class="chat-bubble chat-bubble-received">
Just yourself! Maybe some snacks if you want
</div>
<div class="chat-bubble chat-bubble-received">
Hey! Are you coming to the party tonight?
</div>
</div>
<!-- Input Area -->
<div class="chat-input-container">
<div class="btn-icon" onclick="attachFile()">
<img src="../../icons/add.tga" style="width: 28px; height: 28px;"/>
</div>
<input type="text" class="chat-input" id="message-input" placeholder="Message"/>
<div class="chat-send-btn" onclick="sendMessage()">
<img src="../../icons/send.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
</div>
<script>
function goBackToMessages()
print("[Chat] Going back to messages")
if shellGoBack then
shellGoBack()
end
end
function startCall()
print("[Chat] Starting call")
if showToast then
showToast("Calling Sarah...")
end
if shellNavigateTo then
shellNavigateTo("calling")
end
end
function attachFile()
print("[Chat] Attach file")
if showToast then
showToast("Attach file")
end
end
function sendMessage()
local doc = shell_document
if doc then
local input = doc:GetElementById("message-input")
if input and input.value and input.value ~= "" then
local msg = input.value
print("[Chat] Sending: " .. msg)
local area = doc:GetElementById("messages-area")
if area then
local new_msg = [[<div class="chat-bubble chat-bubble-sent">]] .. msg .. [[</div>]]
area.inner_rml = area.inner_rml .. new_msg
end
input.value = ""
if showToast then
showToast("Message sent")
end
end
end
end
print("[Chat] Content loaded")
</script>

View File

@@ -1,11 +1,119 @@
<!-- Messages App Content Fragment -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-header">
<span class="app-header-title">Messages</span>
<div class="app-bar">
<span class="app-bar-title">Messages</span>
<div class="app-bar-actions">
<div class="btn-icon" onclick="searchMessages()">
<img src="../../icons/search.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
</div>
<div class="app-body">
<span class="placeholder-text">Messages App</span>
<div class="list" style="flex: 1; overflow: auto;">
<div class="list-item" onclick="openChat('Sarah')">
<div class="list-item-avatar" style="background-color: #9C27B0;">S</div>
<div class="list-item-content">
<span class="list-item-title" style="color: #BB86FC;">Sarah</span>
<span class="list-item-subtitle" style="color: #FFFFFF;">Hey! Are you coming to the party tonight?</span>
</div>
<span style="font-size: 14px; color: #888888;">2 min</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openChat('John Smith')">
<div class="list-item-avatar" style="background-color: #3F51B5;">J</div>
<div class="list-item-content">
<span class="list-item-title">John Smith</span>
<span class="list-item-subtitle">Thanks for your help yesterday!</span>
</div>
<span style="font-size: 14px; color: #888888;">1 hr</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openChat('Mom')">
<div class="list-item-avatar" style="background-color: #E91E63;">M</div>
<div class="list-item-content">
<span class="list-item-title" style="color: #BB86FC;">Mom</span>
<span class="list-item-subtitle" style="color: #FFFFFF;">Don't forget to call grandma!</span>
</div>
<span style="font-size: 14px; color: #888888;">3 hr</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openChat('Work Group')">
<div class="list-item-avatar" style="background-color: #FF9800;">W</div>
<div class="list-item-content">
<span class="list-item-title">Work Group</span>
<span class="list-item-subtitle">Bob: Meeting moved to 3pm</span>
</div>
<span style="font-size: 14px; color: #888888;">Yesterday</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openChat('Alice Johnson')">
<div class="list-item-avatar" style="background-color: #4CAF50;">A</div>
<div class="list-item-content">
<span class="list-item-title">Alice Johnson</span>
<span class="list-item-subtitle">See you at the coffee shop!</span>
</div>
<span style="font-size: 14px; color: #888888;">Yesterday</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openChat('David Miller')">
<div class="list-item-avatar" style="background-color: #FF9800;">D</div>
<div class="list-item-content">
<span class="list-item-title">David Miller</span>
<span class="list-item-subtitle">The project is almost done</span>
</div>
<span style="font-size: 14px; color: #888888;">Monday</span>
</div>
<div class="list-divider"></div>
<div class="list-item" onclick="openChat('Emma Wilson')">
<div class="list-item-avatar" style="background-color: #E91E63;">E</div>
<div class="list-item-content">
<span class="list-item-title">Emma Wilson</span>
<span class="list-item-subtitle">That was a great movie!</span>
</div>
<span style="font-size: 14px; color: #888888;">Sunday</span>
</div>
</div>
<div class="btn-fab" onclick="newMessage()">
<img src="../../icons/edit.tga" style="width: 32px; height: 32px;"/>
</div>
</div>
<script>
function openChat(name)
print("[Messages] Opening chat: " .. name)
if shellNavigateTo then
shellNavigateTo("chat")
end
end
function searchMessages()
print("[Messages] Search")
if showToast then
showToast("Search messages")
end
end
function newMessage()
print("[Messages] New message")
if showToast then
showToast("New message")
end
end
print("[Messages] Content loaded")
</script>

View File

@@ -1,11 +1,175 @@
<!-- Music App Content Fragment -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-header">
<span class="app-header-title">Music</span>
<div class="app-content" style="position: relative;">
<div class="app-bar">
<span class="app-bar-title">Good afternoon</span>
<div class="btn-icon" onclick="openMusicSettings()">
<img src="../../icons/settings.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
<div class="app-body">
<span class="placeholder-text">Music App</span>
<div style="flex: 1; overflow: auto; padding-bottom: 100px;">
<!-- Quick Access Grid -->
<div style="display: flex; flex-wrap: wrap; gap: 8px; padding: 16px;">
<div class="quick-card" onclick="openPlaylist('liked')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #7c3aed;">L</div>
<span class="quick-card-title">Liked Songs</span>
</div>
<div class="quick-card" onclick="openPlaylist('daily1')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #667eea;">D</div>
<span class="quick-card-title">Daily Mix 1</span>
</div>
<div class="quick-card" onclick="openPlaylist('release')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #16a34a;">R</div>
<span class="quick-card-title">Release Radar</span>
</div>
<div class="quick-card" onclick="openPlaylist('chill')" style="width: 48%;">
<div class="quick-card-art" style="background-color: #f093fb;">C</div>
<span class="quick-card-title">Chill Vibes</span>
</div>
</div>
<!-- Recently Played -->
<div class="section-header">
<span class="section-title">Recently Played</span>
<span class="section-action" onclick="showAllRecent()">SEE ALL</span>
</div>
<div style="display: flex; overflow-x: auto; padding: 0 16px; gap: 16px;">
<div class="recent-item" onclick="openPlaylist('pop')">
<div class="recent-art" style="background-color: #43e97b;">P</div>
<div class="recent-title">Pop Hits</div>
<div class="recent-subtitle">Playlist</div>
</div>
<div class="recent-item" onclick="openPlaylist('electronic')">
<div class="recent-art" style="background-color: #fa709a;">E</div>
<div class="recent-title">Electronic</div>
<div class="recent-subtitle">Playlist</div>
</div>
<div class="recent-item" onclick="openPlaylist('jazz')">
<div class="recent-art" style="background-color: #667eea;">J</div>
<div class="recent-title">Jazz Classics</div>
<div class="recent-subtitle">Playlist</div>
</div>
</div>
<!-- Made For You -->
<div class="section-header">
<span class="section-title">Made For You</span>
<span class="section-action" onclick="showAllMixes()">SEE ALL</span>
</div>
<div class="playlist-item" onclick="openPlaylist('daily1')">
<div class="playlist-art" style="background-color: #4facfe;">1</div>
<div class="playlist-info">
<div class="playlist-title">Daily Mix 1</div>
<div class="playlist-meta">Based on your listening</div>
</div>
</div>
<div class="playlist-item" onclick="openPlaylist('daily2')">
<div class="playlist-art" style="background-color: #43e97b;">2</div>
<div class="playlist-info">
<div class="playlist-title">Daily Mix 2</div>
<div class="playlist-meta">Electronic, Ambient, Chill</div>
</div>
</div>
<div class="playlist-item" onclick="openPlaylist('discover')">
<div class="playlist-art" style="background-color: #fa709a;">D</div>
<div class="playlist-info">
<div class="playlist-title">Discover Weekly</div>
<div class="playlist-meta">Your weekly mixtape</div>
</div>
</div>
</div>
<!-- Mini Player -->
<div class="mini-player" onclick="openNowPlaying()" style="position: absolute; bottom: 0; left: 0; right: 0;">
<div class="mini-player-art" id="mini-art" style="background-color: #667eea;">M</div>
<div class="mini-player-info">
<div class="mini-player-title" id="mini-title">Midnight City</div>
<div class="mini-player-artist" id="mini-artist">M83</div>
</div>
<div class="mini-player-controls">
<div class="mini-control-btn" onclick="toggleLike(); event.stopPropagation();">
<img src="../../icons/heart.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="mini-control-btn" id="play-btn" onclick="togglePlay(); event.stopPropagation();">
<img id="play-icon" src="../../icons/play.tga" style="width: 28px; height: 28px;"/>
</div>
</div>
</div>
</div>
<script>
local is_playing = false
local current_track = {
title = "Midnight City",
artist = "M83"
}
local function getDoc()
return shell_document
end
function togglePlay()
is_playing = not is_playing
local doc = getDoc()
if doc then
local icon = doc:GetElementById("play-icon")
if icon then
icon:SetAttribute("src", is_playing and "../../icons/pause.tga" or "../../icons/play.tga")
end
end
print("[Music] " .. (is_playing and "Playing" or "Paused"))
if showToast then
showToast(is_playing and "Playing" or "Paused")
end
end
function toggleLike()
print("[Music] Liked")
if showToast then
showToast("Added to Liked Songs")
end
end
function openPlaylist(id)
print("[Music] Opening playlist: " .. id)
if showToast then
showToast("Playlist: " .. id)
end
end
function openNowPlaying()
print("[Music] Now playing")
if showToast then
showToast("Now Playing: " .. current_track.title)
end
end
function showAllRecent()
print("[Music] Show all recent")
if showToast then
showToast("Recently played")
end
end
function showAllMixes()
print("[Music] Show all mixes")
if showToast then
showToast("Made for you")
end
end
function openMusicSettings()
print("[Music] Settings")
if showToast then
showToast("Music settings")
end
end
print("[Music] Content loaded")
</script>

View File

@@ -1,11 +1,309 @@
<!-- Settings App Content Fragment -->
<!-- Styles are in shell.rml -->
<!-- Uses classes from components.rcss -->
<div class="app-content">
<div class="app-header">
<span class="app-header-title">Settings</span>
<div class="app-bar">
<span class="app-bar-title">Settings</span>
</div>
<div class="app-body">
<span class="placeholder-text">Settings App</span>
<div class="search-bar">
<img class="search-icon" src="../../icons/search.tga"/>
<span class="search-input">Search settings</span>
</div>
<div style="flex: 1; overflow: auto;">
<!-- Profile Card -->
<div class="list-item" onclick="openProfile()">
<div class="list-item-avatar" style="background-color: #BB86FC;">U</div>
<div class="list-item-content">
<span class="list-item-title">User</span>
<span class="list-item-subtitle">user@mosis.app</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="divider"></div>
<!-- Network Section -->
<div class="list-header">Network</div>
<div class="list-item" onclick="toggleWifi()">
<div class="list-item-icon" style="background-color: #2196F3; border-radius: 24px;">
<img src="../../icons/wifi.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Wi-Fi</span>
<span id="wifi-status" class="list-item-subtitle">Connected to MosisNetwork</span>
</div>
<div id="toggle-wifi" class="toggle active">
<div class="toggle-thumb"></div>
</div>
</div>
<div class="list-item" onclick="toggleBluetooth()">
<div class="list-item-icon" style="background-color: #3F51B5; border-radius: 24px;">
<img src="../../icons/bluetooth.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Bluetooth</span>
<span id="bt-status" class="list-item-subtitle">Off</span>
</div>
<div id="toggle-bluetooth" class="toggle">
<div class="toggle-thumb"></div>
</div>
</div>
<div class="list-item" onclick="toggleAirplane()">
<div class="list-item-icon" style="background-color: #FF9800; border-radius: 24px;">
<img src="../../icons/plane.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Airplane Mode</span>
<span class="list-item-subtitle">Off</span>
</div>
<div id="toggle-airplane" class="toggle">
<div class="toggle-thumb"></div>
</div>
</div>
<div class="divider"></div>
<!-- Device Section -->
<div class="list-header">Device</div>
<div class="list-item" onclick="openDisplay()">
<div class="list-item-icon" style="background-color: #9C27B0; border-radius: 24px;">
<img src="../../icons/display.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Display</span>
<span class="list-item-subtitle">Brightness, Dark mode</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="list-item" onclick="openSound()">
<div class="list-item-icon" style="background-color: #E91E63; border-radius: 24px;">
<img src="../../icons/volume.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Sound</span>
<span class="list-item-subtitle">Volume, Ringtone</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="list-item" onclick="openNotifications()">
<div class="list-item-icon" style="background-color: #00BCD4; border-radius: 24px;">
<img src="../../icons/notifications.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Notifications</span>
<span class="list-item-subtitle">App notifications</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="list-item" onclick="openBattery()">
<div class="list-item-icon" style="background-color: #4CAF50; border-radius: 24px;">
<img src="../../icons/battery.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Battery</span>
<span class="list-item-subtitle">85% - Not charging</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="list-item" onclick="openStorage()">
<div class="list-item-icon" style="background-color: #795548; border-radius: 24px;">
<img src="../../icons/storage.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Storage</span>
<span class="list-item-subtitle">32 GB of 128 GB used</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="divider"></div>
<!-- Privacy Section -->
<div class="list-header">Privacy</div>
<div class="list-item" onclick="toggleLocation()">
<div class="list-item-icon" style="background-color: #F44336; border-radius: 24px;">
<img src="../../icons/location.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Location</span>
<span id="location-status" class="list-item-subtitle">On - High accuracy</span>
</div>
<div id="toggle-location" class="toggle active">
<div class="toggle-thumb"></div>
</div>
</div>
<div class="list-item" onclick="openPrivacy()">
<div class="list-item-icon" style="background-color: #607D8B; border-radius: 24px;">
<img src="../../icons/lock.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">Privacy</span>
<span class="list-item-subtitle">Permissions, Data</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
<div class="divider"></div>
<!-- About Section -->
<div class="list-header">About</div>
<div class="list-item" onclick="openAbout()">
<div class="list-item-icon" style="background-color: #BB86FC; border-radius: 24px;">
<img src="../../icons/info.tga" style="width: 28px; height: 28px;"/>
</div>
<div class="list-item-content">
<span class="list-item-title">About Phone</span>
<span class="list-item-subtitle">Mosis v1.0</span>
</div>
<span class="list-item-action">&gt;</span>
</div>
</div>
</div>
<script>
local settings = {
wifi = true,
bluetooth = false,
airplane = false,
location = true
}
local function getDoc()
return shell_document
end
function toggleWifi()
settings.wifi = not settings.wifi
local doc = getDoc()
if doc then
local toggle = doc:GetElementById("toggle-wifi")
local status = doc:GetElementById("wifi-status")
if toggle then
toggle:SetClass("active", settings.wifi)
end
if status then
status.inner_rml = settings.wifi and "Connected to MosisNetwork" or "Off"
end
end
print("[Settings] Wi-Fi: " .. tostring(settings.wifi))
if showToast then
showToast(settings.wifi and "Wi-Fi enabled" or "Wi-Fi disabled")
end
end
function toggleBluetooth()
settings.bluetooth = not settings.bluetooth
local doc = getDoc()
if doc then
local toggle = doc:GetElementById("toggle-bluetooth")
local status = doc:GetElementById("bt-status")
if toggle then
toggle:SetClass("active", settings.bluetooth)
end
if status then
status.inner_rml = settings.bluetooth and "On" or "Off"
end
end
print("[Settings] Bluetooth: " .. tostring(settings.bluetooth))
if showToast then
showToast(settings.bluetooth and "Bluetooth enabled" or "Bluetooth disabled")
end
end
function toggleAirplane()
settings.airplane = not settings.airplane
local doc = getDoc()
if doc then
local toggle = doc:GetElementById("toggle-airplane")
if toggle then
toggle:SetClass("active", settings.airplane)
end
if settings.airplane then
settings.wifi = false
settings.bluetooth = false
local wt = doc:GetElementById("toggle-wifi")
local bt = doc:GetElementById("toggle-bluetooth")
if wt then wt:SetClass("active", false) end
if bt then bt:SetClass("active", false) end
end
end
print("[Settings] Airplane: " .. tostring(settings.airplane))
if showToast then
showToast(settings.airplane and "Airplane mode on" or "Airplane mode off")
end
end
function toggleLocation()
settings.location = not settings.location
local doc = getDoc()
if doc then
local toggle = doc:GetElementById("toggle-location")
local status = doc:GetElementById("location-status")
if toggle then
toggle:SetClass("active", settings.location)
end
if status then
status.inner_rml = settings.location and "On - High accuracy" or "Off"
end
end
print("[Settings] Location: " .. tostring(settings.location))
if showToast then
showToast(settings.location and "Location enabled" or "Location disabled")
end
end
function openProfile()
print("[Settings] Profile")
if showToast then showToast("User profile") end
end
function openDisplay()
print("[Settings] Display")
if showToast then showToast("Display settings") end
end
function openSound()
print("[Settings] Sound")
if showToast then showToast("Sound settings") end
end
function openNotifications()
print("[Settings] Notifications")
if showToast then showToast("Notification settings") end
end
function openBattery()
print("[Settings] Battery")
if showToast then showToast("Battery: 85%") end
end
function openStorage()
print("[Settings] Storage")
if showToast then showToast("Storage: 25% used") end
end
function openPrivacy()
print("[Settings] Privacy")
if showToast then showToast("Privacy settings") end
end
function openAbout()
print("[Settings] About")
if showToast then showToast("Mosis Virtual Phone v1.0") end
end
print("[Settings] Content loaded")
</script>