mirror of
https://github.com/callumalpass/tasknotes.git
synced 2026-07-22 12:50:26 +00:00
Add CMD/Ctrl+Enter keyboard shortcuts to modals
Added keyboard event handlers to all modals to enable quick save/submit with CMD/Ctrl+Enter. Each modal now properly registers and cleans up its keyboard handler on open/close. Also added kanban card container styles for scrolling and drag cursor states, and removed deprecated tsconfig ignoreDeprecations flag.
This commit is contained in:
parent
b8c3747e72
commit
ef8d9eb750
9 changed files with 138 additions and 1 deletions
|
|
@ -27,6 +27,7 @@ export class ICSNoteCreationModal extends Modal {
|
|||
private templateContainer: HTMLElement;
|
||||
private templateInput: HTMLInputElement;
|
||||
private previewContainer: HTMLElement;
|
||||
private keyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
constructor(app: App, plugin: TaskNotesPlugin, options: ICSNoteCreationOptions) {
|
||||
super(app);
|
||||
|
|
@ -42,10 +43,26 @@ export class ICSNoteCreationModal extends Modal {
|
|||
|
||||
onOpen() {
|
||||
this.containerEl.addClass("tasknotes-plugin", "ics-note-creation-modal");
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.keyboardHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.handleCreate();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.keyboardHandler);
|
||||
|
||||
this.createModalContent();
|
||||
}
|
||||
|
||||
onClose() {
|
||||
// Clean up keyboard handler
|
||||
if (this.keyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.keyboardHandler);
|
||||
this.keyboardHandler = null;
|
||||
}
|
||||
|
||||
this.contentEl.empty();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export class PropertySelectorModal extends Modal {
|
|||
private tempSelection: string[];
|
||||
private modalTitle: string;
|
||||
private modalDescription: string;
|
||||
private keyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
|
|
@ -33,6 +34,16 @@ export class PropertySelectorModal extends Modal {
|
|||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.keyboardHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.onSubmit(this.tempSelection);
|
||||
this.close();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.keyboardHandler);
|
||||
|
||||
contentEl.createEl("h2", { text: this.modalTitle });
|
||||
|
||||
contentEl.createEl("p", {
|
||||
|
|
@ -91,6 +102,12 @@ export class PropertySelectorModal extends Modal {
|
|||
}
|
||||
|
||||
onClose() {
|
||||
// Clean up keyboard handler
|
||||
if (this.keyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.keyboardHandler);
|
||||
this.keyboardHandler = null;
|
||||
}
|
||||
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export class TaskEditModal extends TaskModal {
|
|||
private task: TaskInfo;
|
||||
private options: TaskEditOptions;
|
||||
private metadataContainer: HTMLElement;
|
||||
private editModalKeyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
// Changed from Set to array for consistency with other state management
|
||||
private completedInstancesChanges: string[] = [];
|
||||
private calendarWrapper: HTMLElement | null = null;
|
||||
|
|
@ -227,6 +228,16 @@ export class TaskEditModal extends TaskModal {
|
|||
// Set the modal title using the standard Obsidian approach (preserves close button)
|
||||
this.titleEl.setText(this.getModalTitle());
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.editModalKeyboardHandler = async (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
await this.handleSave();
|
||||
this.close();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.editModalKeyboardHandler);
|
||||
|
||||
this.initializeFormData().then(() => {
|
||||
this.createModalContent();
|
||||
// Render projects list after modal content is created
|
||||
|
|
@ -371,6 +382,12 @@ export class TaskEditModal extends TaskModal {
|
|||
}
|
||||
|
||||
onClose(): void {
|
||||
// Clean up keyboard handler
|
||||
if (this.editModalKeyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.editModalKeyboardHandler);
|
||||
this.editModalKeyboardHandler = null;
|
||||
}
|
||||
|
||||
// Clean up markdown editor
|
||||
if (this.markdownEditor) {
|
||||
this.markdownEditor.destroy();
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ interface DependencyItem {
|
|||
|
||||
export abstract class TaskModal extends Modal {
|
||||
plugin: TaskNotesPlugin;
|
||||
private keyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
// Dependency item definition
|
||||
protected createDependencyItemFromFile(
|
||||
|
|
@ -486,6 +487,20 @@ export abstract class TaskModal extends Modal {
|
|||
// Set the modal title using the standard Obsidian approach (preserves close button)
|
||||
this.titleEl.setText(this.getModalTitle());
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.keyboardHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
// Skip if event comes from a markdown editor (which has its own handler)
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.closest('.cm-editor')) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
this.handleSave();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.keyboardHandler);
|
||||
|
||||
this.initializeFormData().then(() => {
|
||||
this.createModalContent();
|
||||
this.focusTitleInput();
|
||||
|
|
@ -1889,6 +1904,12 @@ export abstract class TaskModal extends Modal {
|
|||
}
|
||||
|
||||
onClose(): void {
|
||||
// Clean up keyboard handler
|
||||
if (this.keyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.keyboardHandler);
|
||||
this.keyboardHandler = null;
|
||||
}
|
||||
|
||||
// Clean up markdown editor if it exists
|
||||
if (this.detailsMarkdownEditor) {
|
||||
this.detailsMarkdownEditor.destroy();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export class TimeEntryEditorModal extends Modal {
|
|||
private onSave: (timeEntries: TimeEntry[]) => void;
|
||||
private translate: (key: TranslationKey, variables?: Record<string, any>) => string;
|
||||
private entriesContainerEl: HTMLElement;
|
||||
private keyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
|
|
@ -37,6 +38,15 @@ export class TimeEntryEditorModal extends Modal {
|
|||
this.translate("modals.timeEntryEditor.title", { taskTitle: this.task.title })
|
||||
);
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.keyboardHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.save();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.keyboardHandler);
|
||||
|
||||
// Create container for entries
|
||||
this.entriesContainerEl = contentEl.createDiv({ cls: "time-entry-editor-modal__entries" });
|
||||
|
||||
|
|
@ -261,6 +271,12 @@ export class TimeEntryEditorModal extends Modal {
|
|||
}
|
||||
|
||||
onClose() {
|
||||
// Clean up keyboard handler
|
||||
if (this.keyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.keyboardHandler);
|
||||
this.keyboardHandler = null;
|
||||
}
|
||||
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ export class TimeblockCreationModal extends Modal {
|
|||
// Attachment management
|
||||
private selectedAttachments: TAbstractFile[] = [];
|
||||
private attachmentsList: HTMLElement;
|
||||
private keyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
constructor(app: App, plugin: TaskNotesPlugin, options: TimeblockCreationOptions) {
|
||||
super(app);
|
||||
|
|
@ -56,6 +57,15 @@ export class TimeblockCreationModal extends Modal {
|
|||
contentEl.empty();
|
||||
contentEl.addClass("timeblock-creation-modal");
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.keyboardHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.handleSubmit();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.keyboardHandler);
|
||||
|
||||
new Setting(contentEl).setName(this.translate("modals.timeblockCreation.heading")).setHeading();
|
||||
|
||||
// Date display (read-only)
|
||||
|
|
@ -386,6 +396,12 @@ export class TimeblockCreationModal extends Modal {
|
|||
}
|
||||
|
||||
onClose() {
|
||||
// Clean up keyboard handler
|
||||
if (this.keyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.keyboardHandler);
|
||||
this.keyboardHandler = null;
|
||||
}
|
||||
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ export class TimeblockInfoModal extends Modal {
|
|||
// Attachment management
|
||||
private selectedAttachments: TAbstractFile[] = [];
|
||||
private attachmentsList: HTMLElement;
|
||||
private keyboardHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
|
|
@ -70,6 +71,15 @@ export class TimeblockInfoModal extends Modal {
|
|||
contentEl.empty();
|
||||
contentEl.addClass("timeblock-info-modal");
|
||||
|
||||
// Add global keyboard shortcut handler for CMD/Ctrl+Enter
|
||||
this.keyboardHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.handleSave();
|
||||
}
|
||||
};
|
||||
this.containerEl.addEventListener("keydown", this.keyboardHandler);
|
||||
|
||||
new Setting(contentEl).setName(this.translate("modals.timeblockInfo.editHeading")).setHeading();
|
||||
|
||||
// Date and time display (read-only)
|
||||
|
|
@ -505,6 +515,12 @@ export class TimeblockInfoModal extends Modal {
|
|||
}
|
||||
|
||||
onClose() {
|
||||
// Clean up keyboard handler
|
||||
if (this.keyboardHandler) {
|
||||
this.containerEl.removeEventListener("keydown", this.keyboardHandler);
|
||||
this.keyboardHandler = null;
|
||||
}
|
||||
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,6 +376,24 @@
|
|||
KANBAN TASK CARDS
|
||||
================================================ */
|
||||
|
||||
/* Cards container (used for non-virtualized columns) */
|
||||
.tasknotes-plugin .kanban-view__cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--tn-spacing-xs);
|
||||
overflow-y: auto; /* Allow vertical scrolling */
|
||||
flex: 1; /* Fill available space in column */
|
||||
min-height: 0; /* Allow container to shrink and enable scrolling */
|
||||
}
|
||||
|
||||
/* Dragging state for card wrappers */
|
||||
.tasknotes-plugin .kanban-view__card-wrapper[draggable="true"]:hover {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.tasknotes-plugin .kanban-view__card-wrapper[draggable="true"]:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* ================================================
|
||||
RESPONSIVE DESIGN
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"ignoreDeprecations": "6.0",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
|
|
|
|||
Loading…
Reference in a new issue