local deviceinfo = computer.getDeviceInfo() local function getBestGPUOrScreenAddress(componentType) --функцию подарил игорь тимофеев local bestWidth, bestAddress = 0 for address in component.list(componentType) do local width = tonumber(deviceinfo[address].width) if component.type(componentType) == "screen" then if #component.invoke(address, "getKeyboards") > 0 then --экраны с кравиатурами имеют больший приоритет width = width + 10 end end if width > bestWidth then bestAddress, bestWidth = address, width end end return bestAddress end local gpu = component.proxy((computer.getBootGpu and computer.getBootGpu() or getBestGPUOrScreenAddress("gpu")) or error("no gpu found", 0)) local screen = (computer.getBootScreen and computer.getBootScreen() or getBestGPUOrScreenAddress("screen")) or error("no screen found", 0) gpu.bind(screen) local keyboards = component.invoke(screen, "getKeyboards") local rx, ry = gpu.getResolution() local depth = gpu.getDepth() local drive = component.proxy(computer.getBootAddress()) local internet = component.proxy(component.list("internet")() or "") local installerVersion = "AmijaOS Setup" ------------------------------------ local function segments(path) local parts = {} for part in path:gmatch("[^\\/]+") do local current, up = part:find("^%.?%.$") if current then if up == 2 then table.remove(parts) end else table.insert(parts, part) end end return parts end local function canonical(path) local result = table.concat(segments(path), "/") if unicode.sub(path, 1, 1) == "/" then return "/" .. result else return result end end local function fs_path(path) local parts = segments(path) local result = table.concat(parts, "/", 1, #parts - 1) .. "/" if unicode.sub(path, 1, 1) == "/" and unicode.sub(result, 1, 1) ~= "/" then return canonical("/" .. result) else return canonical(result) end end local function fs_concat(...) local set = table.pack(...) for index, value in ipairs(set) do checkArg(index, value, "string") end return canonical(table.concat(set, "/")) end local function cloneTo(folder, targetPath, targetDrive) for _, lpath in ipairs(drive.list(folder) or {}) do local full_path = fs_concat(folder, lpath) local target_path = fs_concat(targetPath, lpath) if drive.isDirectory(full_path) then cloneTo(full_path, target_path, targetDrive) else local file = drive.open(full_path, "rb") local buffer = "" repeat local data = drive.read(file, math.huge) buffer = buffer .. (data or "") until not data drive.close(file) targetDrive.makeDirectory(fs_path(target_path)) local file = targetDrive.open(target_path, "wb") targetDrive.write(file, buffer) targetDrive.close(file) end end end ------------------------------------ local function isValideKeyboard(address) for i, v in ipairs(keyboards) do if v == address then return true end end end local function getInternetFile(url) local handle, data, result, reason = internet.request(url), "" if handle then while true do result, reason = handle.read(math.huge) if result then data = data .. result else handle.close() if reason then return nil, reason else return data end end end else return nil, "unvalid address" end end local function split(str, sep) local parts, count, i = {}, 1, 1 while 1 do if i > #str then break end local char = str:sub(i, i - 1 + #sep) if not parts[count] then parts[count] = "" end if char == sep then count = count + 1 i = i + #sep else parts[count] = parts[count] .. str:sub(i, i) i = i + 1 end end if str:sub(#str - (#sep - 1), #str) == sep then table.insert(parts, "") end return parts end ------------------------------------ local function invert() gpu.setBackground(gpu.setForeground(gpu.getBackground())) end local function setText(str, posX, posY) gpu.set((posX or 0) + math.floor(rx / 2 - ((#str - 1) / 2) + .5), posY or math.floor(ry / 2 + .5), str) end local function clear() gpu.setBackground(0) gpu.setForeground(-1) gpu.fill(1, 1, rx, ry, " ") end local function menu(label, strs, selected) local selected = selected or 1 local function redraw() clear() invert() setText(label, nil, 1) invert() for i, v in ipairs(strs) do if selected == i then invert() end setText(v, nil, i + 1) if selected == i then invert() end end end redraw() while true do local eventData = {computer.pullSignal()} if isValideKeyboard(eventData[2] or "") then if eventData[1] == "key_down" then if eventData[4] == 208 then if selected < #strs then selected = selected + 1 redraw() end elseif eventData[4] == 200 then if selected > 1 then selected = selected - 1 redraw() end elseif eventData[4] == 28 then return selected end end end end end local function status(text) clear() setText(text) end ------------------------------------ local function getInstallDisk() local strs = {} local addresses = {} for address in component.list("filesystem") do if not component.invoke(address, "isReadOnly") and address ~= drive.address and address ~= computer.tmpAddress() then table.insert(strs, address:sub(1, 4) .. ":" .. (component.invoke(address, "getLabel") or "noLabel")) table.insert(addresses, address) end end table.insert(strs, "back") return component.proxy(addresses[menu("select disk", strs, 1)] or "") end local function selectDist(dists) local strs = {} local funcs = {} for i, v in ipairs(dists) do table.insert(strs, v.name) table.insert(funcs, v.call) end table.insert(strs, "back") local num while true do num = menu("select distribution", strs, num) if funcs[num] then local proxy = getInstallDisk() if proxy then if menu("comfirm? the disk will be cleared!", {"NO", "Yes"}) == 2 then status("Please Wait") proxy.remove("/") local label = strs[num] if label == "AmijaOS" then label = "AmijaOS HDD" end proxy.setLabel(label) funcs[num](proxy) if computer.setBootAddress then computer.setBootAddress(proxy.address) end if computer.setBootFile then computer.setBootFile("/init.lua") end computer.shutdown("fast") end end else break end end end local function offline() local dists = {} for i, v in ipairs(drive.list("/distributions") or {}) do table.insert(dists, {name = v:sub(1, #v - 1), call = function(proxy) cloneTo("/core", "/", proxy) cloneTo("/distributions/" .. v, "/", proxy) end}) end table.insert(dists, {name = "core only", call = function(proxy) cloneTo("/core", "/", proxy) end}) selectDist(dists) end local function download(url, targetDrive) local filelist = split(assert(getInternetFile(url .. "/Setup/list.txt")), "\n") for i, path in ipairs(filelist) do if path ~= "" then local full_url = url .. path local data = assert(getInternetFile(full_url)) targetDrive.makeDirectory(fs_path(path)) local file = targetDrive.open(path, "wb") targetDrive.write(file, data) targetDrive.close(file) end end end local function online() local dists = {} --[[ local filelist = split(assert(getInternetFile("https://raw.githubusercontent.com/matvey-mayner/AmijaOS/main/Setup/list.txt")), "\n") for i, v in ipairs(filelist) do if v ~= "" then local url, name = table.unpack(split(v, ";")) table.insert(dists, {name = name, call = function(proxy) download("https://raw.githubusercontent.com/matvey-mayner/AmijaOS/main", proxy) download(url, proxy) end}) end end ]] table.insert(dists, {name = "AmijaOS", call = function(proxy) download("https://raw.githubusercontent.com/matvey-mayner/AmijaOS/main", proxy) end}) table.insert(dists, {name = "AmijaOS-InDev", call = function(proxy) download("https://raw.githubusercontent.com/matvey-mayner/AmijaOS/indev", proxy) end}) selectDist(dists) end local strs = {"shutdown"} local funcs = {computer.shutdown} if internet then table.insert(strs, 1, "online mode") table.insert(funcs, 1, online) end if drive.exists("/core") then table.insert(strs, 1, "offline mode") table.insert(funcs, 1, offline) end local num while true do num = menu(installerVersion, strs, num) funcs[num]() end