Compare commits

...
18 changed files with 85 additions and 24 deletions

No files matched your search

+22 -3
View File
@@ -2,10 +2,14 @@
import fs from "fs-extra";
import gulp from "gulp";
import { createHash } from "node:crypto";
import { createRequire } from "node:module";
import path from "path";
import paths from "../paths.cjs";
import { ensureMapAssets, mapAssetsDir } from "./map-assets.js";
const require = createRequire(import.meta.url);
const npmPath = (...parts) =>
path.resolve(paths.root_dir, "node_modules", ...parts);
const polyPath = (...parts) => path.resolve(paths.root_dir, ...parts);
@@ -83,9 +87,24 @@ async function copyMapPanel(staticDir) {
function copyZXingWasm(staticDir) {
const staticPath = genStaticPath(staticDir);
copyFileDir(
npmPath("zxing-wasm/dist/reader/zxing_reader.wasm"),
staticPath("js")
// Resolve through barcode-detector, the wasm must match the zxing-wasm JS it bundles
const zxingWasm = createRequire(require.resolve("barcode-detector")).resolve(
"zxing-wasm/reader/zxing_reader.wasm"
);
const {
ZXING_WASM_SHA256,
ZXING_WASM_VERSION,
} = require("barcode-detector/pure");
const wasm = fs.readFileSync(zxingWasm);
if (createHash("sha256").update(wasm).digest("hex") !== ZXING_WASM_SHA256) {
throw new Error(
`${zxingWasm} does not match the zxing-wasm ${ZXING_WASM_VERSION} bundled in barcode-detector`
);
}
// Versioned file name, see locateFile in ha-qr-scanner
fs.outputFileSync(
staticPath("js", `zxing_reader-${ZXING_WASM_VERSION}.wasm`),
wasm
);
}
+3 -1
View File
@@ -153,7 +153,9 @@ gulp.task("rspack-watch-app", () => {
: createAppConfig({ isProdBuild: false, latestBuild: true })
).watch({ poll: isWsl }, doneHandler());
gulp.watch(
path.join(paths.translations_src, "en.json"),
// Watch the folder via a glob; git replaces en.json on checkout/stash,
// which can permanently drop a watch on the file itself
path.join(paths.translations_src, "*.json"),
gulp.series("build-translations", "copy-translations-app")
);
});
+16 -3
View File
@@ -40,6 +40,21 @@ const TOOLCHAIN_PACKAGES = [
"caniuse-lite",
];
// Not direct dependencies: read the copy the package that loads them uses.
const TOOLCHAIN_PACKAGE_PARENTS = {
terser: "terser-webpack-plugin",
"caniuse-lite": "browserslist",
};
const toolchainVersion = (pkg) => {
const parent = TOOLCHAIN_PACKAGE_PARENTS[pkg];
const lookup = parent && [
path.dirname(require.resolve(`${parent}/package.json`)),
];
return require(require.resolve(`${pkg}/package.json`, { paths: lookup }))
.version;
};
// Our own build logic — the config, loaders and babel plugins. Their contents
// (not their paths) go into the cache version, so a change invalidates the
// cache the same way `buildDependencies` would, but without tying validity to
@@ -63,9 +78,7 @@ const PATCHES_DIR = path.join(paths.root_dir, "patches");
// stays valid when reused on a different machine or checkout path.
const cacheVersion = () => {
const parts = [
...TOOLCHAIN_PACKAGES.map(
(pkg) => `${pkg}@${require(`${pkg}/package.json`).version}`
),
...TOOLCHAIN_PACKAGES.map((pkg) => `${pkg}@${toolchainVersion(pkg)}`),
...CONFIG_FILES.map(
(file) => `${path.basename(file)}:${fs.readFileSync(file, "utf8")}`
),
+3 -2
View File
@@ -133,14 +133,15 @@
"workbox-routing": "7.4.1",
"workbox-strategies": "7.4.1",
"xss": "1.0.15",
"zrender": "6.1.0",
"zxing-wasm": "3.1.5"
"zrender": "6.1.0"
},
"devDependencies": {
"@ampproject/remapping": "2.3.0",
"@babel/core": "8.0.7",
"@babel/helper-compilation-targets": "8.0.7",
"@babel/helper-define-polyfill-provider": "1.0.0",
"@babel/plugin-transform-class-properties": "8.0.1",
"@babel/plugin-transform-private-methods": "8.0.1",
"@babel/plugin-transform-runtime": "8.0.6",
"@babel/preset-env": "8.0.7",
"@bundle-stats/plugin-webpack-filter": "4.22.3",
+6 -11
View File
@@ -462,9 +462,6 @@ importers:
zrender:
specifier: 6.1.0
version: 6.1.0
zxing-wasm:
specifier: 3.1.5
version: 3.1.5
devDependencies:
'@ampproject/remapping':
specifier: 2.3.0
@@ -478,6 +475,12 @@ importers:
'@babel/helper-define-polyfill-provider':
specifier: 1.0.0
version: 1.0.0(@babel/[email protected])
'@babel/plugin-transform-class-properties':
specifier: 8.0.1
version: 8.0.1(@babel/[email protected])
'@babel/plugin-transform-private-methods':
specifier: 8.0.1
version: 8.0.1(@babel/[email protected])
'@babel/plugin-transform-runtime':
specifier: 8.0.6
version: 8.0.6(@babel/[email protected])
@@ -7836,9 +7839,6 @@ packages:
[email protected]:
resolution: {integrity: sha512-3lC9BJk4fR5ZJxcGjb0hVnDFOW7KpLXHIebiBmVd4FDRQZVeObztoTKxRUPxlWwSgxrMRONK0u50hBD1aTYEKg==}
[email protected]:
resolution: {integrity: sha512-jmxXvTCR/qZxMz2XwR6V+nL2BlDTD1aux7ZWSH9BV77TG9u4k0VyHba/NCCHBHJ60Wg6VV0QL/SMlJczKhJI4w==}
snapshots:
'@ampproject/[email protected]':
@@ -15838,8 +15838,3 @@ snapshots:
dependencies:
'@types/emscripten': 1.41.6
type-fest: 5.10.0
[email protected]:
dependencies:
'@types/emscripten': 1.41.6
type-fest: 5.10.0
+5
View File
@@ -98,6 +98,11 @@
"groupName": "date-fns",
"matchPackageNames": ["date-fns", "date-fns-tz"]
},
{
"description": "Group ECharts with zrender, which we import directly and must match the version echarts depends on",
"groupName": "echarts",
"matchPackageNames": ["echarts", "zrender"]
},
{
"description": "Group formatjs monorepo package",
"groupName": "formatjs",
-1
View File
@@ -14,7 +14,6 @@ export type LocalizeKeys =
| `ui.card.weather.attributes.${string}`
| `ui.card.weather.cardinal_direction.${string}`
| `ui.card.lawn_mower.actions.${string}`
| `ui.common.${string}`
| `ui.components.calendar.event.rrule.${string}`
| `ui.components.selectors.file.${string}`
| `ui.dialogs.entity_registry.editor.${string}`
+5
View File
@@ -38,6 +38,10 @@ export class HaBaseTimeInput extends LitElement {
*/
@property() label?: string;
/** Accessible name for the input when it has no visible label. */
@property({ attribute: "accessible-label" })
public accessibleLabel?: string;
/**
* Helper for the input
*/
@@ -178,6 +182,7 @@ export class HaBaseTimeInput extends LitElement {
class="time-input-wrap"
role="group"
aria-labelledby=${ifDefined(this.label ? "label" : undefined)}
aria-label=${ifDefined(this.label ? undefined : this.accessibleLabel)}
>
${
this.enableSign
+5
View File
@@ -50,6 +50,10 @@ export class HaDateInput extends LitElement {
@property() public label?: string;
/** Accessible name for the input when it has no visible label. */
@property({ attribute: "accessible-label" })
public accessibleLabel?: string;
@property() public helper?: string;
@property({ attribute: "can-clear", type: Boolean }) public canClear = false;
@@ -65,6 +69,7 @@ export class HaDateInput extends LitElement {
.label=${this.label ?? ""}
.hint=${this.helper ?? ""}
.disabled=${this.disabled}
.accessibleLabel=${this.accessibleLabel}
readonly
@click=${this._openDialog}
@keydown=${this._keyDown}
+3 -2
View File
@@ -7,7 +7,7 @@ import { customElement, property, query, state } from "lit/decorators";
// and "qr-scanner" defaults to a suboptimal implementation if it is not available.
// The following import makes a better implementation available that is based on a
// WebAssembly port of ZXing:
import { prepareZXingModule } from "barcode-detector";
import { prepareZXingModule, ZXING_WASM_VERSION } from "barcode-detector";
import type QrScanner from "qr-scanner";
import { consume } from "../common/decorators/consume";
import { consumeLocalize } from "../common/decorators/consume-context-entry";
@@ -29,7 +29,8 @@ prepareZXingModule({
overrides: {
locateFile: (path: string, prefix: string) => {
if (path.endsWith(".wasm")) {
return "/static/js/zxing_reader.wasm";
// Versioned, /static is cached for a month and the glue only works with its own wasm
return `/static/js/zxing_reader-${ZXING_WASM_VERSION}.wasm`;
}
return prefix + path;
},
+5
View File
@@ -15,6 +15,10 @@ export class HaTimeInput extends LitElement {
@property() public label?: string;
/** Accessible name for the input when it has no visible label. */
@property({ attribute: "accessible-label" })
public accessibleLabel?: string;
@property() public helper?: string;
@property({ type: Boolean }) public disabled = false;
@@ -61,6 +65,7 @@ export class HaTimeInput extends LitElement {
return html`
<ha-base-time-input
.label=${this.label}
.accessibleLabel=${this.accessibleLabel}
.hours=${hours}
.minutes=${minutes}
.seconds=${seconds}
@@ -441,7 +441,7 @@ class SupervisorAppConfig extends DirtyStateProviderMixin<
text: this.hass.localize(
"ui.panel.config.apps.configuration.confirm.reset_options.text"
),
confirmText: this.hass.localize("ui.common.reset_options"),
confirmText: this.hass.localize("ui.common.reset"),
dismissText: this.hass.localize("ui.common.cancel"),
destructive: true,
});
@@ -44,11 +44,14 @@ class HuiDateEntityRow extends LitElement implements LovelaceRow {
const unavailable = stateObj.state === UNAVAILABLE;
const name = this.hass.formatEntityName(stateObj, this._config.name);
return html`
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
<ha-date-input
.locale=${this.hass.locale}
.disabled=${unavailable}
.accessibleLabel=${name}
.value=${
stateObj.state === UNAVAILABLE || stateObj.state === UNKNOWN
? undefined
@@ -72,6 +72,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
</ha-date-input>
<ha-time-input
.value=${time}
.accessibleLabel=${name}
.disabled=${unavailable}
.locale=${this.hass.locale}
@value-changed=${this._timeChanged}
@@ -68,6 +68,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
? html`
<ha-date-input
.label=${stateObj.attributes.has_time ? name : undefined}
.accessibleLabel=${stateObj.attributes.has_time ? undefined : name}
.locale=${this.hass.locale}
.disabled=${stateObj.state === UNAVAILABLE}
.value=${stateToIsoDateString(stateObj)}
@@ -88,6 +89,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
? stateObj.state.split(" ")[1]
: stateObj.state
}
.accessibleLabel=${name}
.locale=${this.hass.locale}
.disabled=${stateObj.state === UNAVAILABLE}
@value-changed=${this._timeChanged}
@@ -44,6 +44,8 @@ class HuiTimeEntityRow extends LitElement implements LovelaceRow {
const unavailable = stateObj.state === UNAVAILABLE;
const name = this.hass.formatEntityName(stateObj, this._config.name);
return html`
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
<ha-time-input
@@ -52,6 +54,7 @@ class HuiTimeEntityRow extends LitElement implements LovelaceRow {
? undefined
: stateObj.state
}
.accessibleLabel=${name}
.locale=${this.hass.locale}
.disabled=${unavailable}
@value-changed=${this._timeChanged}
+1
View File
@@ -29,6 +29,7 @@ const marketplaceTableParams = {
source: "string?",
sort: "string?",
direction: "string?",
group: "string?",
} satisfies Redirect["params"];
export const getMyRedirects = (): Redirects => ({
+1
View File
@@ -500,6 +500,7 @@
"submit": "Submit",
"rename": "Rename",
"reset": "Reset",
"retry": "Retry",
"search": "[%key:ui::components::data-table::search%]",
"ok": "OK",
"yes": "Yes",