mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
feat(quick-capture): enhance minimal modal with editable target and resolved paths
- Add FileSuggest to checkbox mode for editable target file selection - Display resolved file paths in file mode (process date templates) - Keep quick action buttons visible in both checkbox and file modes - Update minimal modal styling for improved UX
This commit is contained in:
parent
aaa4ff43eb
commit
b9213964d0
2 changed files with 127 additions and 38 deletions
|
|
@ -12,6 +12,8 @@ import {
|
|||
TaskMetadata,
|
||||
} from "./BaseQuickCaptureModal";
|
||||
import { moment } from "obsidian";
|
||||
import { processDateTemplates } from "@/utils/file/file-operations";
|
||||
import { FileSuggest } from "@/components/ui/inputs/AutoComplete";
|
||||
|
||||
/**
|
||||
* Minimal Quick Capture Modal extending the base class
|
||||
|
|
@ -26,10 +28,12 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
// Suggest instances
|
||||
private minimalSuggest: MinimalQuickCaptureSuggest;
|
||||
private universalSuggest: UniversalEditorSuggest | null = null;
|
||||
private fileSuggest: FileSuggest | null = null;
|
||||
|
||||
// UI element references
|
||||
private targetIndicator: HTMLElement | null = null;
|
||||
private fileNameInput: HTMLInputElement | null = null;
|
||||
private targetFileEl: HTMLDivElement | null = null;
|
||||
private editorContainer: HTMLElement | null = null;
|
||||
|
||||
constructor(app: App, plugin: TaskProgressBarPlugin) {
|
||||
|
|
@ -48,6 +52,7 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
onOpen() {
|
||||
// Store modal instance reference for suggest system
|
||||
(this.modalEl as any).__minimalQuickCaptureModal = this;
|
||||
this.modalEl.toggleClass('tg-minimal-capture-modal', true);
|
||||
|
||||
// Set up the suggest system
|
||||
if (this.minimalSuggest) {
|
||||
|
|
@ -132,35 +137,81 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
this.targetIndicator.empty();
|
||||
|
||||
if (this.currentMode === "checkbox") {
|
||||
// Show target file for checkbox mode
|
||||
// Show editable target file for checkbox mode
|
||||
const label = this.targetIndicator.createSpan({
|
||||
cls: "quick-capture-target-label",
|
||||
text: t("To: "),
|
||||
});
|
||||
|
||||
const target = this.targetIndicator.createSpan({
|
||||
cls: "quick-capture-target-value",
|
||||
// Create contenteditable element for target file path
|
||||
this.targetFileEl = this.targetIndicator.createEl("div", {
|
||||
cls: "quick-capture-target",
|
||||
attr: {
|
||||
contenteditable: "true",
|
||||
spellcheck: "false",
|
||||
},
|
||||
text: this.tempTargetFilePath,
|
||||
});
|
||||
|
||||
// Add FileSuggest for file selection
|
||||
this.fileSuggest = new FileSuggest(
|
||||
this.app,
|
||||
this.targetFileEl,
|
||||
this.plugin.settings.quickCapture,
|
||||
(file) => {
|
||||
this.targetFileEl!.textContent = file.path;
|
||||
this.tempTargetFilePath = file.path;
|
||||
this.taskMetadata.targetFile = file.path;
|
||||
this.markdownEditor?.editor?.focus();
|
||||
}
|
||||
);
|
||||
|
||||
// Update tempTargetFilePath when manually edited
|
||||
this.targetFileEl.addEventListener("blur", () => {
|
||||
if (this.targetFileEl) {
|
||||
this.tempTargetFilePath = this.targetFileEl.textContent || "";
|
||||
this.taskMetadata.targetFile = this.tempTargetFilePath;
|
||||
}
|
||||
});
|
||||
|
||||
// Show quick action buttons
|
||||
const buttonsContainer = this.contentContainer?.querySelector(".quick-capture-minimal-quick-actions");
|
||||
if (buttonsContainer) {
|
||||
(buttonsContainer as HTMLElement).style.display = "flex";
|
||||
}
|
||||
} else {
|
||||
// Show file name input for file mode
|
||||
// Show file name input for file mode with resolved path
|
||||
const label = this.targetIndicator.createSpan({
|
||||
cls: "quick-capture-target-label",
|
||||
text: t("Save as: "),
|
||||
});
|
||||
|
||||
// Get the template value and resolve it immediately
|
||||
const templateValue = this.taskMetadata.customFileName || this.plugin.settings.quickCapture.defaultFileNameTemplate || "{{DATE:YYYY-MM-DD}} - ";
|
||||
let resolvedPath = processDateTemplates(templateValue);
|
||||
|
||||
// Add default folder if configured
|
||||
const defaultFolder = this.plugin.settings.quickCapture.createFileMode?.defaultFolder?.trim();
|
||||
if (
|
||||
this.plugin.settings?.fileSource?.enabled &&
|
||||
defaultFolder &&
|
||||
!resolvedPath.includes("/")
|
||||
) {
|
||||
resolvedPath = `${defaultFolder}/${resolvedPath}`;
|
||||
}
|
||||
|
||||
// Add .md extension if not present
|
||||
if (!resolvedPath.endsWith(".md")) {
|
||||
resolvedPath += ".md";
|
||||
}
|
||||
|
||||
// Create input with resolved path (editable)
|
||||
this.fileNameInput = this.targetIndicator.createEl("input", {
|
||||
cls: "quick-capture-minimal-file-input",
|
||||
attr: {
|
||||
type: "text",
|
||||
placeholder: t("Enter file name..."),
|
||||
value: this.taskMetadata.customFileName || this.plugin.settings.quickCapture.defaultFileNameTemplate || "{{DATE:YYYY-MM-DD}} - ",
|
||||
value: resolvedPath,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -171,10 +222,10 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
}
|
||||
});
|
||||
|
||||
// Hide quick action buttons
|
||||
// Keep quick action buttons visible in file mode
|
||||
const buttonsContainer = this.contentContainer?.querySelector(".quick-capture-minimal-quick-actions");
|
||||
if (buttonsContainer) {
|
||||
(buttonsContainer as HTMLElement).style.display = "none";
|
||||
(buttonsContainer as HTMLElement).style.display = "flex";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -189,7 +240,7 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
|
||||
this.dateButton = leftContainer.createEl("button", {
|
||||
cls: ["quick-action-button", "clickable-icon"],
|
||||
attr: { "aria-label": t("Set date") },
|
||||
attr: {"aria-label": t("Set date")},
|
||||
});
|
||||
setIcon(this.dateButton, "calendar");
|
||||
this.dateButton.addEventListener("click", () => this.showDatePicker());
|
||||
|
|
@ -197,7 +248,7 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
|
||||
this.priorityButton = leftContainer.createEl("button", {
|
||||
cls: ["quick-action-button", "clickable-icon"],
|
||||
attr: { "aria-label": t("Set priority") },
|
||||
attr: {"aria-label": t("Set priority")},
|
||||
});
|
||||
setIcon(this.priorityButton, "zap");
|
||||
this.priorityButton.addEventListener("click", () =>
|
||||
|
|
@ -210,7 +261,7 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
|
||||
this.locationButton = leftContainer.createEl("button", {
|
||||
cls: ["quick-action-button", "clickable-icon"],
|
||||
attr: { "aria-label": t("Set location") },
|
||||
attr: {"aria-label": t("Set location")},
|
||||
});
|
||||
setIcon(this.locationButton, "folder");
|
||||
this.locationButton.addEventListener("click", () =>
|
||||
|
|
@ -219,15 +270,16 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
this.updateButtonState(
|
||||
this.locationButton,
|
||||
this.taskMetadata.location !==
|
||||
(this.plugin.settings.quickCapture.targetType || "fixed")
|
||||
(this.plugin.settings.quickCapture.targetType || "fixed")
|
||||
);
|
||||
|
||||
this.tagButton = leftContainer.createEl("button", {
|
||||
cls: ["quick-action-button", "clickable-icon"],
|
||||
attr: { "aria-label": t("Add tags") },
|
||||
attr: {"aria-label": t("Add tags")},
|
||||
});
|
||||
setIcon(this.tagButton, "tag");
|
||||
this.tagButton.addEventListener("click", () => {});
|
||||
this.tagButton.addEventListener("click", () => {
|
||||
});
|
||||
this.updateButtonState(
|
||||
this.tagButton,
|
||||
!!(this.taskMetadata.tags && this.taskMetadata.tags.length > 0)
|
||||
|
|
@ -318,13 +370,13 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
|
||||
public showDatePicker(cursor?: EditorPosition, coords?: any) {
|
||||
const quickDates = [
|
||||
{ label: t("Tomorrow"), date: moment().add(1, "day").toDate() },
|
||||
{label: t("Tomorrow"), date: moment().add(1, "day").toDate()},
|
||||
{
|
||||
label: t("Day after tomorrow"),
|
||||
date: moment().add(2, "day").toDate(),
|
||||
},
|
||||
{ label: t("Next week"), date: moment().add(1, "week").toDate() },
|
||||
{ label: t("Next month"), date: moment().add(1, "month").toDate() },
|
||||
{label: t("Next week"), date: moment().add(1, "week").toDate()},
|
||||
{label: t("Next month"), date: moment().add(1, "month").toDate()},
|
||||
];
|
||||
|
||||
const menu = new Menu();
|
||||
|
|
@ -373,11 +425,11 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
|
||||
public showPriorityMenu(cursor?: EditorPosition, coords?: any) {
|
||||
const priorities = [
|
||||
{ level: 5, label: t("Highest"), icon: "🔺" },
|
||||
{ level: 4, label: t("High"), icon: "⏫" },
|
||||
{ level: 3, label: t("Medium"), icon: "🔼" },
|
||||
{ level: 2, label: t("Low"), icon: "🔽" },
|
||||
{ level: 1, label: t("Lowest"), icon: "⏬" },
|
||||
{level: 5, label: t("Highest"), icon: "🔺"},
|
||||
{level: 4, label: t("High"), icon: "⏫"},
|
||||
{level: 3, label: t("Medium"), icon: "🔼"},
|
||||
{level: 2, label: t("Low"), icon: "🔽"},
|
||||
{level: 1, label: t("Lowest"), icon: "⏬"},
|
||||
];
|
||||
|
||||
const menu = new Menu();
|
||||
|
|
@ -424,8 +476,8 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
this.updateButtonState(
|
||||
this.locationButton!,
|
||||
this.taskMetadata.location !==
|
||||
(this.plugin.settings.quickCapture.targetType ||
|
||||
"fixed")
|
||||
(this.plugin.settings.quickCapture.targetType ||
|
||||
"fixed")
|
||||
);
|
||||
|
||||
// If called from suggest, replace the 📁 with file text
|
||||
|
|
@ -444,8 +496,8 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
this.updateButtonState(
|
||||
this.locationButton!,
|
||||
this.taskMetadata.location !==
|
||||
(this.plugin.settings.quickCapture?.targetType ||
|
||||
"fixed")
|
||||
(this.plugin.settings.quickCapture?.targetType ||
|
||||
"fixed")
|
||||
);
|
||||
|
||||
// If called from suggest, replace the 📁 with daily note text
|
||||
|
|
@ -497,7 +549,7 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
if (cm && cm.replaceRange) {
|
||||
cm.replaceRange(
|
||||
replacement,
|
||||
{ line: cursor.line, ch: cursor.ch - 1 },
|
||||
{line: cursor.line, ch: cursor.ch - 1},
|
||||
cursor
|
||||
);
|
||||
}
|
||||
|
|
@ -718,6 +770,12 @@ export class MinimalQuickCaptureModal extends BaseQuickCaptureModal {
|
|||
this.universalSuggest = null;
|
||||
}
|
||||
|
||||
// Clean up file suggest
|
||||
if (this.fileSuggest) {
|
||||
this.fileSuggest.close();
|
||||
this.fileSuggest = null;
|
||||
}
|
||||
|
||||
// Clean up suggest
|
||||
if (this.minimalSuggest) {
|
||||
this.minimalSuggest.setMinimalMode(false);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/* Quick Capture Enhanced Styles - with shadcn theme */
|
||||
|
||||
/* shadcn-inspired theme colors integrated with Task Genius */
|
||||
:root {
|
||||
/* Tab component colors */
|
||||
--tg-tab-background: 0 0% 100%;
|
||||
|
|
@ -8,6 +7,9 @@
|
|||
--tg-tab-muted: 240 4.8% 95.9%;
|
||||
--tg-tab-muted-foreground: 240 3.8% 46.1%;
|
||||
--tg-tab-border: 240 5.9% 90%;
|
||||
|
||||
/* Quick Capture Header background (light) */
|
||||
--tg-qc-header-bg: 0 0% 100%;
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
|
|
@ -16,16 +18,27 @@
|
|||
--tg-tab-muted: 240 3.7% 15.9%;
|
||||
--tg-tab-muted-foreground: 240 5% 64.9%;
|
||||
--tg-tab-border: 240 3.7% 15.9%;
|
||||
|
||||
/* Quick Capture Header background (dark) */
|
||||
--tg-qc-header-bg: 240 4% 10%;
|
||||
}
|
||||
|
||||
/* Quick Capture Header - shadcn style */
|
||||
/* Quick Capture Header - shadcn style, with custom background for header */
|
||||
.quick-capture-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid hsl(var(--tg-tab-border));
|
||||
background: hsl(var(--tg-tab-background));
|
||||
background: hsl(var(--tg-qc-header-bg));
|
||||
}
|
||||
|
||||
.tg-minimal-capture-modal .quick-capture-header {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.tg-minimal-capture-modal .model-header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Quick Capture Tabs - shadcn style */
|
||||
|
|
@ -54,6 +67,14 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.tg-minimal-capture-modal .quick-capture-tab-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tg-minimal-capture-modal .quick-capture-tab-icon {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.quick-capture-tab:hover:not(.active) {
|
||||
color: hsl(var(--tg-tab-foreground));
|
||||
}
|
||||
|
|
@ -98,9 +119,9 @@
|
|||
}
|
||||
|
||||
.quick-capture-clear:hover {
|
||||
background: hsl(var(--tg-tab-muted));
|
||||
color: hsl(var(--tg-tab-foreground));
|
||||
border-color: hsl(var(--tg-tab-muted-foreground));
|
||||
/*background: hsl(var(--tg-tab-muted));*/
|
||||
/*color: hsl(var(--tg-tab-foreground));*/
|
||||
/*border-color: hsl(var(--tg-tab-muted-foreground));*/
|
||||
}
|
||||
|
||||
/* Quick Capture Content */
|
||||
|
|
@ -207,15 +228,25 @@
|
|||
.quick-capture-modal.quick-capture-checkbox {
|
||||
width: 800px;
|
||||
max-width: 90vw;
|
||||
height: 600px;
|
||||
height: 700px;
|
||||
max-height: 80vh;
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
||||
.quick-capture-modal.quick-capture-file {
|
||||
width: 700px;
|
||||
width: 800px;
|
||||
max-width: 90vw;
|
||||
height: 500px;
|
||||
max-height: 70vh;
|
||||
height: 750px;
|
||||
max-height: 80vh;
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
||||
.quick-capture-modal.tg-minimal-capture-modal {
|
||||
width: 600px;
|
||||
max-width: 90vw;
|
||||
height: 300px;
|
||||
max-height: 80vh;
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
||||
/* Quick Capture Panel */
|
||||
|
|
@ -268,8 +299,6 @@
|
|||
|
||||
/* Minimal Quick Capture Target Display */
|
||||
.quick-capture-minimal-target-container {
|
||||
padding: 8px 12px;
|
||||
background: hsl(var(--tg-tab-muted));
|
||||
border-radius: 6px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
|
@ -491,10 +520,12 @@
|
|||
font-size: var(--font-ui-medium);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.quick-capture-modal-editor {
|
||||
min-height: 150px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.quick-capture-modal-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
|
|
|||
Loading…
Reference in a new issue