mirror of
https://github.com/devon22/obsidian-gridexplorer.git
synced 2026-07-22 05:38:16 +00:00
2.4.6
This commit is contained in:
parent
7b0f8c19b9
commit
9409cafcc5
9 changed files with 158 additions and 44 deletions
79
main.ts
79
main.ts
|
|
@ -99,9 +99,9 @@ export default class GridExplorerPlugin extends Plugin {
|
|||
|
||||
// 註冊狀態列項目
|
||||
this.statusBarItem = this.addStatusBarItem();
|
||||
this.statusBarItem.onClickEvent(() => {
|
||||
this.activateView();
|
||||
});
|
||||
// this.statusBarItem.onClickEvent(() => {
|
||||
// this.activateView();
|
||||
// });
|
||||
|
||||
// 註冊資料夾的右鍵選單
|
||||
this.registerEvent(
|
||||
|
|
@ -197,13 +197,10 @@ export default class GridExplorerPlugin extends Plugin {
|
|||
.onClick(async () => {
|
||||
const selectedText = editor.getSelection();
|
||||
// 取得或啟用 GridView
|
||||
const view = await this.activateView('folder','/');
|
||||
const view = await this.activateView('','');
|
||||
if (view instanceof GridView) {
|
||||
// 設定搜尋模式和關鍵字
|
||||
view.searchQuery = selectedText;
|
||||
// 設定搜尋範圍 (預設搜尋所有檔案,不含媒體)
|
||||
view.searchAllFiles = true;
|
||||
view.searchMediaFiles = false;
|
||||
// 重新渲染視圖
|
||||
view.render(true); // resetScroll = true
|
||||
}
|
||||
|
|
@ -227,13 +224,10 @@ export default class GridExplorerPlugin extends Plugin {
|
|||
.setSection?.("view")
|
||||
.onClick(async () => {
|
||||
// 取得或啟用 GridView
|
||||
const view = await this.activateView('folder','/');
|
||||
const view = await this.activateView('','');
|
||||
if (view instanceof GridView) {
|
||||
// 設定搜尋模式和關鍵字
|
||||
view.searchQuery = `#${tagName}`;
|
||||
// 設定搜尋範圍 (預設搜尋所有檔案,不含媒體)
|
||||
view.searchAllFiles = true;
|
||||
view.searchMediaFiles = false;
|
||||
// 重新渲染視圖
|
||||
view.render(true); // resetScroll = true
|
||||
}
|
||||
|
|
@ -241,6 +235,67 @@ export default class GridExplorerPlugin extends Plugin {
|
|||
});
|
||||
})
|
||||
);
|
||||
|
||||
// 攔截所有tag點擊事件
|
||||
this.registerDomEvent(document, 'click', async (evt: MouseEvent) => {
|
||||
// 如果未啟用攔截所有tag點擊事件,則跳過
|
||||
if (!this.settings.interceptAllTagClicks) return;
|
||||
// 只處理左鍵
|
||||
if (evt.button !== 0) return;
|
||||
|
||||
// 從觸發點往上找,看是否碰到 tag 連結
|
||||
const el = (evt.target as HTMLElement).closest(
|
||||
'a.tag, /* 預覽模式中的 #tag */\n' +
|
||||
'.tag-pane-tag, /* 標籤面板中的 tag */\n' +
|
||||
'span.cm-hashtag, /* 編輯器中的 tag */\n' +
|
||||
'.metadata-property[data-property-key="tags"] .multi-select-pill /* 屬性面板中的 tag */'
|
||||
) as HTMLElement | null;
|
||||
if (!el) return; // 不是 tag 點擊就跳過
|
||||
|
||||
// 取出 tag 名稱(去掉前導 #)
|
||||
let tagName = '';
|
||||
if (el.matches('span.cm-hashtag')) {
|
||||
// 編輯器模式:可能被拆成多個 span,需組合
|
||||
const collect = [] as string[];
|
||||
let curr: HTMLElement | null = el;
|
||||
// 向左收集
|
||||
while (curr && curr.matches('span.cm-hashtag') && !curr.classList.contains('cm-formatting')) {
|
||||
collect.unshift(curr.textContent ?? '');
|
||||
curr = curr.previousElementSibling as HTMLElement | null;
|
||||
if (curr && (!curr.matches('span.cm-hashtag') || curr.classList.contains('cm-formatting'))) break;
|
||||
}
|
||||
// 向右收集
|
||||
curr = el.nextElementSibling as HTMLElement | null;
|
||||
while (curr && curr.matches('span.cm-hashtag') && !curr.classList.contains('cm-formatting')) {
|
||||
collect.push(curr.textContent ?? '');
|
||||
curr = curr.nextElementSibling as HTMLElement | null;
|
||||
}
|
||||
tagName = collect.join('').trim();
|
||||
} else if (el.classList.contains('tag-pane-tag')) {
|
||||
// Tag Pane 中的元素,需避開計數器
|
||||
const inner = el.querySelector('.tag-pane-tag-text, .tree-item-inner-text') as HTMLElement | null;
|
||||
tagName = inner?.textContent?.trim() ?? '';
|
||||
} else if (el.matches('.metadata-property[data-property-key="tags"] .multi-select-pill')) {
|
||||
// Frontmatter/Properties view
|
||||
tagName = el.textContent?.trim() ?? '';
|
||||
} else {
|
||||
// 預覽模式中的連結 a.tag
|
||||
tagName = (el.getAttribute('data-tag') ?? el.textContent ?? '').trim();
|
||||
}
|
||||
tagName = tagName.replace(/^#/, '');
|
||||
if (!tagName) return;
|
||||
|
||||
// 阻止 Obsidian 自己的處理(開搜尋窗)
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
// 叫出 GridView,並把搜尋字串設成這個 tag
|
||||
const view = await this.activateView('', '');
|
||||
if (view instanceof GridView) {
|
||||
view.searchQuery = `#${tagName}`;
|
||||
view.render(true); // resetScroll
|
||||
}
|
||||
}, true); // 用 capture,可在其他 listener 前先吃到
|
||||
}
|
||||
|
||||
async openNoteInRecentFiles(file: TFile) {
|
||||
|
|
@ -300,7 +355,7 @@ export default class GridExplorerPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async activateView(mode = 'bookmarks', path = '') {
|
||||
async activateView(mode = 'folder', path = '') {
|
||||
const { workspace } = this.app;
|
||||
|
||||
let leaf = null;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "gridexplorer",
|
||||
"name": "GridExplorer",
|
||||
"version": "2.4.5",
|
||||
"version": "2.4.6",
|
||||
"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.5",
|
||||
"version": "2.4.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gridexplorer",
|
||||
"version": "2.4.5",
|
||||
"version": "2.4.6",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gridexplorer",
|
||||
"version": "2.4.5",
|
||||
"version": "2.4.6",
|
||||
"description": "Browse note files in a grid view.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ export class FileWatcher {
|
|||
}, 200);
|
||||
}
|
||||
|
||||
// 清理日期分隔線
|
||||
private cleanupDateDividers(container: HTMLElement | null): void {
|
||||
if (!container) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -150,8 +150,11 @@ export class GridView extends ItemView {
|
|||
}
|
||||
}
|
||||
|
||||
this.sourceMode = mode;
|
||||
this.sourcePath = path;
|
||||
if(mode !== '') this.sourceMode = mode;
|
||||
if(path !== '') this.sourcePath = path;
|
||||
if(this.sourceMode === '') this.sourceMode = 'folder';
|
||||
if(this.sourcePath === '') this.sourcePath = '/';
|
||||
|
||||
this.render(resetScroll);
|
||||
// 通知 Obsidian 保存視圖狀態
|
||||
this.app.workspace.requestSaveLayout();
|
||||
|
|
@ -880,6 +883,13 @@ export class GridView extends ItemView {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (this.searchQuery !== '' && this.searchAllFiles) {
|
||||
// 顯示全域搜尋名稱
|
||||
const folderNameContainer = this.containerEl.createDiv('ge-foldername-content');
|
||||
folderNameContainer.createEl('span', {
|
||||
text: `🔍 ${t('global_search')}`,
|
||||
cls: 'ge-mode-title'
|
||||
});
|
||||
}
|
||||
|
||||
// 創建內容區域
|
||||
|
|
@ -1657,21 +1667,32 @@ export class GridView extends ItemView {
|
|||
tagEl.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const tagText = tag.startsWith('#') ? tag : `#${tag}`;
|
||||
const menu = new Menu();
|
||||
menu.addItem(item => item
|
||||
.setTitle(t('add_to_search'))
|
||||
.onClick(() => {
|
||||
const tagText = tag.startsWith('#') ? tag : `#${tag}`;
|
||||
if (this.searchQuery.includes(tagText)) {
|
||||
return;
|
||||
}
|
||||
this.searchQuery += ` ${tagText}`;
|
||||
this.searchAllFiles = true;
|
||||
this.searchMediaFiles = false;
|
||||
this.render(true);
|
||||
return false;
|
||||
})
|
||||
);
|
||||
//添加加入搜尋選項
|
||||
if (!this.searchQuery.includes(tagText)) {
|
||||
menu.addItem(item => item
|
||||
.setTitle(t('add_tag_to_search'))
|
||||
.setIcon('circle-plus')
|
||||
.onClick(() => {
|
||||
this.searchQuery += ` ${tagText}`;
|
||||
this.render(true);
|
||||
return false;
|
||||
})
|
||||
);
|
||||
}
|
||||
// 添加刪除標籤選項
|
||||
if (this.searchQuery.includes(tagText)) {
|
||||
menu.addItem(item => item
|
||||
.setTitle(t('remove_tag_from_search'))
|
||||
.setIcon('circle-minus')
|
||||
.onClick(() => {
|
||||
this.searchQuery = this.searchQuery.replace(tagText, '');
|
||||
this.render(true);
|
||||
return false;
|
||||
})
|
||||
);
|
||||
}
|
||||
menu.showAtPosition({
|
||||
x: e.clientX,
|
||||
y: e.clientY
|
||||
|
|
@ -1687,8 +1708,6 @@ export class GridView extends ItemView {
|
|||
return;
|
||||
}
|
||||
this.searchQuery = tagText;
|
||||
this.searchAllFiles = true;
|
||||
this.searchMediaFiles = false;
|
||||
this.render(true);
|
||||
return false;
|
||||
});
|
||||
|
|
@ -2104,12 +2123,12 @@ export class GridView extends ItemView {
|
|||
for (const f of selectedFiles) {
|
||||
await this.app.fileManager.trashFile(f);
|
||||
}
|
||||
// 清除選中狀態
|
||||
this.clearSelection();
|
||||
} else {
|
||||
// 刪除單個檔案
|
||||
await this.app.fileManager.trashFile(file);
|
||||
}
|
||||
// 清除選中狀態
|
||||
this.clearSelection();
|
||||
});
|
||||
});
|
||||
menu.showAtMouseEvent(event);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export interface GallerySettings {
|
|||
dateDividerMode: string; // 日期分隔器模式:none, year, month, day
|
||||
showCodeBlocksInSummary: boolean; // 是否在摘要中顯示程式碼區塊
|
||||
folderNoteDisplaySettings: string; // 資料夾筆記設定
|
||||
interceptAllTagClicks: boolean; // 攔截所有tag點擊事件
|
||||
}
|
||||
|
||||
// 預設設定
|
||||
|
|
@ -61,7 +62,7 @@ export const DEFAULT_SETTINGS: GallerySettings = {
|
|||
showBacklinksMode: true, // 預設顯示反向連結模式
|
||||
showOutgoinglinksMode: false, // 預設不顯示外部連結模式
|
||||
showAllFilesMode: false, // 預設不顯示所有檔案模式
|
||||
showRandomNoteMode: false, // 預設不顯示隨機筆記模式
|
||||
showRandomNoteMode: true, // 預設顯示隨機筆記模式
|
||||
showRecentFilesMode: true, // 預設顯示最近筆記模式
|
||||
showTasksMode: false, // 預設不顯示任務模式
|
||||
recentFilesCount: 30, // 預設最近筆記模式顯示的筆數
|
||||
|
|
@ -77,6 +78,7 @@ export const DEFAULT_SETTINGS: GallerySettings = {
|
|||
dateDividerMode: 'none', // 預設不使用日期分隔器
|
||||
showCodeBlocksInSummary: false, // 預設不在摘要中顯示程式碼區塊
|
||||
folderNoteDisplaySettings: 'default', // 預設不處理資料夾筆記
|
||||
interceptAllTagClicks: false, // 預設不攔截所有tag點擊事件
|
||||
};
|
||||
|
||||
// 設定頁面類別
|
||||
|
|
@ -410,6 +412,19 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
});
|
||||
});
|
||||
|
||||
// 攔截所有tag點擊事件
|
||||
new Setting(containerEl)
|
||||
.setName(t('intercept_all_tag_clicks'))
|
||||
.setDesc(t('intercept_all_tag_clicks_desc'))
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.interceptAllTagClicks)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.interceptAllTagClicks = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// 自訂文件副檔名設定
|
||||
new Setting(containerEl)
|
||||
.setName(t('custom_document_extensions'))
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ export const TRANSLATIONS: Translations = {
|
|||
'add': '新增',
|
||||
'root': '根目錄',
|
||||
'more_options': '更多選項',
|
||||
'add_to_search': '加入搜尋',
|
||||
'add_tag_to_search': '加入搜尋',
|
||||
'remove_tag_from_search': '從搜尋中移除',
|
||||
'global_search': '全域搜尋',
|
||||
|
||||
// 視圖標題
|
||||
'grid_view_title': '網格視圖',
|
||||
|
|
@ -112,6 +114,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'show_code_block_in_summary_desc': '設定是否在摘要中顯示CodeBlock的內容',
|
||||
'enable_file_watcher': '啟用檔案監控',
|
||||
'enable_file_watcher_desc': '啟用後會自動偵測檔案變更並更新視圖,關閉後需手動點擊重新整理按鈕',
|
||||
'intercept_all_tag_clicks': '攔截所有標籤點擊事件',
|
||||
'intercept_all_tag_clicks_desc': '啟用後會攔截所有標籤點擊事件,並在網格視圖中打開標籤',
|
||||
'reset_to_default' : '重置為預設值',
|
||||
'reset_to_default_desc': '將所有設定重置為預設值',
|
||||
'settings_reset_notice': '設定值已重置為預設值',
|
||||
|
|
@ -252,7 +256,9 @@ export const TRANSLATIONS: Translations = {
|
|||
'add': 'Add',
|
||||
'root': 'Root',
|
||||
'more_options': 'More options',
|
||||
'add_to_search': 'Add to search',
|
||||
'add_tag_to_search': 'Add to search',
|
||||
'remove_tag_from_search': 'Remove from search',
|
||||
'global_search': 'Global search',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Grid view',
|
||||
|
|
@ -320,6 +326,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'show_code_block_in_summary_desc': 'Set whether to show code block in the summary',
|
||||
'enable_file_watcher': 'Enable file watcher',
|
||||
'enable_file_watcher_desc': 'When enabled, the view will automatically update when files change. If disabled, you need to click the refresh button manually',
|
||||
'intercept_all_tag_clicks': 'Intercept all tag clicks',
|
||||
'intercept_all_tag_clicks_desc': 'When enabled, all tag clicks will be intercepted and opened in the grid view',
|
||||
'reset_to_default': 'Reset to default',
|
||||
'reset_to_default_desc': 'Reset all settings to default values',
|
||||
'settings_reset_notice': 'Settings have been reset to default values',
|
||||
|
|
@ -460,7 +468,9 @@ export const TRANSLATIONS: Translations = {
|
|||
'add': '添加',
|
||||
'root': '根目录',
|
||||
'more_options': '更多选项',
|
||||
'add_to_search': '加入搜索',
|
||||
'add_tag_to_search': '加入搜索',
|
||||
'remove_tag_from_search': '从搜索中移除',
|
||||
'global_search': '全域搜索',
|
||||
|
||||
// 视图标题
|
||||
'grid_view_title': '网格视图',
|
||||
|
|
@ -528,6 +538,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'show_code_block_in_summary_desc': '设置是否在摘要中显示CodeBlock的內容',
|
||||
'enable_file_watcher': '启用文件监控',
|
||||
'enable_file_watcher_desc': '启用后会自动检测文件变更并更新视图,关闭后需手动点击刷新按钮',
|
||||
'intercept_all_tag_clicks': '攔截所有標籤點擊事件',
|
||||
'intercept_all_tag_clicks_desc': '啟用後會攔截所有標籤點擊事件,並在網格視圖中打開標籤',
|
||||
'reset_to_default': '重置为默认值',
|
||||
'reset_to_default_desc': '将所有设置重置为默认值',
|
||||
'settings_reset_notice': '设置值已重置为默认值',
|
||||
|
|
@ -668,7 +680,9 @@ export const TRANSLATIONS: Translations = {
|
|||
'add': '追加',
|
||||
'root': 'ルート',
|
||||
'more_options': 'もっと選択肢',
|
||||
'add_to_search': '検索に追加',
|
||||
'add_tag_to_search': '検索に追加',
|
||||
'remove_tag_from_search': '検索から削除',
|
||||
'global_search': 'グローバル検索',
|
||||
|
||||
// ビュータイトル
|
||||
'grid_view_title': 'グリッドビュー',
|
||||
|
|
@ -736,6 +750,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'show_code_block_in_summary_desc': '要約にCodeBlockを表示するかどうかを設定',
|
||||
'enable_file_watcher': 'ファイル監視を有効にする',
|
||||
'enable_file_watcher_desc': '有効にすると、ファイルの変更を自動的に検出してビューを更新します。無効の場合は、更新ボタンを手動でクリックする必要があります',
|
||||
'intercept_all_tag_clicks': 'すべてのタグクリックを攔截する',
|
||||
'intercept_all_tag_clicks_desc': '有効にすると、すべてのタグクリックを攔截し、グリッドビューでタグを開きます',
|
||||
'reset_to_default': 'デフォルトに戻す',
|
||||
'reset_to_default_desc': 'すべての設定をデフォルト値に戻',
|
||||
'settings_reset_notice': '設定値がデフォルト値にリセットされました',
|
||||
|
|
@ -876,7 +892,9 @@ export const TRANSLATIONS: Translations = {
|
|||
'add': 'Добавить',
|
||||
'root': 'Корень',
|
||||
'more_options': 'Больше опций',
|
||||
'add_to_search': 'Добавить в поиск',
|
||||
'add_tag_to_search': 'Добавить в поиск',
|
||||
'remove_tag_from_search': 'Удалить из поиска',
|
||||
'global_search': 'Глобальный поиск',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Сеточный вид',
|
||||
|
|
@ -944,6 +962,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'show_code_block_in_summary_desc': 'Установите, чтобы показывать CodeBlock в кратком описании',
|
||||
'enable_file_watcher': 'Включить наблюдение за файлами',
|
||||
'enable_file_watcher_desc': 'При включении вид будет автоматически обновляться при изменении файлов. Если отключено, нужно вручную нажимать кнопку обновления',
|
||||
'intercept_all_tag_clicks': 'Поймать все клики по тегу',
|
||||
'intercept_all_tag_clicks_desc': 'При включении все клики по тегу будут пойматься и открыться в сетке',
|
||||
'reset_to_default': 'Сбросить на значения по умолчанию',
|
||||
'reset_to_default_desc': 'Сбросить все настройки на значения по умолчанию',
|
||||
'settings_reset_notice': 'Настройки сброшены на значения по умолчанию',
|
||||
|
|
@ -1084,7 +1104,9 @@ export const TRANSLATIONS: Translations = {
|
|||
'add': 'Додати',
|
||||
'root': 'Корень',
|
||||
'more_options': 'Більше опцій',
|
||||
'add_to_search': 'Додати до пошуку',
|
||||
'add_tag_to_search': 'Додати до пошуку',
|
||||
'remove_tag_from_search': 'Видалити з пошуку',
|
||||
'global_search': 'Глобальний пошук',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Сітковий вигляд',
|
||||
|
|
@ -1152,6 +1174,8 @@ export const TRANSLATIONS: Translations = {
|
|||
'show_code_block_in_summary_desc': 'Встановіть, щоб показувати CodeBlock в короткому описі',
|
||||
'enable_file_watcher': 'Увімкнути спостереження за файлами',
|
||||
'enable_file_watcher_desc': 'При увімкненні вигляд автоматично оновлюватиметься при зміні файлів. Якщо вимкнено, потрібно вручну натискати кнопку оновлення',
|
||||
'intercept_all_tag_clicks': 'Поймати всі кліки по тегу',
|
||||
'intercept_all_tag_clicks_desc': 'При увімкненні всі кліки по тегу будуть поймані та відображатися в сетці',
|
||||
'reset_to_default': 'Скинути до стандартних значень',
|
||||
'reset_to_default_desc': 'Скинути всі налаштування до стандартних значень',
|
||||
'settings_reset_notice': 'Налаштування скинуто до стандартних значень',
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"2.4.5": "1.1.0"
|
||||
"2.4.6": "1.1.0"
|
||||
}
|
||||
Loading…
Reference in a new issue