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)