-- messages.lua - Messages app functionality -- Handles conversation list and individual chats local messages_doc = nil local conversations = {} local current_conversation = nil local current_messages = {} -- Avatar colors local avatar_colors = { "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#FF9800" } local function getAvatarColor(name) local sum = 0 for i = 1, #name do sum = sum + string.byte(name, i) end return avatar_colors[(sum % #avatar_colors) + 1] end -- Initialize conversations data local function initConversationsData() conversations = { { id = "1", name = "Alice Johnson", phone = "+1 555-0101", last_message = "Hey! Are you coming to the party tonight?", time = "2:34 PM", unread = 2, messages = { {sender = "them", text = "Hey!", time = "2:30 PM"}, {sender = "them", text = "What are you up to?", time = "2:31 PM"}, {sender = "me", text = "Not much, just working", time = "2:32 PM"}, {sender = "them", text = "Cool! There's a party at Mike's tonight", time = "2:33 PM"}, {sender = "them", text = "Hey! Are you coming to the party tonight?", time = "2:34 PM"}, } }, { id = "2", name = "Bob Williams", phone = "+1 555-0201", last_message = "Thanks for the help yesterday!", time = "1:15 PM", unread = 0, messages = { {sender = "them", text = "Hey, can you help me with something?", time = "Yesterday"}, {sender = "me", text = "Sure, what do you need?", time = "Yesterday"}, {sender = "them", text = "I need help moving some furniture", time = "Yesterday"}, {sender = "me", text = "No problem, I'll be there at 2", time = "Yesterday"}, {sender = "them", text = "Thanks for the help yesterday!", time = "1:15 PM"}, } }, { id = "3", name = "Carol Davis", phone = "+1 555-0301", last_message = "The meeting has been rescheduled to Friday", time = "Yesterday", unread = 0, messages = { {sender = "them", text = "Hi, are you free for a meeting tomorrow?", time = "Monday"}, {sender = "me", text = "Let me check my calendar", time = "Monday"}, {sender = "me", text = "Yes, I'm free at 3pm", time = "Monday"}, {sender = "them", text = "The meeting has been rescheduled to Friday", time = "Yesterday"}, } }, { id = "4", name = "David Brown", phone = "+1 555-0401", last_message = "Can you send me the files?", time = "Yesterday", unread = 1, messages = { {sender = "them", text = "Hey, do you have the project files?", time = "Yesterday"}, {sender = "me", text = "Which ones?", time = "Yesterday"}, {sender = "them", text = "Can you send me the files?", time = "Yesterday"}, } }, { id = "5", name = "Emma Wilson", phone = "+1 555-0501", last_message = "See you at the coffee shop!", time = "Mon", unread = 0, messages = { {sender = "me", text = "Want to grab coffee later?", time = "Mon"}, {sender = "them", text = "Sure! What time?", time = "Mon"}, {sender = "me", text = "How about 4pm at the usual place?", time = "Mon"}, {sender = "them", text = "See you at the coffee shop!", time = "Mon"}, } }, { id = "6", name = "Frank Miller", phone = "+1 555-0601", last_message = "Great game last night!", time = "Sun", unread = 0, messages = { {sender = "them", text = "Did you watch the game?", time = "Sun"}, {sender = "me", text = "Yes! It was amazing!", time = "Sun"}, {sender = "them", text = "Great game last night!", time = "Sun"}, } }, { id = "7", name = "Grace Lee", phone = "+1 555-0701", last_message = "Happy birthday! :)", time = "Sat", unread = 0, messages = { {sender = "them", text = "Happy birthday! :)", time = "Sat"}, {sender = "me", text = "Thank you so much! :)", time = "Sat"}, } }, } end -- Initialize messages app function initMessages(doc) print("[Messages] Initializing...") messages_doc = doc initConversationsData() renderConversations() end -- Render conversation list function renderConversations() if not messages_doc then return end local container = messages_doc:GetElementById("conversations-list") if not container then return end local html = "" for _, conv in ipairs(conversations) do local color = getAvatarColor(conv.name) local initial = conv.name:sub(1, 1):upper() local unread_badge = "" if conv.unread > 0 then unread_badge = [[
]] .. conv.unread .. [[
]] end html = html .. [[
]] .. initial .. [[
]] .. conv.name .. [[ ]] .. conv.time .. [[
]] .. conv.last_message .. [[
]] .. unread_badge .. [[
]] end container.inner_rml = html end -- Open a conversation function openConversation(conv_id) print("[Messages] Opening conversation: " .. conv_id) -- Find conversation for _, conv in ipairs(conversations) do if conv.id == conv_id then current_conversation = conv current_messages = conv.messages conv.unread = 0 -- Mark as read break end end if current_conversation then -- Store for chat screen if mosis and mosis.state then mosis.state.set("current_chat", { id = current_conversation.id, name = current_conversation.name, phone = current_conversation.phone }) end -- Navigate to chat if navigateTo then navigateTo("chat") else -- Inline chat view showChatInline() end end end -- Show chat inline function showChatInline() if not messages_doc then return end local list = messages_doc:GetElementById("conversations-container") local chat = messages_doc:GetElementById("chat-container") if list and chat then list.style.display = "none" chat.style.display = "flex" renderChat() end end -- Hide chat and return to list function hideChat() if not messages_doc then return end local list = messages_doc:GetElementById("conversations-container") local chat = messages_doc:GetElementById("chat-container") if list and chat then chat.style.display = "none" list.style.display = "flex" renderConversations() -- Refresh to update unread counts end current_conversation = nil end -- Render chat messages function renderChat() if not messages_doc or not current_conversation then return end -- Update header local name_el = messages_doc:GetElementById("chat-name") local avatar_el = messages_doc:GetElementById("chat-avatar") if name_el then name_el.inner_rml = current_conversation.name end if avatar_el then local color = getAvatarColor(current_conversation.name) local initial = current_conversation.name:sub(1, 1):upper() avatar_el.style["background-color"] = color avatar_el.inner_rml = initial end -- Render messages local container = messages_doc:GetElementById("chat-messages") if not container then return end local html = "" for _, msg in ipairs(current_messages) do local class = msg.sender == "me" and "message-sent" or "message-received" html = html .. [[
]] .. msg.text .. [[
]] end container.inner_rml = html -- Scroll to bottom -- Note: RmlUi may need specific handling for scroll end -- Send a message function sendMessage() if not messages_doc or not current_conversation then return end local input = messages_doc:GetElementById("message-input") if not input then return end local text = input.value or "" if text == "" then return end print("[Messages] Sending: " .. text) -- Add message to current conversation table.insert(current_messages, { sender = "me", text = text, time = "Just now" }) -- Update conversation preview current_conversation.last_message = text current_conversation.time = "Just now" -- Clear input input.value = "" -- Re-render chat renderChat() -- Simulate reply after delay if setTimeout then setTimeout(function() simulateReply() end, 2000 + math.random(1000, 3000)) end end -- Simulate a reply function simulateReply() if not current_conversation then return end local replies = { "That's great!", "I see", "Sounds good!", "Let me think about it", "Sure thing!", "OK!", "Thanks!", "Got it", "Nice!", "Interesting..." } local reply = replies[math.random(#replies)] table.insert(current_messages, { sender = "them", text = reply, time = "Just now" }) current_conversation.last_message = reply current_conversation.time = "Just now" renderChat() end -- Handle input keypress (for Enter to send) function onMessageKeypress(event) if event.key == "Return" or event.key == "Enter" then sendMessage() return true end return false end -- Start new conversation function newConversation() print("[Messages] New conversation") if showToast then showToast("New message") end end -- Search conversations function searchConversations(query) print("[Messages] Searching: " .. query) -- TODO: Implement search filtering end -- Delete conversation function deleteConversation(conv_id) print("[Messages] Deleting conversation: " .. conv_id) for i, conv in ipairs(conversations) do if conv.id == conv_id then table.remove(conversations, i) break end end renderConversations() if showToast then showToast("Conversation deleted") end end -- Call contact from chat function callFromChat() if not current_conversation then return end print("[Messages] Calling from chat: " .. current_conversation.name) if mosis and mosis.state then mosis.state.set("current_call", { number = current_conversation.phone, name = current_conversation.name }) end if navigateTo then navigateTo("calling") else if showToast then showToast("Calling " .. current_conversation.name) end end end