From 9cfb6898096ece0768fba7c6dab26d5173f6f002 Mon Sep 17 00:00:00 2001
From: xomf <xomf@noreply.localhost>
Date: Sat, 31 May 2025 17:19:15 +0000
Subject: [PATCH] Add slabos.lua

---
 slabos.lua | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 289 insertions(+)
 create mode 100644 slabos.lua

diff --git a/slabos.lua b/slabos.lua
new file mode 100644
index 0000000..86628d8
--- /dev/null
+++ b/slabos.lua
@@ -0,0 +1,289 @@
+local basalt = require("basalt")
+
+local main = basalt.getMainFrame()
+
+local FRAME_WIDTH = 26
+local FRAME_HEIGHT = 19
+local CONTROL_BUTTON_Y = 20 
+
+local homescreen = main:addFrame()
+    :setPosition(1, 1)
+    :setSize(FRAME_WIDTH, FRAME_HEIGHT)
+    :setBackground(colours.blue)
+    :setVisible(true) 
+
+local active_app_frames = {}
+local current_active_frame = homescreen 
+
+local app_switcher_frame = main:addFrame()
+    :setPosition(1, 1)
+    :setSize(FRAME_WIDTH, FRAME_HEIGHT)
+    :setBackground(colours.brown)
+    :setVisible(false) 
+
+function show_payment_confirmation(amount, purpose, callback)
+
+    local payment_confirmation_frame = main:addFrame()
+        :setPosition(1, 1) 
+        :setSize(FRAME_WIDTH, FRAME_HEIGHT / 3) 
+        :setBackground(colours.black) 
+    payment_confirmation_frame.z = 99
+    payment_confirmation_frame.focused = true
+
+    payment_confirmation_frame:addLabel()
+        :setText("Confirm Payment") 
+        :setForeground(colours.white) 
+
+    payment_confirmation_frame:addLabel()
+        :setPosition(1, 3) 
+        :setText(amount .. "G -> " .. purpose) 
+        :setForeground(colours.white) 
+
+    payment_confirmation_frame:addButton()
+        :setText("Confirm") 
+        :setPosition(1, 6) 
+        :setSize(13, 1) 
+        :setBackground(colours.green) 
+
+        :onClick(function()
+            if callback then
+                callback(true)
+            end
+            payment_confirmation_frame:destroy()
+        end)
+
+    payment_confirmation_frame:addButton()
+        :setText("Deny") 
+        :setPosition(14, 6) 
+        :setSize(13, 1) 
+        :setBackground(colours.red) 
+
+        :onClick(function()
+
+            if callback then
+                callback(false)
+            end
+
+            payment_confirmation_frame:destroy()
+        end)
+        sleep(0.01)
+end
+
+local function payment_listener()
+    local modem = peripheral.find("modem")
+    local lchannel = tonumber(os.getComputerID() .. 43)
+    modem.open(lchannel)
+    while true do
+
+        local event, side, channel, replyChannel, message, distance
+        repeat
+        event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
+        until channel == lchannel
+
+        local payload = textutils.unserialiseJSON(message)
+        if payload.type == "confirmTransaction" then
+            show_payment_confirmation(payload.amount, payload.vendor,function(bruh)
+                if bruh then
+
+                    local confirmation_payload = {
+                        type = "transactionConfirmation",
+                        transaction_id = payload.transaction_id,
+                        confirmed = true
+                    }
+
+                    modem.transmit(replyChannel,channel,textutils.serialiseJSON(confirmation_payload))
+
+                else
+
+                    local confirmation_payload = {
+                        type = "transactionConfirmation",
+                        transaction_id = payload.transaction_id,
+                        confirmed = false
+                    }
+
+                    modem.transmit(replyChannel,channel,textutils.serialiseJSON(confirmation_payload))
+
+                end
+            end)
+
+        end
+
+    end
+
+end
+
+local function populate_homescreen_buttons()
+
+    homescreen:clear()
+
+    local button_width = 8
+    local button_height = 3
+    local button_spacing_x = 3
+    local button_spacing_y = 2
+    local current_x = button_spacing_x
+    local current_y = button_spacing_y
+
+    local app_files = fs.list("/apps/")
+
+    for i = 1, #app_files do
+        local filename = app_files[i]
+
+        local display_name = filename:gsub(".lua$", "")
+
+        if current_x + button_width > homescreen:getWidth() then
+            current_x = button_spacing_x 
+            current_y = current_y + button_height + button_spacing_y 
+        end
+
+        if current_y + button_height > homescreen:getHeight() then
+            break
+        end
+        
+        local app_button = homescreen:addButton()
+            :setText(display_name) 
+            :setPosition(current_x, current_y)
+            :setSize(button_width, button_height)
+            :setBackground(colours.grey)
+            :setForeground(colours.white)
+            :onClick(function()
+
+                if current_active_frame then
+                    current_active_frame:setVisible(false)
+                end
+
+                local app_frame = active_app_frames[filename]
+                if not app_frame then
+
+                    app_frame = main:addFrame()
+                        :setPosition(1, 1) 
+                        :setSize(FRAME_WIDTH, FRAME_HEIGHT)
+                        :setBackground(colours.green) 
+                        :setVisible(false) 
+
+                    app_frame:addProgram()
+                        :setSize(FRAME_WIDTH, FRAME_HEIGHT)
+                        :execute("/apps/" .. filename)
+
+                    active_app_frames[filename] = app_frame
+                end
+
+                app_frame:setVisible(true)
+                current_active_frame = app_frame
+            end)
+
+        current_x = current_x + button_width + button_spacing_x
+    end
+end
+
+local function switch_to_frame(target_frame, frame_name)
+    if current_active_frame then
+        current_active_frame:setVisible(false)
+    end
+    target_frame:setVisible(true)
+    current_active_frame = target_frame
+end
+
+local function populate_app_switcher_ui()
+    app_switcher_frame:clear() 
+
+    app_switcher_frame:addLabel()
+        :setText("Active Applications")
+        :setPosition(5, 1)
+        :setSize(FRAME_WIDTH - 2, 1)
+        :setForeground(colours.white)
+        :setBackground(colours.blue)
+
+    local current_y = 3 
+
+    app_switcher_frame:addButton()
+        :setText("Home Screen")
+        :setPosition(2, current_y)
+        :setSize(FRAME_WIDTH - 3, 1)
+        :setBackground(homescreen == current_active_frame and colours.lightGrey or colours.grey) 
+        :setForeground(colours.white)
+        :onClick(function()
+            switch_to_frame(homescreen, "Home Screen")
+            app_switcher_frame:setVisible(false) 
+        end)
+    current_y = current_y + 2
+
+    for filename, app_frame in pairs(active_app_frames) do
+
+        local display_name = filename:gsub(".lua$", "")
+
+        if current_y + 1 > app_switcher_frame:getHeight() - 2 then 
+            app_switcher_frame:addLabel()
+                :setText("...more apps below...")
+                :setPosition(1, current_y)
+                :setSize(FRAME_WIDTH - 2, 1)
+                :setForeground(colours.orange)
+                :setBackground(colours.black)
+            break
+        end
+
+        app_switcher_frame:addButton()
+            :setText(display_name) 
+            :setPosition(2, current_y)
+            :setSize(FRAME_WIDTH - 8, 1) 
+            :setBackground(app_frame == current_active_frame and colours.lightGrey or colours.grey) 
+            :setForeground(colours.white)
+            :onClick(function()
+                switch_to_frame(app_frame, filename)
+                app_switcher_frame:setVisible(false) 
+            end)
+
+        app_switcher_frame:addButton()
+            :setText("X")
+            :setPosition(FRAME_WIDTH - 6, current_y)
+            :setSize(5, 1)
+            :setBackground(colours.red)
+            :setForeground(colours.white)
+            :onClick(function()
+
+                if app_frame then
+                    app_frame:destroy()
+                end
+                active_app_frames[filename] = nil 
+
+                if current_active_frame == app_frame then
+                    switch_to_frame(homescreen, "Home Screen (after close)")
+                end
+
+                populate_app_switcher_ui()
+            end)
+        current_y = current_y + 2
+    end
+end
+
+populate_homescreen_buttons()
+
+main:addButton()
+    :setText("Home")
+    :setPosition(0, CONTROL_BUTTON_Y)
+    :setSize(14, 1)
+    :setBackground(colours.black)
+    :setForeground(colours.white)
+    :onClick(function()
+
+        if current_active_frame ~= homescreen or app_switcher_frame.visible == true then
+            app_switcher_frame:setVisible(false) 
+            switch_to_frame(homescreen, "Home Screen")
+        end
+    end)
+
+main:addButton()
+    :setText("Switch")
+    :setPosition(14, CONTROL_BUTTON_Y)
+    :setSize(13, 1)
+    :setBackground(colours.red)
+    :setForeground(colours.white)
+    :onClick(function()
+
+        if current_active_frame then
+            current_active_frame:setVisible(false)
+        end
+        populate_app_switcher_ui() 
+        app_switcher_frame:setVisible(true)
+    end)
+
+parallel.waitForAny(basalt.run,payment_listener)
\ No newline at end of file