Notes/src/public/app/widgets/dialogs/jump_to_note.js

126 lines
5.0 KiB
JavaScript
Raw Normal View History

2024-07-24 17:34:26 +08:00
import { t } from "../../services/i18n.js";
2025-01-09 18:07:02 +02:00
import noteAutocompleteService from "../../services/note_autocomplete.js";
import utils from "../../services/utils.js";
2022-12-01 13:07:23 +01:00
import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
const TPL = `<div class="jump-to-note-dialog modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="input-group">
2025-01-09 18:07:02 +02:00
<input class="jump-to-note-autocomplete form-control" placeholder="${t("jump_to_note.search_placeholder")}">
</div>
2025-01-09 18:07:02 +02:00
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("jump_to_note.close")}"></button>
</div>
<div class="modal-body">
<div class="algolia-autocomplete-container jump-to-note-results"></div>
</div>
<div class="modal-footer">
2025-01-09 18:07:02 +02:00
<button class="show-in-full-text-button btn btn-sm">${t("jump_to_note.search_button")}</button>
</div>
</div>
</div>
</div>`;
const KEEP_LAST_SEARCH_FOR_X_SECONDS = 120;
export default class JumpToNoteDialog extends BasicWidget {
constructor() {
super();
this.lastOpenedTs = 0;
}
doRender() {
this.$widget = $(TPL);
2024-09-03 18:15:10 +02:00
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
2024-09-02 19:37:02 +02:00
this.$autoComplete = this.$widget.find(".jump-to-note-autocomplete");
this.$results = this.$widget.find(".jump-to-note-results");
this.$showInFullTextButton = this.$widget.find(".show-in-full-text-button");
2025-01-09 18:07:02 +02:00
this.$showInFullTextButton.on("click", (e) => this.showInFullText(e));
2025-01-09 18:07:02 +02:00
shortcutService.bindElShortcut(this.$widget, "ctrl+return", (e) => this.showInFullText(e));
}
async jumpToNoteEvent() {
2025-01-09 18:07:02 +02:00
const dialogPromise = utils.openDialog(this.$widget);
if (utils.isMobile()) {
dialogPromise.then(($dialog) => {
const el = $dialog.find(">.modal-dialog")[0];
function reposition() {
const offset = 100;
const modalHeight = window.visualViewport.height - offset;
const safeAreaInsetBottom = window.visualViewport.height - window.innerHeight;
el.style.height = `${modalHeight}px`;
el.style.bottom = `${window.visualViewport.height - modalHeight - safeAreaInsetBottom - offset}px`;
}
this.$autoComplete.on("focus", () => {
reposition();
});
window.visualViewport.addEventListener("resize", () => {
reposition();
});
reposition();
});
}
// first open dialog, then refresh since refresh is doing focus which should be visible
this.refresh();
this.lastOpenedTs = Date.now();
}
async refresh() {
2025-01-09 18:07:02 +02:00
noteAutocompleteService
.initNoteAutocomplete(this.$autoComplete, {
allowCreatingNotes: true,
hideGoToSelectedNoteButton: true,
allowJumpToSearchNotes: true,
container: this.$results
})
// clear any event listener added in previous invocation of this function
2025-01-09 18:07:02 +02:00
.off("autocomplete:noteselected")
.on("autocomplete:noteselected", function (event, suggestion, dataset) {
if (!suggestion.notePath) {
return false;
}
appContext.tabManager.getActiveContext().setNote(suggestion.notePath);
});
2023-05-05 23:41:11 +02:00
// if you open the Jump To dialog soon after using it previously, it can often mean that you
// actually want to search for the same thing (e.g., you opened the wrong note at first try)
// so we'll keep the content.
2023-05-05 23:41:11 +02:00
// if it's outside of this time limit, then we assume it's a completely new search and show recent notes instead.
if (Date.now() - this.lastOpenedTs > KEEP_LAST_SEARCH_FOR_X_SECONDS * 1000) {
noteAutocompleteService.showRecentNotes(this.$autoComplete);
} else {
this.$autoComplete
// hack, the actual search value is stored in <pre> element next to the search input
// this is important because the search input value is replaced with the suggestion note's title
.autocomplete("val", this.$autoComplete.next().text())
2025-01-09 18:07:02 +02:00
.trigger("focus")
.trigger("select");
}
}
showInFullText(e) {
2023-06-30 11:18:34 +02:00
// stop from propagating upwards (dangerous, especially with ctrl+enter executable javascript notes)
e.preventDefault();
e.stopPropagation();
const searchString = this.$autoComplete.val();
2025-01-09 18:07:02 +02:00
this.triggerCommand("searchNotes", { searchString });
2024-09-03 18:15:10 +02:00
this.modal.hide();
}
}