add toast and app transition animations
Toast: - Bigger size with bold text (18dp padding, 16dp font) - Pop-up animation from bottom with bounce effect - Fade-out animation when dismissing - Cancels previous toast when showing new one App transitions: - Opening: fade in + scale from 0.8 to 1.0 with back-out easing - Closing: fade out + scale from 1.0 to 0.8 - Skip animation on initial shell load - Async close animation before loading previous app
This commit is contained in:
@@ -30,8 +30,8 @@ function initShell(doc)
|
||||
-- Update time display
|
||||
updateTime()
|
||||
|
||||
-- Load home screen by default
|
||||
loadAppContent_internal("home", "apps/home/home_content.rml")
|
||||
-- Load home screen by default (skip animation on initial load)
|
||||
loadAppContent_internal("home", "apps/home/home_content.rml", true)
|
||||
|
||||
print("[Shell] Shell initialized")
|
||||
end
|
||||
@@ -46,8 +46,8 @@ end
|
||||
|
||||
-- ===== APP LOADING =====
|
||||
|
||||
-- Internal function to load app content
|
||||
function loadAppContent_internal(app_id, app_path)
|
||||
-- Internal function to load app content with optional animation
|
||||
function loadAppContent_internal(app_id, app_path, skip_animation)
|
||||
if not app_container then
|
||||
print("[Shell] ERROR: No app container")
|
||||
return false
|
||||
@@ -68,6 +68,18 @@ function loadAppContent_internal(app_id, app_path)
|
||||
current_app_path = app_path
|
||||
print("[Shell] App loaded: " .. app_id)
|
||||
|
||||
-- Play opening animation (unless skipped for initial load)
|
||||
if not skip_animation then
|
||||
app_container:SetClass("app-opening", true)
|
||||
app_container:SetClass("app-closing", false)
|
||||
-- Remove animation class after it completes
|
||||
if setTimeout then
|
||||
setTimeout(function()
|
||||
app_container:SetClass("app-opening", false)
|
||||
end, 300)
|
||||
end
|
||||
end
|
||||
|
||||
-- If home was loaded, populate apps dynamically
|
||||
if app_id == "home" then
|
||||
populateHomeApps()
|
||||
@@ -126,6 +138,21 @@ end
|
||||
|
||||
-- ===== NAVIGATION =====
|
||||
|
||||
-- Play closing animation then execute callback
|
||||
local function playCloseAnimation(callback)
|
||||
if app_container and setTimeout then
|
||||
app_container:SetClass("app-closing", true)
|
||||
app_container:SetClass("app-opening", false)
|
||||
setTimeout(function()
|
||||
app_container:SetClass("app-closing", false)
|
||||
if callback then callback() end
|
||||
end, 200)
|
||||
else
|
||||
-- No animation support, execute immediately
|
||||
if callback then callback() end
|
||||
end
|
||||
end
|
||||
|
||||
-- Go back to previous app
|
||||
function shellGoBack()
|
||||
print("[Shell] goBack called (history depth: " .. #nav_history .. ")")
|
||||
@@ -139,17 +166,20 @@ function shellGoBack()
|
||||
local previous = table.remove(nav_history)
|
||||
print("[Shell] Going back to: " .. previous.app_id)
|
||||
|
||||
-- Don't push to history when going back
|
||||
local temp_app = current_app
|
||||
current_app = nil
|
||||
current_app_path = nil
|
||||
-- Play closing animation, then load previous app
|
||||
playCloseAnimation(function()
|
||||
-- Don't push to history when going back
|
||||
local temp_app = current_app
|
||||
current_app = nil
|
||||
current_app_path = nil
|
||||
|
||||
local success = loadAppContent_internal(previous.app_id, previous.app_path)
|
||||
if not success then
|
||||
-- Restore state on failure
|
||||
current_app = temp_app
|
||||
end
|
||||
return success
|
||||
local success = loadAppContent_internal(previous.app_id, previous.app_path)
|
||||
if not success then
|
||||
-- Restore state on failure
|
||||
current_app = temp_app
|
||||
end
|
||||
end)
|
||||
return true
|
||||
else
|
||||
print("[Shell] No history - already at root")
|
||||
if current_app ~= "home" then
|
||||
@@ -171,10 +201,12 @@ function shellGoHome()
|
||||
-- Clear history
|
||||
nav_history = {}
|
||||
|
||||
-- Load home
|
||||
current_app = nil
|
||||
current_app_path = nil
|
||||
loadAppContent_internal("home", "apps/home/home_content.rml")
|
||||
-- Play closing animation, then load home
|
||||
playCloseAnimation(function()
|
||||
current_app = nil
|
||||
current_app_path = nil
|
||||
loadAppContent_internal("home", "apps/home/home_content.rml")
|
||||
end)
|
||||
end
|
||||
|
||||
-- Show recents (placeholder)
|
||||
@@ -209,6 +241,8 @@ end
|
||||
|
||||
-- ===== TOASTS =====
|
||||
|
||||
local active_toast_id = nil
|
||||
|
||||
function showToast(message, type)
|
||||
type = type or "default"
|
||||
|
||||
@@ -218,24 +252,39 @@ function showToast(message, type)
|
||||
return
|
||||
end
|
||||
|
||||
local class = "toast"
|
||||
if type == "success" then
|
||||
class = "toast toast-success"
|
||||
elseif type == "error" then
|
||||
class = "toast toast-error"
|
||||
elseif type == "warning" then
|
||||
class = "toast toast-warning"
|
||||
-- Cancel any pending hide timer
|
||||
if active_toast_id and clearTimeout then
|
||||
clearTimeout(active_toast_id)
|
||||
active_toast_id = nil
|
||||
end
|
||||
|
||||
-- Clear existing toasts and add new one
|
||||
local toast_html = '<div class="' .. class .. '"><span>' .. message .. '</span></div>'
|
||||
local type_class = ""
|
||||
if type == "success" then
|
||||
type_class = " toast-success"
|
||||
elseif type == "error" then
|
||||
type_class = " toast-error"
|
||||
elseif type == "warning" then
|
||||
type_class = " toast-warning"
|
||||
end
|
||||
|
||||
-- Create toast with visible animation class
|
||||
local toast_html = '<div id="active-toast" class="toast toast-visible' .. type_class .. '"><span>' .. message .. '</span></div>'
|
||||
container.inner_rml = toast_html
|
||||
|
||||
-- Auto-remove after 3 seconds
|
||||
-- Auto-hide after 2.5 seconds (start hide animation, then remove)
|
||||
if setTimeout then
|
||||
setTimeout(function()
|
||||
container.inner_rml = ""
|
||||
end, 3000)
|
||||
active_toast_id = setTimeout(function()
|
||||
local toast = shell_document:GetElementById("active-toast")
|
||||
if toast then
|
||||
-- Switch to hiding animation
|
||||
toast:SetAttribute("class", "toast toast-hiding" .. type_class)
|
||||
-- Remove after animation completes
|
||||
setTimeout(function()
|
||||
container.inner_rml = ""
|
||||
active_toast_id = nil
|
||||
end, 300)
|
||||
end
|
||||
end, 2500)
|
||||
end
|
||||
|
||||
print("[Shell] Toast: " .. message .. " (" .. type .. ")")
|
||||
|
||||
Reference in New Issue
Block a user