mirror of
https://github.com/devonthesofa/obsidian-note-status.git
synced 2026-07-22 12:30:24 +00:00
Merge pull request #26 from devonthesofa/feature/commands-integration
Fix "Add status to current note" command and implement Quick Status Commands
This commit is contained in:
commit
ffe01a9702
5 changed files with 216 additions and 28 deletions
|
|
@ -25,6 +25,7 @@ export const DEFAULT_SETTINGS: NoteStatusSettings = {
|
|||
tagPrefix: 'obsidian-note-status',
|
||||
strictStatuses: false, // Default to show all statuses from frontmatter
|
||||
excludeUnknownStatus: true, // Default to exclude unknown status files for better performance
|
||||
quickStatusCommands: ['active', 'completed'], // Add default quick commands
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ export class CommandIntegration {
|
|||
|
||||
public updateSettings(settings: NoteStatusSettings): void {
|
||||
this.settings = settings;
|
||||
// Re-register commands when settings change
|
||||
this.unload();
|
||||
this.registerCommands();
|
||||
}
|
||||
|
||||
public registerCommands(): void {
|
||||
|
|
@ -54,6 +57,24 @@ export class CommandIntegration {
|
|||
}
|
||||
});
|
||||
|
||||
// Add status to current note
|
||||
this.plugin.addCommand({
|
||||
id: 'add-status',
|
||||
name: 'Add status to current note',
|
||||
checkCallback: (checking: boolean) => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
if (!file) return false;
|
||||
|
||||
if (!checking) {
|
||||
this.statusDropdown.openStatusDropdown({
|
||||
files: [file],
|
||||
mode: this.settings.useMultipleStatuses ? 'add' : 'replace'
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Insert status metadata
|
||||
this.plugin.addCommand({
|
||||
id: 'insert-status-metadata',
|
||||
|
|
@ -87,28 +108,8 @@ export class CommandIntegration {
|
|||
}
|
||||
});
|
||||
|
||||
// Quick status commands for common statuses
|
||||
const quickStatuses = ['active', 'completed', 'onHold', 'dropped'];
|
||||
quickStatuses.forEach(status => {
|
||||
this.plugin.addCommand({
|
||||
id: `set-status-${status}`,
|
||||
name: `Set status to ${status}`,
|
||||
checkCallback: (checking: boolean) => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
if (!file) return false;
|
||||
|
||||
if (!checking) {
|
||||
this.statusService.handleStatusChange({
|
||||
files: file,
|
||||
statuses: status,
|
||||
operation: 'set'
|
||||
});
|
||||
new Notice(`Status set to ${status}`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
// Register dynamic quick status commands
|
||||
this.registerQuickStatusCommands();
|
||||
|
||||
// Clear status
|
||||
this.plugin.addCommand({
|
||||
|
|
@ -197,6 +198,62 @@ export class CommandIntegration {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register quick status commands based on settings
|
||||
*/
|
||||
private registerQuickStatusCommands(): void {
|
||||
const quickCommands = this.settings.quickStatusCommands || [];
|
||||
const allStatuses = this.statusService.getAllStatuses();
|
||||
|
||||
quickCommands.forEach(statusName => {
|
||||
const status = allStatuses.find(s => s.name === statusName);
|
||||
if (!status) return;
|
||||
|
||||
this.plugin.addCommand({
|
||||
id: `set-status-${statusName}`,
|
||||
name: `Set status to ${statusName}`,
|
||||
checkCallback: (checking: boolean) => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
if (!file) return false;
|
||||
|
||||
if (!checking) {
|
||||
this.statusService.handleStatusChange({
|
||||
files: file,
|
||||
statuses: statusName,
|
||||
operation: 'set'
|
||||
});
|
||||
new Notice(`Status set to ${statusName}`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Add toggle command for multiple status mode
|
||||
if (this.settings.useMultipleStatuses) {
|
||||
this.plugin.addCommand({
|
||||
id: `toggle-status-${statusName}`,
|
||||
name: `Toggle status ${statusName}`,
|
||||
checkCallback: (checking: boolean) => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
if (!file) return false;
|
||||
|
||||
if (!checking) {
|
||||
this.statusService.handleStatusChange({
|
||||
files: file,
|
||||
statuses: statusName,
|
||||
operation: 'toggle'
|
||||
});
|
||||
const currentStatuses = this.statusService.getFileStatuses(file);
|
||||
const hasStatus = currentStatuses.includes(statusName);
|
||||
new Notice(`Status ${statusName} ${hasStatus ? 'added' : 'removed'}`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private cycleStatus(file: TFile): void {
|
||||
const allStatuses = this.statusService.getAllStatuses()
|
||||
.filter(s => s.name !== 'unknown')
|
||||
|
|
@ -224,4 +281,22 @@ export class CommandIntegration {
|
|||
|
||||
new Notice(`Status changed to ${allStatuses[nextIndex]}`);
|
||||
}
|
||||
|
||||
public unload(): void {
|
||||
// Remove existing commands
|
||||
this.removeQuickStatusCommands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all quick status commands
|
||||
*/
|
||||
private removeQuickStatusCommands(): void {
|
||||
const allStatuses = this.statusService.getAllStatuses();
|
||||
|
||||
allStatuses.forEach(status => {
|
||||
(this.app as any).commands.removeCommand(`note-status:set-status-${status.name}`);
|
||||
(this.app as any).commands.removeCommand(`note-status:toggle-status-${status.name}`);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export interface SettingsUICallbacks {
|
|||
*/
|
||||
export class NoteStatusSettingsUI {
|
||||
private callbacks: SettingsUICallbacks;
|
||||
private quickCommandsContainer: HTMLElement | null = null;
|
||||
|
||||
constructor(callbacks: SettingsUICallbacks) {
|
||||
this.callbacks = callbacks;
|
||||
|
|
@ -38,6 +39,7 @@ export class NoteStatusSettingsUI {
|
|||
this.renderUISettings(containerEl, settings);
|
||||
this.renderTagSettings(containerEl, settings);
|
||||
this.renderCustomStatusSettings(containerEl, settings);
|
||||
this.renderQuickCommandsSettings(containerEl, settings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,6 +68,7 @@ export class NoteStatusSettingsUI {
|
|||
|
||||
checkbox.addEventListener('change', () => {
|
||||
this.callbacks.onTemplateToggle(template.id, checkbox.checked);
|
||||
this.refreshQuickCommandsList(settings);
|
||||
});
|
||||
|
||||
headerEl.createEl('span', {
|
||||
|
|
@ -168,6 +171,93 @@ export class NoteStatusSettingsUI {
|
|||
.addToggle(toggle => toggle
|
||||
.setValue(settings.strictStatuses || false)
|
||||
.onChange(value => this.callbacks.onSettingChange('strictStatuses', value)));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the quick commands configuration section
|
||||
*/
|
||||
private renderQuickCommandsSettings(containerEl: HTMLElement, settings: any): void {
|
||||
new Setting(containerEl)
|
||||
.setName('Quick status commands')
|
||||
.setDesc('Select which statuses should have dedicated commands in the command palette. These can be assigned hotkeys for quick access.')
|
||||
.setHeading();
|
||||
|
||||
this.quickCommandsContainer = containerEl.createDiv({ cls: 'quick-commands-container' });
|
||||
this.populateQuickCommandsList(settings);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the quick commands list
|
||||
*/
|
||||
private populateQuickCommandsList(settings: any): void {
|
||||
if (!this.quickCommandsContainer) return;
|
||||
|
||||
this.quickCommandsContainer.empty();
|
||||
// Get all available statuses from service
|
||||
const allStatuses = this.getAllAvailableStatuses(settings);
|
||||
const currentQuickCommands = settings.quickStatusCommands || [];
|
||||
|
||||
allStatuses.forEach(status => {
|
||||
const setting = new Setting(this.quickCommandsContainer)
|
||||
.setName(`${status.icon} ${status.name}`)
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(currentQuickCommands.includes(status.name))
|
||||
.onChange(async (value) => {
|
||||
const updatedCommands = value
|
||||
? [...currentQuickCommands.filter((cmd: string) => cmd !== status.name), status.name]
|
||||
: currentQuickCommands.filter((cmd: string) => cmd !== status.name);
|
||||
|
||||
await this.callbacks.onSettingChange('quickStatusCommands', updatedCommands);
|
||||
}));
|
||||
|
||||
if (status.description) {
|
||||
setting.setDesc(status.description);
|
||||
}
|
||||
});
|
||||
|
||||
if (allStatuses.length === 0) {
|
||||
this.quickCommandsContainer.createDiv({
|
||||
text: 'No statuses available. Enable templates or add custom statuses first.',
|
||||
cls: 'setting-item-description'
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Refresh the quick commands list when statuses change
|
||||
*/
|
||||
private refreshQuickCommandsList(settings: any): void {
|
||||
// Add small delay to ensure settings are updated
|
||||
setTimeout(() => {
|
||||
this.populateQuickCommandsList(settings);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available statuses from templates and custom statuses
|
||||
*/
|
||||
private getAllAvailableStatuses(settings: any): Array<{name: string, icon: string, description?: string}> {
|
||||
const statuses: Array<{name: string, icon: string, description?: string}> = [];
|
||||
|
||||
// Add custom statuses
|
||||
statuses.push(...settings.customStatuses);
|
||||
|
||||
// Add template statuses if not using custom only
|
||||
if (!settings.useCustomStatusesOnly) {
|
||||
for (const templateId of settings.enabledTemplates) {
|
||||
const template = PREDEFINED_TEMPLATES.find(t => t.id === templateId);
|
||||
if (template) {
|
||||
for (const status of template.statuses) {
|
||||
if (!statuses.find(s => s.name === status.name)) {
|
||||
statuses.push(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return statuses.filter(s => s.name !== 'unknown');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,7 +271,11 @@ export class NoteStatusSettingsUI {
|
|||
.setDesc('Ignore template statuses and use only the custom statuses defined below')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(settings.useCustomStatusesOnly || false)
|
||||
.onChange(value => this.callbacks.onSettingChange('useCustomStatusesOnly', value)));
|
||||
.onChange(async (value) => {
|
||||
await this.callbacks.onSettingChange('useCustomStatusesOnly', value);
|
||||
// Update quick commands list when custom-only mode changes
|
||||
this.refreshQuickCommandsList(settings);
|
||||
}));
|
||||
|
||||
const statusList = containerEl.createDiv({ cls: 'custom-status-list' });
|
||||
this.renderCustomStatuses(statusList, settings);
|
||||
|
|
@ -192,7 +286,10 @@ export class NoteStatusSettingsUI {
|
|||
.addButton(button => button
|
||||
.setButtonText('Add Status')
|
||||
.setCta()
|
||||
.onClick(() => this.callbacks.onCustomStatusAdd()));
|
||||
.onClick(async () => {
|
||||
await this.callbacks.onCustomStatusAdd();
|
||||
this.refreshQuickCommandsList(settings);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -209,12 +306,19 @@ export class NoteStatusSettingsUI {
|
|||
setting.addText(text => text
|
||||
.setPlaceholder('Name')
|
||||
.setValue(status.name)
|
||||
.onChange(value => this.callbacks.onCustomStatusChange(index, 'name', value || 'unnamed')));
|
||||
.onChange(async (value) => {
|
||||
await this.callbacks.onCustomStatusChange(index, 'name', value || 'unnamed');
|
||||
// Update quick commands list when status name changes
|
||||
this.refreshQuickCommandsList(settings);
|
||||
}));
|
||||
|
||||
setting.addText(text => text
|
||||
.setPlaceholder('Icon')
|
||||
.setValue(status.icon)
|
||||
.onChange(value => this.callbacks.onCustomStatusChange(index, 'icon', value || '❓')));
|
||||
.onChange(async (value) => {
|
||||
await this.callbacks.onCustomStatusChange(index, 'icon', value || '❓');
|
||||
this.refreshQuickCommandsList(settings);
|
||||
}));
|
||||
|
||||
setting.addColorPicker(colorPicker => colorPicker
|
||||
.setValue(settings.statusColors[status.name] || '#ffffff')
|
||||
|
|
@ -223,13 +327,19 @@ export class NoteStatusSettingsUI {
|
|||
setting.addText(text => text
|
||||
.setPlaceholder('Description')
|
||||
.setValue(status.description || '')
|
||||
.onChange(value => this.callbacks.onCustomStatusChange(index, 'description', value)));
|
||||
.onChange(async (value) => {
|
||||
await this.callbacks.onCustomStatusChange(index, 'description', value);
|
||||
this.refreshQuickCommandsList(settings);
|
||||
}));
|
||||
|
||||
setting.addButton(button => button
|
||||
.setButtonText('Remove')
|
||||
.setClass('status-remove-button')
|
||||
.setWarning()
|
||||
.onClick(() => this.callbacks.onCustomStatusRemove(index)));
|
||||
.onClick(async () => {
|
||||
await this.callbacks.onCustomStatusRemove(index);
|
||||
this.refreshQuickCommandsList(settings);
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
main.ts
1
main.ts
|
|
@ -207,6 +207,7 @@ onunload() {
|
|||
this.workspaceIntegration?.unload();
|
||||
this.metadataIntegration?.unload();
|
||||
this.editorIntegration?.unload();
|
||||
this.commandIntegration?.unload();
|
||||
|
||||
// Clean up services
|
||||
this.styleService?.unload();
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export interface NoteStatusSettings {
|
|||
tagPrefix: string; // Prefix for the status tag (default: 'status')
|
||||
strictStatuses: boolean; // Whether to only show known statuses
|
||||
excludeUnknownStatus: boolean; // Whether to exclude files with unknown status from the status pane
|
||||
quickStatusCommands: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue