diff --git a/src/bootstrap/pluginBootstrap.ts b/src/bootstrap/pluginBootstrap.ts index 40cf4111..a1ea8893 100644 --- a/src/bootstrap/pluginBootstrap.ts +++ b/src/bootstrap/pluginBootstrap.ts @@ -1,7 +1,14 @@ import { Editor, MarkdownView, Notice, Platform, addIcon } from "obsidian"; import { EditorView } from "@codemirror/view"; import type TaskNotesPlugin from "../main"; -import { EVENT_DATA_CHANGED, EVENT_TASK_UPDATED, POMODORO_STATS_VIEW_TYPE, POMODORO_VIEW_TYPE, STATS_VIEW_TYPE, TaskInfo } from "../types"; +import { + EVENT_DATA_CHANGED, + EVENT_TASK_UPDATED, + POMODORO_STATS_VIEW_TYPE, + POMODORO_VIEW_TYPE, + STATS_VIEW_TYPE, + TaskInfo, +} from "../types"; import { RequestDeduplicator, PredictivePrefetcher } from "../utils/RequestDeduplicator"; import { DOMReconciler, UIStateManager } from "../utils/DOMReconciler"; import { FieldMapper } from "../services/FieldMapper"; @@ -43,6 +50,10 @@ import { MicrosoftCalendarService } from "../services/MicrosoftCalendarService"; import { CalendarProviderRegistry } from "../services/CalendarProvider"; import { PomodoroService } from "../services/PomodoroService"; import { AutoExportService } from "../services/AutoExportService"; +import { TaskSelectionService } from "../services/TaskSelectionService"; +import { BasesFilterConverter } from "../services/BasesFilterConverter"; +import { MdbaseSpecService } from "../services/MdbaseSpecService"; +import { registerBasesTaskList } from "../bases/registration"; type FileDeletedEventData = { path: string; prevCache?: unknown }; @@ -100,17 +111,14 @@ export async function initializeCoreServices(plugin: TaskNotesPlugin): Promise { - await plugin.activateCalendarView(); - }); + plugin.addRibbonIcon( + "calendar-days", + plugin.i18n.translate("commands.openCalendarView"), + async () => { + await plugin.activateCalendarView(); + } + ); - plugin.addRibbonIcon("calendar", plugin.i18n.translate("commands.openAdvancedCalendarView"), async () => { - await plugin.openBasesFileForCommand("open-advanced-calendar-view"); - }); + plugin.addRibbonIcon( + "calendar", + plugin.i18n.translate("commands.openAdvancedCalendarView"), + async () => { + await plugin.openBasesFileForCommand("open-advanced-calendar-view"); + } + ); - plugin.addRibbonIcon("check-square", plugin.i18n.translate("commands.openTasksView"), async () => { - await plugin.openBasesFileForCommand("open-tasks-view"); - }); + plugin.addRibbonIcon( + "check-square", + plugin.i18n.translate("commands.openTasksView"), + async () => { + await plugin.openBasesFileForCommand("open-tasks-view"); + } + ); plugin.addRibbonIcon("list", plugin.i18n.translate("commands.openAgendaView"), async () => { await plugin.openBasesFileForCommand("open-agenda-view"); }); - plugin.addRibbonIcon("columns-3", plugin.i18n.translate("commands.openKanbanView"), async () => { - await plugin.openBasesFileForCommand("open-kanban-view"); - }); + plugin.addRibbonIcon( + "columns-3", + plugin.i18n.translate("commands.openKanbanView"), + async () => { + await plugin.openBasesFileForCommand("open-kanban-view"); + } + ); plugin.addRibbonIcon("timer", plugin.i18n.translate("commands.openPomodoroView"), async () => { await plugin.activatePomodoroView(); @@ -151,9 +175,13 @@ export function registerRibbonIcons(plugin: TaskNotesPlugin): void { } ); - plugin.addRibbonIcon("tasknotes-simple", plugin.i18n.translate("commands.createNewTask"), () => { - plugin.openTaskCreationModal(); - }); + plugin.addRibbonIcon( + "tasknotes-simple", + plugin.i18n.translate("commands.createNewTask"), + () => { + plugin.openTaskCreationModal(); + } + ); } export function initializeCalendarProviders(plugin: TaskNotesPlugin): void { @@ -165,14 +193,14 @@ export function initializeCalendarProviders(plugin: TaskNotesPlugin): void { plugin.calendarProviderRegistry.register(plugin.microsoftCalendarService); } -export async function registerBasesIntegration(plugin: TaskNotesPlugin): Promise { +export function registerBasesIntegration(plugin: TaskNotesPlugin): void { if (!plugin.settings?.enableBases || plugin.basesRegistered) { return; } try { - const { registerBasesTaskList } = await import("../bases/registration"); - await registerBasesTaskList(plugin); + // Call without await to prevent blocking if it enters its retry loop + registerBasesTaskList(plugin).catch((e) => console.debug(e)); plugin.basesRegistered = true; } catch (error) { console.debug("[TaskNotes][Bases] Registration failed:", error); @@ -268,8 +296,9 @@ export function initializeServicesLazily(plugin: TaskNotesPlugin): void { }); await plugin.googleCalendarService.initialize(); - plugin.taskCalendarSyncService = new (await import("../services/TaskCalendarSyncService")) - .TaskCalendarSyncService(plugin, plugin.googleCalendarService); + plugin.taskCalendarSyncService = new ( + await import("../services/TaskCalendarSyncService") + ).TaskCalendarSyncService(plugin, plugin.googleCalendarService); plugin.registerEvent( plugin.emitter.on("file-deleted", (data: FileDeletedEventData) => { @@ -278,7 +307,9 @@ export function initializeServicesLazily(plugin: TaskNotesPlugin): void { } const eventIdKey = plugin.fieldMapper.toUserField("googleCalendarEventId"); - const prevCache = data.prevCache as { frontmatter?: Record } | undefined; + const prevCache = data.prevCache as + | { frontmatter?: Record } + | undefined; const eventId = prevCache?.frontmatter?.[eventIdKey]; if (typeof eventId === "string" && eventId.length > 0) { @@ -301,12 +332,12 @@ export function initializeServicesLazily(plugin: TaskNotesPlugin): void { await initializeHTTPAPI(plugin); - const { TaskLinkDetectionService } = await import("../services/TaskLinkDetectionService"); + const { TaskLinkDetectionService } = + await import("../services/TaskLinkDetectionService"); plugin.taskLinkDetectionService = new TaskLinkDetectionService(plugin); - const { InstantTaskConvertService } = await import( - "../services/InstantTaskConvertService" - ); + const { InstantTaskConvertService } = + await import("../services/InstantTaskConvertService"); plugin.instantTaskConvertService = new InstantTaskConvertService( plugin, plugin.statusManager, @@ -324,7 +355,10 @@ export function initializeServicesLazily(plugin: TaskNotesPlugin): void { const editor = (leaf.view as MarkdownView).editor; if (editor && (editor as Editor & { cm?: EditorView }).cm) { const taskPath = data?.path || data?.updatedTask?.path; - dispatchTaskUpdate((editor as Editor & { cm: EditorView }).cm, taskPath); + dispatchTaskUpdate( + (editor as Editor & { cm: EditorView }).cm, + taskPath + ); } } }); diff --git a/src/main.ts b/src/main.ts index adb711fd..e65c5abb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -73,10 +73,7 @@ import { initializeCalendarProviders, registerBasesIntegration, } from "./bootstrap/pluginBootstrap"; -import { - cleanupPluginRuntime, - initializePluginRuntime, -} from "./bootstrap/pluginRuntime"; +import { cleanupPluginRuntime, initializePluginRuntime } from "./bootstrap/pluginRuntime"; export default class TaskNotesPlugin extends Plugin { settings: TaskNotesSettings; @@ -240,7 +237,8 @@ export default class TaskNotesPlugin extends Plugin { getSystemLocale: () => this.getSystemUILocale(), }); - this.i18n.on("locale-changed", ({ current }) => { + this.i18n.on("locale-changed", (event: any) => { + const current: string = event.current; if (!this.initializationComplete) { return; } @@ -256,7 +254,7 @@ export default class TaskNotesPlugin extends Plugin { this.migrationPromise = this.performEarlyMigrationCheck(); initializeCalendarProviders(this); - await registerBasesIntegration(this); + registerBasesIntegration(this); // Defer expensive initialization until layout is ready this.app.workspace.onLayoutReady(() => { @@ -574,7 +572,11 @@ export default class TaskNotesPlugin extends Plugin { } // Migration: Migrate statusSuggestionTrigger to nlpTriggers if needed - if (loadedData && !loadedData.nlpTriggers && loadedData.statusSuggestionTrigger !== undefined) { + if ( + loadedData && + !loadedData.nlpTriggers && + loadedData.statusSuggestionTrigger !== undefined + ) { // eslint-disable-next-line @typescript-eslint/no-require-imports const { DEFAULT_NLP_TRIGGERS } = require("./settings/defaults"); loadedData.nlpTriggers = { @@ -594,10 +596,7 @@ export default class TaskNotesPlugin extends Plugin { if (loadedData && !loadedData.modalFieldsConfig) { // eslint-disable-next-line @typescript-eslint/no-require-imports const { initializeFieldConfig } = require("./utils/fieldConfigDefaults"); - loadedData.modalFieldsConfig = initializeFieldConfig( - undefined, - loadedData.userFields - ); + loadedData.modalFieldsConfig = initializeFieldConfig(undefined, loadedData.userFields); } // Migration: Force enableBases to true (issue #1187) @@ -641,7 +640,8 @@ export default class TaskNotesPlugin extends Plugin { nlpTriggers: { ...DEFAULT_SETTINGS.nlpTriggers, ...(loadedData?.nlpTriggers || {}), - triggers: loadedData?.nlpTriggers?.triggers || DEFAULT_SETTINGS.nlpTriggers.triggers, + triggers: + loadedData?.nlpTriggers?.triggers || DEFAULT_SETTINGS.nlpTriggers.triggers, }, // Modal fields configuration (already migrated above if needed) modalFieldsConfig: loadedData?.modalFieldsConfig, @@ -757,16 +757,13 @@ export default class TaskNotesPlugin extends Plugin { if (created.length > 0) { new Notice( - `Created ${created.length} default Bases file(s):\n${created.join('\n')}`, + `Created ${created.length} default Bases file(s):\n${created.join("\n")}`, 8000 ); } if (skipped.length > 0 && created.length === 0) { - new Notice( - `Default Bases files already exist:\n${skipped.join('\n')}`, - 8000 - ); + new Notice(`Default Bases files already exist:\n${skipped.join("\n")}`, 8000); } } @@ -838,7 +835,8 @@ export default class TaskNotesPlugin extends Plugin { // Only create folder hierarchy if we're actually creating the file const lastSlashIndex = normalizedPath.lastIndexOf("/"); - const directory = lastSlashIndex >= 0 ? normalizedPath.substring(0, lastSlashIndex) : ""; + const directory = + lastSlashIndex >= 0 ? normalizedPath.substring(0, lastSlashIndex) : ""; if (directory) { // eslint-disable-next-line no-await-in-loop @@ -1162,13 +1160,19 @@ export default class TaskNotesPlugin extends Plugin { due: frontmatter.due || undefined, scheduled: frontmatter.scheduled || undefined, contexts: frontmatter.contexts - ? (Array.isArray(frontmatter.contexts) ? frontmatter.contexts : [frontmatter.contexts]) + ? Array.isArray(frontmatter.contexts) + ? frontmatter.contexts + : [frontmatter.contexts] : undefined, projects: frontmatter.projects - ? (Array.isArray(frontmatter.projects) ? frontmatter.projects : [frontmatter.projects]) + ? Array.isArray(frontmatter.projects) + ? frontmatter.projects + : [frontmatter.projects] : undefined, tags: frontmatter.tags - ? (Array.isArray(frontmatter.tags) ? frontmatter.tags : [frontmatter.tags]) + ? Array.isArray(frontmatter.tags) + ? frontmatter.tags + : [frontmatter.tags] : [], timeEstimate: frontmatter.timeEstimate || undefined, recurrence: frontmatter.recurrence || undefined, @@ -1362,7 +1366,8 @@ export default class TaskNotesPlugin extends Plugin { private async openTaskDatePicker(task: TaskInfo, field: "due" | "scheduled") { try { const { DateTimePickerModal } = await import("./modals/DateTimePickerModal"); - const { getDatePart, getTimePart, combineDateAndTime } = await import("./utils/dateUtils"); + const { getDatePart, getTimePart, combineDateAndTime } = + await import("./utils/dateUtils"); const currentValue = (field === "due" ? task.due : task.scheduled) || ""; const modal = new DateTimePickerModal(this.app, { currentDate: getDatePart(currentValue) || null, @@ -1645,7 +1650,8 @@ export default class TaskNotesPlugin extends Plugin { // Open task creation modal with callback to insert link // Use modal-inline-creation context for inline folder behavior (Issue #1424) const modal = new TaskCreationModal(this.app, this, { - prePopulatedValues: Object.keys(prePopulatedValues).length > 0 ? prePopulatedValues : undefined, + prePopulatedValues: + Object.keys(prePopulatedValues).length > 0 ? prePopulatedValues : undefined, onTaskCreated: (task: TaskInfo) => { this.handleInlineTaskCreated(task, insertionContext); }, @@ -1704,5 +1710,4 @@ export default class TaskNotesPlugin extends Plugin { new Notice("Failed to insert task link"); } } - }