mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Fix bug where sometimes Autocomplete menu would not show even though suggestions exist
This commit is contained in:
parent
8d8a559f73
commit
8fd4412dbe
4 changed files with 26 additions and 51 deletions
|
@ -11,11 +11,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export { className as class };
|
export { className as class };
|
||||||
|
|
||||||
export let labelledby: string | undefined = undefined;
|
export let labelledby: string | undefined = undefined;
|
||||||
|
export let show = false;
|
||||||
|
|
||||||
setContext(dropdownKey, null);
|
setContext(dropdownKey, null);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div {id} class="dropdown-menu" aria-labelledby={labelledby}>
|
<div {id} class="dropdown-menu" class:show aria-labelledby={labelledby}>
|
||||||
<div class="dropdown-content {className}">
|
<div class="dropdown-content {className}">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export let toggleOpen = true;
|
export let toggleOpen = true;
|
||||||
export let drop: "down" | "up" = "down";
|
export let drop: "down" | "up" = "down";
|
||||||
|
|
||||||
let placement: string;
|
let placement: "bottom" | "top";
|
||||||
$: switch (drop) {
|
$: switch (drop) {
|
||||||
case "down":
|
case "down":
|
||||||
placement = "bottom";
|
placement = "bottom";
|
||||||
|
@ -52,10 +52,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
dropdown = new Dropdown(toggle, {
|
dropdown = new Dropdown(toggle, {
|
||||||
autoClose,
|
autoClose,
|
||||||
popperConfig: (defaultConfig: Record<string, any>) => ({
|
popperConfig: { placement },
|
||||||
...defaultConfig,
|
|
||||||
placement,
|
|
||||||
}),
|
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
if (autoOpen) {
|
if (autoOpen) {
|
||||||
|
|
|
@ -14,7 +14,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import Tag from "./Tag.svelte";
|
import Tag from "./Tag.svelte";
|
||||||
import WithAutocomplete from "./WithAutocomplete.svelte";
|
import WithAutocomplete from "./WithAutocomplete.svelte";
|
||||||
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
||||||
import { controlPressed } from "lib/keys";
|
|
||||||
import type { Tag as TagType } from "./tags";
|
import type { Tag as TagType } from "./tags";
|
||||||
import {
|
import {
|
||||||
attachId,
|
attachId,
|
||||||
|
@ -34,12 +33,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
tags = names.map(replaceWithUnicodeSeparator).map(attachId);
|
tags = names.map(replaceWithUnicodeSeparator).map(attachId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const noSuggestions = Promise.resolve([]);
|
||||||
|
let suggestionsPromise: Promise<string[]> = noSuggestions;
|
||||||
|
|
||||||
function saveTags(): void {
|
function saveTags(): void {
|
||||||
bridgeCommand(
|
bridgeCommand(
|
||||||
`saveTags:${JSON.stringify(
|
`saveTags:${JSON.stringify(
|
||||||
tags.map((tag) => tag.name).map(replaceWithColons)
|
tags.map((tag) => tag.name).map(replaceWithColons)
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
suggestionsPromise = noSuggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
let active: number | null = null;
|
let active: number | null = null;
|
||||||
|
@ -48,9 +52,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
let activeInput: HTMLInputElement;
|
let activeInput: HTMLInputElement;
|
||||||
|
|
||||||
let autocomplete: any;
|
let autocomplete: any;
|
||||||
|
let autocompleteDisabled: boolean = false;
|
||||||
const noSuggestions = Promise.resolve([]);
|
|
||||||
let suggestionsPromise: Promise<string[]> = noSuggestions;
|
|
||||||
|
|
||||||
async function fetchSuggestions(input: string): Promise<string[]> {
|
async function fetchSuggestions(input: string): Promise<string[]> {
|
||||||
const data = await postRequest(
|
const data = await postRequest(
|
||||||
|
@ -67,12 +69,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const activeTag = tags[active!];
|
const activeTag = tags[active!];
|
||||||
const activeName = activeTag.name;
|
const activeName = activeTag.name;
|
||||||
|
|
||||||
suggestionsPromise =
|
autocompleteDisabled = activeName.length === 0;
|
||||||
activeName.length === 0
|
suggestionsPromise = autocompleteDisabled
|
||||||
? noSuggestions
|
? noSuggestions
|
||||||
: fetchSuggestions(activeTag.name).then((names: string[]): string[] =>
|
: fetchSuggestions(activeTag.name).then((names: string[]): string[] => {
|
||||||
names.map(replaceWithUnicodeSeparator)
|
autocompleteDisabled = names.length === 0;
|
||||||
);
|
return names.map(replaceWithUnicodeSeparator);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAutocomplete(selected: string): void {
|
function onAutocomplete(selected: string): void {
|
||||||
|
@ -254,27 +257,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
activeAfterBlur = null;
|
activeAfterBlur = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPrintableKey(event: KeyboardEvent): boolean {
|
|
||||||
return event.key.length === 1 && !controlPressed(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDeletionKey(event: KeyboardEvent): boolean {
|
|
||||||
return event.code === "Backspace" || event.code === "Delete";
|
|
||||||
}
|
|
||||||
|
|
||||||
function onKeydown(event: KeyboardEvent): void {
|
function onKeydown(event: KeyboardEvent): void {
|
||||||
const visible = autocomplete.isVisible();
|
|
||||||
const printable = isPrintableKey(event);
|
|
||||||
const deletion = isDeletionKey(event);
|
|
||||||
|
|
||||||
if (!visible) {
|
|
||||||
if (printable || deletion) {
|
|
||||||
autocomplete.show();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.code) {
|
switch (event.code) {
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
autocomplete.selectPrevious();
|
autocomplete.selectPrevious();
|
||||||
|
@ -464,12 +447,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
on:select={({ detail }) => onAutocomplete(detail.selected)}
|
on:select={({ detail }) => onAutocomplete(detail.selected)}
|
||||||
on:choose={({ detail }) => onAutocomplete(detail.chosen)}
|
on:choose={({ detail }) => onAutocomplete(detail.chosen)}
|
||||||
let:createAutocomplete
|
let:createAutocomplete
|
||||||
let:disabled
|
|
||||||
>
|
>
|
||||||
<TagInput
|
<TagInput
|
||||||
id={tag.id}
|
id={tag.id}
|
||||||
class="tag-input position-absolute start-0 top-0 ps-2 py-0"
|
class="tag-input position-absolute start-0 top-0 ps-2 py-0"
|
||||||
{disabled}
|
disabled={autocompleteDisabled}
|
||||||
bind:name={activeName}
|
bind:name={activeName}
|
||||||
bind:input={activeInput}
|
bind:input={activeInput}
|
||||||
on:focus={() => {
|
on:focus={() => {
|
||||||
|
|
|
@ -17,17 +17,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export let drop: "down" | "up" = "down";
|
export let drop: "down" | "up" = "down";
|
||||||
export let suggestionsPromise: Promise<string[]>;
|
export let suggestionsPromise: Promise<string[]>;
|
||||||
|
|
||||||
let disabled = true;
|
|
||||||
let dropdown: Dropdown;
|
let dropdown: Dropdown;
|
||||||
|
let show = false;
|
||||||
|
|
||||||
let suggestionsItems: string[] = [];
|
let suggestionsItems: string[] = [];
|
||||||
$: suggestionsPromise.then((items) => {
|
$: suggestionsPromise.then((items) => {
|
||||||
if (items.length > 0) {
|
show = items.length > 0;
|
||||||
disabled = false;
|
|
||||||
|
if (show) {
|
||||||
dropdown.show();
|
dropdown.show();
|
||||||
} else {
|
} else {
|
||||||
dropdown.hide();
|
dropdown.hide();
|
||||||
disabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suggestionsItems = items;
|
suggestionsItems = items;
|
||||||
|
@ -83,7 +83,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
async function chooseSelected() {
|
async function chooseSelected() {
|
||||||
active = true;
|
active = true;
|
||||||
dispatch("choose", { chosen: suggestionsItems[selected ?? -1] });
|
dispatch("choose", { chosen: suggestionsItems[selected ?? -1] });
|
||||||
|
|
||||||
await tick();
|
await tick();
|
||||||
|
show = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function update() {
|
async function update() {
|
||||||
|
@ -97,10 +99,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
return selected !== null;
|
return selected !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function disable(): void {
|
|
||||||
disabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const createAutocomplete =
|
const createAutocomplete =
|
||||||
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
||||||
(element: HTMLElement): any => {
|
(element: HTMLElement): any => {
|
||||||
|
@ -116,7 +114,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
chooseSelected,
|
chooseSelected,
|
||||||
update,
|
update,
|
||||||
hasSelected,
|
hasSelected,
|
||||||
disable,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
|
@ -141,14 +138,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
setSelected(index);
|
setSelected(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy(() => dropdown?.dispose());
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<WithDropdown {drop} toggleOpen={false} let:createDropdown>
|
<WithDropdown {drop} toggleOpen={false} let:createDropdown>
|
||||||
<slot createAutocomplete={createAutocomplete(createDropdown)} {disabled} />
|
<slot createAutocomplete={createAutocomplete(createDropdown)} />
|
||||||
|
|
||||||
<DropdownMenu class={className}>
|
<DropdownMenu class={className} {show}>
|
||||||
{#each suggestionsItems as suggestion, index}
|
{#each suggestionsItems as suggestion, index}
|
||||||
<AutocompleteItem
|
<AutocompleteItem
|
||||||
selected={index === selected}
|
selected={index === selected}
|
||||||
|
|
Loading…
Reference in a new issue