Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/components/inputhints/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import "./style.scss";
* @param {HTMLInputElement} $input Input field
* @param {Array<Hint>|HintCallback} hints Hints or a callback to generate hints
* @param {(value: string) => void} onSelect Callback to call when a hint is selected
* @param {object} [options]
* @param {boolean} [options.dynamic] Regenerate hints when input changes
* @returns {{getSelected: ()=>HTMLLIElement, container: HTMLUListElement}}
*/
export default function inputhints($input, hints, onSelect) {
export default function inputhints($input, hints, onSelect, options = {}) {
/**@type {HTMLUListElement} */
const $ul = <Ul />;
const LIMIT = 100;
Expand All @@ -38,14 +40,26 @@ export default function inputhints($input, hints, onSelect) {
let updateUlTimeout;
let pages = 0;
let currentHints = [];
let hintProvider = null;
let dynamicUpdateTimeout = 0;
let dynamicUpdateVersion = 0;

$input.addEventListener("focus", onfocus);

if (typeof hints === "function") {
const cb = hints;
hintProvider = cb;
hints = [];
$ul.content = [<Hint hint={{ value: "", text: strings["loading..."] }} />];
cb(setHints, hintModification());
const version = ++dynamicUpdateVersion;
cb(
(list) => {
if (!options.dynamic || version === dynamicUpdateVersion)
setHints(list);
},
hintModification(),
"",
);
} else {
setHints(hints);
}
Expand Down Expand Up @@ -139,6 +153,21 @@ export default function inputhints($input, hints, onSelect) {
*/
function oninput() {
const { value: toTest } = this;
if (options.dynamic && hintProvider) {
clearTimeout(dynamicUpdateTimeout);
const version = ++dynamicUpdateVersion;
dynamicUpdateTimeout = setTimeout(() => {
hintProvider(
(list) => {
if (version === dynamicUpdateVersion) setHints(list);
},
hintModification(),
toTest,
);
}, 120);
return;
}

const matched = [];
const regexp = new RegExp(escapeRegExp(toTest), "i");
hints.forEach((hint) => {
Expand Down Expand Up @@ -171,6 +200,8 @@ export default function inputhints($input, hints, onSelect) {
if (preventUpdate) return;

clearTimeout(updateUlTimeout);
clearTimeout(dynamicUpdateTimeout);
dynamicUpdateVersion += 1;
$input.removeEventListener("keypress", handleKeypress);
$input.removeEventListener("keydown", handleKeydown);
$input.removeEventListener("blur", onblur);
Expand Down Expand Up @@ -215,6 +246,7 @@ export default function inputhints($input, hints, onSelect) {
* @param {Array<Hint>} list Hint items
*/
function setHints(list) {
pages = 0;
if (Array.isArray(list)) {
hints = list;
} else {
Expand Down
16 changes: 12 additions & 4 deletions src/components/palette/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,20 @@ This shows that using keyboardHideStart event is faster than not using it.
* @param {()=>string} onsSelectCb Callback to call when a hint is selected
* @param {string} placeholder Placeholder for input
* @param {function} onremove Callback to call when palette is removed
* @param {object} [options]
* @param {boolean} [options.dynamic] Regenerate hints when the query changes
* @returns {void}
*/
// Track active palette for chaining
let activePalette = null;

export default function palette(getList, onsSelectCb, placeholder, onremove) {
export default function palette(
getList,
onsSelectCb,
placeholder,
onremove,
options = {},
) {
// Store previous palette if exists
const previousPalette = activePalette;
const isChained = !!previousPalette;
Expand All @@ -69,7 +77,7 @@ export default function palette(getList, onsSelectCb, placeholder, onremove) {
const $palette = <div id="palette">{$input}</div>;

// Create a palette with input and hints
inputhints($input, generateHints, onSelect);
inputhints($input, generateHints, onSelect, options);

// Only set the darkened theme when this is not a chained palette
if (!isChained) {
Expand Down Expand Up @@ -137,8 +145,8 @@ export default function palette(getList, onsSelectCb, placeholder, onremove) {
* @param {HintCallback} setHints Set hints callback
* @param {HintModification} hintModification Hint modification object
*/
async function generateHints(setHints, hintModification) {
const list = getList(hintModification);
async function generateHints(setHints, hintModification, query) {
const list = getList(hintModification, query);
const data = list instanceof Promise ? await list : list;
setHints(data);
}
Expand Down
17 changes: 16 additions & 1 deletion src/lib/acode.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import windowResize from "handlers/windowResize";
import actionStack from "lib/actionStack";
import commands from "lib/commands";
import EditorFile from "lib/editorFile";
import fileIndex from "lib/fileIndex";
import files from "lib/fileList";
import fileTypeHandler from "lib/fileTypeHandler";
import fonts from "lib/fonts";
Expand Down Expand Up @@ -365,7 +366,21 @@ class Acode {
this.define("dialogBox", dialog);
this.define("prompt", prompt);
this.define("intent", intent);
this.define("fileList", files);
let didWarnAboutFileList = false;
const deprecatedFileList = (...args) => {
if (!didWarnAboutFileList) {
didWarnAboutFileList = true;
console.warn(
'acode.require("fileList") is deprecated. Use the asynchronous "fileIndex" API. fileList now contains only non-native storage providers.',
);
}
return files(...args);
};
Object.assign(deprecatedFileList, files);
deprecatedFileList.deprecated = true;
deprecatedFileList.replacement = "fileIndex";
this.define("fileList", deprecatedFileList);
this.define("fileIndex", fileIndex);
this.define("fs", fsOperation);
this.define("confirm", confirm);
this.define("helpers", helpers);
Expand Down
Loading