Advertisement
Guest User

s

a guest
Nov 14th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.78 KB | None | 0 0
  1. requireInjector(getfenv(1))
  2.  
  3. local Ansi   = require('ansi')
  4. local Config = require('config')
  5. local SHA1   = require('sha1')
  6. local UI     = require('ui')
  7. local Util   = require('util')
  8.  
  9. -- scrap this entire file. don't muck with standard apis
  10.  
  11. local REGISTRY_DIR = 'usr/.registry'
  12.  
  13.  
  14. --                                           FIX SOMEDAY
  15. function os.registerApp(app, key)
  16.  
  17.   app.key = SHA1.sha1(key)
  18.   Util.writeTable(fs.combine(REGISTRY_DIR, app.key), app)
  19.   os.queueEvent('os_register_app')
  20. end
  21.  
  22. function os.unregisterApp(key)
  23.  
  24.   local filename = fs.combine(REGISTRY_DIR, SHA1.sha1(key))
  25.   if fs.exists(filename) then
  26.     fs.delete(filename)
  27.     os.queueEvent('os_register_app')
  28.   end
  29. end
  30.  
  31.  
  32. local sandboxEnv = Util.shallowCopy(getfenv(1))
  33. setmetatable(sandboxEnv, { __index = _G })
  34.  
  35. multishell.setTitle(multishell.getCurrent(), 'App Store')
  36. UI:configure('Appstore', ...)
  37.  
  38. local APP_DIR = 'usr/apps'
  39.  
  40. local sources = {
  41.  
  42.   { text = "STD Default",
  43.     event = 'source',
  44.     url = "http://pastebin.com/raw/zVws7eLq" }, --stock
  45. --[[
  46.   { text = "Discover",
  47.     event = 'source',
  48.     generateName = true,
  49.     url = "http://pastebin.com/raw/9bXfCz6M" }, --owned by dannysmc95
  50.  
  51.   { text = "Opus",
  52.     event = 'source',
  53.     url = "http://pastebin.com/raw/ajQ91Rmn" },
  54. ]]
  55. }
  56.  
  57. shell.setDir(APP_DIR)
  58.  
  59. function downloadApp(app)
  60.   local h
  61.  
  62.   if type(app.url) == "table" then
  63.     h = contextualGet(app.url[1])
  64.   else
  65.     h = http.get(app.url)
  66.   end
  67.  
  68.   if h then
  69.     local contents = h.readAll()
  70.     h:close()
  71.     return contents
  72.   end
  73. end
  74.  
  75. function runApp(app, checkExists, ...)
  76.  
  77.   local path, fn
  78.   local args = { ... }
  79.  
  80.   if checkExists and fs.exists(fs.combine(APP_DIR, app.name)) then
  81.     path = fs.combine(APP_DIR, app.name)
  82.   else
  83.     local program = downloadApp(app)
  84.  
  85.     fn = function()
  86.  
  87.       if not program then
  88.         error('Failed to download')
  89.       end
  90.  
  91.       local fn = loadstring(program, app.name)
  92.  
  93.       if not fn then
  94.         error('Failed to download')
  95.       end
  96.  
  97.       setfenv(fn, sandboxEnv)
  98.       fn(unpack(args))
  99.     end
  100.   end
  101.  
  102.   multishell.openTab({
  103.     title = app.name,
  104.     env = sandboxEnv,
  105.     path = path,
  106.     fn = fn,
  107.     focused = true,
  108.   })
  109.  
  110.   return true, 'Running program'
  111. end
  112.  
  113. local installApp = function(app)
  114.  
  115.   local program = downloadApp(app)
  116.   if not program then
  117.     return false, "Failed to download"
  118.   end
  119.  
  120.   local fullPath = fs.combine(APP_DIR, app.name)
  121.   Util.writeFile(fullPath, program)
  122.   return true, 'Installed as ' .. fullPath
  123. end
  124.  
  125. local viewApp = function(app)
  126.  
  127.   local program = downloadApp(app)
  128.   if not program then
  129.     return false, "Failed to download"
  130.   end
  131.  
  132.   Util.writeFile('/.source', program)
  133.   shell.openForegroundTab('edit /.source')
  134.   fs.delete('/.source')
  135.   return true
  136. end
  137.  
  138. local getSourceListing = function(source)
  139.   local contents = http.get(source.url)
  140.   if contents then
  141.  
  142.     local fn = loadstring(contents.readAll(), source.text)
  143.     contents.close()
  144.  
  145.     local env = { std = { } }
  146.     setmetatable(env, { __index = _G })
  147.     setfenv(fn, env)
  148.     fn()
  149.  
  150.     if env.contextualGet then
  151.       contextualGet = env.contextualGet
  152.     end
  153.  
  154.     source.storeURLs = env.std.storeURLs
  155.     source.storeCatagoryNames = env.std.storeCatagoryNames
  156.  
  157.     if source.storeURLs and source.storeCatagoryNames then
  158.       for k,v in pairs(source.storeURLs) do
  159.         if source.generateName then
  160.           v.name = v.title:match('(%w+)')
  161.           if not v.name or #v.name == 0 then
  162.             v.name = tostring(k)
  163.           else
  164.             v.name = v.name:lower()
  165.           end
  166.         else
  167.           v.name = k
  168.         end
  169.         v.categoryName = source.storeCatagoryNames[v.catagory]
  170.         v.ltitle = v.title:lower()
  171.       end
  172.     end
  173.   end
  174. end
  175.  
  176. local appPage = UI.Page({
  177.   menuBar = UI.MenuBar({
  178.     showBackButton = not pocket,
  179.     buttons = {
  180.       { text = 'Install', event = 'install' },
  181.       { text = 'Run',     event = 'run'     },
  182.       { text = 'View',    event = 'view'    },
  183.       { text = 'Remove',  event = 'uninstall', name = 'removeButton' },
  184.     },
  185.   }),
  186.   container = UI.Window({
  187.     x = 2,
  188.     y = 3,
  189.     height = UI.term.height - 3,
  190.     width = UI.term.width - 2,
  191.     viewport = UI.ViewportWindow(),
  192.   }),
  193.   notification = UI.Notification(),
  194.   accelerators = {
  195.     q = 'back',
  196.     backspace = 'back',
  197.   },
  198. })
  199.  
  200. function appPage.container.viewport:draw()
  201.   local app = self.parent.parent.app
  202.   local str = string.format(
  203.     '%s \nBy: %s \nCategory: %s\nFile name: %s\n\n%s',
  204.     Ansi.yellow .. app.title .. Ansi.reset,
  205.     app.creator,
  206.     app.categoryName, app.name,
  207.     Ansi.yellow .. app.description .. Ansi.reset)
  208.  
  209.   self:clear()
  210.   self:setCursorPos(1, 1)
  211.   self:print(str)
  212.   self.ymax = self.cursorY
  213.  
  214.   if appPage.notification.enabled then
  215.     appPage.notification:draw()
  216.   end
  217. end
  218.  
  219. function appPage:enable(source, app)
  220.   self.source = source
  221.   self.app = app
  222.   UI.Page.enable(self)
  223.  
  224.   self.container.viewport:setScrollPosition(0)
  225.   if fs.exists(fs.combine(APP_DIR, app.name)) then
  226.     self.menuBar.removeButton:enable('Remove')
  227.   else
  228.     self.menuBar.removeButton:disable('Remove')
  229.   end
  230. end
  231.  
  232. function appPage:eventHandler(event)
  233.   if event.type == 'back' then
  234.     UI:setPreviousPage()
  235.  
  236.   elseif event.type == 'run' then
  237.     self.notification:info('Running program', 3)
  238.     self:sync()
  239.     runApp(self.app, true)
  240.  
  241.   elseif event.type == 'view' then
  242.     self.notification:info('Downloading program', 3)
  243.     self:sync()
  244.     viewApp(self.app)
  245.  
  246.   elseif event.type == 'uninstall' then
  247.     if self.app.runOnly then
  248.       s,m = runApp(self.app, false, 'uninstall')
  249.     else
  250.       fs.delete(fs.combine(APP_DIR, self.app.name))
  251.       self.notification:success("Uninstalled " .. self.app.name, 3)
  252.       self:focusFirst(self)
  253.       self.menuBar.removeButton:disable('Remove')
  254.       self.menuBar:draw()
  255.  
  256.       os.unregisterApp(self.app.creator .. '.' .. self.app.name)
  257.     end
  258.  
  259.   elseif event.type == 'install' then
  260.     self.notification:info("Installing", 3)
  261.     self:sync()
  262.     local s, m
  263.     if self.app.runOnly then
  264.       s,m = runApp(self.app, false)
  265.     else
  266.       s,m = installApp(self.app)
  267.     end
  268.     if s then
  269.       self.notification:success(m, 3)
  270.  
  271.       if not self.app.runOnly then
  272.         self.menuBar.removeButton:enable('Remove')
  273.         self.menuBar:draw()
  274.  
  275.         local category = 'Apps'
  276.         if self.app.catagoryName == 'Game' then
  277.           category = 'Games'
  278.         end
  279.  
  280.         os.registerApp({
  281.           run = fs.combine(APP_DIR, self.app.name),
  282.           title = self.app.title,
  283.           category = category,
  284.           icon = self.app.icon,
  285.         }, self.app.creator .. '.' .. self.app.name)
  286.       end
  287.     else
  288.       self.notification:error(m, 3)
  289.     end
  290.   else
  291.     return UI.Page.eventHandler(self, event)
  292.   end
  293.   return true
  294. end
  295.  
  296. local categoryPage = UI.Page({
  297.   menuBar = UI.MenuBar({
  298.     buttons = {
  299.       { text = 'Catalog',  event = 'dropdown', dropdown = 'sourceMenu'   },
  300.       { text = 'Category', event = 'dropdown', dropdown = 'categoryMenu' },
  301.     },
  302.   }),
  303.   sourceMenu = UI.DropMenu({
  304.     buttons = sources,
  305.   }),
  306.   grid = UI.ScrollingGrid({
  307.     y = 2,
  308.     height = UI.term.height - 2,
  309.     columns = {
  310.       { heading = 'Title', key = 'title' },
  311.     },
  312.     sortColumn = 'title',
  313.     autospace = true,
  314.   }),
  315.   statusBar = UI.StatusBar(),
  316.   accelerators = {
  317.     l = 'lua',
  318.     q = 'quit',
  319.   },
  320. })
  321.  
  322. function categoryPage:setCategory(source, name, index)
  323.   self.grid.values = { }
  324.   for k,v in pairs(source.storeURLs) do
  325.     if index == 0 or index == v.catagory then
  326.       table.insert(self.grid.values, v)
  327.     end
  328.   end
  329.   self.statusBar:setStatus(string.format('%s: %s', source.text, name))
  330.   self.grid:update()
  331.   self.grid:setIndex(1)
  332. end
  333.  
  334. function categoryPage:setSource(source)
  335.  
  336.   if not source.categoryMenu then
  337.  
  338.     self.statusBar:setStatus('Loading...')
  339.     self.statusBar:draw()
  340.     self:sync()
  341.  
  342.     getSourceListing(source)
  343.  
  344.     if not source.storeURLs then
  345.       error('Unable to download application list')
  346.     end
  347.  
  348.     local buttons = { }
  349.     for k,v in Util.spairs(source.storeCatagoryNames,
  350.           function(a, b) return a:lower() < b:lower() end) do
  351.  
  352.       if v ~= 'Operating System' then
  353.         table.insert(buttons, {
  354.           text = v,
  355.           event = 'category',
  356.           index = k,
  357.         })
  358.       end
  359.     end
  360.  
  361.     source.categoryMenu = UI.DropMenu({
  362.       y = 2,
  363.       x = 1,
  364.       buttons = buttons,
  365.     })
  366.     source.index, source.name = Util.first(source.storeCatagoryNames)
  367.  
  368.     categoryPage:add({
  369.       categoryMenu = source.categoryMenu
  370.     })
  371.   end
  372.  
  373.   self.source = source
  374.   self.categoryMenu = source.categoryMenu
  375.   categoryPage:setCategory(source, source.name, source.index)
  376. end
  377.  
  378. function categoryPage.grid:sortCompare(a, b)
  379.   return a.ltitle < b.ltitle
  380. end
  381.  
  382. function categoryPage.grid:getRowTextColor(row, selected)
  383.   if fs.exists(fs.combine(APP_DIR, row.name)) then
  384.     return colors.orange
  385.   end
  386.   return UI.Grid:getRowTextColor(row, selected)
  387. end
  388.  
  389. function categoryPage:eventHandler(event)
  390.  
  391.   if event.type == 'grid_select' or event.type == 'select' then
  392.     UI:setPage(appPage, self.source, self.grid:getSelected())
  393.  
  394.   elseif event.type == 'category' then
  395.     self:setCategory(self.source, event.button.text, event.button.index)
  396.     self:setFocus(self.grid)
  397.     self:draw()
  398.  
  399.   elseif event.type == 'source' then
  400.     self:setFocus(self.grid)
  401.     self:setSource(event.button)
  402.     self:draw()
  403.  
  404.   elseif event.type == 'quit' then
  405.     UI:exitPullEvents()
  406.  
  407.   else
  408.     return UI.Page.eventHandler(self, event)
  409.   end
  410.   return true
  411. end
  412.  
  413. print("Retrieving catalog list")
  414. categoryPage:setSource(sources[1])
  415.  
  416. UI:setPage(categoryPage)
  417. UI:pullEvents()
  418. UI.term:reset()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement