Skip to content

Commit 914af8a

Browse files
authored
Merge pull request #85 from geriyoco/main
🔖 Publish v0.4.0
2 parents 207dc34 + 2e305c8 commit 914af8a

File tree

12 files changed

+425
-176
lines changed

12 files changed

+425
-176
lines changed

CHANGELOG.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
# Change Log
22

3+
## [0.4.0] - 2022-07-30
4+
### Added
5+
- Buttons to expand/collapse all sub-folders in the gallery view
6+
- Tooltip containing metadata appears with a delay when hovering over an image in the gallery view
7+
8+
### Changed
9+
- Clicking (both single and double) an image on the gallery will focus the image on the Explorer side bar (see [here](https://github.com/geriyoco/vscode-image-gallery/pull/75#issue-1284403392)); a separate viewer will still be opened up
10+
311
## [0.2.7] - 2022-06-26
412
### Changed
513
- Single clicking an image in Gallery view opens up the image in Preview Mode
614
- Double clicking an image in Gallery view opens up the image (not in Preview Mode)
15+
716
### Fixed
8-
- Files within subfolders were not being sorted correctly
17+
- Files within sub-folders were not being sorted correctly
918

1019
## [0.2.6] - 2022-06-23
1120
### Added
12-
- Gallery supports collapsible subfolders
13-
- Sort subfolders and files by alphanumeric order
21+
- Gallery supports collapsible sub-folders
22+
- Sort sub-folders and files by alphanumeric order
1423

1524
## [0.2.5] - 2022-05-14
1625
### Added

README.md

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,22 @@
33

44
A light-weighted extension that brings you the best image browsing experience in VS Code.
55

6-
## Features
7-
- Smooth panning and zooming
8-
- Gallery view of images
9-
- Lazily load images as they are scrolled into view
10-
- Collapsible subfolders
11-
- Clicking on an image opens it up in a viewer tab
12-
- Auto-refresh when modified
6+
## Highlights
7+
- Excellent for image browsing on a remote server (e.g. via [SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh))
8+
- Gallery view of all images in the selected folder, including its sub-folders.
9+
- Smooth panning and zooming when viewing individual images.
10+
- Auto-refresh when images are modified, added, or deleted
1311
- Extension size less than 1 MB
1412

15-
### Panning and zooming
16-
![demo-editor](docs/demo-editor.gif)
17-
1813
### Gallery view
1914
![demo-gallery](docs/demo-gallery.gif)
2015

16+
### Panning and zooming
17+
![demo-editor](docs/demo-editor.gif)
18+
2119
See [here](docs/photo_credits.md) for the photo credits.
2220

2321
## Like this work?
24-
- ⭐ Star this project on [GitHub](https://github.com/geriyoco/vscode-image-gallery) and [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=GeriYoco.vscode-image-gallery)
25-
- ↪️ Share with your friends: [Twitter](https://twitter.com/intent/tweet?text=Just%20discovered%20this%20on%20the%20%23VSMarketplace%3A%20https%3A%2F%2Fmarketplace.visualstudio.com%2Fitems%3FitemName%3DGeriYoco.vscode-image-gallery), [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://marketplace.visualstudio.com/items?itemName=GeriYoco.vscode-image-gallery)
26-
- 🖥️ Contribute to the project
22+
- ⭐ Star this project on [GitHub](https://github.com/geriyoco/vscode-image-gallery) or [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=GeriYoco.vscode-image-gallery)
23+
- ↪️ Share it with your friends: [Twitter](https://twitter.com/intent/tweet?text=Just%20discovered%20this%20on%20the%20%23VSMarketplace%3A%20https%3A%2F%2Fmarketplace.visualstudio.com%2Fitems%3FitemName%3DGeriYoco.vscode-image-gallery), [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://marketplace.visualstudio.com/items?itemName=GeriYoco.vscode-image-gallery)
24+
- 🖥️ Contribute to the project: Start an [issue](https://github.com/geriyoco/vscode-image-gallery/issues/new) or [fork](https://github.com/geriyoco/vscode-image-gallery/fork) the repository.

media/gallery.css

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,31 @@ html {
2929
-webkit-backface-visibility: hidden;
3030
}
3131

32+
.tooltip {
33+
position: relative;
34+
}
35+
36+
.tooltiptext {
37+
position: absolute;
38+
z-index: 1;
39+
visibility: hidden;
40+
opacity: 0;
41+
transition: 0s opacity;
42+
width: 100%;
43+
background-color: black;
44+
color: #fff;
45+
text-align: left;
46+
padding: 10px;
47+
border-radius: 6px;
48+
white-space: pre;
49+
}
50+
51+
.tooltip:hover .tooltiptext {
52+
opacity: 0.8;
53+
visibility: visible;
54+
transition-delay: 1s;
55+
}
56+
3257
.image-container:hover {
3358
box-shadow: 0 0 10px white;
3459
}
@@ -69,12 +94,47 @@ html {
6994
border: 0;
7095
}
7196

97+
.folder:hover {
98+
box-shadow: 0 0px 10px hsl(60, 65%, 90%);
99+
}
100+
72101
.folder-title {
73102
padding-left: 10px;
74103
text-align: left;
75104
flex-grow: 1;
76105
}
77106

78-
.folder:hover {
79-
box-shadow: 0 0 10px hsl(60, 65%, 90%);
107+
.folder-arrow {
108+
margin-top: -2px;
109+
}
110+
111+
.folder-count {
112+
display: flex;
113+
flex-grow: 1;
114+
justify-content: right;
115+
align-items: center;
116+
color: white;
117+
font-family: arial;
118+
}
119+
120+
.toolbar {
121+
position: sticky;
122+
z-index: 1000;
123+
top: 0;
124+
padding: 15px;
125+
display: flex;
126+
flex-grow: 1;
127+
background-color: hsl(0, 0%, 17%);
128+
}
129+
130+
.codicon {
131+
padding: 3px;
132+
background-color: hsl(0, 0%, 17%);
133+
border: 0;
134+
color: white;
135+
}
136+
137+
.codicon:hover {
138+
background-color: hsl(180, 0%, 21%);
139+
border-radius: 5px;
80140
}

media/gallery.js

Lines changed: 106 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
21
(function () {
32
const vscode = acquireVsCodeApi();
43

4+
let gridElements = document.querySelectorAll(".grid");
5+
gridElements.forEach((gridElement) => {
6+
if (!gridElement.className.includes("grid-0")) {
7+
gridElement.style.display = "none";
8+
gridElement.previousElementSibling.firstElementChild.textContent = "⮞";
9+
}
10+
});
11+
512
let lazyloadImages = document.querySelectorAll(".lazy");
613
let imageObserver = new IntersectionObserver((entries, observer) => {
714
entries.forEach(entry => {
@@ -23,65 +30,144 @@
2330

2431
const clickHandler = (event, preview) => {
2532
let node = event && event.target;
26-
const folderHeader = ['folder','folder-title','folder-arrow'];
33+
const folderHeader = ['folder', 'folder-title', 'folder-arrow'];
2734
if (folderHeader.some(el => node.classList.contains(el))) {
28-
console.log(node);
2935
let id = '';
3036
if (node.classList.contains('folder')) {
3137
id = node.id;
3238
} else {
3339
let lastIndexToSplit = node.id.lastIndexOf('-');
3440
id = node.id.slice(0, lastIndexToSplit);
35-
3641
}
3742

3843
let folderGrid = document.getElementById(id + '-grid');
3944
let folderArrow = document.getElementById(id + '-arrow');
40-
console.log({folderGrid, folderArrow});
41-
folderGrid.style.display = folderGrid.style.display === "none" ? "" : "none";
45+
folderGrid.style.display = folderGrid.style.display === "none" ? "grid" : "none";
4246
folderArrow.textContent = folderArrow.textContent === "⮟" ? "⮞" : "⮟";
47+
48+
let expandAll = Array.from(gridElements).some(el => el.style.display === "none");
49+
if (expandAll) {
50+
let collapseAllButton = document.getElementsByClassName("codicon-collapse-all");
51+
if (collapseAllButton.length !== 0) {
52+
collapseAllButton[0].setAttribute("class", "codicon codicon-expand-all");
53+
}
54+
} else {
55+
let expandAllButton = document.getElementsByClassName("codicon-expand-all");
56+
if (expandAllButton.length !== 0) {
57+
expandAllButton[0].setAttribute("class", "codicon codicon-collapse-all");
58+
}
59+
}
60+
return;
4361
}
44-
if (!node.classList.contains('image')) { return; }
4562

46-
vscode.postMessage({
47-
command: 'vscodeImageGallery.openViewer',
48-
src: node.src,
49-
preview: preview,
50-
});
63+
if (node.classList.contains("codicon-expand-all")) {
64+
gridElements.forEach((gridElement) => {
65+
gridElement.style.display = "grid";
66+
gridElement.previousElementSibling.firstElementChild.textContent = "⮟";
67+
});
68+
node.setAttribute("class", "codicon codicon-collapse-all");
69+
return;
70+
}
71+
if (node.classList.contains("codicon-collapse-all")) {
72+
gridElements.forEach((gridElement) => {
73+
gridElement.style.display = "none";
74+
gridElement.previousElementSibling.firstElementChild.textContent = "⮞";
75+
});
76+
node.setAttribute("class", "codicon codicon-expand-all");
77+
return;
78+
}
79+
80+
if (!node.parentElement.classList.contains('image-container')) { return; }
81+
82+
if (node.parentElement.classList.contains('image-container')) {
83+
node.parentElement.childNodes.forEach((childNode) => {
84+
if (childNode.nodeName.toLowerCase() === 'img') {
85+
vscode.postMessage({
86+
command: 'vscodeImageGallery.openViewer',
87+
src: childNode.src,
88+
preview: preview,
89+
});
90+
}
91+
});
92+
return;
93+
}
94+
return;
5195
};
52-
document.addEventListener('click', event => clickHandler(event, preview=true), true);
53-
document.addEventListener('dblclick', event => clickHandler(event, preview=false), true);
96+
document.addEventListener('click', event => clickHandler(event, preview = true), { passive: true });
97+
document.addEventListener('dblclick', event => clickHandler(event, preview = false), { passive: true });
98+
99+
document.addEventListener('mouseover', event => {
100+
const node = event && event.target;
101+
if (!node.classList.contains('image')) { return; }
102+
103+
const lastDotIndex = node.src.lastIndexOf('.');
104+
const imgExtension = node.src.slice(lastDotIndex + 1, ).toUpperCase();
105+
const dateOptions = {
106+
year: 'numeric',
107+
month: 'long',
108+
day: 'numeric',
109+
hour: '2-digit',
110+
minute: '2-digit',
111+
second: '2-digit',
112+
};
113+
114+
const imgMetadata = JSON.parse(node.getAttribute('data-meta'));
115+
const createdDate = new Date(imgMetadata.ctime).toLocaleDateString('en-US', dateOptions);
116+
const modifiedDate = new Date(imgMetadata.mtime).toLocaleTimeString('en-US', dateOptions);
117+
let i = Math.floor(Math.log(imgMetadata.size) / Math.log(1024));
118+
let imgSize = (imgMetadata.size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['bytes', 'KB', 'MB', 'GB', 'TB'][i];
119+
120+
node.previousElementSibling.textContent = (
121+
`Dimensions: ${node.naturalHeight} x ${node.naturalWidth}
122+
Type: ${imgExtension}
123+
Size: ${imgSize}
124+
Created: ${createdDate}
125+
Modified: ${modifiedDate}`
126+
).replace(/^ +/gm, '');
127+
return;
128+
});
54129

55130
window.addEventListener('message', event => {
56131
const message = event.data;
57132

58133
switch (message.command) {
59134
case 'vscodeImageGallery.addImage':
60135
let addedTimestamp = new Date().getTime();
136+
let folder = Object.keys(message.imagesBySubFolders)[0];
61137
let imgNode = document.createElement("img");
62138
imgNode.setAttribute("class", "image loaded");
63139
imgNode.setAttribute("id", message.imgPath);
64140
imgNode.setAttribute("src", `${message.imgSrc}?t=${addedTimestamp}`);
65141
imgNode.setAttribute("data-src", `${message.imgSrc}?t=${addedTimestamp}`);
142+
imgNode.setAttribute("data-meta", `${JSON.stringify(message.imagesBySubFolders[folder][0].imgMetadata)}`);
66143

67144
let divNode = document.createElement("div");
68145
divNode.setAttribute("class", "filename");
69146
divNode.setAttribute("id", message.imgPath + "-filename");
70147
divNode.textContent = message.imgPath.split("/").pop();
71148

149+
let tooltipNode = document.createElement("span");
150+
tooltipNode.setAttribute("class", "tooltiptext");
151+
tooltipNode.setAttribute("id", message.imgPath + "-tooltip");
152+
72153
let containerNode = document.createElement("div");
73-
containerNode.setAttribute("class", "image-container");
154+
containerNode.setAttribute("class", "image-container tooltip");
155+
containerNode.appendChild(tooltipNode);
74156
containerNode.appendChild(imgNode);
75157
containerNode.appendChild(divNode);
76-
77-
let grid = document.getElementById(`${Object.keys(message.pathsBySubFolders)[0]}-grid`);
158+
159+
let grid = document.getElementById(`${folder}-grid`);
78160
grid.appendChild(containerNode);
161+
162+
let folderItemsCountOnAdd = document.getElementById(`${folder}-items-count`);
163+
folderItemsCountOnAdd.textContent = folderItemsCountOnAdd.textContent.replace(/\d+/g, (match, _) => parseInt(match) + 1);
79164
break;
80165
case 'vscodeImageGallery.changeImage':
81166
let changedTimestamp = new Date().getTime();
82167
let changeImage = document.getElementById(message.imgPath);
83168
changeImage.setAttribute("src", `${message.imgSrc}?t=${changedTimestamp}`);
84169
changeImage.setAttribute("data-src", `${message.imgSrc}?t=${changedTimestamp}`);
170+
changeImage.setAttribute("data-meta", `${JSON.stringify(message.imagesBySubFolders[folder][0].imgMetadata)}`);
85171

86172
let changeFilename = document.getElementById(message.imgPath + "-filename");
87173
changeFilename.setAttribute("class", "filename");
@@ -91,6 +177,9 @@
91177
case 'vscodeImageGallery.deleteImage':
92178
let deleteImage = document.getElementById(message.imgPath);
93179
deleteImage.parentElement.remove();
180+
181+
let folderItemsCountOnDel = document.getElementById(`${Object.keys(message.imagesBySubFolders)[0]}-items-count`);
182+
folderItemsCountOnDel.textContent = folderItemsCountOnDel.textContent.replace(/\d+/g, (match, _) => parseInt(match) - 1);
94183
break;
95184
}
96185
}, true);

media/viewer.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,4 @@
44
panzoom(container, {
55
minZoom: 0.6,
66
});
7-
8-
window.addEventListener('message', event => {
9-
const message = event.data;
10-
11-
switch (message.command) {
12-
case 'vscodeImageGalleryViewer.changeImage':
13-
let timestamp = new Date().getTime();
14-
let changeImage = document.getElementById("image");
15-
changeImage.setAttribute("src", message.imgSrc + "?t=" + timestamp);
16-
changeImage.setAttribute("data-src", message.imgSrc + "?t=" + timestamp);
17-
break;
18-
}
19-
}, true);
207
}());

0 commit comments

Comments
 (0)