View difference between Paste ID: Wb3KRA0D and 82tB9VPi
SHOW: | | - or go back to the newest paste.
1
-- LemonOS: Pocket Shell for Lemonphone
2
-- by ChatGPT (GPT-5)
3
-- Features: Persistent settings, live clock, signal bars, auto-netchat install, firmware info
4
5
local CONFIG_PATH = "/lemonos.cfg"
6
local NETCHAT_PATH = "/netchat"
7
local STARTUP_PATH = "/startup.lua"
8
9
-- Firmware info
10
local firmware = {
11
    device = "Lemonphone Pocket Computer",
12
    version = "LemonOS v1.0.0",
13
}
14
15
local config = {
16
    username = "User",
17
    accentColor = colors.yellow,
18
    bgColor = colors.black,
19
    rednetSide = "back",
20
}
21
22
-- === CONFIG LOAD/SAVE ===
23
local function saveConfig()
24
    local file = fs.open(CONFIG_PATH, "w")
25
    if file then
26
        file.write(textutils.serialize(config))
27
        file.close()
28
    end
29
end
30
31
local function loadConfig()
32
    if fs.exists(CONFIG_PATH) then
33
        local file = fs.open(CONFIG_PATH, "r")
34
        if file then
35
            local data = file.readAll()
36
            file.close()
37
            local ok, tbl = pcall(textutils.unserialize, data)
38
            if ok and type(tbl) == "table" then
39
                for k, v in pairs(tbl) do
40
                    config[k] = v
41
                end
42
            end
43
        end
44
    end
45
end
46
loadConfig()
47
48
-- === AUTO DOWNLOAD NETCHAT ===
49
if not fs.exists(NETCHAT_PATH) then
50
    print("Downloading netchat...")
51
    if http then
52
        local success, response = pcall(http.get, "https://pastebin.com/raw/GwmGxjwy")
53
        if success and response then
54
            local content = response.readAll()
55
            response.close()
56
            local file = fs.open(NETCHAT_PATH, "w")
57
            file.write(content)
58
            file.close()
59
            print("netchat installed!")
60
        else
61
            print("Failed to download netchat.")
62
        end
63
    else
64
        print("HTTP API not enabled, cannot download netchat.")
65
    end
66
    -- Set startup to shell.run("firm.lpsw")
67
    local file = fs.open(STARTUP_PATH, "w")
68
    file.write('shell.run("firm.lpsw")')
69
    file.close()
70
end
71
72
-- === INITIALIZE REDNET ===
73
if peripheral.find("modem") then
74
    rednet.open(config.rednetSide)
75
else
76
    rednet.close(config.rednetSide)
77
end
78
79
-- === UTILITIES ===
80
local function centerText(y, text, color)
81
    local w = term.getSize()
82
    local x = math.floor((w - #text) / 2)
83
    term.setCursorPos(x, y)
84
    if color then term.setTextColor(color) end
85
    term.write(text)
86
    term.setTextColor(colors.white)
87
end
88
89
local function getSignalStrength()
90
    if not rednet.isOpen(config.rednetSide) then return 0 end
91
    local peers = { rednet.lookup("lemonphone_ping") }
92
    if #peers == 0 then
93
        return 1
94
    elseif #peers < 3 then
95
        return 2
96
    else
97
        return 3
98
    end
99
end
100
101
local function drawSignalBars(strength)
102
    local barChar = "|"
103
    local maxBars = 3
104
    for i = 1, maxBars do
105
        if i <= strength then
106
            term.setTextColor(colors.lime)
107
        else
108
            term.setTextColor(colors.gray)
109
        end
110
        term.write(barChar)
111
    end
112
    term.setTextColor(colors.white)
113
end
114
115
local function drawTopBar()
116
    local w = term.getSize()
117
    term.setCursorPos(1, 1)
118
    term.setBackgroundColor(config.accentColor)
119
    term.clearLine()
120
121
    -- Left: signal strength
122
    term.setCursorPos(2, 1)
123
    if rednet.isOpen(config.rednetSide) then
124
        drawSignalBars(getSignalStrength())
125
        term.write(" Net")
126
    else
127
        term.setTextColor(colors.red)
128
        term.write("X NoNet")
129
        term.setTextColor(colors.white)
130
    end
131
132
    -- Right: time and date
133
    local timeStr = textutils.formatTime(os.time(), true)
134
    local dateStr = os.date("%b %d")
135
    local clock = timeStr .. " | " .. dateStr
136
    term.setCursorPos(w - #clock - 1, 1)
137
    term.setTextColor(colors.white)
138
    term.write(clock)
139
end
140
141
local function drawMenu(selected)
142
    local apps = {
143
        {name = "Messages", cmd = "netchat join"},
144
        {name = "Files", cmd = "shell"},
145
        {name = "Settings", cmd = "settings"},
146
        {name = "About Lemonphone", cmd = "about"},
147
        {name = "Reboot", cmd = "reboot"}
148
    }
149
150
    local _, h = term.getSize()
151
    local startY = 4
152
    term.setTextColor(colors.white)
153
    for i, app in ipairs(apps) do
154
        term.setCursorPos(4, startY + i - 1)
155
        if i == selected then
156
            term.setBackgroundColor(colors.gray)
157
            term.setTextColor(colors.black)
158
        else
159
            term.setBackgroundColor(config.bgColor)
160
            term.setTextColor(colors.white)
161
        end
162
        term.clearLine()
163
        term.setCursorPos(4, startY + i - 1)
164
        term.write(app.name)
165
    end
166
167
    term.setBackgroundColor(config.bgColor)
168
    return apps
169
end
170
171
-- === SETTINGS MENU ===
172
local function openSettings()
173
    while true do
174
        term.setBackgroundColor(config.bgColor)
175
        term.clear()
176
        centerText(3, "Settings", config.accentColor)
177
        term.setCursorPos(2, 5)
178
        term.write("1. Change Username")
179
        term.setCursorPos(2, 6)
180
        term.write("2. Change Accent Color")
181
        term.setCursorPos(2, 7)
182
        term.write("3. Back")
183
184
        local _, key = os.pullEvent("key")
185
        if key == keys.one then
186
            term.setCursorPos(2, 9)
187
            term.clearLine()
188
            term.write("Enter new username: ")
189
            config.username = read()
190
            saveConfig()
191
        elseif key == keys.two then
192
            term.setCursorPos(2, 9)
193
            term.clearLine()
194
            term.write("Color name (e.g. yellow): ")
195
            local colorName = read()
196
            if colors[colorName] then
197
                config.accentColor = colors[colorName]
198
                saveConfig()
199
            else
200
                term.setCursorPos(2, 10)
201
                term.write("Invalid color.")
202
                sleep(1)
203
            end
204
        elseif key == keys.three then
205
            return
206
        end
207
    end
208
end
209
210
-- === ABOUT LEMONPHONE ===
211
local function aboutLemonphone()
212
    term.setBackgroundColor(config.bgColor)
213
    term.clear()
214
    centerText(3, "About Lemonphone", config.accentColor)
215
    term.setCursorPos(2, 5)
216
    term.write("Device: " .. firmware.device)
217
    term.setCursorPos(2, 6)
218
    term.write("Firmware: " .. firmware.version)
219
    term.setCursorPos(2, 8)
220
    term.write("Press any key to return...")
221
    os.pullEvent("key")
222
end
223
224
-- === MAIN LOOP ===
225-
local selected = 1
225+
-- Pre-draw everything once
226
term.setBackgroundColor(config.bgColor)
227
term.clear()
228
drawTopBar()
229
centerText(3, config.username .. "'s Lemonphone", config.accentColor)
230
local apps = drawMenu(selected)
231
232-
    drawTopBar()
232+
233-
    centerText(3, config.username .. "'s Lemonphone", config.accentColor)
233+
234-
    local apps = drawMenu(selected)
234+
235
while true do
236
    local event, key = os.pullEvent()
237
    
238
    if event == "key" then
239
        local oldSelected = selected
240
        if key == keys.up then
241
            selected = math.max(1, selected - 1)
242
        elseif key == keys.down then
243
            selected = math.min(#apps, selected + 1)
244
        elseif key == keys.enter then
245
            local chosen = apps[selected]
246
            if chosen.name == "Settings" then
247
                openSettings()
248
            elseif chosen.name == "About Lemonphone" then
249-
                term.setBackgroundColor(config.bgColor)
249+
250-
                term.clear()
250+
251-
                term.setCursorPos(1, 1)
251+
252
                -- Redraw screen after returning from shell
253
                drawTopBar()
254
                centerText(3, config.username .. "'s Lemonphone", config.accentColor)
255
                drawMenu(selected)
256
            end
257
        end
258
259
        -- Only redraw selection highlight if it changed
260
        if oldSelected ~= selected then
261
            drawMenu(selected)
262
        end
263
264
    elseif event == "timer" then
265
        -- Only redraw top bar (time + signal)
266
        drawTopBar()
267
        timer = os.startTimer(refreshRate)
268
    end
269
end
270