This commit is contained in:
Aodhan
2025-06-20 22:27:24 +01:00
parent c09461f58f
commit 324a21800a
10 changed files with 1022 additions and 1866 deletions

194
js/main.js Normal file
View File

@@ -0,0 +1,194 @@
import { showToast, updateImageInfo } from './utils.js';
document.addEventListener('DOMContentLoaded', () => {
const state = {
currentImageInfo: null,
currentOrientation: 'all',
isLoading: false,
isDragging: false,
startX: 0,
startY: 0,
moveX: 0,
moveY: 0,
touchStartTime: 0,
hasMoved: false,
};
const card = document.getElementById('current-card');
const lastActionText = document.getElementById('last-action');
const orientationFilters = document.querySelector('.orientation-filters');
const modal = document.getElementById('fullscreen-modal');
const fullscreenImage = document.getElementById('fullscreen-image');
const closeModal = document.querySelector('.close-modal');
const SWIPE_THRESHOLD = 100;
const performSwipe = (direction) => {
if (!state.currentImageInfo) return;
card.classList.add(`swipe-${direction}`);
lastActionText.textContent = `Last action: Swiped ${direction}`;
const toastMap = { left: 'Discarded', right: 'Kept', up: 'Favorited', down: 'Marked for review' };
showToast(toastMap[direction] || 'Action');
recordSelection(state.currentImageInfo, direction);
setTimeout(() => {
card.classList.remove(`swipe-${direction}`);
loadNewImage();
}, 500);
};
const recordSelection = (imageInfo, action) => {
fetch('/selection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
image_path: imageInfo.path,
resolution: imageInfo.resolution,
action,
}),
}).catch(error => console.error('Error recording selection:', error));
};
const loadNewImage = () => {
if (state.isLoading) return;
state.isLoading = true;
card.classList.add('loading');
fetch(`/random-image?orientation=${state.currentOrientation}&t=${new Date().getTime()}`)
.then(response => response.json())
.then(data => {
state.isLoading = false;
card.classList.remove('loading');
if (data && data.path) {
state.currentImageInfo = data;
const cardImage = card.querySelector('img');
cardImage.src = data.path;
updateImageInfo(data);
adjustContainerToImage(data.orientation);
} else {
card.innerHTML = `<div class="no-images-message">${data.message || 'No more images.'}</div>`;
state.currentImageInfo = null;
}
})
.catch(error => {
console.error('Error fetching image:', error);
state.isLoading = false;
card.classList.remove('loading');
card.innerHTML = '<div class="no-images-message">Error loading image.</div>';
});
};
const adjustContainerToImage = (orientation) => {
const container = document.querySelector('.swipe-container');
if (window.innerWidth < 992) { // Only on desktop
container.style.transition = 'all 0.5s ease-in-out';
if (orientation === 'landscape') {
container.style.flex = '4';
} else {
container.style.flex = '2';
}
}
};
const handlePointerDown = (x, y) => {
state.isDragging = true;
state.startX = x;
state.startY = y;
state.hasMoved = false;
state.touchStartTime = Date.now();
card.classList.add('swiping');
};
const handlePointerMove = (x, y) => {
if (!state.isDragging) return;
state.moveX = x - state.startX;
state.moveY = y - state.startY;
if (Math.abs(state.moveX) > 10 || Math.abs(state.moveY) > 10) {
state.hasMoved = true;
}
card.style.transform = `translate(${state.moveX}px, ${state.moveY}px) rotate(${state.moveX * 0.05}deg)`;
};
const handlePointerUp = () => {
if (!state.isDragging) return;
state.isDragging = false;
card.classList.remove('swiping');
const absX = Math.abs(state.moveX);
const absY = Math.abs(state.moveY);
if (state.hasMoved && (absX > SWIPE_THRESHOLD || absY > SWIPE_THRESHOLD)) {
if (absX > absY) {
performSwipe(state.moveX > 0 ? 'right' : 'left');
} else {
performSwipe(state.moveY > 0 ? 'down' : 'up');
}
} else {
card.style.transform = '';
}
state.moveX = 0;
state.moveY = 0;
};
card.addEventListener('mousedown', e => handlePointerDown(e.clientX, e.clientY));
document.addEventListener('mousemove', e => handlePointerMove(e.clientX, e.clientY));
document.addEventListener('mouseup', () => handlePointerUp());
card.addEventListener('touchstart', e => handlePointerDown(e.touches[0].clientX, e.touches[0].clientY), { passive: true });
card.addEventListener('touchmove', e => handlePointerMove(e.touches[0].clientX, e.touches[0].clientY), { passive: true });
card.addEventListener('touchend', () => handlePointerUp());
document.getElementById('btn-left').addEventListener('click', () => performSwipe('left'));
document.getElementById('btn-right').addEventListener('click', () => performSwipe('right'));
document.getElementById('btn-up').addEventListener('click', () => performSwipe('up'));
document.getElementById('btn-down').addEventListener('click', () => performSwipe('down'));
orientationFilters.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON' && !e.target.classList.contains('active')) {
orientationFilters.querySelector('.active').classList.remove('active');
e.target.classList.add('active');
state.currentOrientation = e.target.dataset.orientation;
loadNewImage();
}
});
card.addEventListener('click', () => {
if (!state.hasMoved && state.currentImageInfo) {
fullscreenImage.src = state.currentImageInfo.path;
document.getElementById('modal-resolution').textContent = `Resolution: ${state.currentImageInfo.resolution}`;
document.getElementById('modal-filename').textContent = `Filename: ${state.currentImageInfo.filename || 'N/A'}`;
document.getElementById('modal-creation-date').textContent = `Creation Date: ${state.currentImageInfo.creation_date || 'N/A'}`;
modal.style.display = 'flex';
}
});
closeModal.addEventListener('click', () => modal.style.display = 'none');
modal.addEventListener('click', (e) => {
if (e.target === modal) {
modal.style.display = 'none';
}
});
document.addEventListener('keydown', (e) => {
if (modal.style.display === 'flex' && e.key === 'Escape') {
modal.style.display = 'none';
return;
}
if (modal.style.display !== 'flex') {
switch (e.key) {
case 'ArrowLeft': performSwipe('left'); break;
case 'ArrowRight': performSwipe('right'); break;
case 'ArrowUp': performSwipe('up'); break;
case 'ArrowDown': performSwipe('down'); break;
}
}
});
loadNewImage();
});