mirror of
https://github.com/devon22/obsidian-gridexplorer.git
synced 2026-07-22 05:38:16 +00:00
2.3.0
This commit is contained in:
parent
fc5ffe5793
commit
1718504eab
11 changed files with 361 additions and 114 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "gridexplorer",
|
||||
"name": "GridExplorer",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.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.2.2",
|
||||
"version": "2.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gridexplorer",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gridexplorer",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0",
|
||||
"description": "Browse note files in a grid view.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export class FileWatcher {
|
|||
private plugin: GridExplorerPlugin;
|
||||
private gridView: GridView;
|
||||
private app: App;
|
||||
private renderTimer: number | null = null; // 用於去抖動 render()
|
||||
|
||||
constructor(plugin: GridExplorerPlugin, gridView: GridView) {
|
||||
this.plugin = plugin;
|
||||
|
|
@ -24,27 +25,25 @@ export class FileWatcher {
|
|||
this.plugin.registerEvent(
|
||||
this.app.vault.on('create', (file) => {
|
||||
if (file instanceof TFile) {
|
||||
if(this.gridView.sourceMode === 'random-note' ||
|
||||
this.gridView.sourceMode === 'bookmarks' ||
|
||||
this.gridView.sourceMode === 'outgoinglinks') {
|
||||
if(this.gridView.sourceMode === 'random-note') {
|
||||
return;
|
||||
} else if (this.gridView.sourceMode === 'recent-files') {
|
||||
if(isDocumentFile(file) || (isMediaFile(file) && this.gridView.randomNoteIncludeMedia)) {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
} else if (this.gridView.sourceMode === 'folder') {
|
||||
if (this.gridView.sourcePath && this.gridView.searchQuery === '') {
|
||||
const fileDirPath = file.path.split('/').slice(0, -1).join('/') || '/';
|
||||
if (fileDirPath === this.gridView.sourcePath) {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
} else if (this.gridView.sourceMode === 'backlinks') {
|
||||
if(isDocumentFile(file)) {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
} else {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -54,21 +53,21 @@ export class FileWatcher {
|
|||
this.plugin.registerEvent(
|
||||
this.app.vault.on('delete', (file) => {
|
||||
if (file instanceof TFile) {
|
||||
if(this.gridView.sourceMode === 'random-note' || this.gridView.sourceMode === 'bookmarks') {
|
||||
if(this.gridView.sourceMode === 'random-note') {
|
||||
return;
|
||||
} else if (this.gridView.sourceMode === 'recent-files') {
|
||||
if(isDocumentFile(file) || (isMediaFile(file) && this.gridView.randomNoteIncludeMedia)) {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
} else if (this.gridView.sourceMode === 'folder') {
|
||||
if (this.gridView.sourcePath && this.gridView.searchQuery === '') {
|
||||
const fileDirPath = file.path.split('/').slice(0, -1).join('/') || '/';
|
||||
if (fileDirPath === this.gridView.sourcePath) {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -85,11 +84,11 @@ export class FileWatcher {
|
|||
const fileDirPath = file.path.split('/').slice(0, -1).join('/') || '/';
|
||||
const oldDirPath = oldPath.split('/').slice(0, -1).join('/') || '/';
|
||||
if (fileDirPath === this.gridView.sourcePath || oldDirPath === this.gridView.sourcePath) {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -99,7 +98,7 @@ export class FileWatcher {
|
|||
this.plugin.registerEvent(
|
||||
(this.app as any).internalPlugins.plugins.bookmarks.instance.on('changed', () => {
|
||||
if (this.gridView.sourceMode === 'bookmarks') {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
@ -110,11 +109,24 @@ export class FileWatcher {
|
|||
if (file instanceof TFile) {
|
||||
if ((this.gridView.sourceMode === 'backlinks' || this.gridView.sourceMode === 'outgoinglinks')
|
||||
&& this.gridView.searchQuery === '') {
|
||||
this.gridView.render();
|
||||
this.scheduleRender();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 以 200ms 去抖動的方式排程 render,避免短時間內大量重繪
|
||||
private scheduleRender = (): void => {
|
||||
if (this.renderTimer !== null) {
|
||||
clearTimeout(this.renderTimer);
|
||||
}
|
||||
// 200ms 延遲,可視需求調整
|
||||
this.renderTimer = window.setTimeout((): void => {
|
||||
console.log('123');
|
||||
this.gridView.render();
|
||||
this.renderTimer = null;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,6 +200,24 @@ export class FolderSelectionModal extends Modal {
|
|||
this.folderOptions.push(randomNoteOption);
|
||||
}
|
||||
|
||||
// 建立任務選項
|
||||
if (this.plugin.settings.showTasksMode) {
|
||||
const tasksOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option ge-special-option',
|
||||
text: `☑️ ${t('tasks_mode')}`
|
||||
});
|
||||
|
||||
tasksOption.addEventListener('click', () => {
|
||||
if (this.activeView) {
|
||||
this.activeView.setSource('tasks', '', true);
|
||||
} else {
|
||||
this.plugin.activateView('tasks');
|
||||
}
|
||||
this.close();
|
||||
});
|
||||
this.folderOptions.push(tasksOption);
|
||||
}
|
||||
|
||||
// 建立根目錄選項
|
||||
const rootFolderOption = this.folderOptionsContainer.createEl('div', {
|
||||
cls: 'ge-grid-view-folder-option',
|
||||
|
|
|
|||
154
src/GridView.ts
154
src/GridView.ts
|
|
@ -32,6 +32,7 @@ export class GridView extends ItemView {
|
|||
minMode: boolean = false; // 最小模式
|
||||
showIgnoredFolders: boolean = false; // 顯示忽略資料夾
|
||||
pinnedList: string[] = []; // 置頂清單
|
||||
taskFilter: string = 'uncompleted'; // 任務分類
|
||||
|
||||
constructor(leaf: WorkspaceLeaf, plugin: GridExplorerPlugin) {
|
||||
super(leaf);
|
||||
|
|
@ -69,6 +70,8 @@ export class GridView extends ItemView {
|
|||
return 'links-going-out';
|
||||
} else if (this.sourceMode === 'random-note') {
|
||||
return 'dice';
|
||||
} else if (this.sourceMode === 'tasks') {
|
||||
return 'square-check-big';
|
||||
} else if (this.sourceMode === 'recent-files') {
|
||||
return 'calendar-days';
|
||||
} else if (this.sourceMode === 'all-files') {
|
||||
|
|
@ -93,6 +96,8 @@ export class GridView extends ItemView {
|
|||
return t('outgoinglinks_mode');
|
||||
} else if (this.sourceMode === 'random-note') {
|
||||
return t('random_note_mode');
|
||||
} else if (this.sourceMode === 'tasks') {
|
||||
return t('tasks_mode');
|
||||
} else if (this.sourceMode === 'recent-files') {
|
||||
return t('recent_files_mode');
|
||||
} else if (this.sourceMode === 'all-files') {
|
||||
|
|
@ -171,7 +176,7 @@ export class GridView extends ItemView {
|
|||
// 只有當點擊的是頂部按鈕區域本身(而不是其中的按鈕)時才觸發捲動
|
||||
if (event.target === headerButtonsDiv) {
|
||||
event.preventDefault();
|
||||
// 取得網格容器(應該是在 grid_render 後建立的第二個子元素)
|
||||
// 取得網格容器
|
||||
const gridContainer = this.containerEl.querySelector('.ge-grid-container');
|
||||
if (gridContainer) {
|
||||
gridContainer.scrollTo({
|
||||
|
|
@ -663,6 +668,60 @@ export class GridView extends ItemView {
|
|||
});
|
||||
}
|
||||
|
||||
if (this.sourceMode === 'tasks' && this.searchQuery === '') {
|
||||
// 建立任務分類按鈕,區分未完成、已完成、全部
|
||||
const taskFilterButton = headerButtonsDiv.createEl('button', {
|
||||
attr: { 'aria-label': t('task_filter') }
|
||||
});
|
||||
if (this.taskFilter === 'uncompleted') {
|
||||
setIcon(taskFilterButton, 'square');
|
||||
} else if (this.taskFilter === 'completed') {
|
||||
setIcon(taskFilterButton, 'square-check-big');
|
||||
} else {
|
||||
setIcon(taskFilterButton, 'square-asterisk');
|
||||
}
|
||||
// 建立下拉選單,uncompleted、completed、all
|
||||
const menu = new Menu();
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(t('uncompleted'))
|
||||
.setChecked(this.taskFilter === 'uncompleted')
|
||||
.setIcon('square')
|
||||
.onClick(() => {
|
||||
this.taskFilter = 'uncompleted';
|
||||
taskFilterButton.textContent = t('uncompleted');
|
||||
setIcon(taskFilterButton, 'square');
|
||||
this.render();
|
||||
});
|
||||
});
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(t('completed'))
|
||||
.setChecked(this.taskFilter === 'completed')
|
||||
.setIcon('square-check-big')
|
||||
.onClick(() => {
|
||||
this.taskFilter = 'completed';
|
||||
taskFilterButton.textContent = t('completed');
|
||||
setIcon(taskFilterButton, 'square-check-big');
|
||||
this.render();
|
||||
});
|
||||
});
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(t('all'))
|
||||
.setChecked(this.taskFilter === 'all')
|
||||
.setIcon('square-asterisk')
|
||||
.onClick(() => {
|
||||
this.taskFilter = 'all';
|
||||
taskFilterButton.textContent = t('all');
|
||||
setIcon(taskFilterButton, 'square-asterisk');
|
||||
this.render();
|
||||
});
|
||||
});
|
||||
|
||||
// 點擊按鈕時顯示下拉選單
|
||||
taskFilterButton.addEventListener('click', (event) => {
|
||||
menu.showAtMouseEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
// 創建內容區域
|
||||
const contentEl = this.containerEl.createDiv('view-content');
|
||||
|
||||
|
|
@ -747,35 +806,42 @@ export class GridView extends ItemView {
|
|||
}
|
||||
|
||||
// 如果是資料夾模式且沒有搜尋結果,顯示目前資料夾名稱
|
||||
// if (this.sourceMode === 'folder' && this.searchQuery === '' && this.sourcePath !== '/') {
|
||||
// const folderName = this.sourcePath.split('/').pop();
|
||||
// const folderNameContainer = container.createDiv('ge-foldername-content');
|
||||
// if (folderNameContainer) {
|
||||
// folderNameContainer.createEl('span', { text: `/ ${folderName}` });
|
||||
// }
|
||||
// }
|
||||
|
||||
// 如果啟用了顯示"回上層資料夾"選項
|
||||
if (this.sourceMode === 'folder' && this.searchQuery === '' &&
|
||||
this.plugin.settings.showParentFolderItem && this.sourcePath !== '/') {
|
||||
// 創建"回上層資料夾"
|
||||
const parentFolderEl = container.createDiv('ge-grid-item ge-folder-item');
|
||||
this.gridItems.push(parentFolderEl); // 添加到網格項目數組
|
||||
// 獲取父資料夾路徑
|
||||
const parentPath = this.sourcePath.split('/').slice(0, -1).join('/') || '/';
|
||||
// 設置資料夾路徑屬性
|
||||
parentFolderEl.dataset.folderPath = parentPath;
|
||||
|
||||
const contentArea = parentFolderEl.createDiv('ge-content-area');
|
||||
const titleContainer = contentArea.createDiv('ge-title-container');
|
||||
const customFolderIcon = this.plugin.settings.customFolderIcon;
|
||||
titleContainer.createEl('span', { cls: 'ge-title', text: `${customFolderIcon} ..`.trim() });
|
||||
|
||||
// 回上層資料夾事件
|
||||
parentFolderEl.addEventListener('click', () => {
|
||||
this.setSource('folder', parentPath, true);
|
||||
this.clearSelection();
|
||||
});
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是資料夾模式,先顯示所有子資料夾
|
||||
|
|
@ -1022,20 +1088,22 @@ export class GridView extends ItemView {
|
|||
}
|
||||
|
||||
// 資料夾渲染完插入 break(僅當有資料夾時或有顯示回上一層資料夾項目時)
|
||||
if (subfolders.length > 0 || (subfolders.length === 0 && this.plugin.settings.showParentFolderItem)) {
|
||||
if (subfolders.length > 0 || (subfolders.length === 0 && this.plugin.settings.dateDividerMode !== 'none' && this.plugin.settings.showParentFolderItem)) {
|
||||
container.createDiv('ge-break');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let loadingDiv: HTMLElement | null = null;
|
||||
if (this.searchQuery || this.sourceMode === 'tasks') {
|
||||
// 顯示搜尋中的提示
|
||||
loadingDiv = container.createDiv({ text: t('searching'), cls: 'ge-loading-indicator' });
|
||||
}
|
||||
|
||||
let files: TFile[] = [];
|
||||
// 使用 Map 來記錄原始順序
|
||||
let fileIndexMap = new Map<TFile, number>();
|
||||
if (this.searchQuery) {
|
||||
// 顯示搜尋中的提示
|
||||
const loadingDiv = container.createDiv('ge-loading-indicator');
|
||||
loadingDiv.setText(t('searching'));
|
||||
|
||||
// 取得 vault 中所有支援的檔案
|
||||
let allFiles: TFile[] = [];
|
||||
if (this.searchAllFiles) {
|
||||
|
|
@ -1112,9 +1180,6 @@ export class GridView extends ItemView {
|
|||
|
||||
// 忽略檔案
|
||||
files = ignoredFiles(files, this);
|
||||
|
||||
// 移除搜尋中的提示
|
||||
loadingDiv.remove();
|
||||
} else {
|
||||
// 無搜尋關鍵字的情況
|
||||
files = await getFiles(this, this.randomNoteIncludeMedia);
|
||||
|
|
@ -1133,6 +1198,10 @@ export class GridView extends ItemView {
|
|||
}
|
||||
}
|
||||
|
||||
if (loadingDiv) {
|
||||
loadingDiv.remove();
|
||||
}
|
||||
|
||||
// 如果沒有檔案,顯示提示訊息
|
||||
if (files.length === 0) {
|
||||
const noFilesDiv = container.createDiv('ge-no-files');
|
||||
|
|
@ -1246,7 +1315,7 @@ export class GridView extends ItemView {
|
|||
//將預覽文字設定到標題的 title 屬性中
|
||||
const titleEl = fileEl.querySelector('.ge-title');
|
||||
if (titleEl && pEl) {
|
||||
titleEl.setAttribute('title', `<${titleEl.textContent}>\n${pEl.textContent}` || '');
|
||||
titleEl.setAttribute('title', `${titleEl.textContent}\n${pEl.textContent}` || '');
|
||||
}
|
||||
|
||||
if (frontMatterInfo.exists) {
|
||||
|
|
@ -1282,6 +1351,7 @@ export class GridView extends ItemView {
|
|||
if (imageAreaEl) {
|
||||
imageAreaEl.remove();
|
||||
}
|
||||
fileEl.style.height = '100%';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1826,10 +1896,10 @@ export class GridView extends ItemView {
|
|||
const file = this.app.vault.getAbstractFileByPath(path);
|
||||
if (file instanceof TFile) {
|
||||
try {
|
||||
// 計算新的檔案路徑
|
||||
// 計算新的檔案路徑
|
||||
const newPath = `${folderPath}/${file.name}`;
|
||||
// 移動檔案
|
||||
await this.app.fileManager.renameFile(file, newPath);
|
||||
// 移動檔案
|
||||
await this.app.fileManager.renameFile(file, newPath);
|
||||
} catch (error) {
|
||||
console.error(`An error occurred while moving the file ${file.path}:`, error);
|
||||
}
|
||||
|
|
@ -1837,7 +1907,7 @@ export class GridView extends ItemView {
|
|||
}
|
||||
|
||||
// 重新渲染視圖
|
||||
this.render();
|
||||
// this.render();
|
||||
return;
|
||||
} catch (error) {
|
||||
console.error('Error parsing dragged files data:', error);
|
||||
|
|
@ -1865,7 +1935,7 @@ export class GridView extends ItemView {
|
|||
// 移動檔案
|
||||
await this.app.fileManager.renameFile(file, newPath);
|
||||
// 重新渲染視圖
|
||||
this.render();
|
||||
// this.render();
|
||||
} catch (error) {
|
||||
console.error('An error occurred while moving the file:', error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,6 +324,39 @@ export async function getFiles(gridView: GridView, includeMediaFiles: boolean):
|
|||
|
||||
bookmarks.forEach(processBookmarkItem);
|
||||
return Array.from(bookmarkedFiles) as TFile[];
|
||||
} else if (sourceMode === 'tasks') {
|
||||
// 任務模式
|
||||
const filesWithTasks = new Set<TFile>();
|
||||
const markdownFiles = app.vault.getMarkdownFiles();
|
||||
|
||||
for (const file of markdownFiles) {
|
||||
try {
|
||||
const content = await app.vault.cachedRead(file);
|
||||
let shouldAdd = false;
|
||||
// 用 gridView.taskFilter 匹配 uncompleted、completed、all 任務
|
||||
if (gridView.taskFilter === 'uncompleted') {
|
||||
// 只匹配未完成的任務: - [ ] 或 * [ ]
|
||||
shouldAdd = /^[\s]*[-*]\s*\[\s*\](?![^\[]*\[\s*[^\s\]]+\]).*$/m.test(content);
|
||||
} else if (gridView.taskFilter === 'completed') {
|
||||
// 只匹配所有任務均已完成的檔案(至少有一個已完成且沒有未完成)
|
||||
const hasCompleted = /^[\s]*[-*]\s*\[x\](?![^\[]*\[\s*[^\s\]]+\]).*$/m.test(content);
|
||||
const hasIncomplete = /^[\s]*[-*]\s*\[\s*\](?![^\[]*\[\s*[^\s\]]+\]).*$/m.test(content);
|
||||
shouldAdd = hasCompleted && !hasIncomplete;
|
||||
} else if (gridView.taskFilter === 'all') {
|
||||
// 匹配任何任務(已完成或未完成皆可)
|
||||
const hasIncomplete = /^[\s]*[-*]\s*\[\s*\](?![^\[]*\[\s*[^\s\]]+\]).*$/m.test(content);
|
||||
const hasCompleted = /^[\s]*[-*]\s*\[x\](?![^\[]*\[\s*[^\s\]]+\]).*$/m.test(content);
|
||||
shouldAdd = hasIncomplete || hasCompleted;
|
||||
}
|
||||
|
||||
if (shouldAdd) {
|
||||
filesWithTasks.add(file);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error reading file ${file.path}:`, error);
|
||||
}
|
||||
}
|
||||
return sortFiles(Array.from(filesWithTasks), gridView);
|
||||
} else if (sourceMode === 'all-files') {
|
||||
// 所有筆記模式
|
||||
const allVaultFiles = app.vault.getFiles().filter(file => {
|
||||
|
|
|
|||
132
src/settings.ts
132
src/settings.ts
|
|
@ -25,6 +25,7 @@ export interface GallerySettings {
|
|||
showAllFilesMode: boolean; // 是否顯示所有檔案模式
|
||||
showRandomNoteMode: boolean; // 是否顯示隨機筆記模式
|
||||
showRecentFilesMode: boolean; // 是否顯示最近筆記模式
|
||||
showTasksMode: boolean; // 是否顯示任務模式
|
||||
customFolderIcon: string; // 自訂資料夾圖示
|
||||
customDocumentExtensions: string; // 自訂文件副檔名(用逗號分隔)
|
||||
recentSources: string[]; // 最近的瀏覽記錄
|
||||
|
|
@ -52,9 +53,9 @@ export const DEFAULT_SETTINGS: GallerySettings = {
|
|||
summaryLength: 100, // 筆記摘要的字數,預設 100
|
||||
enableFileWatcher: true, // 預設啟用檔案監控
|
||||
showMediaFiles: true, // 預設顯示圖片和影片
|
||||
showVideoThumbnails: false, // 預設不顯示影片縮圖
|
||||
showVideoThumbnails: true, // 預設顯示影片縮圖
|
||||
defaultOpenLocation: 'tab', // 預設開啟位置:新分頁
|
||||
showParentFolderItem: false, // 預設不顯示"返回上级文件夹"選項
|
||||
showParentFolderItem: false, // 預設不顯示"返回上層資料夾"選項
|
||||
reuseExistingLeaf: false, // 預設不重用現有的網格視圖
|
||||
showBookmarksMode: true, // 預設顯示書籤模式
|
||||
showSearchMode: true, // 預設顯示搜尋結果模式
|
||||
|
|
@ -63,6 +64,7 @@ export const DEFAULT_SETTINGS: GallerySettings = {
|
|||
showAllFilesMode: false, // 預設不顯示所有檔案模式
|
||||
showRandomNoteMode: false, // 預設不顯示隨機筆記模式
|
||||
showRecentFilesMode: true, // 預設顯示最近筆記模式
|
||||
showTasksMode: false, // 預設不顯示任務模式
|
||||
recentFilesCount: 30, // 預設最近筆記模式顯示的筆數
|
||||
randomNoteCount: 10, // 預設隨機筆記模式顯示的筆數
|
||||
customFolderIcon: '📁', // 自訂資料夾圖示
|
||||
|
|
@ -108,7 +110,7 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
|
||||
// 設定是否顯示書籤模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_bookmarks_mode'))
|
||||
.setName(`📑 ${t('show_bookmarks_mode')}`)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showBookmarksMode)
|
||||
|
|
@ -120,7 +122,7 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
|
||||
// 設定是否顯示搜尋結果模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_search_mode'))
|
||||
.setName(`🔍 ${t('show_search_mode')}`)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showSearchMode)
|
||||
|
|
@ -132,7 +134,7 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
|
||||
// 設定是否顯示反向連結模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_backlinks_mode'))
|
||||
.setName(`🔗 ${t('show_backlinks_mode')}`)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showBacklinksMode)
|
||||
|
|
@ -144,7 +146,7 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
|
||||
// 設定是否顯示外部連結模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_outgoinglinks_mode'))
|
||||
.setName(`🔗 ${t('show_outgoinglinks_mode')}`)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showOutgoinglinksMode)
|
||||
|
|
@ -156,7 +158,7 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
|
||||
// 設定是否顯示所有檔案模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_all_files_mode'))
|
||||
.setName(`📔 ${t('show_all_files_mode')}`)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showAllFilesMode)
|
||||
|
|
@ -166,54 +168,90 @@ export class GridExplorerSettingTab extends PluginSettingTab {
|
|||
});
|
||||
});
|
||||
|
||||
// 設定是否顯示最近檔案模式
|
||||
// 最近檔案模式設定
|
||||
const recentFilesSetting = new Setting(containerEl)
|
||||
.setName(`📅 ${t('show_recent_files_mode')}`);
|
||||
|
||||
// 添加切換按鈕
|
||||
recentFilesSetting.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showRecentFilesMode)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showRecentFilesMode = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// 在設定描述區域添加數字輸入框
|
||||
const recentDescEl = recentFilesSetting.descEl.createEl('div', { cls: 'ge-setting-desc' });
|
||||
|
||||
recentDescEl.createEl('span', { text: t('recent_files_count') });
|
||||
|
||||
const recentInput = recentDescEl.createEl('input', {
|
||||
type: 'number',
|
||||
value: this.plugin.settings.recentFilesCount.toString(),
|
||||
cls: 'ge-setting-number-input'
|
||||
});
|
||||
|
||||
recentInput.addEventListener('change', async (e) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
const value = parseInt(target.value);
|
||||
if (!isNaN(value) && value > 0) {
|
||||
this.plugin.settings.recentFilesCount = value;
|
||||
await this.plugin.saveSettings(false);
|
||||
} else {
|
||||
target.value = this.plugin.settings.recentFilesCount.toString();
|
||||
}
|
||||
});
|
||||
|
||||
// 隨機筆記模式設定
|
||||
const randomNoteSetting = new Setting(containerEl)
|
||||
.setName(`🎲 ${t('show_random_note_mode')}`);
|
||||
|
||||
// 添加切換按鈕
|
||||
randomNoteSetting.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showRandomNoteMode)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showRandomNoteMode = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// 在設定描述區域添加數字輸入框
|
||||
const descEl = randomNoteSetting.descEl.createEl('div', { cls: 'ge-setting-desc' });
|
||||
|
||||
descEl.createEl('span', { text: t('random_note_count') });
|
||||
|
||||
const input = descEl.createEl('input', {
|
||||
type: 'number',
|
||||
value: this.plugin.settings.randomNoteCount.toString(),
|
||||
cls: 'ge-setting-number-input'
|
||||
});
|
||||
|
||||
input.addEventListener('change', async (e) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
const value = parseInt(target.value);
|
||||
if (!isNaN(value) && value > 0) {
|
||||
this.plugin.settings.randomNoteCount = value;
|
||||
await this.plugin.saveSettings(false);
|
||||
} else {
|
||||
target.value = this.plugin.settings.randomNoteCount.toString();
|
||||
}
|
||||
});
|
||||
|
||||
// 顯示任務模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_recent_files_mode'))
|
||||
.setName(`☑️ ${t('show_tasks_mode')}`)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showRecentFilesMode)
|
||||
.setValue(this.plugin.settings.showTasksMode)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showRecentFilesMode = value;
|
||||
this.plugin.settings.showTasksMode = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// 最近檔案模式的顯示資料筆數
|
||||
new Setting(containerEl)
|
||||
.setName(t('recent_files_count'))
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.plugin.settings.recentFilesCount.toString())
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.recentFilesCount = parseInt(value);
|
||||
await this.plugin.saveSettings(false);
|
||||
});
|
||||
});
|
||||
|
||||
// 設定是否顯示隨機筆記模式
|
||||
new Setting(containerEl)
|
||||
.setName(t('show_random_note_mode'))
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.showRandomNoteMode)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showRandomNoteMode = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// 隨機筆記模式的顯示資料筆數
|
||||
new Setting(containerEl)
|
||||
.setName(t('random_note_count'))
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.plugin.settings.randomNoteCount.toString())
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.randomNoteCount = parseInt(value);
|
||||
await this.plugin.saveSettings(false);
|
||||
});
|
||||
});
|
||||
|
||||
// 媒體檔案設定區域
|
||||
containerEl.createEl('h3', { text: t('media_files_settings') });
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'untitled': '未命名',
|
||||
'files': '個檔案',
|
||||
'add': '新增',
|
||||
'root': '根目錄',
|
||||
|
||||
// 視圖標題
|
||||
'grid_view_title': '網格視圖',
|
||||
|
|
@ -53,6 +54,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'all_files_mode': '所有檔案',
|
||||
'recent_files_mode': '最近檔案',
|
||||
'random_note_mode': '隨機筆記',
|
||||
'tasks_mode': '任務',
|
||||
|
||||
// 排序選項
|
||||
'sort_name_asc': '名稱 (A → Z)',
|
||||
|
|
@ -124,6 +126,11 @@ export const TRANSLATIONS: Translations = {
|
|||
'random_note_count': '隨機筆記模式顯示筆數',
|
||||
'random_note_notes_only': '僅筆記',
|
||||
'random_note_include_media_files': '包含媒體檔案',
|
||||
'show_tasks_mode': '顯示任務模式',
|
||||
'task_filter': '任務分類',
|
||||
'uncompleted': '未完成',
|
||||
'completed': '已完成',
|
||||
'all': '全部',
|
||||
|
||||
// 顯示"返回上層資料夾"選項設定
|
||||
'show_parent_folder_item': '顯示「返回上層資料夾」',
|
||||
|
|
@ -235,6 +242,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'untitled': 'Untitled',
|
||||
'files': 'files',
|
||||
'add': 'Add',
|
||||
'root': 'Root',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Grid view',
|
||||
|
|
@ -246,6 +254,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'all_files_mode': 'All files',
|
||||
'recent_files_mode': 'Recent files',
|
||||
'random_note_mode': 'Random note',
|
||||
'tasks_mode': 'Tasks',
|
||||
|
||||
// Sort Options
|
||||
'sort_name_asc': 'Name (A → Z)',
|
||||
|
|
@ -317,6 +326,11 @@ export const TRANSLATIONS: Translations = {
|
|||
'random_note_count': 'Random note count',
|
||||
'random_note_notes_only': 'Notes Only',
|
||||
'random_note_include_media_files': 'Include Media Files',
|
||||
'show_tasks_mode': 'Show tasks mode',
|
||||
'task_filter': 'Task filter',
|
||||
'uncompleted': 'Uncompleted',
|
||||
'completed': 'Completed',
|
||||
'all': 'All',
|
||||
|
||||
// Show "Parent Folder" option setting
|
||||
'show_parent_folder_item': 'Show "Parent Folder" item',
|
||||
|
|
@ -428,6 +442,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'untitled': '未命名',
|
||||
'files': '个文件',
|
||||
'add': '添加',
|
||||
'root': '根目录',
|
||||
|
||||
// 视图标题
|
||||
'grid_view_title': '网格视图',
|
||||
|
|
@ -439,6 +454,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'all_files_mode': '所有文件',
|
||||
'recent_files_mode': '最近文件',
|
||||
'random_note_mode': '随机笔记',
|
||||
'tasks_mode': '任务',
|
||||
|
||||
// 排序选项
|
||||
'sort_name_asc': '名称 (A → Z)',
|
||||
|
|
@ -510,6 +526,11 @@ export const TRANSLATIONS: Translations = {
|
|||
'random_note_count': '随机笔记模式显示笔数',
|
||||
'random_note_notes_only': '仅笔记',
|
||||
'random_note_include_media_files': '包含媒体文件',
|
||||
'show_tasks_mode': '显示任务模式',
|
||||
'task_filter': '任务分类',
|
||||
'uncompleted': '未完成',
|
||||
'completed': '已完成',
|
||||
'all': '全部',
|
||||
|
||||
// 显示"返回上级文件夹"选项设置
|
||||
'show_parent_folder_item': '显示「返回上级文件夹」',
|
||||
|
|
@ -621,6 +642,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'untitled': '無題',
|
||||
'files': 'ファイル',
|
||||
'add': '追加',
|
||||
'root': 'ルート',
|
||||
|
||||
// ビュータイトル
|
||||
'grid_view_title': 'グリッドビュー',
|
||||
|
|
@ -632,6 +654,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'all_files_mode': 'すべてのファイル',
|
||||
'recent_files_mode': '最近のファイル',
|
||||
'random_note_mode': 'ランダムノート',
|
||||
'tasks_mode': 'タスク',
|
||||
|
||||
// 並べ替えオプション
|
||||
'sort_name_asc': '名前 (A → Z)',
|
||||
|
|
@ -703,6 +726,11 @@ export const TRANSLATIONS: Translations = {
|
|||
'random_note_count': 'ランダムノートモード表示筆数',
|
||||
'random_note_notes_only': 'ノートのみ',
|
||||
'random_note_include_media_files': 'メディアファイルを含む',
|
||||
'show_tasks_mode': 'タスクモードを表示',
|
||||
'task_filter': 'タスクフィルタ',
|
||||
'uncompleted': '未完了',
|
||||
'completed': '完了',
|
||||
'all': 'すべて',
|
||||
|
||||
// "親フォルダ"オプション設定を表示
|
||||
'show_parent_folder_item': '「親フォルダ」項目を表示',
|
||||
|
|
@ -814,6 +842,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'untitled': 'Без названия',
|
||||
'files': 'файлы',
|
||||
'add': 'Добавить',
|
||||
'root': 'Корень',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Сеточный вид',
|
||||
|
|
@ -825,6 +854,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'all_files_mode': 'Все файлы',
|
||||
'recent_files_mode': 'Недавние файлы',
|
||||
'random_note_mode': 'Случайная заметка',
|
||||
'tasks_mode': 'Задачи',
|
||||
|
||||
// Sort Options
|
||||
'sort_name_asc': 'Имя (А → Я)',
|
||||
|
|
@ -896,6 +926,11 @@ export const TRANSLATIONS: Translations = {
|
|||
'random_note_count': 'Количество случайных заметок',
|
||||
'random_note_notes_only': 'Только заметки',
|
||||
'random_note_include_media_files': 'Включить медиафайлы',
|
||||
'show_tasks_mode': 'Показывать режим задач',
|
||||
'task_filter': 'Фильтр задач',
|
||||
'uncompleted': 'Незавершенные',
|
||||
'completed': 'Завершенные',
|
||||
'all': 'Все',
|
||||
|
||||
// Show "Parent Folder" option setting
|
||||
'show_parent_folder_item': 'Показывать элемент "Родительская папка"',
|
||||
|
|
@ -1007,6 +1042,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'untitled': 'Без назви',
|
||||
'files': 'файли',
|
||||
'add': 'Додати',
|
||||
'root': 'Корень',
|
||||
|
||||
// View Titles
|
||||
'grid_view_title': 'Сітковий вигляд',
|
||||
|
|
@ -1018,6 +1054,7 @@ export const TRANSLATIONS: Translations = {
|
|||
'all_files_mode': 'Усі файли',
|
||||
'recent_files_mode': 'Останні файли',
|
||||
'random_note_mode': 'Випадкова нотатка',
|
||||
'tasks_mode': 'Задачі',
|
||||
|
||||
// Sort Options
|
||||
'sort_name_asc': 'Назва (А → Я)',
|
||||
|
|
@ -1089,6 +1126,11 @@ export const TRANSLATIONS: Translations = {
|
|||
'random_note_count': 'Кількість випадкових нотаток',
|
||||
'random_note_notes_only': 'Тільки нотатки',
|
||||
'random_note_include_media_files': 'Включити медіафайли',
|
||||
'show_tasks_mode': 'Показувати режим завдань',
|
||||
'task_filter': 'Фільтр завдань',
|
||||
'uncompleted': 'Незавершені',
|
||||
'completed': 'Завершені',
|
||||
'all': 'Всі',
|
||||
|
||||
// Show "Parent Folder" option setting
|
||||
'show_parent_folder_item': 'Показувати елемент "Батьківська папка"',
|
||||
|
|
|
|||
42
styles.css
42
styles.css
|
|
@ -326,17 +326,38 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
/* .ge-foldername-content {
|
||||
.ge-foldername-content {
|
||||
grid-column: 1 / -1;
|
||||
margin-top: 5px;
|
||||
margin-top: -2px;
|
||||
margin-bottom: -3px;
|
||||
margin-left: 7px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ge-foldername-content span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
} */
|
||||
}
|
||||
|
||||
/* 為資料夾名稱、分隔符等元素添加間距 */
|
||||
.ge-foldername-content > *:nth-child(1) {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.ge-foldername-content > *:nth-child(2) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.ge-parent-folder-link {
|
||||
text-decoration: none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.ge-parent-folder-link:hover {
|
||||
border-radius: 4px;
|
||||
background-color: var(--background-modifier-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 搜尋對話框樣式 */
|
||||
.ge-search-container {
|
||||
|
|
@ -542,6 +563,7 @@
|
|||
}
|
||||
|
||||
.ge-loading-indicator {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
|
@ -551,6 +573,7 @@
|
|||
}
|
||||
|
||||
.ge-no-files {
|
||||
grid-column: 1 / -1;
|
||||
text-align: center;
|
||||
padding: 2em;
|
||||
color: var(--text-muted);
|
||||
|
|
@ -902,3 +925,14 @@
|
|||
opacity: 0.9;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* 設定描述區域樣式 */
|
||||
.ge-setting-desc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ge-setting-number-input {
|
||||
width: 60px;
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"2.2.2": "1.1.0"
|
||||
"2.3.0": "1.1.0"
|
||||
}
|
||||
Loading…
Reference in a new issue