Begun framework for frontend settings across devices
This commit is contained in:
parent
77554aa86c
commit
c7ce90883b
@ -398,13 +398,67 @@ const ConnectionMixin = (SuperClass) => {
|
|||||||
data: Object.assign(Object.assign({}, this.browsers[this.browserID]), newData),
|
data: Object.assign(Object.assign({}, this.browsers[this.browserID]), newData),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
get meta() {
|
get global_settings() {
|
||||||
if (!this.registered)
|
var _a;
|
||||||
return null;
|
const settings = {};
|
||||||
return this.browsers[this.browserID].meta;
|
const global = (_a = this._data.settings) !== null && _a !== void 0 ? _a : {};
|
||||||
|
for (const [k, v] of Object.entries(global)) {
|
||||||
|
if (v !== null)
|
||||||
|
settings[k] = v;
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
}
|
}
|
||||||
set meta(value) {
|
get user_settings() {
|
||||||
this._reregister({ meta: value });
|
var _a;
|
||||||
|
const settings = {};
|
||||||
|
const user = (_a = this._data.user_settings[this.hass.user.id]) !== null && _a !== void 0 ? _a : {};
|
||||||
|
for (const [k, v] of Object.entries(user)) {
|
||||||
|
if (v !== null)
|
||||||
|
settings[k] = v;
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
get browser_settings() {
|
||||||
|
var _a, _b;
|
||||||
|
const settings = {};
|
||||||
|
const browser = (_b = (_a = this.browsers[this.browserID]) === null || _a === void 0 ? void 0 : _a.settings) !== null && _b !== void 0 ? _b : {};
|
||||||
|
for (const [k, v] of Object.entries(browser)) {
|
||||||
|
if (v !== null)
|
||||||
|
settings[k] = v;
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
get settings() {
|
||||||
|
return Object.assign(Object.assign(Object.assign({}, this.global_settings), this.user_settings), this.browser_settings);
|
||||||
|
}
|
||||||
|
set_setting(key, value, level) {
|
||||||
|
var _a;
|
||||||
|
switch (level) {
|
||||||
|
case "global": {
|
||||||
|
this.connection.sendMessage({
|
||||||
|
type: "browser_mod/settings",
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "user": {
|
||||||
|
const user = this.hass.user.id;
|
||||||
|
this.connection.sendMessage({
|
||||||
|
type: "browser_mod/settings",
|
||||||
|
user,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "browser": {
|
||||||
|
const settings = (_a = this.browsers[this.browserID]) === null || _a === void 0 ? void 0 : _a.settings;
|
||||||
|
settings[key] = value;
|
||||||
|
this._reregister({ settings });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
get cameraEnabled() {
|
get cameraEnabled() {
|
||||||
if (!this.registered)
|
if (!this.registered)
|
||||||
@ -1769,6 +1823,25 @@ __decorate([
|
|||||||
customElements.define("popup-card", PopupCard);
|
customElements.define("popup-card", PopupCard);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
const AutoSettingsMixin = (SuperClass) => {
|
||||||
|
return class AutoSettingsMixinClass extends SuperClass {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._auto_settings_setup();
|
||||||
|
}
|
||||||
|
async _auto_settings_setup() {
|
||||||
|
await this.connectionPromise;
|
||||||
|
const settings = this.settings;
|
||||||
|
if (settings.sidebarPanelOrder) {
|
||||||
|
localStorage.setItem("sidebarPanelOrder", settings.sidebarPanelOrder);
|
||||||
|
}
|
||||||
|
if (settings.sidebarHiddenPanels) {
|
||||||
|
localStorage.setItem("sidebarHiddenPanels", settings.sidebarHiddenPanels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
- Fix nomenclature
|
- Fix nomenclature
|
||||||
@ -1802,11 +1875,13 @@ __decorate([
|
|||||||
x Redesign services to target devices
|
x Redesign services to target devices
|
||||||
- frontend editor for popup cards
|
- frontend editor for popup cards
|
||||||
- also screensavers
|
- also screensavers
|
||||||
- Tweaks
|
- Saved frontend settings
|
||||||
- Save sidebar
|
X Framework
|
||||||
- Save sidebar per user
|
x Save sidebar
|
||||||
- Kiosk mode
|
- Kiosk mode
|
||||||
- Kiosk mode per user
|
- Default panel?
|
||||||
|
- Screensaver?
|
||||||
|
- Tweaks
|
||||||
- Favicon templates
|
- Favicon templates
|
||||||
- Title templates
|
- Title templates
|
||||||
- Quickbar tweaks (ctrl+enter)?
|
- Quickbar tweaks (ctrl+enter)?
|
||||||
@ -1814,7 +1889,7 @@ __decorate([
|
|||||||
- Media_seek
|
- Media_seek
|
||||||
- Screensavers
|
- Screensavers
|
||||||
*/
|
*/
|
||||||
class BrowserMod extends ServicesMixin(PopupMixin(ActivityMixin(BrowserStateMixin(CameraMixin(MediaPlayerMixin(ScreenSaverMixin(FullyMixin(RequireInteractMixin(ConnectionMixin(EventTarget)))))))))) {
|
class BrowserMod extends ServicesMixin(PopupMixin(ActivityMixin(BrowserStateMixin(CameraMixin(MediaPlayerMixin(ScreenSaverMixin(AutoSettingsMixin(FullyMixin(RequireInteractMixin(ConnectionMixin(EventTarget))))))))))) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.connect();
|
this.connect();
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from typing import Any
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
@ -130,8 +131,30 @@ async def async_setup_connection(hass):
|
|||||||
dev = getBrowser(hass, browserID)
|
dev = getBrowser(hass, browserID)
|
||||||
dev.update(hass, msg.get("data", {}))
|
dev.update(hass, msg.get("data", {}))
|
||||||
|
|
||||||
|
@websocket_api.websocket_command(
|
||||||
|
{
|
||||||
|
vol.Required("type"): "browser_mod/settings",
|
||||||
|
vol.Required("key"): str,
|
||||||
|
vol.Optional("value"): vol.Any(int, str, bool, list, object, None),
|
||||||
|
vol.Optional("user"): str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@websocket_api.async_response
|
||||||
|
async def handle_settings(hass, connection, msg):
|
||||||
|
store = hass.data[DOMAIN]["store"]
|
||||||
|
if "user" in msg:
|
||||||
|
# Set user setting
|
||||||
|
await store.set_user_settings(
|
||||||
|
msg["user"], **{msg["key"]: msg.get("value", None)}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Set global setting
|
||||||
|
await store.set_global_settings(**{msg["key"]: msg.get("value", None)})
|
||||||
|
pass
|
||||||
|
|
||||||
async_register_command(hass, handle_connect)
|
async_register_command(hass, handle_connect)
|
||||||
async_register_command(hass, handle_register)
|
async_register_command(hass, handle_register)
|
||||||
async_register_command(hass, handle_unregister)
|
async_register_command(hass, handle_unregister)
|
||||||
async_register_command(hass, handle_reregister)
|
async_register_command(hass, handle_reregister)
|
||||||
async_register_command(hass, handle_update)
|
async_register_command(hass, handle_update)
|
||||||
|
async_register_command(hass, handle_settings)
|
||||||
|
@ -10,11 +10,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class BrowserStoreData:
|
class Settings:
|
||||||
last_seen = attr.ib(type=int, default=0)
|
kiosk = attr.ib(type=bool, default=None)
|
||||||
enabled = attr.ib(type=bool, default=False)
|
defaultPanel = attr.ib(type=str, default=None)
|
||||||
camera = attr.ib(type=bool, default=False)
|
sidebarPanelOrder = attr.ib(type=list, default=None)
|
||||||
meta = attr.ib(type=str, default="default")
|
sidebarHiddenPanels = attr.ib(type=list, default=None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, data):
|
def from_dict(cls, data):
|
||||||
@ -24,21 +24,54 @@ class BrowserStoreData:
|
|||||||
return attr.asdict(self)
|
return attr.asdict(self)
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s
|
||||||
|
class BrowserStoreData:
|
||||||
|
last_seen = attr.ib(type=int, default=0)
|
||||||
|
enabled = attr.ib(type=bool, default=False)
|
||||||
|
camera = attr.ib(type=bool, default=False)
|
||||||
|
settings = attr.ib(type=Settings, factory=Settings)
|
||||||
|
meta = attr.ib(type=str, default="default")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data):
|
||||||
|
settings = Settings.from_dict(data.get("settings", {}))
|
||||||
|
return cls(
|
||||||
|
**(
|
||||||
|
data
|
||||||
|
| {
|
||||||
|
"settings": settings,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def asdict(self):
|
||||||
|
return attr.asdict(self)
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class ConfigStoreData:
|
class ConfigStoreData:
|
||||||
browsers = attr.ib(type=dict[str:BrowserStoreData], factory=dict)
|
browsers = attr.ib(type=dict[str:BrowserStoreData], factory=dict)
|
||||||
version = attr.ib(type=str, default="2.0")
|
version = attr.ib(type=str, default="2.0")
|
||||||
|
settings = attr.ib(type=Settings, factory=Settings)
|
||||||
|
user_settings = attr.ib(type=dict[str:Settings], factory=dict)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, data={}):
|
def from_dict(cls, data={}):
|
||||||
browsers = {
|
browsers = {
|
||||||
k: BrowserStoreData.from_dict(v) for k, v in data["browsers"].items()
|
k: BrowserStoreData.from_dict(v)
|
||||||
|
for k, v in data.get("browsers", {}).items()
|
||||||
}
|
}
|
||||||
|
user_settings = {
|
||||||
|
k: Settings.from_dict(v) for k, v in data.get("user_settings", {}).items()
|
||||||
|
}
|
||||||
|
settings = Settings.from_dict(data.get("settings", {}))
|
||||||
return cls(
|
return cls(
|
||||||
**(
|
**(
|
||||||
data
|
data
|
||||||
| {
|
| {
|
||||||
"browsers": browsers,
|
"browsers": browsers,
|
||||||
|
"settings": settings,
|
||||||
|
"user_settings": user_settings,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -97,3 +130,19 @@ class BrowserModStore:
|
|||||||
async def delete_browser(self, browserID):
|
async def delete_browser(self, browserID):
|
||||||
del self.data.browsers[browserID]
|
del self.data.browsers[browserID]
|
||||||
await self.updated()
|
await self.updated()
|
||||||
|
|
||||||
|
def get_user_settings(self, name):
|
||||||
|
return self.data.user_settings.get(name, Settings())
|
||||||
|
|
||||||
|
async def set_user_settings(self, name, **data):
|
||||||
|
settings = self.data.user_settings.get(name, Settings())
|
||||||
|
settings.__dict__.update(data)
|
||||||
|
self.data.user_settings[name] = settings
|
||||||
|
await self.updated()
|
||||||
|
|
||||||
|
def get_global_settings(self):
|
||||||
|
return self.data.settings
|
||||||
|
|
||||||
|
async def set_global_settings(self, **data):
|
||||||
|
self.data.settings.__dict__.update(data)
|
||||||
|
await self.updated()
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
// Loads in ha-config-dashboard which is used to copy styling
|
|
||||||
// Also provides ha-settings-row
|
|
||||||
export const loadDevTools = async () => {
|
|
||||||
if (customElements.get("ha-config-dashboard")) return;
|
|
||||||
|
|
||||||
await customElements.whenDefined("partial-panel-resolver");
|
|
||||||
const ppResolver = document.createElement("partial-panel-resolver");
|
|
||||||
const routes = (ppResolver as any).getRoutes([
|
|
||||||
{
|
|
||||||
component_name: "config",
|
|
||||||
url_path: "a",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
await routes?.routes?.a?.load?.();
|
|
||||||
await customElements.whenDefined("ha-panel-config");
|
|
||||||
const configRouter = document.createElement("ha-panel-config");
|
|
||||||
await (configRouter as any)?.routerOptions?.routes?.dashboard?.load?.(); // Load ha-config-dashboard
|
|
||||||
await (configRouter as any)?.routerOptions?.routes?.cloud?.load?.(); // Load ha-settings-row
|
|
||||||
await customElements.whenDefined("ha-config-dashboard");
|
|
||||||
};
|
|
@ -1,6 +1,9 @@
|
|||||||
import { LitElement, html, css } from "lit";
|
import { LitElement, html, css } from "lit";
|
||||||
import { property } from "lit/decorators.js";
|
import { property } from "lit/decorators.js";
|
||||||
import { loadDevTools } from "./helpers";
|
import { loadDevTools } from "../helpers";
|
||||||
|
import { loadHaForm } from "../helpers";
|
||||||
|
|
||||||
|
import "./settings-card";
|
||||||
|
|
||||||
const bmWindow = window as any;
|
const bmWindow = window as any;
|
||||||
|
|
||||||
@ -292,25 +295,9 @@ loadDevTools().then(() => {
|
|||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
|
||||||
<ha-card outlined header="Tweaks">
|
<browser-mod-settings-card
|
||||||
<div class="card-content">
|
.hass=${this.hass}
|
||||||
<ha-settings-row>
|
></browser-mod-settings-card>
|
||||||
<span slot="heading">User sidebar</span>
|
|
||||||
<span slot="description"
|
|
||||||
>Save sidebar as default for current user
|
|
||||||
(${this.hass.user.name})</span
|
|
||||||
>
|
|
||||||
<mwc-button>Save</mwc-button>
|
|
||||||
</ha-settings-row>
|
|
||||||
<ha-settings-row>
|
|
||||||
<span slot="heading">Global sidebar</span>
|
|
||||||
<span slot="description"
|
|
||||||
>Save sidebar as default for all users</span
|
|
||||||
>
|
|
||||||
<mwc-button>Save</mwc-button>
|
|
||||||
</ha-settings-row>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
</ha-config-section>
|
</ha-config-section>
|
||||||
</ha-app-layout>
|
</ha-app-layout>
|
||||||
`;
|
`;
|
||||||
|
160
js/config_panel/settings-card.ts
Normal file
160
js/config_panel/settings-card.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { LitElement, html, css } from "lit";
|
||||||
|
import { property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
|
class BrowserModSettingsCard extends LitElement {
|
||||||
|
@property() hass;
|
||||||
|
|
||||||
|
@state() _selectedTab = 0;
|
||||||
|
|
||||||
|
firstUpdated() {
|
||||||
|
window.browser_mod.addEventListener("browser-mod-config-update", () =>
|
||||||
|
this.requestUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleSwitchTab(ev: CustomEvent) {
|
||||||
|
this._selectedTab = parseInt(ev.detail.index, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const level = ["browser", "user", "global"][this._selectedTab];
|
||||||
|
return html`
|
||||||
|
<ha-card header="Auto settings" outlined>
|
||||||
|
<div class="card-content">
|
||||||
|
<mwc-tab-bar
|
||||||
|
.activeIndex=${this._selectedTab}
|
||||||
|
@MDCTabBar:activated=${this._handleSwitchTab}
|
||||||
|
>
|
||||||
|
<mwc-tab .label=${"Browser"}></mwc-tab>
|
||||||
|
<mwc-tab .label=${"User (" + this.hass.user.name + ")"}></mwc-tab>
|
||||||
|
<mwc-tab .label=${"Global"}></mwc-tab>
|
||||||
|
</mwc-tab-bar>
|
||||||
|
|
||||||
|
${this._render_settings(level)}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
_render_settings(level) {
|
||||||
|
const global = window.browser_mod.global_settings;
|
||||||
|
const user = window.browser_mod.user_settings;
|
||||||
|
const browser = window.browser_mod.browser_settings;
|
||||||
|
const current = { global, user, browser }[level];
|
||||||
|
|
||||||
|
const DESC_BOOLEAN = (val) =>
|
||||||
|
({ true: "Enabled", false: "Disabled", undefined: "unset" }[String(val)]);
|
||||||
|
const DESC_SET_UNSET = (val) => (val === undefined ? "Unset" : "Set");
|
||||||
|
const OVERRIDDEN = (key) => {
|
||||||
|
if (level !== "browser" && browser[key] !== undefined)
|
||||||
|
return html`<br />Overridden by browser setting`;
|
||||||
|
if (level === "global" && user[key] !== undefined)
|
||||||
|
return html`<br />Overridden by user setting`;
|
||||||
|
};
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-settings-row>
|
||||||
|
<span slot="heading">Kiosk mode</span>
|
||||||
|
<span slot="description"> Hide sidebar and header </span>
|
||||||
|
Currenty: ${DESC_BOOLEAN(current.kiosk)} ${OVERRIDDEN("kiosk")}
|
||||||
|
</ha-settings-row>
|
||||||
|
<ha-settings-row>
|
||||||
|
<mwc-button
|
||||||
|
@click=${() => window.browser_mod.set_setting("kiosk", true, level)}
|
||||||
|
>
|
||||||
|
Enable
|
||||||
|
</mwc-button>
|
||||||
|
<mwc-button
|
||||||
|
@click=${() => window.browser_mod.set_setting("kiosk", false, level)}
|
||||||
|
>
|
||||||
|
Disable
|
||||||
|
</mwc-button>
|
||||||
|
<mwc-button
|
||||||
|
@click=${() =>
|
||||||
|
window.browser_mod.set_setting("kiosk", undefined, level)}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</mwc-button>
|
||||||
|
</ha-settings-row>
|
||||||
|
|
||||||
|
<ha-settings-row>
|
||||||
|
<span slot="heading">Sidebar order</span>
|
||||||
|
<span slot="description">Order and visibility of sidebar buttons</span>
|
||||||
|
Currenty: ${DESC_SET_UNSET(current.sidebarPanelOrder)}
|
||||||
|
${OVERRIDDEN("sidebarPanelOrder")}
|
||||||
|
</ha-settings-row>
|
||||||
|
<ha-settings-row>
|
||||||
|
<mwc-button
|
||||||
|
@click=${() => {
|
||||||
|
window.browser_mod.set_setting(
|
||||||
|
"sidebarPanelOrder",
|
||||||
|
localStorage.getItem("sidebarPanelOrder"),
|
||||||
|
level
|
||||||
|
);
|
||||||
|
window.browser_mod.set_setting(
|
||||||
|
"sidebarHiddenPanels",
|
||||||
|
localStorage.getItem("sidebarHiddenPanels"),
|
||||||
|
level
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Set
|
||||||
|
</mwc-button>
|
||||||
|
<mwc-button
|
||||||
|
@click=${() => {
|
||||||
|
window.browser_mod.set_setting(
|
||||||
|
"sidebarPanelOrder",
|
||||||
|
undefined,
|
||||||
|
level
|
||||||
|
);
|
||||||
|
window.browser_mod.set_setting(
|
||||||
|
"sidebarHiddenPanels",
|
||||||
|
undefined,
|
||||||
|
level
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</mwc-button>
|
||||||
|
</ha-settings-row>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
_render_user() {
|
||||||
|
return html`
|
||||||
|
User
|
||||||
|
<ha-settings-row>
|
||||||
|
<span slot="heading">Kiosk mode</span>
|
||||||
|
<span slot="description"> Hide sidebar and header </span>
|
||||||
|
Currenty: Overridden
|
||||||
|
</ha-settings-row>
|
||||||
|
<ha-settings-row>
|
||||||
|
<span slot="heading">Set screensaver</span>
|
||||||
|
<span slot="description"> Set screensaver card </span>
|
||||||
|
<mwc-button>Enable</mwc-button>
|
||||||
|
<mwc-button>Disable</mwc-button>
|
||||||
|
<mwc-button>Clear</mwc-button>
|
||||||
|
</ha-settings-row>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
_render_browser() {
|
||||||
|
return html`
|
||||||
|
Browser
|
||||||
|
<ha-settings-row>
|
||||||
|
<span slot="heading">Kiosk mode</span>
|
||||||
|
<span slot="description"> Hide sidebar and header </span>
|
||||||
|
Currenty: Overridden
|
||||||
|
</ha-settings-row>
|
||||||
|
<ha-settings-row>
|
||||||
|
<span slot="heading">Set screensaver</span>
|
||||||
|
<span slot="description"> Set screensaver card </span>
|
||||||
|
<mwc-button>Enable</mwc-button>
|
||||||
|
<mwc-button>Disable</mwc-button>
|
||||||
|
<mwc-button>Clear</mwc-button>
|
||||||
|
</ha-settings-row>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("browser-mod-settings-card", BrowserModSettingsCard);
|
@ -85,3 +85,24 @@ export const loadHaForm = async () => {
|
|||||||
if (!card) return;
|
if (!card) return;
|
||||||
await card.getConfigElement();
|
await card.getConfigElement();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Loads in ha-config-dashboard which is used to copy styling
|
||||||
|
// Also provides ha-settings-row
|
||||||
|
export const loadDevTools = async () => {
|
||||||
|
if (customElements.get("ha-config-dashboard")) return;
|
||||||
|
|
||||||
|
await customElements.whenDefined("partial-panel-resolver");
|
||||||
|
const ppResolver = document.createElement("partial-panel-resolver");
|
||||||
|
const routes = (ppResolver as any).getRoutes([
|
||||||
|
{
|
||||||
|
component_name: "config",
|
||||||
|
url_path: "a",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
await routes?.routes?.a?.load?.();
|
||||||
|
await customElements.whenDefined("ha-panel-config");
|
||||||
|
const configRouter = document.createElement("ha-panel-config");
|
||||||
|
await (configRouter as any)?.routerOptions?.routes?.dashboard?.load?.(); // Load ha-config-dashboard
|
||||||
|
await (configRouter as any)?.routerOptions?.routes?.cloud?.load?.(); // Load ha-settings-row
|
||||||
|
await customElements.whenDefined("ha-config-dashboard");
|
||||||
|
};
|
||||||
|
25
js/plugin/auto-settings.ts
Normal file
25
js/plugin/auto-settings.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export const AutoSettingsMixin = (SuperClass) => {
|
||||||
|
return class AutoSettingsMixinClass extends SuperClass {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._auto_settings_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
async _auto_settings_setup() {
|
||||||
|
await this.connectionPromise;
|
||||||
|
|
||||||
|
const settings = this.settings;
|
||||||
|
|
||||||
|
if (settings.sidebarPanelOrder) {
|
||||||
|
localStorage.setItem("sidebarPanelOrder", settings.sidebarPanelOrder);
|
||||||
|
}
|
||||||
|
if (settings.sidebarHiddenPanels) {
|
||||||
|
localStorage.setItem(
|
||||||
|
"sidebarHiddenPanels",
|
||||||
|
settings.sidebarHiddenPanels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
@ -119,12 +119,66 @@ export const ConnectionMixin = (SuperClass) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get meta() {
|
get global_settings() {
|
||||||
if (!this.registered) return null;
|
const settings = {};
|
||||||
return this.browsers[this.browserID].meta;
|
const global = this._data.settings ?? {};
|
||||||
|
for (const [k, v] of Object.entries(global)) {
|
||||||
|
if (v !== null) settings[k] = v;
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
}
|
}
|
||||||
set meta(value) {
|
get user_settings() {
|
||||||
this._reregister({ meta: value });
|
const settings = {};
|
||||||
|
const user = this._data.user_settings[this.hass.user.id] ?? {};
|
||||||
|
for (const [k, v] of Object.entries(user)) {
|
||||||
|
if (v !== null) settings[k] = v;
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
get browser_settings() {
|
||||||
|
const settings = {};
|
||||||
|
const browser = this.browsers[this.browserID]?.settings ?? {};
|
||||||
|
for (const [k, v] of Object.entries(browser)) {
|
||||||
|
if (v !== null) settings[k] = v;
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
get settings() {
|
||||||
|
return {
|
||||||
|
...this.global_settings,
|
||||||
|
...this.user_settings,
|
||||||
|
...this.browser_settings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
set_setting(key, value, level) {
|
||||||
|
switch (level) {
|
||||||
|
case "global": {
|
||||||
|
this.connection.sendMessage({
|
||||||
|
type: "browser_mod/settings",
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "user": {
|
||||||
|
const user = this.hass.user.id;
|
||||||
|
this.connection.sendMessage({
|
||||||
|
type: "browser_mod/settings",
|
||||||
|
user,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "browser": {
|
||||||
|
const settings = this.browsers[this.browserID]?.settings;
|
||||||
|
settings[key] = value;
|
||||||
|
this._reregister({ settings });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get cameraEnabled() {
|
get cameraEnabled() {
|
||||||
|
@ -14,6 +14,7 @@ import "./popups";
|
|||||||
import { PopupMixin } from "./popups";
|
import { PopupMixin } from "./popups";
|
||||||
import pjson from "../../package.json";
|
import pjson from "../../package.json";
|
||||||
import "./popup-card";
|
import "./popup-card";
|
||||||
|
import { AutoSettingsMixin } from "./auto-settings";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
@ -48,11 +49,13 @@ import "./popup-card";
|
|||||||
x Redesign services to target devices
|
x Redesign services to target devices
|
||||||
- frontend editor for popup cards
|
- frontend editor for popup cards
|
||||||
- also screensavers
|
- also screensavers
|
||||||
- Tweaks
|
- Saved frontend settings
|
||||||
- Save sidebar
|
X Framework
|
||||||
- Save sidebar per user
|
x Save sidebar
|
||||||
- Kiosk mode
|
- Kiosk mode
|
||||||
- Kiosk mode per user
|
- Default panel?
|
||||||
|
- Screensaver?
|
||||||
|
- Tweaks
|
||||||
- Favicon templates
|
- Favicon templates
|
||||||
- Title templates
|
- Title templates
|
||||||
- Quickbar tweaks (ctrl+enter)?
|
- Quickbar tweaks (ctrl+enter)?
|
||||||
@ -67,7 +70,9 @@ export class BrowserMod extends ServicesMixin(
|
|||||||
CameraMixin(
|
CameraMixin(
|
||||||
MediaPlayerMixin(
|
MediaPlayerMixin(
|
||||||
ScreenSaverMixin(
|
ScreenSaverMixin(
|
||||||
FullyMixin(RequireInteractMixin(ConnectionMixin(EventTarget)))
|
AutoSettingsMixin(
|
||||||
|
FullyMixin(RequireInteractMixin(ConnectionMixin(EventTarget)))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user