improve message input box

This commit is contained in:
hippoz 2023-07-23 18:58:53 +03:00
parent 17a7aaafdd
commit 97847288fc
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
3 changed files with 39 additions and 8 deletions

View file

@ -1,7 +1,7 @@
<script>
import { onDestroy, onMount } from "svelte";
import { getItem } from "../storage";
import { selectedChannel, sendMessageAction, setMessageInputEvent, smallViewport, typingStore, userInfoStore } from "../stores";
import { overlayStore, selectedChannel, sendMessageAction, setMessageInputEvent, smallViewport, typingStore, userInfoStore, usesKeyboardNavigation } from "../stores";
export let channel;
let messageInput = "";
@ -65,14 +65,21 @@
const unsubscribers = [];
// Focus the text area when the component first loads, or when the user selects another channel
const focusTextarea = () => {
if (messageTextarea && getItem("ui:useragent:formFactor") !== "touch") {
messageTextarea.focus();
const handleDocumentKeydown = () => {
if (document.activeElement && (["input", "textarea"]).includes(document.activeElement.tagName.toLowerCase())) {
return;
}
if (overlayStore.isOverlayPresent()) {
return;
}
messageTextarea.focus();
};
onMount(focusTextarea);
unsubscribers.push(selectedChannel.on(focusTextarea));
onMount(() => {
document.addEventListener("keydown", handleDocumentKeydown);
return () => document.removeEventListener("keydown", handleDocumentKeydown);
});
// Handle the setMessageInput event
unsubscribers.push(setMessageInputEvent.on((value) => {
@ -121,7 +128,11 @@
contain: strict;
}
/* TODO: is this good? */
.message-input:focus-visible {
outline: none;
}
.message-input.keyboard-nav:focus-visible {
outline: 2px solid var(--purple-2);
}
@ -179,6 +190,7 @@
bind:value={ messageInput }
bind:this={ messageTextarea }
class:small={ $smallViewport || getItem("ui:alwaysUseMobileChatBar") }
class:keyboard-nav={ $usesKeyboardNavigation }
/>
{#if $smallViewport || getItem("ui:alwaysUseMobileChatBar")}
<button class="icon-button send-button material-icons-outlined" on:click="{ sendMessage }">

View file

@ -1,5 +1,5 @@
import { getItem } from "./storage";
import { showSidebar, smallViewport, theme } from "./stores";
import { showSidebar, smallViewport, theme, usesKeyboardNavigation } from "./stores";
function initViewportSizeHandler() {
const root = document.querySelector(':root');
@ -33,8 +33,22 @@ function updateTheme(themeName) {
classes.add(`theme--${themeName}`);
}
function initKeyboardNavigationDetection() {
document.addEventListener("keydown", ({ key }) => {
if (key === "Tab") {
usesKeyboardNavigation.set(true);
}
});
document.addEventListener("click", e => {
// screenX and screenY are 0 when a user presses enter for navigation
usesKeyboardNavigation.set(!e.screenX && !e.screenY);
});
}
export function initResponsiveHandlers() {
initViewportSizeHandler();
initKeyboardNavigationDetection();
const mediaQuery = window.matchMedia('(min-width: 768px)');

View file

@ -410,6 +410,10 @@ class OverlayStore extends Store {
super([], "OverlayStore");
}
isOverlayPresent() {
return !!this.value.length;
}
push(type, props={}) {
const id = Math.floor(Math.random() * 9999999);
@ -840,6 +844,7 @@ export const selectedChannel = new SelectedChannelStore();
export const showSidebar = new Store(true, "showSidebar");
export const showPresenceSidebar = new Store(false, "showPresenceSidebar");
export const smallViewport = new Store(false, "smallViewport");
export const usesKeyboardNavigation = new Store(false, "usesKeyboardNavigation");
export const showChannelView = new Store(true, "showChannelView");
export const theme = new StorageItemStore("ui:theme");
export const sendTypingUpdatesItemStore = new StorageItemStore("ui:online:sendTypingUpdates");