obsidian-sample-plugin/main.ts

212 lines
6.0 KiB
TypeScript

import { App, Plugin, PluginSettingTab, Setting, TFile } from 'obsidian';
import { FolderSuggest } from './src/suggestions/folderSuggest';
import { renderDonateButton } from './src/components/DonateButton';
import {
getFilesNamesInDirectory,
getObsidianFiles,
getRenderedFileNamesReplaced,
renameFilesInObsidian,
syncScrolls,
} from './src/services/file.service';
import { createPreviewElement } from './src/components/PreviewElement';
interface MyPluginSettings {
folderName: string;
fileNames: TFile[];
existingSymbol: string;
replacePattern: string;
}
const DEFAULT_SETTINGS: MyPluginSettings = {
folderName: '',
fileNames: [],
existingSymbol: '',
replacePattern: '',
};
class BulkRenamePlugin extends Plugin {
settings: MyPluginSettings;
async onload() {
await this.loadSettings();
this.addSettingTab(new BulkRenameSettingsTab(this.app, this));
// this.app.vault.on('rename', (file, oldPath) => {
// });
}
onunload() {}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
}
export type State = {
previewScroll: number;
filesScroll: number;
};
class BulkRenameSettingsTab extends PluginSettingTab {
plugin: BulkRenamePlugin;
state: State;
constructor(app: App, plugin: BulkRenamePlugin) {
super(app, plugin);
this.state = {
previewScroll: 0,
filesScroll: 0,
};
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl('h2', { text: 'Bulk Rename - Settings' });
this.renderFileLocation();
this.renderReplaceSymbol();
this.renderFilesAndPreview();
this.renderRenameFiles();
this.renderSupportDevelopment();
}
renderReplaceSymbol() {
const { settings } = this.plugin;
const desc = document.createDocumentFragment();
const button = document.createElement('button');
button.textContent = 'Preview';
button.className = 'mod-cta';
button.onclick = () => {
this.display();
};
desc.appendChild(button);
new Setting(this.containerEl)
.setName('Existing Symbol')
.setDesc(desc)
.addText((textComponent) => {
const previewLabel = createPreviewElement('Replacement symbols');
textComponent.inputEl.insertAdjacentElement('afterend', previewLabel);
textComponent.setValue(settings.existingSymbol);
textComponent.setPlaceholder('existing symbols');
textComponent.onChange((newValue) => {
settings.existingSymbol = newValue;
this.plugin.saveSettings();
});
})
.addText((textComponent) => {
textComponent.setValue(settings.replacePattern);
textComponent.setPlaceholder('replace with');
textComponent.onChange((newValue) => {
settings.replacePattern = newValue;
this.plugin.saveSettings();
this.calculateFiles();
});
});
}
renderFileLocation() {
new Setting(this.containerEl)
.setName('Folder location')
.setDesc('Files in this folder will be available renamed.')
.addSearch((cb) => {
new FolderSuggest(this.app, cb.inputEl);
cb.setPlaceholder('Example: folder1/')
.setValue(this.plugin.settings.folderName)
.onChange((newFolder) => {
this.plugin.settings.folderName = newFolder;
this.plugin.saveSettings();
this.calculateFiles();
});
// @ts-ignore
cb.containerEl.addClass('templater_search');
})
.addButton((button) => {
button.setButtonText('Refresh');
button.onClick(() => {
this.calculateFiles();
this.display();
});
});
}
renderFilesAndPreview() {
let existingFilesTextArea: HTMLTextAreaElement;
let replacedPreviewTextArea: HTMLTextAreaElement;
new Setting(this.containerEl)
.setName('Files within the folder')
.setDesc(`Total Files: ${this.plugin.settings.fileNames.length}`)
.addTextArea((text) => {
text.setPlaceholder('Here you will see files under folder location');
text.setDisabled(true);
existingFilesTextArea = text.inputEl;
const value = getFilesNamesInDirectory(this.plugin);
text.setValue(value);
const previewLabel = createPreviewElement();
text.inputEl.insertAdjacentElement('afterend', previewLabel);
text.inputEl.addClass('templater_cmd');
})
.addTextArea((text) => {
text.setPlaceholder(
'How filenames will looks like after replacement(click preview first)',
);
text.setDisabled(true);
replacedPreviewTextArea = text.inputEl;
const value = getRenderedFileNamesReplaced(this.plugin);
text.setValue(value);
text.inputEl.addClass('templater_cmd');
})
.then((setting) => {
syncScrolls(existingFilesTextArea, replacedPreviewTextArea, this.state);
});
}
renderRenameFiles() {
const desc = document.createDocumentFragment();
desc.append(
'You are going to update all marked files and their directories',
desc.createEl('br'),
desc.createEl('b', {
text: 'Warning: ',
}),
'This plugin in Beta, make sure you verified all files in preview',
);
new Setting(this.containerEl)
.setDesc(desc)
.setName('Replace patterns')
.addButton((button) => {
button.buttonEl.style.width = '100%';
button.setTooltip("FYI: We don't have undone button yet!");
button.setButtonText('Rename');
button.onClick(async () => {
button.setDisabled(true);
renameFilesInObsidian(this.app, this.plugin);
this.display();
});
});
}
renderSupportDevelopment() {
renderDonateButton(this.containerEl);
}
calculateFiles() {
this.plugin.settings.fileNames = getObsidianFiles(this.app, this.plugin);
}
}
export default BulkRenamePlugin;