mirror of
https://github.com/kepler155c/opus
synced 2024-11-17 14:14:50 +00:00
387 lines
8.8 KiB
Lua
387 lines
8.8 KiB
Lua
require = requireInjector(getfenv(1))
|
|
local Util = require('util')
|
|
local class = require('class')
|
|
local UI = require('ui')
|
|
local Event = require('event')
|
|
|
|
local sandboxEnv = Util.shallowCopy(getfenv(1))
|
|
setmetatable(sandboxEnv, { __index = _G })
|
|
|
|
multishell.setTitle(multishell.getCurrent(), 'App Store')
|
|
UI:configure('Appstore', ...)
|
|
|
|
local sources = {
|
|
|
|
{ text = "STD Default",
|
|
event = 'source',
|
|
url = "http://pastebin.com/raw/zVws7eLq" }, --stock
|
|
|
|
{ text = "Discover",
|
|
event = 'source',
|
|
generateName = true,
|
|
url = "http://pastebin.com/raw/9bXfCz6M" }, --owned by dannysmc95
|
|
|
|
{ text = "Opus",
|
|
event = 'source',
|
|
url = "http://pastebin.com/raw/ajQ91Rmn" },
|
|
}
|
|
|
|
shell.setDir('/apps')
|
|
|
|
function downloadApp(app)
|
|
local h
|
|
|
|
if type(app.url) == "table" then
|
|
h = contextualGet(app.url[1])
|
|
else
|
|
h = http.get(app.url)
|
|
end
|
|
|
|
if h then
|
|
local contents = h.readAll()
|
|
h:close()
|
|
return contents
|
|
end
|
|
end
|
|
|
|
function runApp(app, checkExists, ...)
|
|
|
|
local path, fn
|
|
local args = { ... }
|
|
|
|
if checkExists and fs.exists(fs.combine('/apps', app.name)) then
|
|
path = fs.combine('/apps', app.name)
|
|
else
|
|
local program = downloadApp(app)
|
|
|
|
fn = function()
|
|
|
|
if not program then
|
|
error('Failed to download')
|
|
end
|
|
|
|
local fn = loadstring(program, app.name)
|
|
|
|
if not fn then
|
|
error('Failed to download')
|
|
end
|
|
|
|
setfenv(fn, sandboxEnv)
|
|
fn(unpack(args))
|
|
end
|
|
end
|
|
|
|
multishell.openTab({
|
|
title = app.name,
|
|
env = sandboxEnv,
|
|
path = path,
|
|
fn = fn,
|
|
focused = true,
|
|
})
|
|
|
|
return true, 'Running program'
|
|
end
|
|
|
|
local installApp = function(app)
|
|
|
|
local program = downloadApp(app)
|
|
if not program then
|
|
return false, "Failed to download"
|
|
end
|
|
|
|
local fullPath = fs.combine('/apps', app.name)
|
|
Util.writeFile(fullPath, program)
|
|
return true, 'Installed as ' .. fullPath
|
|
end
|
|
|
|
local viewApp = function(app)
|
|
|
|
local program = downloadApp(app)
|
|
if not program then
|
|
return false, "Failed to download"
|
|
end
|
|
|
|
Util.writeFile('/.source', program)
|
|
shell.openForegroundTab('edit /.source')
|
|
return true
|
|
end
|
|
|
|
local getSourceListing = function(source)
|
|
local contents = http.get(source.url)
|
|
if contents then
|
|
|
|
local fn = loadstring(contents.readAll(), source.text)
|
|
contents.close()
|
|
|
|
local env = { std = { } }
|
|
setmetatable(env, { __index = _G })
|
|
setfenv(fn, env)
|
|
fn()
|
|
|
|
if env.contextualGet then
|
|
contextualGet = env.contextualGet
|
|
end
|
|
|
|
source.storeURLs = env.std.storeURLs
|
|
source.storeCatagoryNames = env.std.storeCatagoryNames
|
|
|
|
if source.storeURLs and source.storeCatagoryNames then
|
|
for k,v in pairs(source.storeURLs) do
|
|
if source.generateName then
|
|
v.name = v.title:match('(%w+)')
|
|
if not v.name or #v.name == 0 then
|
|
v.name = tostring(k)
|
|
else
|
|
v.name = v.name:lower()
|
|
end
|
|
else
|
|
v.name = k
|
|
end
|
|
v.categoryName = source.storeCatagoryNames[v.catagory]
|
|
v.ltitle = v.title:lower()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local appPage = UI.Page({
|
|
backgroundColor = UI.ViewportWindow.defaults.backgroundColor,
|
|
menuBar = UI.MenuBar({
|
|
showBackButton = not os.isPocket(),
|
|
buttons = {
|
|
{ text = 'Install', event = 'install' },
|
|
{ text = 'Run', event = 'run' },
|
|
{ text = 'View', event = 'view' },
|
|
{ text = 'Remove', event = 'uninstall', name = 'removeButton' },
|
|
},
|
|
}),
|
|
container = UI.Window({
|
|
x = 2,
|
|
y = 3,
|
|
height = UI.term.height - 3,
|
|
width = UI.term.width - 2,
|
|
viewport = UI.ViewportWindow(),
|
|
}),
|
|
notification = UI.Notification(),
|
|
accelerators = {
|
|
q = 'back',
|
|
backspace = 'back',
|
|
},
|
|
})
|
|
|
|
function appPage.container.viewport:draw()
|
|
local app = self.parent.parent.app
|
|
local str = string.format(
|
|
'By: %s\nCategory: %s\nFile name: %s\n\n%s',
|
|
app.creator, app.categoryName, app.name, app.description)
|
|
|
|
self:clear()
|
|
local y = self:wrappedWrite(1, 1, app.title, self.width, nil, colors.yellow)
|
|
self.height = self:wrappedWrite(1, y, str, self.width)
|
|
|
|
if appPage.notification.enabled then
|
|
appPage.notification:draw()
|
|
end
|
|
end
|
|
|
|
function appPage:enable(source, app)
|
|
self.source = source
|
|
self.app = app
|
|
UI.Page.enable(self)
|
|
|
|
self.container.viewport:setScrollPosition(0)
|
|
if fs.exists(fs.combine('/apps', app.name)) then
|
|
self.menuBar.removeButton:enable('Remove')
|
|
else
|
|
self.menuBar.removeButton:disable('Remove')
|
|
end
|
|
end
|
|
|
|
function appPage:eventHandler(event)
|
|
if event.type == 'back' then
|
|
UI:setPreviousPage()
|
|
|
|
elseif event.type == 'run' then
|
|
self.notification:info('Running program', 3)
|
|
self:sync()
|
|
runApp(self.app, true)
|
|
|
|
elseif event.type == 'view' then
|
|
self.notification:info('Downloading program', 3)
|
|
self:sync()
|
|
viewApp(self.app)
|
|
|
|
elseif event.type == 'uninstall' then
|
|
if self.app.runOnly then
|
|
s,m = runApp(self.app, false, 'uninstall')
|
|
else
|
|
fs.delete(fs.combine('/apps', self.app.name))
|
|
self.notification:success("Uninstalled " .. self.app.name, 3)
|
|
self:focusFirst(self)
|
|
self.menuBar.removeButton:disable('Remove')
|
|
self.menuBar:draw()
|
|
|
|
os.unregisterApp(fs.combine('/apps', self.app.name))
|
|
end
|
|
|
|
elseif event.type == 'install' then
|
|
self.notification:info("Installing", 3)
|
|
self:sync()
|
|
local s, m
|
|
if self.app.runOnly then
|
|
s,m = runApp(self.app, false)
|
|
else
|
|
s,m = installApp(self.app)
|
|
end
|
|
if s then
|
|
self.notification:success(m, 3)
|
|
|
|
if not self.app.runOnly then
|
|
self.menuBar.removeButton:enable('Remove')
|
|
self.menuBar:draw()
|
|
|
|
local category = 'Apps'
|
|
if self.app.catagoryName == 'Game' then
|
|
category = 'Games'
|
|
end
|
|
|
|
os.registerApp({
|
|
run = fs.combine('/apps', self.app.name),
|
|
title = self.app.title,
|
|
category = category,
|
|
icon = self.app.icon,
|
|
})
|
|
end
|
|
else
|
|
self.notification:error(m, 3)
|
|
end
|
|
else
|
|
return UI.Page.eventHandler(self, event)
|
|
end
|
|
return true
|
|
end
|
|
|
|
local categoryPage = UI.Page({
|
|
menuBar = UI.MenuBar({
|
|
buttons = {
|
|
{ text = 'Catalog', event = 'dropdown', dropdown = 'sourceMenu' },
|
|
{ text = 'Category', event = 'dropdown', dropdown = 'categoryMenu' },
|
|
},
|
|
}),
|
|
sourceMenu = UI.DropMenu({
|
|
buttons = sources,
|
|
}),
|
|
grid = UI.ScrollingGrid({
|
|
y = 2,
|
|
height = UI.term.height - 2,
|
|
columns = {
|
|
{ heading = 'Title', key = 'title' },
|
|
},
|
|
sortColumn = 'title',
|
|
autospace = true,
|
|
}),
|
|
statusBar = UI.StatusBar(),
|
|
accelerators = {
|
|
l = 'lua',
|
|
q = 'quit',
|
|
},
|
|
})
|
|
|
|
function categoryPage:setCategory(source, name, index)
|
|
self.grid.values = { }
|
|
for k,v in pairs(source.storeURLs) do
|
|
if index == 0 or index == v.catagory then
|
|
table.insert(self.grid.values, v)
|
|
end
|
|
end
|
|
self.statusBar:setStatus(string.format('%s: %s', source.text, name))
|
|
self.grid:update()
|
|
self.grid:setIndex(1)
|
|
end
|
|
|
|
function categoryPage:setSource(source)
|
|
|
|
if not source.categoryMenu then
|
|
|
|
self.statusBar:setStatus('Loading...')
|
|
self.statusBar:draw()
|
|
self:sync()
|
|
|
|
getSourceListing(source)
|
|
|
|
if not source.storeURLs then
|
|
error('Unable to download application list')
|
|
end
|
|
|
|
local buttons = { }
|
|
for k,v in Util.spairs(source.storeCatagoryNames,
|
|
function(a, b) return a:lower() < b:lower() end) do
|
|
|
|
if v ~= 'Operating System' then
|
|
table.insert(buttons, {
|
|
text = v,
|
|
event = 'category',
|
|
index = k,
|
|
})
|
|
end
|
|
end
|
|
|
|
source.categoryMenu = UI.DropMenu({
|
|
y = 2,
|
|
x = 1,
|
|
buttons = buttons,
|
|
})
|
|
source.index, source.name = Util.first(source.storeCatagoryNames)
|
|
|
|
categoryPage:add({
|
|
categoryMenu = source.categoryMenu
|
|
})
|
|
end
|
|
|
|
self.source = source
|
|
self.categoryMenu = source.categoryMenu
|
|
categoryPage:setCategory(source, source.name, source.index)
|
|
end
|
|
|
|
function categoryPage.grid:sortCompare(a, b)
|
|
return a.ltitle < b.ltitle
|
|
end
|
|
|
|
function categoryPage.grid:getRowTextColor(row, selected)
|
|
if fs.exists(fs.combine('/apps', row.name)) then
|
|
return colors.orange
|
|
end
|
|
return UI.Grid:getRowTextColor(row, selected)
|
|
end
|
|
|
|
function categoryPage:eventHandler(event)
|
|
|
|
if event.type == 'grid_select' or event.type == 'select' then
|
|
UI:setPage(appPage, self.source, self.grid:getSelected())
|
|
|
|
elseif event.type == 'category' then
|
|
self:setCategory(self.source, event.button.text, event.button.index)
|
|
self:setFocus(self.grid)
|
|
self:draw()
|
|
|
|
elseif event.type == 'source' then
|
|
self:setFocus(self.grid)
|
|
self:setSource(event.button)
|
|
self:draw()
|
|
|
|
elseif event.type == 'quit' then
|
|
Event.exitPullEvents()
|
|
|
|
else
|
|
return UI.Page.eventHandler(self, event)
|
|
end
|
|
return true
|
|
end
|
|
|
|
print("Retrieving catalog list")
|
|
categoryPage:setSource(sources[1])
|
|
|
|
UI:setPage(categoryPage)
|
|
Event.pullEvents()
|
|
UI.term:reset()
|