399 lines
12 KiB
Lua
399 lines
12 KiB
Lua
-- 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 = [[<div class="conversation-unread">]] .. conv.unread .. [[</div>]]
|
|
end
|
|
|
|
html = html .. [[
|
|
<div class="conversation-item" onclick="openConversation(']] .. conv.id .. [[')">
|
|
<div class="conversation-avatar" style="background-color: ]] .. color .. [[;">]] .. initial .. [[</div>
|
|
<div class="conversation-content">
|
|
<div class="conversation-header">
|
|
<span class="conversation-name">]] .. conv.name .. [[</span>
|
|
<span class="conversation-time">]] .. conv.time .. [[</span>
|
|
</div>
|
|
<div class="conversation-preview">]] .. conv.last_message .. [[</div>
|
|
</div>
|
|
]] .. unread_badge .. [[
|
|
</div>
|
|
]]
|
|
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 .. [[
|
|
<div class="message-bubble ]] .. class .. [[">]] .. msg.text .. [[</div>
|
|
]]
|
|
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
|