diff --git a/main.ts b/main.ts index 71a7d49..3e5c0fb 100644 --- a/main.ts +++ b/main.ts @@ -92,8 +92,6 @@ export default class StreamsPlugin extends Plugin { }) ); - - /** * * TESTING @@ -123,11 +121,6 @@ export default class StreamsPlugin extends Plugin { * */ - - - - - // Initial setup const activeLeaf = this.app.workspace.getActiveViewOfType(MarkdownView)?.leaf; if (activeLeaf) { @@ -138,6 +131,18 @@ export default class StreamsPlugin extends Plugin { this.settings.streams .filter(stream => stream.addCommand) .forEach(stream => this.addStreamCommand(stream)); + + // Listen for CreateFileView state changes and update calendar widget accordingly + this.registerEvent( + // Use 'on' directly on app.workspace without type checking + // @ts-ignore - Custom event not in type definitions + this.app.workspace.on('streams-create-file-state-changed', (view: any) => { + this.log.debug('Create file state changed, updating calendar widget'); + if (view && view.leaf) { + this.updateCalendarWidgetForCreateView(view.leaf); + } + }) + ); } private loadStyles() { @@ -410,7 +415,6 @@ export default class StreamsPlugin extends Plugin { } } - /** * * TESTING diff --git a/src/Widgets/CalendarWidget.ts b/src/Widgets/CalendarWidget.ts index 07fa1cc..ea46a0a 100644 --- a/src/Widgets/CalendarWidget.ts +++ b/src/Widgets/CalendarWidget.ts @@ -3,6 +3,7 @@ import { Stream } from '../../types'; import { Logger } from '../utils/Logger'; import { OpenStreamDateCommand } from '../commands/OpenStreamDateCommand'; import { OpenTodayStreamCommand } from '../commands/OpenTodayStreamCommand'; +import { CREATE_FILE_VIEW_TYPE } from './CreateFileView'; interface ContentIndicator { exists: boolean; @@ -29,12 +30,49 @@ export class CalendarWidget { this.widget = document.createElement('div'); this.widget.addClass('stream-calendar-widget'); - // Find the markdown view container - const markdownView = leaf.view as MarkdownView; - const contentContainer = markdownView.contentEl; + // Find the content container based on view type + let contentContainer: HTMLElement | null = null; + + // Handle different view types + const viewType = leaf.view.getViewType(); + this.log.debug(`Creating calendar widget for view type: ${viewType}`); + + if (viewType === 'markdown') { + // For markdown views + const markdownView = leaf.view as MarkdownView; + contentContainer = markdownView.contentEl; + + // Get current file's date if it exists + const currentFile = markdownView.file; + if (currentFile) { + const match = currentFile.basename.match(/^\d{4}-\d{2}-\d{2}/); + if (match) { + this.currentViewedDate = match[0]; + } + } + } else if (viewType === CREATE_FILE_VIEW_TYPE) { + // For create file views + contentContainer = (leaf.view as any).contentEl; + + // Try to get the date from the view's state + try { + const state = leaf.view.getState(); + if (state && state.date) { + const dateString = state.date as string; + // Extract date string in YYYY-MM-DD format for currentViewedDate + this.currentViewedDate = dateString.split('T')[0]; + this.log.debug(`Set currentViewedDate from state: ${this.currentViewedDate}`); + } + } catch (error) { + this.log.error('Error getting date from CreateFileView state:', error); + } + } else { + // For other view types + contentContainer = (leaf.view as any).contentEl; + } if (!contentContainer) { - console.error('Could not find content container'); + this.log.error('Could not find content container'); return; } @@ -48,15 +86,6 @@ export class CalendarWidget { this.fileModifyHandler = this.handleFileModify.bind(this); this.app.vault.on('modify', this.fileModifyHandler); - // Get current file's date if it exists - const currentFile = markdownView.file; - if (currentFile) { - const match = currentFile.basename.match(/^\d{4}-\d{2}-\d{2}/); - if (match) { - this.currentViewedDate = match[0]; - } - } - this.initializeWidget(); this.loadStyles(); } diff --git a/src/Widgets/CreateFileView.ts b/src/Widgets/CreateFileView.ts index ba43248..6a56d58 100644 --- a/src/Widgets/CreateFileView.ts +++ b/src/Widgets/CreateFileView.ts @@ -29,9 +29,40 @@ export class CreateFileView extends ItemView { } getDisplayText(): string { - // Extract just the filename without extension for the tab title - const fileName = this.filePath.split('/').pop()?.replace('.md', '') || ''; - return fileName; + // Format the date for display in a user-friendly way + try { + // Extract date from the filename + const fileName = this.filePath.split('/').pop() || ''; + const match = fileName.match(/(\d{4}-\d{2}-\d{2})\.md$/); + + if (match && match[1]) { + // Get a readable date format + const [year, month, day] = match[1].split('-').map(n => parseInt(n, 10)); + const dateObj = new Date(year, month - 1, day); + + if (!isNaN(dateObj.getTime())) { + // Format as MMM DD, YYYY + const dateString = dateObj.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric' + }); + + // Return a title like "Work Notes: Apr 27, 2025" + if (this.stream && this.stream.name) { + return `${this.stream.name}: ${dateString}`; + } + + return dateString; + } + } + + // Fallback to just the filename without extension + return fileName.replace('.md', ''); + } catch (error) { + this.log.error('Error formatting display text:', error); + return this.filePath.split('/').pop()?.replace('.md', '') || ''; + } } getState(): any { @@ -79,32 +110,34 @@ export class CreateFileView extends ItemView { } } - // Validate the date - if (isNaN(this.date.getTime())) { - this.log.error(`Invalid date after parsing: ${state.date}`); - // Try to extract from filename as fallback - this.extractDateFromFilename(); - } - // Check if date has changed - if (oldDate && this.date) { - dateChanged = oldDate.toDateString() !== this.date.toDateString(); + if (oldDate) { + dateChanged = oldDate.getTime() !== this.date.getTime(); + } else { + dateChanged = true; } - } catch (error) { - this.log.error(`Error setting date: ${error}`); - // Try to extract from filename as fallback - this.extractDateFromFilename(); + this.log.error(`Error parsing date: ${error}`); + this.date = new Date(); // Fallback to current date } - } else { - // Try to extract from filename if no date provided - this.extractDateFromFilename(); } - // If date or file path changed, refresh the view - if (dateChanged || oldFilePath !== this.filePath) { - this.log.debug("Date or file path changed, refreshing view"); - await this.refreshView(); + // Determine if we need to refresh the view + const filePathChanged = oldFilePath !== this.filePath; + + // Check for a flag in the result that indicates this was just a title update + // to prevent infinite loops + const isJustTitleUpdate = result && result.isTitleRefresh; + + if ((filePathChanged || dateChanged) && !isJustTitleUpdate) { + this.log.debug(`State changed significantly, refreshing view`); + // Use a setTimeout to ensure this runs after setState completes + setTimeout(() => { + this.refreshView(); + + // Trigger a custom event so that the plugin can update the calendar widget + this.app.workspace.trigger('streams-create-file-state-changed', this); + }, 0); } } } @@ -234,5 +267,33 @@ export class CreateFileView extends ItemView { // Force a refresh of the view content this.contentEl.empty(); await this.onOpen(); + + // Update the tab title + this.updateTabTitle(); + + // Let Obsidian know the view has updated + this.app.workspace.trigger('layout-change'); + } + + /** + * Updates the tab title to match the current date + * This is needed because when navigating between dates the tab title + * doesn't automatically update + */ + private updateTabTitle(): void { + try { + this.log.debug('Updating tab title'); + + // Force Obsidian to update the tab title by setting the view state again + // This will call getDisplayText() internally and update the tab UI + this.leaf.setViewState({ + type: this.getViewType(), + state: this.getState(), + }, { history: false, isTitleRefresh: true }); + + this.log.debug(`Updated tab title to: ${this.getDisplayText()}`); + } catch (error) { + this.log.error('Error updating tab title:', error); + } } } \ No newline at end of file diff --git a/src/utils/streamUtils.ts b/src/utils/streamUtils.ts index 7db8b8e..682880f 100644 --- a/src/utils/streamUtils.ts +++ b/src/utils/streamUtils.ts @@ -114,8 +114,20 @@ export async function openStreamDate(app: App, stream: Stream, date: Date = new } } - // Get or create a leaf - const leaf = app.workspace.getLeaf('tab'); + // Look for an existing CreateFileView leaf to reuse + let leaf: WorkspaceLeaf | null = null; + + // First, look for an existing CreateFileView leaf + const existingCreateFileViewLeaves = app.workspace.getLeavesOfType(CREATE_FILE_VIEW_TYPE); + if (existingCreateFileViewLeaves.length > 0) { + // Reuse the first one we find + leaf = existingCreateFileViewLeaves[0]; + log.debug('Reusing existing CreateFileView leaf'); + } else { + // If no existing CreateFileView leaf, create a new one + leaf = app.workspace.getLeaf('tab'); + log.debug('Created a new leaf for CreateFileView'); + } // Register the view type if not already registered // Access the viewRegistry through app as any since it might not be in the type definitions diff --git a/styles.css b/styles.css index f8e0668..c430376 100644 --- a/styles.css +++ b/styles.css @@ -81,6 +81,14 @@ If your plugin does not need CSS, delete this file. margin-right: 8px; } +/* Special positioning for calendar in create file view */ +.streams-create-file-container .stream-calendar-widget { + position: fixed; + top: 80px; + right: 0; + margin-right: 0; +} + .stream-calendar-collapsed { position: absolute; top: 0;