feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: make donation panel size and layout configurable - #420

Merged
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel
May 3, 2026
Merged

feat: make donation panel size and layout configurable#420
tastybento merged 4 commits into
developfrom
feat/configurable-donation-panel

Conversation

@tastybento

@tastybentotastybento commented May 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces the hardcoded 36-slot, 4-row layout in DonationPanel with a templated layout loaded from panels/donation_panel.yml, matching the pattern used by value_panel.yml, detail_panel.yml, and top_panel.yml.
  • Admins can change the panel size (1–6 rows via force-shown), relocate the four named buttons (INFO / CANCEL / PREVIEW / CONFIRM), or swap their icons; the donation grid auto-fills every cell that isn't a border or named button.
  • Listener logic (drag/click/close handling) is unchanged — only slot resolution is now template-driven, with the original hardcoded layout kept as a fallback when the template is missing or malformed.

Why this is split out

The donation panel can't fully use TemplatedPanelBuilder because its donation slots are interactive (players drag arbitrary blocks in, items are validated against BlockConfig, invalid items get returned). The standard TemplatedPanel infrastructure assumes static, click-only icons. So this PR keeps the raw Bukkit.createInventory(...) + custom Listener approach and uses TemplateReader only for layout resolution.

Implementation notes

  • New DonationPanelLayout is a pure-Java resolver (no Bukkit dependencies in its logic) so it can be unit-tested without MockBukkit.
  • A non-null template cell with an unrecognised data.type reserves the slot — admins placing decorative items won't see them stomped by donations.
  • If any of INFO / CANCEL / PREVIEW / CONFIRM is missing from the template, the resolver falls back to the full hardcoded default rather than rendering a half-broken UI.
  • Level.onLoad() now calls saveResource("panels/donation_panel.yml", false) alongside the other panel templates.

Test plan

  • mvn test — 184/184 pass, including 9 new DonationPanelLayoutTest cases (null template, default 4-row, 6-row expansion, 1-row pathological, no-border, missing-button fallback, content-inferred row count, title overrides, unknown data.type).
  • Manual: drop the new donation_panel.yml into plugins/BentoBox/addons/Level/panels/, change force-shown to 5, restart, run /island donate, confirm the panel renders with 5 rows and all four buttons in their relocated positions.
  • Manual: delete donation_panel.yml from the data folder and confirm the panel still renders with the legacy 4-row layout (fallback path).

🤖 Generated with Claude Code

DonationPanel previously had a hardcoded 36-slot, 4-row layout. Move it
to the standard BentoBox templated-panel pattern so admins can change
rows, button positions, and icons via panels/donation_panel.yml without
touching code. The panel still uses a custom listener for the
drag-and-drop donation slots; only layout resolution is template-driven,
with the original hardcoded layout kept as a fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

CopilotAI 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.

Pull request overview

This PR moves the donation UI away from a hardcoded 4-row inventory layout and toward the repo’s panel-template approach by introducing a DonationPanelLayout resolver, a new donation_panel.yml, and wiring the donation panel to load its slot positions and icons from config at runtime. It fits into the Level addon’s existing panel system by making the donation panel configurable in the same resource-driven area as the top/detail/value panels, while preserving the custom drag/drop listener logic the donation flow requires.

Changes:

  • Added a new DonationPanelLayout resolver that derives inventory size, button slots, donation slots, and icon materials from a panel template with a hardcoded fallback.
  • Updated DonationPanel to read panels/donation_panel.yml and use the resolved layout instead of fixed slot constants.
  • Added the new donation panel resource file and unit tests for layout resolution, and registered the resource in Level.onLoad().

Reviewed changes

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

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/panels/DonationPanelLayoutTest.javaAdds unit tests for template-to-layout resolution and fallback cases.
src/main/resources/panels/donation_panel.ymlIntroduces the configurable donation panel template shipped with the addon.
src/main/java/world/bentobox/level/panels/DonationPanelLayout.javaImplements the template-driven layout resolver used by the donation panel.
src/main/java/world/bentobox/level/panels/DonationPanel.javaReplaces hardcoded slot usage with runtime-loaded layout data.
src/main/java/world/bentobox/level/Level.javaEnsures the new donation panel template is copied into the data folder on load.

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

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…rce-shown format
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/9233b785-a13b-4ea5-9b58-18fe24bdf4e9
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented May 2, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Done in commit 633f2a7. Three issues addressed:

  1. Decorative items now renderedDonationPanelLayout stores icons for slots with absent/unrecognised data.type in a new decorativeItems map. DonationPanel places those icons in the inventory (skipping border-fill for those slots), so admin-added decorations are visible instead of empty holes.

  2. Template title now respectedDonationPanelLayout exposes a panelTitle field (from template.title(), falling back to DEFAULT_TITLE_REF). DonationPanel calls user.getTranslation(layout.panelTitle) instead of the former hardcoded constant.

  3. YAML format + test coverage — Changed force-shown: 4 to force-shown: [1,2,3,4] in donation_panel.yml to match the list syntax used by the other panel templates. Added 6 new tests including one that reads the actual donation_panel.yml file via YamlConfiguration and verifies its structure (list force-shown, all four button positions and types, and the default title key). Total: 190/190 tests pass.

tastybentoand others added 2 commits May 3, 2026 14:13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DonationPanel: use HashSet.newHashSet (S6485) and method reference
for forEach (S1612).
- DonationPanelLayout: replace 15-param constructor (S107) with a
Builder accumulator. Extract processCell/addDecorative helpers from
fromTemplate to bring cognitive complexity (S3776) and brain-method
metrics (S6541) under threshold, eliminating the multi-decl
warnings (S1659) and reducing in-loop continues (S135).
- DonationPanelLayoutTest: use assertNotEquals instead of assertTrue
with != (S5785).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 2dc713d into developMay 3, 2026
3 checks passed
@tastybento
tastybento deleted the feat/configurable-donation-panel branch May 3, 2026 21:45
Sign up for freeto 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

@tastybento