Skip to content

Commit

Permalink
Allow to mask text in paste dialog (#1764)
Browse files Browse the repository at this point in the history
Related #1739.

This PR optionally allows users to mask the input copy in the paste
dialog, for privacy reasons.

- We [explored and discussed some UI approaches
initially](#1763), and the
“redacted text” technique seemed like the best compromise between
simplicity and effectiveness. It’s basically struck-through text with a
stroke thickness that matches the line height.
- I moved down the keyboard hint, to accommodate the toggle button above
the dialog. To me, it would feel justified to style the text as
[subsidiary](https://github.com/tiny-pilot/tinypilot/blob/22b3e8ec354861b948a09ac0c8a14bac1e0952a1/app/templates/styleguide.html#L76-L77)
(i.e., with reduced font size and slightly diminished color).
- After clicking the toggle button, we give focus to the text area,
because it seems likely that the user wants that.


https://github.com/tiny-pilot/tinypilot/assets/83721279/e66827cf-8858-4c82-8ec3-55ab9d87bca6

<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1764"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>

---------

Co-authored-by: Jan Heuermann <[email protected]>
  • Loading branch information
jotaen4tinypilot and jotaen authored Apr 1, 2024
1 parent 066fbc8 commit d2c09f9
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
2 changes: 1 addition & 1 deletion app/static/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,8 @@ menuBar.addEventListener("video-settings-dialog-requested", () => {
document.getElementById("video-settings-overlay").show();
});
menuBar.addEventListener("paste-dialog-requested", () => {
document.getElementById("paste-overlay").show();
document.getElementById("paste-dialog").initialize();
document.getElementById("paste-overlay").show();
});
menuBar.addEventListener("ctrl-alt-del-requested", () => {
// Even though only the final keystroke matters, send them one at a time to
Expand Down
60 changes: 56 additions & 4 deletions app/templates/custom-elements/paste-dialog.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template id="paste-dialog-template">
<style>
@import "css/style.css";
@import "css/toggle.css";

#paste-area {
display: block;
Expand All @@ -13,12 +14,48 @@
border: 1px solid var(--brand-metallic-dark);
border-radius: var(--border-radius);
}

:host([mask-input=""]) #paste-area {
/* We mask the input text by making it look redacted. This is kind of a
workaround, since there is no such thing as `type=password` for
<textarea> elements, and <input> elements don’t support multiline
values.
The strike-through thickness must be so that even “tall”
characters are fully concealed, e.g., `Ü` (high) or `p` (low). It
should not, however, merge with adjacent lines.
The caret color is so that it differentiates itself in both contexts,
i.e. against redacted text and against the white background. */
color: #333;
text-decoration: line-through;
text-decoration-thickness: 1.25em;
caret-color: #999;
}

.toggle-container {
display: flex;
align-items: center;
justify-content: end;
margin: 0.5em;
}

.toggle-container label {
margin-left: 0.5em;
}

.hint {
margin: 0.5em 0 1em 0;
color: #333;
font-size: 0.9em;
}
</style>
<h3>Paste Text</h3>
<p>
Note: The target system must have an <span class="monospace">en-US</span> or
<span class="monospace">en-GB</span> keyboard layout.
</p>
<div class="toggle-container">
Hide Characters
<label class="toggle">
<input type="checkbox" id="mask-input" />
<span class="toggle-slider"></span>
</label>
</div>
<textarea
id="paste-area"
class="monospace"
Expand All @@ -27,6 +64,10 @@ <h3>Paste Text</h3>
autocapitalize="off"
spellcheck="false"
></textarea>
<div class="hint">
The target system must have an <span class="monospace">en-US</span> or
<span class="monospace">en-GB</span> keyboard layout.
</div>
<button id="confirm-btn" class="btn-success">Paste</button>
<button id="cancel-btn">Close</button>
</template>
Expand All @@ -49,6 +90,7 @@ <h3>Paste Text</h3>
pasteArea: this.shadowRoot.querySelector("#paste-area"),
confirmButton: this.shadowRoot.querySelector("#confirm-btn"),
cancelButton: this.shadowRoot.querySelector("#cancel-btn"),
maskInputButton: this.shadowRoot.querySelector("#mask-input"),
};
this._elements.pasteArea.addEventListener("input", () =>
this._elements.confirmButton.toggleAttribute(
Expand All @@ -70,9 +112,14 @@ <h3>Paste Text</h3>
this._elements.cancelButton.addEventListener("click", () =>
this._closeDialog()
);
this._elements.maskInputButton.addEventListener("input", (event) => {
this._onToggleMaskInput(event.target.checked);
});
}

initialize() {
this.toggleAttribute("mask-input", false);
this._elements.maskInputButton.checked = false;
this._elements.pasteArea.value = "";
this._elements.pasteArea.focus();
this._elements.confirmButton.toggleAttribute("disabled", true);
Expand Down Expand Up @@ -103,6 +150,11 @@ <h3>Paste Text</h3>
_closeDialog() {
this.dispatchEvent(new DialogClosedEvent());
}

_onToggleMaskInput(isMasked) {
this.toggleAttribute("mask-input", isMasked);
this._elements.pasteArea.focus();
}
}
);
})();
Expand Down

0 comments on commit d2c09f9

Please sign in to comment.