mirror of
https://github.com/bfloydd/streams.git
synced 2026-07-22 12:50:25 +00:00
create file tabs are now shared
This commit is contained in:
parent
24b082d85c
commit
9f1d8bdc20
5 changed files with 160 additions and 46 deletions
20
main.ts
20
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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue