mirror of
https://github.com/kennethreitz/photos.kennethreitz.org.git
synced 2026-06-05 06:46:13 +00:00
517357e5bb
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
117 lines
4.5 KiB
HTML
117 lines
4.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { background: #0a0a0a; color: #e8e8e8; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
|
|
a { color: #e8a820; text-decoration: none; }
|
|
|
|
.pills { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; padding: 8px; }
|
|
.pill { padding: 3px 10px; border-radius: 999px; font-size: 0.75rem; background: #141414; color: #888; border: 1px solid #2a2a2a; cursor: pointer; }
|
|
.pill:hover { border-color: #888; color: #e8e8e8; }
|
|
.pill-active { background: #e8a820; border-color: #e8a820; color: #000; font-weight: 600; }
|
|
.pill-active:hover { background: #f0be44; border-color: #f0be44; }
|
|
|
|
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; padding: 0 4px; }
|
|
.grid a { display: block; position: relative; aspect-ratio: 1; overflow: hidden; border-radius: 3px; }
|
|
.grid img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
.overlay { position: absolute; bottom: 0; left: 0; right: 0; padding: 3px 5px; background: linear-gradient(transparent, rgba(0,0,0,0.8)); color: rgba(255,255,255,0.7); font-size: 0.55rem; line-height: 1.3; }
|
|
|
|
.footer { text-align: center; padding: 8px; font-size: 0.75rem; }
|
|
.footer a { color: #888; }
|
|
.footer a:hover { color: #e8a820; }
|
|
|
|
.load-more { text-align: center; padding: 12px; }
|
|
.load-more button { background: #141414; border: 1px solid #2a2a2a; color: #888; padding: 6px 16px; border-radius: 4px; cursor: pointer; font-size: 0.75rem; font-family: inherit; }
|
|
.load-more button:hover { border-color: #888; color: #e8e8e8; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="pills" id="pills"></div>
|
|
<div class="grid" id="grid"></div>
|
|
<div class="load-more" id="load-more">
|
|
<button onclick="loadImages()">Load more</button>
|
|
</div>
|
|
<div class="footer">
|
|
<a href="https://photos.kennethreitz.org{% if year %}/?year={{ year }}{% endif %}" target="_blank">See more at photos.kennethreitz.org.</a>
|
|
</div>
|
|
|
|
<script>
|
|
var year = '{{ year|default:"" }}';
|
|
var offset = 0;
|
|
var loading = false;
|
|
var BATCH = 12;
|
|
var firstLoad = true;
|
|
|
|
fetch('/api/images/years').then(r => r.json()).then(function(years) {
|
|
var pills = document.getElementById('pills');
|
|
var all = document.createElement('a');
|
|
all.className = 'pill' + (!year ? ' pill-active' : '');
|
|
all.textContent = 'All';
|
|
all.href = '/embed/';
|
|
all.target = '_self';
|
|
pills.appendChild(all);
|
|
years.forEach(function(y) {
|
|
var a = document.createElement('a');
|
|
a.className = 'pill' + (year == y ? ' pill-active' : '');
|
|
a.textContent = y;
|
|
a.href = '/embed/?year=' + y;
|
|
a.target = '_self';
|
|
pills.appendChild(a);
|
|
});
|
|
});
|
|
|
|
function loadImages() {
|
|
loading = true;
|
|
var url = '/api/images/explore?limit=' + BATCH;
|
|
if (year) url += '&year=' + year;
|
|
fetch(url).then(r => r.json()).then(function(images) {
|
|
var grid = document.getElementById('grid');
|
|
images.forEach(function(img) {
|
|
var a = document.createElement('a');
|
|
a.href = 'https://photos.kennethreitz.org/images/' + img.id + '/';
|
|
a.target = '_blank';
|
|
|
|
var photo = document.createElement('img');
|
|
photo.src = img.thumbnail_small || img.thumbnail_medium;
|
|
photo.alt = img.title;
|
|
photo.loading = 'lazy';
|
|
a.appendChild(photo);
|
|
|
|
if (img.camera || img.focal_length || img.aperture) {
|
|
var ov = document.createElement('div');
|
|
ov.className = 'overlay';
|
|
var parts = [];
|
|
if (img.camera) parts.push(img.camera);
|
|
if (img.focal_length) parts.push(img.focal_length + 'mm');
|
|
if (img.aperture) parts.push('f/' + img.aperture);
|
|
ov.innerHTML = parts.join('<br>');
|
|
a.appendChild(ov);
|
|
}
|
|
|
|
grid.appendChild(a);
|
|
});
|
|
|
|
offset += images.length;
|
|
hasMore = images.length >= BATCH;
|
|
if (firstLoad) { BATCH = 48; firstLoad = false; }
|
|
loading = false;
|
|
});
|
|
}
|
|
|
|
var hasMore = true;
|
|
window.addEventListener('scroll', function() {
|
|
if (loading || !hasMore) return;
|
|
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 200) {
|
|
loadImages();
|
|
}
|
|
});
|
|
|
|
loadImages();
|
|
</script>
|
|
{{ analytics_code|safe }}
|
|
</body>
|
|
</html>
|