Automatically adjust dialog position when the virtual keyboard is displayed, and allow input from the virtual keyboard to update value bindings in Svelte textfields.

This commit is contained in:
David Carley
2022-08-18 08:01:00 +00:00
parent 2554f0ea75
commit 1bd096e55c
8 changed files with 81 additions and 4 deletions

View File

@@ -4,6 +4,7 @@
import TextField from "@smui/textfield";
import MessageDialog from "$dialogs/MessageDialog.svelte";
import * as api from "$lib/api";
import { virtualKeyboardChangeHelper } from "$lib/customActions";
// https://man7.org/linux/man-pages/man7/hostname.7.html
//
@@ -72,15 +73,12 @@
<Content id="change-hostname-dialog-content">
<TextField
bind:value={hostname}
use={[[virtualKeyboardChangeHelper, (newValue) => (hostname = newValue)]]}
label="New Hostname"
spellcheck="false"
variant="filled"
style="width: 100%;"
/>
<p>
<em>Clicking Confirm will reboot the controller to apply the change.</em>
</p>
</Content>
<Actions>

View File

@@ -135,6 +135,67 @@
}
</script>
<script lang="ts">
import { onMount, onDestroy } from "svelte";
let bodyObserver: MutationObserver;
let keyboardObserver: MutationObserver;
onMount(() => {
bodyObserver = new MutationObserver(() => {
const virtualKeyboard = document.getElementById(
"virtualKeyboardChromeExtension"
);
if (virtualKeyboard) {
bodyObserver.disconnect();
bodyObserver = undefined;
const virtualKeyboardOverlay = document.getElementById(
"virtualKeyboardChromeExtensionOverlayScrollExtend"
);
keyboardObserver = new MutationObserver(() => {
const open = virtualKeyboard.getAttribute("_state") === "open";
const keyboardHeight = Number.parseFloat(
virtualKeyboardOverlay.style.height
);
const dialogContainers = document.querySelectorAll<HTMLDivElement>(
".mdc-dialog .mdc-dialog__container"
);
for (let dialogContainer of dialogContainers) {
dialogContainer.style["marginBottom"] = open
? `${keyboardHeight}px`
: "";
}
});
keyboardObserver.observe(virtualKeyboard, { attributes: true });
}
});
bodyObserver.observe(document.querySelector("body"), {
subtree: false,
childList: true,
});
});
onDestroy(() => {
if (bodyObserver) {
bodyObserver.disconnect();
bodyObserver = undefined;
}
if (keyboardObserver) {
keyboardObserver.disconnect();
keyboardObserver = undefined;
}
});
</script>
<HomeMachineDialog {...$HomeMachineDialogProps} />
<ProbeDialog {...$ProbeDialogProps} />
<ScreenRotationDialog {...$ScreenRotationDialogProps} />

View File

@@ -3,6 +3,7 @@
import TextField from "@smui/textfield";
import Button, { Label } from "@smui/button";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
import { virtualKeyboardChangeHelper } from "$lib/customActions";
export let open: boolean;
export let axis = "";
@@ -30,6 +31,7 @@
label="Absolute"
type="number"
bind:value
use={[[virtualKeyboardChangeHelper, (newValue) => (value = newValue)]]}
variant="filled"
style="width: 100%;"
/>

View File

@@ -3,6 +3,7 @@
import TextField from "@smui/textfield";
import Button, { Label } from "@smui/button";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
import { virtualKeyboardChangeHelper } from "$lib/customActions";
export let open: boolean;
export let axis = "";
@@ -42,6 +43,7 @@
label="Position"
type="number"
bind:value
use={[[virtualKeyboardChangeHelper, (newValue) => (value = newValue)]]}
spellcheck="false"
variant="filled"
style="width: 100%;"

View File

@@ -5,6 +5,7 @@
import CircularProgress from "@smui/circular-progress";
import VirtualList from "svelte-tiny-virtual-list";
import * as api from "$lib/api";
import { virtualKeyboardChangeHelper } from "$lib/customActions";
const itemHeight = 35;
@@ -153,6 +154,9 @@
<Label>Date & Time</Label>
<TextField
bind:value
use={[
[virtualKeyboardChangeHelper, (newValue) => (value = newValue)],
]}
label="Time"
type="datetime-local"
variant="filled"

View File

@@ -7,6 +7,7 @@
import MessageDialog from "$dialogs/MessageDialog.svelte";
import type { WifiNetwork } from "$lib/NetworkInfo";
import * as api from "$lib/api";
import { virtualKeyboardChangeHelper } from "$lib/customActions";
export let open = false;
export let network: WifiNetwork;
@@ -56,6 +57,7 @@
{#if needPassword}
<TextField
bind:value={password}
use={[[virtualKeyboardChangeHelper, (newValue) => (password = newValue)]]}
label="Password"
spellcheck="false"
variant="filled"

View File

@@ -0,0 +1,4 @@
export function virtualKeyboardChangeHelper(node: HTMLElement, cb: (value: any) => void) {
const input = node.querySelector("input");
input.addEventListener("keyup", () => cb(input.value));
}

View File

@@ -20,6 +20,10 @@
:root {
--mdc-theme-text-primary-on-background: #777;
.mdc-dialog .mdc-dialog__container {
transition: margin-bottom 0.5s;
}
.mdc-dialog .mdc-dialog__content {
color: #777;
}