Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

streamer mode fix #512

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions raw_package/index.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<esphome-main
version="{{ version }}"
docsLink="{{ docs_link }}"
{% if streamer_mode %}streamerMode{% end %}
{% if login_enabled %}logoutUrl="{{ relative_url }}logout"{% end %}
></esphome-main>
{% end %}
Expand Down
8 changes: 7 additions & 1 deletion src/components/remote-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { StreamError, streamLogs } from "../api";
import { ColoredConsole, coloredConsoleStyles } from "../util/console-color";
import { fireEvent } from "../util/fire-event";

export class ESPHomeBlurSecrets {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this inside remote-process ? This can be in it's own file and doesn't have to be a class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I din't think it needed its own file as it is so small - and it needs to be a class as it is used as a static/global variable, I find this a better approach than using the window object to set globals...

public static enabled = false;
}

@customElement("esphome-remote-process")
class ESPHomeRemoteProcess extends HTMLElement {
public type!: "validate" | "logs" | "upload" | "clean-mqtt" | "clean";
Expand All @@ -28,7 +32,9 @@ class ESPHomeRemoteProcess extends HTMLElement {
}
${coloredConsoleStyles}
</style>
<div class="log"></div>
<div class="log${
balloob marked this conversation as resolved.
Show resolved Hide resolved
ESPHomeBlurSecrets.enabled ? " blur-secrets" : ""
}"></div>
`;

const coloredConsole = new ColoredConsole(shadowRoot.querySelector("div")!);
Expand Down
85 changes: 56 additions & 29 deletions src/editor/esphome-editor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import { LitElement, html } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { customElement, property, query, state } from "lit/decorators.js";
import "@material/mwc-dialog";
import "@material/mwc-button";
import "@material/mwc-snackbar";
Expand All @@ -12,6 +12,7 @@ import type { Snackbar } from "@material/mwc-snackbar";
import { fireEvent } from "../util/fire-event";
import { debounce } from "../util/debounce";
import "./monaco-provider";
import "./streamer-warning";

// WebSocket URL Helper
const loc = window.location;
Expand All @@ -25,6 +26,33 @@ const darkQuery: MediaQueryList = window.matchMedia(
"(prefers-color-scheme: dark)"
);

const commonStyle = html`
<style>
html,
body {
height: 100vh;
overflow: hidden;
}
.esphome-header {
display: flex;
justify-content: space-between;
align-items: center;
align-content: stretch;
}
.esphome-header h2 {
line-height: 100%;
/* this margin, padding stretches the container, offsetHeight does not calculate margin of .editor-header */
padding: 0.8rem 0.5rem 1rem 0.5rem;
margin: 0px;
font-size: 1.4rem;
flex: 1 1 auto;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>
`;

@customElement("esphome-editor")
class ESPHomeEditor extends LitElement {
private editor?: monaco.editor.IStandaloneCodeEditor;
Expand All @@ -34,42 +62,25 @@ class ESPHomeEditor extends LitElement {
private editorActiveSecrets = false;

@property() public fileName!: string;
@property({ type: Boolean }) streamerMode = false;
@query("mwc-snackbar", true) private _snackbar!: Snackbar;
@query("main", true) private container!: HTMLElement;
@query(".esphome-header", true) private editor_header!: HTMLElement;
@state() private _showSecrets = false;

createRenderRoot() {
return this;
}

protected render() {
const isSecrets =
this.fileName === "secrets.yaml" || this.fileName === "secrets.yml";
private _isSecrets() {
return this.fileName === "secrets.yaml" || this.fileName === "secrets.yml";
}

protected render() {
const isSecrets = this._isSecrets();
return html`
${commonStyle}
<style>
html,
body {
height: 100vh;
overflow: hidden;
}
.esphome-header {
display: flex;
justify-content: space-between;
align-items: center;
align-content: stretch;
}
h2 {
line-height: 100%;
/* this margin, padding stretches the container, offsetHeight does not calculate margin of .editor-header */
padding: 0.8rem 0.5rem 1rem 0.5rem;
margin: 0px;
font-size: 1.4rem;
flex: 1 1 auto;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
mwc-icon-button {
--mdc-icon-button-size: 32px;
}
Expand Down Expand Up @@ -101,9 +112,24 @@ class ESPHomeEditor extends LitElement {
></mwc-button>`}
</div>
<main></main>
${isSecrets && this.streamerMode && !this._showSecrets
? html`<streamer-warning
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be it's own dialog like how we open the wizard. The editor shouldn't know it's opening a secret. Just the header should, if streamer mode enabeld, prompt to confirm the user wants that before opening the editor. The editor should not be aware of streamer mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The editor is already aware of secrets - thats not something new...
And as mentioned before, I think this is better here for when the secrets have its own URL (the other part I am working on), the header wont be able to show a popup if the user went directly to /secrets...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only way a user can go to secrets is by pressing the button in the top toolbar. If they go any other way, streamer mode does not have to guard for that. The dialog needs to be it's own file.

@closed=${this.__handleSecretsWarning}
></streamer-warning>`
: ""}
`;
}

private __handleSecretsWarning(e: CustomEvent) {
if (e.detail.action === "close") {
this._handleClose();
} else if (e.detail.action === "accept") {
this._showSecrets = true;
// as the 1st update was skipped, fire firstUpdated again
setTimeout(() => this.firstUpdated(), 50);
}
}

public getValue() {
return this.editor!.getModel()?.getValue();
}
Expand Down Expand Up @@ -137,6 +163,10 @@ class ESPHomeEditor extends LitElement {
}

firstUpdated() {
const isSecrets = this._isSecrets();
if (isSecrets && this.streamerMode && !this._showSecrets) {
return;
}
// @ts-ignore
self.MonacoEnvironment = {
getWorkerUrl: function (moduleId: string, label: string) {
Expand All @@ -159,9 +189,6 @@ class ESPHomeEditor extends LitElement {
'ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace',
});

const isSecrets =
this.fileName === "secrets.yaml" || this.fileName === "secrets.yml";

getFile(this.fileName).then((response) => {
if (response === null && isSecrets) {
response = EMPTY_SECRETS;
Expand Down
54 changes: 54 additions & 0 deletions src/editor/streamer-warning.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { LitElement, css, html } from "lit";
import { customElement } from "lit/decorators.js";
import { fireEvent } from "../util/fire-event";
import { mdiIncognito } from "@mdi/js";

@customElement("streamer-warning")
export class ESPHomeStreamerWarning extends LitElement {
protected render() {
return html`
<mwc-dialog
open
scrimClickAction=""
@escapeKeyAction=${() => fireEvent(this, "closed", { action: "close" })}
@closed=${(e: any) =>
fireEvent(this, "closed", { action: e.detail.action })}
>
<div class="dialog-content">
<esphome-svg-icon .path=${mdiIncognito}></esphome-svg-icon>
<h3>Streamer mode enabled</h3>
<p>Are you sure you want to disclose your secrets?</p>
</div>
<mwc-button
slot="secondaryAction"
label="Cancel"
dialogAction="close"
></mwc-button>
<mwc-button
slot="primaryAction"
label="Show Secrets"
dialogAction="accept"
></mwc-button>
</<mwc-dialog>
`;
}

static styles = css`
.dialog-content {
text-align: center;
--mdc-theme-primary: var(--primary-text-color);
}
esphome-svg-icon {
--mdc-icon-size: 56px;
}
mwc-button {
--mdc-theme-primary: var(--primary-text-color);
}
`;
}

declare global {
interface HTMLElementTagNameMap {
"streamer-warning": ESPHomeStreamerWarning;
}
}
10 changes: 8 additions & 2 deletions src/esphome-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import "./components/esphome-header-menu";
import "./components/esphome-fab";
import { LitElement, html, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { ESPHomeBlurSecrets } from "./components/remote-process";

@customElement("esphome-main")
class ESPHomeMainView extends LitElement {
@property() version = "unknown";

@property() docsLink = "";

@property() logoutUrl?: string;
@property({ type: Boolean }) streamerMode = false;

@state() private editing?: string;

Expand All @@ -27,6 +27,7 @@ class ESPHomeMainView extends LitElement {
<esphome-editor
@close=${this._handleEditorClose}
fileName=${this.editing}
.streamerMode=${this.streamerMode}
></esphome-editor>
`;
}
Expand Down Expand Up @@ -61,6 +62,11 @@ class ESPHomeMainView extends LitElement {
return this;
}

connectedCallback() {
ESPHomeBlurSecrets.enabled = this.streamerMode;
super.connectedCallback();
}

protected firstUpdated(changedProps: PropertyValues): void {
super.firstUpdated(changedProps);
document.body.addEventListener<any>("edit-file", (ev) => {
Expand Down
8 changes: 6 additions & 2 deletions src/util/console-color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export class ColoredConsole {
constructor(public targetElement: HTMLElement) {}

logs(): string {
return this.targetElement.innerText;
const logs = this.targetElement.cloneNode(true) as HTMLElement;
logs.querySelectorAll(".log-secret").forEach((e) => (e.innerHTML = ""));
grahambrown11 marked this conversation as resolved.
Show resolved Hide resolved
return logs.innerText;
}

addLine(line: string) {
Expand Down Expand Up @@ -228,9 +230,11 @@ export const coloredConsoleStyles = `
-ms-user-select: none;
user-select: none;
}
.log.blur-secrets .log-secret {
filter: blur(5px);
}
.log-secret-redacted {
opacity: 0;
width: 1px;
font-size: 1px;
}
.log-fg-black {
Expand Down