Compare commits
1 Commits
lit-grid-l
...
restore-co
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3272c32f87 |
4
.dockerignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
hass_frontend
|
||||||
|
hass_frontend_es5
|
||||||
|
.git
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
"airbnb-typescript/base",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"airbnb-typescript/base",
|
||||||
"plugin:wc/recommended",
|
"plugin:wc/recommended",
|
||||||
"plugin:lit/recommended",
|
"plugin:lit/recommended",
|
||||||
"prettier",
|
"prettier",
|
||||||
@@ -45,16 +45,16 @@
|
|||||||
"func-names": 0,
|
"func-names": 0,
|
||||||
"prefer-arrow-callback": 0,
|
"prefer-arrow-callback": 0,
|
||||||
"no-underscore-dangle": 0,
|
"no-underscore-dangle": 0,
|
||||||
|
"no-var": 0,
|
||||||
"strict": 0,
|
"strict": 0,
|
||||||
"prefer-spread": 0,
|
"prefer-spread": 0,
|
||||||
"no-plusplus": 0,
|
"no-plusplus": 0,
|
||||||
"no-bitwise": 2,
|
"no-bitwise": 0,
|
||||||
"comma-dangle": 0,
|
"comma-dangle": 0,
|
||||||
"vars-on-top": 0,
|
"vars-on-top": 0,
|
||||||
"no-continue": 0,
|
"no-continue": 0,
|
||||||
"no-param-reassign": 0,
|
"no-param-reassign": 0,
|
||||||
"no-multi-assign": 0,
|
"no-multi-assign": 0,
|
||||||
"no-console": 2,
|
|
||||||
"radix": 0,
|
"radix": 0,
|
||||||
"no-alert": 0,
|
"no-alert": 0,
|
||||||
"no-return-await": 0,
|
"no-return-await": 0,
|
||||||
@@ -75,16 +75,13 @@
|
|||||||
"object-curly-newline": 0,
|
"object-curly-newline": 0,
|
||||||
"default-case": 0,
|
"default-case": 0,
|
||||||
"wc/no-self-class": 0,
|
"wc/no-self-class": 0,
|
||||||
"no-shadow": 0,
|
|
||||||
"@typescript-eslint/camelcase": 0,
|
"@typescript-eslint/camelcase": 0,
|
||||||
"@typescript-eslint/ban-ts-comment": 0,
|
"@typescript-eslint/ban-ts-ignore": 0,
|
||||||
"@typescript-eslint/no-use-before-define": 0,
|
"@typescript-eslint/no-use-before-define": 0,
|
||||||
"@typescript-eslint/no-non-null-assertion": 0,
|
"@typescript-eslint/no-non-null-assertion": 0,
|
||||||
"@typescript-eslint/no-explicit-any": 0,
|
"@typescript-eslint/no-explicit-any": 0,
|
||||||
"@typescript-eslint/no-unused-vars": 0,
|
"@typescript-eslint/no-unused-vars": 0,
|
||||||
"@typescript-eslint/explicit-function-return-type": 0,
|
"@typescript-eslint/explicit-function-return-type": 0
|
||||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
|
||||||
"@typescript-eslint/no-shadow": ["error"]
|
|
||||||
},
|
},
|
||||||
"plugins": ["disable", "import", "lit", "prettier", "@typescript-eslint"],
|
"plugins": ["disable", "import", "lit", "prettier", "@typescript-eslint"],
|
||||||
"processor": "disable/disable"
|
"processor": "disable/disable"
|
||||||
|
2
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
@@ -51,7 +51,7 @@ DO NOT DELETE ANY TEXT from this template! Otherwise, your issue may be closed w
|
|||||||
<!--
|
<!--
|
||||||
Provide details about the versions you are using, which helps us reproducing
|
Provide details about the versions you are using, which helps us reproducing
|
||||||
and finding the issue quicker. Version information is found in the
|
and finding the issue quicker. Version information is found in the
|
||||||
Home Assistant frontend: Configuration -> Info.
|
Home Assistant frontend: Developer tools -> Info.
|
||||||
|
|
||||||
Browser version and operating system is important! Please try to replicate
|
Browser version and operating system is important! Please try to replicate
|
||||||
your issue in a different browser and be sure to include your findings.
|
your issue in a different browser and be sure to include your findings.
|
||||||
|
26
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: Request a feature for the UI, Frontend or Lovelace
|
||||||
|
about: Request an new feature for the Home Assistant frontend.
|
||||||
|
labels: feature request
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
DO NOT DELETE ANY TEXT from this template!
|
||||||
|
Otherwise, your request may be closed without comment.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## The request
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Describe to our maintainers, the feature you would like to be added.
|
||||||
|
Please be clear and concise and, if possible, provide a screenshot or mockup.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## The alternatives
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Are you currently using, or have you considered alternatives?
|
||||||
|
If so, could you please describe those?
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Additional information
|
3
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,5 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Request a feature for the UI, Frontend or Lovelace
|
|
||||||
url: https://github.com/home-assistant/frontend/discussions/category_choices
|
|
||||||
about: Request an new feature for the Home Assistant frontend.
|
|
||||||
- name: Report a bug that is NOT related to the UI, Frontend or Lovelace
|
- name: Report a bug that is NOT related to the UI, Frontend or Lovelace
|
||||||
url: https://github.com/home-assistant/core/issues
|
url: https://github.com/home-assistant/core/issues
|
||||||
about: This is the issue tracker for our frontend. Please report other issues with the backend repository.
|
about: This is the issue tracker for our frontend. Please report other issues with the backend repository.
|
||||||
|
6
.github/workflows/ci.yaml
vendored
@@ -34,8 +34,10 @@ jobs:
|
|||||||
run: yarn install
|
run: yarn install
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
- name: Build resources
|
- name: Build icons
|
||||||
run: ./node_modules/.bin/gulp gen-icons-json build-translations gather-gallery-demos
|
run: ./node_modules/.bin/gulp gen-icons-json
|
||||||
|
- name: Build translations
|
||||||
|
run: ./node_modules/.bin/gulp build-translations
|
||||||
- name: Run eslint
|
- name: Run eslint
|
||||||
run: ./node_modules/.bin/eslint '{**/src,src}/**/*.{js,ts,html}' --ignore-path .gitignore
|
run: ./node_modules/.bin/eslint '{**/src,src}/**/*.{js,ts,html}' --ignore-path .gitignore
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
|
60
.github/workflows/codeql-analysis.yml
vendored
@@ -1,60 +0,0 @@
|
|||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [dev, master]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [dev]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# Override automatic language detection by changing the below list
|
|
||||||
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
|
|
||||||
language: ['javascript']
|
|
||||||
# Learn more...
|
|
||||||
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
# We must fetch at least the immediate parents so that if this is
|
|
||||||
# a pull request then we can checkout the head.
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
# If this run was triggered by a pull request event, then checkout
|
|
||||||
# the head of the pull request instead of the merge commit.
|
|
||||||
- run: git checkout HEAD^2
|
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v1
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v1
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 https://git.io/JvXDl
|
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
||||||
# and modify them (or add more) to build your code if your project
|
|
||||||
# uses a compiled language
|
|
||||||
|
|
||||||
#- run: |
|
|
||||||
# make bootstrap
|
|
||||||
# make release
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v1
|
|
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
FROM node:8.11.1-alpine
|
||||||
|
|
||||||
|
# install yarn
|
||||||
|
ENV PATH /root/.yarn/bin:$PATH
|
||||||
|
|
||||||
|
## Install/force base tools
|
||||||
|
RUN apk update \
|
||||||
|
&& apk add make g++ curl bash binutils tar git python2 python3 \
|
||||||
|
&& rm -rf /var/cache/apk/* \
|
||||||
|
&& /bin/bash \
|
||||||
|
&& touch ~/.bashrc
|
||||||
|
|
||||||
|
## Install yarn
|
||||||
|
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||||
|
|
||||||
|
## Setup the project
|
||||||
|
RUN mkdir -p /frontend
|
||||||
|
|
||||||
|
WORKDIR /frontend
|
||||||
|
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
COPY script/docker_entrypoint.sh /usr/bin/docker_entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod +x /usr/bin/docker_entrypoint.sh
|
||||||
|
|
||||||
|
CMD [ "docker_entrypoint.sh" ]
|
11
README.md
@@ -22,8 +22,17 @@ This is the repository for the official [Home Assistant](https://home-assistant.
|
|||||||
|
|
||||||
A complete guide can be found at the following [link](https://www.home-assistant.io/developers/frontend/). It describes a short guide for the build of project.
|
A complete guide can be found at the following [link](https://www.home-assistant.io/developers/frontend/). It describes a short guide for the build of project.
|
||||||
|
|
||||||
|
### Docker environment
|
||||||
|
|
||||||
|
It is possible to compile the project and/or run commands in the development environment having only the [Docker](https://www.docker.com) pre-installed in the system. On the root of project you can do:
|
||||||
|
|
||||||
|
- `sh ./script/docker_run.sh build` Build all the project with one command
|
||||||
|
- `sh ./script/docker_run.sh bash` Open an interactive shell (the same environment generated by the _classic environment_) where you can run commands. This bash work on your project directory and any change on your file is automatically present within your build bash.
|
||||||
|
|
||||||
|
**Note**: if you have installed `npm` in addition to the `docker`, you can use the commands `npm run docker_build` and `npm run bash` to get a full build or bash as explained above
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Home Assistant is open-source and Apache 2 licensed. Feel free to browse the repository, learn and reuse parts in your own projects.
|
Home Assistant is open-source and Apache 2 licensed. Feel free to browse the repository, learn and reuse parts in your own projects.
|
||||||
|
|
||||||
We use [BrowserStack](https://www.browserstack.com) to test Home Assistant on a large variety of devices.
|
We use [BrowserStack](https://www.browserstack.com) to test Home Assistant on a large variation of devices.
|
||||||
|
@@ -20,13 +20,7 @@ module.exports.emptyPackages = ({ latestBuild }) =>
|
|||||||
// Loads stuff from a CDN
|
// Loads stuff from a CDN
|
||||||
require.resolve("@polymer/font-roboto/roboto.js"),
|
require.resolve("@polymer/font-roboto/roboto.js"),
|
||||||
require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"),
|
require.resolve("@vaadin/vaadin-material-styles/font-roboto.js"),
|
||||||
// Compatibility not needed for latest builds
|
// Polyfill only needed for ES5 workers so filter out in latestBuild
|
||||||
latestBuild &&
|
|
||||||
// wrapped in require.resolve so it blows up if file no longer exists
|
|
||||||
require.resolve(
|
|
||||||
path.resolve(paths.polymer_dir, "src/resources/compatibility.ts")
|
|
||||||
),
|
|
||||||
// This polyfill is loaded in workers to support ES5, filter it out.
|
|
||||||
latestBuild && require.resolve("proxy-polyfill/src/index.js"),
|
latestBuild && require.resolve("proxy-polyfill/src/index.js"),
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
@@ -52,24 +46,17 @@ module.exports.terserOptions = (latestBuild) => ({
|
|||||||
module.exports.babelOptions = ({ latestBuild }) => ({
|
module.exports.babelOptions = ({ latestBuild }) => ({
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
presets: [
|
presets: [
|
||||||
!latestBuild && [
|
!latestBuild && [require("@babel/preset-env").default, { modules: false }],
|
||||||
require("@babel/preset-env").default,
|
|
||||||
{
|
|
||||||
useBuiltIns: "entry",
|
|
||||||
corejs: "3.6",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
require("@babel/preset-typescript").default,
|
require("@babel/preset-typescript").default,
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
plugins: [
|
plugins: [
|
||||||
// Part of ES2018. Converts {...a, b: 2} to Object.assign({}, a, {b: 2})
|
// Part of ES2018. Converts {...a, b: 2} to Object.assign({}, a, {b: 2})
|
||||||
!latestBuild && [
|
[
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
"@babel/plugin-proposal-object-rest-spread",
|
||||||
{ loose: true, useBuiltIns: true },
|
{ loose: true, useBuiltIns: true },
|
||||||
],
|
],
|
||||||
// Only support the syntax, Webpack will handle it.
|
// Only support the syntax, Webpack will handle it.
|
||||||
"@babel/plugin-syntax-import-meta",
|
"@babel/syntax-dynamic-import",
|
||||||
"@babel/plugin-syntax-dynamic-import",
|
|
||||||
"@babel/plugin-proposal-optional-chaining",
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
[
|
[
|
||||||
@@ -80,7 +67,7 @@ module.exports.babelOptions = ({ latestBuild }) => ({
|
|||||||
require("@babel/plugin-proposal-class-properties").default,
|
require("@babel/plugin-proposal-class-properties").default,
|
||||||
{ loose: true },
|
{ loose: true },
|
||||||
],
|
],
|
||||||
].filter(Boolean),
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Are already ES5, cause warnings when babelified.
|
// Are already ES5, cause warnings when babelified.
|
||||||
@@ -92,8 +79,8 @@ module.exports.babelExclude = () => [
|
|||||||
const outputPath = (outputRoot, latestBuild) =>
|
const outputPath = (outputRoot, latestBuild) =>
|
||||||
path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5");
|
path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5");
|
||||||
|
|
||||||
const publicPath = (latestBuild, root = "") =>
|
const publicPath = (latestBuild) =>
|
||||||
latestBuild ? `${root}/frontend_latest/` : `${root}/frontend_es5/`;
|
latestBuild ? "/frontend_latest/" : "/frontend_es5/";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BundleConfig {
|
BundleConfig {
|
||||||
@@ -125,6 +112,7 @@ module.exports.config = {
|
|||||||
authorize: "./src/entrypoints/authorize.ts",
|
authorize: "./src/entrypoints/authorize.ts",
|
||||||
onboarding: "./src/entrypoints/onboarding.ts",
|
onboarding: "./src/entrypoints/onboarding.ts",
|
||||||
core: "./src/entrypoints/core.ts",
|
core: "./src/entrypoints/core.ts",
|
||||||
|
compatibility: "./src/entrypoints/compatibility.ts",
|
||||||
"custom-panel": "./src/entrypoints/custom-panel.ts",
|
"custom-panel": "./src/entrypoints/custom-panel.ts",
|
||||||
},
|
},
|
||||||
outputPath: outputPath(paths.app_output_root, latestBuild),
|
outputPath: outputPath(paths.app_output_root, latestBuild),
|
||||||
@@ -139,6 +127,10 @@ module.exports.config = {
|
|||||||
return {
|
return {
|
||||||
entry: {
|
entry: {
|
||||||
main: path.resolve(paths.demo_dir, "src/entrypoint.ts"),
|
main: path.resolve(paths.demo_dir, "src/entrypoint.ts"),
|
||||||
|
compatibility: path.resolve(
|
||||||
|
paths.polymer_dir,
|
||||||
|
"src/entrypoints/compatibility.ts"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
outputPath: outputPath(paths.demo_output_root, latestBuild),
|
outputPath: outputPath(paths.demo_output_root, latestBuild),
|
||||||
publicPath: publicPath(latestBuild),
|
publicPath: publicPath(latestBuild),
|
||||||
@@ -177,14 +169,18 @@ module.exports.config = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
hassio({ isProdBuild, latestBuild }) {
|
hassio({ isProdBuild, latestBuild }) {
|
||||||
|
if (latestBuild) {
|
||||||
|
throw new Error("Hass.io does not support latest build!");
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
entry: {
|
entry: {
|
||||||
entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"),
|
entrypoint: path.resolve(paths.hassio_dir, "src/entrypoint.ts"),
|
||||||
},
|
},
|
||||||
outputPath: outputPath(paths.hassio_output_root, latestBuild),
|
outputPath: paths.hassio_output_root,
|
||||||
publicPath: publicPath(latestBuild, paths.hassio_publicPath),
|
publicPath: paths.hassio_publicPath,
|
||||||
isProdBuild,
|
isProdBuild,
|
||||||
latestBuild,
|
latestBuild,
|
||||||
|
dontHash: new Set(["entrypoint"]),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -20,7 +20,6 @@ gulp.task(
|
|||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations"),
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
"gen-index-cast-dev",
|
|
||||||
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -6,32 +6,30 @@ const merge = require("merge-stream");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const paths = require("../paths");
|
const paths = require("../paths");
|
||||||
|
|
||||||
const zopfliOptions = { threshold: 150 };
|
|
||||||
|
|
||||||
gulp.task("compress-app", function compressApp() {
|
gulp.task("compress-app", function compressApp() {
|
||||||
const jsLatest = gulp
|
const jsLatest = gulp
|
||||||
.src(path.resolve(paths.app_output_latest, "**/*.js"))
|
.src(path.resolve(paths.app_output_latest, "**/*.js"))
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli({ threshold: 150 }))
|
||||||
.pipe(gulp.dest(paths.app_output_latest));
|
.pipe(gulp.dest(paths.app_output_latest));
|
||||||
|
|
||||||
const jsEs5 = gulp
|
const jsEs5 = gulp
|
||||||
.src(path.resolve(paths.app_output_es5, "**/*.js"))
|
.src(path.resolve(paths.app_output_es5, "**/*.js"))
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli({ threshold: 150 }))
|
||||||
.pipe(gulp.dest(paths.app_output_es5));
|
.pipe(gulp.dest(paths.app_output_es5));
|
||||||
|
|
||||||
const polyfills = gulp
|
const polyfills = gulp
|
||||||
.src(path.resolve(paths.app_output_static, "polyfills/*.js"))
|
.src(path.resolve(paths.app_output_static, "polyfills/*.js"))
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli({ threshold: 150 }))
|
||||||
.pipe(gulp.dest(path.resolve(paths.app_output_static, "polyfills")));
|
.pipe(gulp.dest(path.resolve(paths.app_output_static, "polyfills")));
|
||||||
|
|
||||||
const translations = gulp
|
const translations = gulp
|
||||||
.src(path.resolve(paths.app_output_static, "translations/**/*.json"))
|
.src(path.resolve(paths.app_output_static, "translations/**/*.json"))
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli({ threshold: 150 }))
|
||||||
.pipe(gulp.dest(path.resolve(paths.app_output_static, "translations")));
|
.pipe(gulp.dest(path.resolve(paths.app_output_static, "translations")));
|
||||||
|
|
||||||
const icons = gulp
|
const icons = gulp
|
||||||
.src(path.resolve(paths.app_output_static, "mdi/*.json"))
|
.src(path.resolve(paths.app_output_static, "mdi/*.json"))
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli({ threshold: 150 }))
|
||||||
.pipe(gulp.dest(path.resolve(paths.app_output_static, "mdi")));
|
.pipe(gulp.dest(path.resolve(paths.app_output_static, "mdi")));
|
||||||
|
|
||||||
return merge(jsLatest, jsEs5, polyfills, translations, icons);
|
return merge(jsLatest, jsEs5, polyfills, translations, icons);
|
||||||
@@ -40,6 +38,6 @@ gulp.task("compress-app", function compressApp() {
|
|||||||
gulp.task("compress-hassio", function compressApp() {
|
gulp.task("compress-hassio", function compressApp() {
|
||||||
return gulp
|
return gulp
|
||||||
.src(path.resolve(paths.hassio_output_root, "**/*.js"))
|
.src(path.resolve(paths.hassio_output_root, "**/*.js"))
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli())
|
||||||
.pipe(gulp.dest(paths.hassio_output_root));
|
.pipe(gulp.dest(paths.hassio_output_root));
|
||||||
});
|
});
|
||||||
|
@@ -53,6 +53,7 @@ gulp.task("gen-pages-dev", (done) => {
|
|||||||
const content = renderTemplate(page, {
|
const content = renderTemplate(page, {
|
||||||
latestPageJS: `/frontend_latest/${page}.js`,
|
latestPageJS: `/frontend_latest/${page}.js`,
|
||||||
|
|
||||||
|
es5Compatibility: "/frontend_es5/compatibility.js",
|
||||||
es5PageJS: `/frontend_es5/${page}.js`,
|
es5PageJS: `/frontend_es5/${page}.js`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@ gulp.task("gen-pages-prod", (done) => {
|
|||||||
const content = renderTemplate(page, {
|
const content = renderTemplate(page, {
|
||||||
latestPageJS: latestManifest[`${page}.js`],
|
latestPageJS: latestManifest[`${page}.js`],
|
||||||
|
|
||||||
|
es5Compatibility: es5Manifest["compatibility.js"],
|
||||||
es5PageJS: es5Manifest[`${page}.js`],
|
es5PageJS: es5Manifest[`${page}.js`],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -90,11 +92,14 @@ gulp.task("gen-pages-prod", (done) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("gen-index-app-dev", (done) => {
|
gulp.task("gen-index-app-dev", (done) => {
|
||||||
|
// In dev mode we don't mangle names, so we hardcode urls. That way we can
|
||||||
|
// run webpack as last in watch mode, which blocks output.
|
||||||
const content = renderTemplate("index", {
|
const content = renderTemplate("index", {
|
||||||
latestAppJS: "/frontend_latest/app.js",
|
latestAppJS: "/frontend_latest/app.js",
|
||||||
latestCoreJS: "/frontend_latest/core.js",
|
latestCoreJS: "/frontend_latest/core.js",
|
||||||
latestCustomPanelJS: "/frontend_latest/custom-panel.js",
|
latestCustomPanelJS: "/frontend_latest/custom-panel.js",
|
||||||
|
|
||||||
|
es5Compatibility: "/frontend_es5/compatibility.js",
|
||||||
es5AppJS: "/frontend_es5/app.js",
|
es5AppJS: "/frontend_es5/app.js",
|
||||||
es5CoreJS: "/frontend_es5/core.js",
|
es5CoreJS: "/frontend_es5/core.js",
|
||||||
es5CustomPanelJS: "/frontend_es5/custom-panel.js",
|
es5CustomPanelJS: "/frontend_es5/custom-panel.js",
|
||||||
@@ -118,6 +123,7 @@ gulp.task("gen-index-app-prod", (done) => {
|
|||||||
latestCoreJS: latestManifest["core.js"],
|
latestCoreJS: latestManifest["core.js"],
|
||||||
latestCustomPanelJS: latestManifest["custom-panel.js"],
|
latestCustomPanelJS: latestManifest["custom-panel.js"],
|
||||||
|
|
||||||
|
es5Compatibility: es5Manifest["compatibility.js"],
|
||||||
es5AppJS: es5Manifest["app.js"],
|
es5AppJS: es5Manifest["app.js"],
|
||||||
es5CoreJS: es5Manifest["core.js"],
|
es5CoreJS: es5Manifest["core.js"],
|
||||||
es5CustomPanelJS: es5Manifest["custom-panel.js"],
|
es5CustomPanelJS: es5Manifest["custom-panel.js"],
|
||||||
@@ -199,9 +205,12 @@ gulp.task("gen-index-cast-prod", (done) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("gen-index-demo-dev", (done) => {
|
gulp.task("gen-index-demo-dev", (done) => {
|
||||||
|
// In dev mode we don't mangle names, so we hardcode urls. That way we can
|
||||||
|
// run webpack as last in watch mode, which blocks output.
|
||||||
const content = renderDemoTemplate("index", {
|
const content = renderDemoTemplate("index", {
|
||||||
latestDemoJS: "/frontend_latest/main.js",
|
latestDemoJS: "/frontend_latest/main.js",
|
||||||
|
|
||||||
|
es5Compatibility: "/frontend_es5/compatibility.js",
|
||||||
es5DemoJS: "/frontend_es5/main.js",
|
es5DemoJS: "/frontend_es5/main.js",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -224,6 +233,7 @@ gulp.task("gen-index-demo-prod", (done) => {
|
|||||||
const content = renderDemoTemplate("index", {
|
const content = renderDemoTemplate("index", {
|
||||||
latestDemoJS: latestManifest["main.js"],
|
latestDemoJS: latestManifest["main.js"],
|
||||||
|
|
||||||
|
es5Compatibility: es5Manifest["compatibility.js"],
|
||||||
es5DemoJS: es5Manifest["main.js"],
|
es5DemoJS: es5Manifest["main.js"],
|
||||||
});
|
});
|
||||||
const minified = minifyHtml(content);
|
const minified = minifyHtml(content);
|
||||||
@@ -236,6 +246,8 @@ gulp.task("gen-index-demo-prod", (done) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("gen-index-gallery-dev", (done) => {
|
gulp.task("gen-index-gallery-dev", (done) => {
|
||||||
|
// In dev mode we don't mangle names, so we hardcode urls. That way we can
|
||||||
|
// run webpack as last in watch mode, which blocks output.
|
||||||
const content = renderGalleryTemplate("index", {
|
const content = renderGalleryTemplate("index", {
|
||||||
latestGalleryJS: "./frontend_latest/entrypoint.js",
|
latestGalleryJS: "./frontend_latest/entrypoint.js",
|
||||||
});
|
});
|
||||||
@@ -263,42 +275,3 @@ gulp.task("gen-index-gallery-prod", (done) => {
|
|||||||
);
|
);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("gen-index-hassio-dev", async () => {
|
|
||||||
writeHassioEntrypoint(
|
|
||||||
`${paths.hassio_publicPath}/frontend_latest/entrypoint.js`,
|
|
||||||
`${paths.hassio_publicPath}/frontend_es5/entrypoint.js`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("gen-index-hassio-prod", async () => {
|
|
||||||
const latestManifest = require(path.resolve(
|
|
||||||
paths.hassio_output_latest,
|
|
||||||
"manifest.json"
|
|
||||||
));
|
|
||||||
const es5Manifest = require(path.resolve(
|
|
||||||
paths.hassio_output_es5,
|
|
||||||
"manifest.json"
|
|
||||||
));
|
|
||||||
writeHassioEntrypoint(
|
|
||||||
latestManifest["entrypoint.js"],
|
|
||||||
es5Manifest["entrypoint.js"]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
function writeHassioEntrypoint(latestEntrypoint, es5Entrypoint) {
|
|
||||||
fs.mkdirSync(paths.hassio_output_root, { recursive: true });
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.resolve(paths.hassio_output_root, "entrypoint.js"),
|
|
||||||
`
|
|
||||||
try {
|
|
||||||
new Function("import('${latestEntrypoint}')")();
|
|
||||||
} catch (err) {
|
|
||||||
var el = document.createElement('script');
|
|
||||||
el.src = '${es5Entrypoint}';
|
|
||||||
document.body.appendChild(el);
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
{ encoding: "utf-8" }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
// Run demo develop mode
|
// Run demo develop mode
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
const env = require("../env");
|
const env = require("../env");
|
||||||
const paths = require("../paths");
|
|
||||||
|
|
||||||
require("./clean.js");
|
require("./clean.js");
|
||||||
require("./translations.js");
|
require("./translations.js");
|
||||||
@@ -15,31 +12,6 @@ require("./service-worker.js");
|
|||||||
require("./entry-html.js");
|
require("./entry-html.js");
|
||||||
require("./rollup.js");
|
require("./rollup.js");
|
||||||
|
|
||||||
gulp.task("gather-gallery-demos", async function gatherDemos() {
|
|
||||||
const files = await fs.promises.readdir(
|
|
||||||
path.resolve(paths.gallery_dir, "src/demos")
|
|
||||||
);
|
|
||||||
|
|
||||||
let content = "export const DEMOS = {\n";
|
|
||||||
|
|
||||||
for (const file of files) {
|
|
||||||
const demoId = path.basename(file, ".ts");
|
|
||||||
const demoPath = "../src/demos/" + demoId;
|
|
||||||
content += ` "${demoId}": () => import("${demoPath}"),\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
content += "};";
|
|
||||||
|
|
||||||
const galleryBuild = path.resolve(paths.gallery_dir, "build");
|
|
||||||
|
|
||||||
fs.mkdirSync(galleryBuild, { recursive: true });
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.resolve(galleryBuild, "import-demos.ts"),
|
|
||||||
content,
|
|
||||||
"utf-8"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-gallery",
|
"develop-gallery",
|
||||||
gulp.series(
|
gulp.series(
|
||||||
@@ -48,11 +20,7 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-gallery",
|
"clean-gallery",
|
||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel(
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"gen-icons-json",
|
|
||||||
"build-translations",
|
|
||||||
"gather-gallery-demos"
|
|
||||||
),
|
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
"gen-index-gallery-dev",
|
"gen-index-gallery-dev",
|
||||||
env.useRollup() ? "rollup-dev-server-gallery" : "webpack-dev-server-gallery"
|
env.useRollup() ? "rollup-dev-server-gallery" : "webpack-dev-server-gallery"
|
||||||
@@ -67,11 +35,7 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-gallery",
|
"clean-gallery",
|
||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel(
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"gen-icons-json",
|
|
||||||
"build-translations",
|
|
||||||
"gather-gallery-demos"
|
|
||||||
),
|
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
||||||
"gen-index-gallery-prod"
|
"gen-index-gallery-prod"
|
||||||
|
@@ -36,13 +36,11 @@ function copyMdiIcons(staticDir) {
|
|||||||
function copyPolyfills(staticDir) {
|
function copyPolyfills(staticDir) {
|
||||||
const staticPath = genStaticPath(staticDir);
|
const staticPath = genStaticPath(staticDir);
|
||||||
|
|
||||||
// For custom panels using ES5 builds that don't use Babel 7+
|
// Web Component polyfills and adapters
|
||||||
copyFileDir(
|
copyFileDir(
|
||||||
npmPath("@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"),
|
npmPath("@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"),
|
||||||
staticPath("polyfills/")
|
staticPath("polyfills/")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Web Component polyfills and adapters
|
|
||||||
copyFileDir(
|
copyFileDir(
|
||||||
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js"),
|
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js"),
|
||||||
staticPath("polyfills/")
|
staticPath("polyfills/")
|
||||||
|
@@ -11,7 +11,6 @@ const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
|
|||||||
const PACKAGE_PATH = path.resolve(ICON_PACKAGE_PATH, "package.json");
|
const PACKAGE_PATH = path.resolve(ICON_PACKAGE_PATH, "package.json");
|
||||||
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
|
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
|
||||||
const OUTPUT_DIR = path.resolve(__dirname, "../../build/mdi");
|
const OUTPUT_DIR = path.resolve(__dirname, "../../build/mdi");
|
||||||
const REMOVED_ICONS_PATH = path.resolve(__dirname, "../removedIcons.json");
|
|
||||||
|
|
||||||
const encoding = "utf8";
|
const encoding = "utf8";
|
||||||
|
|
||||||
@@ -26,13 +25,6 @@ const getMeta = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const addRemovedMeta = (meta) => {
|
|
||||||
const file = fs.readFileSync(REMOVED_ICONS_PATH, { encoding });
|
|
||||||
const removed = JSON.parse(file);
|
|
||||||
const combinedMeta = [...meta, ...removed];
|
|
||||||
return combinedMeta.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
};
|
|
||||||
|
|
||||||
const splitBySize = (meta) => {
|
const splitBySize = (meta) => {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
const CHUNK_SIZE = 50000;
|
const CHUNK_SIZE = 50000;
|
||||||
@@ -77,7 +69,7 @@ const findDifferentiator = (curString, prevString) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
gulp.task("gen-icons-json", (done) => {
|
gulp.task("gen-icons-json", (done) => {
|
||||||
const meta = addRemovedMeta(getMeta());
|
const meta = getMeta();
|
||||||
const split = splitBySize(meta);
|
const split = splitBySize(meta);
|
||||||
|
|
||||||
if (!fs.existsSync(OUTPUT_DIR)) {
|
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||||
|
@@ -1,9 +1,6 @@
|
|||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
const env = require("../env");
|
const env = require("../env");
|
||||||
const paths = require("../paths");
|
|
||||||
|
|
||||||
require("./clean.js");
|
require("./clean.js");
|
||||||
require("./gen-icons-json.js");
|
require("./gen-icons-json.js");
|
||||||
@@ -19,7 +16,6 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-hassio",
|
"clean-hassio",
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"gen-index-hassio-dev",
|
|
||||||
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -33,7 +29,6 @@ gulp.task(
|
|||||||
"clean-hassio",
|
"clean-hassio",
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
||||||
"gen-index-hassio-prod",
|
|
||||||
...// Don't compress running tests
|
...// Don't compress running tests
|
||||||
(env.isTest() ? [] : ["compress-hassio"])
|
(env.isTest() ? [] : ["compress-hassio"])
|
||||||
)
|
)
|
||||||
|
@@ -92,7 +92,11 @@ gulp.task("rollup-watch-app", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("rollup-watch-hassio", () => {
|
gulp.task("rollup-watch-hassio", () => {
|
||||||
watchRollup(rollupConfig.createHassioConfig, ["hassio/src/**"]);
|
watchRollup(
|
||||||
|
// Force latestBuild = false for hassio config.
|
||||||
|
(conf) => rollupConfig.createHassioConfig({ ...conf, latestBuild: false }),
|
||||||
|
["hassio/src/**"]
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("rollup-dev-server-demo", () => {
|
gulp.task("rollup-dev-server-demo", () => {
|
||||||
@@ -133,7 +137,12 @@ gulp.task(
|
|||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("rollup-prod-hassio", () =>
|
gulp.task("rollup-prod-hassio", () =>
|
||||||
bothBuilds(rollupConfig.createHassioConfig, { isProdBuild: true })
|
buildRollup(
|
||||||
|
rollupConfig.createHassioConfig({
|
||||||
|
isProdBuild: true,
|
||||||
|
latestBuild: false,
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("rollup-prod-gallery", () =>
|
gulp.task("rollup-prod-gallery", () =>
|
||||||
|
@@ -7,6 +7,7 @@ const gulp = require("gulp");
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const foreach = require("gulp-foreach");
|
const foreach = require("gulp-foreach");
|
||||||
const merge = require("gulp-merge-json");
|
const merge = require("gulp-merge-json");
|
||||||
|
const minify = require("gulp-jsonminify");
|
||||||
const rename = require("gulp-rename");
|
const rename = require("gulp-rename");
|
||||||
const transform = require("gulp-json-transform");
|
const transform = require("gulp-json-transform");
|
||||||
const { mapFiles } = require("../util");
|
const { mapFiles } = require("../util");
|
||||||
@@ -300,6 +301,7 @@ gulp.task("build-flattened-translations", function () {
|
|||||||
return flatten(data);
|
return flatten(data);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.pipe(minify())
|
||||||
.pipe(
|
.pipe(
|
||||||
rename((filePath) => {
|
rename((filePath) => {
|
||||||
if (filePath.dirname === "core") {
|
if (filePath.dirname === "core") {
|
||||||
|
@@ -129,7 +129,7 @@ gulp.task("webpack-watch-hassio", () => {
|
|||||||
webpack(
|
webpack(
|
||||||
createHassioConfig({
|
createHassioConfig({
|
||||||
isProdBuild: false,
|
isProdBuild: false,
|
||||||
latestBuild: true,
|
latestBuild: false,
|
||||||
})
|
})
|
||||||
).watch({}, handler());
|
).watch({}, handler());
|
||||||
});
|
});
|
||||||
@@ -139,8 +139,9 @@ gulp.task(
|
|||||||
() =>
|
() =>
|
||||||
new Promise((resolve) =>
|
new Promise((resolve) =>
|
||||||
webpack(
|
webpack(
|
||||||
bothBuilds(createHassioConfig, {
|
createHassioConfig({
|
||||||
isProdBuild: true,
|
isProdBuild: true,
|
||||||
|
latestBuild: false,
|
||||||
}),
|
}),
|
||||||
handler(resolve)
|
handler(resolve)
|
||||||
)
|
)
|
||||||
|
@@ -34,12 +34,7 @@ module.exports = {
|
|||||||
|
|
||||||
hassio_dir: path.resolve(__dirname, "../hassio"),
|
hassio_dir: path.resolve(__dirname, "../hassio"),
|
||||||
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
|
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
|
||||||
hassio_output_latest: path.resolve(
|
hassio_publicPath: "/api/hassio/app/",
|
||||||
__dirname,
|
|
||||||
"../hassio/build/frontend_latest"
|
|
||||||
),
|
|
||||||
hassio_output_es5: path.resolve(__dirname, "../hassio/build/frontend_es5"),
|
|
||||||
hassio_publicPath: "/api/hassio/app",
|
|
||||||
|
|
||||||
translations_src: path.resolve(__dirname, "../src/translations"),
|
translations_src: path.resolve(__dirname, "../src/translations"),
|
||||||
};
|
};
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
[]
|
|
@@ -14,6 +14,32 @@ module.exports = function (userOptions = {}) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
name: "ignore",
|
name: "ignore",
|
||||||
|
resolveId(importee, importer) {
|
||||||
|
// Only use ignore to intercept imports that we don't control
|
||||||
|
// inside node_module dependencies.
|
||||||
|
if (
|
||||||
|
importee.endsWith("commonjsHelpers.js") ||
|
||||||
|
importee.endsWith("rollupPluginBabelHelpers.js") ||
|
||||||
|
importee.endsWith("?commonjs-proxy") ||
|
||||||
|
!importer ||
|
||||||
|
!importer.includes("/node_modules/")
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let fullPath;
|
||||||
|
try {
|
||||||
|
fullPath = importee.startsWith(".")
|
||||||
|
? path.resolve(importee, importer)
|
||||||
|
: require.resolve(importee);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error in ignore plugin", { importee, importer }, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return files.some((toIgnorePath) => fullPath.startsWith(toIgnorePath))
|
||||||
|
? fullPath
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
|
||||||
load(id) {
|
load(id) {
|
||||||
return files.some((toIgnorePath) => id.startsWith(toIgnorePath))
|
return files.some((toIgnorePath) => id.startsWith(toIgnorePath))
|
||||||
|
@@ -2,6 +2,7 @@ const webpack = require("webpack");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||||
|
const WorkerPlugin = require("worker-plugin");
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
const bundle = require("./bundle");
|
const bundle = require("./bundle");
|
||||||
|
|
||||||
@@ -29,15 +30,12 @@ const createWebpackConfig = ({
|
|||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.m?js$|\.ts$/,
|
test: /\.js$|\.ts$/,
|
||||||
exclude: bundle.babelExclude(),
|
exclude: bundle.babelExclude(),
|
||||||
use: {
|
use: {
|
||||||
loader: "babel-loader",
|
loader: "babel-loader",
|
||||||
options: bundle.babelOptions({ latestBuild }),
|
options: bundle.babelOptions({ latestBuild }),
|
||||||
},
|
},
|
||||||
resolve: {
|
|
||||||
fullySpecified: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
@@ -48,13 +46,16 @@ const createWebpackConfig = ({
|
|||||||
optimization: {
|
optimization: {
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new TerserPlugin({
|
new TerserPlugin({
|
||||||
|
cache: true,
|
||||||
parallel: true,
|
parallel: true,
|
||||||
extractComments: true,
|
extractComments: true,
|
||||||
|
sourceMap: true,
|
||||||
terserOptions: bundle.terserOptions(latestBuild),
|
terserOptions: bundle.terserOptions(latestBuild),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
new WorkerPlugin(),
|
||||||
new ManifestPlugin({
|
new ManifestPlugin({
|
||||||
// Only include the JS of entrypoints
|
// Only include the JS of entrypoints
|
||||||
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
||||||
@@ -69,9 +70,7 @@ const createWebpackConfig = ({
|
|||||||
if (
|
if (
|
||||||
!context.includes("/node_modules/") ||
|
!context.includes("/node_modules/") ||
|
||||||
// calling define.amd will call require("!!webpack amd options")
|
// calling define.amd will call require("!!webpack amd options")
|
||||||
resource.startsWith("!!webpack") ||
|
resource.startsWith("!!webpack")
|
||||||
// loaded by webpack dev server but doesn't exist.
|
|
||||||
resource === "webpack/hot"
|
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -81,11 +80,7 @@ const createWebpackConfig = ({
|
|||||||
? path.resolve(context, resource)
|
? path.resolve(context, resource)
|
||||||
: require.resolve(resource);
|
: require.resolve(resource);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
console.error("Error in ignore plugin", resource, context);
|
||||||
"Error in Home Assistant ignore plugin",
|
|
||||||
resource,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,15 +93,6 @@ const createWebpackConfig = ({
|
|||||||
new RegExp(bundle.emptyPackages({ latestBuild }).join("|")),
|
new RegExp(bundle.emptyPackages({ latestBuild }).join("|")),
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||||
),
|
),
|
||||||
// We need to change the import of the polyfill for EventTarget, so we replace the polyfill file with our customized one
|
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
|
||||||
new RegExp(
|
|
||||||
require.resolve(
|
|
||||||
"lit-virtualizer/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
path.resolve(paths.polymer_dir, "src/resources/EventTarget-ponyfill.js")
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [".ts", ".js", ".json"],
|
extensions: [".ts", ".js", ".json"],
|
||||||
@@ -118,22 +104,6 @@ const createWebpackConfig = ({
|
|||||||
}
|
}
|
||||||
return `${chunk.name}.${chunk.hash.substr(0, 8)}.js`;
|
return `${chunk.name}.${chunk.hash.substr(0, 8)}.js`;
|
||||||
},
|
},
|
||||||
environment: {
|
|
||||||
// The environment supports arrow functions ('() => { ... }').
|
|
||||||
arrowFunction: latestBuild,
|
|
||||||
// The environment supports BigInt as literal (123n).
|
|
||||||
bigIntLiteral: false,
|
|
||||||
// The environment supports const and let for variable declarations.
|
|
||||||
const: latestBuild,
|
|
||||||
// The environment supports destructuring ('{ a, b } = obj').
|
|
||||||
destructuring: latestBuild,
|
|
||||||
// The environment supports an async import() function to import EcmaScript modules.
|
|
||||||
dynamicImport: latestBuild,
|
|
||||||
// The environment supports 'for of' iteration ('for (const x of array) { ... }').
|
|
||||||
forOf: latestBuild,
|
|
||||||
// The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '...').
|
|
||||||
module: latestBuild,
|
|
||||||
},
|
|
||||||
chunkFilename:
|
chunkFilename:
|
||||||
isProdBuild && !isStatsBuild
|
isProdBuild && !isStatsBuild
|
||||||
? "chunk.[chunkhash].js"
|
? "chunk.[chunkhash].js"
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
@@ -37,21 +37,24 @@
|
|||||||
<body>
|
<body>
|
||||||
<%= renderTemplate('_js_base') %>
|
<%= renderTemplate('_js_base') %>
|
||||||
|
|
||||||
<script>
|
<script type="module" crossorigin="use-credentials">
|
||||||
import("<%= latestLauncherJS %>");
|
import "<%= latestLauncherJS %>";
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script nomodule>
|
||||||
if (!window.latestJS) {
|
(function() {
|
||||||
<% if (useRollup) { %>
|
// // Safari 10.1 supports type=module but ignores nomodule, so we add this check.
|
||||||
_ls("/static/js/s.min.js").onload = function() {
|
if (!isS101) {
|
||||||
System.import("<%= es5LauncherJS %>");
|
_ls("/static/polyfills/custom-elements-es5-adapter.js");
|
||||||
};
|
<% if (useRollup) { %>
|
||||||
<% } else { %>
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
_ls("<%= es5LauncherJS %>");
|
System.import("<%= es5LauncherJS %>");
|
||||||
<% } %>
|
};
|
||||||
}
|
<% } else { %>
|
||||||
|
_ls("<%= es5LauncherJS %>");
|
||||||
|
<% } %>
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<hc-layout subtitle="FAQ">
|
<hc-layout subtitle="FAQ">
|
||||||
@@ -212,8 +215,13 @@
|
|||||||
Chromecast is a technology developed by Google, and is available on:
|
Chromecast is a technology developed by Google, and is available on:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Google Chrome (all platforms except iOS)</li>
|
<li>Google Chrome (all platforms except on iOS)</li>
|
||||||
<li>Microsoft Edge (all platforms)</li>
|
<li>
|
||||||
|
Microsoft Edge (all platforms,
|
||||||
|
<a href="https://www.microsoftedgeinsider.com" target="_blank"
|
||||||
|
>dev and canary builds only</a
|
||||||
|
>)
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -246,7 +254,7 @@ http:
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
var _gaq = [["_setAccount", "UA-57927901-9"], ["_trackPageview"]];
|
var _gaq = [["_setAccount", "UA-57927901-9"], ["_trackPageview"]];
|
||||||
(function (d, t) {
|
(function(d, t) {
|
||||||
var g = d.createElement(t),
|
var g = d.createElement(t),
|
||||||
s = d.getElementsByTagName(t)[0];
|
s = d.getElementsByTagName(t)[0];
|
||||||
g.src =
|
g.src =
|
||||||
|
@@ -28,21 +28,24 @@
|
|||||||
|
|
||||||
<hc-connect></hc-connect>
|
<hc-connect></hc-connect>
|
||||||
|
|
||||||
<script>
|
<script type="module" crossorigin="use-credentials">
|
||||||
import("<%= latestLauncherJS %>");
|
import "<%= latestLauncherJS %>";
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script nomodule>
|
||||||
if (!window.latestJS) {
|
(function() {
|
||||||
<% if (useRollup) { %>
|
// // Safari 10.1 supports type=module but ignores nomodule, so we add this check.
|
||||||
_ls("/static/js/s.min.js").onload = function() {
|
if (!isS101) {
|
||||||
System.import("<%= es5LauncherJS %>");
|
_ls("/static/polyfills/custom-elements-es5-adapter.js");
|
||||||
};
|
<% if (useRollup) { %>
|
||||||
<% } else { %>
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
_ls("<%= es5LauncherJS %>");
|
System.import("<%= es5LauncherJS %>");
|
||||||
<% } %>
|
};
|
||||||
}
|
<% } else { %>
|
||||||
|
_ls("<%= es5LauncherJS %>");
|
||||||
|
<% } %>
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import "../../../src/resources/safari-14-attachshadow-patch";
|
|
||||||
import "../../../src/resources/ha-style";
|
import "../../../src/resources/ha-style";
|
||||||
import "../../../src/resources/roboto";
|
import "../../../src/resources/roboto";
|
||||||
import "./layout/hc-connect";
|
import "./layout/hc-connect";
|
||||||
|
@@ -8,7 +8,6 @@ import {
|
|||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { CastManager } from "../../../../src/cast/cast_manager";
|
import { CastManager } from "../../../../src/cast/cast_manager";
|
||||||
@@ -29,7 +28,7 @@ import {
|
|||||||
getLovelaceCollection,
|
getLovelaceCollection,
|
||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
} from "../../../../src/data/lovelace";
|
} from "../../../../src/data/lovelace";
|
||||||
import "../../../../src/layouts/hass-loading-screen";
|
import "../../../../src/layouts/loading-screen";
|
||||||
import { generateDefaultViewConfig } from "../../../../src/panels/lovelace/common/generate-lovelace-config";
|
import { generateDefaultViewConfig } from "../../../../src/panels/lovelace/common/generate-lovelace-config";
|
||||||
import "./hc-layout";
|
import "./hc-layout";
|
||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
@@ -42,13 +41,13 @@ class HcCast extends LitElement {
|
|||||||
|
|
||||||
@property() public castManager!: CastManager;
|
@property() public castManager!: CastManager;
|
||||||
|
|
||||||
@internalProperty() private askWrite = false;
|
@property() private askWrite = false;
|
||||||
|
|
||||||
@internalProperty() private lovelaceConfig?: LovelaceConfig | null;
|
@property() private lovelaceConfig?: LovelaceConfig | null;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this.lovelaceConfig === undefined) {
|
if (this.lovelaceConfig === undefined) {
|
||||||
return html` <hass-loading-screen no-toolbar></hass-loading-screen>> `;
|
return html` <loading-screen></loading-screen>> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
const error =
|
const error =
|
||||||
|
@@ -17,8 +17,8 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
internalProperty,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { CastManager, getCastManager } from "../../../../src/cast/cast_manager";
|
import { CastManager, getCastManager } from "../../../../src/cast/cast_manager";
|
||||||
import { castSendShowDemo } from "../../../../src/cast/receiver_messages";
|
import { castSendShowDemo } from "../../../../src/cast/receiver_messages";
|
||||||
@@ -27,7 +27,7 @@ import {
|
|||||||
saveTokens,
|
saveTokens,
|
||||||
} from "../../../../src/common/auth/token_storage";
|
} from "../../../../src/common/auth/token_storage";
|
||||||
import "../../../../src/components/ha-icon";
|
import "../../../../src/components/ha-icon";
|
||||||
import "../../../../src/layouts/hass-loading-screen";
|
import "../../../../src/layouts/loading-screen";
|
||||||
import { registerServiceWorker } from "../../../../src/util/register-service-worker";
|
import { registerServiceWorker } from "../../../../src/util/register-service-worker";
|
||||||
import "./hc-layout";
|
import "./hc-layout";
|
||||||
|
|
||||||
@@ -60,19 +60,19 @@ const INTRO = html`
|
|||||||
|
|
||||||
@customElement("hc-connect")
|
@customElement("hc-connect")
|
||||||
export class HcConnect extends LitElement {
|
export class HcConnect extends LitElement {
|
||||||
@internalProperty() private loading = false;
|
@property() private loading = false;
|
||||||
|
|
||||||
// If we had stored credentials but we cannot connect,
|
// If we had stored credentials but we cannot connect,
|
||||||
// show a screen asking retry or logout.
|
// show a screen asking retry or logout.
|
||||||
@internalProperty() private cannotConnect = false;
|
@property() private cannotConnect = false;
|
||||||
|
|
||||||
@internalProperty() private error?: string | TemplateResult;
|
@property() private error?: string | TemplateResult;
|
||||||
|
|
||||||
@internalProperty() private auth?: Auth;
|
@property() private auth?: Auth;
|
||||||
|
|
||||||
@internalProperty() private connection?: Connection;
|
@property() private connection?: Connection;
|
||||||
|
|
||||||
@internalProperty() private castManager?: CastManager | null;
|
@property() private castManager?: CastManager | null;
|
||||||
|
|
||||||
private openDemo = false;
|
private openDemo = false;
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ export class HcConnect extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.castManager === undefined || this.loading) {
|
if (this.castManager === undefined || this.loading) {
|
||||||
return html` <hass-loading-screen no-toolbar></hass-loading-screen> `;
|
return html` <loading-screen></loading-screen> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.castManager === null) {
|
if (this.castManager === null) {
|
||||||
|
@@ -30,7 +30,7 @@ class HcLayout extends LitElement {
|
|||||||
<ha-card>
|
<ha-card>
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<img class="hero" src="/images/google-nest-hub.png" />
|
<img class="hero" src="/images/google-nest-hub.png" />
|
||||||
<h1 class="card-header">
|
<div class="card-header">
|
||||||
Home Assistant Cast${this.subtitle ? ` – ${this.subtitle}` : ""}
|
Home Assistant Cast${this.subtitle ? ` – ${this.subtitle}` : ""}
|
||||||
${this.auth
|
${this.auth
|
||||||
? html`
|
? html`
|
||||||
@@ -44,7 +44,7 @@ class HcLayout extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</h1>
|
</div>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
@@ -6,60 +6,13 @@ import { castContext } from "./cast_context";
|
|||||||
import { HcMain } from "./layout/hc-main";
|
import { HcMain } from "./layout/hc-main";
|
||||||
import { ReceivedMessage } from "./types";
|
import { ReceivedMessage } from "./types";
|
||||||
|
|
||||||
const lovelaceController = new HcMain();
|
const controller = new HcMain();
|
||||||
document.body.append(lovelaceController);
|
document.body.append(controller);
|
||||||
|
|
||||||
const mediaPlayer = document.createElement("cast-media-player");
|
|
||||||
mediaPlayer.style.display = "none";
|
|
||||||
document.body.append(mediaPlayer);
|
|
||||||
const playerStylesAdded = false;
|
|
||||||
|
|
||||||
let controls: HTMLElement | null;
|
|
||||||
|
|
||||||
const setTouchControlsVisibility = (visible: boolean) => {
|
|
||||||
if (!castContext.getDeviceCapabilities().touch_input_supported) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
controls =
|
|
||||||
controls ||
|
|
||||||
(document.body.querySelector("touch-controls") as HTMLElement | null);
|
|
||||||
if (controls) {
|
|
||||||
controls.style.display = visible ? "initial" : "none";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const showLovelaceController = () => {
|
|
||||||
mediaPlayer.style.display = "none";
|
|
||||||
lovelaceController.style.display = "initial";
|
|
||||||
document.body.setAttribute("style", "overflow-y: auto !important");
|
|
||||||
setTouchControlsVisibility(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const showMediaPlayer = () => {
|
|
||||||
lovelaceController.style.display = "none";
|
|
||||||
mediaPlayer.style.display = "initial";
|
|
||||||
document.body.removeAttribute("style");
|
|
||||||
setTouchControlsVisibility(true);
|
|
||||||
if (!playerStylesAdded) {
|
|
||||||
const style = document.createElement("style");
|
|
||||||
style.innerHTML = `
|
|
||||||
body {
|
|
||||||
--logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg');
|
|
||||||
--logo-repeat: no-repeat;
|
|
||||||
--playback-logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg');
|
|
||||||
--theme-hue: 200;
|
|
||||||
--progress-color: #03a9f4;
|
|
||||||
--splash-image: url('https://home-assistant.io/images/cast/splash.png');
|
|
||||||
--splash-size: cover;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = new cast.framework.CastReceiverOptions();
|
const options = new cast.framework.CastReceiverOptions();
|
||||||
options.disableIdleTimeout = true;
|
options.disableIdleTimeout = true;
|
||||||
options.customNamespaces = {
|
options.customNamespaces = {
|
||||||
|
// @ts-ignore
|
||||||
[CAST_NS]: cast.framework.system.MessageType.JSON,
|
[CAST_NS]: cast.framework.system.MessageType.JSON,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,61 +30,13 @@ options.uiConfig = new cast.framework.ui.UiConfig();
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
options.uiConfig.touchScreenOptimizedApp = true;
|
options.uiConfig.touchScreenOptimizedApp = true;
|
||||||
|
|
||||||
castContext.setInactivityTimeout(86400); // 1 day
|
|
||||||
|
|
||||||
castContext.addCustomMessageListener(
|
castContext.addCustomMessageListener(
|
||||||
CAST_NS,
|
CAST_NS,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
(ev: ReceivedMessage<HassMessage>) => {
|
(ev: ReceivedMessage<HassMessage>) => {
|
||||||
// We received a show Lovelace command, stop media from playing, hide media player and show Lovelace controller
|
|
||||||
if (
|
|
||||||
playerManager.getPlayerState() !==
|
|
||||||
cast.framework.messages.PlayerState.IDLE
|
|
||||||
) {
|
|
||||||
playerManager.stop();
|
|
||||||
} else {
|
|
||||||
showLovelaceController();
|
|
||||||
}
|
|
||||||
const msg = ev.data;
|
const msg = ev.data;
|
||||||
msg.senderId = ev.senderId;
|
msg.senderId = ev.senderId;
|
||||||
lovelaceController.processIncomingMessage(msg);
|
controller.processIncomingMessage(msg);
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const playerManager = castContext.getPlayerManager();
|
|
||||||
|
|
||||||
playerManager.setMessageInterceptor(
|
|
||||||
cast.framework.messages.MessageType.LOAD,
|
|
||||||
(loadRequestData) => {
|
|
||||||
// We received a play media command, hide Lovelace and show media player
|
|
||||||
showMediaPlayer();
|
|
||||||
const media = loadRequestData.media;
|
|
||||||
// Special handling if it came from Google Assistant
|
|
||||||
if (media.entity) {
|
|
||||||
media.contentId = media.entity;
|
|
||||||
media.streamType = cast.framework.messages.StreamType.LIVE;
|
|
||||||
media.contentType = "application/vnd.apple.mpegurl";
|
|
||||||
// @ts-ignore
|
|
||||||
media.hlsVideoSegmentFormat =
|
|
||||||
cast.framework.messages.HlsVideoSegmentFormat.FMP4;
|
|
||||||
}
|
|
||||||
return loadRequestData;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
playerManager.addEventListener(
|
|
||||||
cast.framework.events.EventType.MEDIA_STATUS,
|
|
||||||
(event) => {
|
|
||||||
if (
|
|
||||||
event.mediaStatus?.playerState ===
|
|
||||||
cast.framework.messages.PlayerState.IDLE &&
|
|
||||||
event.mediaStatus?.idleReason &&
|
|
||||||
event.mediaStatus?.idleReason !==
|
|
||||||
cast.framework.messages.IdleReason.INTERRUPTED
|
|
||||||
) {
|
|
||||||
// media finished or stopped, return to default Lovelace
|
|
||||||
showLovelaceController();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,10 +1,4 @@
|
|||||||
import {
|
import { customElement, html, property, TemplateResult } from "lit-element";
|
||||||
customElement,
|
|
||||||
html,
|
|
||||||
property,
|
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
|
||||||
} from "lit-element";
|
|
||||||
import { mockHistory } from "../../../../demo/src/stubs/history";
|
import { mockHistory } from "../../../../demo/src/stubs/history";
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
||||||
import {
|
import {
|
||||||
@@ -19,9 +13,9 @@ import "./hc-lovelace";
|
|||||||
|
|
||||||
@customElement("hc-demo")
|
@customElement("hc-demo")
|
||||||
class HcDemo extends HassElement {
|
class HcDemo extends HassElement {
|
||||||
@property({ attribute: false }) public lovelacePath!: string;
|
@property() public lovelacePath!: string;
|
||||||
|
|
||||||
@internalProperty() private _lovelaceConfig?: LovelaceConfig;
|
@property() private _lovelaceConfig?: LovelaceConfig;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this._lovelaceConfig) {
|
if (!this._lovelaceConfig) {
|
||||||
|
@@ -11,7 +11,7 @@ import { HomeAssistant } from "../../../../src/types";
|
|||||||
|
|
||||||
@customElement("hc-launch-screen")
|
@customElement("hc-launch-screen")
|
||||||
class HcLaunchScreen extends LitElement {
|
class HcLaunchScreen extends LitElement {
|
||||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property() public error?: string;
|
@property() public error?: string;
|
||||||
|
|
||||||
|
@@ -9,20 +9,19 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
||||||
import { Lovelace } from "../../../../src/panels/lovelace/types";
|
import { Lovelace } from "../../../../src/panels/lovelace/types";
|
||||||
|
import "../../../../src/panels/lovelace/views/hui-panel-view";
|
||||||
import "../../../../src/panels/lovelace/views/hui-view";
|
import "../../../../src/panels/lovelace/views/hui-view";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import "./hc-launch-screen";
|
import "./hc-launch-screen";
|
||||||
|
|
||||||
@customElement("hc-lovelace")
|
@customElement("hc-lovelace")
|
||||||
class HcLovelace extends LitElement {
|
class HcLovelace extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false }) public lovelaceConfig!: LovelaceConfig;
|
@property() public lovelaceConfig!: LovelaceConfig;
|
||||||
|
|
||||||
@property() public viewPath?: string | number;
|
@property() public viewPath?: string | number;
|
||||||
|
|
||||||
public urlPath?: string | null;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const index = this._viewIndex;
|
const index = this._viewIndex;
|
||||||
if (index === undefined) {
|
if (index === undefined) {
|
||||||
@@ -36,7 +35,6 @@ class HcLovelace extends LitElement {
|
|||||||
const lovelace: Lovelace = {
|
const lovelace: Lovelace = {
|
||||||
config: this.lovelaceConfig,
|
config: this.lovelaceConfig,
|
||||||
editMode: false,
|
editMode: false,
|
||||||
urlPath: this.urlPath!,
|
|
||||||
enableFullEditMode: () => undefined,
|
enableFullEditMode: () => undefined,
|
||||||
mode: "storage",
|
mode: "storage",
|
||||||
language: "en",
|
language: "en",
|
||||||
@@ -44,13 +42,22 @@ class HcLovelace extends LitElement {
|
|||||||
deleteConfig: async () => undefined,
|
deleteConfig: async () => undefined,
|
||||||
setEditMode: () => undefined,
|
setEditMode: () => undefined,
|
||||||
};
|
};
|
||||||
return html`
|
return this.lovelaceConfig.views[index].panel
|
||||||
<hui-view
|
? html`
|
||||||
.hass=${this.hass}
|
<hui-panel-view
|
||||||
.lovelace=${lovelace}
|
.hass=${this.hass}
|
||||||
.index=${index}
|
.lovelace=${lovelace}
|
||||||
></hui-view>
|
.config=${this.lovelaceConfig.views[index]}
|
||||||
`;
|
></hui-panel-view>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<hui-view
|
||||||
|
.hass=${this.hass}
|
||||||
|
.lovelace=${lovelace}
|
||||||
|
.index=${index}
|
||||||
|
columns="2"
|
||||||
|
></hui-view>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps) {
|
protected updated(changedProps) {
|
||||||
@@ -66,7 +73,7 @@ class HcLovelace extends LitElement {
|
|||||||
|
|
||||||
if (configBackground) {
|
if (configBackground) {
|
||||||
(this.shadowRoot!.querySelector(
|
(this.shadowRoot!.querySelector(
|
||||||
"hui-view"
|
"hui-view, hui-panel-view"
|
||||||
) as HTMLElement)!.style.setProperty(
|
) as HTMLElement)!.style.setProperty(
|
||||||
"--lovelace-background",
|
"--lovelace-background",
|
||||||
configBackground
|
configBackground
|
||||||
|
@@ -3,12 +3,7 @@ import {
|
|||||||
getAuth,
|
getAuth,
|
||||||
UnsubscribeFunc,
|
UnsubscribeFunc,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import {
|
import { customElement, html, property, TemplateResult } from "lit-element";
|
||||||
customElement,
|
|
||||||
html,
|
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
|
||||||
} from "lit-element";
|
|
||||||
import { CAST_NS } from "../../../../src/cast/const";
|
import { CAST_NS } from "../../../../src/cast/const";
|
||||||
import {
|
import {
|
||||||
ConnectMessage,
|
ConnectMessage,
|
||||||
@@ -36,13 +31,13 @@ let resourcesLoaded = false;
|
|||||||
|
|
||||||
@customElement("hc-main")
|
@customElement("hc-main")
|
||||||
export class HcMain extends HassElement {
|
export class HcMain extends HassElement {
|
||||||
@internalProperty() private _showDemo = false;
|
@property() private _showDemo = false;
|
||||||
|
|
||||||
@internalProperty() private _lovelaceConfig?: LovelaceConfig;
|
@property() private _lovelaceConfig?: LovelaceConfig;
|
||||||
|
|
||||||
@internalProperty() private _lovelacePath: string | number | null = null;
|
@property() private _lovelacePath: string | number | null = null;
|
||||||
|
|
||||||
@internalProperty() private _error?: string;
|
@property() private _error?: string;
|
||||||
|
|
||||||
private _unsubLovelace?: UnsubscribeFunc;
|
private _unsubLovelace?: UnsubscribeFunc;
|
||||||
|
|
||||||
@@ -87,7 +82,6 @@ export class HcMain extends HassElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.lovelaceConfig=${this._lovelaceConfig}
|
.lovelaceConfig=${this._lovelaceConfig}
|
||||||
.viewPath=${this._lovelacePath}
|
.viewPath=${this._lovelacePath}
|
||||||
.urlPath=${this._urlPath}
|
|
||||||
@config-refresh=${this._generateLovelaceConfig}
|
@config-refresh=${this._generateLovelaceConfig}
|
||||||
></hc-lovelace>
|
></hc-lovelace>
|
||||||
`;
|
`;
|
||||||
@@ -198,8 +192,6 @@ export class HcMain extends HassElement {
|
|||||||
this._handleNewLovelaceConfig(lovelaceConfig)
|
this._handleNewLovelaceConfig(lovelaceConfig)
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log("Error fetching Lovelace configuration", err, msg);
|
|
||||||
// Generate a Lovelace config.
|
// Generate a Lovelace config.
|
||||||
this._unsubLovelace = () => undefined;
|
this._unsubLovelace = () => undefined;
|
||||||
await this._generateLovelaceConfig();
|
await this._generateLovelaceConfig();
|
||||||
@@ -216,7 +208,9 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
this._showDemo = false;
|
this._showDemo = false;
|
||||||
this._lovelacePath = msg.viewPath;
|
this._lovelacePath = msg.viewPath;
|
||||||
|
if (castContext.getDeviceCapabilities().touch_input_supported) {
|
||||||
|
this._breakFree();
|
||||||
|
}
|
||||||
this._sendStatus();
|
this._sendStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +233,9 @@ export class HcMain extends HassElement {
|
|||||||
this._showDemo = true;
|
this._showDemo = true;
|
||||||
this._lovelacePath = "overview";
|
this._lovelacePath = "overview";
|
||||||
this._sendStatus();
|
this._sendStatus();
|
||||||
|
if (castContext.getDeviceCapabilities().touch_input_supported) {
|
||||||
|
this._breakFree();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +256,14 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _breakFree() {
|
||||||
|
const controls = document.body.querySelector("touch-controls");
|
||||||
|
if (controls) {
|
||||||
|
controls.remove();
|
||||||
|
}
|
||||||
|
document.body.setAttribute("style", "overflow-y: auto !important");
|
||||||
|
}
|
||||||
|
|
||||||
private sendMessage(senderId: string, response: any) {
|
private sendMessage(senderId: string, response: any) {
|
||||||
castContext.sendCustomMessage(CAST_NS, senderId, response);
|
castContext.sendCustomMessage(CAST_NS, senderId, response);
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
const { createCastConfig } = require("../build-scripts/webpack.js");
|
const { createCastConfig } = require("../build-scripts/webpack.js");
|
||||||
const { isProdBuild, isStatsBuild } = require("../build-scripts/env.js");
|
const { isProdBuild } = require("../build-scripts/env.js");
|
||||||
|
|
||||||
|
// File just used for stats builds
|
||||||
|
|
||||||
|
const latestBuild = true;
|
||||||
|
|
||||||
module.exports = createCastConfig({
|
module.exports = createCastConfig({
|
||||||
isProdBuild: isProdBuild(),
|
isProdBuild: isProdBuild(),
|
||||||
isStatsBuild: isStatsBuild(),
|
latestBuild,
|
||||||
latestBuild: true,
|
|
||||||
});
|
});
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 532 B After Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 535 B After Width: | Height: | Size: 803 B |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 184 B After Width: | Height: | Size: 375 B |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
@@ -26,9 +26,9 @@ export const demoThemeJimpower = () => ({
|
|||||||
"switch-checked-color": "var(--accent-color)",
|
"switch-checked-color": "var(--accent-color)",
|
||||||
"paper-dialog-background-color": "#434954",
|
"paper-dialog-background-color": "#434954",
|
||||||
"secondary-text-color": "#5294E2",
|
"secondary-text-color": "#5294E2",
|
||||||
"error-color": "#E45E65",
|
"google-red-500": "#E45E65",
|
||||||
"divider-color": "rgba(0, 0, 0, .12)",
|
"divider-color": "rgba(0, 0, 0, .12)",
|
||||||
"success-color": "#39E949",
|
"google-green-500": "#39E949",
|
||||||
"switch-unchecked-button-color": "var(--disabled-text-color)",
|
"switch-unchecked-button-color": "var(--disabled-text-color)",
|
||||||
"label-badge-border-color": "green",
|
"label-badge-border-color": "green",
|
||||||
"paper-listbox-color": "var(--primary-color)",
|
"paper-listbox-color": "var(--primary-color)",
|
||||||
|
@@ -27,9 +27,9 @@ export const demoThemeKernehed = () => ({
|
|||||||
"switch-checked-color": "var(--accent-color)",
|
"switch-checked-color": "var(--accent-color)",
|
||||||
"paper-dialog-background-color": "#292929",
|
"paper-dialog-background-color": "#292929",
|
||||||
"secondary-text-color": "#b58e31",
|
"secondary-text-color": "#b58e31",
|
||||||
"error-color": "#b58e31",
|
"google-red-500": "#b58e31",
|
||||||
"divider-color": "rgba(0, 0, 0, .12)",
|
"divider-color": "rgba(0, 0, 0, .12)",
|
||||||
"success-color": "#2980b9",
|
"google-green-500": "#2980b9",
|
||||||
"switch-unchecked-button-color": "var(--disabled-text-color)",
|
"switch-unchecked-button-color": "var(--disabled-text-color)",
|
||||||
"label-badge-border-color": "green",
|
"label-badge-border-color": "green",
|
||||||
"paper-listbox-color": "#777777",
|
"paper-listbox-color": "#777777",
|
||||||
|
@@ -7,183 +7,205 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
cards: [
|
cards: [
|
||||||
{ type: "custom:ha-demo-card" },
|
{ type: "custom:ha-demo-card" },
|
||||||
{
|
{
|
||||||
type: "grid",
|
|
||||||
columns: 4,
|
|
||||||
cards: [
|
cards: [
|
||||||
{
|
{
|
||||||
image: "/assets/teachingbirds/isa_square.jpg",
|
cards: [
|
||||||
type: "picture-entity",
|
|
||||||
show_name: false,
|
|
||||||
tap_action: {
|
|
||||||
action: "more-info",
|
|
||||||
},
|
|
||||||
entity: "sensor.presence_isa",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: "/assets/teachingbirds/Stefan_square.jpg",
|
|
||||||
type: "picture-entity",
|
|
||||||
show_name: false,
|
|
||||||
tap_action: {
|
|
||||||
action: "more-info",
|
|
||||||
},
|
|
||||||
entity: "sensor.presence_stefan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: "/assets/teachingbirds/background_square.png",
|
|
||||||
elements: [
|
|
||||||
{
|
{
|
||||||
state_image: {
|
image: "/assets/teachingbirds/isa_square.jpg",
|
||||||
on: "/assets/teachingbirds/radiator_on.jpg",
|
type: "picture-entity",
|
||||||
off: "/assets/teachingbirds/radiator_off.jpg",
|
show_name: false,
|
||||||
},
|
|
||||||
type: "image",
|
|
||||||
style: {
|
|
||||||
width: "100%",
|
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
},
|
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "more-info",
|
action: "more-info",
|
||||||
},
|
},
|
||||||
entity: "switch.stefan_radiator_3",
|
entity: "sensor.presence_isa",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
style: {
|
image: "/assets/teachingbirds/Stefan_square.jpg",
|
||||||
top: "90%",
|
type: "picture-entity",
|
||||||
left: "50%",
|
show_name: false,
|
||||||
|
tap_action: {
|
||||||
|
action: "more-info",
|
||||||
},
|
},
|
||||||
type: "state-label",
|
entity: "sensor.presence_stefan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "/assets/teachingbirds/background_square.png",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
state_image: {
|
||||||
|
on: "/assets/teachingbirds/radiator_on.jpg",
|
||||||
|
off: "/assets/teachingbirds/radiator_off.jpg",
|
||||||
|
},
|
||||||
|
type: "image",
|
||||||
|
style: {
|
||||||
|
width: "100%",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
},
|
||||||
|
tap_action: {
|
||||||
|
action: "more-info",
|
||||||
|
},
|
||||||
|
entity: "switch.stefan_radiator_3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
top: "90%",
|
||||||
|
left: "50%",
|
||||||
|
},
|
||||||
|
type: "state-label",
|
||||||
|
entity: "sensor.temperature_stefan",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "picture-elements",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "/assets/teachingbirds/background_square.png",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
"--mdc-icon-size": "100%",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
},
|
||||||
|
type: "icon",
|
||||||
|
tap_action: {
|
||||||
|
action: "navigate",
|
||||||
|
navigation_path: "/lovelace/home_info",
|
||||||
|
},
|
||||||
|
icon: "mdi:car",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "picture-elements",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "horizontal-stack",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
show_name: false,
|
||||||
|
type: "picture-entity",
|
||||||
|
name: "Alarm",
|
||||||
|
image: "/assets/teachingbirds/House_square.jpg",
|
||||||
|
entity: "alarm_control_panel.house",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Roomba",
|
||||||
|
image: "/assets/teachingbirds/roomba_square.jpg",
|
||||||
|
show_name: false,
|
||||||
|
type: "picture-entity",
|
||||||
|
state_image: {
|
||||||
|
"Not Today": "/assets/teachingbirds/roomba_bw_square.jpg",
|
||||||
|
},
|
||||||
|
entity: "input_select.roomba_mode",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
show_name: false,
|
||||||
|
type: "picture-entity",
|
||||||
|
state_image: {
|
||||||
|
Mail: "/assets/teachingbirds/mailbox_square.jpg",
|
||||||
|
"Package and mail":
|
||||||
|
"/assets/teachingbirds/mailbox_square.jpg",
|
||||||
|
Empty: "/assets/teachingbirds/mailbox_bw_square.jpg",
|
||||||
|
Package: "/assets/teachingbirds/mailbox_square.jpg",
|
||||||
|
},
|
||||||
|
entity: "sensor.mailbox",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
show_name: false,
|
||||||
|
state_image: {
|
||||||
|
"Put out": "/assets/teachingbirds/trash_square.jpg",
|
||||||
|
"Take in": "/assets/teachingbirds/trash_square.jpg",
|
||||||
|
},
|
||||||
|
type: "picture-entity",
|
||||||
|
image: "/assets/teachingbirds/trash_bear_bw_square.jpg",
|
||||||
|
entity: "sensor.trash_status",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "horizontal-stack",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
state_image: {
|
||||||
|
Idle: "/assets/teachingbirds/washer_square.jpg",
|
||||||
|
Running: "/assets/teachingbirds/laundry_running_square.jpg",
|
||||||
|
Clean: "/assets/teachingbirds/laundry_clean_2_square.jpg",
|
||||||
|
},
|
||||||
|
entity: "input_select.washing_machine_status",
|
||||||
|
type: "picture-entity",
|
||||||
|
show_name: false,
|
||||||
|
name: "Washer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state_image: {
|
||||||
|
Idle: "/assets/teachingbirds/dryer_square.jpg",
|
||||||
|
Running: "/assets/teachingbirds/clothes_drying_square.jpg",
|
||||||
|
Clean: "/assets/teachingbirds/folded_clothes_square.jpg",
|
||||||
|
},
|
||||||
|
entity: "input_select.dryer_status",
|
||||||
|
type: "picture-entity",
|
||||||
|
show_name: false,
|
||||||
|
name: "Dryer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "/assets/teachingbirds/guests_square.jpg",
|
||||||
|
type: "picture-entity",
|
||||||
|
show_name: false,
|
||||||
|
tap_action: {
|
||||||
|
action: "toggle",
|
||||||
|
},
|
||||||
|
entity: "input_boolean.guest_mode",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "/assets/teachingbirds/cleaning_square.jpg",
|
||||||
|
type: "picture-entity",
|
||||||
|
show_name: false,
|
||||||
|
tap_action: {
|
||||||
|
action: "toggle",
|
||||||
|
},
|
||||||
|
entity: "input_boolean.cleaning_day",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "horizontal-stack",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "vertical-stack",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "vertical-stack",
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
cards: [
|
||||||
|
{
|
||||||
|
graph: "line",
|
||||||
|
type: "sensor",
|
||||||
|
entity: "sensor.temperature_bedroom",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
graph: "line",
|
||||||
|
type: "sensor",
|
||||||
|
name: "S's room",
|
||||||
entity: "sensor.temperature_stefan",
|
entity: "sensor.temperature_stefan",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
type: "picture-elements",
|
type: "horizontal-stack",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: "/assets/teachingbirds/background_square.png",
|
cards: [
|
||||||
elements: [
|
|
||||||
{
|
{
|
||||||
style: {
|
graph: "line",
|
||||||
"--mdc-icon-size": "100%",
|
type: "sensor",
|
||||||
top: "50%",
|
entity: "sensor.temperature_passage",
|
||||||
left: "50%",
|
},
|
||||||
},
|
{
|
||||||
type: "icon",
|
graph: "line",
|
||||||
tap_action: {
|
type: "sensor",
|
||||||
action: "navigate",
|
name: "Laundry",
|
||||||
navigation_path: "/lovelace/home_info",
|
entity: "sensor.temperature_downstairs_bathroom",
|
||||||
},
|
|
||||||
icon: "mdi:car",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
type: "picture-elements",
|
type: "horizontal-stack",
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
show_name: false,
|
|
||||||
type: "picture-entity",
|
|
||||||
name: "Alarm",
|
|
||||||
image: "/assets/teachingbirds/House_square.jpg",
|
|
||||||
entity: "alarm_control_panel.house",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Roomba",
|
|
||||||
image: "/assets/teachingbirds/roomba_square.jpg",
|
|
||||||
show_name: false,
|
|
||||||
type: "picture-entity",
|
|
||||||
state_image: {
|
|
||||||
"Not Today": "/assets/teachingbirds/roomba_bw_square.jpg",
|
|
||||||
},
|
|
||||||
entity: "input_select.roomba_mode",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
show_name: false,
|
|
||||||
type: "picture-entity",
|
|
||||||
state_image: {
|
|
||||||
Mail: "/assets/teachingbirds/mailbox_square.jpg",
|
|
||||||
"Package and mail": "/assets/teachingbirds/mailbox_square.jpg",
|
|
||||||
Empty: "/assets/teachingbirds/mailbox_bw_square.jpg",
|
|
||||||
Package: "/assets/teachingbirds/mailbox_square.jpg",
|
|
||||||
},
|
|
||||||
entity: "sensor.mailbox",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
show_name: false,
|
|
||||||
state_image: {
|
|
||||||
"Put out": "/assets/teachingbirds/trash_square.jpg",
|
|
||||||
"Take in": "/assets/teachingbirds/trash_square.jpg",
|
|
||||||
},
|
|
||||||
type: "picture-entity",
|
|
||||||
image: "/assets/teachingbirds/trash_bear_bw_square.jpg",
|
|
||||||
entity: "sensor.trash_status",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
state_image: {
|
|
||||||
Idle: "/assets/teachingbirds/washer_square.jpg",
|
|
||||||
Running: "/assets/teachingbirds/laundry_running_square.jpg",
|
|
||||||
Clean: "/assets/teachingbirds/laundry_clean_2_square.jpg",
|
|
||||||
},
|
|
||||||
entity: "input_select.washing_machine_status",
|
|
||||||
type: "picture-entity",
|
|
||||||
show_name: false,
|
|
||||||
name: "Washer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
state_image: {
|
|
||||||
Idle: "/assets/teachingbirds/dryer_square.jpg",
|
|
||||||
Running: "/assets/teachingbirds/clothes_drying_square.jpg",
|
|
||||||
Clean: "/assets/teachingbirds/folded_clothes_square.jpg",
|
|
||||||
},
|
|
||||||
entity: "input_select.dryer_status",
|
|
||||||
type: "picture-entity",
|
|
||||||
show_name: false,
|
|
||||||
name: "Dryer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: "/assets/teachingbirds/guests_square.jpg",
|
|
||||||
type: "picture-entity",
|
|
||||||
show_name: false,
|
|
||||||
tap_action: {
|
|
||||||
action: "toggle",
|
|
||||||
},
|
|
||||||
entity: "input_boolean.guest_mode",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image: "/assets/teachingbirds/cleaning_square.jpg",
|
|
||||||
type: "picture-entity",
|
|
||||||
show_name: false,
|
|
||||||
tap_action: {
|
|
||||||
action: "toggle",
|
|
||||||
},
|
|
||||||
entity: "input_boolean.cleaning_day",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "grid",
|
|
||||||
columns: 2,
|
|
||||||
cards: [
|
|
||||||
{
|
|
||||||
graph: "line",
|
|
||||||
type: "sensor",
|
|
||||||
entity: "sensor.temperature_bedroom",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
graph: "line",
|
|
||||||
type: "sensor",
|
|
||||||
name: "S's room",
|
|
||||||
entity: "sensor.temperature_stefan",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
graph: "line",
|
|
||||||
type: "sensor",
|
|
||||||
entity: "sensor.temperature_passage",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
graph: "line",
|
|
||||||
type: "sensor",
|
|
||||||
name: "Laundry",
|
|
||||||
entity: "sensor.temperature_downstairs_bathroom",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -4,7 +4,7 @@ import {
|
|||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
internalProperty,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { CastManager } from "../../../src/cast/cast_manager";
|
import { CastManager } from "../../../src/cast/cast_manager";
|
||||||
@@ -20,7 +20,7 @@ import { HomeAssistant } from "../../../src/types";
|
|||||||
class CastDemoRow extends LitElement implements LovelaceRow {
|
class CastDemoRow extends LitElement implements LovelaceRow {
|
||||||
public hass!: HomeAssistant;
|
public hass!: HomeAssistant;
|
||||||
|
|
||||||
@internalProperty() private _castManager?: CastManager | null;
|
@property() private _castManager?: CastManager | null;
|
||||||
|
|
||||||
public setConfig(_config: CastConfig): void {
|
public setConfig(_config: CastConfig): void {
|
||||||
// No config possible.
|
// No config possible.
|
||||||
@@ -52,6 +52,7 @@ class CastDemoRow extends LitElement implements LovelaceRow {
|
|||||||
});
|
});
|
||||||
mgr.castContext.addEventListener(
|
mgr.castContext.addEventListener(
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
|
// @ts-ignore
|
||||||
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
||||||
(ev) => {
|
(ev) => {
|
||||||
// On Android, opening a new session always results in SESSION_RESUMED.
|
// On Android, opening a new session always results in SESSION_RESUMED.
|
||||||
|
@@ -1,16 +1,15 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/paper-spinner/paper-spinner-lite";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { until } from "lit-html/directives/until";
|
import { until } from "lit-html/directives/until";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/components/ha-circular-progress";
|
|
||||||
import { LovelaceCardConfig } from "../../../src/data/lovelace";
|
import { LovelaceCardConfig } from "../../../src/data/lovelace";
|
||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
import { Lovelace, LovelaceCard } from "../../../src/panels/lovelace/types";
|
import { Lovelace, LovelaceCard } from "../../../src/panels/lovelace/types";
|
||||||
@@ -22,11 +21,11 @@ import {
|
|||||||
} from "../configs/demo-configs";
|
} from "../configs/demo-configs";
|
||||||
|
|
||||||
export class HADemoCard extends LitElement implements LovelaceCard {
|
export class HADemoCard extends LitElement implements LovelaceCard {
|
||||||
@property({ attribute: false }) public lovelace?: Lovelace;
|
@property() public lovelace?: Lovelace;
|
||||||
|
|
||||||
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
@property() public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@internalProperty() private _switching?: boolean;
|
@property() private _switching?: boolean;
|
||||||
|
|
||||||
private _hidden = localStorage.hide_demo_card;
|
private _hidden = localStorage.hide_demo_card;
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
<div class="picker">
|
<div class="picker">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
${this._switching
|
${this._switching
|
||||||
? html`<ha-circular-progress active></ha-circular-progress>`
|
? html` <paper-spinner-lite active></paper-spinner-lite> `
|
||||||
: until(
|
: until(
|
||||||
selectedDemoConfig.then(
|
selectedDemoConfig.then(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import "../../src/resources/safari-14-attachshadow-patch";
|
|
||||||
import "@polymer/polymer/lib/elements/dom-if";
|
import "@polymer/polymer/lib/elements/dom-if";
|
||||||
import "@polymer/polymer/lib/elements/dom-repeat";
|
import "@polymer/polymer/lib/elements/dom-repeat";
|
||||||
import "../../src/resources/ha-style";
|
import "../../src/resources/ha-style";
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import "../../src/resources/compatibility";
|
|
||||||
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
|
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
|
||||||
import { navigate } from "../../src/common/navigate";
|
import { navigate } from "../../src/common/navigate";
|
||||||
import {
|
import {
|
||||||
|
@@ -86,26 +86,30 @@
|
|||||||
<%= renderTemplate('_js_base') %>
|
<%= renderTemplate('_js_base') %>
|
||||||
<%= renderTemplate('_preload_roboto') %>
|
<%= renderTemplate('_preload_roboto') %>
|
||||||
|
|
||||||
<script>
|
<script type="module" src="<%= latestDemoJS %>"></script>
|
||||||
import("<%= latestDemoJS %>");
|
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script nomodule>
|
||||||
if (!window.latestJS) {
|
(function() {
|
||||||
<% if (useRollup) { %>
|
// // Safari 10.1 supports type=module but ignores nomodule, so we add this check.
|
||||||
_ls("/static/js/s.min.js").onload = function() {
|
if (!isS101) {
|
||||||
System.import("<%= es5DemoJS %>");
|
_ls("/static/polyfills/custom-elements-es5-adapter.js");
|
||||||
};
|
<% if (useRollup) { %>
|
||||||
<% } else { %>
|
_ls("/static/js/s.min.js").onload = function() {
|
||||||
_ls("<%= es5DemoJS %>");
|
System.import("<%= es5Compatibility %>").then(function() {
|
||||||
<% } %>
|
System.import("<%= es5DemoJS %>");
|
||||||
}
|
});
|
||||||
|
};
|
||||||
|
<% } else { %>
|
||||||
|
_ls("<%= es5Compatibility %>");
|
||||||
|
_ls("<%= es5DemoJS %>");
|
||||||
|
<% } %>
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var _gaq = [["_setAccount", "UA-57927901-5"], ["_trackPageview"]];
|
var _gaq = [["_setAccount", "UA-57927901-5"], ["_trackPageview"]];
|
||||||
(function (d, t) {
|
(function(d, t) {
|
||||||
var g = d.createElement(t),
|
var g = d.createElement(t),
|
||||||
s = d.getElementsByTagName(t)[0];
|
s = d.getElementsByTagName(t)[0];
|
||||||
g.src =
|
g.src =
|
||||||
|