mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
add force hide and auto hide of autocomplete details
This commit is contained in:
@ -4116,6 +4116,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div name="AutoCompleteToggle">
|
<div name="AutoCompleteToggle">
|
||||||
<h4 data-i18n="AutoComplete Settings">AutoComplete Settings</h4>
|
<h4 data-i18n="AutoComplete Settings">AutoComplete Settings</h4>
|
||||||
|
<label data-newbie-hidden class="checkbox_label" for="stscript_autocomplete_autoHide">
|
||||||
|
<input id="stscript_autocomplete_autoHide" type="checkbox" />
|
||||||
|
<small data-i18n="Automatically hide details">
|
||||||
|
Automatically hide details
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
<div class="flex1" title="Determines how entries are found for autocomplete." data-i18n="[title]Determines how entries are found for autocomplete.">
|
<div class="flex1" title="Determines how entries are found for autocomplete." data-i18n="[title]Determines how entries are found for autocomplete.">
|
||||||
<label for="stscript_matching" data-i18n="Autocomplete Matching"><small>Matching</small></label>
|
<label for="stscript_matching" data-i18n="Autocomplete Matching"><small>Matching</small></label>
|
||||||
|
@ -25,6 +25,8 @@ export class AutoComplete {
|
|||||||
/**@type {boolean}*/ isReplaceable = false;
|
/**@type {boolean}*/ isReplaceable = false;
|
||||||
/**@type {boolean}*/ isShowingDetails = false;
|
/**@type {boolean}*/ isShowingDetails = false;
|
||||||
/**@type {boolean}*/ wasForced = false;
|
/**@type {boolean}*/ wasForced = false;
|
||||||
|
/**@type {boolean}*/ isForceHidden = false;
|
||||||
|
/**@type {boolean}*/ canBeAutoHidden = false;
|
||||||
|
|
||||||
/**@type {string}*/ text;
|
/**@type {string}*/ text;
|
||||||
/**@type {AutoCompleteNameResult}*/ parserResult;
|
/**@type {AutoCompleteNameResult}*/ parserResult;
|
||||||
@ -57,6 +59,10 @@ export class AutoComplete {
|
|||||||
return power_user.stscript.matching ?? 'fuzzy';
|
return power_user.stscript.matching ?? 'fuzzy';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get autoHide() {
|
||||||
|
return power_user.stscript.autocomplete.autoHide ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -224,6 +230,16 @@ export class AutoComplete {
|
|||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
basicAutoHideCheck() {
|
||||||
|
// auto hide only if at least one char has been typed after the name + space
|
||||||
|
return this.textarea.selectionStart > this.parserResult.start
|
||||||
|
+ this.parserResult.name.length
|
||||||
|
+ (this.startQuote ? 1 : 0)
|
||||||
|
+ (this.endQuote ? 1 : 0)
|
||||||
|
+ 1
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the autocomplete.
|
* Show the autocomplete.
|
||||||
* @param {boolean} isInput Whether triggered by input.
|
* @param {boolean} isInput Whether triggered by input.
|
||||||
@ -244,6 +260,9 @@ export class AutoComplete {
|
|||||||
return this.hide();
|
return this.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// disable force-hide if trigger was forced
|
||||||
|
if (isForced) this.isForceHidden = false;
|
||||||
|
|
||||||
// request provider to get name result (potentially "incomplete", i.e. not an actual existing name) for
|
// request provider to get name result (potentially "incomplete", i.e. not an actual existing name) for
|
||||||
// cursor position
|
// cursor position
|
||||||
this.parserResult = await this.getNameAt(this.text, this.textarea.selectionStart);
|
this.parserResult = await this.getNameAt(this.text, this.textarea.selectionStart);
|
||||||
@ -275,12 +294,16 @@ export class AutoComplete {
|
|||||||
this.name = this.name.slice(0, this.textarea.selectionStart - (this.parserResult.start) - (this.startQuote ? 1 : 0));
|
this.name = this.name.slice(0, this.textarea.selectionStart - (this.parserResult.start) - (this.startQuote ? 1 : 0));
|
||||||
this.parserResult.name = this.name;
|
this.parserResult.name = this.name;
|
||||||
this.isReplaceable = true;
|
this.isReplaceable = true;
|
||||||
|
this.isForceHidden = false;
|
||||||
|
this.canBeAutoHidden = false;
|
||||||
} else {
|
} else {
|
||||||
this.isReplaceable = false;
|
this.isReplaceable = false;
|
||||||
|
this.canBeAutoHidden = this.basicAutoHideCheck();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if not forced and no user input -> just show details
|
// if not forced and no user input -> just show details
|
||||||
this.isReplaceable = false;
|
this.isReplaceable = false;
|
||||||
|
this.canBeAutoHidden = this.basicAutoHideCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isForced || isInput || isSelect) {
|
if (isForced || isInput || isSelect) {
|
||||||
@ -292,8 +315,11 @@ export class AutoComplete {
|
|||||||
this.secondaryParserResult = result;
|
this.secondaryParserResult = result;
|
||||||
this.name = this.secondaryParserResult.name;
|
this.name = this.secondaryParserResult.name;
|
||||||
this.isReplaceable = isForced || this.secondaryParserResult.isRequired;
|
this.isReplaceable = isForced || this.secondaryParserResult.isRequired;
|
||||||
|
this.isForceHidden = false;
|
||||||
|
this.canBeAutoHidden = false;
|
||||||
} else {
|
} else {
|
||||||
this.isReplaceable = false;
|
this.isReplaceable = false;
|
||||||
|
this.canBeAutoHidden = this.basicAutoHideCheck();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,7 +340,17 @@ export class AutoComplete {
|
|||||||
// filter the list of options by the partial name according to the matching type
|
// filter the list of options by the partial name according to the matching type
|
||||||
.filter(it => this.isReplaceable || it.name == '' ? matchers[this.matchType](it.name) : it.name.toLowerCase() == this.name)
|
.filter(it => this.isReplaceable || it.name == '' ? matchers[this.matchType](it.name) : it.name.toLowerCase() == this.name)
|
||||||
// remove aliases
|
// remove aliases
|
||||||
.filter((it,idx,list) => list.findIndex(opt=>opt.value == it.value) == idx)
|
.filter((it,idx,list) => list.findIndex(opt=>opt.value == it.value) == idx);
|
||||||
|
|
||||||
|
if (this.result.length == 0 && this.effectiveParserResult != this.parserResult && isForced) {
|
||||||
|
// no matching secondary results and forced trigger -> show current command details
|
||||||
|
this.secondaryParserResult = null;
|
||||||
|
this.result = [this.effectiveParserResult.optionList.find(it=>it.name == this.effectiveParserResult.name)];
|
||||||
|
this.name = this.effectiveParserResult.name;
|
||||||
|
this.fuzzyRegex = /(.*)(.*)(.*)/;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.result
|
||||||
// update remaining options
|
// update remaining options
|
||||||
.map(option => {
|
.map(option => {
|
||||||
// build element
|
// build element
|
||||||
@ -336,6 +372,15 @@ export class AutoComplete {
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (this.isForceHidden) {
|
||||||
|
// hidden with escape
|
||||||
|
return this.hide();
|
||||||
|
}
|
||||||
|
if (this.autoHide && this.canBeAutoHidden && !isForced && this.effectiveParserResult == this.parserResult && this.result.length == 1) {
|
||||||
|
// auto hide user setting enabled and somewhere after name part and would usually show command details
|
||||||
|
return this.hide();
|
||||||
|
}
|
||||||
if (this.result.length == 0) {
|
if (this.result.length == 0) {
|
||||||
if (!isInput) {
|
if (!isInput) {
|
||||||
// no result and no input? hide autocomplete
|
// no result and no input? hide autocomplete
|
||||||
@ -683,6 +728,8 @@ export class AutoComplete {
|
|||||||
if (evt.ctrlKey || evt.altKey || evt.shiftKey) return;
|
if (evt.ctrlKey || evt.altKey || evt.shiftKey) return;
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
this.isForceHidden = true;
|
||||||
|
this.wasForced = false;
|
||||||
this.hide();
|
this.hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -259,6 +259,7 @@ let power_user = {
|
|||||||
stscript: {
|
stscript: {
|
||||||
matching: 'fuzzy',
|
matching: 'fuzzy',
|
||||||
autocomplete: {
|
autocomplete: {
|
||||||
|
autoHide: false,
|
||||||
style: 'theme',
|
style: 'theme',
|
||||||
font: {
|
font: {
|
||||||
scale: 0.8,
|
scale: 0.8,
|
||||||
@ -1618,6 +1619,7 @@ function loadPowerUserSettings(settings, data) {
|
|||||||
$('#token_padding').val(power_user.token_padding);
|
$('#token_padding').val(power_user.token_padding);
|
||||||
$('#aux_field').val(power_user.aux_field);
|
$('#aux_field').val(power_user.aux_field);
|
||||||
|
|
||||||
|
$('#stscript_autocomplete_autoHide').prop('checked', power_user.stscript.autocomplete.autoHide ?? false).trigger('input');
|
||||||
$('#stscript_matching').val(power_user.stscript.matching ?? 'fuzzy');
|
$('#stscript_matching').val(power_user.stscript.matching ?? 'fuzzy');
|
||||||
$('#stscript_autocomplete_style').val(power_user.stscript.autocomplete_style ?? 'theme');
|
$('#stscript_autocomplete_style').val(power_user.stscript.autocomplete_style ?? 'theme');
|
||||||
document.body.setAttribute('data-stscript-style', power_user.stscript.autocomplete_style);
|
document.body.setAttribute('data-stscript-style', power_user.stscript.autocomplete_style);
|
||||||
@ -3646,6 +3648,11 @@ $(document).ready(() => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#stscript_autocomplete_autoHide').on('input', function () {
|
||||||
|
power_user.stscript.autocomplete.autoHide = !!$(this).prop('checked');
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
$('#stscript_matching').on('change', function () {
|
$('#stscript_matching').on('change', function () {
|
||||||
const value = $(this).find(':selected').val();
|
const value = $(this).find(':selected').val();
|
||||||
power_user.stscript.matching = String(value);
|
power_user.stscript.matching = String(value);
|
||||||
|
Reference in New Issue
Block a user