mirror of
https://github.com/devon22/obsidian-gridexplorer.git
synced 2026-07-22 05:38:16 +00:00
2.5.0
This commit is contained in:
parent
e00dbf2fae
commit
180c605f2c
14 changed files with 452 additions and 54 deletions
16
README.md
16
README.md
|
|
@ -13,14 +13,18 @@ This is a grid view plugin designed for Obsidian, aimed at providing a more intu
|
|||
- **Folder Mode**: Shows notes in a folder structure, supporting entry into subfolders.
|
||||
- **Bookmark Mode**: Allows quick access to notes in your bookmarks.
|
||||
- **Search Results Mode**: Displays Obsidian's search results.
|
||||
- **Custom Sorting**: Supports various sorting methods, including by name, modification time, and random sorting.
|
||||
- **Backlinks Mode**: Shows notes that link to the current note.
|
||||
- **Outgoing Links Mode**: Shows outgoing links from the current note, including media files.
|
||||
- **All Files Mode**: Lists all files in the vault.
|
||||
- **Recent Files Mode**: Lists the n most recently modified files.
|
||||
- **Random Files Mode**: Randomly lists n files.
|
||||
- **Custom Sorting**: Supports various sorting methods, including by name, modification time, random sorting, and per-folder custom sorting.
|
||||
- **Settings Options**: Allows customization of grid item width and default sorting method.
|
||||
- **Multilingual Support**: Currently supports English, Traditional Chinese, Simplified Chinese, and Japanese.
|
||||
- **Multilingual Support**: Currently supports English, Traditional Chinese, Simplified Chinese, and Japanese.
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the plugin and place it in the Obsidian plugins folder.
|
||||
2. Enable this plugin in Obsidian.
|
||||
Find "GridExplorer" in the Community plugins through the Obsidian app.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
@ -61,9 +65,7 @@ Available colors:
|
|||
- purple
|
||||
- pink
|
||||
|
||||
|
||||
CSS Class: `.ge-grid-item.ge-foldernote`
|
||||
|
||||
CSS Class: `.ge-grid-item.ge-foldernote`
|
||||
|
||||
## Settings
|
||||
|
||||
|
|
|
|||
12
README_ja.md
12
README_ja.md
|
|
@ -13,14 +13,18 @@
|
|||
- **フォルダモード**:フォルダ構造でノートを表示し、サブフォルダへの移動をサポートします。
|
||||
- **ブックマークモード**:ブックマークに登録したノートへ素早くアクセスできます。
|
||||
- **検索結果モード**:Obsidian の検索結果を表示します。
|
||||
- **カスタムソート**:名前、更新日時、ランダムソートなど、様々な並べ替え方法をサポートします。
|
||||
- **バックリンクモード**:現在のノートへのバックリンクを持つノートを表示します。
|
||||
- **アウトゴーイングリンクモード**:現在のノートからの外部リンク(メディアファイル含む)を表示します。
|
||||
- **全ファイルモード**:ボールト内の全ファイルを一覧表示します。
|
||||
- **最近ファイルモード**:最近変更された n 個のファイルを表示します。
|
||||
- **ランダムファイルモード**:ランダムに n 個のファイルを表示します。
|
||||
- **カスタムソート**:名前、更新日時、作成日時、ランダムソートなど、様々な並べ替え方法やフォルダごとのカスタムソートをサポートします。
|
||||
- **設定オプション**:グリッドアイテムの幅やデフォルトの並べ替え方法をカスタマイズできます。
|
||||
- **多言語サポート**:現在、英語、繁体字中国語、簡体字中国語、日本語をサポートしています。
|
||||
|
||||
## インストール
|
||||
|
||||
1. プラグインをダウンロードし、Obsidian のプラグインフォルダに配置します。
|
||||
2. Obsidian でこのプラグインを有効にします。
|
||||
Obsidian アプリのコミュニティプラグインから「GridExplorer」を検索してインストールしてください。
|
||||
|
||||
## 使用方法
|
||||
|
||||
|
|
@ -61,10 +65,8 @@ color: red
|
|||
- purple
|
||||
- pink
|
||||
|
||||
|
||||
CSS Class: `.ge-grid-item.ge-foldernote`
|
||||
|
||||
|
||||
## 設定
|
||||
|
||||
プラグインの設定ページでは、以下のことができます:
|
||||
|
|
|
|||
|
|
@ -11,16 +11,20 @@
|
|||
|
||||
- **網格視圖**:以網格形式顯示您的筆記和資料夾,方便快速瀏覽。
|
||||
- **資料夾模式**:以資料夾結構顯示筆記,支持進入子資料夾。
|
||||
- **書籤模式**:可以快速訪問您書籤中的筆記。
|
||||
- **書籤模式**:訪問書籤中的筆記。
|
||||
- **搜尋結果模式**:顯示 Obsidian 的搜尋結果。
|
||||
- **自定義排序**:支持多種排序方式,包括名稱、修改時間和隨機排序。
|
||||
- **反向連結模式**:顯示當前筆記的反向連結筆記。
|
||||
- **外部連結模式**:顯示當前筆記的外部連結,包含媒體檔案。
|
||||
- **所有檔案模式**:列出整個儲存庫內的所有檔案。
|
||||
- **最近檔案模式**:列出最近修改的n個檔案。
|
||||
- **隨機檔案模式**:隨機列出n個檔案。
|
||||
- **自定義排序**:支援多種排序方式,包括名稱、修改時間和隨機排序,也可自訂個別資料夾的排序方式。
|
||||
- **設定選項**:可以自定義網格項目的寬度和預設排序方式。
|
||||
- **多語言支持**:目前支持英文、繁體中文、簡體中文和日文。
|
||||
|
||||
## 安裝
|
||||
|
||||
1. 下載插件並將其放入 Obsidian 的插件資料夾中。
|
||||
2. 在 Obsidian 中啟用此插件。
|
||||
透過 Obsidian 應用程式在社群外掛程式中尋找「GridExplorer」。
|
||||
|
||||
## 使用方法
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "gridexplorer",
|
||||
"name": "GridExplorer",
|
||||
"version": "2.4.7",
|
||||
"version": "2.5.0",
|
||||
"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": "2.4.7",
|
||||
"version": "2.5.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gridexplorer",
|
||||
"version": "2.4.7",
|
||||
"version": "2.5.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gridexplorer",
|
||||
"version": "2.4.7",
|
||||
"version": "2.5.0",
|
||||
"description": "Browse note files in a grid view.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
85
src/CustomModeModal.ts
Normal file
85
src/CustomModeModal.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import { App, Modal, Setting, Notice } from 'obsidian';
|
||||
import { CustomMode } from './settings';
|
||||
import { t } from './translations';
|
||||
import GridExplorerPlugin from '../main';
|
||||
|
||||
export class CustomModeModal extends Modal {
|
||||
plugin: GridExplorerPlugin;
|
||||
mode: CustomMode | null;
|
||||
onSubmit: (result: CustomMode) => void;
|
||||
|
||||
constructor(app: App, plugin: GridExplorerPlugin, mode: CustomMode | null, onSubmit: (result: CustomMode) => void) {
|
||||
super(app);
|
||||
this.plugin = plugin;
|
||||
this.mode = mode;
|
||||
this.onSubmit = onSubmit;
|
||||
}
|
||||
|
||||
onOpen() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
|
||||
contentEl.createEl('h2', { text: this.mode ? t('edit_custom_mode') : t('add_custom_mode') });
|
||||
|
||||
let icon = this.mode ? this.mode.icon : '🧩';
|
||||
let displayName = this.mode ? this.mode.displayName : '';
|
||||
let dataviewCode = this.mode ? this.mode.dataviewCode : '';
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName(t('custom_mode_icon'))
|
||||
.setDesc(t('custom_mode_icon_desc'))
|
||||
.addText(text => {
|
||||
text.setValue(icon)
|
||||
.onChange(value => {
|
||||
icon = value || '🧩';
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName(t('custom_mode_display_name'))
|
||||
.setDesc(t('custom_mode_display_name_desc'))
|
||||
.addText(text => {
|
||||
text.setValue(displayName)
|
||||
.onChange(value => {
|
||||
displayName = value;
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName(t('custom_mode_dataview_code'))
|
||||
.setDesc(t('custom_mode_dataview_code_desc'))
|
||||
.addTextArea(text => {
|
||||
text.setValue(dataviewCode)
|
||||
.onChange(value => {
|
||||
dataviewCode = value;
|
||||
});
|
||||
text.inputEl.setAttr('rows', 10);
|
||||
text.inputEl.style.width = '100%';
|
||||
});
|
||||
|
||||
new Setting(contentEl)
|
||||
.addButton(button => {
|
||||
button.setButtonText(t('save'))
|
||||
.setCta()
|
||||
.onClick(() => {
|
||||
if (!displayName.trim()) {
|
||||
new Notice(t('display_name_cannot_be_empty'));
|
||||
return;
|
||||
}
|
||||
const internalName = this.mode ? this.mode.internalName : `custom-${Date.now()}`;
|
||||
this.onSubmit({
|
||||
internalName,
|
||||
icon,
|
||||
displayName,
|
||||
dataviewCode
|
||||
});
|
||||
this.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onClose() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
}
|
||||
|
|
@ -127,10 +127,21 @@ export class FileWatcher {
|
|||
// 監聽當前開啟的檔案變更,讀取反向連結
|
||||
this.plugin.registerEvent(
|
||||
this.app.workspace.on('file-open', (file) => {
|
||||
if (file instanceof TFile) {
|
||||
if ((this.gridView.sourceMode === 'backlinks' || this.gridView.sourceMode === 'outgoinglinks')
|
||||
&& this.gridView.searchQuery === '') {
|
||||
if (file instanceof TFile && this.gridView.searchQuery === '') {
|
||||
const sourceMode = this.gridView.sourceMode;
|
||||
|
||||
// 處理反向連結和出向連結
|
||||
if (sourceMode === 'backlinks' || sourceMode === 'outgoinglinks') {
|
||||
this.scheduleRender();
|
||||
return;
|
||||
}
|
||||
|
||||
// 處理自訂模式,僅當腳本包含 dv.current 時才觸發
|
||||
if (sourceMode.startsWith('custom-')) {
|
||||
const mode = this.plugin.settings.customModes.find(m => m.internalName === sourceMode);
|
||||
if (mode && mode.dataviewCode.includes('dv.current')) {
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -54,12 +54,32 @@ export class FolderSelectionModal extends Modal {
|
|||
// 鍵盤事件處理
|
||||
this.searchInput.addEventListener('keydown', this.handleKeyDown.bind(this));
|
||||
|
||||
// 建立自訂模式選項
|
||||
if (this.plugin.settings.customModes.length > 0) {
|
||||
this.plugin.settings.customModes.forEach(mode => {
|
||||
const customOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `${mode.icon} ${mode.displayName}`
|
||||
});
|
||||
|
||||
customOption.addEventListener('click', () => {
|
||||
if (this.activeView) {
|
||||
this.activeView.setSource(mode.internalName, '', true);
|
||||
} else {
|
||||
this.plugin.activateView(mode.internalName);
|
||||
}
|
||||
this.close();
|
||||
});
|
||||
this.folderOptions.push(customOption);
|
||||
});
|
||||
}
|
||||
|
||||
// 建立書籤選項
|
||||
if (this.plugin.settings.showBookmarksMode) {
|
||||
const bookmarksPlugin = (this.app as any).internalPlugins.plugins.bookmarks;
|
||||
if (bookmarksPlugin?.enabled) {
|
||||
const bookmarkOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `📑 ${t('bookmarks_mode')}`
|
||||
});
|
||||
|
||||
|
|
@ -84,7 +104,7 @@ export class FolderSelectionModal extends Modal {
|
|||
if(searchInputEl) {
|
||||
if (searchInputEl.value.trim().length > 0) {
|
||||
const searchOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `🔍 ${t('search_results')}: ${searchInputEl.value}`
|
||||
});
|
||||
|
||||
|
|
@ -108,7 +128,7 @@ export class FolderSelectionModal extends Modal {
|
|||
if (activeFile) {
|
||||
const activeFileName = activeFile ? `: ${activeFile.basename}` : '';
|
||||
const backlinksOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `🔗 ${t('backlinks_mode')}${activeFileName}`
|
||||
});
|
||||
|
||||
|
|
@ -130,7 +150,7 @@ export class FolderSelectionModal extends Modal {
|
|||
if (activeFile) {
|
||||
const activeFileName = activeFile ? `: ${activeFile.basename}` : '';
|
||||
const outgoinglinksOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `🔗 ${t('outgoinglinks_mode')}${activeFileName}`
|
||||
});
|
||||
|
||||
|
|
@ -149,7 +169,7 @@ export class FolderSelectionModal extends Modal {
|
|||
// 建立最近檔案選項
|
||||
if (this.plugin.settings.showRecentFilesMode) {
|
||||
const recentFilesOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `📅 ${t('recent_files_mode')}`
|
||||
});
|
||||
|
||||
|
|
@ -167,7 +187,7 @@ export class FolderSelectionModal extends Modal {
|
|||
// 建立所有筆記選項
|
||||
if (this.plugin.settings.showAllFilesMode) {
|
||||
const allFilesOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `📔 ${t('all_files_mode')}`
|
||||
});
|
||||
|
||||
|
|
@ -185,7 +205,7 @@ export class FolderSelectionModal extends Modal {
|
|||
// 建立隨機筆記選項
|
||||
if (this.plugin.settings.showRandomNoteMode) {
|
||||
const randomNoteOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `🎲 ${t('random_note_mode')}`
|
||||
});
|
||||
|
||||
|
|
@ -203,7 +223,7 @@ export class FolderSelectionModal extends Modal {
|
|||
// 建立任務選項
|
||||
if (this.plugin.settings.showTasksMode) {
|
||||
const tasksOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
text: `☑️ ${t('tasks_mode')}`
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ export class GridView extends ItemView {
|
|||
return 'calendar-days';
|
||||
} else if (this.sourceMode === 'all-files') {
|
||||
return 'book-text';
|
||||
} else if (this.sourceMode.startsWith('custom-')) {
|
||||
return 'puzzle';
|
||||
} else if (this.sourceMode === 'folder') {
|
||||
return 'folder';
|
||||
} else {
|
||||
|
|
@ -102,6 +104,9 @@ export class GridView extends ItemView {
|
|||
return t('recent_files_mode');
|
||||
} else if (this.sourceMode === 'all-files') {
|
||||
return t('all_files_mode');
|
||||
} else if (this.sourceMode.startsWith('custom-')) {
|
||||
const mode = this.plugin.settings.customModes.find(m => m.internalName === this.sourceMode);
|
||||
return mode ? mode.displayName : t('custom_mode');
|
||||
} else if (this.sourceMode === 'folder') {
|
||||
if (this.sourcePath === '/') {
|
||||
return t('root');
|
||||
|
|
@ -385,7 +390,10 @@ export class GridView extends ItemView {
|
|||
setIcon(refreshButton, 'refresh-ccw');
|
||||
|
||||
// 添加排序按鈕
|
||||
if (this.sourceMode !== 'bookmarks' && this.sourceMode !== 'recent-files' && this.sourceMode !== 'random-note') {
|
||||
if (this.sourceMode !== 'bookmarks' &&
|
||||
this.sourceMode !== 'recent-files' &&
|
||||
this.sourceMode !== 'random-note' &&
|
||||
!this.sourceMode.startsWith('custom-')) {
|
||||
const sortButton = headerButtonsDiv.createEl('button', { attr: { 'aria-label': t('sorting') } });
|
||||
sortButton.addEventListener('click', (evt) => {
|
||||
const menu = new Menu();
|
||||
|
|
@ -869,8 +877,18 @@ export class GridView extends ItemView {
|
|||
modeName = t('tasks_mode');
|
||||
break;
|
||||
default:
|
||||
modeIcon = '📁';
|
||||
modeName = t('root');
|
||||
if (this.sourceMode.startsWith('custom-')) {
|
||||
const mode = this.plugin.settings.customModes.find(m => m.internalName === this.sourceMode);
|
||||
modeIcon = mode ? mode.icon : '🧩';
|
||||
modeName = mode ? mode.displayName : t('custom_mode');
|
||||
} else { // folder mode
|
||||
modeIcon = '📁';
|
||||
if (this.sourcePath && this.sourcePath !== '/') {
|
||||
modeName = this.sourcePath.split('/').pop() || this.sourcePath;
|
||||
} else {
|
||||
modeName = t('root');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 顯示模式名稱
|
||||
|
|
@ -1274,6 +1292,11 @@ export class GridView extends ItemView {
|
|||
allFiles.forEach((file, index) => {
|
||||
fileIndexMap.set(file, index);
|
||||
});
|
||||
} else if (this.sourceMode.startsWith('custom-')) {
|
||||
// 使用 Map 來記錄原始順序
|
||||
allFiles.forEach((file, index) => {
|
||||
fileIndexMap.set(file, index);
|
||||
});
|
||||
} else if (this.sourceMode === 'search') {
|
||||
allFiles = allFiles.filter(file =>
|
||||
isDocumentFile(file) || (isMediaFile(file) && this.searchMediaFiles)
|
||||
|
|
@ -1392,10 +1415,18 @@ export class GridView extends ItemView {
|
|||
return indexA - indexB;
|
||||
});
|
||||
} else if (this.sourceMode === 'random-note') {
|
||||
// 臨時的排序類型
|
||||
const sortType = this.sortType;
|
||||
this.sortType = 'random';
|
||||
files = sortFiles(files, this);
|
||||
this.sortType = sortType;
|
||||
} else if (this.sourceMode.startsWith('custom-')) {
|
||||
// 保持原始順序
|
||||
files.sort((a, b) => {
|
||||
const indexA = fileIndexMap.get(a) ?? Number.MAX_SAFE_INTEGER;
|
||||
const indexB = fileIndexMap.get(b) ?? Number.MAX_SAFE_INTEGER;
|
||||
return indexA - indexB;
|
||||
});
|
||||
} else {
|
||||
files = sortFiles(files, this);
|
||||
}
|
||||
|
|
@ -1767,7 +1798,8 @@ export class GridView extends ItemView {
|
|||
const shouldShowDateDividers = dateDividerMode !== 'none' &&
|
||||
(sortType.startsWith('mtime-') || sortType.startsWith('ctime-')) &&
|
||||
this.sourceMode !== 'random-note' &&
|
||||
this.sourceMode !== 'bookmarks';
|
||||
this.sourceMode !== 'bookmarks' &&
|
||||
!this.sourceMode.startsWith('custom-');
|
||||
|
||||
let lastDateString = '';
|
||||
let pinDividerAdded = false;
|
||||
|
|
|
|||
|
|
@ -394,6 +394,50 @@ export async function getFiles(gridView: GridView, includeMediaFiles: boolean):
|
|||
}
|
||||
}
|
||||
return sortFiles(Array.from(filesWithTasks), gridView);
|
||||
} else if (sourceMode.startsWith('custom-')) {
|
||||
const dvApi = app.plugins.plugins.dataview?.api;
|
||||
if (!dvApi) {
|
||||
new Notice('Dataview plugin is not enabled.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const mode = settings.customModes.find(m => m.internalName === sourceMode);
|
||||
if (!mode) {
|
||||
new Notice(`Custom mode ${sourceMode} not found.`);
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const activeFile = app.workspace.getActiveFile();
|
||||
if (activeFile) {
|
||||
// 暫時添加 .current 到 dvApi 物件內
|
||||
dvApi.current = () => dvApi.page(activeFile.path);
|
||||
}
|
||||
|
||||
const func = new Function('app', 'dv', mode.dataviewCode);
|
||||
const dvPagesResult = func(app, dvApi);
|
||||
const dvPages = Array.isArray(dvPagesResult) ? dvPagesResult : Array.from(dvPagesResult || []);
|
||||
|
||||
if (!dvPages || dvPages.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const files = new Set<TFile>();
|
||||
|
||||
for (const page of dvPages) {
|
||||
if (page.file?.path) {
|
||||
const file = app.vault.getAbstractFileByPath(page.file.path);
|
||||
if (file instanceof TFile) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(files) as TFile[];
|
||||
} catch (error) {
|
||||
console.error('Grid Explorer: Error executing Dataview query.', error);
|
||||
// new Notice('Error executing Dataview query. See console for details.');
|
||||
return [];
|
||||
}
|
||||
} else if (sourceMode === 'all-files') {
|
||||
// 所有筆記模式
|
||||
const allVaultFiles = app.vault.getFiles().filter(file => {
|
||||
|
|
|
|||
138
src/settings.ts
138
src/settings.ts
|
|
@ -1,6 +1,14 @@
|
|||
import { App, PluginSettingTab, Setting, Notice } from 'obsidian';
|
||||
import { App, PluginSettingTab, Setting, Notice, ButtonComponent } from 'obsidian';
|
||||
import { t } from './translations';
|
||||
import GridExplorerPlugin from '../main';
|
||||
import { CustomModeModal } from './CustomModeModal';
|
||||
|
||||
export interface CustomMode {
|
||||
internalName: string;
|
||||
icon: string;
|
||||
displayName: string;
|
||||
dataviewCode: string;
|
||||
}
|
||||
|
||||
export interface GallerySettings {
|
||||
ignoredFolders: string[]; // 要忽略的資料夾路徑
|
||||
|
|
@ -39,6 +47,7 @@ export interface GallerySettings {
|
|||
showCodeBlocksInSummary: boolean; // 是否在摘要中顯示程式碼區塊
|
||||
folderNoteDisplaySettings: string; // 資料夾筆記設定
|
||||
interceptAllTagClicks: boolean; // 攔截所有tag點擊事件
|
||||
customModes: CustomMode[]; // 自訂模式
|
||||
}
|
||||
|
||||
// 預設設定
|
||||
|
|
@ -79,6 +88,14 @@ export const DEFAULT_SETTINGS: GallerySettings = {
|
|||
showCodeBlocksInSummary: false, // 預設不在摘要中顯示程式碼區塊
|
||||
folderNoteDisplaySettings: 'default', // 預設不處理資料夾筆記
|
||||
interceptAllTagClicks: false, // 預設不攔截所有tag點擊事件
|
||||
customModes: [
|
||||
{
|
||||
internalName: 'custom-1750837329297',
|
||||
icon: '🧩',
|
||||
displayName: 'My Books (Sample)',
|
||||
dataviewCode: 'return dv.pages("#Book");',
|
||||
}
|
||||
], // 自訂模式
|
||||
};
|
||||
|
||||
// 設定頁面類別
|
||||
|
|
@ -94,18 +111,100 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
||||
// 回復預設值按鈕
|
||||
// 顯示模式設定區域
|
||||
// 自訂模式設定
|
||||
containerEl.createEl('h3', { text: t('custom_mode_settings') });
|
||||
|
||||
// 建立自訂模式的容器,以便實現拖曳排序
|
||||
const customModesContainer = containerEl.createDiv();
|
||||
this.plugin.settings.customModes.forEach((mode, index) => {
|
||||
const setting = new Setting(customModesContainer)
|
||||
.setName(`${mode.icon} ${mode.displayName}`);
|
||||
|
||||
// 讓設定項目可以被拖曳
|
||||
setting.settingEl.setAttr('draggable', 'true');
|
||||
|
||||
// 拖曳開始時,儲存被拖曳項目的索引
|
||||
setting.settingEl.addEventListener('dragstart', (event: DragEvent) => {
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.setData('text/plain', index.toString());
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
});
|
||||
|
||||
// 當拖曳到其他項目上時,允許放下
|
||||
setting.settingEl.addEventListener('dragover', (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
}
|
||||
});
|
||||
|
||||
// 放下項目時,更新順序
|
||||
setting.settingEl.addEventListener('drop', async (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
if (!event.dataTransfer) return;
|
||||
|
||||
const fromIndexStr = event.dataTransfer.getData('text/plain');
|
||||
if (!fromIndexStr) return;
|
||||
|
||||
const fromIndex = parseInt(fromIndexStr);
|
||||
const toIndex = index;
|
||||
|
||||
if (fromIndex === toIndex) return;
|
||||
|
||||
// 重新排序陣列
|
||||
const modes = this.plugin.settings.customModes;
|
||||
const movedMode = modes.splice(fromIndex, 1)[0];
|
||||
modes.splice(toIndex, 0, movedMode);
|
||||
|
||||
// 儲存設定並重新整理顯示
|
||||
await this.plugin.saveSettings();
|
||||
this.display();
|
||||
});
|
||||
|
||||
// 編輯按鈕
|
||||
setting.addButton((button: ButtonComponent) => {
|
||||
button.setButtonText(t('edit'))
|
||||
.onClick(() => {
|
||||
// 找到正確的索引,以防萬一順序已變
|
||||
const modeIndex = this.plugin.settings.customModes.findIndex(m => m.internalName === mode.internalName);
|
||||
if (modeIndex === -1) return;
|
||||
new CustomModeModal(this.app, this.plugin, this.plugin.settings.customModes[modeIndex], (result) => {
|
||||
this.plugin.settings.customModes[modeIndex] = result;
|
||||
this.plugin.saveSettings();
|
||||
this.display();
|
||||
}).open();
|
||||
});
|
||||
});
|
||||
|
||||
// 移除按鈕
|
||||
setting.addButton((button: ButtonComponent) => {
|
||||
button.setButtonText(t('remove'))
|
||||
.setWarning()
|
||||
.onClick(() => {
|
||||
// 找到正確的索引,以防萬一順序已變
|
||||
const modeIndex = this.plugin.settings.customModes.findIndex(m => m.internalName === mode.internalName);
|
||||
if (modeIndex === -1) return;
|
||||
this.plugin.settings.customModes.splice(modeIndex, 1);
|
||||
this.plugin.saveSettings();
|
||||
this.display();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(t('reset_to_default'))
|
||||
.setDesc(t('reset_to_default_desc'))
|
||||
.addButton(button => button
|
||||
.setButtonText(t('reset'))
|
||||
.onClick(async () => {
|
||||
this.plugin.settings = { ...DEFAULT_SETTINGS };
|
||||
await this.plugin.saveSettings();
|
||||
this.display();
|
||||
new Notice(t('settings_reset_notice'));
|
||||
}));
|
||||
.addButton(button => {
|
||||
button.setButtonText(t('add_custom_mode'))
|
||||
.setCta()
|
||||
.onClick(() => {
|
||||
new CustomModeModal(this.app, this.plugin, null, (result) => {
|
||||
this.plugin.settings.customModes.push(result);
|
||||
this.plugin.saveSettings();
|
||||
this.display();
|
||||
}).open();
|
||||
});
|
||||
});
|
||||
|
||||
// 顯示模式設定區域
|
||||
containerEl.createEl('h3', { text: t('display_mode_settings') });
|
||||
|
|
@ -693,6 +792,21 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
|
||||
containerEl.appendChild(ignoredFolderPatternsContainer);
|
||||
|
||||
containerEl.createEl('h3', { text: t('reset_to_default') });
|
||||
|
||||
// 回復預設值按鈕
|
||||
new Setting(containerEl)
|
||||
.setName(t('reset_to_default'))
|
||||
.setDesc(t('reset_to_default_desc'))
|
||||
.addButton(button => button
|
||||
.setButtonText(t('reset'))
|
||||
.setWarning()
|
||||
.onClick(async () => {
|
||||
this.plugin.settings = { ...DEFAULT_SETTINGS };
|
||||
await this.plugin.saveSettings();
|
||||
this.display();
|
||||
new Notice(t('settings_reset_notice'));
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_tag_to_search': '加入搜尋',
|
||||
'remove_tag_from_search': '從搜尋中移除',
|
||||
'global_search': '全域搜尋',
|
||||
'remove': '移除',
|
||||
'edit': '編輯',
|
||||
'delete': '刪除',
|
||||
'save': '儲存',
|
||||
|
||||
// 視圖標題
|
||||
'grid_view_title': '網格視圖',
|
||||
|
|
@ -88,7 +92,6 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_ignored_folder_pattern': '新增忽略資料夾模式',
|
||||
'ignored_folder_pattern_placeholder': '輸入資料夾名稱或正則表達式',
|
||||
'no_ignored_folder_patterns': '沒有忽略的資料夾模式。',
|
||||
'remove': '移除',
|
||||
'default_sort_type': '預設排序模式',
|
||||
'default_sort_type_desc': '設定開啟網格視圖時的預設排序模式',
|
||||
'note_title_field': '筆記標題欄位名稱',
|
||||
|
|
@ -122,6 +125,17 @@ export const TRANSLATIONS: Translations = {
|
|||
'settings_reset_notice': '設定值已重置為預設值',
|
||||
'ignored_folders_settings': '忽略資料夾設定',
|
||||
'display_mode_settings': '顯示模式設定',
|
||||
'custom_mode_settings': '自訂模式設定',
|
||||
'add_custom_mode': '新增自訂模式',
|
||||
'edit_custom_mode': '編輯自訂模式',
|
||||
'custom_mode_icon': '圖示',
|
||||
'custom_mode_icon_desc': '在模式選單中顯示的圖示',
|
||||
'custom_mode_display_name': '顯示名稱',
|
||||
'custom_mode_display_name_desc': '在模式選單中顯示的名稱',
|
||||
'custom_mode_dataview_code': 'Dataviewjs 代碼',
|
||||
'custom_mode_dataview_code_desc': '輸入 Dataviewjs 代碼以取得檔案列表',
|
||||
'display_name_cannot_be_empty': '顯示名稱不能為空',
|
||||
'custom_mode': '自訂模式',
|
||||
'show_bookmarks_mode': '顯示書籤模式',
|
||||
'show_search_mode': '顯示搜尋結果模式',
|
||||
'show_backlinks_mode': '顯示反向連結模式',
|
||||
|
|
@ -261,6 +275,10 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_tag_to_search': 'Add to search',
|
||||
'remove_tag_from_search': 'Remove from search',
|
||||
'global_search': 'Global search',
|
||||
'remove': 'Remove',
|
||||
'edit': 'Edit',
|
||||
'delete': 'Delete',
|
||||
'save': 'Save',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Grid view',
|
||||
|
|
@ -301,7 +319,6 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_ignored_folder_pattern': 'Add folder pattern',
|
||||
'ignored_folder_pattern_placeholder': 'Enter folder name or regex pattern',
|
||||
'no_ignored_folder_patterns': 'No ignored folder patterns.',
|
||||
'remove': 'Remove',
|
||||
'default_sort_type': 'Default sort type',
|
||||
'default_sort_type_desc': 'Set the default sorting method when opening Grid View',
|
||||
'note_title_field': 'Note title field name',
|
||||
|
|
@ -335,6 +352,17 @@ export const TRANSLATIONS: Translations = {
|
|||
'settings_reset_notice': 'Settings have been reset to default values',
|
||||
'ignored_folders_settings': 'Ignore folders settings',
|
||||
'display_mode_settings': 'Display mode settings',
|
||||
'custom_mode_settings': 'Custom Mode Settings',
|
||||
'add_custom_mode': 'Add Custom Mode',
|
||||
'edit_custom_mode': 'Edit Custom Mode',
|
||||
'custom_mode_icon': 'Icon',
|
||||
'custom_mode_icon_desc': 'The icon displayed in the mode menu',
|
||||
'custom_mode_display_name': 'Display Name',
|
||||
'custom_mode_display_name_desc': 'The name displayed in the mode menu',
|
||||
'custom_mode_dataview_code': 'Dataview Query',
|
||||
'custom_mode_dataview_code_desc': 'Enter a Dataview query to get the list of files',
|
||||
'display_name_cannot_be_empty': 'Display name cannot be empty',
|
||||
'custom_mode': 'Custom Mode',
|
||||
'show_bookmarks_mode': 'Show bookmarks mode',
|
||||
'show_search_mode': 'Show search results mode',
|
||||
'show_backlinks_mode': 'Show backlinks mode',
|
||||
|
|
@ -474,6 +502,10 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_tag_to_search': '加入搜索',
|
||||
'remove_tag_from_search': '从搜索中移除',
|
||||
'global_search': '全域搜索',
|
||||
'remove': '移除',
|
||||
'edit': '编辑',
|
||||
'delete': '删除',
|
||||
'save': '保存',
|
||||
|
||||
// 视图标题
|
||||
'grid_view_title': '网格视图',
|
||||
|
|
@ -514,7 +546,6 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_ignored_folder_pattern': '添加忽略文件夹模式',
|
||||
'ignored_folder_pattern_placeholder': '输入文件夹名称或正则表达式',
|
||||
'no_ignored_folder_patterns': '没有忽略的文件夹模式。',
|
||||
'remove': '移除',
|
||||
'default_sort_type': '默认排序模式',
|
||||
'default_sort_type_desc': '设置打开网格视图时的默认排序模式',
|
||||
'note_title_field': '笔记标题字段名称',
|
||||
|
|
@ -548,6 +579,17 @@ export const TRANSLATIONS: Translations = {
|
|||
'settings_reset_notice': '设置值已重置为默认值',
|
||||
'ignored_folders_settings': '忽略文件夹设置',
|
||||
'display_mode_settings': '显示模式设置',
|
||||
'custom_mode_settings': '自定义模式设置',
|
||||
'add_custom_mode': '添加自定义模式',
|
||||
'edit_custom_mode': '编辑自定义模式',
|
||||
'custom_mode_icon': '图标',
|
||||
'custom_mode_icon_desc': '在模式菜单中显示的图标',
|
||||
'custom_mode_display_name': '显示名称',
|
||||
'custom_mode_display_name_desc': '在模式菜单中显示的名称',
|
||||
'custom_mode_dataview_code': 'Dataviewjs 代码',
|
||||
'custom_mode_dataview_code_desc': '输入 Dataviewjs 代码以获取文件列表',
|
||||
'display_name_cannot_be_empty': '显示名称不能为空',
|
||||
'custom_mode': '自定义模式',
|
||||
'show_bookmarks_mode': '显示书签模式',
|
||||
'show_search_mode': '显示搜索结果模式',
|
||||
'show_backlinks_mode': '显示反向链接模式',
|
||||
|
|
@ -687,6 +729,10 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_tag_to_search': '検索に追加',
|
||||
'remove_tag_from_search': '検索から削除',
|
||||
'global_search': 'グローバル検索',
|
||||
'remove': '削除',
|
||||
'edit': '編集',
|
||||
'delete': '削除',
|
||||
'save': '保存',
|
||||
|
||||
// ビュータイトル
|
||||
'grid_view_title': 'グリッドビュー',
|
||||
|
|
@ -727,7 +773,6 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_ignored_folder_pattern': 'フォルダパターンを追加',
|
||||
'ignored_folder_pattern_placeholder': 'フォルダ名または正規表現パターンを入力',
|
||||
'no_ignored_folder_patterns': '無視するフォルダパターンはありません。',
|
||||
'remove': '削除',
|
||||
'default_sort_type': 'デフォルトの並び替え',
|
||||
'default_sort_type_desc': 'グリッドビューを開いたときのデフォルトの並び替え方法を設定',
|
||||
'note_title_field': 'ノートタイトルフィールド名',
|
||||
|
|
@ -761,6 +806,17 @@ export const TRANSLATIONS: Translations = {
|
|||
'settings_reset_notice': '設定値がデフォルト値にリセットされました',
|
||||
'ignored_folders_settings': '無視するフォルダ設定',
|
||||
'display_mode_settings': '表示モード設定',
|
||||
'custom_mode_settings': 'カスタムモード設定',
|
||||
'add_custom_mode': 'カスタムモードを追加',
|
||||
'edit_custom_mode': 'カスタムモードを編集',
|
||||
'custom_mode_icon': 'アイコン',
|
||||
'custom_mode_icon_desc': 'モードメニューで表示するアイコン',
|
||||
'custom_mode_display_name': '表示名',
|
||||
'custom_mode_display_name_desc': 'モードメニューで表示する名前',
|
||||
'custom_mode_dataview_code': 'Dataviewjs コード',
|
||||
'custom_mode_dataview_code_desc': 'ファイルリストを取得する Dataviewjs コードを入力',
|
||||
'display_name_cannot_be_empty': '表示名は空にできません',
|
||||
'custom_mode': 'カスタムモード',
|
||||
'show_bookmarks_mode': 'ブックマークモードを表示',
|
||||
'show_search_mode': '検索結果モードを表示',
|
||||
'show_backlinks_mode': 'バックリンクモードを表示',
|
||||
|
|
@ -900,6 +956,10 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_tag_to_search': 'Добавить в поиск',
|
||||
'remove_tag_from_search': 'Удалить из поиска',
|
||||
'global_search': 'Глобальный поиск',
|
||||
'remove': 'Удалить',
|
||||
'edit': 'Редактировать',
|
||||
'delete': 'Удалить',
|
||||
'save': 'Сохранить',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Сеточный вид',
|
||||
|
|
@ -940,7 +1000,6 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_ignored_folder_pattern': 'Добавить шаблон папки',
|
||||
'ignored_folder_pattern_placeholder': 'Введите имя папки или шаблон регулярного выражения',
|
||||
'no_ignored_folder_patterns': 'Нет шаблонов игнорируемых папок.',
|
||||
'remove': 'Удалить',
|
||||
'default_sort_type': 'Тип сортировки по умолчанию',
|
||||
'default_sort_type_desc': 'Установите метод сортировки по умолчанию при открытии сеточного вида',
|
||||
'note_title_field': 'Имя поля "Название заметки"',
|
||||
|
|
@ -974,6 +1033,17 @@ export const TRANSLATIONS: Translations = {
|
|||
'settings_reset_notice': 'Настройки сброшены на значения по умолчанию',
|
||||
'ignored_folders_settings': 'Настройки игнорируемых папок',
|
||||
'display_mode_settings': 'Настройки режима отображения',
|
||||
'custom_mode_settings': 'Настройки режима отображения',
|
||||
'add_custom_mode': 'Добавить режим отображения',
|
||||
'edit_custom_mode': 'Редактировать режим отображения',
|
||||
'custom_mode_icon': 'Иконка',
|
||||
'custom_mode_icon_desc': 'Иконка, отображаемая в меню режимов',
|
||||
'custom_mode_display_name': 'Отображаемое имя',
|
||||
'custom_mode_display_name_desc': 'Отображаемое имя в меню режимов',
|
||||
'custom_mode_dataview_code': 'Код Dataview',
|
||||
'custom_mode_dataview_code_desc': 'Введите код Dataview для получения списка файлов',
|
||||
'display_name_cannot_be_empty': 'Отображаемое имя не может быть пустым',
|
||||
'custom_mode': 'Режим отображения',
|
||||
'show_bookmarks_mode': 'Показывать режим закладок',
|
||||
'show_search_mode': 'Показывать режим результатов поиска',
|
||||
'show_backlinks_mode': 'Показывать режим обратных ссылок',
|
||||
|
|
@ -1113,6 +1183,10 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_tag_to_search': 'Додати до пошуку',
|
||||
'remove_tag_from_search': 'Видалити з пошуку',
|
||||
'global_search': 'Глобальний пошук',
|
||||
'remove': 'Видалити',
|
||||
'edit': 'Редагувати',
|
||||
'delete': 'Видалити',
|
||||
'save': 'Зберегти',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Сітковий вигляд',
|
||||
|
|
@ -1153,7 +1227,6 @@ export const TRANSLATIONS: Translations = {
|
|||
'add_ignored_folder_pattern': 'Додати шаблон папки',
|
||||
'ignored_folder_pattern_placeholder': 'Введіть назву папки або шаблон регулярного виразу',
|
||||
'no_ignored_folder_patterns': 'Немає шаблонів ігнорованих папок.',
|
||||
'remove': 'Видалити',
|
||||
'default_sort_type': 'Тип сортування за замовчуванням',
|
||||
'default_sort_type_desc': 'Встановіть метод сортування за замовчуванням при відкритті сіткового вигляду',
|
||||
'note_title_field': 'Назва поля "Назва нотатки"',
|
||||
|
|
@ -1187,6 +1260,17 @@ export const TRANSLATIONS: Translations = {
|
|||
'settings_reset_notice': 'Налаштування скинуто до стандартних значень',
|
||||
'ignored_folders_settings': 'Налаштування ігнорованих папок',
|
||||
'display_mode_settings': 'Налаштування режиму відображення',
|
||||
'custom_mode_settings': 'Налаштування режиму відображення',
|
||||
'add_custom_mode': 'Додати режим відображення',
|
||||
'edit_custom_mode': 'Редагувати режим відображення',
|
||||
'custom_mode_icon': 'Іконка',
|
||||
'custom_mode_icon_desc': 'Іконка, відображається в меню режимів',
|
||||
'custom_mode_display_name': 'Відображається ім`я',
|
||||
'custom_mode_display_name_desc': 'Відображається ім`я в меню режимів',
|
||||
'custom_mode_dataview_code': 'Код Dataview',
|
||||
'custom_mode_dataview_code_desc': 'Введіть код Dataview для отримання списку файлів',
|
||||
'display_name_cannot_be_empty': 'Відображається ім`я не може бути порожнім',
|
||||
'custom_mode': 'Режим відображення',
|
||||
'show_bookmarks_mode': 'Показувати режим закладок',
|
||||
'show_search_mode': 'Показувати режим результатів пошуку',
|
||||
'show_backlinks_mode': 'Показувати режим зворотних посилань',
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"2.4.7": "1.1.0"
|
||||
"2.5.0": "1.1.0"
|
||||
}
|
||||
Loading…
Reference in a new issue