1734 lines
57 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local GUI = require("GUI")
local screen = require("Screen")
local filesystem = require("Filesystem")
local color = require("Color")
local image = require("Image")
local internet = require("Internet")
local json = require("JSON")
local color = require("Color")
local paths = require("Paths")
local system = require("System")
local text = require("Text")
local number = require("Number")
--------------------------------------------------------------------------------
local VKAPIVersion = "5.85"
local config = {
avatars = {
[7799889] = 0x2D2D2D,
},
loadCountConversations = 10,
loadCountMessages = 10,
loadCountNews = 10,
scrollSpeed = 2,
addMessagePostfix = true,
updateContentTrigger = 0.2,
loadCountWall = 10,
loadCountFriends = 10,
loadCountDocs = 10,
maximumPreviewFileSize = 4096,
style = "Default.lua",
}
local scriptDirectory = filesystem.path(system.getCurrentScript())
local applicationDataPath = paths.user.applicationData .. "VK/"
local configPath = applicationDataPath .. "Config5.cfg"
local imageCachePath = applicationDataPath .. "Cache/"
local iconsPath = scriptDirectory .. "Icons/"
local stylesPath = scriptDirectory .. "Styles/"
--------------------------------------------------------------------------------
local currentAccessToken, currentPeerID
local showUserProfile, showConversations
local lastPizda
local style
local function saveConfig()
filesystem.writeTable(configPath, config)
end
local function loadStyle()
style = filesystem.readTable(stylesPath .. config.style)
end
if filesystem.exists(configPath) then
config = filesystem.readTable(configPath)
end
local localization = system.getLocalization(scriptDirectory .. "Localizations/")
loadStyle()
local list, icons = filesystem.list(iconsPath), {}
for i = 1, #list do
icons[unicode.lower(filesystem.hideExtension(list[i]))] = image.load(iconsPath .. list[i])
end
--------------------------------------------------------------------------------
local workspace, window = system.addWindow(GUI.filledWindow(1, 1, 100, 26, 0x0))
local leftPanel = window:addChild(GUI.panel(1, 1, 1, 1, 0x0))
local leftLayout = window:addChild(GUI.layout(1, 3, 1, 1, 1, 1))
leftLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
leftLayout:setSpacing(1, 1, 1)
leftLayout:setMargin(1, 1, 0, 1)
local progressIndicator = window:addChild(GUI.progressIndicator(1, 1, 0x0, 0x0, 0x0))
local contentContainer = window:addChild(GUI.container(1, 1, 1, 1))
local function log(...)
local file = filesystem.open("/url.log", "a")
file:write(...)
file:write("\n\n")
file:close()
end
local function request(url, postData, headers)
progressIndicator.active = true
workspace:draw()
-- log("REQUEST URL: ", url)
headers = headers or {}
headers["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
local data = ""
local success, reason = internet.rawRequest(
url,
postData,
headers,
function(chunk)
data = data .. chunk
progressIndicator:roll()
workspace:draw()
end,
math.huge
)
if success then
data = json.decode(data)
progressIndicator.active = false
workspace:draw()
return data
else
GUI.alert("Failed to perform internet request: ")
end
end
local function responseRequest(...)
local result = request(...)
if result then
if result.response then
return result.response
else
GUI.alert("API request was successfult, but response field is missing, shit saved to /url.log")
-- log("MISSING RESPONSE: ", text.serialize(result, true))
end
end
end
local function methodRequest(data)
return responseRequest("https://api.vk.com/method/" .. data .. "&access_token=" .. currentAccessToken .. "&v=" .. VKAPIVersion)
end
local function executeRequest(code)
return methodRequest("execute?code=" .. internet.encode(code))
end
local function addPanel(container, color)
return container:addChild(GUI.panel(1, 1, container.width, container.height, color), 1)
end
local function fitToLastChild(what, addition)
if what.update then
what:update()
end
local endPoint = -math.huge
for i = 1, #what.children do
local child = what.children[i]
if not child.hidden then
endPoint = math.max(endPoint, child.localY + child.height - 1)
end
end
what.height = endPoint + addition
end
local function truncateEmoji(text)
text = text:gsub("&#%d+;", ":)")
return text
end
local function drawSelection(object, backgroundColor, textColor)
screen.drawText(object.x, object.y - 1, backgroundColor, string.rep("", object.width - 1) .. "")
screen.drawText(object.x, object.y + object.height, backgroundColor, string.rep("", object.width - 1) .. "")
screen.drawRectangle(object.x, object.y, object.width, object.height, backgroundColor, textColor, " ")
end
local function selectableSelect(object)
for i = 1, #object.parent.children do
object.parent.children[i].selected = object.parent.children[i] == object
end
workspace:draw()
if object.onTouch then
contentContainer.eventHandler = nil
object.onTouch()
end
end
local function selectableEventHandler(workspace, object, e1)
if e1 == "touch" then
object:select()
end
end
local function addSelectable(layout, method, height)
local object = layout:addChild(GUI[method](1, 1, layout.width, height))
object.eventHandler = selectableEventHandler
object.selected = false
object.select = selectableSelect
return object
end
local function pizdaDraw(object)
local textColor = style.leftToolbarDefaultForeground
if object.selected then
textColor = style.leftToolbarSelectedForeground
drawSelection(object, style.leftToolbarSelectedBackground, textColor)
end
screen.drawText(object.x + 2, math.floor(object.y + object.height / 2), textColor, object.name)
end
local maxPizdaLength = 0
local function pizdaSelect(object)
lastPizda = function()
object:select()
end
selectableSelect(object)
end
local function addPizda(name)
local object = addSelectable(leftLayout, "object", 1)
object.draw = pizdaDraw
object.name = name
object.select = pizdaSelect
maxPizdaLength = math.max(maxPizdaLength, unicode.len(name))
return object
end
local function addScrollEventHandler(layout, regularDirection, updater)
layout.eventHandler = function(workspace, layout, e1, e2, e3, e4, e5)
if e1 == "scroll" then
local cell = layout.cells[1][1]
if regularDirection then
if e5 > 0 then
cell.verticalMargin = cell.verticalMargin + config.scrollSpeed
if cell.verticalMargin > 1 then
cell.verticalMargin = 1
end
else
cell.verticalMargin = cell.verticalMargin - config.scrollSpeed
local lastChild = layout.children[#layout.children]
if lastChild.localY + lastChild.height - 1 < layout.height * (1 - config.updateContentTrigger) then
updater()
end
end
else
if e5 > 0 then
cell.verticalMargin = cell.verticalMargin - config.scrollSpeed
layout:update()
if layout.children[1].localY > layout.height * config.updateContentTrigger then
updater()
end
else
cell.verticalMargin = cell.verticalMargin + config.scrollSpeed
if cell.verticalMargin > 1 then
cell.verticalMargin = 1
end
end
end
workspace:draw()
end
end
end
local function getAbbreviatedFileSize(size, decimalPlaces)
if size < 1024 then
return number.roundToDecimalPlaces(size, 2) .. " B"
else
local power = math.floor(math.log(size, 1024))
return number.roundToDecimalPlaces(size / 1024 ^ power, decimalPlaces) .. " " .. ({"KB", "MB", "GB", "TB"})[power]
end
end
local function capitalize(text)
return unicode.upper(unicode.sub(text, 1, 1)) .. unicode.sub(text, 2, -1)
end
local function isPeerChat(id)
return id > 2000000000
end
local function isPeerGroup(id)
return id < 0
end
local function getEblo(where, id)
for i = 1, #where do
if where[i].id == id then
return where[i]
end
end
end
local function getSenderName(profiles, conversations, groups, peerID)
if isPeerChat(peerID) then
return conversations.chat_settings.title
elseif isPeerGroup(peerID) then
return getEblo(groups, -peerID).name
else
local eblo = getEblo(profiles, peerID)
return eblo.first_name .. " " .. eblo.last_name
end
end
local function getNameShortcut(name)
local first, second = name:match("([^%s]+)%s(.+)")
if first and second then
return unicode.upper(unicode.sub(first, 1, 1) .. unicode.sub(second, 1, 1))
else
return unicode.upper(unicode.sub(name, 1, 2))
end
end
local function getAvatarColors(peerID)
local hue = math.abs(peerID) % 360
return color.HSBToInteger(hue, 0.25, 1), color.HSBToInteger(hue, 1, 0.9)
end
local function avatarDraw(object)
screen.drawRectangle(object.x, object.y, object.width, object.height, object.backgroundColor, object.textColor, " ")
screen.drawText(math.floor(object.x + object.width / 2 - unicode.len(object.shortcut) / 2), math.floor(object.y + object.height / 2 - 1), object.textColor, object.shortcut)
if object.selected then
screen.drawRectangle(object.x, object.y, object.width, object.height, 0x0, 0x0, " ", 0.5)
end
end
local function avatarEventHandler(workspace, object, e1)
if e1 == "touch" then
object.selected = true
workspace:draw()
event.sleep(0.2)
object.selected = false
showUserProfile(object.peerID)
end
end
local function newAvatar(x, y, width, height, name, peerID)
local object = GUI.object(x, y, width, height)
object.backgroundColor, object.textColor = getAvatarColors(peerID)
object.draw = avatarDraw
object.shortcut = getNameShortcut(name)
object.peerID = peerID
-- Нехуй на группы тыкать, НИРИАЛИЗОВАНО ИЩО
if peerID > 0 then
object.eventHandler = avatarEventHandler
end
return object
end
local function verticalLineDraw(object)
for i = 1, object.height do
screen.drawText(object.x, object.y + i - 1, object.color, "")
end
end
local function newVerticalLine(x, y, height, color)
local object = GUI.object(x, y, 1, height)
object.draw = verticalLineDraw
object.color = color
return object
end
local function horizontalLineDraw(object)
screen.drawText(object.x, object.y, object.color, string.rep("", object.width))
end
local function newHorizontalLine(x, y, width, color)
local object = GUI.object(x, y, width, 1)
object.draw = horizontalLineDraw
object.color = color
return object
end
local function attachmentDraw(object)
-- screen.drawRectangle(object.x, object.y, object.width, 1, 0x880000, 0xA5A5A5, " ")
local x, y, typeLength = object.x, object.y, unicode.len(object.type)
-- Type
screen.drawText(x, y, object.typeB, ""); x = x + 1
screen.drawRectangle(x, y, typeLength + 2, 1, object.typeB, object.typeT, " "); x = x + 1
screen.drawText(x, y, object.typeT, object.type); x = x + typeLength + 1
local textB = object.selected and style.blockAttachmentTextSelectionBackground or object.textB
local textT = object.selected and style.blockAttachmentTextSelectionForeground or object.textT
screen.set(x, y, textB, object.typeB, ""); x = x + 1
-- Text
screen.drawRectangle(x, y, object.width - typeLength - 5, 1, textB, textT, " "); x = x + 1
screen.drawText(x, y, textT, text.limit(object.text, object.width - typeLength - 7))
screen.drawText(object.x + object.width - 1, y, textB, "")
-- if object.previewText or object.previewPicture then
-- screen.drawRectangle(object.x + 1, object.y + 1, object.width - 2, object.height - 1, 0xE1E1E1, 0x0, " ")
-- local centerX, centerY = object.x + object.width / 2, object.y + 1 + object.height / 2
-- if object.previewText then
-- screen.drawText(
-- math.floor(centerX - unicode.len(object.previewText) / 2),
-- object.y + 2,
-- 0x0,
-- object.previewText
-- )
-- else
-- screen.drawImage(
-- math.floor(centerX - image.getWidth(object.previewPicture) / 2),
-- math.floor(centerY - image.getHeight(object.previewPicture) / 2),
-- object.previewPicture
-- )
-- end
-- end
end
local function newAttachment(x, y, maxWidth, attachment, typeB, typeT, textB, textT)
local object = GUI.object(x, y, 1, 1)
object.typeB = typeB
object.typeT = typeT
object.textB = textB
object.textT = textT
object.type = capitalize(localization.attachmentsTypes[attachment.type])
if attachment.photo then
local maxIndex, maxWidth = 1, 0
for i = 1, #attachment.photo.sizes do
if maxWidth < attachment.photo.sizes[i].width then
maxIndex, maxWidth = i, attachment.photo.sizes[i].width
end
end
object.text = attachment.photo.sizes[maxIndex].width .. " x " .. attachment.photo.sizes[maxIndex].height .. " px"
elseif attachment.video then
object.text = attachment.video.title
elseif attachment.audio then
object.text = attachment.audio.artist .. " - " .. attachment.audio.title
elseif attachment.sticker then
object.text = ":)"
elseif attachment.link then
object.text = #attachment.link.title > 0 and attachment.link.title or attachment.link.url
elseif attachment.doc then
-- if attachment.doc.ext == "pic" then
-- object.type = "OC Image"
-- local cachePath = imageCachePath .. attachment.doc.owner_id .. "_" .. attachment.doc.id .. ".pic"
-- if attachment.doc.size <= config.maximumPreviewFileSize then
-- local function try()
-- local picture, reason = image.load(cachePath)
-- if picture then
-- if image.getWidth(picture) <= maxWidth then
-- object.previewPicture = picture
-- object.height = object.height + image.getHeight(picture) - 1
-- else
-- object.previewText = "Image is too big for preview"
-- end
-- else
-- object.previewText = tostring(reason)
-- end
-- end
-- if filesystem.exists(cachePath) then
-- try()
-- else
-- local success, reason = internet.download(attachment.doc.url, cachePath)
-- if success then
-- try()
-- else
-- object.previewText = "Failed to download image"
-- end
-- end
-- else
-- object.previewText = "Image file size is too big"
-- end
-- object.height = object.height + 3
-- end
object.text = attachment.doc.title .. ", " .. getAbbreviatedFileSize(attachment.doc.size)
elseif attachment.gift then
object.text = ":3"
elseif attachment.audio_message then
local length = 30
local values, trigger, value, counter, stepper, maxValue = {}, #attachment.audio_message.waveform / length, 0, 0, 0, 0
for i = 1, #attachment.audio_message.waveform do
value = value + attachment.audio_message.waveform[i]
if stepper > trigger then
table.insert(values, value / counter)
maxValue = math.max(maxValue, values[#values])
value, counter, stepper = 0, 0, stepper - trigger
else
counter, stepper = counter + 1, stepper + 1
end
end
local pixels = {"", "", "", ""}
object.text = ""
for i = 1, #values do
object.text = object.text .. (pixels[math.ceil(values[i] / maxValue * 4)] or "")
end
else
object.text = "N/A"
end
object.width = math.min(maxWidth, unicode.len(object.type) + unicode.len(object.text) + 7)
object.draw = attachmentDraw
object.eventHandler = attachmentEventHandler
return object
end
local function newPost(x, y, width, avatarWidth, senderColor, textColor, dateColor, lineColor, attachmentColorTypeB, attachmentColorTypeF, attachmentColorTextB, attachmentColorTextF, mainMessage, profiles, conversations, groups, senderName, fwdMessagesFieldName, data)
local object = GUI.container(x, y, width, 1)
local localX, localY = 1, 1
local avatar = object:addChild(newAvatar(localX, localY, avatarWidth, math.floor(avatarWidth / 2), getNameShortcut(senderName), data.from_id or data.source_id))
localX = localX + avatar.width + 1
local nameText = object:addChild(GUI.text(localX, localY, senderColor, senderName))
object:addChild(GUI.text(localX + nameText.width + 1, localY, dateColor, os.date("%H:%M", data.date)))
localY = localY + 1
if #data.text > 0 then
local lines = text.wrap(data.text, width - localX)
object.textBox = object:addChild(GUI.textBox(localX, localY, width - localX, #lines, nil, textColor, lines, 1, 0, 0))
object.textBox.eventHandler = nil
localY = localY + object.textBox.height + 1
else
localY = localY + 1
end
local function addAnotherPost(senderName, data)
-- localY = localY + (mainMessage and 0 or 1)
local offset = mainMessage and avatarWidth + 2 or 1
local attachment = object:addChild(
newPost(
offset + 2,
localY,
math.max(16, width - 6),
avatarWidth,
senderColor,
textColor,
dateColor,
lineColor,
attachmentColorTypeB,
attachmentColorTypeF,
attachmentColorTextB,
attachmentColorTextF,
false,
profiles,
conversations,
groups,
senderName,
fwdMessagesFieldName,
data
)
)
object:addChild(newVerticalLine(offset, localY, attachment.height, lineColor))
localY = localY + attachment.height + 1
end
if data.attachments and #data.attachments > 0 then
for i = 1, #data.attachments do
local attachment = data.attachments[i]
if localization.attachmentsTypes[attachment.type] then
if attachment.wall then
addAnotherPost(
attachment.wall.from.name or (attachment.wall.from.first_name .. " " .. attachment.wall.from.last_name),
attachment.wall
)
else
local attachment = object:addChild(newAttachment(localX, localY, object.width - localX, attachment, attachmentColorTypeB, attachmentColorTypeF, attachmentColorTextB, attachmentColorTextF))
localY = localY + attachment.height + 1
end
end
end
end
-- fwd_messages
if data[fwdMessagesFieldName] then
for i = 1, #data[fwdMessagesFieldName] do
addAnotherPost(
getSenderName(profiles, conversations, groups, data[fwdMessagesFieldName][i].from_id),
data[fwdMessagesFieldName][i]
)
end
end
if data.likes or data.reposts or data.views or data.comments then
local layout = object:addChild(GUI.layout(localX, localY, object.width - localX, 2, 1, 1))
layout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_BOTTOM)
layout:setDirection(1, 1, GUI.DIRECTION_HORIZONTAL)
layout:setSpacing(1, 1, 2)
local function addStuff(icon, text)
local container = layout:addChild(GUI.container(1, 1, 5 + unicode.len(text), 2))
container:addChild(GUI.image(1, 1, icon))
container:addChild(GUI.text(6, 2, style.counterText, text))
end
addStuff(icons.likes, tostring(data.likes and data.likes.count or 0))
addStuff(icons.comments, tostring(data.comments and data.comments.count or 0))
addStuff(icons.reposts, tostring(data.reposts and data.reposts.count or 0))
addStuff(icons.views, tostring(data.views and data.views.count or 0))
localY = localY + 3
end
object.height = localY - 2
-- object:addChild(GUI.panel(1, 1, width, object.height, math.random(0xFFFFFF)), 1)
return object
end
local function uploadDocument(path)
local fileName = filesystem.name(path)
local uploadServer = methodRequest("docs.getUploadServer?")
if uploadServer then
local boundary = "----WebKitFormBoundaryISgaMqjePLcGZFOx"
local handle = filesystem.open(path, "rb")
local data =
"--" .. boundary .. "\r\n" ..
"Content-Disposition: form-data; name=\"file\"; filename=\"" .. fileName .. "\"\r\n" ..
"Content-Type: application/octet-stream\r\n\r\n" ..
handle:read("*a") .. "\r\n" ..
"--" .. boundary .. "--"
handle:close()
local uploadResult, reason = request(
uploadServer.upload_url,
data,
{
["Content-Type"] = "multipart/form-data; boundary=" .. boundary,
["Content-Length"] = #data,
}
)
filesystem.writeTable("/test.txt", {
url = uploadServer.upload_url,
data = data,
size = #data,
}, true)
if uploadResult then
if uploadResult.file then
return methodRequest("docs.save?file=" .. uploadResult.file .. "&title=" .. fileName)
else
GUI.alert("UPLOAD ALMOST ZAEBIS, BUT NOT FILE", uploadResult)
end
else
GUI.alert("UPLOAD FAIL", reason)
end
end
end
local function getHistory(peerID, startMessageID)
return methodRequest("messages.getHistory?extended=1&fields=first_name,last_name,online&count=" .. config.loadCountMessages .. "&peer_id=" .. peerID .. (startMessageID and "&offset=1" or "") .. (startMessageID and ("&start_message_id=" .. startMessageID) or ""))
end
local function showHistory(container, peerID)
local messagesHistory = getHistory(peerID, nil)
if messagesHistory then
container:removeChildren()
local inputLayout = container:addChild(GUI.layout(1, container.height - 2, container.width, 3, 1, 1))
inputLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
inputLayout:setSpacing(1, 1, 0)
inputLayout:setDirection(1, 1, GUI.DIRECTION_HORIZONTAL)
local attachButton = inputLayout:addChild(GUI.adaptiveButton(1, 1, 2, 1, style.messageButtonDefaultBackground, style.messageButtonDefaultForeground, style.messageButtonPressedBackground, style.messageButtonPressedForeground, "+"))
attachButton.switchMode = true
local sendButton = inputLayout:addChild(GUI.adaptiveButton(1, 1, 2, 1, style.messageButtonDefaultBackground, style.messageButtonDefaultForeground, style.messageButtonPressedBackground, style.messageButtonPressedForeground, localization.send))
local input = inputLayout:addChild(GUI.input(1, 1, inputLayout.width - sendButton.width - attachButton.width, 3, style.messageInputBackground, style.messageInputForeground, style.messageInputPlaceholder, style.messageInputBackground, style.messageInputForeground, "", localization.typeMessageHere), 2)
local layout = container:addChild(GUI.layout(2, 1, container.width - 2, container.height - input.height, 1, 1))
layout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_BOTTOM)
layout:setMargin(1, 1, 0, 1)
local function addFromHistory(history)
for i = 1, #history.items do
local post = layout:addChild(
newPost(
2,
y,
container.width - 2,
4,
style.messageSelectedTitle,
style.messageSelectedText,
style.messageSelectedDate,
style.messageSelectedLine,
style.messageAttachmentTypeBackground,
style.messageAttachmentTypeForeground,
style.messageAttachmentTextBackground,
style.messageAttachmentTextForeground,
true,
history.profiles,
history.conversations,
history.groups,
getSenderName(
history.profiles,
history.conversations,
history.groups,
history.items[i].from_id
),
"fwd_messages",
history.items[i]
), 1
)
post.id = history.items[i].id
end
end
addFromHistory(messagesHistory)
addScrollEventHandler(layout, false, function()
local newMessagesHistory = getHistory(peerID, layout.children[1].id)
if newMessagesHistory then
addFromHistory(newMessagesHistory)
end
end)
local attachedPath
attachButton.onTouch = function()
if attachedPath then
attachedPath = nil
else
local filesystemDialog = GUI.addFilesystemDialog(window, true, 45, window.height - 5, "Open", "Cancel", "File name", "/")
filesystemDialog:setMode(GUI.IO_MODE_OPEN, GUI.IO_MODE_FILE)
filesystemDialog.onSubmit = function(path)
attachedPath = path
end
filesystemDialog:show()
end
end
sendButton.onTouch = function()
if #input.text > 0 then
local attachment
if attachedPath then
local saveResult = uploadDocument(attachedPath)
if saveResult then
attachment = "&attachment=doc" .. saveResult[1].owner_id .. "_" .. saveResult[1].id
end
attachedPath = nil
end
local sendResult = methodRequest("messages.send?peer_id=" .. peerID .. (attachment or "") .. (#input.text > 0 and ("&message=" .. internet.encode(input.text)) or ""))
if sendResult then
showHistory(container, peerID)
end
end
end
workspace:draw()
end
end
local function usersRequest(ids, nameCase, fields)
return methodRequest("users.get?name_case=" .. nameCase .. "&user_ids=" .. ids .. (fields and "&fields=" .. fields or ""))
end
local function friendsRequest(online, peerID, order, offset, count, fields)
return methodRequest("friends.get" .. (online and "Online" or "") .. "?name_case=Nom&user_id=" .. peerID .. "&order=" .. order .. (offset and "&offset=" .. offset or "") .. (count and "&count=" .. count or "") .. (fields and "&fields=" .. fields or ""))
end
local function wallRequest(peerID, offset, filter)
return methodRequest("wall.get?extended=1&fields=first_name,last_name&owner_id=" .. peerID .. "&offset=" .. offset .. "&count=" .. config.loadCountWall .. "&filter=" .. filter)
end
showUserProfile = function(peerID)
local friendsDisplayColumns, friendsDisplayRows = 3, 2
local friendsDisplayCount = friendsDisplayColumns * friendsDisplayRows
local friendsNameLimit = 6
local result = executeRequest([[
var me=API.users.get({"user_ids":]] .. peerID .. [[,"fields":"activities,education,tv,status,sex,schools,relation,quotes,personal,occupation,connections,counters,contacts,verified,city,country,site,last_seen,online,bdate,books,movies,music,games,universities,interests,home_town,relatives,friend_status","name_case":"Nom"})[0];
var args={"user_id":me.id,"order" :"random","count":]] .. friendsDisplayCount .. [[,"target_uid":]] .. peerID .. [[};
var AFR=API.friends.get(args);
args.count=null;
var OFR=API.friends.getOnline(args);
var MFR=API.friends.getMutual(args);
var OFC=OFR.length;
var MFC=MFR.length;
OFR=OFR.slice(0,]] .. friendsDisplayCount .. [[);
MFR=MFR.slice(0,]] .. friendsDisplayCount .. [[);
var S="";
var i=0;
while (i < AFR.items.length) {
S=S+AFR.items[i]+",";
i=i+1;
}
i=0;
while (i<OFR.length) {
S=S+OFR[i]+",";
i=i+1;
}
i=0;
while (i < MFR.length) {
S=S+MFR[i]+",";
i=i+1;
}
var SFI=API.users.get({"user_ids":S.substr(0,S.length - 1),"fields":"first_name"});
var AFI={};
var OFI={};
var MFI={};
var j;
i=0;
while (i < AFR.items.length) {
j=0;
while (j < SFI.length) {
if (AFR.items[i] == SFI[j].id) {
AFI.push(SFI[j]);
j=SFI.length;
}
j=j+1;
}
i=i+1;
}
i=0;
while (i < OFR.length) {
j=0;
while (j < SFI.length) {
if (OFR[i] == SFI[j].id) {
OFI.push(SFI[j]);
j=SFI.length;
}
j=j+1;
}
i=i+1;
}
i=0;
while (i < MFR.length) {
j=0;
while (j < SFI.length) {
if (MFR[i] == SFI[j].id) {
MFI.push(SFI[j]);
j=SFI.length;
}
j=j+1;
}
i=i+1;
}
return {
"user":me,
"all_friends":AFI,
"online_friends":OFI,
"mutual_friends":MFI,
"all_friends_count":AFR.count,
"online_friends_count":OFC,
"mutual_friends_count":MFC
};
]])
if result then
local wall = wallRequest(peerID, 0, "all")
if wall then
local user = result.user
local fullName = user.first_name .. " " .. user.last_name
local profileKeys = localization.profileKeys
contentContainer:removeChildren()
local userContainer = contentContainer:addChild(GUI.container(1, 1, contentContainer.width, 1))
-- Авочка
local leftLayout = userContainer:addChild(GUI.layout(3, 2, 24, 1, 1, 1))
leftLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
local avatarContainer = leftLayout:addChild(GUI.container(1, 1, leftLayout.width, 1))
local avatar = avatarContainer:addChild(newAvatar(3, 2, avatarContainer.width - 4, math.floor((avatarContainer.width - 4) / 2), getNameShortcut(fullName), user.id))
if peerID ~= currentPeerID then
local messageButton = avatarContainer:addChild(GUI.roundedButton(3, avatar.localY + avatar.height + 1, avatar.width, 1, style.blockButtonDefaultBackground, style.blockButtonDefaultForeground, style.blockButtonPressedBackground, style.blockButtonPressedForeground, localization.message))
messageButton.onTouch = function()
showConversations(peerID)
end
end
fitToLastChild(avatarContainer, 1)
addPanel(avatarContainer, style.blockBackground)
-- Список друзяшек
local function addFriendsList(title, titleCount, list)
if #list > 0 then
local rowsCount = math.min(math.ceil(#list / friendsDisplayColumns), friendsDisplayRows)
local container = leftLayout:addChild(GUI.container(1, 1, leftLayout.width, 3 + rowsCount * 5))
addPanel(container, style.blockBackground)
title = container:addChild(GUI.text(3, 2, style.blockTitle, title))
container:addChild(GUI.text(title.localX + title.width + 1, 2, style.blockValue, tostring(titleCount)))
local layout = container:addChild(GUI.layout(1, 4, container.width, container.height - 3, friendsDisplayColumns, rowsCount))
local index = 1
for row = 1, rowsCount do
for column = 1, friendsDisplayColumns do
if list[index] then
layout.defaultColumn, layout.defaultRow = column, row
local eblo = list[index]
layout:addChild(newAvatar(1, 1, 4, 2, getNameShortcut(eblo.first_name .. " " .. eblo.last_name), eblo.id))
layout:addChild(GUI.text(1, 4, 0xA5A5A5, text.limit(eblo.first_name, friendsNameLimit)))
index = index + 1
else
break
end
end
end
end
end
if peerID ~= currentPeerID then
addFriendsList(localization.friendsMutual, result.mutual_friends_count, result.mutual_friends)
end
addFriendsList(localization.friends, result.all_friends_count, result.all_friends)
addFriendsList(localization.friendsOnline, result.online_friends_count, result.online_friends)
-- Инфа о юзвере
local rightLayout = userContainer:addChild(GUI.layout(leftLayout.localX + leftLayout.width + 2, 2, userContainer.width - leftLayout.width - 6, 1, 1, 1))
rightLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
local infoContainer = rightLayout:addChild(GUI.container(1, 1, rightLayout.width, 1))
local infoPanel = addPanel(infoContainer, style.blockBackground)
local infoLayout = infoContainer:addChild(GUI.layout(infoPanel.localX + 2, infoPanel.localY + 1, infoPanel.width - 4, 1, 1, 1))
infoLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
infoLayout:setSpacing(1, 1, 0)
local layoutToAdd = infoLayout
local function addTitle(text)
local container = layoutToAdd:addChild(GUI.container(1, 1, layoutToAdd.width, 3))
if text then
text = container:addChild(GUI.text(1, 2, style.blockTitle, text))
container:addChild(newHorizontalLine(text.width + 2, 2, container.width - text.width - 1, style.blockLine))
else
container:addChild(newHorizontalLine(1, 2, container.width, style.blockLine))
end
end
local maxProfileKeyLength = 0
for key, value in pairs(profileKeys) do
maxProfileKeyLength = math.max(maxProfileKeyLength, unicode.len(value))
end
maxProfileKeyLength = maxProfileKeyLength + 4
local function addKeyAndValue(key, value)
local container = layoutToAdd:addChild(GUI.container(1, 1, layoutToAdd.width, 1))
container:addChild(GUI.text(1, 1, style.blockKey, key .. ": "))
local width = container.width - maxProfileKeyLength
local lines = text.wrap(value, width)
container:addChild(GUI.textBox(maxProfileKeyLength, 1, width, #lines, nil, style.blockValue, lines, 1)).eventHandler = nil
container.height = #lines
end
local function isTypeValid(what)
local whatType = type(what)
return what and (whatType == "string" and #what > 0 or whatType == "number" and what ~= 0)
end
local function anyExists(...)
local args = {...}
for i = 1, #args do
if isTypeValid(args[i]) then
return true
end
end
end
local function addIfExists(what, ...)
if isTypeValid(what) then
addKeyAndValue(...)
end
end
infoLayout:addChild(GUI.text(1, 1, style.blockTitle, fullName))
if user.status and #user.status > 0 then
local statusButton = infoLayout:addChild(GUI.adaptiveButton(1, 1, 0, 0, nil, style.blockValue, nil, 0x0, user.status_audio and ("* " .. user.status_audio.artist .. " - " .. user.status_audio.title) or user.status))
end
addTitle()
if user.bdate then
local cyka = {}
for part in user.bdate:gmatch("%d+") do
table.insert(cyka, part)
end
addKeyAndValue(profileKeys.birthday, cyka[1] .. " " .. localization.months[tonumber(cyka[2])] .. (cyka[3] and " " .. cyka[3] or ""))
end
if user.city then
addKeyAndValue(profileKeys.city, user.city.title == "Москва" and "Массква" or user.city.title)
end
addIfExists(user.relation, profileKeys.relation, localization.relationStatuses[user.sex > 0 and user.sex or 1][user.relation])
if user.occupation then
addKeyAndValue(profileKeys.occupation, user.occupation.name)
end
if user.university_name and #user.university_name > 0 then
addKeyAndValue(profileKeys.education, user.university_name .. "'" .. tostring(user.graduation):sub(-2, -1))
end
addIfExists(user.site, profileKeys.site, user.site)
-- Вот тута начинается дополнительная инфа
local expandButton = infoLayout:addChild(GUI.button(1, 1, infoLayout.width, 2, nil, style.blockTextButton, nil, 0x0, ""))
local additionalLayout = infoLayout:addChild(GUI.layout(1, 1, infoLayout.width, 1, 1, 1))
additionalLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
additionalLayout:setSpacing(1, 1, 0)
additionalLayout.hidden = true
layoutToAdd = additionalLayout
-- Основная инфа
if anyExists(user.home_town, user.personal and user.personal.langs) then
addTitle(localization.profileTitleMainInformation)
addIfExists(user.home_town, profileKeys.homeCity, user.home_town)
if user.personal and user.personal.langs then
addKeyAndValue(profileKeys.languages, table.concat(user.personal.langs, ", "))
end
end
-- Контакты
if anyExists(user.mobile_phone, user.home_phone, user.skype, user.instagram, user.facebook) then
addTitle(localization.profileTitleContacts)
addIfExists(user.mobile_phone, profileKeys.mobilePhone, user.mobile_phone)
addIfExists(user.home_phone, profileKeys.homePhone, user.home_phone)
addIfExists(user.skype, "Skype", user.skype)
addIfExists(user.instagram, "Instagram", user.instagram)
addIfExists(user.facebook, "Facebook", user.facebook)
end
if user.personal and anyExists(user.personal.political, user.personal.religon, user.personal.life_main, user.personal.people_main, user.personal.smoking, user.personal.alcohol, user.personal.inspired_by) then
addTitle(localization.profileTitlePersonal)
addIfExists(user.personal.political, profileKeys.political, localization.personalPoliticalTypes[user.personal.political])
addIfExists(user.personal.religon, profileKeys.religion, user.personal.religon)
addIfExists(user.personal.life_main, profileKeys.lifeMain, localization.personalLifeMainTypes[user.personal.life_main])
addIfExists(user.personal.people_main, profileKeys.peopleMain, localization.personalPeopleMainTypes[user.personal.people_main])
addIfExists(user.personal.smoking, profileKeys.smoking, localization.personalBlyadTypes[user.personal.smoking])
addIfExists(user.personal.alcohol, profileKeys.alcohol, localization.personalBlyadTypes[user.personal.alcohol])
addIfExists(user.personal.inspired_by, profileKeys.inspiredBy, user.personal.inspired_by)
end
if anyExists(user.activities, user.interests, user.music, user.movies, user.tv, user.games, user.books, user.quotes) then
addTitle(localization.profileTitleAdditions)
addIfExists(user.activities, profileKeys.activities, user.activities)
addIfExists(user.interests, profileKeys.interests, user.interests)
addIfExists(user.music, profileKeys.music, user.music)
addIfExists(user.movies, profileKeys.movies, user.movies)
addIfExists(user.tv, profileKeys.tv, user.tv)
addIfExists(user.games, profileKeys.games, user.games)
addIfExists(user.books, profileKeys.books, user.books)
addIfExists(user.quotes, profileKeys.quotes, user.quotes)
end
-- И снова добавляем в основной лейаут
layoutToAdd = infoLayout
addTitle()
local statsLayout = layoutToAdd:addChild(GUI.layout(1, 1, layoutToAdd.width, 2, 1, 1))
statsLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_CENTER, GUI.ALIGNMENT_VERTICAL_TOP)
statsLayout:setDirection(1, 1, GUI.DIRECTION_HORIZONTAL)
statsLayout:setSpacing(1, 1, 2)
local function counterDraw(object)
local centerX = object.x + object.width / 2
screen.drawText(math.floor(centerX - object.countLength / 2), object.y, style.blockTitle, object.count)
screen.drawText(math.floor(centerX - object.descriptionLength / 2), object.y + 1, style.blockValue, object.description)
end
for i = 1, #localization.profileCounters do
local count = user.counters[localization.profileCounters[i].field]
if count then
local object = GUI.object(1, 1, 1, 2)
object.count = tostring(count)
object.description = localization.profileCounters[i].description
object.countLength = unicode.len(object.count)
object.descriptionLength = unicode.len(object.description)
object.width = math.max(object.countLength, object.descriptionLength)
object.draw = counterDraw
statsLayout:addChild(object)
end
end
-- Стена
local wallLayout = rightLayout:addChild(GUI.layout(1, 1, rightLayout.width, 1, 1, 1))
wallLayout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
for i = 1, #wall.items do
local item = wall.items[i]
local post = newPost(
3,
2,
rightLayout.width - 4,
4,
style.blockTitle,
style.blockText,
style.blockDate,
style.blockLine,
style.blockAttachmentTypeBackground,
style.blockAttachmentTypeForeground,
style.blockAttachmentTextBackground,
style.blockAttachmentTextForeground,
true,
wall.profiles,
wall.conversations,
wall.groups,
getSenderName(wall.profiles, wall.conversations, wall.groups, item.from_id),
"copy_history",
item
)
local container = wallLayout:addChild(GUI.container(1, 1, rightLayout.width, post.height + 2))
addPanel(container, style.blockBackground)
container:addChild(post)
end
fitToLastChild(wallLayout, 0)
local function update()
-- Фиттим дополнительный лейаут
fitToLastChild(additionalLayout, 0)
-- Фиттим лейаут с инфой
fitToLastChild(infoLayout, 0)
-- Подгоняем контейнер под него
infoContainer.height = infoLayout.height + 2
infoPanel.height = infoContainer.height
-- Фиттим лево-правые лейауты
fitToLastChild(leftLayout, 1)
fitToLastChild(rightLayout, 1)
-- Фиттим весь юзер-контейнер с авой, друганами и всем дерьмом
fitToLastChild(userContainer, 0)
-- Ой, кнопочка!
expandButton.text = additionalLayout.hidden and localization.profileShowAdditional or localization.profileHideAdditional
end
update()
expandButton.onTouch = function()
additionalLayout.hidden = not additionalLayout.hidden
update()
end
contentContainer.eventHandler = function(workspace, contentContainer, e1, e2, e3, e4, e5)
if e1 == "scroll" then
userContainer.localY = userContainer.localY + (e5 > 0 and 1 or -1) * config.scrollSpeed
if userContainer.localY + userContainer.height - 1 < contentContainer.height then
userContainer.localY = contentContainer.height - userContainer.height
end
if userContainer.localY > 1 then
userContainer.localY = 1
end
workspace:draw()
end
end
end
end
end
local profileSelectable = addPizda(localization.profile)
profileSelectable.onTouch = function()
showUserProfile(currentPeerID)
-- Яша
-- showUserProfile(60991376)
-- Яна
-- showUserProfile(155326634)
-- Крутой
-- showUserProfile(21321257)
end
local function showFriends(peerID)
local offset = 0
local function getFriends()
local result = executeRequest([[
var friends = API.friends.get({"offset":]] .. offset .. [[,"count":]] .. config.loadCountFriends .. [[,"order": "hints","fields":"first_name,last_name,occupation"});
var lists = API.friends.getLists();
return {
"friends": friends.items,
"lists": lists.items,
"friends_count": friends.count
};
]])
if result then
-- Удобнее!
local newLists = {}
for i = 1, #result.lists do
newLists[result.lists[i].id] = result.lists[i].name
end
result.lists = newLists
return result
end
end
local friends = getFriends()
if friends then
contentContainer:removeChildren()
local layout = contentContainer:addChild(GUI.layout(3, 1, contentContainer.width - 4, contentContainer.height, 1, 1))
layout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
layout:setMargin(1, 1, 0, 1)
local function addFromList(result)
for i = 1, #result.friends do
local friend = result.friends[i]
local fullName = friend.first_name .. " " .. friend.last_name
local container = layout:addChild(GUI.container(1, 1, layout.width, 1))
local avatar = container:addChild(newAvatar(3, 2, 8, 4, getNameShortcut(fullName), friend.id))
local startX = avatar.localX + avatar.width + 2
local x, y = startX, avatar.localY
container:addChild(GUI.text(startX, y, style.blockTitle, fullName)); y = y + 1
if friend.occupation then
container:addChild(GUI.text(startX, y, style.blockValue, friend.occupation.name)); y = y + 1
end
y = y + 1
if friend.lists then
local offset, space = 1, 2
for j = 1, #friend.lists do
local text = result.lists[friend.lists[j]] or "N/A"
if x + unicode.len(text) + offset * 2 >= container.width then
x, y = startX, y + 2
end
local button = container:addChild(GUI.adaptiveRoundedButton(x, y, offset, 0, style.blockButtonDefaultBackground, style.blockButtonDefaultForeground, style.blockButtonPressedBackground, style.blockButtonPressedForeground, text))
x = x + button.width + space
end
y = y + 2
end
container:addChild(GUI.adaptiveButton(startX, y, 0, 0, nil, style.blockTextButton, nil, 0x0, localization.sendMessage)).onTouch = function()
showConversations(friend.id)
end
fitToLastChild(container, 1)
addPanel(container, style.blockBackground)
end
end
addFromList(friends)
addScrollEventHandler(layout, true, function()
offset = offset + config.loadCountFriends
local friends = getFriends()
if friends then
addFromList(friends)
workspace:draw()
end
end)
end
end
local newsSelectable = addPizda(localization.news)
newsSelectable.onTouch = function()
local function getNews(startFrom)
return methodRequest("newsfeed.get?filters=post&fields=first_name,last_name,name&count=" .. config.loadCountNews .. (startFrom and ("&start_from=" .. startFrom) or ""))
end
local news = getNews(nil)
if news then
contentContainer:removeChildren()
local layout = contentContainer:addChild(GUI.layout(3, 1, contentContainer.width - 4, contentContainer.height, 1, 1))
layout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
layout:setSpacing(1, 1, 1)
layout:setMargin(1, 1, 0, 1)
local function addFromList(list)
for i = 1, #list.items do
local item = list.items[i]
local postContainer = layout:addChild(GUI.container(1, 1, layout.width, 1))
local post = postContainer:addChild(
newPost(
3,
2,
postContainer.width - 4,
6,
style.blockTitle,
style.blockText,
style.blockDate,
style.blockLine,
style.blockAttachmentTypeBackground,
style.blockAttachmentTypeForeground,
style.blockAttachmentTextBackground,
style.blockAttachmentTextForeground,
true,
list.profiles,
list.conversations,
list.groups,
getSenderName(list.profiles, list.conversations, list.groups, item.source_id),
"copy_history",
item
)
)
postContainer.height = post.height + 2
postContainer:addChild(GUI.panel(1, 1, postContainer.width, postContainer.height, style.blockBackground), 1)
end
end
addFromList(news)
local nextFrom = news.next_from
addScrollEventHandler(layout, true, function()
local newNews = getNews(nextFrom)
if newNews then
nextFrom = newNews.next_from
addFromList(newNews)
end
end)
workspace:draw()
end
end
showConversations = function(peerID)
local function getConversations(startMessageID)
return methodRequest("messages.getConversations?filter=all&extended=1&fields=first_name,last_name,online,id&count=" .. config.loadCountConversations .. (startMessageID and "&offset=1" or "") .. (startMessageID and ("&start_message_id=" .. startMessageID) or ""))
end
local result = getConversations(nil)
if result then
contentContainer:removeChildren()
local layout = contentContainer:addChild(GUI.layout(1, 1, 28, contentContainer.height, 1, 1))
layout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
layout:setSpacing(1, 1, 1)
layout:setMargin(1, 1, 0, 1)
local conversationPanel = contentContainer:addChild(GUI.panel(layout.width + 1, 1, contentContainer.width - layout.width, contentContainer.height, style.messageSelectedBackground))
local conversationContainer = contentContainer:addChild(GUI.container(conversationPanel.localX, 1, conversationPanel.width, conversationPanel.height))
local function conversationDraw(container)
if container.selected then
container.senderText.color = style.messageSelectedTitle
container.messagePreviewText.color = style.messageSelectedText
container.dateText.color = style.messageSelectedDate
drawSelection(container, style.messageSelectedBackground, style.blockTitle)
else
container.senderText.color = style.messageTitle
container.messagePreviewText.color = style.messageText
container.dateText.color = style.messageDate
end
-- Спиздим метод у этого контейнера. Надеюсь, он не обидится
contentContainer.draw(container)
end
local function addFromList(list)
for i = 1, #list.items do
local item = list.items[i]
-- Превью текста сообщеньки с вложениями и прочей залупой
local messagePreview
if #item.last_message.text == 0 then
if #item.last_message.fwd_messages > 0 then
messagePreview = localization.fwdMessages .. #item.last_message.fwd_messages
elseif #item.last_message.attachments > 0 then
local data = {}
for i = 1, #item.last_message.attachments do
if localization.attachmentsTypes[item.last_message.attachments[i].type] then
data[i] = localization.attachmentsTypes[item.last_message.attachments[i].type] or "N/A"
end
end
messagePreview = table.concat(data, ", ")
else
messagePreview = item.last_message.text
end
else
messagePreview = item.last_message.text
end
-- Префиксы для отправленных мною, либо же для имен отправителей в конфах
if item.last_message.out == 1 then
messagePreview = localization.you .. messagePreview
else
if isPeerChat(item.conversation.peer.id) then
local eblo = getEblo(list.profiles, item.last_message.from_id)
messagePreview = eblo.first_name .. ": " .. messagePreview
end
end
local container = addSelectable(layout, "container", 2)
container.id = item.last_message.id
container.selected = item.conversation.peer.id == peerID
local senderName = getSenderName(list.profiles, item.conversation, list.groups, item.conversation.peer.id)
local avatar = container:addChild(newAvatar(2, 1, 4, 2, getNameShortcut(senderName), item.conversation.peer.id))
container.senderText = container:addChild(GUI.text(avatar.localX + avatar.width + 1, 1, 0x0, text.limit(senderName, container.width - avatar.width - 9)))
container.messagePreviewText = container:addChild(GUI.text(container.senderText.localX, 2, 0x0, text.limit(messagePreview, container.width - avatar.width - 3)))
container.dateText = container:addChild(GUI.text(container.width - 5, 1, 0x0, os.date("%H:%M", item.last_message.date)))
container.draw = conversationDraw
container.onTouch = function()
showHistory(conversationContainer, item.conversation.peer.id)
end
end
end
addFromList(result)
addScrollEventHandler(layout, true, function()
local newConversations = getConversations(layout.children[#layout.children].id)
if newConversations then
addFromList(newConversations)
end
end)
if peerID then
showHistory(conversationContainer, peerID)
else
if #layout.children > 0 then
layout.children[1]:select()
else
workspace:draw()
end
end
end
end
local conversationsSelectable = addPizda(localization.conversations)
conversationsSelectable.onTouch = function()
showConversations()
end
local friendsSelectable = addPizda(localization.friends)
friendsSelectable.onTouch = function()
showFriends(currentPeerID)
end
local function showDocuments()
local offset = 0
local function getDocs()
return methodRequest("docs.get?owner_id=" .. currentPeerID .. "&count=" .. config.loadCountDocs .. "&offset=" .. offset)
end
local docs = getDocs()
if docs then
contentContainer:removeChildren()
local layout = contentContainer:addChild(GUI.layout(3, 1, contentContainer.width - 4, contentContainer.height, 1, 1))
layout:setAlignment(1, 1, GUI.ALIGNMENT_HORIZONTAL_LEFT, GUI.ALIGNMENT_VERTICAL_TOP)
layout:setSpacing(1, 1, 1)
layout:setMargin(1, 1, 0, 1)
local container = layout:addChild(GUI.container(1, 1, layout.width, 1))
container:addChild(GUI.keyAndValue(3, 1, style.blockTitle, style.blockText, localization.documentsCount .. ": ", tostring(docs.count)))
local button = container:addChild(GUI.adaptiveRoundedButton(1, 1, 2, 0, style.blockButtonDefaultBackground, style.blockButtonDefaultForeground, style.blockButtonPressedBackground, style.blockButtonPressedForeground, localization.documentsAdd))
button.localX = container.width - button.width - 1
button.onTouch = function()
local filesystemDialog = GUI.addFilesystemDialog(window, true, 45, window.height - 5, "Open", "Cancel", "File name", "/")
filesystemDialog:setMode(GUI.IO_MODE_OPEN, GUI.IO_MODE_FILE)
filesystemDialog.onSubmit = function(path)
local saveResult = uploadDocument(path)
if saveResult then
showDocuments()
end
end
filesystemDialog:show()
end
local function addFromList(list)
for i = 1, #list do
local item = list[i]
local container = layout:addChild(GUI.container(1, 1, layout.width, 4))
addPanel(container, style.blockBackground)
container:addChild(GUI.text(3, 2, style.blockTitle, item.title))
container:addChild(GUI.text(3, 3, style.blockText, getAbbreviatedFileSize(item.size, 2) .. ", " .. os.date("%d.%m.%Y %H:%M", item.date)))
end
end
addFromList(docs.items)
addScrollEventHandler(layout, true, function()
offset = offset + config.loadCountDocs
local newDocs = getDocs()
if newDocs then
addFromList(newDocs.items)
end
end)
end
workspace:draw()
end
addPizda(localization.documents).onTouch = function()
showDocuments()
end
local function applyStyle()
window.backgroundPanel.colors.background = style.leftToolbarSelectedBackground
leftPanel.colors.background = style.leftToolbarDefaultBackground
progressIndicator.colors.passive, progressIndicator.colors.primary, progressIndicator.colors.secondary = style.UIProgressIndicatorPassive, style.UIProgressIndicatorPrimary, style.UIProgressIndicatorSecondary
for _, icon in pairs(icons) do
for y = 1, image.getHeight(icon) do
for x = 1, image.getWidth(icon) do
local b, f, a, s = image.get(icon, x, y)
image.set(icon, x, y, b, style.counterIcon, a, s)
end
end
end
end
local settingsSelectable = addPizda(localization.settings)
settingsSelectable.onTouch = function()
contentContainer:removeChildren()
local layout = contentContainer:addChild(GUI.layout(1, 1, contentContainer.width, contentContainer.height, 1, 1))
local function addYobaSlider(min, max, field)
local slider = layout:addChild(GUI.slider(1, 1, 36, style.UISliderPrimary, style.UISliderSecondary, style.UISliderPipe, style.UISliderValue, min, max, config[field], false, localization[field] .. ": ", ""))
slider.roundValues = true
slider.onValueChanged = function()
config[field] = number.round(slider.value)
saveConfig()
end
end
layout:addChild(GUI.text(1, 1, style.UITitle, localization.settingsStyle))
local comboBox = layout:addChild(GUI.comboBox(1, 1, 36, 3, style.UIComboBoxBackground, style.UIComboBoxForeground, style.UIComboBoxArrowBackground, style.UIComboBoxArrowForeground))
local list = filesystem.list(stylesPath)
for i = 1, #list do
if filesystem.extension(list[i]) == ".lua" then
comboBox:addItem(filesystem.hideExtension(list[i])).onTouch = function()
config.style = list[i]
loadStyle()
applyStyle()
lastPizda()
saveConfig()
end
if list[i] == config.style then
comboBox.selectedItem = comboBox:count()
end
end
end
layout:addChild(GUI.text(1, 1, style.UITitle, localization.settingsAdditional))
addYobaSlider(2, 50, "loadCountConversations")
addYobaSlider(2, 50, "loadCountMessages")
addYobaSlider(2, 50, "loadCountFriends")
addYobaSlider(2, 50, "loadCountNews")
addYobaSlider(2, 50, "loadCountWall")
addYobaSlider(2, 50, "loadCountDocs")
addYobaSlider(2, 10, "scrollSpeed")
workspace:draw()
end
local function login()
local loginContainer = window:addChild(GUI.container(1, 1, window.width, window.height), #window.children)
addPanel(loginContainer, style.UIBackground)
local layout = loginContainer:addChild(GUI.layout(1, 1, loginContainer.width, loginContainer.height, 1, 1))
local logo = layout:addChild(GUI.image(1, 1, image.load(scriptDirectory .. "Icon.pic")))
logo.height = logo.height + 1
local usernameInput = layout:addChild(GUI.input(1, 1, 36, 3, style.UIInputBackground, style.UIInputForeground, style.UIInputPlaceholder, style.UIInputBackground, style.UIInputFocusedForeground, config.username or "", localization.username))
local passwordInput = layout:addChild(GUI.input(1, 1, 36, 3, style.UIInputBackground, style.UIInputForeground, style.UIInputPlaceholder, style.UIInputBackground, style.UIInputFocusedForeground, config.password or "", localization.password, true, ""))
local loginButton = layout:addChild(GUI.button(1, 1, 36, 3, style.UIButtonDefaultBackground, style.UIButtonDefaultForeground, style.UIButtonPressedBackground, style.UIButtonPressedForeground, localization.login))
loginButton.colors.disabled = {
background = style.UIButtonDisabledBackground,
text = style.UIButtonDisabledForeground,
}
local saveSwitch = layout:addChild(GUI.switchAndLabel(1, 1, 36, 6, style.UISwitchActive, style.UISwitchPassive, style.UISwitchPipe, style.UIText, localization.saveLogin, true))
local loginusernameInput = layout:addChild(GUI.label(1, 1, 36, 1, style.UIText, localization.invalidPassword))
loginusernameInput.hidden = true
usernameInput.onInputFinished = function()
loginButton.disabled = #usernameInput.text == 0 or #passwordInput.text == 0
workspace:draw()
end
passwordInput.onInputFinished = usernameInput.onInputFinished
loginButton.onTouch = function()
local result, reason = request("https://oauth.vk.com/token?grant_type=password&client_id=3697615&client_secret=AlVXZFMUqyrnABp8ncuU&username=" .. usernameInput.text .. "&password=" .. passwordInput.text .. "&v=" .. VKAPIVersion)
if result then
if result.access_token then
currentAccessToken = result.access_token
currentPeerID = result.user_id
config.accessToken = saveSwitch.switch.state and currentAccessToken or nil
config.username = saveSwitch.switch.state and usernameInput.text or nil
config.peerID = saveSwitch.switch.state and currentPeerID or nil
loginContainer:remove()
conversationsSelectable:select()
else
loginusernameInput.hidden = false
logout()
end
saveConfig()
end
end
lastPizda = login
usernameInput.onInputFinished()
workspace:draw()
end
local function logout()
currentAccessToken = nil
currentPeerID = nil
config.accessToken = nil
config.peerID = nil
login()
end
addPizda(localization.exit).onTouch = function()
logout()
saveConfig()
end
window.onResize = function(width, height)
leftPanel.width, leftPanel.height = maxPizdaLength + localization.leftBarOffset, height
leftLayout.width, leftLayout.height = leftPanel.width, leftPanel.height - 2
progressIndicator.localX, progressIndicator.localY = math.floor(leftPanel.width / 2 - 1), leftPanel.height - progressIndicator.height + 1
for i = 1, #leftLayout.children do
leftLayout.children[i].width = leftLayout.width
end
window.backgroundPanel.localX, window.backgroundPanel.width, window.backgroundPanel.height = leftPanel.width + 1, width - leftPanel.width, height
contentContainer.localX, contentContainer.width, contentContainer.height = window.backgroundPanel.localX, window.backgroundPanel.width, window.backgroundPanel.height
if lastPizda then
lastPizda()
end
end
--------------------------------------------------------------------------------
currentAccessToken = config.accessToken
currentPeerID = config.peerID
window.actionButtons.localX = 3
window.actionButtons:moveToFront()
window:resize(window.width, window.height)
applyStyle()
if currentAccessToken then
conversationsSelectable:select()
else
login()
end