Compare commits

...

2 Commits

Author SHA1 Message Date
Marek
71f7a13729 update 2026-04-19 19:18:32 +02:00
Marek
a937331a93 update 2026-04-18 17:54:40 +02:00
2 changed files with 189 additions and 37 deletions

107
main.js
View File

@@ -2016,6 +2016,7 @@ var GridView = class extends import_obsidian7.ItemView {
this.plugin.settings.titleFontSize + "em" this.plugin.settings.titleFontSize + "em"
); );
this.gridItems = []; this.gridItems = [];
const gridInner = container.createDiv("ge-grid-inner");
if ( if (
this.sourceMode === "bookmarks" && this.sourceMode === "bookmarks" &&
!((_a = this.app.internalPlugins.plugins.bookmarks) == null !((_a = this.app.internalPlugins.plugins.bookmarks) == null
@@ -2038,7 +2039,7 @@ var GridView = class extends import_obsidian7.ItemView {
this.plugin.settings.showParentFolderItem && this.plugin.settings.showParentFolderItem &&
this.sourcePath !== "/" this.sourcePath !== "/"
) { ) {
const parentFolderEl = container.createDiv("ge-grid-item ge-folder-item"); const parentFolderEl = gridInner.createDiv("ge-grid-item ge-folder-item");
this.gridItems.push(parentFolderEl); this.gridItems.push(parentFolderEl);
const parentPath = const parentPath =
this.sourcePath.split("/").slice(0, -1).join("/") || "/"; this.sourcePath.split("/").slice(0, -1).join("/") || "/";
@@ -2049,6 +2050,38 @@ var GridView = class extends import_obsidian7.ItemView {
cls: "ge-title", cls: "ge-title",
text: `\u{1F4C1} ..`, text: `\u{1F4C1} ..`,
}); });
const parentFolderObj = this.app.vault.getAbstractFileByPath(parentPath);
if (parentFolderObj instanceof import_obsidian7.TFolder) {
const parentFiles = parentFolderObj.children
.filter((c) => c instanceof import_obsidian7.TFile)
.filter((f) => isDocumentFile(f) || isMediaFile(f));
const filteredParentFiles = this.sortFiles(this.ignoredFiles(parentFiles));
if (filteredParentFiles.length > 0) {
const filesList = parentFolderEl.createDiv("ge-folder-files");
for (const f of filteredParentFiles) {
const fileRow = filesList.createDiv("ge-folder-file-item");
fileRow.dataset.filePath = f.path;
const icon = fileRow.createDiv("ge-icon-container");
const ext = f.extension.toLowerCase();
let iconName = "file";
if (isImageFile(f)) iconName = "image";
else if (isVideoFile(f)) iconName = "play-circle";
else if (isAudioFile(f)) iconName = "music";
else if (ext === "pdf") iconName = "ge-pdf-file";
else if (ext === "canvas") iconName = "layout-dashboard";
else if (ext === "md" || ext === "txt") iconName = "file-text";
(0, import_obsidian8.setIcon)(icon, iconName);
fileRow.createEl("span", {
cls: "ge-folder-file-title",
text: f.basename,
});
fileRow.addEventListener("click", (e) => {
e.stopPropagation();
this.app.workspace.getLeaf(false).openFile(f);
});
}
}
}
parentFolderEl.addEventListener("click", () => { parentFolderEl.addEventListener("click", () => {
this.setSource("folder", parentPath); this.setSource("folder", parentPath);
this.clearSelection(); this.clearSelection();
@@ -2176,7 +2209,7 @@ var GridView = class extends import_obsidian7.ItemView {
}) })
.sort((a, b) => a.name.localeCompare(b.name)); .sort((a, b) => a.name.localeCompare(b.name));
for (const folder of subfolders) { for (const folder of subfolders) {
const folderEl = container.createDiv("ge-grid-item ge-folder-item"); const folderEl = gridInner.createDiv("ge-grid-item ge-folder-item");
this.gridItems.push(folderEl); this.gridItems.push(folderEl);
folderEl.dataset.folderPath = folder.path; folderEl.dataset.folderPath = folder.path;
if (import_obsidian7.Platform.isDesktop) { if (import_obsidian7.Platform.isDesktop) {
@@ -2218,6 +2251,35 @@ var GridView = class extends import_obsidian7.ItemView {
this.setSource("folder", folder.path); this.setSource("folder", folder.path);
this.clearSelection(); this.clearSelection();
}); });
const folderFiles = folder.children
.filter((c) => c instanceof import_obsidian7.TFile)
.filter((f) => isDocumentFile(f) || isMediaFile(f));
const filteredFolderFiles = this.sortFiles(this.ignoredFiles(folderFiles));
if (filteredFolderFiles.length > 0) {
const filesList = folderEl.createDiv("ge-folder-files");
for (const f of filteredFolderFiles) {
const fileRow = filesList.createDiv("ge-folder-file-item");
fileRow.dataset.filePath = f.path;
const icon = fileRow.createDiv("ge-icon-container");
const ext = f.extension.toLowerCase();
let iconName = "file";
if (isImageFile(f)) iconName = "image";
else if (isVideoFile(f)) iconName = "play-circle";
else if (isAudioFile(f)) iconName = "music";
else if (ext === "pdf") iconName = "ge-pdf-file";
else if (ext === "canvas") iconName = "layout-dashboard";
else if (ext === "md" || ext === "txt") iconName = "file-text";
(0, import_obsidian8.setIcon)(icon, iconName);
fileRow.createEl("span", {
cls: "ge-folder-file-title",
text: f.basename,
});
fileRow.addEventListener("click", (e) => {
e.stopPropagation();
this.app.workspace.getLeaf(false).openFile(f);
});
}
}
folderEl.addEventListener("contextmenu", (event) => { folderEl.addEventListener("contextmenu", (event) => {
event.preventDefault(); event.preventDefault();
const menu = new import_obsidian7.Menu(); const menu = new import_obsidian7.Menu();
@@ -2315,7 +2377,7 @@ var GridView = class extends import_obsidian7.ItemView {
} }
let files = []; let files = [];
if (this.searchQuery && this.sourceMode !== "random-note") { if (this.searchQuery && this.sourceMode !== "random-note") {
const loadingDiv = container.createDiv("ge-loading-indicator"); const loadingDiv = gridInner.createDiv("ge-loading-indicator");
loadingDiv.setText(t("searching")); loadingDiv.setText(t("searching"));
let allFiles = []; let allFiles = [];
if (this.searchAllFiles) { if (this.searchAllFiles) {
@@ -2455,52 +2517,43 @@ var GridView = class extends import_obsidian7.ItemView {
threshold: 0.1, threshold: 0.1,
} }
); );
let filesCardEl = null;
let filesListEl = null;
if (files.length > 0) {
filesCardEl = gridInner.createDiv("ge-grid-item ge-files-card");
filesListEl = filesCardEl.createDiv("ge-folder-files");
}
for (const file of files) { for (const file of files) {
const fileEl = container.createDiv("ge-grid-item"); const fileEl = filesListEl.createDiv("ge-folder-file-item");
this.gridItems.push(fileEl); this.gridItems.push(fileEl);
fileEl.dataset.filePath = file.path; fileEl.dataset.filePath = file.path;
const contentArea = fileEl.createDiv("ge-content-area");
const titleContainer = contentArea.createDiv("ge-title-container");
const extension = file.extension.toLowerCase(); const extension = file.extension.toLowerCase();
const iconContainer = fileEl.createDiv("ge-icon-container");
if (isImageFile(file)) { if (isImageFile(file)) {
const iconContainer = titleContainer.createDiv( iconContainer.addClass("ge-img");
"ge-icon-container ge-img"
);
(0, import_obsidian8.setIcon)(iconContainer, "image"); (0, import_obsidian8.setIcon)(iconContainer, "image");
} else if (isVideoFile(file)) { } else if (isVideoFile(file)) {
const iconContainer = titleContainer.createDiv( iconContainer.addClass("ge-video");
"ge-icon-container ge-video"
);
(0, import_obsidian8.setIcon)(iconContainer, "play-circle"); (0, import_obsidian8.setIcon)(iconContainer, "play-circle");
} else if (isAudioFile(file)) { } else if (isAudioFile(file)) {
const iconContainer = titleContainer.createDiv( iconContainer.addClass("ge-audio");
"ge-icon-container ge-audio"
);
(0, import_obsidian8.setIcon)(iconContainer, "music"); (0, import_obsidian8.setIcon)(iconContainer, "music");
} else if (extension === "pdf") { } else if (extension === "pdf") {
const iconContainer = titleContainer.createDiv( iconContainer.addClass("ge-pdf");
"ge-icon-container ge-pdf"
);
(0, import_obsidian8.setIcon)(iconContainer, "ge-pdf-file"); (0, import_obsidian8.setIcon)(iconContainer, "ge-pdf-file");
} else if (extension === "canvas") { } else if (extension === "canvas") {
const iconContainer = titleContainer.createDiv( iconContainer.addClass("ge-canvas");
"ge-icon-container ge-canvas"
);
(0, import_obsidian8.setIcon)(iconContainer, "layout-dashboard"); (0, import_obsidian8.setIcon)(iconContainer, "layout-dashboard");
} else if (extension === "md" || extension === "txt") { } else if (extension === "md" || extension === "txt") {
const iconContainer = titleContainer.createDiv("ge-icon-container");
(0, import_obsidian8.setIcon)(iconContainer, "file-text"); (0, import_obsidian8.setIcon)(iconContainer, "file-text");
} else { } else {
const iconContainer = titleContainer.createDiv("ge-icon-container");
(0, import_obsidian8.setIcon)(iconContainer, "file"); (0, import_obsidian8.setIcon)(iconContainer, "file");
} }
const titleEl = titleContainer.createEl("span", { const titleEl = fileEl.createEl("span", {
cls: "ge-title", cls: "ge-folder-file-title",
text: file.basename, text: file.basename,
}); });
titleEl.setAttribute("title", file.basename); titleEl.setAttribute("title", file.basename);
fileEl.createDiv("ge-image-area");
observer.observe(fileEl);
fileEl.addEventListener("click", (event) => { fileEl.addEventListener("click", (event) => {
const index = this.gridItems.indexOf(fileEl); const index = this.gridItems.indexOf(fileEl);
if (index >= 0) { if (index >= 0) {

View File

@@ -18,15 +18,50 @@
/* Grid 樣式 */ /* Grid 樣式 */
.ge-grid-container { .ge-grid-container {
display: grid; display: block;
grid-template-columns: repeat(auto-fill, minmax(var(--grid-item-width, 300px), 1fr)); padding: 0 !important;
gap: 12px;
padding: 12px !important;
align-items: start;
align-content: start;
background: var(--background-secondary) !important; background: var(--background-secondary) !important;
flex: 1; flex: 1 1 0;
width: 100%;
min-width: 0;
max-width: 100%;
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
container-type: inline-size;
}
.ge-grid-inner {
display: block;
column-width: 320px;
column-gap: 12px;
padding: 12px;
box-sizing: border-box;
width: 100%;
}
@container (max-width: 340px) {
.ge-grid-inner {
column-count: 1;
}
}
@container (min-width: 340px) and (max-width: 660px) {
.ge-grid-inner {
column-count: 2;
}
}
@container (min-width: 660px) and (max-width: 990px) {
.ge-grid-inner {
column-count: 3;
}
}
@container (min-width: 990px) and (max-width: 1320px) {
.ge-grid-inner {
column-count: 4;
}
} }
.is-mobile .ge-grid-container::-webkit-scrollbar { .is-mobile .ge-grid-container::-webkit-scrollbar {
@@ -43,7 +78,24 @@
transition: transform 0.2s, box-shadow 0.2s; transition: transform 0.2s, box-shadow 0.2s;
display: flex; display: flex;
gap: 14px; gap: 14px;
height: var(--grid-item-height); width: auto;
max-width: 100%;
min-width: 0;
box-sizing: border-box;
break-inside: avoid;
margin-bottom: 12px;
overflow: hidden;
}
.ge-grid-item.ge-files-card {
cursor: default;
min-height: 0;
}
.ge-grid-item.ge-files-card:hover {
transform: none;
background-color: var(--background-primary);
box-shadow: none;
} }
.ge-grid-item:hover { .ge-grid-item:hover {
@@ -174,7 +226,9 @@
padding: 7px; padding: 7px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
transition: all 0.2s ease; transition: all 0.2s ease;
height: 100%; height: auto;
flex-direction: column;
gap: 6px;
} }
.ge-grid-item.ge-folder-item:hover { .ge-grid-item.ge-folder-item:hover {
@@ -189,6 +243,10 @@
.ge-grid-item.ge-folder-item .ge-title { .ge-grid-item.ge-folder-item .ge-title {
color: var(--text-normal); color: var(--text-normal);
overflow: visible;
text-overflow: clip;
white-space: normal;
word-break: break-word;
} }
/* 上層資料夾的特殊樣式 */ /* 上層資料夾的特殊樣式 */
@@ -203,7 +261,48 @@
/* 調整資料夾項目的高度 */ /* 調整資料夾項目的高度 */
.ge-grid-item.ge-folder-item .ge-content-area { .ge-grid-item.ge-folder-item .ge-content-area {
min-height: 0px; min-height: 0px;
justify-content: center; justify-content: flex-start;
}
.ge-folder-files {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 4px;
width: 100%;
min-width: 0;
}
.ge-folder-file-item {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
background-color: var(--background-primary);
border: 1px solid var(--background-modifier-border);
font-size: 0.85em;
max-width: 100%;
min-width: 0;
box-sizing: border-box;
}
.ge-folder-file-item:hover {
background-color: var(--background-modifier-hover);
}
.ge-folder-file-item .ge-icon-container {
flex-shrink: 0;
width: 14px;
height: 14px;
}
.ge-folder-file-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
} }
.ge-grid-item.ge-folder-item .ge-title-container { .ge-grid-item.ge-folder-item .ge-title-container {