Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ async fn main() {
.at("/check_update.js")
.get(|_| resource(include_str!("../static/check_update.js"), "text/javascript", false).boxed());
app.at("/copy.js").get(|_| resource(include_str!("../static/copy.js"), "text/javascript", false).boxed());
app
.at("/downloadGallery.js")
.get(|_| resource(include_str!("../static/downloadGallery.js"), "text/javascript", false).boxed());

app.at("/commits.atom").get(|_| async move { proxy_commit_info().await }.boxed());
app.at("/instances.json").get(|_| async move { proxy_instances().await }.boxed());
Expand Down
78 changes: 78 additions & 0 deletions static/downloadGallery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Usage: downloadGallery(images, baseName)

(function() {
// Add js-enabled class for CSS detection
document.body.classList.add('js-enabled');

window.downloadGallery = async function(images, baseName) {
// Request permission to download multiple files
// This will show a browser prompt asking for permission
try {
// Create a single reusable download link
const a = document.createElement('a');
a.style.display = 'none';
document.body.appendChild(a);

// Use the File System Access API if available, otherwise fall back to individual downloads
for (let i = 0; i < images.length; i++) {
const imageUrl = images[i];
const filename = `${baseName}_${i + 1}.jpg`;

// Fetch the image as a blob
const response = await fetch(imageUrl);
const blob = await response.blob();

// Reuse the same link element
const url = URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);

// Small delay between downloads to avoid overwhelming the browser
if (i < images.length - 1) {
await new Promise(resolve => setTimeout(resolve, 100));
}
}

document.body.removeChild(a);
} catch (error) {
console.error('Error downloading gallery:', error);
alert('Failed to download some images. Please try downloading them individually.');
}
};

// Attach click handlers to gallery download links
function attachDownloadHandlers() {
document.querySelectorAll('.download_gallery > a').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();

// Find all gallery images
const post = link.closest('.post');
if (!post) return;

const gallery = post.querySelector('.gallery');
if (!gallery) return;

const images = [];
gallery.querySelectorAll('figure img').forEach(function(img) {
images.push(img.src);
});

if (images.length === 0) return;

// Get base name from data attribute
const baseName = link.getAttribute('data-base-name') || 'redlib_gallery';

downloadGallery(images, baseName);
});
});
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', attachDownloadHandlers);
} else {
attachDownloadHandlers();
}
})();
8 changes: 8 additions & 0 deletions static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,14 @@ a.search_subreddit:hover {
margin-right: 15px;
}

#post_links li.download_gallery {
display: none;
}

.js-enabled #post_links li.download_gallery {
display: list-item;
}

.desktop_item {
display: auto;
}
Expand Down
1 change: 1 addition & 0 deletions templates/post.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<script src="/highlighted.js" defer></script>
{% endif %}
{% endif %}
<script src="/downloadGallery.js" defer></script>
{% endblock %}

{% block subscriptions %}
Expand Down
9 changes: 9 additions & 0 deletions templates/utils.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ <h1 class="post_title">
</a>
</li>
{% endif %}
{% if post.post_type == "gallery" %}
<!-- Gallery download -->
<li class="download_gallery">
<a href="#" data-post-id="{{ post.id }}" data-base-name="redlib_{{ post.id }}">
<span class="mobile_item">dl</span>
<span class="desktop_item">download all ({{ post.gallery.len() }})</span>
</a>
</li>
{% endif %}
</ul>
<p>{{ post.upvote_ratio }}%<span id="upvoted"> Upvoted</span></p>
</div>
Expand Down
Loading