From 960badacc52a71fb7bbd794e2a913fcb1b138414 Mon Sep 17 00:00:00 2001 From: Sabine Lim Date: Sun, 14 May 2023 03:12:46 +1000 Subject: [PATCH] Implement effects --- Basalt/plugins/xml.lua | 55 +++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/Basalt/plugins/xml.lua b/Basalt/plugins/xml.lua index 83500a1..fd77bfd 100644 --- a/Basalt/plugins/xml.lua +++ b/Basalt/plugins/xml.lua @@ -167,27 +167,56 @@ local function registerFunctionEvent(self, data, event, renderContext) end end -local potentialObservers = {} +local clearEffectDependencies = function(effect) + for _, dependency in ipairs(effect.dependencies) do + for index, backlink in ipairs(dependency) do + if (backlink == effect) then + table.remove(dependency, index) + end + end + end + effect.dependencies = {}; +end + +local effectStack = {} return { basalt = function() local object = { reactive = function(initialValue) - local internalValue = initialValue - local observers = {} + local value = initialValue + local observerEffects = {} local getter = function() - if (potentialObservers ~= nil) then - table.insert(observers, potentialObservers[#potentialObservers]) + local invokingEffect = effectStack[#effectStack] + if (invokingEffect ~= nil) then + table.insert(observerEffects, invokingEffect) + table.insert(invokingEffect.dependencies, observerEffects) end - return internalValue + return value end - local setter = function(value) - internalValue = value - for _, updateFn in ipairs(observers) do - updateFn(internalValue) + local setter = function(newValue) + value = newValue + local observerEffectsCopy = {} + for index, effect in ipairs(observerEffects) do + observerEffectsCopy[index] = effect + end + for _, effect in ipairs(observerEffectsCopy) do + effect.execute() end end return getter, setter + end, + + effect = function(effectFn) + local effect = {dependencies = {}} + local execute = function() + clearEffectDependencies(effect) + table.insert(effectStack, effect) + effectFn() + table.remove(effectStack) + end + effect.execute = execute + effect.execute() end } return object @@ -231,9 +260,7 @@ return { local value = load("return " .. expression, nil, "t", renderContext.env)() self:updateValue(prop, value) end - table.insert(potentialObservers, update) - update() - table.remove(potentialObservers) + basalt.effect(update) end self:updateSpecifiedValuesByXMLData(data, { @@ -345,7 +372,6 @@ return { loadLayout = function(self, path, props) if(fs.exists(path))then local renderContext = {} - renderContext.potentialObservers = {} renderContext.env = _ENV renderContext.env.props = props local f = fs.open(path, "r") @@ -475,6 +501,7 @@ return { Button = function(base, basalt) local object = { updateValue = function(self, name, value) + basalt.log("Updating value, " .. name .. " = " .. value) if (value == nil) then return end base.updateValue(self, name, value) if (name == "text") then