Timers interfere with each other because of shared pauseOffset

I recently started reusing a couple of timers for UI animations, and noticed that they started breaking in strange ways. I peeked inside the CoreLibs and found the following:

When calling :pause() on any timer, it sets the pauseOffset for every timer, and no combination of :reset() or :start() restores this. This can cause timers to complete immediately (and skip over the entire UI animation in a single frame), including for example the timerX and timerY used in GridView.

I managed to fix this issue by changing the pauseOffset into an instance property, and setting it back to 0 when calling :reset(). Included a diff below for reference.

(btw this doesn't seem to be a recent change, traced it back to SDK 2.4.2 at least)

CoreLibs/timer.lua

--- CoreLibs/timer.lua      2025-05-22 00:22:32
+++ CoreLibs/timer-fix.lua  2025-05-25 16:16:41
@@ -86,6 +86,7 @@
        o._endValue = endValue or 0
 
        o._currentTime = 0
+       o._pauseOffset = 0
        o.value = o._startValue
        o.active = true
        o.delay = 0
@@ -203,22 +204,19 @@
        return playdate.timer.keyRepeatTimerWithDelay(300, 100, func, ...)
 end
 
-
-local pauseOffset = 0
-
 function playdate.timer:pause()
        self.paused = true
        if self._lastTime ~= nil and self.active == true then
-               pauseOffset = playdate.getCurrentTimeMilliseconds() - self._lastTime
+               self._pauseOffset = playdate.getCurrentTimeMilliseconds() - self._lastTime
        else
-               pauseOffset = 0
+               self._pauseOffset = 0
        end
 end
 
 
 function playdate.timer:start()
        self.paused = false
-       self._lastTime = playdate.getCurrentTimeMilliseconds() - pauseOffset
+       self._lastTime = playdate.getCurrentTimeMilliseconds() - self._pauseOffset
 end
 
 function playdate.timer:reset()
@@ -226,6 +224,7 @@
        self._endValue = self.originalValues.endValue
        self._easingFunction = self.originalValues.easingFunction
        self._currentTime = 0
+       self._pauseOffset = 0
        self._lastTime = nil
        self.active = true
        self.hasReversed = false
1 Like