Skip to content

Commit dd32dd3

Browse files
committed
Release 5.1.6 UI settings access fix
1 parent 0b045d0 commit dd32dd3

9 files changed

Lines changed: 116 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 5.1.6 - 2026-05-03
4+
5+
In-card UI settings access fix.
6+
7+
- Keeps `Settings` permanently available in the main bar when `settings_source` is set to UI/in-card mode, even if saved settings, YAML, or older local state omit it.
8+
- Locks the Settings item in the in-card main bar selector so it is clear that it cannot be disabled in UI mode.
9+
- Bumps editor custom element tags so Home Assistant loads the refreshed visual editor after the release update.
10+
311
## 5.1.5 - 2026-05-02
412

513
Home Assistant Dashboard picker registry fix.

LOCAL_DEPLOYMENT.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Use only this runtime package folder in Home Assistant `www`:
1212

1313
Use only this Lovelace resource pattern:
1414

15-
`/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.5`
15+
`/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.6`
1616

1717
From now on, bump only the query version after `?v=`.
1818
Do not change the file name again unless there is a hard cache emergency.
@@ -29,14 +29,14 @@ Stable deploy target:
2929

3030
`dist/` should always be the latest approved install package.
3131

32-
## Current 5.1.5 Mapping
32+
## Current 5.1.6 Mapping
3333

3434
- Edit: `src/homeii-music-flow.js`
3535
- Review/share: `dist/`
3636
- Deploy to HA `www`: copy the full contents of `dist/` into `www/community/homeii-music-flow/`
3737
- Package includes: `homeii-music-flow.js`, `sendspin-js/`, `vendor/embla-carousel.umd.js`, `homeii-flow-logo.svg`
3838
- Lovelace type: `custom:homeii-music-flow`
39-
- Lovelace resource: `/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.5`
39+
- Lovelace resource: `/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.6`
4040

4141
## Cache Reset Rule
4242

@@ -48,7 +48,7 @@ If a new version is approved:
4848

4949
Example:
5050

51-
`/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.5`
51+
`/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.6`
5252

5353
## Foundation Note
5454

PUBLISHING.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
- the HACS My Home Assistant button
2424
- the HACS download/install button
2525

26-
## 2. Create the 5.1.5 release
26+
## 2. Create the 5.1.6 release
2727

28-
- Create a Git tag named `v5.1.5`.
28+
- Create a Git tag named `v5.1.6`.
2929
- Create a GitHub release from that tag.
30-
- Title the release `5.1.5`.
31-
- Use the `5.1.5` section from `CHANGELOG.md` as the release notes.
30+
- Title the release `5.1.6`.
31+
- Use the `5.1.6` section from `CHANGELOG.md` as the release notes.
3232
- If you attach a release artifact, zip the contents of `dist/`; do not publish only a single JS file while the local Sendspin player and Embla swipe support are enabled.
3333

3434
## 3. Verify repository files after publishing
@@ -79,7 +79,7 @@ to:
7979

8080
Then load:
8181

82-
`/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.5`
82+
`/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.6`
8383

8484
## 7. Final pre-release smoke test
8585

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
</p>
2323

2424
<p align="center">
25-
<a href="https://github.com/r11a/homeii-music-flow"><img alt="version" src="https://img.shields.io/badge/version-5.1.5-gold"></a>
25+
<a href="https://github.com/r11a/homeii-music-flow"><img alt="version" src="https://img.shields.io/badge/version-5.1.6-gold"></a>
2626
<img alt="Home Assistant" src="https://img.shields.io/badge/Home%20Assistant-Dashboard-41BDF5">
2727
<img alt="Music Assistant" src="https://img.shields.io/badge/Music%20Assistant-required-7C5CFF">
2828
<img alt="Sendspin" src="https://img.shields.io/badge/Sendspin-browser%20player-18B6FF">
@@ -49,6 +49,10 @@ HOMEii Flow started from my own daily use of Home Assistant and Music Assistant.
4949
- **Hebrew and RTL ready:** layout, labels, alignment, and interaction patterns are built for Hebrew as a first-class use case.
5050
- **Release-ready package:** HACS-ready `dist/` output includes the card, Sendspin files, Embla swipe support, and the brand asset.
5151

52+
## What's New In 5.1.6
53+
54+
- **In-card UI settings access fixed:** when settings are managed from the in-card UI, the `Settings` button now always stays in the main bar and cannot be disabled from the in-card selector.
55+
5256
## What's New In 5.1.5
5357

5458
- **Dashboard picker registry fix:** HOMEii Flow now mutates Home Assistant's existing `window.customCards` registry in place instead of replacing it, matching the way the HA picker imports and reads custom-card metadata.
@@ -126,7 +130,7 @@ If HACS does not add the resource automatically, add:
126130
3. Add this Dashboard resource:
127131

128132
```text
129-
/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.5
133+
/local/community/homeii-music-flow/homeii-music-flow.js?v=5.1.6
130134
```
131135

132136
4. Add the card:
@@ -704,7 +708,7 @@ npm run lint
704708
npm test
705709
```
706710

707-
Current packaged version: `5.1.5`
711+
Current packaged version: `5.1.6`
708712

709713
## Release Readiness
710714

dist/homeii-music-flow.js

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@
429429
_versionedAssetUrl(url) {
430430
const value = String(url || "").trim();
431431
if (!value || /^data:/i.test(value) || /[?&]v=/.test(value)) return value;
432-
const version = typeof HOMEII_CARD_VERSION === "string" ? HOMEII_CARD_VERSION : "5.1.5";
432+
const version = typeof HOMEII_CARD_VERSION === "string" ? HOMEII_CARD_VERSION : "5.1.6";
433433
return `${value}${value.includes("?") ? "&" : "?"}v=${encodeURIComponent(version)}`;
434434
}
435435

@@ -9685,9 +9685,9 @@ function ensureHaEditorComponents() {
96859685
} catch (_) {}
96869686
}
96879687

9688-
const HOMEII_CARD_VERSION = "5.1.5";
9689-
const HOMEII_BROWSER_EDITOR_TAG = "homeii-music-flow-browser-editor-v5150";
9690-
const HOMEII_MOBILE_EDITOR_TAG = "homeii-music-flow-editor-v5150";
9688+
const HOMEII_CARD_VERSION = "5.1.6";
9689+
const HOMEII_BROWSER_EDITOR_TAG = "homeii-music-flow-browser-editor-v5160";
9690+
const HOMEII_MOBILE_EDITOR_TAG = "homeii-music-flow-editor-v5160";
96919691

96929692
const HomeiiEditorLocale = Object.freeze({
96939693
isHebrewLanguageTag(value) {
@@ -9942,7 +9942,9 @@ const HomeiiMobileSettingsFoundation = Object.freeze({
99429942
.filter((item) => !(usesVisualSettings && item === "settings"))
99439943
.filter((item) => !(hidePlayers && item === "players"));
99449944
const normalizedFallback = fallback.filter((item) => !(hidePlayers && item === "players"));
9945-
return cleaned.length ? cleaned : normalizedFallback;
9945+
const normalized = cleaned.length ? cleaned : normalizedFallback;
9946+
if (!usesVisualSettings && !normalized.includes("settings")) normalized.push("settings");
9947+
return normalized;
99469948
},
99479949
normalizeMobileQuickActions(items, fallbackItems = []) {
99489950
const allowed = new Set(["timer", "like", "lyrics", "queue", "radio", "history", "info"]);
@@ -23195,6 +23197,27 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2319523197
margin:0;
2319623198
accent-color:var(--ma-accent);
2319723199
}
23200+
.settings-check-pill.is-locked {
23201+
cursor:default;
23202+
opacity:.94;
23203+
}
23204+
.settings-check-pill.is-locked input {
23205+
opacity:.78;
23206+
}
23207+
.settings-fixed-badge {
23208+
margin-inline-start:auto;
23209+
padding:3px 8px;
23210+
border-radius:999px;
23211+
background:rgba(245,166,35,.16);
23212+
color:var(--ma-accent);
23213+
font-size:11px;
23214+
font-weight:900;
23215+
letter-spacing:0;
23216+
}
23217+
.rtl .settings-fixed-badge {
23218+
margin-inline-start:0;
23219+
margin-inline-end:auto;
23220+
}
2319823221
.rtl .settings-check-pill {
2319923222
direction:rtl;
2320023223
justify-content:flex-start;
@@ -26972,6 +26995,7 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2697226995
const playerOptions = (this._state.players || []).map((player) => [player.entity_id, player.attributes?.friendly_name || player.entity_id]);
2697326996
const visibleMainBarOptions = mainBarOptions;
2697426997
const showStudioMainBarOption = this._controlRoomEnabled();
26998+
const settingsMainBarLocked = !this._usesVisualSettings();
2697526999
return `
2697627000
<div class="settings-shell">
2697727001
<div class="settings-group">
@@ -27081,11 +27105,15 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2708127105
<span>${this._esc(this._controlRoomLabel())}</span>
2708227106
</label>
2708327107
` : ``}
27084-
${visibleMainBarOptions.map(([value, label]) => `
27085-
<label class="settings-check-pill">
27086-
<input type="checkbox" data-setting-main-bar-item="${this._esc(value)}" ${selectedMainBar.has(value) ? "checked" : ""}>
27108+
${visibleMainBarOptions.map(([value, label]) => {
27109+
const locked = settingsMainBarLocked && value === "settings";
27110+
return `
27111+
<label class="settings-check-pill ${locked ? "is-locked" : ""}">
27112+
<input type="checkbox" data-setting-main-bar-item="${this._esc(value)}" ${selectedMainBar.has(value) || locked ? "checked" : ""} ${locked ? "disabled" : ""}>
2708727113
<span>${this._esc(label)}</span>
27088-
</label>`).join("")}
27114+
${locked ? `<span class="settings-fixed-badge">${this._esc(this._m("Fixed", "קבוע"))}</span>` : ""}
27115+
</label>`;
27116+
}).join("")}
2708927117
</div>
2709027118
<div class="settings-label">${this._m("Volume control (large screen only)", "בקרת ווליום (זמין רק במסך גדול)")}</div>
2709127119
<div class="settings-pills">
@@ -29056,6 +29084,10 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2905629084
const mainBarCheckbox = e.target?.closest?.("input[data-setting-main-bar-item]");
2905729085
if (mainBarCheckbox) {
2905829086
const item = mainBarCheckbox.dataset.settingMainBarItem;
29087+
if (!this._usesVisualSettings() && item === "settings") {
29088+
mainBarCheckbox.checked = true;
29089+
return;
29090+
}
2905929091
const current = new Set(this._mobileMainBarItems());
2906029092
if (mainBarCheckbox.checked) current.add(item); else current.delete(item);
2906129093
const next = Array.from(current);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "homeii-music-flow",
3-
"version": "5.1.5",
3+
"version": "5.1.6",
44
"description": "Premium Home Assistant Music Assistant dashboard card with a mobile-first visual player and built-in editor.",
55
"private": true,
66
"license": "MIT",

src/core/state/mobile-settings.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ export function normalizeMobileMainBarItems(items, {
7272
.filter((item) => !(usesVisualSettings && item === "settings"))
7373
.filter((item) => !(hidePlayers && item === "players"));
7474
const normalizedFallback = fallback.filter((item) => !(hidePlayers && item === "players"));
75-
return cleaned.length ? cleaned : normalizedFallback;
75+
const normalized = cleaned.length ? cleaned : normalizedFallback;
76+
if (!usesVisualSettings && !normalized.includes("settings")) normalized.push("settings");
77+
return normalized;
7678
}
7779

7880
export function normalizeMobileLibraryTabs(tabs, fallbackTabs = []) {

src/homeii-music-flow.js

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@
429429
_versionedAssetUrl(url) {
430430
const value = String(url || "").trim();
431431
if (!value || /^data:/i.test(value) || /[?&]v=/.test(value)) return value;
432-
const version = typeof HOMEII_CARD_VERSION === "string" ? HOMEII_CARD_VERSION : "5.1.5";
432+
const version = typeof HOMEII_CARD_VERSION === "string" ? HOMEII_CARD_VERSION : "5.1.6";
433433
return `${value}${value.includes("?") ? "&" : "?"}v=${encodeURIComponent(version)}`;
434434
}
435435

@@ -9685,9 +9685,9 @@ function ensureHaEditorComponents() {
96859685
} catch (_) {}
96869686
}
96879687

9688-
const HOMEII_CARD_VERSION = "5.1.5";
9689-
const HOMEII_BROWSER_EDITOR_TAG = "homeii-music-flow-browser-editor-v5150";
9690-
const HOMEII_MOBILE_EDITOR_TAG = "homeii-music-flow-editor-v5150";
9688+
const HOMEII_CARD_VERSION = "5.1.6";
9689+
const HOMEII_BROWSER_EDITOR_TAG = "homeii-music-flow-browser-editor-v5160";
9690+
const HOMEII_MOBILE_EDITOR_TAG = "homeii-music-flow-editor-v5160";
96919691

96929692
const HomeiiEditorLocale = Object.freeze({
96939693
isHebrewLanguageTag(value) {
@@ -9942,7 +9942,9 @@ const HomeiiMobileSettingsFoundation = Object.freeze({
99429942
.filter((item) => !(usesVisualSettings && item === "settings"))
99439943
.filter((item) => !(hidePlayers && item === "players"));
99449944
const normalizedFallback = fallback.filter((item) => !(hidePlayers && item === "players"));
9945-
return cleaned.length ? cleaned : normalizedFallback;
9945+
const normalized = cleaned.length ? cleaned : normalizedFallback;
9946+
if (!usesVisualSettings && !normalized.includes("settings")) normalized.push("settings");
9947+
return normalized;
99469948
},
99479949
normalizeMobileQuickActions(items, fallbackItems = []) {
99489950
const allowed = new Set(["timer", "like", "lyrics", "queue", "radio", "history", "info"]);
@@ -23195,6 +23197,27 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2319523197
margin:0;
2319623198
accent-color:var(--ma-accent);
2319723199
}
23200+
.settings-check-pill.is-locked {
23201+
cursor:default;
23202+
opacity:.94;
23203+
}
23204+
.settings-check-pill.is-locked input {
23205+
opacity:.78;
23206+
}
23207+
.settings-fixed-badge {
23208+
margin-inline-start:auto;
23209+
padding:3px 8px;
23210+
border-radius:999px;
23211+
background:rgba(245,166,35,.16);
23212+
color:var(--ma-accent);
23213+
font-size:11px;
23214+
font-weight:900;
23215+
letter-spacing:0;
23216+
}
23217+
.rtl .settings-fixed-badge {
23218+
margin-inline-start:0;
23219+
margin-inline-end:auto;
23220+
}
2319823221
.rtl .settings-check-pill {
2319923222
direction:rtl;
2320023223
justify-content:flex-start;
@@ -26972,6 +26995,7 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2697226995
const playerOptions = (this._state.players || []).map((player) => [player.entity_id, player.attributes?.friendly_name || player.entity_id]);
2697326996
const visibleMainBarOptions = mainBarOptions;
2697426997
const showStudioMainBarOption = this._controlRoomEnabled();
26998+
const settingsMainBarLocked = !this._usesVisualSettings();
2697526999
return `
2697627000
<div class="settings-shell">
2697727001
<div class="settings-group">
@@ -27081,11 +27105,15 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2708127105
<span>${this._esc(this._controlRoomLabel())}</span>
2708227106
</label>
2708327107
` : ``}
27084-
${visibleMainBarOptions.map(([value, label]) => `
27085-
<label class="settings-check-pill">
27086-
<input type="checkbox" data-setting-main-bar-item="${this._esc(value)}" ${selectedMainBar.has(value) ? "checked" : ""}>
27108+
${visibleMainBarOptions.map(([value, label]) => {
27109+
const locked = settingsMainBarLocked && value === "settings";
27110+
return `
27111+
<label class="settings-check-pill ${locked ? "is-locked" : ""}">
27112+
<input type="checkbox" data-setting-main-bar-item="${this._esc(value)}" ${selectedMainBar.has(value) || locked ? "checked" : ""} ${locked ? "disabled" : ""}>
2708727113
<span>${this._esc(label)}</span>
27088-
</label>`).join("")}
27114+
${locked ? `<span class="settings-fixed-badge">${this._esc(this._m("Fixed", "קבוע"))}</span>` : ""}
27115+
</label>`;
27116+
}).join("")}
2708927117
</div>
2709027118
<div class="settings-label">${this._m("Volume control (large screen only)", "בקרת ווליום (זמין רק במסך גדול)")}</div>
2709127119
<div class="settings-pills">
@@ -29056,6 +29084,10 @@ class HomeiiMusicFlowBaseCard extends HomeiiBaseMusicCard {
2905629084
const mainBarCheckbox = e.target?.closest?.("input[data-setting-main-bar-item]");
2905729085
if (mainBarCheckbox) {
2905829086
const item = mainBarCheckbox.dataset.settingMainBarItem;
29087+
if (!this._usesVisualSettings() && item === "settings") {
29088+
mainBarCheckbox.checked = true;
29089+
return;
29090+
}
2905929091
const current = new Set(this._mobileMainBarItems());
2906029092
if (mainBarCheckbox.checked) current.add(item); else current.delete(item);
2906129093
const next = Array.from(current);

tests/mobile-settings.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ describe("mobile settings foundation", () => {
8686
fallbackItems: ["actions", "players", "library", "settings"],
8787
})).toEqual(["theme"]);
8888

89+
expect(normalizeMobileMainBarItems(["actions"], {
90+
usesVisualSettings: false,
91+
hidePlayers: false,
92+
fallbackItems: ["actions"],
93+
})).toEqual(["actions", "settings"]);
94+
8995
expect(normalizeMobileMainBarItems([], {
9096
usesVisualSettings: false,
9197
hidePlayers: true,

0 commit comments

Comments
 (0)