Newer
Older
Kristify / src / frontend.lua
local ctx = ({ ... })[1]
local storage = ctx.storage
local speaker = ctx.speakerLib
local basalt = ctx.basalt

-- Button functions
local base
local function smartLoadLayout(frame, path)
    local pathLUA = fs.combine(ctx.path.page, path..".lua")
    local pathXML = fs.combine(ctx.path.page, path..".xml")
    if fs.exists(pathLUA) then
        local file = fs.open(pathLUA, "r")
        local data = file.readAll()
        file.close()
        local func,err = load(data, path, "bt", _ENV)
        if not func then
            ctx.logger:error("Could not load layout \'data/"..path..".lua\'! ("..err..")")
            return
        end
        local success,obj = pcall(func,ctx,frame)
        if not success then
            ctx.logger:error(obj)
            return
        end
        frame:addObject(obj)
    elseif fs.exists(pathXML) then
        frame:addLayout(pathXML)
    else
        ctx.logger:error("Layout \'data/"..path.."\' does not exist!")
    end
    return frame
end

-- Create frame
ctx.logger:debug("Attatching monitor and loading layout.")
base = basalt.createFrame()
local mon = peripheral.wrap(ctx.config.monSide)
mon.setTextScale(ctx.config.monScale or 0.5)

base:setMonitor(ctx.config.monSide)
    :setTheme(ctx.theme)
smartLoadLayout(base, "index")

-- Catalog refresh
local tItems = {}
local page = 1
local function updateCatalog()
    local body = base:getDeepObject("_body")
    local nParW,nParH = body:getSize()
    -- Clear
    local obj = body:getObject("_widget_1")
    local i=1
    repeat
        if obj then
            body:removeObject(obj)
        end
        obj = body:getObject("_widget_"..i)
        i = i+1
    until obj == nil

    basalt.drawFrames()

    -- Refill
    local nScreenX, nScreenY = 1,1
    for i,item in ipairs(tItems) do
        -- Load widget template
        smartLoadLayout(body, "widget")
        local widget = base:getDeepObject("_widget")
        widget.name = (widget.name).."_"..i

        local nW,nH = widget:getSize()

        local function fill(name,value)
            value = tostring(value)
            local obj = widget:getDeepObject(name)
            if not obj then return end
            obj:setValue(value)

            local nX,_ = obj:getPosition()
            value = tostring(obj:getValue())
            if #value+nX+1 >= nW then
                widget:setSize(#value+nX+1, nH)
                nW,nH = #value+nX+1, nH
            end

            return obj
        end

        -- Fill data
        local name = fill("_name",item.displayName)
        fill("_stock",item.amount)
        fill("_metaname",item.metaname)

        -- Name color
        if type(item.color) == "string" then
            name:setForeground(colors[item.color])
        end

        -- Price
        local button = widget:getDeepObject("_price")
        local _, h = button:getSize()
        local btnLabel = item.price .. "kst"
        button
            :setText(btnLabel)
            :setSize(#btnLabel + 2, h)

        -- Frame clicking
        widget:onClick(function()
            local info = base:getDeepObject("_importantMSG")
            if info then
                info:setText("Pay to "..item.metaname.."@"..ctx.config.name..".kst for a purchase!")
                speaker:play("click")
            end
        end)

        widget:setPosition(nScreenX,nScreenY)
        -- Next Position
        nScreenX = nScreenX+nW
        if nScreenX > nParW then
            nScreenY = nScreenY+nH
            nScreenX = 1+nW
            widget:setPosition(1,nScreenY)
        end
    end
end

--Button events
basalt.setVariable("navBack", function()
    local body = base:getDeepObject("_body")
    if page > 1 then
        speaker:play("click")
        local _,nH = body:getSize()
        local _,nY = body:getOffset()
        body:setOffset(0,nY-nH+1)
        page = page-1
        lblPage = base:getDeepObject("_curPage")
        if lblPage then
            lblPage:setText(""..page)
        end
    end
end)
basalt.setVariable("navNext", function()
    local body = base:getDeepObject("_body")
    local nMax = body:getScrollAmount()
    local _,nH = body:getSize()
    local _,nY = body:getOffset()

    if nY > nMax then return end
    speaker:play("click")
    body:setOffset(0,nY+nH-1)
    page = page+1
    lblPage = base:getDeepObject("_curPage")
    if lblPage then
        lblPage:setText(""..page)
    end
end)

-- Adjust theme
ctx.logger:debug("Adjust theme by config file")
local title = base:getDeepObject("_title")
local factor = 1
local nW,nX = 51,20
if title then
    factor = title:getFontSize()
    title:setText(ctx.config.name)
    nW = title:getSize()
    nX = title:getPosition()
    basalt.drawFrames()
end

local titleEnd = base:getDeepObject("_title_end")
if titleEnd then
    local _, nY = titleEnd:getPosition()
    titleEnd:setPosition(nX + (math.floor(nW)*factor*1.5), nY)
end

local watermark = base:getDeepObject("_watermark")
if watermark then
    watermark:setText("Kristify")
end

local helpBtn = base:getDeepObject("_helpButton")
if helpBtn then
    helpBtn:setText("?")
end

local page = base:getDeepObject("_curPage")
if page then
    page:setText("1")
end

local msg = base:getDeepObject("_importantMSG")
if msg then
    msg:setText("Pay to <metaname>@"..ctx.config.name..".kst for a purchase!")
end

local subtitle = base:getDeepObject("_subtitle")
if subtitle then
    base:addThread("_moveSubtitle")
        :start(function()
            local nW = subtitle:getSize()
            if #ctx.config.tagline <= nW then
                subtitle:setText(ctx.config.tagline)
                return
            end

            local i, cooldown = 1, 7
            while true do
                if cooldown <= 0 then
                    i = i + 1
                    if i > (#ctx.config.tagline) + 5 then
                        i = 1
                        cooldown = 7
                    end
                else
                    cooldown = cooldown - 1
                end
                subtitle:setText(ctx.config.tagline:sub(i))
                sleep(0.2)
            end
        end
    )
end
os.queueEvent("kristify:IndexLoaded")

-- Event
basalt.onEvent(function(event)
    if event == "kstUpdateProducts" then
        ctx.logger:debug("Received event: kstUpdateProducts; Refresh cache")
        storage.refreshStorage(true)
        os.queueEvent("kristify:storageRefreshed")
        -- Sort
        tItems = {}
        for _, item in ipairs(ctx.products) do
            local amount = storage.getCount(item.id, item.nbt)
            if amount ~= 0 then
                local newItem = {
                    amount = amount
                }
                for k, v in pairs(item) do
                    newItem[k] = v
                end
                tItems[#tItems + 1] = newItem
            end
        end
        table.sort(tItems, function(a, b)
            return a.amount > b.amount
        end)

        updateCatalog()
        os.queueEvent("kristify:CatalogUpdated")
    end
end)

os.queueEvent("kstUpdateProducts")
basalt.autoUpdate(base)