refactor: add components folder with statusBar

This commit is contained in:
Aleix 2025-05-16 15:47:51 +02:00
parent 1cae811a91
commit b6db59c593
5 changed files with 221 additions and 177 deletions

View file

@ -0,0 +1,107 @@
import { NoteStatusSettings } from '../../models/types';
import { StatusService } from '../../services/status-service';
import { StatusBarView } from './status-bar-view';
/**
* Controller for the status bar
*/
export class StatusBarController {
private view: StatusBarView;
private settings: NoteStatusSettings;
private statusService: StatusService;
private currentStatuses: string[] = ['unknown'];
constructor(statusBarEl: HTMLElement, settings: NoteStatusSettings, statusService: StatusService) {
this.view = new StatusBarView(statusBarEl);
this.settings = settings;
this.statusService = statusService;
// Register right-click handler for force refresh
this.setupContextMenu(statusBarEl);
this.update(['unknown']);
}
/**
* Set up right-click context menu for force refresh
*/
private setupContextMenu(element: HTMLElement): void {
element.addEventListener('contextmenu', (e) => {
e.preventDefault();
window.dispatchEvent(new CustomEvent('note-status:force-refresh'));
});
}
/**
* Update the status bar with new statuses
*/
public update(statuses: string[]): void {
this.currentStatuses = statuses;
this.render();
}
/**
* Render the status bar
*/
private render(): void {
this.view.reset();
if (!this.settings.showStatusBar) {
this.view.hide();
return;
}
if (!this.settings.useMultipleStatuses) {
this.renderStatuses([this.currentStatuses[0]]);
} else {
this.renderStatuses(this.currentStatuses);
}
this.handleAutoHide();
}
/**
* Render statuses - handles both single and multiple status cases
*/
private renderStatuses(statuses: string[]): void {
const statusDetails = statuses.map(status => {
const statusObj = this.statusService.getAllStatuses().find(s => s.name === status);
return {
name: status,
icon: this.statusService.getStatusIcon(status),
tooltipText: statusObj?.description ? `${status} - ${statusObj.description}` : status
};
});
this.view.renderStatuses(statusDetails);
}
/**
* Handle auto-hide behavior
*/
private handleAutoHide(): void {
const onlyUnknown = this.currentStatuses.length === 1 &&
this.currentStatuses[0] === 'unknown';
if (this.settings.autoHideStatusBar && onlyUnknown) {
this.view.hide();
} else {
this.view.show();
}
}
/**
* Update settings reference
*/
public updateSettings(settings: NoteStatusSettings): void {
this.settings = settings;
this.render();
}
/**
* Clean up when plugin is unloaded
*/
public unload(): void {
this.view.destroy();
}
}

View file

@ -0,0 +1,107 @@
import { setTooltip } from 'obsidian';
/**
* Renders the status bar UI
*/
export class StatusBarView {
private element: HTMLElement;
constructor(element: HTMLElement) {
this.element = element;
this.element.addClass('note-status-bar');
}
/**
* Clears the element and resets CSS classes
*/
reset(): void {
this.element.empty();
this.element.removeClass('left', 'hidden', 'auto-hide', 'visible');
this.element.addClass('note-status-bar');
}
/**
* Hide the status bar
*/
hide(): void {
this.element.addClass('hidden');
this.element.removeClass('visible');
}
/**
* Show the status bar
*/
show(): void {
this.element.removeClass('hidden');
this.element.addClass('visible');
}
renderStatuses(statuses: Array<{name: string, icon: string, tooltipText: string}>): void {
if (statuses.length === 1) {
this.renderSingleStatus(statuses[0].name, statuses[0].icon, statuses[0].tooltipText);
} else {
this.renderMultipleStatuses(statuses);
}
}
/**
* Render a single status
*/
private renderSingleStatus(status: string, icon: string, tooltipText: string): void {
const statusText = this.element.createEl('span', {
text: `Status: ${status}`,
cls: `note-status-${status}`
});
setTooltip(statusText, tooltipText);
const statusIcon = this.element.createEl('span', {
text: icon,
cls: `note-status-icon status-${status}`
});
setTooltip(statusIcon, tooltipText);
}
/**
* Render multiple statuses
*/
private renderMultipleStatuses(statuses: Array<{name: string, icon: string, tooltipText: string}>): void {
this.element.createEl('span', {
text: 'Statuses: ',
cls: 'note-status-label'
});
const badgesContainer = this.element.createEl('span', {
cls: 'note-status-badges'
});
statuses.forEach(status => this.createStatusBadge(badgesContainer, status));
}
/**
* Create a status badge for multiple status display
*/
private createStatusBadge(container: HTMLElement, status: {name: string, icon: string, tooltipText: string}): void {
const badge = container.createEl('span', {
cls: `note-status-badge status-${status.name}`
});
setTooltip(badge, status.tooltipText);
badge.createEl('span', {
text: status.icon,
cls: 'note-status-badge-icon'
});
badge.createEl('span', {
text: status.name,
cls: 'note-status-badge-text'
});
}
/**
* Clean up the element
*/
destroy(): void {
this.element.empty();
}
}

View file

@ -12,7 +12,6 @@ import { StatusService } from './services/status-service';
import { StyleService } from './services/style-service';
// UI Components
import { StatusBar } from './ui/components/status-bar';
import { StatusDropdown } from './ui/components/status-dropdown';
import { StatusPaneView } from './ui/components/status-pane-view';
import { ExplorerIntegration } from './ui/integrations/explorer-integration';
@ -20,6 +19,7 @@ import { StatusContextMenu } from './ui/menus/status-context-menu';
// Settings
import { NoteStatusSettingTab } from './settings/settings-tab';
import { StatusBarController } from 'components/statusBar/status-bar-controller';
/**
* Main plugin class for Note Status functionality
@ -28,7 +28,7 @@ export default class NoteStatus extends Plugin {
settings: NoteStatusSettings;
statusService: StatusService;
styleService: StyleService;
statusBar: StatusBar;
statusBar: StatusBarController;
statusDropdown: StatusDropdown;
explorerIntegration: ExplorerIntegration;
statusContextMenu: StatusContextMenu;
@ -105,7 +105,7 @@ export default class NoteStatus extends Plugin {
*/
private initializeUI(): void {
// Init basic UI components
this.statusBar = new StatusBar(this.addStatusBarItem(), this.settings, this.statusService);
this.statusBar = new StatusBarController(this.addStatusBarItem(), this.settings, this.statusService);
this.statusDropdown = new StatusDropdown(this.app, this.settings, this.statusService);
// Initialize explorer integration with a slight delay to ensure UI elements are ready

View file

@ -383,11 +383,10 @@ export class StatusService {
// General UI refresh
window.dispatchEvent(new CustomEvent('note-status:refresh-ui'));
// If it's the active file, ensure status bar and toolbar are updated
const activeFile = this.app.workspace.getActiveFile();
if (activeFile && files.some(f => f.path === activeFile.path)) {
const statuses = this.getFileStatuses(activeFile);
this.notifyStatusChanged(statuses, activeFile)
// Notify status changes for each modified file
for (const file of files) {
const statuses = this.getFileStatuses(file);
this.notifyStatusChanged(statuses, file);
}
}

View file

@ -1,169 +0,0 @@
import { setTooltip } from 'obsidian';
import { NoteStatusSettings } from '../../models/types';
import { StatusService } from '../../services/status-service';
/**
* Handles the status bar functionality
*/
export class StatusBar {
private statusBarEl: HTMLElement;
private settings: NoteStatusSettings;
private statusService: StatusService;
private currentStatuses: string[] = ['unknown'];
constructor(statusBarEl: HTMLElement, settings: NoteStatusSettings, statusService: StatusService) {
this.statusBarEl = statusBarEl;
this.settings = settings;
this.statusService = statusService;
this.statusBarEl.addClass('note-status-bar');
this.setupContextMenu();
this.update(['unknown']);
}
/**
* Set up right-click context menu for force refresh
*/
private setupContextMenu(): void {
this.statusBarEl.addEventListener('contextmenu', (e) => {
e.preventDefault();
window.dispatchEvent(new CustomEvent('note-status:force-refresh'));
});
}
/**
* Update the status bar with new statuses
*/
public update(statuses: string[]): void {
this.currentStatuses = statuses;
this.render();
}
/**
* Render the status bar based on current settings and statuses
*/
public render(): void {
this.statusBarEl.empty();
this.resetClasses();
if (!this.settings.showStatusBar) {
this.statusBarEl.addClass('hidden');
return;
}
// Select display mode based on number of statuses and settings
if (this.currentStatuses.length === 1 || !this.settings.useMultipleStatuses) {
this.renderSingleStatus();
} else {
this.renderMultipleStatuses();
}
this.handleAutoHide();
}
/**
* Reset CSS classes to their default state
*/
private resetClasses(): void {
this.statusBarEl.removeClass('left', 'hidden', 'auto-hide', 'visible');
this.statusBarEl.addClass('note-status-bar');
}
/**
* Render a single status display
*/
private renderSingleStatus(): void {
const primaryStatus = this.currentStatuses[0];
const statusObj = this.statusService.getAllStatuses().find(s => s.name === primaryStatus);
const tooltipText = statusObj?.description
? `${primaryStatus} - ${statusObj.description}`
: primaryStatus;
// Create status text
const statusText = this.statusBarEl.createEl('span', {
text: `Status: ${primaryStatus}`,
cls: `note-status-${primaryStatus}`
});
setTooltip(statusText, tooltipText);
// Create status icon
const statusIcon = this.statusBarEl.createEl('span', {
text: this.statusService.getStatusIcon(primaryStatus),
cls: `note-status-icon status-${primaryStatus}`
});
setTooltip(statusIcon, tooltipText);
}
/**
* Render multiple statuses display
*/
private renderMultipleStatuses(): void {
this.statusBarEl.createEl('span', {
text: 'Statuses: ',
cls: 'note-status-label'
});
const badgesContainer = this.statusBarEl.createEl('span', {
cls: 'note-status-badges'
});
this.currentStatuses.forEach(status =>
this.createStatusBadge(badgesContainer, status));
}
/**
* Create a status badge for multiple status display
*/
private createStatusBadge(container: HTMLElement, status: string): void {
const statusObj = this.statusService.getAllStatuses().find(s => s.name === status);
const tooltipText = statusObj?.description
? `${status} - ${statusObj.description}`
: status;
const badge = container.createEl('span', {
cls: `note-status-badge status-${status}`
});
setTooltip(badge, tooltipText);
badge.createEl('span', {
text: this.statusService.getStatusIcon(status),
cls: 'note-status-badge-icon'
});
badge.createEl('span', {
text: status,
cls: 'note-status-badge-text'
});
}
/**
* Handle auto-hide behavior
*/
private handleAutoHide(): void {
const onlyUnknown = this.currentStatuses.length === 1 &&
this.currentStatuses[0] === 'unknown';
if (this.settings.autoHideStatusBar && onlyUnknown) {
this.statusBarEl.addClass('hidden');
this.statusBarEl.removeClass('visible');
} else {
this.statusBarEl.removeClass('hidden');
this.statusBarEl.addClass('visible');
}
}
/**
* Update settings reference
*/
public updateSettings(settings: NoteStatusSettings): void {
this.settings = settings;
this.render();
}
/**
* Clean up when plugin is unloaded
*/
public unload(): void {
this.statusBarEl.empty();
}
}