local args = {...} require("advancedLua") local component = require("component") local computer = require("computer") local web = require("web") local GUI = require("GUI") local buffer = require("doubleBuffering") local MineOSCore = require("MineOSCore") local MineOSPaths = require("MineOSPaths") local MineOSInterface = require("MineOSInterface") local image = require("image") local fs = require("filesystem") local color = require("color") local unicode = require("unicode") -------------------------------------------------------------------------------- local host = "http://eliteclubsessions.ru/mineos/appmarket/" local luaIcon = image.load(MineOSPaths.icons .. "Lua.pic") local fileNotExistsIcon = image.load(MineOSPaths.icons .. "FileNotExists.pic") local scriptIcon = image.load(MineOSPaths.icons .. "Script.pic") local localization = MineOSCore.getCurrentApplicationLocalization() local appMarketPath = MineOSPaths.applicationData .. "AppMarket/" local configPath = appMarketPath .. "Config.cfg" local iconCachePath = appMarketPath .. "Cache/" fs.makeDirectory(iconCachePath) local config = { language_id = 18, orderBy = 1, orderDirection = 1, user = {}, versions = {}, } local categories = { localization.categoryApplications, localization.categoryLibraries, localization.categoryScripts, } local orderDirections = { "desc", "asc", } local downloadPaths = { "/MineOS/Applications/", "/lib/", "/bin/", } local licenses = { "MIT", "GNU GPLv3", "GNU AGPLv3", "GNU LGPLv3", "Apache Licence 2.0", "Mozilla Public License 2.0", "The Unlicense", } local orderBys = { "rating", "name", "date", } local languages = { [3] = "Arabic", [6] = "Belarusian", [7] = "Bulgarian", [12] = "Czech", [15] = "German", [16] = "Greek", [18] = "English", [20] = "Spanish", [21] = "Estonian", [24] = "Finnish", [25] = "French", [31] = "Hindi", [38] = "Italian", [39] = "Japanese", [45] = "Korean", [47] = "Latin", [64] = "Dutch", [65] = "Norwegian", [68] = "Polish", [69] = "Portuguese", [70] = "Romanian", [71] = "Russian", [78] = "Swedish", [83] = "Thai", [85] = "Turkish", [88] = "Ukrainian", [91] = "Vietnamese", [94] = "Chinese", } local search = "" local appWidth, appHeight, appHSpacing, appVSpacing, currentPage, appsPerPage, appsPerWidth, appsPerHeight = 34, 6, 2, 1, 0 local updateFileList, editPublication -------------------------------------------------------------------------------- local mainContainer, window = MineOSInterface.addWindow(MineOSInterface.tabbedWindow(1, 1, 110, 30)) local contentContainer = window:addChild(GUI.container(1, 4, 1, 1)) local statusWidget = window:addChild(GUI.object(1, 1, 1, 1)) statusWidget.draw = function() buffer.square(statusWidget.x, statusWidget.y, statusWidget.width, 1, 0x2D2D2D, 0xF0F0F0, " ") buffer.text(statusWidget.x + 1, statusWidget.y, 0xF0F0F0, statusWidget.text) end -------------------------------------------------------------------------------- local function saveConfig() table.toFile(configPath, config, true) end local function loadConfig() if fs.exists(configPath) then config = table.fromFile(configPath) else saveConfig() end end -------------------------------------------------------------------------------- local function RawAPIRequest(script, data, notUnserialize) -- local requestResult, requestReason = web.request(host .. script .. ".php?" .. web.serialize(data)) local requestResult, requestReason = web.request(host .. script .. ".php?" .. web.serialize(data, true), nil, { ["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36", -- ["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", -- ["Accept-Language"] = "en-us,en;q=0.5", -- ["Accept-Charset"] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7" }) if requestResult then if not notUnserialize then local unserializeResult, unserializeReason = table.fromString(requestResult) if unserializeResult then if unserializeResult.success then return unserializeResult else return false, "API request not succeded: " .. tostring(unserializeResult.reason) end else return false, "Failed to unserialize response data: " .. tostring(unserializeReason) end else return result end else return false, "Web request failed: " .. tostring(requestReason) end end local function fieldAPIRequest(fieldToReturn, script, data) local success, reason = RawAPIRequest(script, data) if success then if success[fieldToReturn] then return success[fieldToReturn] else GUI.error("Request was successful, but field " .. tostring(fieldToReturn) .. " doesn't exists") end else GUI.error(reason) end end local function checkContentLength(url) local handle = component.internet.request(url) if handle then local _, _, responseData repeat _, _, responseData = handle:response() until responseData local contentLength = tonumber(responseData["Content-Length"][1]) if contentLength <= 10240 then return handle else handle:close() return false, "Specified image size is too big" end else return false, "Invalid URL" end end local function checkImage(url, mneTolkoSprosit) local handle, reason = checkContentLength(url) if handle then local needCheck, data, chunk, reason = true, "" while true do chunk, reason = handle.read(math.huge) if chunk then data = data .. chunk if needCheck and #data > 8 then if data:sub(1, 4) == "OCIF" then if string.byte(data:sub(6, 6)) <= 8 and string.byte(data:sub(7, 7)) <= 4 then if mneTolkoSprosit then handle:close() return true end needCheck = false else handle:close() return false, "Image size is larger than 8x4" end else handle:close() return false, "Wrong image file signature" end end else handle:close() if reason then return false, reason else return data end end end else return false, reason end end local function tryToDownload(...) local success, reason = web.download(...) if not success then GUI.error(reason) end end -------------------------------------------------------------------------------- local lastMethod, lastArguments local function callLastMethod() lastMethod(table.unpack(lastArguments)) end local function status(text) statusWidget.text = text MineOSInterface.OSDraw() end local function newButtonsLayout(x, y, width, spacing) local buttonsLayout = GUI.layout(x, y, width, 1, 1, 1) buttonsLayout:setCellDirection(1, 1, GUI.directions.horizontal) buttonsLayout:setCellSpacing(1, 1, spacing) return buttonsLayout end local function getUpdateState(publication) if config.versions[publication.publication_name] then if fs.exists(config.versions[publication.publication_name].path) then if config.versions[publication.publication_name].version >= publication.version then return 4 else return 3 end else return 2 end else return 1 end end local function ratingWidgetDraw(object) local x = 0 for i = 1, 5 do buffer.text(object.x + x, object.y, object.rating >= i and object.colors.first or object.colors.second, "*") x = x + object.spacing end return object end local function newRatingWidget(x, y, rating, firstColor, secondColor) local object = GUI.object(x, y, 9, 1) object.colors = { first = firstColor or 0xFFB600, second = secondColor or 0xC3C3C3 } object.spacing = 2 object.draw = ratingWidgetDraw object.rating = rating return object end local function deletePublication(publication) local container = MineOSInterface.addUniversalContainer(MineOSInterface.mainContainer, localization.areYouSure) local buttonsLayout = container.layout:addChild(newButtonsLayout(1, 1, container.layout.width, 2)) buttonsLayout:addChild(GUI.adaptiveButton(1, 1, 2, 0, 0xA5A5A5, 0x2D2D2D, 0x0, 0xE1E1E1, localization.no)).onTouch = function() container:delete() MineOSInterface.OSDraw() end buttonsLayout:addChild(GUI.adaptiveButton(1, 1, 2, 0, 0xE1E1E1, 0x2D2D2D, 0x0, 0xE1E1E1, localization.yes)).onTouch = function() local success, reason = RawAPIRequest("delete", { token = config.user.token, publication_name = publication.publication_name, }) if success then container:delete() updateFileList(publication.category_id) else GUI.error(reason) end end end -------------------------------------------------------------------------------- local function getDependencyPath(mainFilePath, dependency) local path -- Если зависимость - эт публикация if dependency.publication_name then path = downloadPaths[dependency.category_id] .. dependency.path -- Если зависимость - эт ресурс else -- Ресурсы по абсолютному пути if dependency.path:sub(1, 1) == "/" then path = dependency.path -- Ресурсы по релятивному пути else path = mainFilePath .. "Resources/" .. dependency.path end end return path:gsub("/+", "/") end local function download(publication) if not publication.translated_description then status(localization.statusApplicationInfo) publication = fieldAPIRequest("result", "publication", { publication_name = publication.publication_name, language_id = config.language_id, }) end if publication then local container = MineOSInterface.addUniversalContainer(MineOSInterface.mainContainer, localization.choosePath) container.layout:setCellFitting(2, 1, false, false) local filesystemChooser = container.layout:addChild(GUI.filesystemChooser(1, 1, 44, 3, 0xE1E1E1, 0x2D2D2D, 0x4B4B4B, 0x969696, downloadPaths[publication.category_id] .. (publication.category_id == 1 and publication.publication_name .. ".app" or publication.path), localization.save, localization.cancel, localization.fileName, "/")) filesystemChooser:setMode(GUI.filesystemModes.save, GUI.filesystemModes.file) container.layout:addChild(GUI.text(1, 1, 0xE1E1E1, localization.tree)) local tree = container.layout:addChild(GUI.tree(1, 1, 44, 10, 0xE1E1E1, 0xA5A5A5, 0x3C3C3C, 0xA5A5A5, 0x3C3C3C, 0xE1E1E1, 0xB4B4B4, 0xA5A5A5, 0xC3C3C3, 0x444444)) -- Хуйня, хуячащая ваще прям все - включая ТО, шо нужно загрузить local mainFilePath, mainFilePathForDependencies local function updateTree() tree.items = {} tree.fromItem = 1 mainFilePath = filesystemChooser.path .. (publication.category_id == 1 and "/Main.lua" or "") mainFilePathForDependencies = filesystemChooser.path .. (publication.category_id == 1 and "/" or "") -- Вот тута будет йоба-древо local dependencyTree = {} local treeData = { { path = mainFilePath, source_url = publication.source_url, } } if publication.dependencies then for i = 1, #publication.all_dependencies do table.insert(treeData, publication.dependencies_data[publication.all_dependencies[i]]) end end for i = 1, #treeData do local idiNahooy = dependencyTree local dependencyPath = getDependencyPath(mainFilePathForDependencies, treeData[i]) for blyad in fs.path(dependencyPath):gmatch("[^/]+") do if not idiNahooy[blyad] then idiNahooy[blyad] = {} end idiNahooy = idiNahooy[blyad] end table.insert(idiNahooy, { path = dependencyPath, source_url = treeData[i].source_url, }) end -- Пизда для формирования той ебалы, как ее там local function pizda(t, offset, initPath) for chlen, devka in pairs(t) do if devka.path then tree:addItem(fs.name(devka.path), devka.path, offset, false) else tree:addItem(chlen, chlen, offset, true) tree.expandedItems[chlen] = true pizda(devka, offset + 2, initPath .. chlen .. "/") end end end pizda(dependencyTree, 1, "/") end local shortcutSwitchAndLabel = container.layout:addChild(GUI.switchAndLabel(1, 1, 44, 8, 0x66DB80, 0x0, 0xE1E1E1, 0x878787, localization.createShortcut .. ":", true)) shortcutSwitchAndLabel.hidden = publication.category_id ~= 1 container.layout:addChild(GUI.button(1, 1, 44, 3, 0x696969, 0xFFFFFF, 0x0, 0xFFFFFF, localization.download)).onTouch = function() container.layout:deleteChildren(2) local progressBar = container.layout:addChild(GUI.progressBar(1, 1, 40, 0x66DB80, 0x0, 0xE1E1E1, 0, true, true, "", "%")) local countOfShit = 1 + (publication.all_dependencies and #publication.all_dependencies or 0) local function govnoed(pizda, i) container.label.text = localization.downloading .. " " .. fs.name(pizda.path) progressBar.value = math.round(i / countOfShit * 100) MineOSInterface.OSDraw() end -- SAVED config.versions[publication.publication_name] = { path = mainFilePathForDependencies, version = publication.version, } govnoed(publication, 1) tryToDownload(publication.source_url, mainFilePath) if publication.dependencies then for i = 1, #publication.all_dependencies do local dependency = publication.dependencies_data[publication.all_dependencies[i]] local dependencyPath = getDependencyPath(mainFilePathForDependencies, dependency) govnoed(dependency, i + 1) if dependency.publication_name then if getUpdateState(dependency) < 4 then config.versions[dependency.publication_name] = { path = dependencyPath, version = dependency.version, } tryToDownload(dependency.source_url, dependencyPath) end else tryToDownload(dependency.source_url, dependencyPath) end end end container:delete() callLastMethod() if not shortcutSwitchAndLabel.hidden and shortcutSwitchAndLabel.switch.state then MineOSCore.createShortcut(MineOSPaths.desktop .. fs.hideExtension(fs.name(mainFilePathForDependencies)) .. ".lnk", mainFilePathForDependencies) end computer.pushSignal("MineOSCore", "updateFileList") saveConfig() end filesystemChooser.onSubmit = updateTree updateTree() status(localization.statusWaiting) end end local function addPanel(container, color) container.panel = container:addChild(GUI.panel(1, 1, container.width, container.height, color or 0xFFFFFF)) end local function addApplicationInfo(container, publication) local icon if publication.category_id == 1 then if publication.icon_url then local path = iconCachePath .. publication.publication_name .. "@" .. publication.version .. ".pic" if fs.exists(path) then icon = image.load(path) else local data, reason = checkImage(publication.icon_url) if data then local file = io.open(path, "w") file:write(data) file:close() icon = image.load(path) else GUI.error("Failed to download publication icon: " .. reason) icon = fileNotExistsIcon end end else icon = fileNotExistsIcon end elseif publication.category_id == 2 then icon = luaIcon else icon = scriptIcon end addPanel(container) container.image = container:addChild(GUI.image(3, 2, icon)) container.nameLabel = container:addChild(GUI.text(13, 2, 0x0, publication.publication_name)) container.versionLabel = container:addChild(GUI.text(13, 3, 0x878787, "©" .. publication.user_name)) container.rating = container:addChild(newRatingWidget(13, 4, publication.average_rating and math.round(publication.average_rating) or 0)) local updateState = getUpdateState(publication) container.downloadButton = container:addChild(GUI.adaptiveRoundedButton(13, 5, 1, 0, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, updateState == 4 and localization.installed or updateState == 3 and localization.update or localization.install)) container.downloadButton.onTouch = function() download(publication) end container.downloadButton.colors.disabled.background = 0xD2D2D2 container.downloadButton.colors.disabled.text = 0xFFFFFF container.downloadButton.disabled = updateState == 4 end local function keyValueWidgetDraw(object) buffer.text(object.x, object.y, object.colors.key, object.key) buffer.text(object.x + unicode.len(object.key), object.y, object.colors.value, object.value) end local function newKeyValueWidget(x, y, width, keyColor, valueColor, key, value) local object = GUI.object(x, y, width, 1) object.colors = { key = keyColor, value = valueColor } object.key = key object.value = value object.draw = keyValueWidgetDraw return object end local function containerScrollEventHandler(mainContainer, object, eventData) if eventData[1] == "scroll" then local first, last = object.children[1], object.children[#object.children] if eventData[5] == 1 then if first.localY < 2 then for i = 1, #object.children do object.children[i].localY = object.children[i].localY + 1 end MineOSInterface.OSDraw() end else if last.localY + last.height - 1 >= object.height then for i = 1, #object.children do object.children[i].localY = object.children[i].localY - 1 end MineOSInterface.OSDraw() end end end end local function newPublicationInfo(publication_name) lastMethod, lastArguments = newPublicationInfo, {publication_name} status(localization.statusApplicationInfo) local publication = fieldAPIRequest("result", "publication", { publication_name = publication_name, language_id = config.language_id, }) if publication then contentContainer:deleteChildren() local infoContainer = contentContainer:addChild(GUI.container(1, 1, contentContainer.width, contentContainer.height)) infoContainer.eventHandler = containerScrollEventHandler infoContainer.passScreenEvents = true -- Жирный йоба-лейаут для отображения ВАЩЕ всего - и инфы, и отзыввов local layout = infoContainer:addChild(GUI.layout(3, 2, infoContainer.width - 4, infoContainer.height, 1, 1)) layout:setCellAlignment(1, 1, GUI.alignment.horizontal.center, GUI.alignment.vertical.top) -- А вот эт уже контейнер чисто инфы крч local detailsContainer = layout:addChild(GUI.container(3, 2, layout.width, 6)) -- Тут будут находиться ваще пизда подробности о публикации local ratingsContainer = detailsContainer:addChild(GUI.container(1, 1, 26, 6)) ratingsContainer.localX = detailsContainer.width - ratingsContainer.width + 1 addPanel(ratingsContainer, 0xE1E1E1) -- Всякая текстовая пизда local y = 2 -- Фигачим кнопочки на изменение хуйни if publication.user_name == config.user.name then local buttonsLayout = ratingsContainer:addChild(newButtonsLayout(2, y, ratingsContainer.width - 2, 2)) buttonsLayout:addChild(GUI.adaptiveRoundedButton(2, 1, 1, 0, 0x969696, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.edit)).onTouch = function() editPublication(publication) end buttonsLayout:addChild(GUI.adaptiveRoundedButton(2, 1, 1, 0, 0x969696, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.remove)).onTouch = function() deletePublication(publication) end y = y + 2 end ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.developer, ": " .. publication.user_name)); y = y + 1 ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.license, ": " .. licenses[publication.license_id])); y = y + 1 ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.category, ": " .. categories[publication.category_id])); y = y + 1 ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.version, ": " .. publication.version)); y = y + 1 ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.updated, ": " .. os.date("%d.%m.%Y", publication.timestamp))); y = y + 1 -- Добавляем инфу с общими рейтингами if publication.reviews then local ratings = {0, 0, 0, 0, 0} for i = 1, #publication.reviews do ratings[publication.reviews[i].rating] = ratings[publication.reviews[i].rating] + 1 end y = y + 1 ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.reviews, ": " .. #publication.reviews)); y = y + 1 ratingsContainer:addChild(newKeyValueWidget(2, y, ratingsContainer.width - 2, 0x2D2D2D, 0x878787, localization.averageRating, ": " .. string.format("%.1f", publication.average_rating or 0))); y = y + 1 for i = #ratings, 1, -1 do local text = tostring(ratings[i]) local textLength = #text ratingsContainer:addChild(newRatingWidget(2, y, i, nil, 0xC3C3C3)) ratingsContainer:addChild(GUI.progressBar(12, y, ratingsContainer.width - textLength - 13, 0x2D2D2D, 0xC3C3C3, 0xC3C3C3, ratings[i] / #publication.reviews * 100, true)) ratingsContainer:addChild(GUI.text(ratingsContainer.width - textLength, y, 0x2D2D2D, text)) y = y + 1 end end -- Добавляем контейнер под описание и прочую пизду local textDetailsContainer = detailsContainer:addChild(GUI.container(1, 1, detailsContainer.width - ratingsContainer.width, detailsContainer.height)) -- Ебурим саму пизду addApplicationInfo(textDetailsContainer, publication) -- Ебурим описание local x, y = 3, 7 local lines = string.wrap(publication.translated_description, textDetailsContainer.width - 4) local textBox = textDetailsContainer:addChild(GUI.textBox(3, y, textDetailsContainer.width - 4, #lines, nil, 0x969696, lines, 1, 0, 0)) textBox.eventHandler = nil y = y + textBox.height + 1 -- Зависимости if publication.dependencies then local publicationDependencyExists = false for i = 1, #publication.all_dependencies do if publication.dependencies_data[publication.all_dependencies[i]].publication_name then publicationDependencyExists = true break end end if publicationDependencyExists then textDetailsContainer:addChild(GUI.label(1, y, textDetailsContainer.width, 1, 0x696969, localization.dependencies)):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top) y = y + 2 for i = 1, #publication.all_dependencies do local dependency = publication.dependencies_data[publication.all_dependencies[i]] if dependency.publication_name then local textLength = unicode.len(dependency.publication_name) if x + textLength + 4 > textDetailsContainer.width - 4 then x, y = 3, y + 2 end local button = textDetailsContainer:addChild(GUI.roundedButton(x, y, textLength + 2, 1, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, dependency.publication_name)) button.onTouch = function() newPublicationInfo(dependency.publication_name) end x = x + button.width + 2 end end y = y + 2 end end -- Подсчитываем результирующие размеры textDetailsContainer.height = math.max( textDetailsContainer.children[#textDetailsContainer.children].localY + textDetailsContainer.children[#textDetailsContainer.children].height, ratingsContainer.children[#ratingsContainer.children].localY + ratingsContainer.children[#ratingsContainer.children].height ) textDetailsContainer.panel.height = textDetailsContainer.height ratingsContainer.height = textDetailsContainer.height ratingsContainer.panel.height = textDetailsContainer.height detailsContainer.height = textDetailsContainer.height if config.user.token and config.user.name ~= publication.user_name then local existingReviewText if publication.reviews then for i = 1, #publication.reviews do if publication.reviews[i].user_name == config.user.name then existingReviewText = publication.reviews[i].comment break end end end layout:addChild(GUI.adaptiveRoundedButton(1, 1, 2, 0, 0x696969, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, existingReviewText and localization.changeReview or localization.writeReview)).onTouch = function() local container = MineOSInterface.addUniversalContainer(window, existingReviewText and localization.changeReview or localization.writeReview) container.layout:setCellFitting(2, 1, false, false) local input = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, existingReviewText or "", localization.writeReviewHere)) local pizda = container.layout:addChild(GUI.container(1, 1, 1, 1)) local eblo = pizda:addChild(GUI.text(1, 1, 0xE1E1E1, localization.yourRating .. ": ")) pizda.width = eblo.width + 9 local cyka = pizda:addChild(newRatingWidget(eblo.width + 1, 1, 4)) cyka.eventHandler = function(mainContainer, object, eventData) if eventData[1] == "touch" then cyka.rating = math.round((eventData[3] - object.x + 1) / object.width * 5) MineOSInterface.OSDraw() end end local govno = container.layout:addChild(GUI.button(1, 1, 36, 3, 0x696969, 0xFFFFFF, 0x3C3C3C, 0xFFFFFF, "OK")) govno.disabled = true govno.colors.disabled.background = 0xA5A5A5 govno.colors.disabled.text = 0xC3C3C3 govno.onTouch = function() status(localization.statusPublishingReview) local success, reason = RawAPIRequest("review", { token = config.user.token, publication_name = publication.publication_name, rating = cyka.rating, comment = input.text, }) container:delete() if success then newPublicationInfo(publication.publication_name) else MineOSInterface.OSDraw() GUI.error(reason) end end input.onInputFinished = function() local textLength, from, to = unicode.len(input.text), 2, 1000 if textLength >= from and textLength <= to then govno.disabled = false else govno.disabled = true if textLength > to then GUI.error("Too big review length (" .. textLength .. "). Maximum is " .. to) end end MineOSInterface.OSDraw() end input.onInputFinished() end end if publication.reviews then -- Отображаем все оценки layout:addChild(GUI.text(1, 1, 0x696969, localization.reviewsOfUsers)) -- Перечисляем все отзывы for i = 1, #publication.reviews do local reviewContainer = layout:addChild(GUI.container(1, 1, layout.width, 4)) addPanel(reviewContainer) local y = 2 local nameLabel = reviewContainer:addChild(GUI.text(3, y, 0x2D2D2D, publication.reviews[i].user_name)) reviewContainer:addChild(GUI.text(nameLabel.localX + nameLabel.width + 1, y, 0xC3C3C3, "(" .. os.date("%d.%m.%Y", publication.reviews[i].timestamp) .. ")")) y = y + 1 reviewContainer:addChild(newRatingWidget(3, y, publication.reviews[i].rating)) y = y + 1 local lines = string.wrap(publication.reviews[i].comment, reviewContainer.width - 4) local textBox = reviewContainer:addChild(GUI.textBox(3, y, reviewContainer.width - 4, #lines, nil, 0x878787, lines, 1, 0, 0)) textBox.eventHandler = nil y = y + #lines if publication.reviews[i].votes or config.user.token and config.user.name ~= publication.reviews[i].user_name then y = y + 1 end if publication.reviews[i].votes then reviewContainer:addChild(GUI.text(3, y, 0xC3C3C3, publication.reviews[i].positive_votes .. " из " .. publication.reviews[i].votes .. " пользователей считают этот отзыв полезным")) y = y + 1 end if config.user.token and config.user.name ~= publication.reviews[i].user_name then local wasHelpText = reviewContainer:addChild(GUI.text(3, y, 0xC3C3C3, localization.wasReviewHelpful)) local yesButton = reviewContainer:addChild(GUI.adaptiveButton(wasHelpText.localX + wasHelpText.width + 1, y, 0, 0, nil, 0x696969, nil, 0x2D2D2D, localization.yes)) local stripLabel = reviewContainer:addChild(GUI.text(yesButton.localX + yesButton.width + 1, y, 0xC3C3C3, "|")) local noButton = reviewContainer:addChild(GUI.adaptiveButton(stripLabel.localX + stripLabel.width + 1, y, 0, 0, nil, 0x696969, nil, 0x2D2D2D, localization.no)) local function go(rating) status(localization.statusVotingReview) local success = fieldAPIRequest("result", "review_vote", { token = config.user.token, review_id = publication.reviews[i].id, rating = rating }) if success then wasHelpText.text = localization.thanksForVote wasHelpText.color = 0x696969 yesButton:delete() stripLabel:delete() noButton:delete() status(localization.statusWaiting) end end yesButton.onTouch = function() go(1) end noButton.onTouch = function() go(0) end y = y + 1 end reviewContainer.height = y reviewContainer.panel.height = reviewContainer.height end end layout:update() layout.height = layout.children[#layout.children].localY + layout.children[#layout.children].height - 1 status(localization.statusWaiting) end end -------------------------------------------------------------------------------- local function applicationWidgetEventHandler(mainContainer, object, eventData) if eventData[1] == "touch" then object.parent.panel.colors.background = 0xE1E1E1 MineOSInterface.OSDraw() newPublicationInfo(object.parent.publication_name) end end local function newApplicationPreview(x, y, publication) local container = GUI.container(x, y, appWidth, appHeight) container.publication_name = publication.publication_name addApplicationInfo(container, publication) container.panel.eventHandler, container.image.eventHandler, container.nameLabel.eventHandler, container.versionLabel.eventHandler, container.rating.eventHandler = applicationWidgetEventHandler, applicationWidgetEventHandler, applicationWidgetEventHandler, applicationWidgetEventHandler, applicationWidgetEventHandler return container end -------------------------------------------------------------------------------- local function newPlusMinusCyka(width, disableLimit) local layout = GUI.layout(1, 1, width, 1, 2, 1) layout:setColumnWidth(1, GUI.sizePolicies.percentage, 1.0) layout:setColumnWidth(2, GUI.sizePolicies.absolute, 8) layout:setCellFitting(1, 1, true, false) layout:setCellMargin(2, 1, 1, 0) layout:setCellAlignment(1, 1, GUI.alignment.horizontal.left, GUI.alignment.vertical.top) layout:setCellAlignment(2, 1, GUI.alignment.horizontal.left, GUI.alignment.vertical.top) layout:setCellDirection(1, 1, GUI.directions.horizontal) layout:setCellDirection(2, 1, GUI.directions.horizontal) layout.comboBox = layout:addChild(GUI.comboBox(1, 1, width - 7, 1, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) layout.defaultColumn = 2 layout.addButton = layout:addChild(GUI.button(1, 1, 3, 1, 0x696969, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, "+")) layout.removeButton = layout:addChild(GUI.button(1, 1, 3, 1, 0x696969, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, "-")) local overrideRemoveButtonDraw = layout.removeButton.draw layout.removeButton.draw = function(...) layout.removeButton.disabled = layout.comboBox:count() <= disableLimit overrideRemoveButtonDraw(...) end layout.removeButton.onTouch = function() layout.comboBox:removeItem(layout.comboBox.selectedItem) MineOSInterface.OSDraw() end return layout end editPublication = function(initialPublication) lastMethod, lastArguments = editPublication, {initialPublication} contentContainer:deleteChildren() local layout = contentContainer:addChild(GUI.layout(1, 1, contentContainer.width, contentContainer.height, 3, 1)) layout:setColumnWidth(1, GUI.sizePolicies.percentage, 0.5) layout:setColumnWidth(2, GUI.sizePolicies.absolute, 36) layout:setColumnWidth(3, GUI.sizePolicies.percentage, 0.5) layout:setCellAlignment(1, 1, GUI.alignment.horizontal.right, GUI.alignment.vertical.center) layout:setCellAlignment(2, 1, GUI.alignment.horizontal.left, GUI.alignment.vertical.center) layout:setCellFitting(2, 1, true, false) layout:setCellMargin(1, 1, 1, 0) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.category .. ":")) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.license .. ":")) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.publicationName .. ":")) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.mainFileURL .. ":")) local iconHint = layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.iconURL .. ":")) local pathHint = layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.mainFileName .. ":")) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.description .. ":")) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.dependenciesAndResources .. ":")) layout.defaultColumn = 2 layout:addChild(GUI.label(1, 1, 36, 1, 0x0, initialPublication and localization.editPublication or localization.publish)):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top) local categoryComboBox = layout:addChild(GUI.comboBox(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) for i = 1, #categories do categoryComboBox:addItem(categories[i]) end if initialPublication then categoryComboBox.selectedItem = initialPublication.category_id end local licenseComboBox = layout:addChild(GUI.comboBox(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) for i = 1, #licenses do licenseComboBox:addItem(licenses[i]) end if initialPublication then licenseComboBox.selectedItem = initialPublication.license_id end local nameInput = layout:addChild(GUI.input(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, initialPublication and initialPublication.publication_name or "", "My Script")) local mainUrlInput = layout:addChild(GUI.input(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, initialPublication and initialPublication.source_url or "", "http://example.com/Main.lua")) local iconUrlInput = layout:addChild(GUI.input(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, initialPublication and initialPublication.icon_url or "", "http://example.com/Icon.pic")) local mainPathInput = layout:addChild(GUI.input(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, initialPublication and initialPublication.path or "", "MyScript.lua")) local descriptionInput = layout:addChild(GUI.input(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, initialPublication and initialPublication.initial_description or "", "This is my cool script")) local dependenciesLayout = layout:addChild(newPlusMinusCyka(36, 0)) local function addDependency(dependency) local text if dependency.publication_name then text = "#" .. dependency.publication_name else if dependency.path:sub(1, 1) == "/" then text = dependency.path else text = "../" .. dependency.path end end dependenciesLayout.comboBox:addItem(text).dependency = dependency dependenciesLayout.comboBox.selectedItem = dependenciesLayout.comboBox:count() end if initialPublication and initialPublication.dependencies then for i = 1, #initialPublication.dependencies do local dependency = initialPublication.dependencies_data[initialPublication.dependencies[i]] if dependency.publication_name then addDependency({publication_name = dependency.publication_name}) elseif dependency.path ~= "Icon.pic" then addDependency({source_url = dependency.source_url, path = dependency.path}) end end end local lastDependencyType = 1 dependenciesLayout.addButton.onTouch = function() local container = MineOSInterface.addUniversalContainer(MineOSInterface.mainContainer, localization.addDependency) container.layout:setCellFitting(2, 1, false, false) local dependencyTypeComboBox = container.layout:addChild(GUI.comboBox(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) dependencyTypeComboBox:addItem(localization.fileByURL) dependencyTypeComboBox:addItem(localization.existingPublication) dependencyTypeComboBox.selectedItem = lastDependencyType local publicationNameInput = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, "", "Double Buffering")) local urlInput = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, "", "http://example.com/English.lang")) local pathInput = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, "", "")) local pathType = container.layout:addChild(GUI.switchAndLabel(1, 1, 36, 8, 0x66DB80, 0x0, 0xE1E1E1, 0x878787, localization.relativePath .. ":", true)) local button = container.layout:addChild(GUI.button(1, 1, 36, 3, 0x696969, 0xFFFFFF, 0x0, 0xFFFFFF, localization.add)) button.onTouch = function() addDependency({ publication_name = lastDependencyType > 1 and publicationNameInput.text or nil, path = lastDependencyType == 1 and (pathType.switch.state and pathInput.text:gsub("^/+", "") or "/" .. pathInput.text:gsub("/+", "/")) or nil, source_url = lastDependencyType == 1 and urlInput.text or nil, }) container:delete() MineOSInterface.OSDraw() end publicationNameInput.onInputFinished = function() if lastDependencyType == 1 then button.disabled = #pathInput.text == 0 or #urlInput.text == 0 else button.disabled = #publicationNameInput.text == 0 end end pathInput.onInputFinished, urlInput.onInputFinished = publicationNameInput.onInputFinished, publicationNameInput.onInputFinished local function onDependencyTypeComboBoxItemSelected() lastDependencyType = dependencyTypeComboBox.selectedItem publicationNameInput.hidden = lastDependencyType == 1 pathInput.hidden = not publicationNameInput.hidden urlInput.hidden = pathInput.hidden pathType.hidden = categoryComboBox.selectedItem > 1 or pathInput.hidden end dependencyTypeComboBox.onItemSelected = function() onDependencyTypeComboBoxItemSelected() MineOSInterface.OSDraw() end pathType.switch.onStateChanged = function() pathInput.placeholderText = pathType.switch.state and "Localization/English.lang" or "/MineOS/Localization/English.lang" end publicationNameInput.onInputFinished() onDependencyTypeComboBoxItemSelected() pathType.switch.onStateChanged() MineOSInterface.OSDraw() end local publishButton = layout:addChild(GUI.adaptiveRoundedButton(1, 1, 2, 0, 0x696969, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.save)) local function checkFields() publishButton.disabled = not (#nameInput.text > 0 and #mainUrlInput.text > 0 and #descriptionInput.text > 0 and (iconUrlInput.hidden and true or #iconUrlInput.text > 0) and (mainPathInput.hidden and true or #mainPathInput.text > 0)) end iconUrlInput.onInputFinished, nameInput.onInputFinished, mainUrlInput.onInputFinished, mainPathInput.onInputFinished, descriptionInput.onInputFinished = checkFields, checkFields, checkFields, checkFields, checkFields categoryComboBox.onItemSelected = function() iconHint.hidden = categoryComboBox.selectedItem > 1 iconUrlInput.hidden = iconHint.hidden pathHint.hidden = not iconHint.hidden mainPathInput.hidden = pathHint.hidden nameInput.onInputFinished() MineOSInterface.OSDraw() end categoryComboBox.onItemSelected() publishButton.onTouch = function() local dependencies = {} for i = 1, dependenciesLayout.comboBox:count() do table.insert(dependencies, dependenciesLayout.comboBox:getItem(i).dependency) end if categoryComboBox.selectedItem == 1 then table.insert(dependencies, { source_url = iconUrlInput.text, path = "Icon.pic" }) end status(initialPublication and localization.statusUpdatingPublication or localization.statusUploadingPublication) local success, reason = RawAPIRequest(initialPublication and "update" or "upload", { -- Вот эта хня чисто для апдейта publication_name = initialPublication and initialPublication.publication_name or nil, -- А вот эта хня универсальная token = config.user.token, name = nameInput.text, source_url = mainUrlInput.text, path = categoryComboBox.selectedItem == 1 and "Main.lua" or mainPathInput.text, description = descriptionInput.text, license_id = licenseComboBox.selectedItem, dependencies = dependencies, category_id = categoryComboBox.selectedItem, }) if success then window.tabBar.selectedItem = categoryComboBox.selectedItem if initialPublication then newPublicationInfo(nameInput.text) else config.orderBy = 3 saveConfig() updateFileList(window.tabBar.selectedItem) end else GUI.error(reason) end end status(localization.statusWaiting) end -------------------------------------------------------------------------------- updateFileList = function(category_id, updates) lastMethod, lastArguments = updateFileList, {category_id, updates} status(updates and localization.statusSearchingUpdates or localization.statusUpdatingList) local publication_names if updates then publication_names = {} for name in pairs(config.versions) do table.insert(publication_names, name) end end local result = fieldAPIRequest("result", "publications", { category_id = category_id, order_by = updates and "date" or orderBys[config.orderBy], order_direction = updates and "desc" or orderDirections[config.orderDirection], offset = currentPage * appsPerPage, count = updates and 100 or appsPerPage + 1, search = search, publication_names = publication_names, }) if result then contentContainer:deleteChildren() if updates then local i = 1 while i <= #result do if getUpdateState(result[i]) ~= 3 then table.remove(result, i) else i = i + 1 end end end local y = 2 local layout = contentContainer:addChild(GUI.layout(1, y, contentContainer.width, 1, 1, 1)) layout:setCellDirection(1, 1, GUI.directions.horizontal) layout:setCellSpacing(1, 1, 2) if updates then if #result > 0 then layout:addChild(GUI.adaptiveRoundedButton(1, 1, 2, 0, 0x696969, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.updateAll)).onTouch = function() local container = MineOSInterface.addUniversalContainer(MineOSInterface.mainContainer, "") container.layout:setCellFitting(2, 1, false, false) local progressBar = container.layout:addChild(GUI.progressBar(1, 1, 40, 0x66DB80, 0x0, 0xE1E1E1, 0, true, true, "", "%")) for i = 1, #result do container.label.text = localization.downloading .. " " .. result[i].publication_name progressBar.value = math.round(i / #result * 100) MineOSInterface.OSDraw() local publication = fieldAPIRequest("result", "publication", { publication_name = result[i].publication_name, language_id = config.language_id, }) config.versions[publication.publication_name].version = publication.version tryToDownload(publication.source_url, config.versions[publication.publication_name].path .. (fs.extension(config.versions[publication.publication_name].path) == ".app" and "Main.lua" or "")) if publication then local publicationPath = config.versions[publication.publication_name].path if publication.dependencies then for j = 1, #publication.all_dependencies do local dependency = publication.dependencies_data[publication.all_dependencies[j]] if not dependency.publication_name then local dependencyPath = getDependencyPath(publicationPath, dependency) container.label.text = localization.downloading .. " " .. dependency.path MineOSInterface.OSDraw() tryToDownload(dependency.source_url, dependencyPath) end end end end end container:delete() saveConfig() computer.shutdown(true) end else contentContainer:addChild(GUI.label(1, 1, contentContainer.width, contentContainer.height, 0x2D2D2D, localization.noUpdates)):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.center) end else local input = layout:addChild(GUI.input(1, 1, 20, layout.height, 0xFFFFFF, 0x2D2D2D, 0x696969, 0xFFFFFF, 0x2D2D2D, search or "", localization.search, true)) input.onInputFinished = function() if #input.text == 0 then search = nil else search = input.text end currentPage = 0 updateFileList(category_id, updates) end local orderByComboBox = layout:addChild(GUI.comboBox(1, 1, 18, layout.height, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) orderByComboBox:addItem(localization.byRating) orderByComboBox:addItem(localization.byName) orderByComboBox:addItem(localization.byDate) orderByComboBox.selectedItem = config.orderBy local orderDirectionComboBox = layout:addChild(GUI.comboBox(1, 1, 18, layout.height, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) orderDirectionComboBox:addItem(localization.desc) orderDirectionComboBox:addItem(localization.asc) orderDirectionComboBox.selectedItem = config.orderDirection orderByComboBox.onItemSelected = function() config.orderBy = orderByComboBox.selectedItem config.orderDirection = orderDirectionComboBox.selectedItem updateFileList(category_id, updates) saveConfig() end orderDirectionComboBox.onItemSelected = orderByComboBox.onItemSelected if config.user.token then layout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0x696969, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.publish)).onTouch = function() editPublication() end end end y = y + layout.height + 1 local navigationLayout = contentContainer:addChild(GUI.layout(1, contentContainer.height - 1, contentContainer.width, 1, 1, 1)) navigationLayout:setCellDirection(1, 1, GUI.directions.horizontal) navigationLayout:setCellSpacing(1, 1, 2) local function switchPage(forward) currentPage = currentPage + (forward and 1 or -1) updateFileList(category_id, updates) end local backButton = navigationLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0xFFFFFF, 0x696969, 0xA5A5A5, 0xFFFFFF, "<")) backButton.colors.disabled.background = 0xD2D2D2 backButton.colors.disabled.text = 0xB4B4B4 backButton.disabled = currentPage == 0 backButton.onTouch = function() switchPage(false) end navigationLayout:addChild(GUI.text(1, 1, 0x696969, localization.page .. " " .. (currentPage + 1))) local nextButton = navigationLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0xFFFFFF, 0x696969, 0xA5A5A5, 0xFFFFFF, ">")) nextButton.colors.disabled = backButton.colors.disabled nextButton.disabled = #result <= appsPerPage nextButton.onTouch = function() switchPage(true) end local xStart = math.floor(1 + contentContainer.width / 2 - (appsPerWidth * (appWidth + appHSpacing) - appHSpacing) / 2) local x, counter = xStart, 1 for i = 1, #result do contentContainer:addChild(newApplicationPreview(x, y, result[i])) if counter >= appsPerPage then break elseif counter % appsPerWidth == 0 then x, y = xStart, y + appHeight + appVSpacing else x = x + appWidth + appHSpacing end counter = counter + 1 -- Если мы тока шо создали приложеньку, от отрисовываем содержимое сразу же if category_id == 1 then MineOSInterface.OSDraw() end end status(localization.statusWaiting) end end window.onResize = function(width, height) window.backgroundPanel.width = width window.backgroundPanel.height = height - 4 contentContainer.width = width contentContainer.height = window.height - 4 window.tabBar.width = width statusWidget.width = window.width statusWidget.localY = window.height appsPerWidth = math.floor((contentContainer.width + appHSpacing) / (appWidth + appHSpacing)) appsPerHeight = math.floor((contentContainer.height - 6 + appVSpacing) / (appHeight + appVSpacing)) appsPerPage = appsPerWidth * appsPerHeight currentPage = 0 contentContainer:deleteChildren() callLastMethod() end local function account() lastMethod, lastArguments = account, {} if config.user.token then status(localization.statusUser) local result = fieldAPIRequest("result", "publications", { user_name = config.user.name, order_by = "name", order_direction = "asc", }) if result then contentContainer:deleteChildren() local layout = contentContainer:addChild(GUI.layout(1, 1, contentContainer.width, contentContainer.height, 1, 1)) layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.profile)) layout:addChild(newKeyValueWidget(1, 1, 36, 0x4B4B4B, 0x878787, localization.nickname, ": " .. config.user.name)) layout:addChild(newKeyValueWidget(1, 1, 36, 0x4B4B4B, 0x878787, "E-Mail", ": " .. config.user.email)) layout:addChild(newKeyValueWidget(1, 1, 36, 0x4B4B4B, 0x878787, localization.registrationDate, ": " .. os.date("%d.%m.%Y", config.user.timestamp))) local buttonsLayout = layout:addChild(newButtonsLayout(1, 1, layout.width, 3)) buttonsLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0xA5A5A5, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.clearCache)).onTouch = function() for file in fs.list(iconCachePath) do fs.remove(iconCachePath .. file) end config.versions = {} saveConfig() end buttonsLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 2, 0, 0xA5A5A5, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.exit)).onTouch = function() config.user = {} saveConfig() account() end layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.language)) local languageComboBox = layout:addChild(GUI.comboBox(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) for key, value in pairs(languages) do languageComboBox:addItem(value).onTouch = function() config.language_id = key saveConfig() end if key == config.language_id then languageComboBox.selectedItem = languageComboBox:count() end end if #result > 0 then layout:addChild(GUI.text(1, 1, 0x2D2D2D, localization.publications)) local comboBox = layout:addChild(GUI.comboBox(1, 1, 36, 1, 0xFFFFFF, 0x696969, 0x969696, 0xE1E1E1)) for i = 1, #result do comboBox:addItem(result[i].publication_name) end local buttonsLayout = layout:addChild(newButtonsLayout(1, 1, layout.width, 3)) buttonsLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0xA5A5A5, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.open)).onTouch = function() newPublicationInfo(result[comboBox.selectedItem].publication_name) end buttonsLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0xA5A5A5, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.edit)).onTouch = function() status(localization.statusApplicationInfo) local result = fieldAPIRequest("result", "publication", { publication_name = result[comboBox.selectedItem].publication_name, language_id = config.language_id, }) if result then editPublication(result) end end buttonsLayout:addChild(GUI.adaptiveRoundedButton(1, 1, 1, 0, 0xA5A5A5, 0xFFFFFF, 0x2D2D2D, 0xFFFFFF, localization.remove)).onTouch = function() deletePublication(result[comboBox.selectedItem]) end end status(localization.statusWaiting) end else contentContainer:deleteChildren() local layout = contentContainer:addChild(GUI.layout(1, 1, contentContainer.width, contentContainer.height, 1, 1)) local function addShit(register) layout:deleteChildren() layout:addChild(GUI.label(1, 1, 36, 1, 0x0, register and localization.createAccount or localization.login)):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top) if register then layout.nameInput = layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, "", localization.nickname)) end layout.emailInput = layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, config.user.email or "", register and "E-mail" or localization.nicknameOrEmail)) layout.passwordInput = layout:addChild(GUI.input(1, 1, 36, 3, 0xFFFFFF, 0x696969, 0xB4B4B4, 0xFFFFFF, 0x2D2D2D, "", localization.password, false, "*")) if register then layout.submit = layout:addChild(GUI.button(1, 1, 36, 3, 0xA5A5A5, 0xFFFFFF, 0x696969, 0xFFFFFF, "OK")) end end addShit(false) layout:addChild(GUI.button(1, 1, 36, 3, 0xA5A5A5, 0xFFFFFF, 0x696969, 0xFFFFFF, "OK")).onTouch = function() status(localization.statusLoggingIn) local result = fieldAPIRequest("result", "login", { [(string.find(layout.emailInput.text, "@") and "email" or "name")] = layout.emailInput.text, password = layout.passwordInput.text }) if result then config.user = { token = result.token, name = result.name, id = result.id, email = result.email, timestamp = result.timestamp, } saveConfig() account() end end local registerLayout = layout:addChild(GUI.layout(1, 1, layout.width, 1, 1, 1)) registerLayout:setCellDirection(1, 1, GUI.directions.horizontal) local registerText = registerLayout:addChild(GUI.text(1, 1, 0xA5A5A5, localization.notRegistered)) registerLayout:addChild(GUI.adaptiveButton(1, 1, 0, 0, nil, 0x696969, nil, 0x0, localization.createAccount)).onTouch = function() addShit(true) layout.submit.onTouch = function() status(localization.statusRegistering) local result = fieldAPIRequest("result", "register", { name = layout.nameInput.text, email = layout.emailInput.text, password =layout.passwordInput.text, }) if result then contentContainer:deleteChildren() contentContainer:addChild(GUI.label(1, 1, contentContainer.width, contentContainer.height, 0x2D2D2D, localization.registrationSuccessfull)):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.center) MineOSInterface.OSDraw() end end end end end local function loadCategory(category_id, updates) currentPage, search = 0, nil updateFileList(category_id, updates) end for i = 1, #categories do window.tabBar:addItem(categories[i]).onTouch = function() loadCategory(i) end end window.tabBar:addItem(localization.categoryUpdates).onTouch = function() loadCategory(nil, true) end window.tabBar:addItem(localization.categoryAccount).onTouch = function() account() end -------------------------------------------------------------------------------- loadConfig() lastMethod = loadCategory if args[1] == "updates" then lastArguments = {nil, true} window.tabBar.selectedItem = #categories + 1 else lastArguments = {1} end window:resize(window.width, window.height)