mirror of
https://github.com/devon22/obsidian-gridexplorer.git
synced 2026-07-22 05:38:16 +00:00
1.9.9
This commit is contained in:
parent
8389bf04fc
commit
a414b60cb0
10 changed files with 258 additions and 13 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "gridexplorer",
|
||||
"name": "GridExplorer",
|
||||
"version": "1.9.8",
|
||||
"version": "1.9.9",
|
||||
"minAppVersion": "1.1.0",
|
||||
"description": "Browse note files in a grid view.",
|
||||
"author": "Devon22",
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "gridexplorer",
|
||||
"version": "1.9.8",
|
||||
"version": "1.9.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gridexplorer",
|
||||
"version": "1.9.8",
|
||||
"version": "1.9.9",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gridexplorer",
|
||||
"version": "1.9.8",
|
||||
"version": "1.9.9",
|
||||
"description": "Browse note files in a grid view.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,17 @@ export class FileWatcher {
|
|||
}
|
||||
})
|
||||
);
|
||||
|
||||
// 監聽當前開啟的檔案變更,讀取反向連結
|
||||
this.plugin.registerEvent(
|
||||
this.app.workspace.on('file-open', (file) => {
|
||||
if (file instanceof TFile) {
|
||||
if (this.gridView.sourceMode === 'backlinks' && this.gridView.searchQuery === '') {
|
||||
this.gridView.render();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
84
src/FolderRenameModal.ts
Normal file
84
src/FolderRenameModal.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import { App, Modal, Setting, TFolder } from 'obsidian';
|
||||
import { t } from './translations';
|
||||
import GridExplorerPlugin from '../main';
|
||||
import { GridView } from './GridView';
|
||||
|
||||
export function showFolderRenameModal(app: App, plugin: GridExplorerPlugin, folder: TFolder, gridView: GridView) {
|
||||
new FolderRenameModal(app, plugin, folder, gridView).open();
|
||||
}
|
||||
|
||||
export class FolderRenameModal extends Modal {
|
||||
plugin: GridExplorerPlugin;
|
||||
folder: TFolder;
|
||||
gridView: GridView;
|
||||
newName: string;
|
||||
|
||||
constructor(app: App, plugin: GridExplorerPlugin, folder: TFolder, gridView: GridView) {
|
||||
super(app);
|
||||
this.plugin = plugin;
|
||||
this.folder = folder;
|
||||
this.gridView = gridView;
|
||||
this.newName = folder.name;
|
||||
}
|
||||
|
||||
onOpen() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
|
||||
// 如果有 GridView 實例,禁用其鍵盤導航
|
||||
if (this.gridView) {
|
||||
this.gridView.disableKeyboardNavigation();
|
||||
}
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName(t('rename_folder'))
|
||||
.setDesc(t('enter_new_folder_name'))
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.folder.name)
|
||||
.onChange(value => {
|
||||
this.newName = value;
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(contentEl)
|
||||
.addButton(button => {
|
||||
button
|
||||
.setButtonText(t('confirm'))
|
||||
.setCta()
|
||||
.onClick(() => {
|
||||
this.renameFolder();
|
||||
this.close();
|
||||
});
|
||||
})
|
||||
.addButton(button => {
|
||||
button
|
||||
.setButtonText(t('cancel'))
|
||||
.onClick(() => {
|
||||
this.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async renameFolder() {
|
||||
try {
|
||||
await this.app.fileManager.renameFile(this.folder, this.newName);
|
||||
// 重新渲染視圖
|
||||
setTimeout(() => {
|
||||
this.gridView.render();
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
console.error('Failed to rename folder', error);
|
||||
}
|
||||
}
|
||||
|
||||
onClose() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
|
||||
// 如果有 GridView 實例,重新啟用其鍵盤導航
|
||||
if (this.gridView) {
|
||||
this.gridView.enableKeyboardNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { App, Modal, Setting, Platform } from 'obsidian';
|
||||
import { App, Modal, Platform } from 'obsidian';
|
||||
import { GridView } from './GridView';
|
||||
import { t } from './translations';
|
||||
import GridExplorerPlugin from '../main';
|
||||
|
|
|
|||
132
src/GridView.ts
132
src/GridView.ts
|
|
@ -5,6 +5,7 @@ import { findFirstImageInNote } from './mediaUtils';
|
|||
import { MediaModal } from './MediaModal';
|
||||
import { showFolderNoteSettingsModal } from './FolderNoteSettingsModal';
|
||||
import { showNoteColorSettingsModal } from './NoteColorSettingsModal';
|
||||
import { showFolderRenameModal } from './FolderRenameModal';
|
||||
import { showSearchModal } from './SearchModal';
|
||||
import { FileWatcher } from './FileWatcher';
|
||||
import { t } from './translations';
|
||||
|
|
@ -102,10 +103,10 @@ export class GridView extends ItemView {
|
|||
}
|
||||
}
|
||||
|
||||
async setSource(mode: string, path = '', resetScroll = false) {
|
||||
async setSource(mode: string, path = '', resetScroll = false, recordHistory = true) {
|
||||
|
||||
// 記錄之前的狀態到歷史記錄中(如果有)
|
||||
if (this.sourceMode) {
|
||||
if (this.sourceMode && recordHistory) {
|
||||
const previousState = JSON.stringify({ mode: this.sourceMode, path: this.sourcePath });
|
||||
this.recentSources.unshift(previousState);
|
||||
// 限制歷史記錄數量為10個
|
||||
|
|
@ -170,6 +171,11 @@ export class GridView extends ItemView {
|
|||
}
|
||||
return [];
|
||||
} else if (this.sourceMode === 'backlinks') {
|
||||
|
||||
if(this.searchQuery !== '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 反向連結模式:找出所有引用當前筆記的檔案
|
||||
const activeFile = this.app.workspace.getActiveFile();
|
||||
if (!activeFile) {
|
||||
|
|
@ -188,7 +194,7 @@ export class GridView extends ItemView {
|
|||
}
|
||||
}
|
||||
|
||||
return this.sortFiles(this.ignoredFiles(Array.from(backlinks) as TFile[]));
|
||||
return this.sortFiles(Array.from(backlinks) as TFile[]);
|
||||
} else if(this.sourceMode === 'bookmarks') {
|
||||
// 書籤模式
|
||||
const bookmarksPlugin = (this.app as any).internalPlugins.plugins.bookmarks;
|
||||
|
|
@ -499,6 +505,64 @@ export class GridView extends ItemView {
|
|||
});
|
||||
setIcon(newNoteButton, 'square-pen');
|
||||
|
||||
newNoteButton.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault();
|
||||
const menu = new Menu();
|
||||
// 新增筆記
|
||||
menu.addItem((item) => {
|
||||
item
|
||||
.setTitle(t('new_note'))
|
||||
.setIcon('square-pen')
|
||||
.onClick(async () => {
|
||||
let newFileName = `${t('untitled')}.md`;
|
||||
let newFilePath = !this.sourcePath || this.sourcePath === '/' ? newFileName : `${this.sourcePath}/${newFileName}`;
|
||||
|
||||
// 檢查檔案是否已存在,如果存在則遞增編號
|
||||
let counter = 1;
|
||||
while (this.app.vault.getAbstractFileByPath(newFilePath)) {
|
||||
newFileName = `${t('untitled')} ${counter}.md`;
|
||||
newFilePath = !this.sourcePath || this.sourcePath === '/' ? newFileName : `${this.sourcePath}/${newFileName}`;
|
||||
counter++;
|
||||
}
|
||||
|
||||
try {
|
||||
// 建立新筆記
|
||||
const newFile = await this.app.vault.create(newFilePath, '');
|
||||
// 開啟新筆記
|
||||
await this.app.workspace.getLeaf().openFile(newFile);
|
||||
} catch (error) {
|
||||
console.error('An error occurred while creating a new note:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
// 新增資料夾
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(t('new_folder'))
|
||||
.setIcon('folder')
|
||||
.onClick(async () => {
|
||||
let newFolderName = `${t('untitled')}`;
|
||||
let newFolderPath = !this.sourcePath || this.sourcePath === '/' ? newFolderName : `${this.sourcePath}/${newFolderName}`;
|
||||
|
||||
// 檢查資料夾是否已存在,如果存在則遞增編號
|
||||
let counter = 1;
|
||||
while (this.app.vault.getAbstractFileByPath(newFolderPath)) {
|
||||
newFolderName = `${t('untitled')} ${counter}`;
|
||||
newFolderPath = !this.sourcePath || this.sourcePath === '/' ? newFolderName : `${this.sourcePath}/${newFolderName}`;
|
||||
counter++;
|
||||
}
|
||||
|
||||
try {
|
||||
// 建立新資料夾
|
||||
await this.app.vault.createFolder(newFolderPath);
|
||||
this.render(false);
|
||||
} catch (error) {
|
||||
console.error('An error occurred while creating a new folder:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
menu.showAtMouseEvent(event);
|
||||
});
|
||||
|
||||
// 添加回上層按鈕(僅在資料夾模式且不在根目錄時顯示)
|
||||
if (this.sourceMode === 'folder' && this.sourcePath !== '/' && this.searchQuery === '') {
|
||||
const upButton = headerButtonsDiv.createEl('button', { attr: { 'aria-label': t('go_up') } });
|
||||
|
|
@ -655,7 +719,18 @@ export class GridView extends ItemView {
|
|||
.setTitle(`${displayText}`)
|
||||
.setIcon(`${icon}`)
|
||||
.onClick(() => {
|
||||
this.setSource(mode, path, true);
|
||||
// 找出當前點擊的紀錄索引
|
||||
const clickedIndex = this.recentSources.findIndex(source => {
|
||||
const parsed = JSON.parse(source);
|
||||
return parsed.mode === mode && parsed.path === path;
|
||||
});
|
||||
|
||||
// 如果找到點擊的紀錄,清除它之上的紀錄
|
||||
if (clickedIndex !== -1) {
|
||||
this.recentSources = this.recentSources.slice(clickedIndex + 1);
|
||||
}
|
||||
|
||||
this.setSource(mode, path, true, false);
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
@ -792,6 +867,9 @@ export class GridView extends ItemView {
|
|||
});
|
||||
}
|
||||
|
||||
// 創建資料夾夾名稱區域
|
||||
// headerButtonsDiv.createDiv('ge-foldername-content');
|
||||
|
||||
// 創建內容區域
|
||||
const contentEl = this.containerEl.createDiv('view-content');
|
||||
|
||||
|
|
@ -851,6 +929,21 @@ export class GridView extends ItemView {
|
|||
return;
|
||||
}
|
||||
|
||||
// 如果是資料夾模式且沒有搜尋結果,顯示目前資料夾名稱
|
||||
// if (this.sourceMode === 'folder' && this.searchQuery === '' && this.sourcePath !== '/') {
|
||||
// const folderName = this.sourcePath.split('/').pop();
|
||||
// const folderNameContainer = this.containerEl.querySelector('.ge-foldername-content') as HTMLElement;
|
||||
// if (folderNameContainer) {
|
||||
// folderNameContainer.createEl('span', { text: `📁 ${folderName}` });
|
||||
// }
|
||||
// } else {
|
||||
// const folderNameContainer = this.containerEl.querySelector('.ge-foldername-content') as HTMLElement;
|
||||
// if (folderNameContainer) {
|
||||
// folderNameContainer.empty();
|
||||
// folderNameContainer.style.display = 'none';
|
||||
// }
|
||||
// }
|
||||
|
||||
// 如果啟用了顯示"回上層資料夾"選項
|
||||
if (this.sourceMode === 'folder' && this.searchQuery === '' &&
|
||||
this.plugin.settings.showParentFolderItem && this.sourcePath !== '/') {
|
||||
|
|
@ -992,10 +1085,9 @@ export class GridView extends ItemView {
|
|||
});
|
||||
//刪除資料夾筆記
|
||||
menu.addItem((item) => {
|
||||
(item as any).setWarning(true);
|
||||
item
|
||||
.setTitle(t('delete_folder_note'))
|
||||
.setIcon('trash')
|
||||
.setIcon('folder-x')
|
||||
.onClick(() => {
|
||||
this.app.fileManager.trashFile(noteFile as TFile);
|
||||
// 重新渲染視圖
|
||||
|
|
@ -1025,7 +1117,33 @@ export class GridView extends ItemView {
|
|||
.onClick(() => {
|
||||
this.plugin.settings.ignoredFolders.push(folder.path);
|
||||
this.plugin.saveSettings();
|
||||
this.render();
|
||||
});
|
||||
});
|
||||
// 重新命名資料夾
|
||||
menu.addItem((item) => {
|
||||
item
|
||||
.setTitle(t('rename_folder'))
|
||||
.setIcon('file-cog')
|
||||
.onClick(() => {
|
||||
if (folder instanceof TFolder) {
|
||||
showFolderRenameModal(this.app, this.plugin, folder, this);
|
||||
}
|
||||
});
|
||||
});
|
||||
//刪除資料夾
|
||||
menu.addItem((item) => {
|
||||
(item as any).setWarning(true);
|
||||
item
|
||||
.setTitle(t('delete_folder'))
|
||||
.setIcon('trash')
|
||||
.onClick(async () => {
|
||||
if (folder instanceof TFolder) {
|
||||
await this.app.fileManager.trashFile(folder);
|
||||
// 重新渲染視圖
|
||||
setTimeout(() => {
|
||||
this.render();
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
});
|
||||
menu.showAtMouseEvent(event);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'search_current_location_only': '僅搜尋目前位置',
|
||||
'cancel': '取消',
|
||||
'new_note': '新增筆記',
|
||||
'new_folder': '新增資料夾',
|
||||
'delete_folder': '刪除資料夾',
|
||||
'untitled': '未命名',
|
||||
'files': '個檔案',
|
||||
'add': '新增',
|
||||
|
|
@ -168,6 +170,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'note_color': '筆記顏色',
|
||||
'note_color_desc': '設定此筆記的顯示顏色',
|
||||
'set_note_color': '設定筆記顏色',
|
||||
'rename_folder': '重新命名資料夾',
|
||||
'enter_new_folder_name': '輸入新資料夾名稱',
|
||||
},
|
||||
'en': {
|
||||
// Notifications
|
||||
|
|
@ -184,6 +188,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'search_current_location_only': 'Search current location only',
|
||||
'cancel': 'Cancel',
|
||||
'new_note': 'New note',
|
||||
'new_folder': 'New folder',
|
||||
'delete_folder': 'Delete folder',
|
||||
'untitled': 'Untitled',
|
||||
'files': 'files',
|
||||
'add': 'Add',
|
||||
|
|
@ -318,6 +324,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'note_color': 'Note color',
|
||||
'note_color_desc': 'Set the display color for this note',
|
||||
'set_note_color': 'Set note color',
|
||||
'rename_folder': 'Rename folder',
|
||||
'enter_new_folder_name': 'Enter new folder name',
|
||||
},
|
||||
'zh': {
|
||||
// 通知信息
|
||||
|
|
@ -334,6 +342,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'search_current_location_only': '仅搜索当前位置',
|
||||
'cancel': '取消',
|
||||
'new_note': '新建笔记',
|
||||
'new_folder': '新建文件夹',
|
||||
'delete_folder': '删除文件夹',
|
||||
'untitled': '未命名',
|
||||
'files': '个文件',
|
||||
'add': '添加',
|
||||
|
|
@ -468,6 +478,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'note_color': '笔记颜色',
|
||||
'note_color_desc': '设置此笔记的显示颜色',
|
||||
'set_note_color': '设置笔记颜色',
|
||||
'rename_folder': '重新命名文件夹',
|
||||
'enter_new_folder_name': '输入新文件夹名称',
|
||||
},
|
||||
'ja': {
|
||||
// 通知メッジ
|
||||
|
|
@ -484,6 +496,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'search_current_location_only': '現在の場所のみ検索',
|
||||
'cancel': 'キャンセル',
|
||||
'new_note': '新規ノート',
|
||||
'new_folder': '新規フォルダ',
|
||||
'delete_folder': '削除フォルダ',
|
||||
'untitled': '無題',
|
||||
'files': 'ファイル',
|
||||
'add': '追加',
|
||||
|
|
@ -618,5 +632,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'note_color': 'ノート色',
|
||||
'note_color_desc': 'このノートの表示色を設定',
|
||||
'set_note_color': 'ノート色を設定',
|
||||
'rename_folder': 'フォルダを再命名',
|
||||
'enter_new_folder_name': '新しいフォルダ名を入力',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
styles.css
16
styles.css
|
|
@ -257,6 +257,22 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
/* .ge-foldername-content {
|
||||
margin-top: 5px;
|
||||
flex-basis: 100%;
|
||||
order: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: var(--button-radius);
|
||||
}
|
||||
|
||||
.ge-foldername-content span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
} */
|
||||
|
||||
/* 搜尋對話框樣式 */
|
||||
.ge-search-container {
|
||||
margin-bottom: 8px;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"1.9.8": "1.1.0"
|
||||
"1.9.9": "1.1.0"
|
||||
}
|
||||
Loading…
Reference in a new issue