Compare commits
6 Commits
9df738465a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a2494b11b0 | |||
| 10a2cd4880 | |||
| 95734536f9 | |||
| 5a9fa01cd7 | |||
| 7c1e0de4ff | |||
| aa64d18060 |
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
perms = {
|
|
||||||
repo = false,
|
|
||||||
network = false,
|
|
||||||
app = false,
|
|
||||||
http = false,
|
|
||||||
},
|
|
||||||
author = "CadenCoaster",
|
|
||||||
name = "Dookie Clicker",
|
|
||||||
appid = "com.ruffles.clicker",
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
BIN
apps/org.ruffles.launcher
Normal file
BIN
apps/org.ruffles.launcher
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
37
install.lua
Normal file
37
install.lua
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
local expect = require "cc.expect".expect
|
||||||
|
local base_url = "https://git.cadencoaster.com/Rivulet/ccphone/raw/branch/main/"
|
||||||
|
local function download_to(path)
|
||||||
|
expect(2, path, "string")
|
||||||
|
term.write(path)
|
||||||
|
if not http.checkURL(base_url..path) then error("URL is not valid" ,2) end
|
||||||
|
local data = http.get(base_url..path).readAll()
|
||||||
|
fs.makeDir(fs.getDir(path))
|
||||||
|
local file = fs.open(path,"w")
|
||||||
|
if not file then error("Failed to open file", 2) end
|
||||||
|
file.write(data)
|
||||||
|
file.close()
|
||||||
|
print(" OK")
|
||||||
|
end
|
||||||
|
|
||||||
|
local filesystem = {
|
||||||
|
files = {
|
||||||
|
"startup/00_entrypointclient.lua",
|
||||||
|
"startup/99_phoneOS.lua",
|
||||||
|
"startup/01_repo.lua",
|
||||||
|
"libs/containers.lua",
|
||||||
|
"libs/windows.lua",
|
||||||
|
"apps/com.ruffles.launcher",
|
||||||
|
},
|
||||||
|
dirs = {
|
||||||
|
"global-libraries",
|
||||||
|
"apps-meta",
|
||||||
|
},
|
||||||
|
}for _,i in ipairs(filesystem.dirs) do
|
||||||
|
print("making dir",i)
|
||||||
|
fs.makeDir(i)
|
||||||
|
end
|
||||||
|
for _,i in ipairs(filesystem.files) do
|
||||||
|
download_to(i)
|
||||||
|
end
|
||||||
|
|
||||||
|
shell.run("wget run https://raw.githubusercontent.com/Pyroxenium/Basalt2/main/install.lua -f /global-libraries/basalt.lua")
|
||||||
File diff suppressed because one or more lines are too long
3605
libs/deflate.lua
Normal file
3605
libs/deflate.lua
Normal file
File diff suppressed because it is too large
Load Diff
22
libs/persistent-storage.lua
Normal file
22
libs/persistent-storage.lua
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
local id = ...
|
||||||
|
local deflate = dofile("libs/deflate.lua")
|
||||||
|
local filepath = fs.combine("/persisted-data",id)
|
||||||
|
local expect = dofile("rom/modules/main/cc/expect.lua")
|
||||||
|
local expect, field = expect.expect, expect.field
|
||||||
|
local lib={}
|
||||||
|
function lib.load()
|
||||||
|
if fs.exists(filepath) then
|
||||||
|
local file = fs.open(filepath,"r")
|
||||||
|
local data = textutils.unserialise(deflate:DecompressDeflate(file.readAll()))
|
||||||
|
file.close()
|
||||||
|
return data
|
||||||
|
else
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function lib.save(data)
|
||||||
|
expect(1,data,"table")
|
||||||
|
local file = fs.open(filepath,"w")
|
||||||
|
file.write(deflate:CompressDeflate(textutils.serialise(data),{level=8}))
|
||||||
|
end
|
||||||
|
return lib
|
||||||
@@ -7,6 +7,60 @@ local function add(t, v)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local function normalize_color(c)
|
||||||
|
if type(c) ~= "number" then error("bad color", 2) end
|
||||||
|
if c < 1 then error("bad color", 2) end
|
||||||
|
|
||||||
|
-- If c is already a power of two, this keeps it.
|
||||||
|
-- If it's a mask, this picks the highest power-of-two <= c.
|
||||||
|
local p = 1
|
||||||
|
while p * 2 <= c do p = p * 2 end
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns: bestColor, bestCount, totalCells, countsTable
|
||||||
|
-- countsTable maps colorBit -> count
|
||||||
|
local function most_common_bg(win, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
|
||||||
|
local w, h
|
||||||
|
if win.getSize then
|
||||||
|
w, h = win.getSize()
|
||||||
|
else
|
||||||
|
w, h = win.w, win.h
|
||||||
|
end
|
||||||
|
|
||||||
|
local ignore = opts.ignore
|
||||||
|
if ignore ~= nil then ignore = normalize_color(ignore) end
|
||||||
|
|
||||||
|
local counts = {}
|
||||||
|
local total = 0
|
||||||
|
|
||||||
|
for x = 1, w do
|
||||||
|
local col = win.buffer and win.buffer[x]
|
||||||
|
for y = 1, h do
|
||||||
|
local cell = col and col[y]
|
||||||
|
local bc = cell and cell.bc or win.bgColor or colors.black
|
||||||
|
bc = normalize_color(bc)
|
||||||
|
|
||||||
|
if not ignore or bc ~= ignore then
|
||||||
|
counts[bc] = (counts[bc] or 0) + 1
|
||||||
|
total = total + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local fallback = normalize_color(opts.fallback or win.bgColor or colors.black)
|
||||||
|
local best, bestN = fallback, -1
|
||||||
|
|
||||||
|
for c, n in pairs(counts) do
|
||||||
|
if n > bestN or (n == bestN and c == fallback) then
|
||||||
|
best, bestN = c, n
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return best, bestN, total, counts
|
||||||
|
end
|
||||||
|
|
||||||
-- hex <-> color bit lookups (Lua 5.1 safe)
|
-- hex <-> color bit lookups (Lua 5.1 safe)
|
||||||
local HEX = "0123456789abcdef"
|
local HEX = "0123456789abcdef"
|
||||||
@@ -65,6 +119,11 @@ function lib.create(name, w, h, x, y)
|
|||||||
_palette = {}, -- optional local palette store
|
_palette = {}, -- optional local palette store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function t.getMostCommonBackgroundColor(opts)
|
||||||
|
local c, n, total, counts = most_common_bg(t, opts)
|
||||||
|
return c, color_to_hex[c], n, total, counts
|
||||||
|
end
|
||||||
|
|
||||||
local function init_col(xi)
|
local function init_col(xi)
|
||||||
local w = t.w
|
local w = t.w
|
||||||
local h = t.h
|
local h = t.h
|
||||||
|
|||||||
82
scan.lua
Normal file
82
scan.lua
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
local exceptions = {
|
||||||
|
["/scan.lua"] = true,
|
||||||
|
["/install.lua"] = true,
|
||||||
|
["scan.lua"] = true,
|
||||||
|
["install.lua"] = true,
|
||||||
|
["/.settings"] = true,
|
||||||
|
[".settings"] = true,
|
||||||
|
["/.git"] = true,
|
||||||
|
[".git"] = true,
|
||||||
|
["/rom"] = true,
|
||||||
|
["rom"] = true,
|
||||||
|
["/scan.dat"] = true,
|
||||||
|
["scan.dat"] = true
|
||||||
|
}
|
||||||
|
local function scan(dir)
|
||||||
|
local out = {}
|
||||||
|
for _,i in ipairs(fs.list(dir)) do
|
||||||
|
local path = fs.combine(dir,i)
|
||||||
|
if exceptions[path] == nil then
|
||||||
|
if fs.isDir(path) then
|
||||||
|
out[i] = scan(path)
|
||||||
|
else
|
||||||
|
local file = fs.open(path,"r")
|
||||||
|
out[i] = file.readAll()
|
||||||
|
file.close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
local function format(scandata)
|
||||||
|
local format_data = {
|
||||||
|
files = {},
|
||||||
|
dirs = {}
|
||||||
|
}
|
||||||
|
local function scan_format(dir,data)
|
||||||
|
if type(data) == "table" then
|
||||||
|
local has_scanned = false
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
has_scanned = true
|
||||||
|
scan_format(fs.combine(dir,k),v)
|
||||||
|
end
|
||||||
|
if not has_scanned then
|
||||||
|
format_data.dirs[#format_data.dirs+1] = dir
|
||||||
|
end
|
||||||
|
else
|
||||||
|
format_data.files[#format_data.files+1] = dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
scan_format("/",scandata)
|
||||||
|
return format_data
|
||||||
|
end
|
||||||
|
local textdata = textutils.serialise(format(scan("/")))
|
||||||
|
local firstpart = [[local expect = require "cc.expect".expect
|
||||||
|
local base_url = "https://git.cadencoaster.com/Rivulet/ccphone/raw/branch/main/"
|
||||||
|
local function download_to(path)
|
||||||
|
expect(2, path, "string")
|
||||||
|
term.write(path)
|
||||||
|
if not http.checkURL(base_url..path) then error("URL is not valid" ,2) end
|
||||||
|
local data = http.get(base_url..path).readAll()
|
||||||
|
fs.makeDir(fs.getDir(path))
|
||||||
|
local file = fs.open(path,"w")
|
||||||
|
if not file then error("Failed to open file", 2) end
|
||||||
|
file.write(data)
|
||||||
|
file.close()
|
||||||
|
print(" OK")
|
||||||
|
end
|
||||||
|
|
||||||
|
local filesystem = ]]
|
||||||
|
local secondpart = [[
|
||||||
|
for _,i in ipairs(filesystem.dirs) do
|
||||||
|
print("making dir",i)
|
||||||
|
fs.makeDir(i)
|
||||||
|
end
|
||||||
|
for _,i in ipairs(filesystem.files) do
|
||||||
|
download_to(i)
|
||||||
|
end
|
||||||
|
|
||||||
|
shell.run("wget run https://raw.githubusercontent.com/Pyroxenium/Basalt2/main/install.lua -f /global-libraries/basalt.lua")]]
|
||||||
|
local outfile = fs.open("install.lua","w")
|
||||||
|
outfile.write(firstpart..textdata..secondpart)
|
||||||
|
outfile.close()
|
||||||
@@ -14,7 +14,6 @@ function _G.app.getApps()
|
|||||||
local out = {}
|
local out = {}
|
||||||
for _,f in ipairs(fs.list("/apps-meta")) do
|
for _,f in ipairs(fs.list("/apps-meta")) do
|
||||||
if fs.exists(fs.combine("/apps-meta",f)) then
|
if fs.exists(fs.combine("/apps-meta",f)) then
|
||||||
print(f)
|
|
||||||
local file = fs.open(fs.combine("/apps-meta",f),"r")
|
local file = fs.open(fs.combine("/apps-meta",f),"r")
|
||||||
if file then
|
if file then
|
||||||
out[#out+1] = textutils.unserialise(file.readAll())
|
out[#out+1] = textutils.unserialise(file.readAll())
|
||||||
@@ -24,13 +23,54 @@ function _G.app.getApps()
|
|||||||
end
|
end
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
function _G.app.launch(id,perms)
|
function _G.app.closeApp(pid)
|
||||||
|
if pid == focusedapp then
|
||||||
|
app.focusapp(-1)
|
||||||
|
apps[pid] = nil
|
||||||
|
else
|
||||||
|
apps[pid] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function _G.app.getRunningApps()
|
||||||
|
local pids = {}
|
||||||
|
for k,_ in pairs(apps) do
|
||||||
|
pids[#pids+1] = k
|
||||||
|
end
|
||||||
|
return pids
|
||||||
|
end
|
||||||
|
function _G.app.getTitle(pid)
|
||||||
|
if not apps[pid] then return false, "Process not found" end
|
||||||
|
return apps[pid].title
|
||||||
|
end
|
||||||
|
function _G.app.getDetail(pid)
|
||||||
|
if not apps[pid] then return false, "Process not found" end
|
||||||
|
local registered_apps = app.getApps()
|
||||||
|
local appid = apps[pid].id
|
||||||
|
local appdetails = nil
|
||||||
|
local msg = "Details not found (likely doesn't have a metadata file)"
|
||||||
|
for _,registered_app in ipairs(registered_apps) do
|
||||||
|
if registered_app.appid == appid then
|
||||||
|
appdetails = registered_app
|
||||||
|
msg = nil
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return appdetails, msg
|
||||||
|
end
|
||||||
|
function _G.app.launch(id,perms,parentperms)
|
||||||
|
if parentperms then
|
||||||
|
for k,v in pairs(perms) do
|
||||||
|
if v and not parentperms[k] then
|
||||||
|
return false, "Unable to grant permission: "..k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
local w,h = term.getSize()
|
local w,h = term.getSize()
|
||||||
if not fs.exists(fs.combine("/apps",id)) then return false,"App Not Found" end
|
if not fs.exists(fs.combine("/apps",id)) then return false,"App Not Found" end
|
||||||
local win = windows.create(id,w,h-2,1,2)
|
local win = windows.create(id,w,h-2,1,2)
|
||||||
local env = containers.getENV(fs.combine("/apps",id), win, perms)
|
local env = containers.getENV(fs.combine("/apps",id), win, perms)
|
||||||
local appobj = {win=win,co=nil,id=id,title=id}
|
local appobj = {win=win,co=nil,id=id,title=id}
|
||||||
function env.setAppTitle(str) appobj.title=str end
|
function env.setAppTitle(str) appobj.title=tostring(str) end
|
||||||
appobj.co = coroutine.create(function () containers.start(env) end)
|
appobj.co = coroutine.create(function () containers.start(env) end)
|
||||||
local pid = -1
|
local pid = -1
|
||||||
for k=1,#apps+1 do
|
for k=1,#apps+1 do
|
||||||
@@ -75,7 +115,7 @@ local function render()
|
|||||||
term.setCursorPos(1,1)
|
term.setCursorPos(1,1)
|
||||||
term.setBackgroundColor(colors.black)
|
term.setBackgroundColor(colors.black)
|
||||||
if focusedapp then
|
if focusedapp then
|
||||||
term.setBackgroundColor(focusedapp.win.getBackgroundColour())
|
term.setBackgroundColor(focusedapp.win.getMostCommonBackgroundColor())
|
||||||
end
|
end
|
||||||
term.clearLine()
|
term.clearLine()
|
||||||
term.write(os.date("%I:%M %p"))
|
term.write(os.date("%I:%M %p"))
|
||||||
@@ -87,6 +127,7 @@ local function render()
|
|||||||
term.setCursorPos(w-right:len()+1,1)
|
term.setCursorPos(w-right:len()+1,1)
|
||||||
term.write(right)
|
term.write(right)
|
||||||
term.setCursorPos((w/2)-(home_button:len()/2)+1,h)
|
term.setCursorPos((w/2)-(home_button:len()/2)+1,h)
|
||||||
|
term.clearLine()
|
||||||
term.write(home_button)
|
term.write(home_button)
|
||||||
term.setCursorPos(1,h)
|
term.setCursorPos(1,h)
|
||||||
if focusedapp then
|
if focusedapp then
|
||||||
@@ -119,16 +160,7 @@ local function process()
|
|||||||
event[4] = event[4]-1
|
event[4] = event[4]-1
|
||||||
end
|
end
|
||||||
if focusedapp then
|
if focusedapp then
|
||||||
if focusedapp.event then
|
if focusedapp.filter == nil or focusedapp.filter == event[1] then
|
||||||
local success, content = coroutine.resume(focusedapp.co,table.unpack(focusedapp.event))
|
|
||||||
if success then
|
|
||||||
-- print(focusedapp.title,focusedapp.filter)
|
|
||||||
focusedapp.event = nil
|
|
||||||
focusedapp.filter = content
|
|
||||||
else
|
|
||||||
app.focusapp(-1)
|
|
||||||
end
|
|
||||||
elseif focusedapp.filter == nil or focusedapp.filter == event[1] then
|
|
||||||
local success, content = coroutine.resume(focusedapp.co,table.unpack(event))
|
local success, content = coroutine.resume(focusedapp.co,table.unpack(event))
|
||||||
if success then
|
if success then
|
||||||
focusedapp.filter = content
|
focusedapp.filter = content
|
||||||
@@ -138,13 +170,16 @@ local function process()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for k,v in pairs(apps) do
|
for k,v in pairs(apps) do
|
||||||
if v.filter == nil or v.filter == event[1] and v.event == nil and v ~= focusedapp then
|
if (v.filter == nil or v.filter == event[1]) and v ~= focusedapp and event[1] ~= "mouse_click" and event[1] ~= "mouse_up" and event[1] ~= "mouse_drag" and event[1] ~= "mouse_scroll" and event[1] ~= "char" and event[1] ~= "key" and event[1] ~= "key_up" then
|
||||||
v.event = event
|
local success, content = coroutine.resume(v.co,table.unpack(event))
|
||||||
|
if success then
|
||||||
|
v.filter = content
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print("launching launcher app..")
|
print("launching launcher app..")
|
||||||
launcherapp = app.launch(launcherappid,{http=true,app=true,repo=true,network=true})
|
launcherapp = app.launch(launcherappid,{http=true,app=true,repo=true,network=true,peripheral=true})
|
||||||
print("launched launcher app")
|
print("launched launcher app")
|
||||||
parallel.waitForAny(process,render,network.run)
|
parallel.waitForAny(process,render,network.run)
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
local basalt = require("globals.basalt")
|
|
||||||
|
|
||||||
-- Get the main frame (your window)
|
|
||||||
local count = 0
|
|
||||||
local main = basalt.getMainFrame()
|
|
||||||
main:setBackground(colors.black)
|
|
||||||
local w,h = term.getSize()
|
|
||||||
main:addLabel({
|
|
||||||
x = w/2-(7/2)+1,
|
|
||||||
y = 2,
|
|
||||||
text = "Welcome!",
|
|
||||||
foreground = colors.yellow
|
|
||||||
})
|
|
||||||
local countLabel = main:addLabel({
|
|
||||||
x = w/2-(7/2)+1,
|
|
||||||
y = 5,
|
|
||||||
text = "0",
|
|
||||||
foreground = colors.white
|
|
||||||
})
|
|
||||||
|
|
||||||
local button = main:addButton({
|
|
||||||
x = w/2-(7/2)+1,
|
|
||||||
y = 10,
|
|
||||||
text = "Click Me!",
|
|
||||||
foreground = colors.white
|
|
||||||
}):center():onClick(function () count = count + 1 countLabel:setText(tostring(count)) end)
|
|
||||||
|
|
||||||
|
|
||||||
basalt.run()
|
|
||||||
Reference in New Issue
Block a user