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
51 changes: 51 additions & 0 deletions flask_backend/static/poster-download-btn.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.image-container .download-btn {
position: absolute !important;
bottom: 12px !important;
right: 12px !important;
top: auto !important;
left: auto !important;
background-color: rgba(0, 0, 0, 0.5) !important;
border: none !important;
border-radius: 50% !important;
-webkit-border-radius: 50% !important;
-moz-border-radius: 50% !important;
width: 40px !important;
height: 40px !important;
min-width: 40px !important;
min-height: 40px !important;
max-width: 40px !important;
max-height: 40px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
padding: 0 !important;
z-index: 1000 !important;
margin: 0 !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
box-sizing: border-box !important;
outline: none !important;
float: none !important;
pointer-events: auto !important;
overflow: hidden !important;
}

.image-container .download-btn:hover {
background-color: rgba(0, 0, 0, 0.7) !important;
transform: scale(1.1) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;
}

.image-container .download-btn:active {
transform: scale(0.95) !important;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) !important;
}

.image-container .download-btn svg {
width: 24px !important;
height: 24px !important;
fill: rgba(255, 255, 255, 1) !important;
display: block !important;
}

2 changes: 2 additions & 0 deletions flask_backend/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<!-- halfmoon css file -->
<link rel="stylesheet"
href="{{ url_for('static', filename='halfmoon/halfmoon.min.css') }}" />
{% block extra_css %}
{% endblock extra_css %}
<style>
.navbar .dropdown-menu {
position: absolute !important;
Expand Down
29 changes: 22 additions & 7 deletions flask_backend/templates/movie/movie_posters.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
{% for image in images %}
<img data-screening-id="{{ image['screening_id'] }}"
class="grid-item"
src="{{ image['url'] }}"
width="325"
height="{{ image['height'] }}"
onerror="removeOnError(event)"
{% if image['image_alt'] %}alt="{{ image['image_alt'] }}"{% endif %} />
<div class="grid-item image-container">
<img data-screening-id="{{ image['screening_id'] }}"
class="poster-image"
src="{{ image['url'] }}"
width="325"
height="{{ image['height'] }}"
onerror="removeOnError(event)"
{% if image['image_alt'] %}alt="{{ image['image_alt'] }}"{% endif %} />
<button class="download-btn"
onclick="downloadImage('{{ image['url'] }}'); event.stopPropagation();"
title="Baixar imagem"
aria-label="Baixar imagem"
type="button">
<svg xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="rgba(255, 255, 255, 1)">
<path d="M480-320 280-520l56-58 104 104v-326h80v326l104-104 56 58-200 200ZM240-160q-33 0-56.5-23.5T160-240v-120h80v120h480v-120h80v120q0 33-23.5 56.5T720-160H240Z" />
</svg>
</button>
</div>
{% endfor %}
93 changes: 77 additions & 16 deletions flask_backend/templates/movie/posters.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,33 @@
<meta name="description"
content="Acesse o mosaico com todos os posters dos filmes cadastrados no site.">
{% endblock meta_tags %}
{% block extra_css %}
<link rel="stylesheet"
href="{{ url_for('static', filename='poster-download-btn.css') }}">
{% endblock extra_css %}
<style>
.grid-item {
width: 325px;
}

.image-container {
position: relative !important;
display: inline-block !important;
width: 325px !important;
margin: 0 !important;
padding: 0 !important;
line-height: 0 !important;
vertical-align: top !important;
box-sizing: border-box !important;
}

.image-container .poster-image {
display: block !important;
width: 325px !important;
height: auto !important;
margin: 0 !important;
padding: 0 !important;
}
</style>
{% block header %}
<h1>
Expand Down Expand Up @@ -77,16 +100,18 @@ <h1>
const nextPageText = await nextPageFetch.text();
const parser = new DOMParser();
const doc = parser.parseFromString(nextPageText, 'text/html');
const nextPageImages = doc.querySelectorAll("img.grid-item");
const nextPageContainers = doc.querySelectorAll(".grid-item.image-container");

section.setAttribute('data-page', nextPage);
nextPageImages.forEach((img) => section.appendChild(img));
masonry.appended(nextPageImages);
nextPageContainers.forEach((container) => section.appendChild(container));
masonry.appended(nextPageContainers);

const imgsObserver = Array.from(section.getElementsByTagName('img'));
const imgsObserver = Array.from(section.querySelectorAll('img.poster-image'));
const lastImage = imgsObserver[imgsObserver.length - 1];
lastImage.setAttribute("data-observed", 1);
_observer.observe(lastImage);
if (lastImage) {
lastImage.setAttribute("data-observed", 1);
_observer.observe(lastImage);
}
// register that someone scrolled up to the next page
// using a goatcounter event
if (window.goatcounter) {
Expand All @@ -100,17 +125,50 @@ <h1>

function removeOnError(e) {
const img = e.target;
const container = img.closest('.image-container');
const isObserved = img.getAttribute("data-observed");
img.remove();
if (container) {
container.remove();
} else {
img.remove();
}
if (isObserved) {
const imgs = Array.from(document.querySelectorAll("section.grid img.grid-item"));
const lastImage = imgs[imgs.length - 1];
observer.observe(lastImage);
lastImage.setAttribute("data-observed", 1);
const imgs = Array.from(document.querySelectorAll("section.grid img.poster-image"));
if (imgs.length > 0) {
const lastImage = imgs[imgs.length - 1];
observer.observe(lastImage);
lastImage.setAttribute("data-observed", 1);
}
}
masonry.layout();
}

function downloadImage(imageUrl) {
// Se a URL é relativa, adiciona o domínio
const fullUrl = imageUrl.startsWith('http') ? imageUrl : window.location.origin + imageUrl;

fetch(fullUrl)
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
// Extrai o nome do arquivo da URL
const urlParts = imageUrl.split('/');
const filename = urlParts[urlParts.length - 1] || 'poster.jpg';
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
})
.catch(error => {
console.error('Erro ao baixar imagem:', error);
// Fallback: abre a imagem em nova aba
window.open(fullUrl, '_blank');
});
}


// Função para carregar uma nova página de imagens
async function fetchNextPage() {
Expand All @@ -132,11 +190,11 @@ <h1>
const nextPageText = await nextPageFetch.text();
const parser = new DOMParser();
const doc = parser.parseFromString(nextPageText, 'text/html');
const nextPageImages = doc.querySelectorAll("img.grid-item");
const nextPageContainers = doc.querySelectorAll(".grid-item.image-container");

section.setAttribute('data-page', nextPage);
nextPageImages.forEach((img) => section.appendChild(img));
masonry.appended(nextPageImages);
nextPageContainers.forEach((container) => section.appendChild(container));
masonry.appended(nextPageContainers);
}

document.addEventListener("DOMContentLoaded", async (event) => {
Expand All @@ -156,8 +214,11 @@ <h1>
observer = new IntersectionObserver(intersectionCallback, {
threshold: 1
});
const imgs = Array.from(document.querySelectorAll(".grid-item"));
observer.observe(imgs[imgs.length - 1]);
const imgs = Array.from(document.querySelectorAll("img.poster-image"));
if (imgs.length > 0) {
observer.observe(imgs[imgs.length - 1]);
imgs[imgs.length - 1].setAttribute("data-observed", 1);
}
});
</script>
<script src="{{ url_for('static', filename='imagesLoaded.js') }}"></script>
Expand Down