diff --git a/public/images/badge-apple-app-store.svg b/public/images/badge-apple-app-store.svg new file mode 100644 index 00000000..072b425a --- /dev/null +++ b/public/images/badge-apple-app-store.svg @@ -0,0 +1,46 @@ + + Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/badge-google-play.png b/public/images/badge-google-play.png new file mode 100644 index 00000000..131f3aca Binary files /dev/null and b/public/images/badge-google-play.png differ diff --git a/rollup.config.js b/rollup.config.js index 80fd7d17..8301b5a7 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,4 +1,4 @@ -import { parse } from 'path'; +import { parse } from "path"; import typescript from "@rollup/plugin-typescript"; import commonjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; @@ -27,6 +27,7 @@ const plugins = (latestBuild) => // Each entrypoint a different build to avoid code reuse across builds export default [ "./src/entrypoints/my-index.ts", + "./src/entrypoints/my-invite.ts", "./src/entrypoints/my-redirect.ts", "./src/entrypoints/my-change-url.ts", "./src/entrypoints/my-create-link.ts", diff --git a/src-11ty/invite.html b/src-11ty/invite.html new file mode 100644 index 00000000..2ebd672e --- /dev/null +++ b/src-11ty/invite.html @@ -0,0 +1,53 @@ +--- +layout: base_card_with_hero +javascript_source: my-invite.js +permalink: "invite/" +description: Invited to join my Home Assistant instance. +--- + + + +

Welcome to Home Assistant

+ +
+

+ You have been invited to join a Home Assistant instance. To accept the + invitation, download the Home Assistant application to continue. +

+

+ Get it on Google Play + Download on the App Store +

+

When the application is installed, click below to accept the invite.

+

+ Loading... +

+

+ Invitations are currently only supported on the Home Assistant apps. +

+
diff --git a/src/components/my-url-input.ts b/src/components/my-url-input.ts index 61e77b9b..4fa80b16 100644 --- a/src/components/my-url-input.ts +++ b/src/components/my-url-input.ts @@ -1,5 +1,5 @@ -import "@material/web/button/filled-button" -import "@material/web/textfield/filled-text-field" +import "@material/web/button/filled-button"; +import "@material/web/textfield/filled-text-field"; import type { MdFilledTextField } from "@material/web/textfield/filled-text-field"; import { css, CSSResult, html, LitElement, TemplateResult } from "lit"; import { customElement, state, query, property } from "lit/decorators.js"; @@ -29,9 +29,9 @@ export class MyUrlInputMain extends LitElement { .value=${this.value || DEFAULT_HASS_URL} @keydown=${this._handleInputKeyDown} > - ${this.value ? "Update" : "Save"} + ${this.value ? "Update" : "Save"} `; } @@ -54,7 +54,7 @@ export class MyUrlInputMain extends LitElement { if (value.indexOf("://") === -1) { this._textfield.setCustomValidity( - "Please enter your full URL, including the protocol part (https://)." + "Please enter your full URL, including the protocol part (https://).", ); this._textfield.reportValidity(); return; diff --git a/src/entrypoints/my-invite.ts b/src/entrypoints/my-invite.ts new file mode 100644 index 00000000..3b0cc749 --- /dev/null +++ b/src/entrypoints/my-invite.ts @@ -0,0 +1,36 @@ +import "@material/web/button/filled-button"; +import { LitElement, TemplateResult, html } from "lit"; +import { customElement } from "lit/decorators.js"; + +const SUPPORTED_PARAMS = ["url"]; + +const INVITE_URL = new URL("homeassistant://invite"); +// We read params from location.hash instead of location.search, as they +// won't be sent to the server when the user visits the link. +const hashParams = new URLSearchParams(location.hash.substring(1)); +const inviteHashParams = new URLSearchParams(); +for (const [key, value] of hashParams.entries()) { + if (SUPPORTED_PARAMS.includes(key)) { + inviteHashParams.append(key, value); + } +} +if (inviteHashParams.size > 0) { + INVITE_URL.hash = inviteHashParams.toString(); +} + +@customElement("my-invite") +export class MyUrlInputMain extends LitElement { + protected render(): TemplateResult { + return html` + + Accept Invite + + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "my-invite": MyUrlInputMain; + } +}