This commit is contained in:
Devon22 2025-06-18 23:29:27 +08:00
parent 1718504eab
commit 55638f0eb7
14 changed files with 423 additions and 270 deletions

View file

@ -61,6 +61,10 @@ Available colors:
- purple
- pink
CSS Class `.ge-grid-item.ge-foldernote`
## Settings
In the plugin's settings page, you can:

View file

@ -61,6 +61,10 @@ color: red
- purple
- pink
CSS Class `.ge-grid-item.ge-foldernote`
## 設定
プラグインの設定ページでは、以下のことができます:

View file

@ -61,6 +61,10 @@ color: red
- purple
- pink
CSS Class `.ge-grid-item.ge-foldernote`
## 設定
在插件的設定頁面中,您可以:

View file

@ -1,7 +1,7 @@
{
"id": "gridexplorer",
"name": "GridExplorer",
"version": "2.3.0",
"version": "2.4.0",
"minAppVersion": "1.1.0",
"description": "Browse note files in a grid view.",
"author": "Devon22",

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "gridexplorer",
"version": "2.3.0",
"version": "2.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "gridexplorer",
"version": "2.3.0",
"version": "2.4.0",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",

View file

@ -1,6 +1,6 @@
{
"name": "gridexplorer",
"version": "2.3.0",
"version": "2.4.0",
"description": "Browse note files in a grid view.",
"main": "main.js",
"scripts": {

View file

@ -7,6 +7,7 @@ export interface FolderNoteSettings {
sort: string;
color: string;
icon: string;
isPinned: boolean;
}
export function showFolderNoteSettingsModal(app: App, plugin: GridExplorerPlugin, folder: TFolder, gridView: GridView) {
@ -20,7 +21,8 @@ export class FolderNoteSettingsModal extends Modal {
settings: FolderNoteSettings = {
sort: '',
color: '',
icon: '📁'
icon: '📁',
isPinned: false
};
existingFile: TFile | null = null;
@ -105,6 +107,19 @@ export class FolderNoteSettingsModal extends Modal {
});
});
// 置頂勾選框
new Setting(contentEl)
.setName(t('pinned'))
.setDesc(t('pinned_desc'))
.addToggle(toggle => {
toggle
.setValue(this.settings.isPinned)
.onChange(value => {
this.settings.isPinned = value;
});
});
// 按鈕區域
const buttonSetting = new Setting(contentEl);
@ -142,6 +157,16 @@ export class FolderNoteSettingsModal extends Modal {
if ('icon' in fileCache.frontmatter) {
this.settings.icon = fileCache.frontmatter.icon || '📁';
}
// 讀取置頂設定
if (fileCache.frontmatter?.pinned && Array.isArray(fileCache.frontmatter.pinned)) {
this.settings.isPinned = fileCache.frontmatter.pinned.some((item: any) => {
if (!item) return false;
const pinnedName = item.toString();
const pinnedNameWithoutExt = pinnedName.replace(/\.\w+$/, '');
return pinnedNameWithoutExt === this.folder.name;
});
}
}
} catch (error) {
console.error('無法讀取資料夾筆記設定', error);
@ -184,6 +209,27 @@ export class FolderNoteSettingsModal extends Modal {
} else {
delete frontmatter['icon'];
}
const folderName = `${this.folder.name}.md`;
if (this.settings.isPinned) {
// 如果原本就有 pinned 陣列,則添加或更新
if (Array.isArray(frontmatter['pinned'])) {
if (!frontmatter['pinned'].includes(folderName)) {
frontmatter['pinned'] = [folderName, ...frontmatter['pinned']];
}
} else {
// 如果沒有 pinned 陣列,則創建一個新的
frontmatter['pinned'] = [folderName];
}
} else if (Array.isArray(frontmatter['pinned'])) {
// 如果取消置頂,則從陣列中移除
frontmatter['pinned'] = frontmatter['pinned'].filter(
(item: any) => item !== folderName
);
// 如果陣列為空,則刪除該欄位
if (frontmatter['pinned'].length === 0) {
delete frontmatter['pinned'];
}
}
});
// 強制更新 metadata cache

View file

@ -1,4 +1,4 @@
import { App, Modal, Setting, TFolder } from 'obsidian';
import { App, Modal, Setting, TFolder, normalizePath } from 'obsidian';
import { t } from './translations';
import GridExplorerPlugin from '../main';
import { GridView } from './GridView';
@ -57,7 +57,9 @@ export class FolderRenameModal extends Modal {
async renameFolder() {
try {
await this.app.fileManager.renameFile(this.folder, this.newName);
const parentPath = this.folder.parent ? this.folder.parent.path : '';
const newPath = normalizePath(parentPath ? `${parentPath}/${this.newName}` : this.newName);
await this.app.fileManager.renameFile(this.folder, newPath);
// 重新渲染視圖
setTimeout(() => {
this.gridView.render();

View file

@ -246,10 +246,32 @@ export class FolderSelectionModal extends Modal {
// 建立資料夾選項
folders.forEach(folder => {
// 計算資料夾層級
const depth = (folder.path.match(/\//g) || []).length;
const displayName = folder.path.split('/').pop() || '/';
const folderOption = this.folderOptionsContainer.createEl('div', {
cls: 'ge-grid-view-folder-option',
text: `📁 ${folder.path || '/'}`
attr: {
'data-depth': depth.toString(),
'data-path': folder.path
}
});
// 產生 ascii tree 前綴
const prefixSpan = document.createElement('span');
prefixSpan.className = 'ge-folder-tree-prefix';
prefixSpan.textContent = depth > 0 ? ' '.repeat(depth - 1) + '└ ' : '';
folderOption.appendChild(prefixSpan);
// 資料夾圖示與名稱
const icon = document.createElement('span');
icon.textContent = '📁 ';
folderOption.appendChild(icon);
const nameSpan = document.createElement('span');
nameSpan.textContent = displayName;
folderOption.appendChild(nameSpan);
folderOption.addEventListener('click', () => {
if (this.activeView) {
@ -359,7 +381,8 @@ export class FolderSelectionModal extends Modal {
this.folderOptions.forEach(option => {
const text = option.textContent?.toLowerCase() || '';
if (searchTerm === '' || text.includes(searchTerm)) {
const fullPath = option.getAttribute('data-path')?.toLowerCase() || '';
if (searchTerm === '' || text.includes(searchTerm) || fullPath.includes(searchTerm)) {
option.style.display = 'block';
hasVisibleOptions = true;
} else {

View file

@ -1,4 +1,4 @@
import { WorkspaceLeaf, ItemView, TFolder, TFile, Menu, Notice, Platform, setIcon, getFrontMatterInfo, FrontMatterCache } from 'obsidian';
import { WorkspaceLeaf, ItemView, TFolder, TFile, Menu, Notice, Platform, setIcon, getFrontMatterInfo, FrontMatterCache, normalizePath } from 'obsidian';
import { showFolderSelectionModal } from './FolderSelectionModal';
import { findFirstImageInNote } from './mediaUtils';
import { MediaModal } from './MediaModal';
@ -186,100 +186,7 @@ export class GridView extends ItemView {
}
}
});
// 為頂部按鈕區域添加右鍵選單事件
headerButtonsDiv.addEventListener('contextmenu', (event: MouseEvent) => {
// 只有當點擊的是頂部按鈕區域本身(而不是其中的按鈕)時才觸發捲動
if (event.target === headerButtonsDiv) {
event.preventDefault();
const menu = new Menu();
menu.addItem((item) => {
item
.setTitle(t('open_new_grid_view'))
.setIcon('grid')
.onClick(() => {
const { workspace } = this.app;
let leaf = null;
workspace.getLeavesOfType('grid-view');
switch (this.plugin.settings.defaultOpenLocation) {
case 'left':
leaf = workspace.getLeftLeaf(false);
break;
case 'right':
leaf = workspace.getRightLeaf(false);
break;
case 'tab':
default:
leaf = workspace.getLeaf('tab');
break;
}
if (!leaf) {
// 如果無法獲取指定位置的 leaf則回退到新分頁
leaf = workspace.getLeaf('tab');
}
leaf.setViewState({ type: 'grid-view', active: true });
// 設定資料來源
if (leaf.view instanceof GridView) {
leaf.view.setSource('folder', '/');
}
// 確保視圖是活躍的
workspace.revealLeaf(leaf);
});
});
//如果目前是資料夾模式且有資料夾筆記,則增加"打開資料夾筆記"選項
if (this.sourceMode === 'folder' && this.sourcePath && this.sourcePath !== '/') {
const folderName = this.sourcePath.split('/').pop() || '';
const notePath = `${this.sourcePath}/${folderName}.md`;
const noteFile = this.app.vault.getAbstractFileByPath(notePath);
if (noteFile instanceof TFile) {
menu.addItem((item) => {
item
.setTitle(t('open_folder_note'))
.setIcon('panel-left-open')
.onClick(() => {
this.app.workspace.getLeaf().openFile(noteFile);
});
});
}
}
// 最小化模式選項
menu.addItem((item) => {
item
.setTitle(t('min_mode'))
.setIcon('minimize-2')
.setChecked(this.minMode)
.onClick(() => {
this.minMode = !this.minMode;
this.app.workspace.requestSaveLayout();
this.render();
});
});
// 顯示忽略資料夾選項
menu.addItem((item) => {
item
.setTitle(t('show_ignored_folders'))
.setIcon('folder-open-dot')
.setChecked(this.showIgnoredFolders)
.onClick(() => {
this.showIgnoredFolders = !this.showIgnoredFolders;
this.app.workspace.requestSaveLayout();
this.render();
});
});
menu.addItem((item) => {
item
.setTitle(t('open_settings'))
.setIcon('settings')
.onClick(() => {
// 打開插件設定頁面
(this.app as any).setting.open();
(this.app as any).setting.openTabById(this.plugin.manifest.id);
});
});
menu.showAtMouseEvent(event);
}
});
// 添加新增筆記按鈕
const newNoteButton = headerButtonsDiv.createEl('button', { attr: { 'aria-label': t('new_note') } });
newNoteButton.addEventListener('click', async () => {
@ -363,97 +270,6 @@ export class GridView extends ItemView {
menu.showAtMouseEvent(event);
});
// 添加回上層按鈕(僅在資料夾模式且不在根目錄時顯示)
if (this.sourceMode === 'folder' && this.sourcePath !== '/' && this.searchQuery === '') {
const upButton = headerButtonsDiv.createEl('button', { attr: { 'aria-label': t('go_up') } });
upButton.addEventListener('click', () => {
const parentPath = this.sourcePath.split('/').slice(0, -1).join('/') || '/';
this.setSource('folder', parentPath, true);
this.clearSelection();
});
setIcon(upButton, 'arrow-up');
if(Platform.isDesktop) {
// 為上層按鈕添加拖曳目標功能
upButton.addEventListener('dragover', (event) => {
// 防止預設行為以允許放置
event.preventDefault();
// 設定拖曳效果為移動
event.dataTransfer!.dropEffect = 'move';
// 顯示可放置的視覺提示
upButton.addClass('ge-dragover');
});
upButton.addEventListener('dragleave', () => {
// 移除視覺提示
upButton.removeClass('ge-dragover');
});
upButton.addEventListener('drop', async (event) => {
// 防止預設行為
event.preventDefault();
// 移除視覺提示
upButton.removeClass('ge-dragover');
// 獲取上一層資料夾路徑
const parentPath = this.sourcePath.split('/').slice(0, -1).join('/') || '/';
if (!parentPath) return;
// 獲取資料夾物件
const folder = this.app.vault.getAbstractFileByPath(parentPath);
if (!(folder instanceof TFolder)) return;
// 檢查是否有多個檔案被拖曳
const filesData = event.dataTransfer?.getData('application/obsidian-grid-explorer-files');
if (filesData) {
try {
// 解析檔案路徑列表
const filePaths = JSON.parse(filesData);
// 移動所有檔案
for (const filePath of filePaths) {
const file = this.app.vault.getAbstractFileByPath(filePath);
if (file instanceof TFile) {
// 計算新的檔案路徑
const newPath = `${parentPath}/${file.name}`;
// 移動檔案
await this.app.fileManager.renameFile(file, newPath);
}
}
// 重新渲染視圖
this.render();
} catch (error) {
console.error('An error occurred while moving multiple files to parent folder:', error);
}
return;
}
// 如果沒有多個檔案資料,嘗試獲取單個檔案路徑(向後兼容)
const filePath = event.dataTransfer?.getData('text/plain');
if (!filePath) return;
const cleanedFilePath = filePath.replace(/!?\[\[(.*?)\]\]/, '$1');
// 獲取檔案物件
const file = this.app.vault.getAbstractFileByPath(cleanedFilePath);
if (file instanceof TFile) {
try {
// 計算新的檔案路徑
const newPath = `${parentPath}/${file.name}`;
// 移動檔案
await this.app.fileManager.renameFile(file, newPath);
// 重新渲染視圖
this.render();
} catch (error) {
console.error('An error occurred while moving the file to parent folder:', error);
}
}
});
}
}
// 添加重新選擇資料夾按鈕
const reselectButton = headerButtonsDiv.createEl('button', { attr: { 'aria-label': t('reselect') } });
reselectButton.addEventListener('click', () => {
@ -722,6 +538,226 @@ export class GridView extends ItemView {
});
}
// 添加設定按鈕
if (this.searchQuery === '') {
const moreOptionsButton = headerButtonsDiv.createEl('button', { attr: { 'aria-label': t('more_options') } });
setIcon(moreOptionsButton, 'ellipsis-vertical');
const menu = new Menu();
menu.addItem((item) => {
item
.setTitle(t('open_new_grid_view'))
.setIcon('grid')
.onClick(() => {
const { workspace } = this.app;
let leaf = null;
workspace.getLeavesOfType('grid-view');
switch (this.plugin.settings.defaultOpenLocation) {
case 'left':
leaf = workspace.getLeftLeaf(false);
break;
case 'right':
leaf = workspace.getRightLeaf(false);
break;
case 'tab':
default:
leaf = workspace.getLeaf('tab');
break;
}
if (!leaf) {
// 如果無法獲取指定位置的 leaf則回退到新分頁
leaf = workspace.getLeaf('tab');
}
leaf.setViewState({ type: 'grid-view', active: true });
// 設定資料來源
if (leaf.view instanceof GridView) {
leaf.view.setSource('folder', '/');
}
// 確保視圖是活躍的
workspace.revealLeaf(leaf);
});
});
//如果目前是資料夾模式且有資料夾筆記,則增加"打開資料夾筆記"選項
if (this.sourceMode === 'folder' && this.sourcePath && this.sourcePath !== '/') {
const folder = this.app.vault.getAbstractFileByPath(this.sourcePath);
const folderName = this.sourcePath.split('/').pop() || '';
const notePath = `${this.sourcePath}/${folderName}.md`;
const noteFile = this.app.vault.getAbstractFileByPath(notePath);
if (noteFile instanceof TFile) {
//打開資料夾筆記
menu.addItem((item) => {
item
.setTitle(t('open_folder_note'))
.setIcon('panel-left-open')
.onClick(() => {
this.app.workspace.getLeaf().openFile(noteFile);
});
});
//編輯資料夾筆記設定
menu.addItem((item) => {
item
.setTitle(t('edit_folder_note_settings'))
.setIcon('settings-2')
.onClick(() => {
if (folder instanceof TFolder) {
showFolderNoteSettingsModal(this.app, this.plugin, folder, this);
}
});
});
//刪除資料夾筆記
menu.addItem((item) => {
item
.setTitle(t('delete_folder_note'))
.setIcon('folder-x')
.onClick(() => {
this.app.fileManager.trashFile(noteFile as TFile);
});
});
} else {
//建立Folder note
menu.addItem((item) => {
item
.setTitle(t('create_folder_note'))
.setIcon('file-cog')
.onClick(() => {
if (folder instanceof TFolder) {
showFolderNoteSettingsModal(this.app, this.plugin, folder, this);
}
});
});
}
}
// 最小化模式選項
menu.addItem((item) => {
item
.setTitle(t('min_mode'))
.setIcon('minimize-2')
.setChecked(this.minMode)
.onClick(() => {
this.minMode = !this.minMode;
this.app.workspace.requestSaveLayout();
this.render();
});
});
// 顯示忽略資料夾選項
menu.addItem((item) => {
item
.setTitle(t('show_ignored_folders'))
.setIcon('folder-open-dot')
.setChecked(this.showIgnoredFolders)
.onClick(() => {
this.showIgnoredFolders = !this.showIgnoredFolders;
this.app.workspace.requestSaveLayout();
this.render();
});
});
menu.addItem((item) => {
item
.setTitle(t('open_settings'))
.setIcon('settings')
.onClick(() => {
// 打開插件設定頁面
(this.app as any).setting.open();
(this.app as any).setting.openTabById(this.plugin.manifest.id);
});
});
moreOptionsButton.addEventListener('click', (event) => {
menu.showAtMouseEvent(event);
});
}
// 如果是資料夾模式且沒有搜尋結果,顯示目前資料夾名稱
if (this.sourceMode === 'folder' && this.searchQuery === '' && this.sourcePath !== '/') {
const pathParts = this.sourcePath.split('/');
const parentPath = pathParts.slice(0, -1).join('/') || '/';
let parentFolderName = pathParts.slice(-2, -1)[0] || '/';
const currentFolderName = pathParts.pop() || t('root');
// 若為根目錄,以 'root' 顯示
if (parentPath === '/' || parentFolderName === '/' || parentFolderName === '') {
parentFolderName = t('root');
}
const folderNameContainer = this.containerEl.createDiv('ge-foldername-content');
// 建立可點擊的上層資料夾名稱
const customFolderIcon = this.plugin.settings.customFolderIcon;
const parentFolderLink = folderNameContainer.createEl('a', {
text: `${customFolderIcon} ${parentFolderName}`.trim(),
cls: 'ge-parent-folder-link'
});
parentFolderLink.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
this.setSource('folder', parentPath, true);
this.clearSelection();
});
// 分隔符號
folderNameContainer.createEl('span', { text: ' > ' });
// 目前資料夾名稱
folderNameContainer.createEl('span', { text: currentFolderName });
if (Platform.isDesktop) {
// 為上層按鈕添加拖曳目標功能
parentFolderLink.addEventListener('dragover', (event) => {
event.preventDefault();
event.dataTransfer!.dropEffect = 'move';
parentFolderLink.addClass('ge-dragover');
});
parentFolderLink.addEventListener('dragleave', () => {
parentFolderLink.removeClass('ge-dragover');
});
parentFolderLink.addEventListener('drop', async (event) => {
event.preventDefault();
parentFolderLink.removeClass('ge-dragover');
const parentPath = this.sourcePath.split('/').slice(0, -1).join('/') || '/';
if (!parentPath) return;
const folder = this.app.vault.getAbstractFileByPath(parentPath);
if (!(folder instanceof TFolder)) return;
const filesData = event.dataTransfer?.getData('application/obsidian-grid-explorer-files');
if (filesData) {
try {
const filePaths = JSON.parse(filesData);
for (const filePath of filePaths) {
const file = this.app.vault.getAbstractFileByPath(filePath);
if (file instanceof TFile) {
const newPath = normalizePath(`${parentPath}/${file.name}`);
await this.app.fileManager.renameFile(file, newPath);
}
}
} catch (error) {
console.error('An error occurred while moving multiple files to parent folder:', error);
}
return;
}
const filePath = event.dataTransfer?.getData('text/plain');
if (!filePath) return;
const cleanedFilePath = filePath.replace(/!?\[\[(.*?)\]\]/, '$1');
const file = this.app.vault.getAbstractFileByPath(cleanedFilePath);
if (file instanceof TFile) {
try {
const newPath = normalizePath(`${parentPath}/${file.name}`);
await this.app.fileManager.renameFile(file, newPath);
this.render();
} catch (error) {
console.error('An error occurred while moving the file to parent folder:', error);
}
}
});
}
}
// 創建內容區域
const contentEl = this.containerEl.createDiv('view-content');
@ -735,8 +771,20 @@ export class GridView extends ItemView {
const noteFile = this.app.vault.getAbstractFileByPath(notePath);
if (noteFile instanceof TFile) {
const metadata = this.app.metadataCache.getFileCache(noteFile)?.frontmatter;
if (metadata && Array.isArray(metadata['pinned'])) {
this.pinnedList = metadata['pinned'] as string[];
if (metadata) {
if (Array.isArray(metadata['pinned'])) {
if (this.plugin.settings.folderNoteDisplaySettings === 'pinned') {
// 先過濾掉所有重複的資料夾筆記
this.pinnedList = metadata['pinned'].filter((name: string) => name !== `${folderName}.md`);
// 將資料夾筆記添加到最前面
this.pinnedList.unshift(`${folderName}.md`);
} else {
this.pinnedList = metadata['pinned'];
}
} else if (this.plugin.settings.folderNoteDisplaySettings === 'pinned') {
// 如果沒有置頂清單,則建立一個僅包含資料夾筆記的清單
this.pinnedList = [`${folderName}.md`];
}
} else {
this.pinnedList = [];
}
@ -762,7 +810,7 @@ export class GridView extends ItemView {
}
async grid_render() {
const container = this.containerEl.children[1] as HTMLElement;
const container = this.containerEl.querySelector('.view-content') as HTMLElement;
container.empty();
container.addClass('ge-grid-container');
@ -805,45 +853,6 @@ export class GridView extends ItemView {
return;
}
// 如果是資料夾模式且沒有搜尋結果,顯示目前資料夾名稱
if (this.sourceMode === 'folder' && this.searchQuery === '' &&
this.plugin.settings.showParentFolderItem && this.sourcePath !== '/') {
const pathParts = this.sourcePath.split('/');
const parentPath = pathParts.slice(0, -1).join('/') || '/';
let parentFolderName = pathParts.slice(-2, -1)[0] || '/';
const currentFolderName = pathParts.pop() || t('root');
// 若為根目錄,以 'root' 顯示
if (parentPath === '/' || parentFolderName === '/' || parentFolderName === '') {
parentFolderName = t('root');
}
const folderNameContainer = container.createDiv('ge-foldername-content');
if (folderNameContainer) {
// 建立可點擊的上層資料夾名稱
const customFolderIcon = this.plugin.settings.customFolderIcon;
const parentFolderLink = folderNameContainer.createEl('a', {
text: `${customFolderIcon} ${parentFolderName}`.trim(),
cls: 'ge-parent-folder-link'
});
// 點擊後跳轉到上層資料夾
parentFolderLink.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
this.setSource('folder', parentPath, true);
this.clearSelection();
});
// 分隔符號
folderNameContainer.createEl('span', { text: ' > ' });
// 目前資料夾名稱
folderNameContainer.createEl('span', { text: currentFolderName });
}
}
// 如果是資料夾模式,先顯示所有子資料夾
if (this.sourceMode === 'folder' && this.searchQuery === '') {
const currentFolder = this.app.vault.getAbstractFileByPath(this.sourcePath || '/');
@ -989,6 +998,7 @@ export class GridView extends ItemView {
const notePath = `${folder.path}/${folder.name}.md`;
let noteFile = this.app.vault.getAbstractFileByPath(notePath);
if (noteFile instanceof TFile) {
//打開資料夾筆記
menu.addItem((item) => {
item
.setTitle(t('open_folder_note'))
@ -997,6 +1007,7 @@ export class GridView extends ItemView {
this.app.workspace.getLeaf().openFile(noteFile);
});
});
//編輯資料夾筆記設定
menu.addItem((item) => {
item
.setTitle(t('edit_folder_note_settings'))
@ -1014,10 +1025,6 @@ export class GridView extends ItemView {
.setIcon('folder-x')
.onClick(() => {
this.app.fileManager.trashFile(noteFile as TFile);
// 重新渲染視圖
setTimeout(() => {
this.render();
}, 100);
});
});
} else {
@ -1087,8 +1094,8 @@ export class GridView extends ItemView {
});
}
// 資料夾渲染完插入 break僅當有資料夾時或有顯示回上一層資料夾項目時
if (subfolders.length > 0 || (subfolders.length === 0 && this.plugin.settings.dateDividerMode !== 'none' && this.plugin.settings.showParentFolderItem)) {
// 資料夾渲染完插入 break僅當有資料夾
if (subfolders.length > 0) {
container.createDiv('ge-break');
}
}
@ -1224,6 +1231,16 @@ export class GridView extends ItemView {
const otherFiles = files.filter(f => !this.pinnedList.includes(f.name));
files = [...pinnedFiles, ...otherFiles];
}
if (this.sourceMode === 'folder' && this.sourcePath !== '/') {
if (this.plugin.settings.folderNoteDisplaySettings === 'hidden') {
const currentFolder = this.app.vault.getAbstractFileByPath(this.sourcePath);
if (currentFolder instanceof TFolder) {
const folderName = currentFolder.name;
files = files.filter(f => f.name !== `${folderName}.md`);
}
}
}
// 創建 Intersection Observer
const observer = new IntersectionObserver((entries, observer) => {
@ -1599,6 +1616,14 @@ export class GridView extends ItemView {
this.gridItems.push(fileEl); // 添加到網格項目數組
fileEl.dataset.filePath = file.path;
// 如果檔案與父資料夾同名,添加 ge-foldernote 類別
const parentPath = file.parent?.path || '';
const parentName = parentPath.split('/').pop() || '';
const fileName = file.basename;
if (parentName === fileName) {
fileEl.addClass('ge-foldernote');
}
// 創建左側內容區,包含圖示和標題
const contentArea = fileEl.createDiv('ge-content-area');
@ -1897,7 +1922,7 @@ export class GridView extends ItemView {
if (file instanceof TFile) {
try {
// 計算新的檔案路徑
const newPath = `${folderPath}/${file.name}`;
const newPath = normalizePath(`${folderPath}/${file.name}`);
// 移動檔案
await this.app.fileManager.renameFile(file, newPath);
} catch (error) {
@ -1905,10 +1930,9 @@ export class GridView extends ItemView {
}
}
}
// 重新渲染視圖
// this.render();
return;
} catch (error) {
console.error('Error parsing dragged files data:', error);
}
@ -1931,11 +1955,10 @@ export class GridView extends ItemView {
if (file instanceof TFile && folder instanceof TFolder) {
try {
// 計算新的檔案路徑
const newPath = `${folderPath}/${file.name}`;
const newPath = normalizePath(`${folderPath}/${file.name}`);
// 移動檔案
await this.app.fileManager.renameFile(file, newPath);
// 重新渲染視圖
// this.render();
} catch (error) {
console.error('An error occurred while moving the file:', error);
}

View file

@ -16,7 +16,6 @@ export interface GallerySettings {
showMediaFiles: boolean; // 是否顯示圖片和影片
showVideoThumbnails: boolean; // 是否顯示影片縮圖
defaultOpenLocation: string; // 預設開啟位置
showParentFolderItem: boolean; // 是否显示"返回上级文件夹"选项
reuseExistingLeaf: boolean; // 是否重用現有的網格視圖
showBookmarksMode: boolean; // 是否顯示書籤模式
showSearchMode: boolean; // 是否顯示搜尋結果模式
@ -38,6 +37,7 @@ export interface GallerySettings {
showNoteTags: boolean; // 是否顯示筆記標籤
dateDividerMode: string; // 日期分隔器模式none, year, month, day
showCodeBlocksInSummary: boolean; // 是否在摘要中顯示程式碼區塊
folderNoteDisplaySettings: string; // 資料夾筆記設定
}
// 預設設定
@ -55,7 +55,6 @@ export const DEFAULT_SETTINGS: GallerySettings = {
showMediaFiles: true, // 預設顯示圖片和影片
showVideoThumbnails: true, // 預設顯示影片縮圖
defaultOpenLocation: 'tab', // 預設開啟位置:新分頁
showParentFolderItem: false, // 預設不顯示"返回上層資料夾"選項
reuseExistingLeaf: false, // 預設不重用現有的網格視圖
showBookmarksMode: true, // 預設顯示書籤模式
showSearchMode: true, // 預設顯示搜尋結果模式
@ -77,6 +76,7 @@ export const DEFAULT_SETTINGS: GallerySettings = {
showNoteTags: false, // 預設不顯示筆記標籤
dateDividerMode: 'none', // 預設不使用日期分隔器
showCodeBlocksInSummary: false, // 預設不在摘要中顯示程式碼區塊
folderNoteDisplaySettings: 'default', // 預設不處理資料夾筆記
};
// 設定頁面類別
@ -436,19 +436,6 @@ export class GridExplorerSettingTab extends PluginSettingTab {
await this.plugin.saveSettings();
});
});
// 顯示"回上層資料夾"選項設定
new Setting(containerEl)
.setName(t('show_parent_folder_item'))
.setDesc(t('show_parent_folder_item_desc'))
.addToggle(toggle => {
toggle
.setValue(this.plugin.settings.showParentFolderItem)
.onChange(async (value) => {
this.plugin.settings.showParentFolderItem = value;
await this.plugin.saveSettings();
});
});
// 顯示筆記標籤設定
new Setting(containerEl)
@ -565,7 +552,25 @@ export class GridExplorerSettingTab extends PluginSettingTab {
await this.plugin.saveSettings();
}));
// 資料夾筆記設定區域
containerEl.createEl('h3', { text: t('folder_note_settings') });
// 資料夾筆記設定 (預設、置頂、隱藏)
new Setting(containerEl)
.setName(t('foldernote_display_settings'))
.setDesc(t('foldernote_display_settings_desc'))
.addDropdown(dropdown => {
dropdown
.addOption('default', t('default'))
.addOption('pinned', t('pinned'))
.addOption('hidden', t('hidden'))
.setValue(this.plugin.settings.folderNoteDisplaySettings)
.onChange(async (value) => {
this.plugin.settings.folderNoteDisplaySettings = value;
await this.plugin.saveSettings();
});
});
// 忽略資料夾設定區域
containerEl.createEl('h3', { text: t('ignored_folders_settings') });

View file

@ -43,6 +43,7 @@ export const TRANSLATIONS: Translations = {
'files': '個檔案',
'add': '新增',
'root': '根目錄',
'more_options': '更多選項',
// 視圖標題
'grid_view_title': '網格視圖',
@ -130,7 +131,11 @@ export const TRANSLATIONS: Translations = {
'task_filter': '任務分類',
'uncompleted': '未完成',
'completed': '已完成',
'foldernote_display_settings': '資料夾筆記顯示設定',
'foldernote_display_settings_desc': '設定資料夾筆記的顯示方式',
'all': '全部',
'default': '預設',
'hidden': '隱藏',
// 顯示"返回上層資料夾"選項設定
'show_parent_folder_item': '顯示「返回上層資料夾」',
@ -243,6 +248,7 @@ export const TRANSLATIONS: Translations = {
'files': 'files',
'add': 'Add',
'root': 'Root',
'more_options': 'More options',
// View Titles
'grid_view_title': 'Grid view',
@ -330,7 +336,11 @@ export const TRANSLATIONS: Translations = {
'task_filter': 'Task filter',
'uncompleted': 'Uncompleted',
'completed': 'Completed',
'foldernote_display_settings': 'Folder note display settings',
'foldernote_display_settings_desc': 'Set the display mode of folder notes',
'all': 'All',
'default': 'Default',
'hidden': 'Hidden',
// Show "Parent Folder" option setting
'show_parent_folder_item': 'Show "Parent Folder" item',
@ -443,6 +453,7 @@ export const TRANSLATIONS: Translations = {
'files': '个文件',
'add': '添加',
'root': '根目录',
'more_options': '更多选项',
// 视图标题
'grid_view_title': '网格视图',
@ -530,7 +541,11 @@ export const TRANSLATIONS: Translations = {
'task_filter': '任务分类',
'uncompleted': '未完成',
'completed': '已完成',
'foldernote_display_settings': '文件夹笔记显示设置',
'foldernote_display_settings_desc': '设置文件夹笔记的显示方式',
'all': '全部',
'default': '默认',
'hidden': '隐藏',
// 显示"返回上级文件夹"选项设置
'show_parent_folder_item': '显示「返回上级文件夹」',
@ -643,6 +658,7 @@ export const TRANSLATIONS: Translations = {
'files': 'ファイル',
'add': '追加',
'root': 'ルート',
'more_options': 'もっと選択肢',
// ビュータイトル
'grid_view_title': 'グリッドビュー',
@ -730,7 +746,11 @@ export const TRANSLATIONS: Translations = {
'task_filter': 'タスクフィルタ',
'uncompleted': '未完了',
'completed': '完了',
'foldernote_display_settings': 'フォルダノートの表示設定',
'foldernote_display_settings_desc': 'フォルダノートの表示方法を設定します',
'all': 'すべて',
'default': 'デフォルト',
'hidden': '隠す',
// "親フォルダ"オプション設定を表示
'show_parent_folder_item': '「親フォルダ」項目を表示',
@ -843,6 +863,7 @@ export const TRANSLATIONS: Translations = {
'files': 'файлы',
'add': 'Добавить',
'root': 'Корень',
'more_options': 'Больше опций',
// View Titles
'grid_view_title': 'Сеточный вид',
@ -930,7 +951,11 @@ export const TRANSLATIONS: Translations = {
'task_filter': 'Фильтр задач',
'uncompleted': 'Незавершенные',
'completed': 'Завершенные',
'foldernote_display_settings': 'Настройки отображения заметок папок',
'foldernote_display_settings_desc': 'Установить режим отображения заметок папок',
'all': 'Все',
'default': 'По умолчанию',
'hidden': 'Скрытые',
// Show "Parent Folder" option setting
'show_parent_folder_item': 'Показывать элемент "Родительская папка"',
@ -1043,6 +1068,7 @@ export const TRANSLATIONS: Translations = {
'files': 'файли',
'add': 'Додати',
'root': 'Корень',
'more_options': 'Більше опцій',
// View Titles
'grid_view_title': 'Сітковий вигляд',
@ -1130,7 +1156,11 @@ export const TRANSLATIONS: Translations = {
'task_filter': 'Фільтр завдань',
'uncompleted': 'Незавершені',
'completed': 'Завершені',
'foldernote_display_settings': 'Налаштування відображення нотаток папки',
'foldernote_display_settings_desc': 'Встановіть режим відображення нотаток папки',
'all': 'Всі',
'default': 'По умолчанию',
'hidden': 'Сховати',
// Show "Parent Folder" option setting
'show_parent_folder_item': 'Показувати елемент "Батьківська папка"',

View file

@ -16,6 +16,13 @@
background-color: var(--background-modifier-hover);
}
/* ascii tree prefix */
.ge-folder-tree-prefix {
font-family: monospace;
white-space: pre;
color: var(--text-muted);
}
/* Grid 樣式 */
.ge-grid-container {
display: grid;
@ -327,11 +334,10 @@
}
.ge-foldername-content {
grid-column: 1 / -1;
margin-top: -2px;
margin-bottom: -3px;
margin-left: 7px;
justify-content: center;
padding: 8px;
background-color: var(--background-secondary);
border-bottom: 1px solid var(--background-modifier-border);
}
.ge-foldername-content span {
@ -341,6 +347,7 @@
/* 為資料夾名稱、分隔符等元素添加間距 */
.ge-foldername-content > *:nth-child(1) {
margin-left: 11px;
margin-right: 3px;
}
@ -359,6 +366,11 @@
text-decoration: none;
}
.ge-parent-folder-link.ge-dragover {
border: 2px dashed var(--interactive-accent);
transform: scale(1.05);
}
/* 搜尋對話框樣式 */
.ge-search-container {
margin-bottom: 8px;

View file

@ -1,3 +1,3 @@
{
"2.3.0": "1.1.0"
"2.4.0": "1.1.0"
}