mirror of
https://github.com/devon22/obsidian-gridexplorer.git
synced 2026-07-22 05:38:16 +00:00
2.6.2
This commit is contained in:
parent
cfb912e76e
commit
8677eee105
9 changed files with 256 additions and 91 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "gridexplorer",
|
||||
"name": "GridExplorer",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"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.6.1",
|
||||
"version": "2.6.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gridexplorer",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gridexplorer",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"description": "Browse note files in a grid view.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
173
src/GridView.ts
173
src/GridView.ts
|
|
@ -1,4 +1,4 @@
|
|||
import { WorkspaceLeaf, ItemView, TFolder, TFile, Menu, Notice, Platform, setIcon, getFrontMatterInfo, FrontMatterCache, normalizePath } from 'obsidian';
|
||||
import { WorkspaceLeaf, ItemView, TFolder, TFile, Menu, Notice, Platform, setIcon, getFrontMatterInfo, FrontMatterCache, normalizePath, setTooltip } from 'obsidian';
|
||||
import GridExplorerPlugin from '../main';
|
||||
import { handleKeyDown as handleKeyDownHelper } from './handleKeyDown';
|
||||
import { isDocumentFile, isMediaFile, isImageFile, isVideoFile, isAudioFile, sortFiles, ignoredFiles, getFiles, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS } from './fileUtils';
|
||||
|
|
@ -197,6 +197,11 @@ export class GridView extends ItemView {
|
|||
if(this.sourceMode === '') this.sourceMode = 'folder';
|
||||
if(this.sourcePath === '') this.sourcePath = '/';
|
||||
|
||||
// 非資料夾模式時,強制路徑為根目錄
|
||||
if(this.sourceMode !== 'folder') {
|
||||
this.sourcePath = '/';
|
||||
}
|
||||
|
||||
this.render(resetScroll);
|
||||
// 通知 Obsidian 保存視圖狀態
|
||||
this.app.workspace.requestSaveLayout();
|
||||
|
|
@ -696,12 +701,12 @@ export class GridView extends ItemView {
|
|||
parentFolderName = t('root');
|
||||
}
|
||||
|
||||
const folderNameContainer = this.containerEl.createDiv('ge-foldername-content');
|
||||
const modenameContainer = this.containerEl.createDiv('ge-modename-content');
|
||||
|
||||
// 為區域添加點擊事件,點擊後網格容器捲動到最頂部
|
||||
folderNameContainer.addEventListener('click', (event: MouseEvent) => {
|
||||
modenameContainer.addEventListener('click', (event: MouseEvent) => {
|
||||
// 只有當點擊的是頂部按鈕區域本身(而不是其中的按鈕)時才觸發捲動
|
||||
if (event.target === folderNameContainer) {
|
||||
if (event.target === modenameContainer) {
|
||||
event.preventDefault();
|
||||
// 取得網格容器
|
||||
const gridContainer = this.containerEl.querySelector('.ge-grid-container');
|
||||
|
|
@ -716,7 +721,7 @@ export class GridView extends ItemView {
|
|||
|
||||
// 建立可點擊的上層資料夾名稱
|
||||
const customFolderIcon = this.plugin.settings.customFolderIcon;
|
||||
const parentFolderLink = folderNameContainer.createEl('a', {
|
||||
const parentFolderLink = modenameContainer.createEl('a', {
|
||||
text: `${customFolderIcon} ${parentFolderName}`.trim(),
|
||||
cls: 'ge-parent-folder-link'
|
||||
});
|
||||
|
|
@ -801,10 +806,10 @@ export class GridView extends ItemView {
|
|||
});
|
||||
|
||||
// 分隔符號
|
||||
folderNameContainer.createEl('span', { text: ' > ' });
|
||||
modenameContainer.createEl('span', { text: ' > ' });
|
||||
|
||||
// 目前資料夾名稱
|
||||
folderNameContainer.createEl('span', { text: currentFolderName });
|
||||
modenameContainer.createEl('span', { text: currentFolderName });
|
||||
|
||||
if (Platform.isDesktop) {
|
||||
// 為上層按鈕添加拖曳目標功能
|
||||
|
|
@ -864,12 +869,12 @@ export class GridView extends ItemView {
|
|||
}
|
||||
} else if (!(this.searchQuery !== '' && this.searchAllFiles)) {
|
||||
// 顯示目前模式名稱
|
||||
const folderNameContainer = this.containerEl.createDiv('ge-foldername-content');
|
||||
const modenameContainer = this.containerEl.createDiv('ge-modename-content');
|
||||
|
||||
// 為區域添加點擊事件,點擊後網格容器捲動到最頂部
|
||||
folderNameContainer.addEventListener('click', (event: MouseEvent) => {
|
||||
modenameContainer.addEventListener('click', (event: MouseEvent) => {
|
||||
// 只有當點擊的是頂部按鈕區域本身(而不是其中的按鈕)時才觸發捲動
|
||||
if (event.target === folderNameContainer) {
|
||||
if (event.target === modenameContainer) {
|
||||
event.preventDefault();
|
||||
// 取得網格容器
|
||||
const gridContainer = this.containerEl.querySelector('.ge-grid-container');
|
||||
|
|
@ -953,17 +958,45 @@ export class GridView extends ItemView {
|
|||
}
|
||||
}
|
||||
|
||||
// 顯示模式名稱
|
||||
folderNameContainer.createEl('span', {
|
||||
text: `${modeIcon} ${modeName}`.trim(),
|
||||
cls: 'ge-mode-title'
|
||||
});
|
||||
// 顯示模式名稱 (若為自訂模式則提供點擊選單以快速切換)
|
||||
let modeTitleEl: HTMLElement;
|
||||
if (this.sourceMode.startsWith('custom-')) {
|
||||
// 使用可點擊的 <a> 元素
|
||||
modeTitleEl = modenameContainer.createEl('a', {
|
||||
text: `${modeIcon} ${modeName}`.trim(),
|
||||
cls: 'ge-parent-folder-link'
|
||||
});
|
||||
|
||||
// 點擊時顯示所有自訂模式選單
|
||||
modeTitleEl.addEventListener('click', (evt) => {
|
||||
const menu = new Menu();
|
||||
this.plugin.settings.customModes
|
||||
.filter(m => m.enabled ?? true) // 僅顯示啟用的自訂模式
|
||||
.forEach((m) => {
|
||||
menu.addItem(item => {
|
||||
item.setTitle(`${m.icon || '🧩'} ${m.displayName}`)
|
||||
.setChecked(m.internalName === this.sourceMode)
|
||||
.onClick(() => {
|
||||
// 切換至選取的自訂模式並重新渲染
|
||||
this.setSource(m.internalName, '', true);
|
||||
});
|
||||
});
|
||||
});
|
||||
menu.showAtMouseEvent(evt);
|
||||
});
|
||||
} else {
|
||||
// 其他模式維持原本的 span
|
||||
modeTitleEl = modenameContainer.createEl('span', {
|
||||
text: `${modeIcon} ${modeName}`.trim(),
|
||||
cls: 'ge-mode-title'
|
||||
});
|
||||
}
|
||||
|
||||
switch (this.sourceMode) {
|
||||
case 'tasks':
|
||||
folderNameContainer.createEl('span', { text: ' > ' });
|
||||
modenameContainer.createEl('span', { text: ' > ' });
|
||||
|
||||
const taskFilterSpan = folderNameContainer.createEl('a', { text: t(`${this.taskFilter}`), cls: 'ge-task-filter' });
|
||||
const taskFilterSpan = modenameContainer.createEl('a', { text: t(`${this.taskFilter}`), cls: 'ge-task-filter' });
|
||||
taskFilterSpan.addEventListener('click', (evt) => {
|
||||
const menu = new Menu();
|
||||
menu.addItem((item) => {
|
||||
|
|
@ -999,10 +1032,16 @@ export class GridView extends ItemView {
|
|||
break;
|
||||
default:
|
||||
if (this.sourceMode.startsWith('custom-')) {
|
||||
// 把 modenameContainer 加上所有自訂模式選項的選單
|
||||
|
||||
// 取得當前自訂模式
|
||||
const mode = this.plugin.settings.customModes.find(m => m.internalName === this.sourceMode);
|
||||
if (mode && mode.options && mode.options.length > 0) {
|
||||
folderNameContainer.createEl('span', { text: ' > ' });
|
||||
modenameContainer.createEl('span', { text: ' > ' });
|
||||
|
||||
if (this.customOptionIndex >= mode.options.length || this.customOptionIndex < -1) {
|
||||
this.customOptionIndex = -1;
|
||||
}
|
||||
|
||||
let subName: string | undefined;
|
||||
if (this.customOptionIndex === -1) {
|
||||
|
|
@ -1012,7 +1051,7 @@ export class GridView extends ItemView {
|
|||
subName = opt.name?.trim() || `${t('option')} ${this.customOptionIndex + 1}`;
|
||||
}
|
||||
|
||||
const subSpan = folderNameContainer.createEl('a', { text: subName ?? '-', cls: 'ge-sub-option' });
|
||||
const subSpan = modenameContainer.createEl('a', { text: subName ?? '-', cls: 'ge-sub-option' });
|
||||
subSpan.addEventListener('click', (evt) => {
|
||||
const menu = new Menu();
|
||||
// 預設選項
|
||||
|
|
@ -1045,8 +1084,8 @@ export class GridView extends ItemView {
|
|||
}
|
||||
} else if (this.searchQuery !== '' && this.searchAllFiles) {
|
||||
// 顯示全域搜尋名稱
|
||||
const folderNameContainer = this.containerEl.createDiv('ge-foldername-content');
|
||||
folderNameContainer.createEl('span', {
|
||||
const modenameContainer = this.containerEl.createDiv('ge-modename-content');
|
||||
modenameContainer.createEl('span', {
|
||||
text: `🔍 ${t('global_search')}`,
|
||||
cls: 'ge-mode-title'
|
||||
});
|
||||
|
|
@ -1226,7 +1265,7 @@ export class GridView extends ItemView {
|
|||
const titleContainer = contentArea.createDiv('ge-title-container');
|
||||
const customFolderIcon = this.plugin.settings.customFolderIcon;
|
||||
titleContainer.createEl('span', { cls: 'ge-title', text: `${customFolderIcon} ${folder.name}`.trim() });
|
||||
titleContainer.setAttribute('title', folder.name);
|
||||
setTooltip(folderEl, folder.name,{ placement: this.cardLayout === 'vertical' ? 'bottom' : 'right' });
|
||||
|
||||
// 檢查同名筆記是否存在
|
||||
const notePath = `${folder.path}/${folder.name}.md`;
|
||||
|
|
@ -1681,11 +1720,59 @@ export class GridView extends ItemView {
|
|||
|
||||
let pEl: HTMLElement | null = null;
|
||||
if (!this.minMode) {
|
||||
const summaryField = this.plugin.settings.noteSummaryField || 'summary';
|
||||
const summaryValue = metadata?.[summaryField];
|
||||
let summaryField = this.plugin.settings.noteSummaryField || 'summary';
|
||||
let summaryValue = metadata?.[summaryField];
|
||||
if (this.sourceMode.startsWith('custom-')) {
|
||||
// 自訂模式下,使用自訂的 fields 來顯示摘要
|
||||
const mode = this.plugin.settings.customModes.find(m => m.internalName === this.sourceMode);
|
||||
if (mode) {
|
||||
let fields = mode?.fields || '';
|
||||
// 當有選到子選項 (index >= 0) 而且 options 陣列確實存在
|
||||
if (this.customOptionIndex >= 0 &&
|
||||
mode.options &&
|
||||
this.customOptionIndex < mode.options.length) {
|
||||
const option = mode.options[this.customOptionIndex];
|
||||
fields = option.fields || '';
|
||||
}
|
||||
|
||||
// 如果 fields 不為空,則使用它來顯示摘要
|
||||
if (fields) {
|
||||
// 將 fields 以逗號分隔成陣列,並過濾掉空值
|
||||
const fieldList = fields.split(',').map(f => f.trim()).filter(Boolean);
|
||||
const fieldValues: string[] = [];
|
||||
|
||||
// 收集所有欄位值
|
||||
fieldList.forEach(field => {
|
||||
if (metadata?.[field] !== undefined && metadata?.[field] !== '' && metadata?.[field] !== null) {
|
||||
// 如果是數字,則加入千位分隔符號
|
||||
if (typeof metadata[field] === 'number') {
|
||||
metadata[field] = metadata[field].toLocaleString();
|
||||
}
|
||||
// 如果是陣列,則轉換為字串
|
||||
if (Array.isArray(metadata[field])) {
|
||||
metadata[field] = metadata[field].join(', ');
|
||||
}
|
||||
fieldValues.push(`${field}: ${metadata[field]}`);
|
||||
}
|
||||
});
|
||||
|
||||
// 如果有找到任何欄位值,則組合起來
|
||||
if (fieldValues.length > 0) {
|
||||
summaryValue = fieldValues.join('\n'); // 使用 | 分隔不同欄位
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (summaryValue) {
|
||||
pEl = contentArea.createEl('p', { text: summaryValue.trim() });
|
||||
if (!this.sourceMode.startsWith('custom-')) {
|
||||
// Frontmatter 有設定摘要值
|
||||
pEl = contentArea.createEl('p', { text: summaryValue.trim() });
|
||||
} else {
|
||||
// custom mode 有設定顯示欄位值
|
||||
pEl = contentArea.createEl('p', { text: summaryValue.trim() , cls: 'ge-content-area-p-field' });
|
||||
}
|
||||
} else {
|
||||
// Frontmatter 沒有設定摘要值,則使用內文
|
||||
let contentWithoutFrontmatter = '';
|
||||
if (summaryLength < 500) {
|
||||
contentWithoutFrontmatter = content.substring(frontMatterInfo.contentStart).slice(0, 500);
|
||||
|
|
@ -1737,7 +1824,8 @@ 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}` || '');
|
||||
setTooltip(contentArea as HTMLElement, `${titleEl.textContent}`, { placement: this.cardLayout === 'vertical' ? 'bottom' : 'right' })
|
||||
}
|
||||
|
||||
if (frontMatterInfo.exists) {
|
||||
|
|
@ -1783,6 +1871,8 @@ export class GridView extends ItemView {
|
|||
if (!this.minMode) {
|
||||
contentArea.createEl('p', { text: file.extension.toUpperCase() });
|
||||
}
|
||||
|
||||
setTooltip(fileEl as HTMLElement, `${file.name}`, { placement: this.cardLayout === 'vertical' ? 'bottom' : 'right' })
|
||||
}
|
||||
|
||||
// 顯示標籤(僅限 Markdown 檔案)
|
||||
|
|
@ -2208,6 +2298,11 @@ export class GridView extends ItemView {
|
|||
fileEl.addClass('ge-foldernote');
|
||||
}
|
||||
|
||||
//如果檔案是否處於置頂範圍,添加 ge-pinned 類別
|
||||
if (this.pinnedList.includes(file.name)) {
|
||||
fileEl.addClass('ge-pinned');
|
||||
}
|
||||
|
||||
// 創建左側內容區,包含圖示和標題
|
||||
const contentArea = fileEl.createDiv('ge-content-area');
|
||||
|
||||
|
|
@ -2216,7 +2311,9 @@ export class GridView extends ItemView {
|
|||
const extension = file.extension.toLowerCase();
|
||||
|
||||
// 檢查是否為媒體檔案,如果是則添加 ge-media-card 類別
|
||||
if (this.cardLayout === 'vertical' && (isImageFile(file) || isVideoFile(file))) {
|
||||
if (this.cardLayout === 'vertical' &&
|
||||
(isImageFile(file) || isVideoFile(file)) &&
|
||||
!this.minMode) {
|
||||
fileEl.addClass('ge-media-card');
|
||||
}
|
||||
|
||||
|
|
@ -2252,7 +2349,7 @@ export class GridView extends ItemView {
|
|||
const displayText = shouldShowExtension ? `${file.basename}.${file.extension}` : file.basename;
|
||||
const titleEl = titleContainer.createEl('span', { cls: 'ge-title', text: displayText });
|
||||
if (this.plugin.settings.multiLineTitle) titleEl.addClass('ge-multiline-title');
|
||||
titleEl.setAttribute('title', displayText);
|
||||
//titleEl.setAttribute('title', displayText);
|
||||
|
||||
// 創建圖片區域,但先不載入圖片
|
||||
if (!this.minMode) {
|
||||
|
|
@ -2347,6 +2444,7 @@ export class GridView extends ItemView {
|
|||
|
||||
// 獲取選中的檔案
|
||||
const selectedFiles = this.getSelectedFiles();
|
||||
let drag_filename = '';
|
||||
|
||||
// 添加拖曳資料
|
||||
if (selectedFiles.length > 1) {
|
||||
|
|
@ -2360,6 +2458,8 @@ export class GridView extends ItemView {
|
|||
// 添加檔案路徑列表
|
||||
event.dataTransfer?.setData('application/obsidian-grid-explorer-files',
|
||||
JSON.stringify(selectedFiles.map(f => f.path)));
|
||||
|
||||
drag_filename = `${selectedFiles.length} ${t('files')}`;
|
||||
} else {
|
||||
// 如果只有單個檔案被選中,使用檔案路徑
|
||||
const isMedia = isMediaFile(file);
|
||||
|
|
@ -2373,8 +2473,25 @@ export class GridView extends ItemView {
|
|||
// 添加檔案路徑列表
|
||||
event.dataTransfer?.setData('application/obsidian-grid-explorer-files',
|
||||
JSON.stringify([file.path]));
|
||||
|
||||
drag_filename = file.basename;
|
||||
}
|
||||
|
||||
const dragImage = document.createElement('div');
|
||||
dragImage.className = 'ge-custom-drag-preview';
|
||||
dragImage.textContent = drag_filename;
|
||||
|
||||
// 將元素暫時加入 DOM
|
||||
document.body.appendChild(dragImage);
|
||||
|
||||
// 設定拖曳圖示
|
||||
event.dataTransfer!.setDragImage(dragImage, 20, 20);
|
||||
|
||||
// 延遲移除元素(讓拖曳圖示正常顯示)
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(dragImage);
|
||||
}, 0);
|
||||
|
||||
// 設定拖曳效果
|
||||
event.dataTransfer!.effectAllowed = 'all';
|
||||
// 添加拖曳中的視覺效果
|
||||
|
|
|
|||
|
|
@ -30,25 +30,25 @@ export class CustomModeModal extends Modal {
|
|||
// 向下相容:使用第一個選項作為主要 dataviewCode
|
||||
let dataviewCode = this.mode ? this.mode.dataviewCode : '';
|
||||
let enabled = this.mode ? (this.mode.enabled ?? true) : true;
|
||||
let fields = this.mode ? this.mode.fields : '';
|
||||
|
||||
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_icon'))
|
||||
.setDesc(t('custom_mode_icon_desc'))
|
||||
.setName(t('custom_mode_display_name'))
|
||||
.setDesc(t('custom_mode_display_name_desc'))
|
||||
.addText(text => {
|
||||
text.setValue(icon)
|
||||
.onChange(value => {
|
||||
icon = value || '🧩';
|
||||
});
|
||||
// 設置固定寬度,適合單個圖示
|
||||
text.inputEl.style.width = '3em';
|
||||
text.inputEl.style.minWidth = '3em';
|
||||
})
|
||||
.addText(text => {
|
||||
text.setValue(displayName)
|
||||
.onChange(value => {
|
||||
displayName = value;
|
||||
});
|
||||
});
|
||||
|
||||
const dvSetting = new Setting(contentEl)
|
||||
|
|
@ -61,9 +61,11 @@ export class CustomModeModal extends Modal {
|
|||
dvSetting.settingEl.style.gap = '0.5rem';
|
||||
|
||||
dvSetting.addText(text => {
|
||||
text.setValue(name).onChange(v => name = v);
|
||||
text.setValue(name)
|
||||
.setPlaceholder(t('default'))
|
||||
.onChange(v => name = v);
|
||||
});
|
||||
|
||||
|
||||
dvSetting.addTextArea(text => {
|
||||
text.setValue(dataviewCode)
|
||||
.onChange(value => {
|
||||
|
|
@ -75,6 +77,14 @@ export class CustomModeModal extends Modal {
|
|||
text.inputEl.style.width = '100%';
|
||||
});
|
||||
|
||||
dvSetting.addText(text => {
|
||||
text.setValue(fields || '')
|
||||
.setPlaceholder(t('custom_mode_fields_placeholder'))
|
||||
.onChange(value => {
|
||||
fields = value;
|
||||
});
|
||||
});
|
||||
|
||||
// 讓 Text 與 TextArea 在 control 區域各佔一行
|
||||
dvSetting.controlEl.style.display = 'flex';
|
||||
dvSetting.controlEl.style.flexDirection = 'column';
|
||||
|
|
@ -115,6 +125,13 @@ export class CustomModeModal extends Modal {
|
|||
});
|
||||
text.inputEl.setAttr('rows', 6);
|
||||
text.inputEl.style.width = '100%';
|
||||
})
|
||||
.addText(text => {
|
||||
text.setPlaceholder(t('custom_mode_fields_placeholder'))
|
||||
.setValue(opt.fields || '')
|
||||
.onChange(val => {
|
||||
opt.fields = val;
|
||||
});
|
||||
});
|
||||
|
||||
// 移除按鈕(至少保留一個)
|
||||
|
|
@ -160,7 +177,8 @@ export class CustomModeModal extends Modal {
|
|||
name,
|
||||
dataviewCode,
|
||||
options: options,
|
||||
enabled
|
||||
enabled,
|
||||
fields
|
||||
});
|
||||
this.close();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { t } from './translations';
|
|||
export interface CustomModeOption {
|
||||
name: string;
|
||||
dataviewCode: string;
|
||||
fields?: string;
|
||||
}
|
||||
|
||||
export interface CustomMode {
|
||||
|
|
@ -16,6 +17,7 @@ export interface CustomMode {
|
|||
dataviewCode: string;
|
||||
options?: CustomModeOption[];
|
||||
enabled?: boolean; // 是否顯示此自訂模式,預設為 true
|
||||
fields?: string;
|
||||
}
|
||||
|
||||
export interface GallerySettings {
|
||||
|
|
|
|||
|
|
@ -148,13 +148,12 @@ export const TRANSLATIONS: Translations = {
|
|||
'import_error': '匯入失敗:無效的檔案格式',
|
||||
'edit_custom_mode': '編輯自訂模式',
|
||||
'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 代碼以取得檔案列表',
|
||||
'custom_mode_sub_options': '自訂模式子選項',
|
||||
'custom_mode_fields_placeholder': '輸入 frontmatter 欄位名稱,用逗號分隔 (如: date,category,status) (可選)',
|
||||
'show_bookmarks_mode': '顯示書籤模式',
|
||||
'show_search_mode': '顯示搜尋結果模式',
|
||||
'show_backlinks_mode': '顯示反向連結模式',
|
||||
|
|
@ -409,13 +408,12 @@ export const TRANSLATIONS: Translations = {
|
|||
'import_error': 'Import failed: Invalid file format',
|
||||
'edit_custom_mode': 'Edit Custom Mode',
|
||||
'custom_mode': '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',
|
||||
'custom_mode_sub_options': 'Custom Mode Sub Options',
|
||||
'custom_mode_fields_placeholder': 'Enter frontmatter field names, separated by commas (e.g. date,category,status) (optional)',
|
||||
'show_bookmarks_mode': 'Show bookmarks mode',
|
||||
'show_search_mode': 'Show search results mode',
|
||||
'show_backlinks_mode': 'Show backlinks mode',
|
||||
|
|
@ -670,13 +668,12 @@ export const TRANSLATIONS: Translations = {
|
|||
'import_error': '导入失败:无效的文件格式',
|
||||
'edit_custom_mode': '编辑自定义模式',
|
||||
'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 代码以获取文件列表',
|
||||
'custom_mode_sub_options': '自定义模式子选项',
|
||||
'custom_mode_fields_placeholder': '输入 frontmatter 栏位名称,用逗号分隔 (如: date,category,status) (可选)',
|
||||
'show_bookmarks_mode': '显示书签模式',
|
||||
'show_search_mode': '显示搜索结果模式',
|
||||
'show_backlinks_mode': '显示反向链接模式',
|
||||
|
|
@ -931,13 +928,12 @@ export const TRANSLATIONS: Translations = {
|
|||
'import_error': 'インポート失敗:無効なファイル形式',
|
||||
'edit_custom_mode': 'カスタムモードを編集',
|
||||
'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 コードを入力',
|
||||
'custom_mode_sub_options': 'カスタムモード子選択肢',
|
||||
'custom_mode_fields_placeholder': 'frontmatterのフィールド名をカンマ区切りで入力 (例: date,category,status) (任意)',
|
||||
'show_bookmarks_mode': 'ブックマークモードを表示',
|
||||
'show_search_mode': '検索結果モードを表示',
|
||||
'show_backlinks_mode': 'バックリンクモードを表示',
|
||||
|
|
@ -1193,13 +1189,12 @@ export const TRANSLATIONS: Translations = {
|
|||
'import_error': 'Ошибка импорта: недопустимый формат файла',
|
||||
'edit_custom_mode': 'Редактировать режим отображения',
|
||||
'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 для получения списка файлов',
|
||||
'custom_mode_sub_options': 'Подопции пользовательского режима',
|
||||
'custom_mode_fields_placeholder': 'Введите названия полей frontmatter через запятую (напр.: date,category,status) (необязательно)',
|
||||
'show_bookmarks_mode': 'Показывать режим закладок',
|
||||
'show_search_mode': 'Показывать режим результатов поиска',
|
||||
'show_backlinks_mode': 'Показывать режим обратных ссылок',
|
||||
|
|
@ -1454,13 +1449,12 @@ export const TRANSLATIONS: Translations = {
|
|||
'import_error': 'Помилка імпорту: недопустимий формат файлу',
|
||||
'edit_custom_mode': 'Редагувати режим відображення',
|
||||
'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 для отримання списку файлів',
|
||||
'custom_mode_sub_options': 'Підпараметри користувацького режиму',
|
||||
'custom_mode_fields_placeholder': 'Введіть назви полів frontmatter через кому (напр.: date,category,status) (необязательно)',
|
||||
'show_bookmarks_mode': 'Показувати режим закладок',
|
||||
'show_search_mode': 'Показувати режим результатів пошуку',
|
||||
'show_backlinks_mode': 'Показувати режим зворотних посилань',
|
||||
|
|
|
|||
93
styles.css
93
styles.css
|
|
@ -4,8 +4,6 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
/* 網格容器 Grid Container */
|
||||
|
|
@ -46,6 +44,10 @@
|
|||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.ge-grid-item:hover p {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* 摘要區域 Content Area */
|
||||
.ge-content-area {
|
||||
flex: 1;
|
||||
|
|
@ -134,20 +136,27 @@
|
|||
line-height: 1.4;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
height: 100%;
|
||||
-webkit-line-clamp: 3;
|
||||
line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ge-grid-item:hover p {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.ge-content-area p:empty {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ge-content-area-p-field,
|
||||
.ge-content-area .ge-content-area-p-field {
|
||||
display: block;
|
||||
-webkit-line-clamp: unset !important;
|
||||
line-clamp: unset !important;
|
||||
-webkit-box-orient: unset !important;
|
||||
white-space: pre-wrap;
|
||||
overflow: visible;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* 圖片區域 Image Area */
|
||||
.ge-image-area {
|
||||
width: var(--image-area-width);
|
||||
|
|
@ -182,7 +191,8 @@
|
|||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
height: var(--grid-item-height); /* 與一般網格一致,保持同排等高 */
|
||||
gap: 12px;
|
||||
gap: 0px;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
/* 摘要文字 Content Area */
|
||||
|
|
@ -190,18 +200,14 @@
|
|||
order: 1;
|
||||
flex: 1 1 auto; /* 使摘要區撐開,標籤可貼底 */
|
||||
flex-grow: 1; /* Add this line */
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
/* 圖片置中,滿版顯示 Image Area */
|
||||
.ge-vertical-card .ge-image-area {
|
||||
order: 3;
|
||||
width: 100%;
|
||||
height: var(--image-area-height);
|
||||
}
|
||||
|
||||
.ge-vertical-card .ge-image-area img,
|
||||
.ge-vertical-card .ge-image-area video {
|
||||
border-radius: 6px;
|
||||
height: var(--image-area-height);
|
||||
}
|
||||
|
||||
/* 標籤列置底 Tags Container */
|
||||
|
|
@ -219,6 +225,11 @@
|
|||
order: 3;
|
||||
}
|
||||
|
||||
.ge-vertical-card.ge-image-top .ge-image-area img,
|
||||
.ge-vertical-card.ge-image-top .ge-image-area video {
|
||||
border-radius: calc(var(--button-radius) - var(--border-width)) calc(var(--button-radius) - var(--border-width)) 0px 0px !important;
|
||||
}
|
||||
|
||||
/* 預設 bottom 可維持原有順序,以下為明確設置 */
|
||||
.ge-vertical-card.ge-image-bottom .ge-image-area {
|
||||
order: 3;
|
||||
|
|
@ -228,6 +239,11 @@
|
|||
order: 1;
|
||||
}
|
||||
|
||||
.ge-vertical-card.ge-image-bottom .ge-image-area img,
|
||||
.ge-vertical-card.ge-image-bottom .ge-image-area video {
|
||||
border-radius: 0px 0px calc(var(--button-radius) - var(--border-width)) calc(var(--button-radius) - var(--border-width)) !important;
|
||||
}
|
||||
|
||||
/* 鼠標懸停效果:整張卡片微抬升 */
|
||||
.ge-vertical-card .ge-grid-item:hover {
|
||||
transform: translateY(-2px);
|
||||
|
|
@ -292,6 +308,7 @@
|
|||
justify-content: center;
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.ge-video-thumbnail svg {
|
||||
|
|
@ -535,8 +552,8 @@
|
|||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
/* 資料夾名稱區域樣式 Folder Name Content */
|
||||
.ge-foldername-content {
|
||||
/* Mode名稱區域樣式 Mode Name Content */
|
||||
.ge-modename-content {
|
||||
justify-content: center;
|
||||
padding: 10px 8px 9px 8px;
|
||||
background-color: var(--background-secondary);
|
||||
|
|
@ -544,24 +561,23 @@
|
|||
font-size: var(--font-ui-medium);
|
||||
}
|
||||
|
||||
.ge-foldername-content span {
|
||||
.ge-modename-content span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.ge-foldername-content span.ge-mode-title {
|
||||
.ge-modename-content span.ge-mode-title {
|
||||
padding-left: 5px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
/* 為資料夾名稱、分隔符等元素添加間距 */
|
||||
.ge-foldername-content > *:nth-child(1) {
|
||||
.ge-modename-content > *:nth-child(1) {
|
||||
margin-left: 11px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.ge-foldername-content > *:nth-child(2) {
|
||||
.ge-modename-content > *:nth-child(2) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
|
|
@ -1193,18 +1209,18 @@
|
|||
width: 60px;
|
||||
}
|
||||
|
||||
/* 忽略資料夾設定 */
|
||||
/* 忽略資料夾設定 Ignored Folders Setting */
|
||||
.ge-ignored-folders-container {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* 忽略資料夾列表 */
|
||||
/* 忽略資料夾列表 Ignored Folders List */
|
||||
.ge-ignored-folders-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 忽略資料夾項目 */
|
||||
/* 忽略資料夾項目 Ignored Folder Item */
|
||||
.ge-ignored-folder-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -1216,7 +1232,7 @@
|
|||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
/* 忽略資料夾路徑 */
|
||||
/* 忽略資料夾路徑 Ignored Folder Path */
|
||||
.ge-ignored-folder-path {
|
||||
flex-grow: 1;
|
||||
margin-right: 8px;
|
||||
|
|
@ -1225,7 +1241,7 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 忽略資料夾刪除按鈕 */
|
||||
/* 忽略資料夾刪除按鈕 Ignored Folder Remove */
|
||||
.ge-ignored-folder-remove {
|
||||
background-color: var(--interactive-normal);
|
||||
color: var(--text-normal);
|
||||
|
|
@ -1240,13 +1256,34 @@
|
|||
background-color: var(--interactive-hover);
|
||||
}
|
||||
|
||||
/* 忽略資料夾模式的容器 */
|
||||
/* 忽略資料夾模式的容器 Ignored Folder Patterns Container */
|
||||
.ignored-folder-patterns-container {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* 忽略資料夾模式列表 */
|
||||
/* 忽略資料夾模式列表 Ignored Folder Patterns List */
|
||||
.ge-ignored-folder-patterns-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 拖曳預覽 Drag Preview */
|
||||
.ge-custom-drag-preview {
|
||||
position: absolute;
|
||||
top: -1000px; /* 隱藏在視窗外 */
|
||||
left: -1000px;
|
||||
font-size: var(--font-ui-small);
|
||||
white-space: nowrap;
|
||||
color: rgba(var(--mono-rgb-0), 0.9);
|
||||
background: rgba(var(--mono-rgb-100), 0.9);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
max-width: 150px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
{
|
||||
"2.5.6": "1.1.0",
|
||||
"2.5.7": "1.1.0",
|
||||
"2.6.0": "1.1.0",
|
||||
"2.6.1": "1.1.0"
|
||||
"2.6.2": "1.1.0"
|
||||
}
|
||||
Loading…
Reference in a new issue