mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-10 02:02:29 +08:00
chore(client/ts): port more files
This commit is contained in:
parent
7f4f8bcc75
commit
4e7572cf04
@ -177,7 +177,7 @@ export type CommandMappings = {
|
||||
ExecuteCommandData<TextEditor> & {
|
||||
callback?: GetTextEditorCallback;
|
||||
};
|
||||
executeWithCodeEditor: CommandData & ExecuteCommandData<null>;
|
||||
executeWithCodeEditor: CommandData & ExecuteCommandData<CodeMirrorInstance>;
|
||||
/**
|
||||
* Called upon when attempting to retrieve the content element of a {@link NoteContext}.
|
||||
* Generally should not be invoked manually, as it is used by {@link NoteContext.getContentElement}.
|
||||
@ -246,7 +246,7 @@ export type CommandMappings = {
|
||||
|
||||
toggleZenMode: CommandData;
|
||||
|
||||
updateAttributeList: CommandData & { attributes: FAttribute[] };
|
||||
updateAttributeList: CommandData & { attributes: Attribute[] };
|
||||
saveAttributes: CommandData;
|
||||
reloadAttributes: CommandData;
|
||||
refreshNoteList: CommandData & { noteId: string };
|
||||
|
@ -311,7 +311,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
|
||||
async getCodeEditor() {
|
||||
return this.timeout(
|
||||
new Promise((resolve) =>
|
||||
new Promise<CodeMirrorInstance>((resolve) =>
|
||||
appContext.triggerCommand("executeWithCodeEditor", {
|
||||
resolve,
|
||||
ntxId: this.ntxId
|
||||
|
@ -1,7 +1,7 @@
|
||||
import utils from "./utils.js";
|
||||
|
||||
type ElementType = HTMLElement | Document;
|
||||
type Handler = (e: JQuery.TriggeredEvent<ElementType, string, ElementType, ElementType>) => void;
|
||||
type Handler = (e: JQuery.TriggeredEvent<ElementType | Element, string, ElementType | Element, ElementType | Element>) => void;
|
||||
|
||||
function removeGlobalShortcut(namespace: string) {
|
||||
bindGlobalShortcut("", null, namespace);
|
||||
@ -11,7 +11,7 @@ function bindGlobalShortcut(keyboardShortcut: string, handler: Handler | null, n
|
||||
bindElShortcut($(document), keyboardShortcut, handler, namespace);
|
||||
}
|
||||
|
||||
function bindElShortcut($el: JQuery<ElementType>, keyboardShortcut: string, handler: Handler | null, namespace: string | null = null) {
|
||||
function bindElShortcut($el: JQuery<ElementType | Element>, keyboardShortcut: string, handler: Handler | null, namespace: string | null = null) {
|
||||
if (utils.isDesktop()) {
|
||||
keyboardShortcut = normalizeShortcut(keyboardShortcut);
|
||||
|
||||
|
42
src/public/app/types.d.ts
vendored
42
src/public/app/types.d.ts
vendored
@ -184,6 +184,48 @@ declare global {
|
||||
}
|
||||
};
|
||||
|
||||
var CodeMirror: {
|
||||
(el: HTMLElement, opts: {
|
||||
value: string;
|
||||
viewportMargin: number;
|
||||
indentUnit: number;
|
||||
matchBrackets: boolean;
|
||||
matchTags: { bothTags: boolean };
|
||||
highlightSelectionMatches: {
|
||||
showToken: boolean;
|
||||
annotateScrollbar: boolean;
|
||||
};
|
||||
lineNumbers: boolean;
|
||||
lineWrapping: boolean;
|
||||
}): CodeMirrorInstance;
|
||||
keyMap: {
|
||||
default: Record<string, string>;
|
||||
};
|
||||
modeURL: string;
|
||||
modeInfo: ModeInfo[];
|
||||
findModeByMIME(mime: string): ModeInfo;
|
||||
autoLoadMode(instance: CodeMirrorInstance, mode: string)
|
||||
}
|
||||
|
||||
interface ModeInfo {
|
||||
name: string;
|
||||
mode: string;
|
||||
mime: string;
|
||||
mimes: string[];
|
||||
}
|
||||
|
||||
interface CodeMirrorInstance {
|
||||
getValue(): string;
|
||||
setValue(val: string);
|
||||
clearHistory();
|
||||
setOption(name: string, value: string);
|
||||
refresh();
|
||||
focus();
|
||||
setCursor(line: number, col: number);
|
||||
lineCount(): number;
|
||||
on(event: string, callback: () => void);
|
||||
}
|
||||
|
||||
var katex: {
|
||||
renderToString(text: string, opts: {
|
||||
throwOnError: boolean
|
||||
|
@ -42,10 +42,21 @@ const TPL = `
|
||||
|
||||
const MAX_DISPLAYED_NOTES = 15;
|
||||
|
||||
// TODO: Deduplicate with server.
|
||||
interface QuickSearchResponse {
|
||||
searchResultNoteIds: string[];
|
||||
error: string;
|
||||
}
|
||||
|
||||
export default class QuickSearchWidget extends BasicWidget {
|
||||
|
||||
private dropdown!: bootstrap.Dropdown;
|
||||
private $searchString!: JQuery<HTMLElement>;
|
||||
private $dropdownMenu!: JQuery<HTMLElement>;
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
|
||||
this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]);
|
||||
|
||||
this.$searchString = this.$widget.find(".search-string");
|
||||
this.$dropdownMenu = this.$widget.find(".dropdown-menu");
|
||||
@ -88,7 +99,7 @@ export default class QuickSearchWidget extends BasicWidget {
|
||||
}
|
||||
|
||||
async search() {
|
||||
const searchString = this.$searchString.val().trim();
|
||||
const searchString = String(this.$searchString.val())?.trim();
|
||||
|
||||
if (!searchString) {
|
||||
this.dropdown.hide();
|
||||
@ -98,10 +109,10 @@ export default class QuickSearchWidget extends BasicWidget {
|
||||
this.$dropdownMenu.empty();
|
||||
this.$dropdownMenu.append(`<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span>${t("quick-search.searching")}</span>`);
|
||||
|
||||
const { searchResultNoteIds, error } = await server.get(`quick-search/${encodeURIComponent(searchString)}`);
|
||||
const { searchResultNoteIds, error } = await server.get<QuickSearchResponse>(`quick-search/${encodeURIComponent(searchString)}`);
|
||||
|
||||
if (error) {
|
||||
let tooltip = new Tooltip(this.$searchString, {
|
||||
let tooltip = new Tooltip(this.$searchString[0], {
|
||||
trigger: "manual",
|
||||
title: `Search error: ${error}`,
|
||||
placement: "right"
|
||||
@ -164,7 +175,7 @@ export default class QuickSearchWidget extends BasicWidget {
|
||||
this.dropdown.hide();
|
||||
|
||||
await appContext.triggerCommand("searchNotes", {
|
||||
searchString: this.$searchString.val()
|
||||
searchString: String(this.$searchString.val())
|
||||
});
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import froca from "../../services/froca.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import options from "../../services/options.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import type FNote from "../../entities/fnote.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="edited-notes-widget">
|
||||
@ -15,27 +16,39 @@ const TPL = `
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="no-edited-notes-found">${t("edited_notes.no_edited_notes_found")}</div>
|
||||
|
||||
|
||||
<div class="edited-notes-list"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// TODO: Deduplicate with server.
|
||||
interface EditedNotesResponse {
|
||||
noteId: string;
|
||||
isDeleted: boolean;
|
||||
title: string;
|
||||
notePath: string[];
|
||||
}
|
||||
|
||||
export default class EditedNotesWidget extends NoteContextAwareWidget {
|
||||
|
||||
private $list!: JQuery<HTMLElement>;
|
||||
private $noneFound!: JQuery<HTMLElement>;
|
||||
|
||||
get name() {
|
||||
return "editedNotes";
|
||||
}
|
||||
|
||||
isEnabled() {
|
||||
return super.isEnabled() && this.note.hasOwnedLabel("dateNote");
|
||||
return super.isEnabled() && this.note?.hasOwnedLabel("dateNote");
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
return {
|
||||
show: this.isEnabled(),
|
||||
// promoted attributes have priority over edited notes
|
||||
activate: (this.note.getPromotedDefinitionAttributes().length === 0 || !options.is("promotedAttributesOpenInRibbon")) && options.is("editedNotesOpenInRibbon"),
|
||||
activate: (this.note?.getPromotedDefinitionAttributes().length === 0 || !options.is("promotedAttributesOpenInRibbon")) && options.is("editedNotesOpenInRibbon"),
|
||||
title: t("edited_notes.title"),
|
||||
icon: "bx bx-calendar-edit"
|
||||
};
|
||||
@ -48,8 +61,8 @@ export default class EditedNotesWidget extends NoteContextAwareWidget {
|
||||
this.$noneFound = this.$widget.find(".no-edited-notes-found");
|
||||
}
|
||||
|
||||
async refreshWithNote(note) {
|
||||
let editedNotes = await server.get(`edited-notes/${note.getLabelValue("dateNote")}`);
|
||||
async refreshWithNote(note: FNote) {
|
||||
let editedNotes = await server.get<EditedNotesResponse[]>(`edited-notes/${note.getLabelValue("dateNote")}`);
|
||||
|
||||
editedNotes = editedNotes.filter((n) => n.noteId !== note.noteId);
|
||||
|
@ -3,6 +3,7 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import AttributeDetailWidget from "../attribute_widgets/attribute_detail.js";
|
||||
import AttributeEditorWidget from "../attribute_widgets/attribute_editor.js";
|
||||
import type { CommandListenerData } from "../../components/app_context.js";
|
||||
import type FAttribute from "../../entities/fattribute.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="attribute-list">
|
||||
@ -75,7 +76,8 @@ export default class OwnedAttributeListWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
|
||||
async updateAttributeListCommand({ attributes }: CommandListenerData<"updateAttributeList">) {
|
||||
await this.attributeEditorWidget.updateAttributeList(attributes);
|
||||
// TODO: See why we need FAttribute[] and Attribute[]
|
||||
await this.attributeEditorWidget.updateAttributeList(attributes as FAttribute[]);
|
||||
}
|
||||
|
||||
focus() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import TypeWidget from "./type_widget.js";
|
||||
import libraryLoader from "../../services/library_loader.js";
|
||||
import options from "../../services/options.js";
|
||||
import type FNote from "../../entities/fnote.js";
|
||||
|
||||
/**
|
||||
* An abstract {@link TypeWidget} which implements the CodeMirror editor, meant to be used as a parent for
|
||||
@ -16,6 +17,10 @@ import options from "../../services/options.js";
|
||||
* - Call `this._update(note, content)` in `#doRefresh(note)`.
|
||||
*/
|
||||
export default class AbstractCodeTypeWidget extends TypeWidget {
|
||||
|
||||
protected $editor!: JQuery<HTMLElement>;
|
||||
protected codeEditor!: CodeMirrorInstance;
|
||||
|
||||
doRender() {
|
||||
this.initialized = this.#initEditor();
|
||||
}
|
||||
@ -28,8 +33,14 @@ export default class AbstractCodeTypeWidget extends TypeWidget {
|
||||
delete CodeMirror.keyMap.default["Alt-Right"];
|
||||
|
||||
CodeMirror.modeURL = `${window.glob.assetPath}/node_modules/codemirror/mode/%N/%N.js`;
|
||||
CodeMirror.modeInfo.find((mode) => mode.name === "JavaScript").mimes.push(...["application/javascript;env=frontend", "application/javascript;env=backend"]);
|
||||
CodeMirror.modeInfo.find((mode) => mode.name === "SQLite").mimes = ["text/x-sqlite", "text/x-sqlite;schema=trilium"];
|
||||
const jsMode = CodeMirror.modeInfo.find((mode) => mode.name === "JavaScript");
|
||||
if (jsMode) {
|
||||
jsMode.mimes.push(...["application/javascript;env=frontend", "application/javascript;env=backend"]);
|
||||
}
|
||||
const sqlMode = CodeMirror.modeInfo.find((mode) => mode.name === "SQLite");
|
||||
if (sqlMode) {
|
||||
sqlMode.mimes = ["text/x-sqlite", "text/x-sqlite;schema=trilium"];
|
||||
}
|
||||
|
||||
this.codeEditor = CodeMirror(this.$editor[0], {
|
||||
value: "",
|
||||
@ -73,7 +84,7 @@ export default class AbstractCodeTypeWidget extends TypeWidget {
|
||||
* @param {*} note the note that was changed.
|
||||
* @param {*} content the new content of the note.
|
||||
*/
|
||||
_update(note, content) {
|
||||
_update(note: { mime: string }, content: string) {
|
||||
// CodeMirror breaks pretty badly on null, so even though it shouldn't happen (guarded by a consistency check)
|
||||
// we provide fallback
|
||||
this.codeEditor.setValue(content || "");
|
@ -21,7 +21,6 @@ const TPL = `<div style="height: 100%; display: flex; flex-direction: column;">
|
||||
|
||||
export default class BackendLogWidget extends AbstractCodeTypeWidget {
|
||||
|
||||
private $editor!: JQuery<HTMLElement>;
|
||||
private $refreshBackendLog!: JQuery<HTMLElement>;
|
||||
|
||||
doRender() {
|
||||
@ -45,7 +44,7 @@ export default class BackendLogWidget extends AbstractCodeTypeWidget {
|
||||
}
|
||||
|
||||
async load() {
|
||||
const content = await server.get("backend-log");
|
||||
const content = await server.get<string>("backend-log");
|
||||
await this.initialized;
|
||||
|
||||
this._update(
|
||||
|
@ -24,8 +24,6 @@ const TPL = `
|
||||
|
||||
export default class EditableCodeTypeWidget extends AbstractCodeTypeWidget {
|
||||
|
||||
private $editor!: JQuery<HTMLElement>;
|
||||
|
||||
static getType() {
|
||||
return "editableCode";
|
||||
}
|
||||
@ -59,7 +57,7 @@ export default class EditableCodeTypeWidget extends AbstractCodeTypeWidget {
|
||||
const blob = await this.note?.getBlob();
|
||||
|
||||
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||
this._update(note, blob?.content);
|
||||
this._update(note, blob?.content ?? "");
|
||||
});
|
||||
|
||||
this.show();
|
||||
|
@ -19,7 +19,6 @@ const TPL = `
|
||||
</div>`;
|
||||
|
||||
export default class ReadOnlyCodeTypeWidget extends AbstractCodeTypeWidget {
|
||||
$editor!: JQuery<HTMLElement>;
|
||||
|
||||
static getType() {
|
||||
return "readOnlyCode";
|
||||
|
Loading…
x
Reference in New Issue
Block a user