mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-24 04:52:48 +01:00
309 lines
10 KiB
Lua
309 lines
10 KiB
Lua
|
||
local event = require("event")
|
||
local modemConnection = require("modemConnection")
|
||
local ecs = require("ECSAPI")
|
||
local fs = require("filesystem")
|
||
local serialization = require("serialization")
|
||
local buffer = require("doubleBuffering")
|
||
local context = require("context")
|
||
local image = require("image")
|
||
local unicode = require("unicode")
|
||
local component = require("component")
|
||
local modem = component.modem
|
||
|
||
-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
local colors = {
|
||
leftBar = 0x262626,
|
||
leftBarSelection = 0x00A8FF,
|
||
leftBarAlternative = 0x383838,
|
||
leftBarText = 0xFFFFFF,
|
||
leftBarSelectionText = 0xFFFFFF,
|
||
leftBarSearchButton = 0x555555,
|
||
leftBarSearchButtonText = 0xFFFFFF,
|
||
|
||
topBar = 0xEEEEEE,
|
||
topMenu = 0xFFFFFF,
|
||
|
||
chatZone = 0xFFFFFF,
|
||
senderCloudColor = 0x3392FF,
|
||
senderCloudTextColor = 0xFFFFFF,
|
||
yourCloudColor = 0x55BBFF,
|
||
yourCloudTextColor = 0xFFFFFF,
|
||
systemMessageColor = 0x555555,
|
||
|
||
messageInputBarColor = 0xEEEEEE,
|
||
messsageInputBarButtonColor = 0x3392FF,
|
||
messsageInputBarButtonTextColor = 0xFFFFFF,
|
||
messsageInputBarLineColor = 0x000000,
|
||
}
|
||
|
||
local chatHistory = {}
|
||
local avatars = {}
|
||
|
||
-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
local personalAvatarPath = "sampleAvatar.pic"
|
||
local chatHistoryPath = "ChatHistory.cfg"
|
||
local friendAvatarPath = "FriendAvatar.pic"
|
||
local avatarWidthLimit = 6
|
||
local avatarHeightLimit = 3
|
||
|
||
local currentChatID = 1
|
||
local currentChatMessage = 0
|
||
|
||
buffer.start()
|
||
local leftBarWidth = math.floor(buffer.screen.width * 0.2)
|
||
local chatZoneWidth = buffer.screen.width - leftBarWidth
|
||
local heightOfTopBar = 2 + avatarHeightLimit
|
||
local yLeftBar = 2 + heightOfTopBar
|
||
local chatZoneX = leftBarWidth + 1
|
||
local bottom
|
||
local chatZoneHeight = buffer.screen.height - yLeftBar + 1
|
||
local cloudWidth = chatZoneWidth - 2 * (avatarWidthLimit + 9)
|
||
local cloudTextWidth = cloudWidth - 4
|
||
local messageInputHeight = 5
|
||
|
||
-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
--Объекты для тача
|
||
local obj = {}
|
||
local function newObj(class, name, ...)
|
||
obj[class] = obj[class] or {}
|
||
obj[class][name] = {...}
|
||
end
|
||
|
||
local function saveChatHistory()
|
||
fs.makeDirectory(fs.path(chatHistoryPath) or "")
|
||
local file = io.open(chatHistoryPath, "w")
|
||
file:write(serialization.serialize(chatHistoryPath))
|
||
file:close()
|
||
end
|
||
|
||
local function loadChatHistory()
|
||
if fs.exists(chatHistoryPath) then
|
||
local file = io.open(chatHistoryPath, "r")
|
||
chatHistory = serialization.unserialize(file:read("*a"))
|
||
file:close()
|
||
else
|
||
chatHistory = {}
|
||
saveChatHistory()
|
||
end
|
||
end
|
||
|
||
local function loadAvatarFromFile(path)
|
||
local avatar = image.load(personalAvatarPath)
|
||
local widthDifference = avatar.width - avatarWidthLimit
|
||
local heightDifference = avatar.height - avatarHeightLimit
|
||
|
||
if widthDifference > 0 then
|
||
avatar = image.crop(avatar, "fromRight", widthDifference)
|
||
end
|
||
if heightDifference > 0 then
|
||
avatar = image.crop(avatar, "fromBottom", heightDifference)
|
||
end
|
||
|
||
return avatar
|
||
end
|
||
|
||
local function loadPersonalAvatar()
|
||
avatars.personal = loadAvatarFromFile(personalAvatarPath)
|
||
end
|
||
|
||
local function drawLeftBar()
|
||
buffer.square(1, yLeftBar, leftBarWidth, buffer.screen.height - 1, colors.leftBar, 0xFFFFFF, " ")
|
||
|
||
local yPos = yLeftBar
|
||
local counter = 1
|
||
local text, textColor
|
||
|
||
for i = 1, #chatHistory do
|
||
textColor = colors.leftBarText
|
||
|
||
if i == currentChatID then
|
||
buffer.square(1, yPos, leftBarWidth, 3, colors.leftBarSelection, 0xFFFFFF, " ")
|
||
textColor = 0xFFFFFF
|
||
elseif counter % 2 ~= 0 then
|
||
buffer.square(1, yPos, leftBarWidth, 3, colors.leftBarAlternative, 0xFFFFFF, " ")
|
||
end
|
||
|
||
text = chatHistory[i].name or address
|
||
text = ecs.stringLimit("end", text, leftBarWidth - 4)
|
||
|
||
yPos = yPos + 1
|
||
buffer.text(2, yPos, textColor, text)
|
||
|
||
yPos = yPos + 2
|
||
counter = counter + 1
|
||
if yPos > buffer.screen.height then break end
|
||
end
|
||
|
||
--Кнопочка поиска юзеров
|
||
obj.search = {buffer.button(1, buffer.screen.height - 2, leftBarWidth, 3, colors.leftBarSearchButton, colors.leftBarSearchButtonText, "Поиск")}
|
||
end
|
||
|
||
local function drawTopBar()
|
||
buffer.square(1, 2, buffer.screen.width, heightOfTopBar, colors.topBar, 0xFFFFFF, " ")
|
||
|
||
buffer.image(3, 3, avatars.personal)
|
||
-- buffer.text(chatZoneX, yLeftBar + avatarHeightLimit + 2, )
|
||
end
|
||
|
||
local function drawTopMenu()
|
||
buffer.menu(1, 1, buffer.screen.width, colors.topMenu, 0, {"Чат", 0x000099}, {"Настройки", 0x262626}, {"О программе", 0x262626})
|
||
end
|
||
|
||
local function drawCloud(x, y, cloudColor, textColor, fromYou, text)
|
||
local upperPixel = "▀"
|
||
local lowerPixel = "▄"
|
||
local cloudHeight = #text + 2
|
||
-- local cloudTextWidth = unicode.len(text[1])
|
||
|
||
if not fromYou then
|
||
buffer.set(x, y - cloudHeight + 2, colors.chatZone, cloudColor, upperPixel)
|
||
buffer.set(x + 1, y - cloudHeight + 2, cloudColor, 0xFFFFFF, " ")
|
||
x = x + 2
|
||
else
|
||
buffer.set(x + cloudTextWidth + 3, y - cloudHeight + 2, colors.chatZone, cloudColor, upperPixel)
|
||
buffer.set(x + cloudTextWidth + 2, y - cloudHeight + 2, cloudColor, 0xFFFFFF, " ")
|
||
end
|
||
|
||
buffer.square(x + 1, y - cloudHeight + 1, cloudTextWidth, cloudHeight, cloudColor, 0xFFFFFF, " ")
|
||
buffer.square(x, y - cloudHeight + 2, cloudTextWidth + 2, cloudHeight - 2, cloudColor, 0xFFFFFF, " ")
|
||
|
||
buffer.set(x, y - cloudHeight + 1, colors.chatZone, cloudColor, lowerPixel)
|
||
buffer.set(x + cloudTextWidth + 1, y - cloudHeight + 1, colors.chatZone, cloudColor, lowerPixel)
|
||
buffer.set(x, y, colors.chatZone, cloudColor, upperPixel)
|
||
buffer.set(x + cloudTextWidth + 1, y, colors.chatZone, cloudColor, upperPixel)
|
||
|
||
x = x + 1
|
||
y = y - 1
|
||
|
||
for i = #text, 1, -1 do
|
||
buffer.text(x, y, textColor, text[i])
|
||
y = y - 1
|
||
end
|
||
|
||
return y
|
||
end
|
||
|
||
local function stringWrap(text, limit)
|
||
local strings = {}
|
||
local textLength = unicode.len(text)
|
||
local subFrom = 1
|
||
while subFrom <= textLength do
|
||
table.insert(strings, unicode.sub(text, subFrom, subFrom + limit - 1))
|
||
subFrom = subFrom + limit
|
||
end
|
||
return strings
|
||
end
|
||
|
||
local function drawChat()
|
||
local x, y = chatZoneX, yLeftBar
|
||
buffer.square(x, y, chatZoneWidth, chatZoneHeight, colors.chatZone, 0xFFFFFF, " ")
|
||
|
||
-- Ставим ограничение отрисовки буфера, чтобы облачка сообщений не ебошили
|
||
-- За края верхней зоны чатзоны, ну ты понял, да?
|
||
buffer.setDrawLimit(x, y, chatZoneWidth, chatZoneHeight)
|
||
|
||
--ВОТ ТУТ НАЧИНАЕТСЯ ЕБОЛААААААА
|
||
-- Стартовая точка
|
||
y = buffer.screen.height - messageInputHeight - 1
|
||
local xYou, xSender = x + 2, buffer.screen.width - 9
|
||
-- Отрисовка облачков
|
||
local cloudColor, textColor
|
||
for i = currentChatMessage, 1, -1 do
|
||
--Если не указан тип сообщения, то ренедрим дефолтные облачка
|
||
if not chatHistory[currentChatID][i].type then
|
||
--Если сообщенька от тебя, то цвет меняем
|
||
if chatHistory[currentChatID][i].fromYou then
|
||
cloudColor, textColor = colors.yourCloudColor, colors.yourCloudTextColor
|
||
y = drawCloud(xSender - cloudWidth - 2, y, cloudColor, textColor, chatHistory[currentChatID][i].fromYou, stringWrap(chatHistory[currentChatID][i].message, cloudTextWidth))
|
||
buffer.image(xSender, y, avatars.personal)
|
||
else
|
||
cloudColor, textColor = colors.senderCloudColor, colors.senderCloudTextColor
|
||
y = drawCloud(xYou + 8, y, cloudColor, textColor, chatHistory[currentChatID][i].fromYou, stringWrap(chatHistory[currentChatID][i].message, cloudTextWidth))
|
||
buffer.image(xYou, y, avatars.personal)
|
||
end
|
||
else
|
||
for i = chatZoneX, buffer.screen.width - 2 do
|
||
buffer.set(i, y, colors.chatZone, colors.systemMessageColor, "─")
|
||
end
|
||
local x = math.floor(chatZoneX + (chatZoneWidth - 2) / 2 - unicode.len(chatHistory[currentChatID][i].message) / 2)
|
||
buffer.text(x, y, colors.systemMessageColor, " " .. chatHistory[currentChatID][i].message .. " ")
|
||
end
|
||
|
||
y = y - 2
|
||
if y <= yLeftBar then break end
|
||
end
|
||
|
||
-- Убираем ограничение отроисовки буфера
|
||
buffer.resetDrawLimit()
|
||
|
||
buffer.scrollBar(buffer.screen.width - 1, yLeftBar, 2, chatZoneHeight - messageInputHeight, #chatHistory[currentChatID], currentChatMessage, 0xDDDDDD, ecs.colors.blue)
|
||
end
|
||
|
||
local function drawMessageInputBar()
|
||
local x, y = chatZoneX, buffer.screen.height - messageInputHeight + 1
|
||
-- buffer.text(x, y, colors.messsageInputBarLineColor, string.rep("▄", chatZoneWidth - 2))
|
||
buffer.square(x, y, chatZoneWidth, messageInputHeight, colors.messageInputBarColor, 0xFFFFFF, " ")
|
||
y = y + 1
|
||
buffer.frame(x + 2, y, chatZoneWidth - 18, 3, colors.messsageInputBarLineColor)
|
||
buffer.button(buffer.screen.width - 3 - 10, y, 12, 3, colors.messsageInputBarButtonColor, colors.messsageInputBarButtonTextColor, "Отправить")
|
||
end
|
||
|
||
local function drawAll()
|
||
drawTopBar()
|
||
drawLeftBar()
|
||
drawTopMenu()
|
||
drawChat()
|
||
drawMessageInputBar()
|
||
buffer.draw()
|
||
end
|
||
|
||
local function scrollChat(direction)
|
||
if direction == 1 then
|
||
if currentChatMessage > 1 then
|
||
currentChatMessage = currentChatMessage - 1
|
||
drawChat()
|
||
drawMessageInputBar(currentChatMessage)
|
||
buffer.draw()
|
||
end
|
||
else
|
||
if currentChatMessage < #chatHistory[currentChatID] then
|
||
currentChatMessage = currentChatMessage + 1
|
||
drawChat()
|
||
drawMessageInputBar(currentChatMessage)
|
||
buffer.draw()
|
||
end
|
||
end
|
||
end
|
||
|
||
-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
-- buffer.square(1, 1, buffer.screen.width, buffer.screen.height, 0x262626, 0xFFFFFF, " ")
|
||
|
||
loadChatHistory()
|
||
loadPersonalAvatar()
|
||
currentChatMessage = #chatHistory[currentChatID]
|
||
|
||
drawAll()
|
||
|
||
-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
while true do
|
||
local e = { event.pull() }
|
||
if e[1] == "touch" then
|
||
|
||
elseif e[1] == "scroll" then
|
||
if ecs.clickedAtArea(e[3], e[4], chatZoneX, yLeftBar, chatZoneX + chatZoneWidth - 1, yLeftBar + chatZoneHeight - 1) then
|
||
scrollChat(e[5])
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
|
||
|
||
|