Skip to content

feat(scroll-list): smooth scrolling for inventory and crafting menus - #195

Draft
onlynyans wants to merge 3 commits into
doodlum:mainfrom
onlynyans:smooth-scroll-v2
Draft

onlynyans wants to merge 3 commits into
doodlum:mainfrom
onlynyans:smooth-scroll-v2

Conversation

@onlynyans

@onlynyans onlynyans commented May 7, 2026

Copy link
Copy Markdown

Implements momentum-based smooth scrolling across the SkyUI item-menu family (inventory, container, barter, gift, magic, crafting).

MCM exposes Smooth Scrolling (toggle) and Scroll Duration (50-500 ms) under the existing ItemList page.

Architecture:

  • ScrollingList.as: wheel handler, tween driver, mask + entriesContainer plumbing for sub-row visual offset.
  • ScrollTweener.as (new): velocity math, chain-count cadence
  • TabularList.as: registers configLoad / configUpdate listeners and reads the two MCM keys (enabled, durationMs) onto inherited fields. Inner-list instances (ItemList / CraftingItemList stage classes) inherit from TabularList, so they pick up the handling automatically -- no controller- level forwarder needed in InventoryLists / CraftingLists.
  • BasicListEntry.as: hit-test handlers walk up the display tree to find the owning list (entriesContainer nesting can put _parent on the container, not the list).
  • EntryClipManager.as: routes new entry clips into entriesContainer when the list provides one; falls back to the list itself otherwise.
  • swfsources.cmake: TabularList.as added to the components/list injection block for both craftingmenu and skyui_inventorylists

Summary by CodeRabbit

  • New Features

    • Optional smooth/momentum scrolling for inventory and menu lists
    • MCM options to enable smooth scrolling and set scroll duration
  • Improvements

    • Smoother visual scrolling and gliding between rows
    • More reliable item interaction and selection behavior during scrolling
    • Improved list rendering and responsiveness
  • Bug Fixes

    • Prevents momentum from being interrupted by scrollbar or mouse events

Review Change Stack

…crafting menus

Implements momentum-based smooth scrolling across the SkyUI item-menu family
(inventory, container, barter, gift, magic, crafting). Wheel ticks add velocity
to a list-level tweener; subsequent frames advance the visual scroll position
with friction-based decay. Two cadence modes:

  - Curve (default): chain-count tracking. Each rapid wheel tick within
    ACCEL_WINDOW_MS extends a chain; per-tick impulse multiplier grows along
    a quadratic curve up to CURVE_ACCEL_MAX_MULT. Spam-flicking the wheel
    "winds up" -- single tick = ~1 row, four rapid ticks = ~12 rows.
  - Classic: gap-based per-tick multiplier (same shape as the original draft).
    Each rapid tick scales by gap-since-last; doesn't compound across the chain.

MCM exposes Smooth Scrolling (toggle) and Scroll Duration (50-500 ms) under
the existing ItemList page.

Architecture:
  - ScrollingList.as: wheel handler, tween driver, mask + entriesContainer
    plumbing for sub-row visual offset.
  - ScrollTweener.as (new): velocity math, chain-count cadence, mode selector.
  - TabularList.as: registers configLoad / configUpdate listeners and reads
    the two MCM keys (enabled, durationMs) onto inherited fields. Inner-list
    instances (ItemList / CraftingItemList stage classes) inherit from
    TabularList, so they pick up the handling automatically -- no controller-
    level forwarder needed in InventoryLists / CraftingLists.
  - BasicListEntry.as: hit-test handlers walk up the display tree to find
    the owning list (entriesContainer nesting can put _parent on the
    container, not the list).
  - EntryClipManager.as: routes new entry clips into entriesContainer when
    the list provides one; falls back to the list itself otherwise.
  - swfsources.cmake: TabularList.as added to the components/list injection
    block for both craftingmenu and skyui_inventorylists, so the patches
    actually land in the deployed bytecode.
@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a velocity-based ScrollTweener and integrates momentum scrolling into ScrollingList, updates entry delegation/attachment, exposes runtime MCM controls and migration, and updates SWF build/exports.

Changes

Smooth Momentum Scrolling System

Layer / File(s) Summary
Momentum Engine
source/actionscript/Common/skyui/components/list/ScrollTweener.as
New ScrollTweener class implements velocity-based momentum with impulse chaining, exponential decay, tick/cancel, and settled detection.
List Entry Navigation
source/actionscript/Common/skyui/components/list/BasicListEntry.as
BasicListEntry resolves owning list by traversing parent chain before delegating rollover/press events.
Entry Clip Attachment
source/actionscript/Common/skyui/components/list/EntryClipManager.as
EntryClipManager now attaches new entry clips under the list's entriesContainer when available, falling back to the list itself.
ScrollingList Integration
source/actionscript/Common/skyui/components/list/ScrollingList.as
Adds smoothScrollEnabled/smoothScrollDuration, visual fractional scroll tracking, ScrollTweener integration, per-frame ticker, entriesContainer mask, momentum-aware rendering/input handling, and synchronization/cleanup.
TabularList Configuration
source/actionscript/Common/skyui/components/list/TabularList.as
Registers runtime config-update callback and centralizes smooth-scroll config application via applySmoothScrollConfig().
Game Configuration
source/scripts/SKI_ConfigMenu.psc
Adds MCM version 10 migration, smooth-scroll toggle and duration slider in $General, and state handlers persisting ListLayout.smoothScroll overrides.
Build and Assets
source/swfsources.cmake, source/swf/skyui/inventorylists.xml
Adds new AS sources to SWF targets and exports __Packages.skyui.components.list.ScrollTweener sprite; updates SWF metadata/shape records.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • doodlum
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(scroll-list): smooth scrolling for inventory and crafting menus' directly and clearly describes the main change—adding smooth/momentum-based scrolling to inventory and crafting menus. It is concise, specific, and accurately summarizes the primary objective of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
source/actionscript/Common/skyui/components/list/ScrollTweener.as (2)

172-182: 💤 Low value

settle() and cancel() are identical — collapse or differentiate.

Both methods zero velocity and deactivate. Callers already use them with intentional semantics ("settle = natural end" vs "cancel = forced abort"), but the bodies are the same. Either:

  1. Delegate one to the other for clarity, or
  2. Drop one if the semantic distinction isn't needed.
♻️ Option: delegate cancel → settle
     public function cancel()
     {
-        this._velocity = 0;
-        this._active = false;
+        this.settle();
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/actionscript/Common/skyui/components/list/ScrollTweener.as` around
lines 172 - 182, The methods settle() and cancel() are identical; to preserve
their semantic intent while avoiding duplication, have cancel() delegate to
settle() instead of duplicating logic: replace cancel()'s body with a single
call to settle() so settle() remains the single implementation that sets
_velocity = 0 and _active = false; update any comments if needed to reflect that
cancel simply invokes settle.

49-51: 💤 Low value

Use the named constant for the default cadence mode.

Initializing CADENCE_MODE with the literal 0 works (because of declaration order constraints) but is fragile if CADENCE_MODE_CURVE's value ever changes. AS2 supports this in a static initializer block or, more simply, leave CADENCE_MODE uninitialized at declaration and assign in a static {} block — or add a comment cross-referencing the chosen mode.

♻️ Suggested clarification
     private static var CADENCE_MODE_CURVE:   Number = 0;
     private static var CADENCE_MODE_CLASSIC: Number = 1;
-    private static var CADENCE_MODE:         Number = 0;
+    private static var CADENCE_MODE:         Number = 0; // = CADENCE_MODE_CURVE
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/actionscript/Common/skyui/components/list/ScrollTweener.as` around
lines 49 - 51, The CADENCE_MODE is currently initialized with the literal 0
which is fragile; change it to use the named constant by removing the literal
initialization and set CADENCE_MODE = CADENCE_MODE_CURVE in a static initializer
(or leave uninitialized at declaration and assign it inside a static { } block)
so CADENCE_MODE references CADENCE_MODE_CURVE directly; update references to
CADENCE_MODE as needed and/or add a short comment explaining the default maps to
CADENCE_MODE_CURVE.
source/actionscript/Common/skyui/components/list/ScrollingList.as (1)

581-588: 💤 Low value

Bounds-check change is correct given the new clipCount policy.

Allowing a_index == _maxListIndex here is necessary now that UpdateList requests _maxListIndex + 1 clips during a fractional glide. EntryClipManager.getClip still gates on a_index >= _clipCount, so callers that ask for an index beyond the currently-sized pool (i.e. when fractional == 0) still get undefined safely. Worth a brief inline note that the relaxed upper bound is paired with the dynamic clipCount in UpdateList so future readers don't tighten it again.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/actionscript/Common/skyui/components/list/ScrollingList.as` around
lines 581 - 588, Relax the bounds check in getClipByIndex so it permits a_index
== _maxListIndex (to match UpdateList requesting _maxListIndex + 1 clips during
fractional glides) and add a brief inline comment explaining this pairing with
the dynamic clipCount; reference getClipByIndex, UpdateList, _maxListIndex,
clipCount and EntryClipManager.getClip to note that EntryClipManager.getClip
still guards against a_index >= _clipCount so callers remain safe when
fractional == 0.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/actionscript/Common/skyui/components/list/ScrollingList.as`:
- Around line 442-446: The momentum scroller starts a process-wide setInterval
in onMouseWheel which can keep firing after the list MovieClip is removed; add
an onUnload method on the ScrollingList class that checks and clears the
interval (_tickIntervalId) and cancels the momentum state (_isMomentumActive)
and any active tween (the same cleanup done when tickScrollTween settles or
scrollPosition setter runs). In onUnload call
clearInterval(this._tickIntervalId) if set, set this._tickIntervalId = null and
this._isMomentumActive = false, and ensure any tween-related state/method (the
one tickScrollTween relies on) is stopped/cleared to prevent callbacks on a
destroyed object. Ensure onUnload is invoked by the lifecycle or parent so the
interval is always cleared when the list is removed.

In `@source/actionscript/Common/skyui/components/list/TabularList.as`:
- Around line 37-46: The TabularList constructor is re-registering ConfigManager
callbacks already registered by the parent ScrollingList, causing
onConfigLoad/onConfigUpdate to run twice; remove the duplicate
skyui.util.ConfigManager.registerLoadCallback(this, "onConfigLoad") and
skyui.util.ConfigManager.registerUpdateCallback(this, "onConfigUpdate") calls
from TabularList's constructor (after super()) and rely on the parent's
registration so the overridden TabularList.onConfigLoad and onConfigUpdate are
invoked once via prototype dispatch.

---

Nitpick comments:
In `@source/actionscript/Common/skyui/components/list/ScrollingList.as`:
- Around line 581-588: Relax the bounds check in getClipByIndex so it permits
a_index == _maxListIndex (to match UpdateList requesting _maxListIndex + 1 clips
during fractional glides) and add a brief inline comment explaining this pairing
with the dynamic clipCount; reference getClipByIndex, UpdateList, _maxListIndex,
clipCount and EntryClipManager.getClip to note that EntryClipManager.getClip
still guards against a_index >= _clipCount so callers remain safe when
fractional == 0.

In `@source/actionscript/Common/skyui/components/list/ScrollTweener.as`:
- Around line 172-182: The methods settle() and cancel() are identical; to
preserve their semantic intent while avoiding duplication, have cancel()
delegate to settle() instead of duplicating logic: replace cancel()'s body with
a single call to settle() so settle() remains the single implementation that
sets _velocity = 0 and _active = false; update any comments if needed to reflect
that cancel simply invokes settle.
- Around line 49-51: The CADENCE_MODE is currently initialized with the literal
0 which is fragile; change it to use the named constant by removing the literal
initialization and set CADENCE_MODE = CADENCE_MODE_CURVE in a static initializer
(or leave uninitialized at declaration and assign it inside a static { } block)
so CADENCE_MODE references CADENCE_MODE_CURVE directly; update references to
CADENCE_MODE as needed and/or add a short comment explaining the default maps to
CADENCE_MODE_CURVE.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 70057cb1-db99-40fe-8b88-4a6d13674b11

📥 Commits

Reviewing files that changed from the base of the PR and between 3d537a3 and dd29109.

📒 Files selected for processing (10)
  • data/interface/translations/skyui_se_english.txt
  • source/actionscript/Common/skyui/components/list/BasicListEntry.as
  • source/actionscript/Common/skyui/components/list/EntryClipManager.as
  • source/actionscript/Common/skyui/components/list/ScrollTweener.as
  • source/actionscript/Common/skyui/components/list/ScrollingList.as
  • source/actionscript/Common/skyui/components/list/TabularList.as
  • source/scripts/SKI_ConfigMenu.psc
  • source/swf/craftingmenu.xml
  • source/swf/skyui/inventorylists.xml
  • source/swfsources.cmake

Comment thread source/actionscript/Common/skyui/components/list/ScrollingList.as
Comment thread source/actionscript/Common/skyui/components/list/TabularList.as
@onlynyans
onlynyans marked this pull request as draft May 8, 2026 16:13
biipbiiip added 2 commits May 9, 2026 00:31
…ttle/cancel

ScrollingList config listener removed - was moved to TabularList. onUnload clears setInterval if the menu tears down mid-glide. settle() dropped, was same as cancel().
Cadence mode was planned, but dropped. Removed CLASSIC_FRICTION_PER_FRAME, CLASSIC_ACCEL_MAX_MULT, CADENCE_MODE_* + mode-branching in impulse()/tick(). CURVE_* -> bare ACCEL_MAX_MULT etc.

Cleaned design comments from ScrollingList, ScrollTweener, TabularList, BasicListEntry, EntryClipManager.
@onlynyans
onlynyans marked this pull request as ready for review May 9, 2026 09:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/actionscript/Common/skyui/components/list/ScrollingList.as`:
- Around line 409-419: The setter that forwards to scrollbar.position must
cancel any active momentum so programmatic writes aren't ignored: in the
scrollPosition setter (the code that does "scrollbar.position = a_newPosition")
check and cancel the active tween/momentum (clear whatever tween/timer and set
_isMomentumActive = false) before forwarding or immediately after, then call
updateScrollPosition(newPos) (or ensure onScroll will apply it) so keyboard
paths like moveSelectionUp/moveSelectionDown and external writes take effect;
alternatively, in onScroll detect origin and if the event is from an explicit
setter, cancel the momentum and proceed (see _isMomentumActive, onScroll,
tickScrollTween, updateScrollPosition, and the scrollbar.position write).

In `@source/actionscript/Common/skyui/components/list/ScrollTweener.as`:
- Around line 97-101: The cancel() method leaves chain metadata (_chainCount and
_lastImpulseTime) intact so a subsequent impulse() within ACCEL_WINDOW_MS
inherits previous cadence; update cancel() to also reset _chainCount to 0 and
_lastImpulseTime to 0 (or a sentinel indicating "no prior impulse") so the next
impulse() starts a fresh chain and cannot immediately get ACCEL_MAX_MULT
cadence.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5557ec2b-e733-4fcb-8a47-a2706122277c

📥 Commits

Reviewing files that changed from the base of the PR and between dd29109 and ff5407a.

📒 Files selected for processing (5)
  • source/actionscript/Common/skyui/components/list/BasicListEntry.as
  • source/actionscript/Common/skyui/components/list/EntryClipManager.as
  • source/actionscript/Common/skyui/components/list/ScrollTweener.as
  • source/actionscript/Common/skyui/components/list/ScrollingList.as
  • source/actionscript/Common/skyui/components/list/TabularList.as
🚧 Files skipped from review as they are similar to previous changes (3)
  • source/actionscript/Common/skyui/components/list/TabularList.as
  • source/actionscript/Common/skyui/components/list/EntryClipManager.as
  • source/actionscript/Common/skyui/components/list/BasicListEntry.as

Comment on lines 409 to +419
private function onScroll(event: Object)
{
this.updateScrollPosition(Math.floor(event.position + 0.5));
// Ignore scrollbar events while momentum is driving position; otherwise the scrollbar
// event would snap us back and cancel the tween.
if (this._isMomentumActive)
return;
var newPos: Number = Math.floor(event.position + 0.5);
if (newPos == this._scrollPosition)
return;
this.updateScrollPosition(newPos);
}

@coderabbitai coderabbitai Bot May 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Programmatic scrollPosition writes are silently swallowed during momentum.

The setter at lines 54-63 forwards to scrollbar.position = a_newPosition, which dispatches the "scroll" event into onScroll. With _isMomentumActive true, onScroll returns at line 414 without applying the new position, so _scrollPosition / _visualScrollPosition / UpdateList never update — only the scrollbar thumb visual moves, and even that gets stomped on the next tickScrollTween (line 449). Concretely:

  • moveSelectionUp/moveSelectionDown keyboard paths (lines 321-322, 325, 348-349, 352) calling this.scrollPosition = ... are no-ops while a wheel glide is in flight.
  • The same applies to any external consumer setting scrollPosition during a tween.

The _isMomentumActive guard was intended to suppress self-fired scroll events from line 449, but it can't distinguish them from a user/programmatic write. Cancel the tween in the setter (or in onScroll for non-self-originated changes) so explicit position changes win.

🛠️ Proposed fix — cancel momentum in the setter
     public function set scrollPosition(a_newPosition: Number)
     {
         if (a_newPosition == this._scrollPosition || a_newPosition < 0 || a_newPosition > this._maxScrollPosition)
             return;
-            
+
+        // Programmatic scrollPosition takes precedence over an in-flight tween.
+        if (this._isMomentumActive) {
+            this._scrollTweener.cancel();
+            this._isMomentumActive = false;
+            if (this._tickIntervalId != -1) {
+                clearInterval(this._tickIntervalId);
+                this._tickIntervalId = -1;
+            }
+        }
+
         if (this.scrollbar != undefined)
             this.scrollbar.position = a_newPosition;
         else
             this.updateScrollPosition(a_newPosition);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/actionscript/Common/skyui/components/list/ScrollingList.as` around
lines 409 - 419, The setter that forwards to scrollbar.position must cancel any
active momentum so programmatic writes aren't ignored: in the scrollPosition
setter (the code that does "scrollbar.position = a_newPosition") check and
cancel the active tween/momentum (clear whatever tween/timer and set
_isMomentumActive = false) before forwarding or immediately after, then call
updateScrollPosition(newPos) (or ensure onScroll will apply it) so keyboard
paths like moveSelectionUp/moveSelectionDown and external writes take effect;
alternatively, in onScroll detect origin and if the event is from an explicit
setter, cancel the momentum and proceed (see _isMomentumActive, onScroll,
tickScrollTween, updateScrollPosition, and the scrollbar.position write).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we skip this please? Kind of out of scope here. What person has one hand on the arrow keys and the other on the scroll wheel 😭

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@biipbiiip Fair enough 😄 — the overlap window where someone would hit arrow keys mid-glide is vanishingly small in practice. Happy to skip it!

Comment on lines +97 to +101
public function cancel()
{
this._velocity = 0;
this._active = false;
}

@coderabbitai coderabbitai Bot May 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

cancel() leaves chain state stale, allowing fresh impulses to inherit accelerated cadence.

cancel() resets _velocity and _active, but leaves _chainCount and _lastImpulseTime untouched. After an edge clamp (tickScrollTween lines 429/432) or any other cancel, the next impulse() from rest will see _velocity == 0, so the reversal branch in line 49 won't fire. With sinceLast still inside ACCEL_WINDOW_MS, line 52 increments rather than resetting _chainCount, so a freshly-started scroll can immediately receive cadenceMult near ACCEL_MAX_MULT (12×) and shoot away on the first wheel tick.

🛠️ Proposed fix
     public function cancel()
     {
         this._velocity = 0;
         this._active = false;
+        this._chainCount = 0;
+        this._lastImpulseTime = 0;
     }

Alternatively, treat _velocity == 0 as a chain-reset condition in impulse():

-        if (reversing || sinceLast <= 0 || sinceLast >= window)
+        if (reversing || this._velocity == 0 || sinceLast <= 0 || sinceLast >= window)
             this._chainCount = 1;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function cancel()
{
this._velocity = 0;
this._active = false;
}
public function cancel()
{
this._velocity = 0;
this._active = false;
this._chainCount = 0;
this._lastImpulseTime = 0;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/actionscript/Common/skyui/components/list/ScrollTweener.as` around
lines 97 - 101, The cancel() method leaves chain metadata (_chainCount and
_lastImpulseTime) intact so a subsequent impulse() within ACCEL_WINDOW_MS
inherits previous cadence; update cancel() to also reset _chainCount to 0 and
_lastImpulseTime to 0 (or a sentinel indicating "no prior impulse") so the next
impulse() starts a fresh chain and cannot immediately get ACCEL_MAX_MULT
cadence.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to skip this please - I don't want the chain to reset on cancel/edge clamp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@biipbiiip, understood — preserving _chainCount and _lastImpulseTime across cancel() is intentional so that a scroll resuming after an edge clamp (or any other cancellation) continues building cadence naturally rather than snapping back to a 1× multiplier. I'll drop this suggestion.


✏️ Learnings added
Learnt from: biipbiiip
Repo: doodlum/SkyUI-Community PR: 195
File: source/actionscript/Common/skyui/components/list/ScrollTweener.as:97-101
Timestamp: 2026-05-09T17:26:49.955Z
Learning: In `source/actionscript/Common/skyui/components/list/ScrollTweener.as`, `cancel()` intentionally does NOT reset `_chainCount` or `_lastImpulseTime`. The author wants chain cadence to persist across cancellations and edge clamps so that a scroll restarting shortly after still benefits from the accumulated impulse chain rather than resetting to 1× multiplier. Do not flag this as a bug.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@onlynyans
onlynyans marked this pull request as draft May 18, 2026 04:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant