MineOS/Applications/AppMarket/AppMarket.lua
Igor Timofeev 33d8f23973 Угу
2016-06-07 08:40:02 +03:00

445 lines
14 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.

package.loaded.GUI = nil
_G.GUI = nil
local libraries = {
buffer = "doubleBuffering",
MineOSCore = "MineOSCore",
image = "image",
GUI = "GUI",
fs = "filesystem",
component = "component",
unicode = "unicode",
files = "files",
ecs = "ECSAPI",
}
for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end; libraries = nil
------------------------------------------------------------------------------------------------------------------
local obj = {}
local sizes = {}
local colors = {
main = 0xFFFFFF,
topBar = 0xDDDDDD,
topBarText = 0x555555,
topBarElement = 0xCCCCCC,
topBarElementText = 0x555555,
statusBar = 0xDDDDDD,
statusBarText = 0x888888,
appName = 0x262626,
version = 0x555555,
description = 0x888888,
downloadButton = 0xAAAAAA,
downloadButtonText = 0xFFFFFF,
downloading = 0x009240,
downloadingText = 0xFFFFFF,
downloaded = 0xCCCCCC,
downloadedText = 0xFFFFFF,
}
local typeFilters = {
"Application",
"Library",
"Wallpaper",
"Script",
}
local appStorePath = "MineOS/System/AppStore/"
local pathToApplications = "MineOS/System/OS/Applications.txt"
local updateImage = image.load(MineOSCore.paths.icons .. "Update.pic")
-- local topBarElements = {{title = "Приложения", type = "Application"}, {title = "Библиотеки", type = "Library"}, {title = "Обои", type = "Wallpaper"}, {title = "Другое"}, {title = "Обновления"}}
local topBarElements = {"Приложения", "Библиотеки", "Обои", "Другое", "Обновления"}
local oldApplications, newApplications, currentApps, changes = {}, {}, {}, {}
local currentTopBarElement = 1
local from, limit, fromY = 1, 8
------------------------------------------------------------------------------------------------------------------
local function correctDouble(number)
return string.format("%.2f", number)
end
local function status(text)
text = unicode.sub(text, 1, sizes.width - 2)
local y = sizes.y + sizes.height - 1
buffer.square(sizes.x, y, sizes.width, 1, colors.statusBar, colors.statusBarText, " ")
buffer.text(sizes.x + 1, y, colors.statusBarText, text)
buffer.draw()
end
local function calculateSizes()
sizes.width, sizes.height = math.floor(buffer.screen.width * 0.6), math.floor(buffer.screen.height * 0.7)
sizes.x, sizes.y = math.floor(buffer.screen.width / 2 - sizes.width / 2), math.floor(buffer.screen.height / 2 - sizes.height / 2)
sizes.topBarHeight = 3
obj.main = GUI.object(sizes.x, sizes.y + sizes.topBarHeight, sizes.width, sizes.height - sizes.topBarHeight)
sizes.downloadButtonWidth = 17
sizes.descriptionTruncateSize = sizes.width - 6 - MineOSCore.iconWidth - sizes.downloadButtonWidth
sizes.searchFieldWidth = math.floor(sizes.width * 0.3)
obj.searchTextField = GUI.textField(math.floor(sizes.x + sizes.width / 2 - sizes.searchFieldWidth / 2), 1, sizes.searchFieldWidth, 1, 0xEEEEEE, 0x777777, 0xEEEEEE, 0x555555, nil, "Поиск", false, true)
end
local function drawTopBar()
obj.topBarButtons = GUI.toolbar(sizes.x, sizes.y, sizes.width, sizes.topBarHeight, 2, currentTopBarElement, colors.topBar, colors.topBarText, colors.topBarElement, colors.topBarElementText, table.unpack(topBarElements))
obj.windowActionButtons = GUI.windowActionButtons(sizes.x + 1, sizes.y)
end
local function getIcon(url)
local success, response = ecs.internetRequest(url)
local path = appStorePath .. "TempIcon.pic"
if success then
local file = io.open(path, "w")
file:write(response)
file:close()
else
GUI.error(tostring(response), {title = {color = 0xFFDB40, text = "Ошибка при загрузке иконки"}})
end
return image.load(path)
end
local function getDescription(url)
local success, response = ecs.internetRequest(url)
if success then
return response
else
GUI.error(tostring(response), {title = {color = 0xFFDB40, text = "Ошибка при загрузке описания приложения"}})
end
end
local function getApplication(i)
currentApps[i] = {}
currentApps[i].name = fs.name(newApplications[i].name)
if newApplications[i].icon then
currentApps[i].icon = getIcon(newApplications.GitHubUserURL .. newApplications[i].icon)
else
if newApplications[i].type == "Application" then
currentApps[i].icon = failureIcon
elseif newApplications[i].type == "Wallpaper" then
currentApps[i].icon = MineOSCore.icons.image
elseif newApplications[i].type == "Library" then
currentApps[i].icon = MineOSCore.icons.lua
else
currentApps[i].icon = MineOSCore.icons.script
end
end
if newApplications[i].about then
currentApps[i].description = getDescription(newApplications.GitHubUserURL .. newApplications[i].about .. _G.OSSettings.language .. ".txt")
currentApps[i].description = ecs.stringWrap({currentApps[i].description}, sizes.descriptionTruncateSize )
else
currentApps[i].description = {"Описание отсутствует"}
end
if newApplications[i].version then
currentApps[i].version = "Версия: " .. correctDouble(newApplications[i].version)
else
currentApps[i].version = "Версия не указана"
end
end
local function checkAppExists(name, type)
if type == "Application" then
name = name .. ".app"
end
return fs.exists(name)
end
local function drawApplication(x, y, i, doNotDrawButton)
buffer.image(x, y, currentApps[i].icon)
buffer.text(x + 10, y, colors.appName, currentApps[i].name)
buffer.text(x + 10, y + 1, colors.version, currentApps[i].version)
local appExists = checkAppExists(newApplications[i].name, newApplications[i].type)
local text = appExists and "Обновить" or "Загрузить"
if not doNotDrawButton then
local xButton, yButton = sizes.x + sizes.width - sizes.downloadButtonWidth - 2, y + 1
if currentApps[i].buttonObject then
currentApps[i].buttonObject.x, currentApps[i].buttonObject.y = xButton, yButton
currentApps[i].buttonObject:draw()
else
currentApps[i].buttonObject = GUI.button(xButton, yButton, sizes.downloadButtonWidth, 1, colors.downloadButton, colors.downloadButtonText, 0x555555, 0xFFFFFF, text)
end
end
for j = 1, #currentApps[i].description do
buffer.text(x + 10, y + j + 1, colors.description, currentApps[i].description[j])
end
y = y + (#currentApps[i].description > 2 and #currentApps[i].description - 2 or 0)
y = y + 5
return x, y
end
local function drawPageSwitchButtons(y)
local text = "Приложения с " .. from .. " по " .. from + limit - 1
local textLength = unicode.len(text)
local buttonWidth = 5
local width = buttonWidth * 2 + textLength + 2
local x = math.floor(sizes.x + sizes.width / 2 - width / 2)
obj.prevPageButton = GUI.button(x, y, buttonWidth, 1, colors.downloadButton, colors.downloadButtonText, 0x262626, 0xFFFFFF, "<")
x = x + obj.prevPageButton.width + 1
buffer.text(x, y, colors.version, text)
x = x + textLength + 1
obj.nextPageButton = GUI.button(x, y, buttonWidth, 1, colors.downloadButton, colors.downloadButtonText, 0x262626, 0xFFFFFF, ">")
end
local function clearMainZone()
buffer.square(sizes.x, obj.main.y, sizes.width, obj.main.height, 0xFFFFFF)
end
local function drawMain(refreshData)
clearMainZone()
local x, y = sizes.x + 2, fromY
buffer.setDrawLimit(sizes.x, obj.main.y, sizes.width, obj.main.height)
obj.searchTextField.y, obj.searchTextField.invisible = y, false
obj.searchTextField:draw()
y = y + 2
local matchCount = 1
for i = 1, #newApplications do
if newApplications[i].type == typeFilters[currentTopBarElement] then
-- if obj.searchTextField.text then GUI.error(tostring(unicode.lower(obj.searchTextField.text))) end
if not obj.searchTextField.text or (string.find(unicode.lower(fs.name(newApplications[i].name)), unicode.lower(obj.searchTextField.text))) then
if matchCount >= from and matchCount <= from + limit - 1 then
if refreshData and not currentApps[i] then
status("Загрузка информации о приложении \"" .. newApplications[i].name .. "\"")
getApplication(i)
end
x, y = drawApplication(x, y, i)
end
matchCount = matchCount + 1
end
end
end
if matchCount > limit then
drawPageSwitchButtons(y)
end
buffer.resetDrawLimit()
end
local function getNewApplications()
local pathToNewApplications = "MineOS/System/OS/AppStore/NewApplications.txt"
ecs.getFileFromUrl(oldApplications.GitHubApplicationListURL, pathToNewApplications)
newApplications = files.loadTableFromFile(pathToNewApplications)
end
local function getChanges()
changes = {}
for i = 1, #oldApplications do
for j = 1, #newApplications do
if oldApplications[i].name == newApplications[j].name then
if oldApplications[i].version < newApplications[j].version then
table.insert(changes, j)
end
end
end
end
end
local function updates()
clearMainZone()
if #changes > 0 then
buffer.setDrawLimit(sizes.x, obj.main.y, sizes.width, obj.main.height)
local x, y = sizes.x + 2, fromY
obj.updateAllButton = GUI.button(math.floor(sizes.x + sizes.width / 2 - sizes.downloadButtonWidth / 2), y, 20, 1, colors.downloadButton, colors.downloadButtonText, 0x555555, 0xFFFFFF, "Обновить все")
y = y + 2
for i = from, (from + limit) do
if not changes[i] then break end
if not currentApps[changes[i]] then
status("Загрузка информации о приложении \"" .. fs.name(newApplications[changes[i]].name) .. "\"")
getApplication(changes[i])
end
x, y = drawApplication(x, y, changes[i], true)
end
if #changes > limit then
drawPageSwitchButtons(y)
end
buffer.resetDrawLimit()
else
local text = "У вас самое новое ПО"
buffer.text(math.floor(sizes.x + sizes.width / 2 - unicode.len(text) / 2), math.floor(obj.main.y + obj.main.height / 2 - 1), colors.description, text)
end
end
local function flush()
fromY = obj.main.y + 1
from = 1
fs.makeDirectory(appStorePath)
currentApps = {}
end
local function loadOldApplications()
oldApplications = files.loadTableFromFile(pathToApplications)
end
local function saveOldApplications()
files.saveTableToFile(pathToApplications, oldApplications)
end
local function drawAll(refreshIcons, force)
drawTopBar()
if currentTopBarElement == 5 then
updates()
else
drawMain(refreshIcons)
end
buffer.draw(force)
end
local function updateImageWindow()
clearMainZone()
local x, y = math.floor(sizes.x + sizes.width / 2 - updateImage.width / 2), math.floor(obj.main.y + obj.main.height / 2 - updateImage.height / 2 - 2)
buffer.image(x, y, updateImage)
return y + updateImage.height
end
local function updateImageWindowWithText(text)
local y = updateImageWindow() + 2
local x = math.floor(sizes.x + sizes.width / 2 - unicode.len(text) / 2)
buffer.text(x, y, colors.description, text)
end
local function updateAll()
local y = updateImageWindow()
local barWidth = math.floor(sizes.width * 0.6)
local xBar = math.floor(sizes.x + sizes.width / 2 - barWidth / 2)
y = y + 2
for i = 1, #changes do
local text = "Обновление " .. fs.name(newApplications[changes[i]].name)
local xText = math.floor(sizes.x + sizes.width / 2 - unicode.len(text) / 2)
buffer.square(sizes.x, y + 1, sizes.width, 1, 0xFFFFFF)
buffer.text(xText, y + 1, colors.description, text)
GUI.progressBar(xBar, y, barWidth, 1, 0xAAAAAA, 0x55FF55, i, #changes, true)
buffer.draw()
ecs.getOSApplication(newApplications[changes[i]], true)
end
changes = {}
oldApplications = newApplications
saveOldApplications()
end
------------------------------------------------------------------------------------------------------------------
buffer.start()
buffer.clear(0xFF8888)
local args = {...}
if args[1] == "updateCheck" then
currentTopBarElement = 5
end
calculateSizes()
flush()
loadOldApplications()
drawTopBar()
GUI.windowShadow(sizes.x, sizes.y, sizes.width, sizes.height, 50)
updateImageWindowWithText("Загрузка списка приложений")
buffer.draw()
getNewApplications()
getChanges()
drawAll(true, false)
while true do
local e = {event.pull()}
if e[1] == "touch" then
if obj.main:isClicked(e[3], e[4]) then
if obj.searchTextField:isClicked(e[3], e[4]) then
obj.searchTextField:input()
flush()
drawAll(true, false)
end
if currentTopBarElement < 5 then
for appIndex, app in pairs(currentApps) do
if app.buttonObject:isClicked(e[3], e[4]) then
app.buttonObject:press(0.3)
if app.buttonObject.text == "Обновить" or app.buttonObject.text == "Загрузить" then
app.buttonObject.text = "Загрузка"
app.buttonObject.disabled = true
app.buttonObject.colors.disabled.button, app.buttonObject.colors.disabled.text = colors.downloading, colors.downloadingText
app.buttonObject:draw()
buffer.draw()
ecs.getOSApplication(newApplications[appIndex], true)
app.buttonObject.text = "Установлено"
app.buttonObject.colors.disabled.button, app.buttonObject.colors.disabled.text = colors.downloaded, colors.downloadedText
app.buttonObject:draw()
buffer.draw()
end
break
end
end
else
if obj.updateAllButton and obj.updateAllButton:isClicked(e[3], e[4]) then
obj.updateAllButton:press()
updateAll()
flush()
drawAll()
end
end
if obj.nextPageButton then
if obj.nextPageButton:isClicked(e[3], e[4]) then
obj.nextPageButton:press()
fromY = obj.main.y + 1
from = from + limit
currentApps = {}
drawAll(true, false)
elseif obj.prevPageButton:isClicked(e[3], e[4]) then
if from > limit then
fromY = obj.main.y + 1
from = from - limit
currentApps = {}
drawAll(true, false)
end
end
end
end
if obj.windowActionButtons.close:isClicked(e[3], e[4]) then
obj.windowActionButtons.close:press()
return
end
for key, button in pairs(obj.topBarButtons) do
if button:isClicked(e[3], e[4]) then
currentTopBarElement = key
flush()
drawAll(true, false)
break
end
end
elseif e[1] == "scroll" then
if e[5] == 1 then
if (fromY < obj.main.y) then
fromY = fromY + 2
drawAll(false, false)
end
else
fromY = fromY - 2
drawAll(false, false)
end
end
end