Refactor animation goal settings to use instant transitions

- Replaced `Flipper.Spring` with `Flipper.Instant` for setting animation goals across multiple components, including `Page`, `Checkbox`, `Dropdown`, `IconButton`, `TextButton`, `TextInput`, `TouchRipple`, and `Notification`.
- This change simplifies the animation logic, providing immediate transitions without spring dynamics, enhancing performance and responsiveness.

These updates improve the user experience by ensuring quicker visual feedback during state changes.
This commit is contained in:
Joe 2026-02-18 02:20:23 -06:00
parent fe5852f958
commit 201b971101
10 changed files with 154 additions and 115 deletions

View file

@ -23,10 +23,7 @@ end
function Checkbox:didUpdate(lastProps)
if lastProps.active ~= self.props.active then
self.motor:setGoal(Flipper.Spring.new(self.props.active and 1 or 0, {
frequency = 6,
dampingRatio = 1.1,
}))
self.motor:setGoal(Flipper.Instant.new(self.props.active and 1 or 0))
end
end

View file

@ -36,10 +36,7 @@ function Dropdown:didUpdate(prevProps)
})
end
self.openMotor:setGoal(Flipper.Spring.new(self.state.open and 1 or 0, {
frequency = 6,
dampingRatio = 1.1,
}))
self.openMotor:setGoal(Flipper.Instant.new(self.state.open and 1 or 0))
end
function Dropdown:render()

View file

@ -8,11 +8,6 @@ local Flipper = require(Packages.Flipper)
local Assets = require(Plugin.Assets)
local bindingUtil = require(Plugin.App.bindingUtil)
local HOVER_SPRING_PROPS = {
frequency = 5,
dampingRatio = 1.1,
}
local e = Roact.createElement
local IconButton = Roact.Component:extend("IconButton")
@ -38,11 +33,11 @@ function IconButton:render()
[Roact.Event.Activated] = self.props.onClick,
[Roact.Event.MouseEnter] = function()
self.motor:setGoal(Flipper.Spring.new(1, HOVER_SPRING_PROPS))
self.motor:setGoal(Flipper.Instant.new(1))
end,
[Roact.Event.MouseLeave] = function()
self.motor:setGoal(Flipper.Spring.new(0, HOVER_SPRING_PROPS))
self.motor:setGoal(Flipper.Instant.new(0))
end,
}, {
Icon = e("ImageLabel", {

View file

@ -40,17 +40,11 @@ function Notification:dismiss()
end
self.dismissed = true
self.motor:setGoal(Flipper.Spring.new(0, {
frequency = 5,
dampingRatio = 1,
}))
self.motor:setGoal(Flipper.Instant.new(0))
end
function Notification:didMount()
self.motor:setGoal(Flipper.Spring.new(1, {
frequency = 3,
dampingRatio = 1,
}))
self.motor:setGoal(Flipper.Instant.new(1))
self.props.soundPlayer:play(Assets.Sounds.Notification)

View file

@ -433,10 +433,7 @@ function DomLabel:didUpdate(prevProps)
then
-- Close the expansion when the domlabel is changed to a different thing
self.expanded = false
self.motor:setGoal(Flipper.Spring.new(24, {
frequency = 5,
dampingRatio = 1,
}))
self.motor:setGoal(Flipper.Instant.new(24))
end
end
@ -541,71 +538,50 @@ function DomLabel:render()
SelectionService:Set({ props.instance })
end
else
-- Single click expands the changes (after a delay to check for double click)
task.delay(0.3, function()
-- Guard against unmounted component or stale click
if not self.isMounted then
-- Removed script: show diff of old source vs empty
if
props.patchType == "Remove"
and props.instance
and props.changeInfo
and props.changeInfo.linesRemoved
and props.showStringDiff
then
local ok, source = pcall(function()
return (props.instance :: any).Source
end)
if ok and type(source) == "string" then
props.showStringDiff(source, "", props.instancePath)
return
end
end
if os.clock() - (self.lastDoubleClickTime or 0) <= 0.35 then
-- This was a double click, so don't expand
return
end
-- Use self.props to get current props, not stale closure
local p = self.props
-- Removed script: show diff of old source vs empty
if
p.patchType == "Remove"
and p.instance
and p.changeInfo
and p.changeInfo.linesRemoved
and p.showStringDiff
then
local ok, source = pcall(function()
return (p.instance :: any).Source
end)
if ok and type(source) == "string" then
p.showStringDiff(source, "", p.instancePath)
-- Added script: find Source in changeList and show diff of empty vs new source
if
props.patchType == "Add"
and props.changeList
and props.changeInfo
and props.changeInfo.linesAdded
and props.showStringDiff
then
for _, entry in props.changeList do
if entry[1] == "Source" and type(entry[3]) == "string" then
props.showStringDiff("", tostring(entry[3]), props.instancePath)
return
end
end
end
-- Added script: find Source in changeList and show diff of empty vs new source
if
p.patchType == "Add"
and p.changeList
and p.changeInfo
and p.changeInfo.linesAdded
and p.showStringDiff
then
for _, entry in p.changeList do
if entry[1] == "Source" and type(entry[3]) == "string" then
p.showStringDiff("", tostring(entry[3]), p.instancePath)
return
end
end
if props.changeList then
local cl = props.changeList
if #cl == 2 and cl[2][1] == "Source" and props.showStringDiff then
props.showStringDiff(tostring(cl[2][2]), tostring(cl[2][3]), props.instancePath)
else
self.expanded = not self.expanded
local goalHeight = 24
+ (if self.expanded then math.clamp(#props.changeList * 24, 24, 24 * 6) else 0)
self.motor:setGoal(Flipper.Instant.new(goalHeight))
end
if p.changeList then
-- If the only change is Source, open the diff viewer directly
-- changeList[1] is the header, changeList[2+] are entries
local cl = p.changeList
if #cl == 2 and cl[2][1] == "Source" and p.showStringDiff then
p.showStringDiff(tostring(cl[2][2]), tostring(cl[2][3]), p.instancePath)
else
self.expanded = not self.expanded
local goalHeight = 24
+ (if self.expanded then math.clamp(#p.changeList * 24, 24, 24 * 6) else 0)
self.motor:setGoal(Flipper.Spring.new(goalHeight, {
frequency = 5,
dampingRatio = 1,
}))
end
end
end)
end
end
end,
}),

View file

@ -13,11 +13,6 @@ local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
local SlicedImage = require(script.Parent.SlicedImage)
local TouchRipple = require(script.Parent.TouchRipple)
local SPRING_PROPS = {
frequency = 5,
dampingRatio = 1,
}
local e = Roact.createElement
local TextButton = Roact.Component:extend("TextButton")
@ -33,7 +28,7 @@ end
function TextButton:didUpdate(lastProps)
if lastProps.enabled ~= self.props.enabled then
self.motor:setGoal({
enabled = Flipper.Spring.new(self.props.enabled and 1 or 0),
enabled = Flipper.Instant.new(self.props.enabled and 1 or 0),
})
end
end
@ -61,13 +56,13 @@ function TextButton:render()
[Roact.Event.MouseEnter] = function()
self.motor:setGoal({
hover = Flipper.Spring.new(1, SPRING_PROPS),
hover = Flipper.Instant.new(1),
})
end,
[Roact.Event.MouseLeave] = function()
self.motor:setGoal({
hover = Flipper.Spring.new(0, SPRING_PROPS),
hover = Flipper.Instant.new(0),
})
end,
}, {

View file

@ -11,11 +11,6 @@ local bindingUtil = require(Plugin.App.bindingUtil)
local SlicedImage = require(script.Parent.SlicedImage)
local SPRING_PROPS = {
frequency = 5,
dampingRatio = 1,
}
local e = Roact.createElement
local TextInput = Roact.Component:extend("TextInput")
@ -31,7 +26,7 @@ end
function TextInput:didUpdate(lastProps)
if lastProps.enabled ~= self.props.enabled then
self.motor:setGoal({
enabled = Flipper.Spring.new(self.props.enabled and 1 or 0),
enabled = Flipper.Instant.new(self.props.enabled and 1 or 0),
})
end
end
@ -98,13 +93,13 @@ function TextInput:render()
[Roact.Event.MouseEnter] = function()
self.motor:setGoal({
hover = Flipper.Spring.new(1, SPRING_PROPS),
hover = Flipper.Instant.new(1),
})
end,
[Roact.Event.MouseLeave] = function()
self.motor:setGoal({
hover = Flipper.Spring.new(0, SPRING_PROPS),
hover = Flipper.Instant.new(0),
})
end,

View file

@ -8,11 +8,6 @@ local Flipper = require(Packages.Flipper)
local Assets = require(Plugin.Assets)
local bindingUtil = require(Plugin.App.bindingUtil)
local EXPAND_SPRING = {
frequency = 7,
dampingRatio = 2,
}
local TouchRipple = Roact.Component:extend("TouchRipple")
function TouchRipple:init()
@ -81,8 +76,8 @@ function TouchRipple:render()
self.setPosition(relativePosition)
self.motor:setGoal({
scale = Flipper.Spring.new(1, EXPAND_SPRING),
opacity = Flipper.Spring.new(1, EXPAND_SPRING),
scale = Flipper.Instant.new(1),
opacity = Flipper.Instant.new(1),
})
input:GetPropertyChangedSignal("UserInputState"):Connect(function()
@ -90,10 +85,7 @@ function TouchRipple:render()
if userInputState == Enum.UserInputState.Cancel or userInputState == Enum.UserInputState.End then
self.motor:setGoal({
opacity = Flipper.Spring.new(0, {
frequency = 5,
dampingRatio = 1,
}),
opacity = Flipper.Instant.new(0),
})
end
end)

View file

@ -62,10 +62,7 @@ end
function Page:didUpdate(lastProps)
if self.props.active ~= lastProps.active then
self.motor:setGoal(Flipper.Spring.new(self.props.active and 1 or 0, {
frequency = 6,
dampingRatio = 1,
}))
self.motor:setGoal(Flipper.Instant.new(self.props.active and 1 or 0))
end
end