-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
executable file
·163 lines (139 loc) · 4.31 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import { App, Plugin, PluginSettingTab, Setting, TFile, TFolder, Notice } from "obsidian";
interface AutoFileMoveSettings {
folderMapping: Record<string, string>; // mapping from extension to folder
}
const DEFAULT_SETTINGS: AutoFileMoveSettings = {
folderMapping: {},
};
export default class AutoFileMovePlugin extends Plugin {
settings: AutoFileMoveSettings;
async onload() {
console.log("Auto File Move Plugin loaded!");
await this.loadSettings();
this.addSettingTab(new AutoFileMoveSettingTab(this.app, this));
this.registerEvent(
this.app.vault.on("create", async (file: TFile) => {
if (Object.keys(this.settings.folderMapping).length > 0) {
await this.handleFile(file);
} else {
console.log("No folder mapping defined. Skipping file organization.");
}
})
);
}
async handleFile(file: TFile): Promise<boolean> {
if (!(file instanceof TFile)) return false;
const extension = file.extension;
const targetFolder = this.settings.folderMapping[extension];
if (targetFolder) {
await this.ensureFolderExists(targetFolder);
const targetPath = `${targetFolder}/${file.name}`;
try {
await this.app.vault.rename(file, targetPath);
return true; // file moved
} catch (err) {
console.error(`Failed to move file ${file.name}:`, err);
}
} else {
console.log(`No folder mapping found for extension: ${extension}`);
}
return false; // file not moved
}
async ensureFolderExists(folderPath: string) {
if (!await this.app.vault.adapter.exists(folderPath)) {
await this.app.vault.createFolder(folderPath);
}
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
if (Object.keys(this.settings.folderMapping).length > 0) {
await this.organizeVault();
}
}
async organizeVault() {
const files = this.app.vault.getFiles();
const movedFiles: string[] = [];
for (const file of files) {
const moved = await this.handleFile(file);
if (moved) {
movedFiles.push(file.name);
}
}
// notice of diff
if (movedFiles.length > 0) {
new Notice(`Moved ${movedFiles.length} files:\n${movedFiles.join(", ")}`);
} else {
new Notice("No files were moved.");
}
}
}
class AutoFileMoveSettingTab extends PluginSettingTab {
plugin: AutoFileMovePlugin;
constructor(app: App, plugin: AutoFileMovePlugin) {
super(app, plugin);
this.plugin = plugin;
}
async display(): Promise<void> {
const { containerEl } = this;
containerEl.empty();
// get all folders
const allFolders = this.app.vault.getAllFolders();
for (const [extension, folder] of Object.entries(this.plugin.settings.folderMapping)) {
new Setting(containerEl)
.setName(`Extension: ${extension}`)
.setDesc("Change the folder for this extension")
.addDropdown(dropdown => {
// init dropdown
dropdown.addOption("", "Select folder...");
allFolders.forEach(f => dropdown.addOption(f.path, f.path));
dropdown.setValue(folder);
// changes dropdown
dropdown.onChange(async (value) => {
if (value) {
this.plugin.settings.folderMapping[extension] = value;
await this.plugin.saveSettings();
new Notice(`Folder for .${extension} files updated to: ${value}`);
}
});
})
.addButton(btn =>
btn
.setButtonText("Delete")
.setCta()
.onClick(async () => {
delete this.plugin.settings.folderMapping[extension];
await this.plugin.saveSettings();
this.display();
})
);
}
let newExtension = "";
let newFolder = "";
new Setting(containerEl)
.setName("Add new mapping")
.setDesc("Add a new extension and target folder")
.addText(text => text
.setPlaceholder("Enter extension (e.g., docx)")
.onChange((value) => newExtension = value.trim())
)
.addDropdown(dropdown => {
dropdown.addOption("", "Select folder...");
allFolders.forEach(folder => dropdown.addOption(folder.path, folder.path));
dropdown.onChange(value => newFolder = value);
})
.addButton(btn => {
btn.setButtonText("Add")
.setCta()
.onClick(async () => {
if (newExtension && newFolder) {
this.plugin.settings.folderMapping[newExtension] = newFolder;
await this.plugin.saveSettings();
this.display();
}
});
});
}
}