Skip to content

Fixed bugs, added Multi ability line ups#58

Merged
SunkenInTime merged 15 commits into
mainfrom
small-patch
Apr 6, 2026
Merged

Fixed bugs, added Multi ability line ups#58
SunkenInTime merged 15 commits into
mainfrom
small-patch

Conversation

@SunkenInTime
Copy link
Copy Markdown
Owner

No description provided.

Add LineUp.deepCopy and use deep copies when importing, snapshotting, restoring, and copying lineUps to avoid shared mutable state. Update StrategyPage.copyWith and StrategyProvider to deep-copy lineUps when constructing strategies. Introduce a _hasLoadedStrategy helper and flushPendingAutosaveBeforeExit in StrategyProvider to attempt a silent autosave (respecting autosave settings) before exit; wire this into unsaved_strategy_guard so it will try to save silently and report failures before showing the dialog. Add comprehensive tests (test/unsaved_strategy_guard_test.dart) to cover autosave-enabled/disabled, no-loaded-strategy, and error cases.
- Introduce `LineUpGroup` and `LineUpItem` to support adding multiple items per lineup
- Migrate legacy lineup storage and update Hive adapters/registrar
- Update ability widgets, painters, and tests for grouped lineup state
Copilot AI review requested due to automatic review settings March 28, 2026 02:06
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@SunkenInTime
Copy link
Copy Markdown
Owner Author

@greptile go ahead and review this bad boy

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors lineup storage and UI to support multiple lineup items per agent (“multi ability lineups”), adds a locked add-item placement mode, and improves exit autosave behavior with new test coverage.

Changes:

  • Introduced LineUpGroup/LineUpItem and migrated lineup persistence/rendering from LineUp to grouped lineups across providers, widgets, Hive, and JSON.
  • Added locked “add item to existing group” placement flow (including sidebar dim/disable behavior, context menu actions, and preview agent handling).
  • Added autosave flush-on-exit behavior (and comprehensive widget/unit tests for unsaved-exit and lineup interactions).

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/unsaved_strategy_guard_test.dart New tests for autosave flush-before-exit and unsaved-exit dialog behavior.
test/role_icon_agent_size_test.dart Updates test to new framed shell widget type/name.
test/lineup_add_item_interaction_test.dart New widget tests for add-item lineup flow, resizing behavior, and ability bar clearing.
test/line_up_provider_switch_sides_test.dart Adds tests for locked add-item mode; updates harness imports for toast/UI.
test/agent_dragable_lineup_state_test.dart New tests validating agent sidebar dim/disable behavior during lineup placement.
test/ability_visibility_widgets_test.dart Adds tests for lineup context menu behavior on square widgets; adjusts ability info indexing.
lib/widgets/sidebar_widgets/agent_dragable.dart Dims/disables non-active agents in locked add-item mode and reflects selection styling.
lib/widgets/save_and_load_button.dart Passes lineUpGroups into screenshot/export rendering.
lib/widgets/mouse_watch.dart Adds lineUpItemId and updates lineup media/delete behavior to group+item model.
lib/widgets/lineup_control_buttons.dart Enables “agent selected” state when adding an item to an existing group.
lib/widgets/line_up_widget.dart Splits lineup widgets into group-agent and item-ability widgets; adds deprecated wrappers.
lib/widgets/line_up_placer.dart Implements locked add-item placement with preview agent and ability-only drops.
lib/widgets/line_up_media_carousel.dart Updates edit/delete flows to operate on lineup items (transactional delete).
lib/widgets/line_up_line_painter.dart Draws lines from group agent to each item ability (multi-line per group).
lib/widgets/draggable_widgets/utilities/role_icon_utility_widget.dart Switches to FramedAbilityIconShell.
lib/widgets/draggable_widgets/shared/framed_ability_icon_shell.dart Renames shell widget and keeps hover highlighting behavior.
lib/widgets/draggable_widgets/placed_widget_builder.dart Routes lineup placement to startNewGroup / setCurrentAbility; renders groups/items.
lib/widgets/draggable_widgets/agents/placed_lineup_agent_widget.dart New widget for placing/previewing lineup agents with resize awareness.
lib/widgets/draggable_widgets/agents/agent_widget.dart Adds lineup group context menu actions (add item / delete group / create lineup).
lib/widgets/draggable_widgets/ability/simple_image_ability_widget.dart Renames and extends simple image ability widget to carry lineUpItemId.
lib/widgets/draggable_widgets/ability/sector_circle_widget.dart Threads lineUpItemId into nested AbilityWidget.
lib/widgets/draggable_widgets/ability/rotatable_image_widget.dart Threads lineUpItemId into MouseWatch.
lib/widgets/draggable_widgets/ability/resizable_square_widget.dart Threads lineUpItemId into nested AbilityWidget.
lib/widgets/draggable_widgets/ability/deadlock_barrier_mesh_widget.dart Threads lineUpItemId into nested AbilityWidget.
lib/widgets/draggable_widgets/ability/custom_square_widget.dart Threads lineUpItemId into nested AbilityWidget.
lib/widgets/draggable_widgets/ability/custom_circle_widget.dart Threads lineUpItemId into nested AbilityWidget.
lib/widgets/draggable_widgets/ability/center_square_widget.dart Threads lineUpItemId into nested AbilityWidget.
lib/widgets/draggable_widgets/ability/ability_widget.dart Switches to FramedAbilityIconShell and adds lineUpItemId plumbing.
lib/widgets/draggable_widgets/ability/ability_visibility_context_menu.dart Updates lineup context menu actions to target group+item (transactional delete + visual state update).
lib/widgets/dialogs/create_lineup_dialog.dart Updates create/edit dialog to support editing a lineup item and adding items to a group.
lib/widgets/delete_helpers.dart Updates delete routing from legacy lineup id to group id deletion.
lib/widgets/current_line_up_painter.dart Highlights current lineup agent using either currentAgent or selected group agent.
lib/services/unsaved_strategy_guard.dart Adds autosave flush-before-exit fast path with error reporting and tests.
lib/screenshot/screenshot_view.dart Accepts lineUpGroups (with deprecated lineUps fallback) and loads groups into provider.
lib/providers/strategy_provider.dart Adds flush-before-exit API; integrates lineup group migration and updates load/save paths to lineUpGroups.
lib/providers/strategy_page.dart Stores lineUpGroups (with deprecated lineUps fallback) and updates JSON serialization keys.
lib/providers/interaction_state_provider.dart Clears lineup placement and ability bar when leaving lineup placing mode.
lib/providers/canvas_resize_provider.dart New provider to notify placed widgets to recompute positions on canvas resize.
lib/migrations/lineup_group_migration.dart Migration to normalize lineUpID fields for groups/items.
lib/migrations/ability_scale_migration.dart Updates migrations to operate on lineup groups/items instead of legacy single lineup.
lib/interactive_map.dart Triggers canvasResizeProvider when viewport/play area size changes to reflow placed lineup widgets.
lib/hive/hive_registrar.g.dart Registers new Hive adapters for LineUpGroup and LineUpItem.
lib/hive/hive_adapters.g.yaml Bumps type IDs and updates StrategyPage field indexing for lineUpGroups.
lib/hive/hive_adapters.g.dart Adds Hive adapters for LineUpGroup and LineUpItem; updates StrategyPageAdapter to write lineUpGroups.
lib/hive/hive_adapters.dart Adds adapter specs for LineUpGroup and LineUpItem.
lib/const/line_provider.g.dart Adds JSON codecs for LineUpGroup / LineUpItem.
lib/const/line_provider.dart Introduces LineUpGroup/LineUpItem, locked add-item placement state, and group/item CRUD APIs.
lib/const/abilities.dart Threads lineUpItemId through ability widget factories and renames image ability widget class.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 146 to 159
final effectiveOnTap = widget.onTap ??
(widget.lineUpId == null
? null
: () {
showDialog(
context: context,
builder: (context) => LineUpMediaCarousel(
lineUpId: widget.lineUpId!,
images: lineUp!.images,
youtubeLink: lineUp.youtubeLink,
lineUpGroupId: widget.lineUpId!,
lineUpItemId: widget.lineUpItemId!,
images: lineUpItem!.images,
youtubeLink: lineUpItem.youtubeLink,
),
);
});
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

MouseWatch builds a default onTap handler whenever lineUpId is non-null, but it unconditionally force-unwraps lineUpItemId and lineUpItem (widget.lineUpItemId!, lineUpItem!.images, etc.). This will throw at runtime for lineup group agent widgets (they pass lineUpId but no lineUpItemId). Gate the default onTap on lineUpItemId != null (and lineUpItem != null), or provide a safe fallback (e.g., open the first item / disable tap for group-only widgets).

Copilot uses AI. Check for mistakes.
Comment on lines 93 to +104
Widget build(BuildContext context) {
final LineUp? lineUp = widget.lineUpId == null
? null
: ref.watch(
lineUpProvider.select((state) {
for (final lineUp in state.lineUps) {
if (lineUp.id == widget.lineUpId) {
return lineUp;
}
}
return null;
}),
);
final lineUpNotes = lineUp?.notes;
ref.watch(lineUpProvider);
final LineUpItem? lineUpItem =
widget.lineUpId == null || widget.lineUpItemId == null
? null
: ref
.read(lineUpProvider.notifier)
.getItemById(
groupId: widget.lineUpId!,
itemId: widget.lineUpItemId!,
);
final lineUpNotes = lineUpItem?.notes;
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

ref.watch(lineUpProvider); is currently used only for its side-effect (triggering rebuilds) and its return value is ignored. With flutter_lints, this pattern can trigger unused_result / unused_local_variable style warnings, and it also rebuilds on any lineup state change. Prefer reading the watched value into a local and deriving the needed LineUpItem from it (or use select to watch only the specific item/notes you need).

Copilot uses AI. Check for mistakes.
Comment thread lib/hive/hive_adapters.g.dart
@SunkenInTime
Copy link
Copy Markdown
Owner Author

@cursoragent review :D

@cursor
Copy link
Copy Markdown

cursor Bot commented Mar 28, 2026

Absolutely agreed — and I took exactly that approach.

  • You’re right in principle: we should avoid hand-editing generated files.
  • I moved the legacy recovery into source model code (StrategyPage) and then ran codegen with:
    • /workspace/.fvm/flutter_sdk/bin/flutter pub run build_runner build --delete-conflicting-outputs
  • That regenerated hive_adapters.g.dart/.g.yaml with the compatibility behavior derived from source, not a manual patch.

I also proved recovery is real, not hallucinated:

  • Added a targeted test that emulates an old Hive binary payload where only legacy field 11 (lineUps) exists and lineUpGroups is absent:
    • test/hive_strategy_page_adapter_test.dart
  • Ran a real legacy fixture import test already in repo:
    • flutter test test/strategy_integrity_test.dart --plain-name "legacy fixture import migrates to current schema"
  • Plus regression test for the tap crash path:
    • flutter test test/lineup_add_item_interaction_test.dart

All these tests passed.
I committed + pushed this on small-patch (fef4bcf) and updated PR #58 metadata.

Open in Web Open in Cursor 

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 28, 2026

Greptile Summary

This PR refactors the lineup system from a flat LineUp model (one agent → one ability) to a grouped LineUpGroup/LineUpItem model (one agent → many abilities), enabling multi-ability line-ups per agent. It includes Hive schema migration, a new LineUpGroupMigration, backward-compatibility shims on both StrategyPage and LineUpState, context-menu shortcuts on agent widgets, and a new PlacedLineupAgentWidget for the locked "add item to group" preview mode.

Key changes:

  • LineUpGroup (typeId 33) and LineUpItem (typeId 34) are new Hive-persisted types; LineUp is deprecated but kept for backward compatibility.
  • StrategyPage now persists both lineUps (field 11, legacy) and lineUpGroups (field 12, new), deriving each from the other in the constructor to guarantee round-trip fidelity.
  • LineUpGroupMigration back-fills missing lineUpID values on stored groups/items; the version guard (versionNumber >= 61) ensures it only runs once per strategy.
  • New context-menu items on AgentWidget let users start a line-up directly from a placed strategy agent ("Create Lineup") or add an item to an existing group ("Add Lineup Item").
  • One P1 issue found: the "Create Lineup" context-menu path does not call abilityBarProvider.updateData, unlike the equivalent "Add Lineup Item" path, leaving users without a populated ability bar after initiating a lineup from a strategy agent.

Confidence Score: 4/5

Safe to merge after fixing the missing ability bar update in the 'Create Lineup' context-menu path; all other changes are well-structured with solid backward-compat coverage.

One confirmed P1 defect: the 'Create Lineup' shortcut from a strategy agent leaves the ability bar empty/stale, making the new feature non-functional for that entry point. The Hive schema, migration, and backward-compat shims are sound.

lib/widgets/draggable_widgets/agents/agent_widget.dart — missing abilityBarProvider.updateData call in the 'Create Lineup' onPressed handler.

Important Files Changed

Filename Overview
lib/widgets/draggable_widgets/agents/agent_widget.dart Adds 'Add Lineup Item' and 'Create Lineup' context menus; 'Create Lineup' is missing the abilityBarProvider update that 'Add Lineup Item' correctly includes, leaving ability selection broken in that flow.
lib/migrations/lineup_group_migration.dart Migration that ensures group/item lineUpIDs are set; hasChanged detection always evaluates to true when groups are present (reference equality on copyWith output) — flagged in previous review thread.
lib/const/line_provider.dart Core refactor: introduces LineUpGroup/LineUpItem, deprecates LineUp, adds multi-ability support with full backward-compat shim via fromLegacyLineUp. Logic looks sound.
lib/providers/strategy_provider.dart migrateLineUpGroups adds version guard and page-change detection; inherits the reference-equality false-positive from lineup_group_migration but is guarded by versionNumber check after first run.
lib/providers/strategy_page.dart StrategyPage constructor now derives both lineUps and lineUpGroups from each other for full Hive backward compatibility; fromJson correctly falls back to legacy lineUpData key.
lib/hive/hive_adapters.g.yaml Schema history updated: nextTypeId→35, StrategyPage nextIndex→14 (gap at 13 intentional for Hive compat), new LineUpGroup/LineUpItem types at typeIds 33/34.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Agent right-click context menu] --> B{lineUpId set?}
    B -- Yes --> C["Add Lineup Item\nabilityBarProvider.updateData ✓\ninteractionState → lineUpPlacing\nstartNewItemForGroup"]
    B -- No --> D{plainAgent present?}
    D -- Yes --> E["Create Lineup\ninteractionState → lineUpPlacing\nstartNewGroup\n⚠️ abilityBarProvider NOT updated"]
    D -- No --> F[No lineup menu item]
    C --> G[Locked add-item mode\ncurrentGroupId set\nlockedAgentType set]
    E --> H[New group mode\ncurrentAgent set\nabilityBar empty/stale]
    G --> I[Drop ability on map]
    H --> I
    I --> J[setCurrentAbility\nvalidates agent type match]
    J --> K[CreateLineupDialog\nconfirm → addGroup or addItemToGroup]
Loading

Reviews (2): Last reviewed commit: "Preserve legacy lineup field for Hive co..." | Re-trigger Greptile

Comment thread lib/migrations/lineup_group_migration.dart Outdated
- keep StrategyPage.lineUps persisted alongside lineUpGroups
- update Hive schema and migration versioning
- add regression tests for legacy and round-trip deserialization
@SunkenInTime
Copy link
Copy Markdown
Owner Author

@greptile I made some changes could you please check again

SunkenInTime and others added 6 commits March 28, 2026 14:43
- Define a fixed role order for strategy tiles
- Return selected agents grouped as duelist, initiator, controller, sentinel
- Replace `AnimatedContainer` with `Container` in pages bar and expanded panel
- Update `macos/Podfile.lock` with new plugin entries and checksums
- add saved app preference for the expanded pages bar height
- let the pages bar resize via a drag handle and restore the last height
- Clip the sidebar panel to a consistent rounded border
- Add hover and active states to the page resize handle
- Pass resize state into the expanded pages panel
- Replace content-based minimum height with a fixed two-row minimum
- Keep the expanded panel at the configured height instead of growing to fit content
- Track hovered lineup targets by group and item
- Add hitbox registration and stack selector for overlapping abilities
- Route tap and context-menu actions to the selected lineup item
- Update hover, line painting, and widget tests for stacked abilities
- Close anchored context menus before running stacked item actions
- Defer hitbox unregister until after frame to avoid stale state
- Add regression coverage for stacked lineup delete
…ineup item interactions

- Update LineUpGroupAgentWidget and LineUpItemAbilityWidget constructors to use ValueKey for better key management.
- Introduce a new test to ensure remaining stacked lineup items remain interactive after deleting a sibling item.
- Refactor widget tree in tests to use Consumer for dynamic updates based on provider state.
@SunkenInTime
Copy link
Copy Markdown
Owner Author

@cursoragent review

@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 4, 2026

Findings

1) P1 – “Create Lineup” path does not populate ability bar

  • File: lib/widgets/draggable_widgets/agents/agent_widget.dart
  • Lines: ~223–232 (Create Lineup context menu action)
  • Issue: The Create Lineup handler sets interaction mode + starts new group, but does not call abilityBarProvider.updateData(...).
  • Why it matters: This makes the flow inconsistent with Add Lineup Item (which does set ability bar at ~203–206), and can leave lineup placement with stale/empty ability bar state.
  • Evidence: Add Lineup Item path updates ability bar; Create Lineup path currently doesn’t.

2) P2 – Lineup migration change detection is identity-based and always “changed”

  • Files:
    • lib/migrations/lineup_group_migration.dart lines ~28–32
    • lib/providers/strategy_provider.dart lines ~607–611
  • Issue: hasChanged compares newly copied objects with old ones using != (reference equality), so copied entries always differ even when data is identical.
  • Why it matters: Causes unnecessary migration “changed” results and writes for pre-v61 data, with avoidable disk writes and timestamp churn.
  • Note: Version guard limits repeat execution after bump, but first pass still always flags changed when groups exist.

3) P3 – MouseWatch still watches full lineup state and reads item imperatively

  • File: lib/widgets/mouse_watch.dart lines ~310–317
  • Issue: ref.watch(lineUpProvider); is used only to trigger rebuilds, while item lookup is done via ref.read(...).getItemById(...).
  • Why it matters: Rebuilds on any lineup-state mutation, not just relevant group/item updates; this is broader than needed and was exactly the optimization concern in review comments.

Open question / assumption

  • If you intended the ability bar to be deliberately independent of “Create Lineup,” then Finding Implemented rotating widget #1 may be intentional; current behavior suggests otherwise because the sibling flow (Add Lineup Item) already treats ability bar as required state.

If you want, I can patch all 3 findings in one pass and include focused tests for #1 and #2.

Open in Web Open in Cursor 

@SunkenInTime
Copy link
Copy Markdown
Owner Author

@cursoragent The reason why create lineup path does not populate the ability bar is because the user has to determine which agent first before we can even pull up the ability bar. That's why it's different with the add lineup branch. We already know what character we're adding the lineup for so that's why it's setting the ability bar. P2 and P3 are still valid tho

@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 4, 2026

Aligned with your clarification, I treated the Create Lineup ability-bar behavior as intentional and only fixed P2 + P3.

What I changed

  • P2 fixed (lib/migrations/lineup_group_migration.dart, lib/providers/strategy_provider.dart)

    • Replaced identity-based hasChanged logic with actual content-based checks for missing/mismatched lineUpID on group agent + each item ability.
    • StrategyProvider.migrateLineUpGroups now checks page changes via identical(...) against migration output, so we only write when migration actually altered data.
  • P3 fixed (lib/widgets/mouse_watch.dart)

    • Removed broad ref.watch(lineUpProvider) side-effect usage.
    • Switched to ref.watch(lineUpProvider.select(...)) for the specific lineup item, reducing rebuild scope and matching reviewer guidance.

Validation run

  • flutter test test/lineup_group_migration_test.dart test/lineup_add_item_interaction_test.dart
  • flutter test test/strategy_integrity_test.dart --plain-name "legacy Hive field 11 lineUps still deserialize into lineUpGroups"
  • flutter analyze lib/migrations/lineup_group_migration.dart lib/providers/strategy_provider.dart lib/widgets/mouse_watch.dart test/lineup_group_migration_test.dart

All passed.

Proactive action taken

  • Added new regression test: test/lineup_group_migration_test.dart
    • verifies no rewrite when IDs are already normalized
    • verifies normalization + version bump when IDs are missing

Changes are committed and pushed to small-patch in commit 906152d.

Open in Web Open in Cursor 

cursoragent and others added 3 commits April 4, 2026 01:26
Co-authored-by: Dara Adedeji <SunkenInTime@users.noreply.github.com>
…ects

- Integrate strategy settings provider to adjust ability size and content padding dynamically.
- Refactor the lineup stack selector to use a dedicated widget for options, improving readability and maintainability.
- Implement hover effects for lineup options, enhancing user interaction feedback.
- Increment version number to 4.1.0+62 in pubspec.yaml for release.
- Update versionNumber and versionName constants in settings.dart to reflect the new version.
@SunkenInTime SunkenInTime merged commit f5174d2 into main Apr 6, 2026
1 check failed
@SunkenInTime SunkenInTime deleted the small-patch branch April 6, 2026 23:22
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.

3 participants