620 lines
24 KiB
JavaScript
620 lines
24 KiB
JavaScript
(function ($) {
|
||
'use strict';
|
||
|
||
if (typeof mcGalleryPro === 'undefined') {
|
||
console.error('MC Gallery Pro: Configuration not found.');
|
||
return;
|
||
}
|
||
|
||
const api = mcGalleryPro.restBase.replace(/\/?$/, '');
|
||
const ajaxUrl = mcGalleryPro.uploadUrl;
|
||
const maxUploads = mcGalleryPro.maxUploads || 5;
|
||
|
||
let originalBodyPadding = '';
|
||
let scrollbarWidth = 0;
|
||
|
||
let sessionData = {
|
||
token: null,
|
||
username: null,
|
||
serverId: null,
|
||
verified: false
|
||
};
|
||
|
||
let selectedFiles = [];
|
||
|
||
function getScrollbarWidth() {
|
||
if (scrollbarWidth > 0) return scrollbarWidth;
|
||
const outer = document.createElement('div');
|
||
outer.style.visibility = 'hidden';
|
||
outer.style.width = '100px';
|
||
outer.style.msOverflowStyle = 'scrollbar';
|
||
document.body.appendChild(outer);
|
||
|
||
const widthNoScroll = outer.offsetWidth;
|
||
outer.style.overflow = 'scroll';
|
||
|
||
const inner = document.createElement('div');
|
||
inner.style.width = '100%';
|
||
outer.appendChild(inner);
|
||
|
||
const widthWithScroll = inner.offsetWidth;
|
||
outer.parentNode.removeChild(outer);
|
||
|
||
scrollbarWidth = widthNoScroll - widthWithScroll;
|
||
return scrollbarWidth;
|
||
}
|
||
|
||
function showFeedback(msg, type = 'info') {
|
||
const $fb = $('#mc-feedback-msg');
|
||
$fb.removeClass('mc-msg-success mc-msg-error');
|
||
|
||
if (type === 'success') {
|
||
$fb.addClass('mc-msg-success');
|
||
} else if (type === 'error') {
|
||
$fb.addClass('mc-msg-error');
|
||
}
|
||
|
||
$fb.html(msg).fadeIn(300);
|
||
}
|
||
|
||
function switchStep(stepNum) {
|
||
$('.mc-step').removeClass('active');
|
||
$(`.mc-step[data-step="${stepNum}"]`).addClass('active');
|
||
}
|
||
|
||
function resetModal() {
|
||
$('#mc-upload-username').val('');
|
||
$('#mc-token-text').text('Waiting...');
|
||
$('#mc-upload-file').val('');
|
||
$('#mc-file-name').text('Keine Bilder gewählt').css('color', '');
|
||
$('.mc-file-drop').css('border-color', '').css('background', '');
|
||
$('#mc-feedback-msg').hide().empty();
|
||
$('#mc-file-preview').empty();
|
||
$('#mc-upload-progress').hide();
|
||
$('#mc-btn-upload-more').hide();
|
||
$('#mc-btn-final-upload').show();
|
||
selectedFiles = [];
|
||
sessionData = {
|
||
token: null,
|
||
username: null,
|
||
serverId: null,
|
||
verified: false
|
||
};
|
||
switchStep(1);
|
||
}
|
||
|
||
function loadServers() {
|
||
const $select = $('#mc-upload-server');
|
||
if (!$select.length) return;
|
||
|
||
$select.html('<option>Lade Server...</option>').prop('disabled', true);
|
||
|
||
fetch(api + '/servers')
|
||
.then(response => {
|
||
if (!response.ok) throw new Error('Server response not OK');
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
if (data.success && Array.isArray(data.data) && data.data.length > 0) {
|
||
$select.empty().prop('disabled', false);
|
||
data.data.forEach(server => {
|
||
const displayText = server.host
|
||
? `${server.title} (${server.host})`
|
||
: server.title;
|
||
$select.append($('<option>')
|
||
.val(server.id)
|
||
.text(displayText)
|
||
);
|
||
});
|
||
} else {
|
||
$select.html('<option>Keine aktiven Server</option>');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Failed to load servers:', error);
|
||
$select.html('<option>Fehler beim Laden</option>');
|
||
});
|
||
}
|
||
|
||
function loadAlbums() {
|
||
const $select = $('#mc-upload-album');
|
||
$select.html('<option value="">Kein Album</option>').prop('disabled', true);
|
||
|
||
if (!sessionData.token || !sessionData.verified) return;
|
||
|
||
fetch(api + '/albums', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
token: sessionData.token,
|
||
username: sessionData.username,
|
||
server_id: sessionData.serverId
|
||
})
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success && data.data.albums) {
|
||
$select.prop('disabled', false);
|
||
data.data.albums.forEach(album => {
|
||
$select.append($('<option>')
|
||
.val(album.id)
|
||
.text(album.title)
|
||
);
|
||
});
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Failed to load albums:', error);
|
||
});
|
||
}
|
||
|
||
// FIX 1: View Counter Zähler erhöhen
|
||
function incrementViewCount(attachId, $badgeElement) {
|
||
$.post(ajaxUrl, {
|
||
action: 'mc_gallery_increment_view',
|
||
attach_id: attachId,
|
||
nonce: mcGalleryPro.nonce
|
||
}, function(response) {
|
||
if (response.success && response.data && typeof response.data.views !== 'undefined') {
|
||
// Badge sofort aktualisieren (Animation optional)
|
||
$badgeElement.find('.mc-views-count').text(response.data.views);
|
||
}
|
||
}).fail(function() {
|
||
console.error('Failed to increment view count');
|
||
});
|
||
}
|
||
|
||
function renderFilePreview() {
|
||
const $preview = $('#mc-file-preview');
|
||
$preview.empty();
|
||
|
||
if (selectedFiles.length === 0) return;
|
||
|
||
selectedFiles.forEach((file, index) => {
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const $item = $(`
|
||
<div class="mc-preview-item" data-index="${index}">
|
||
<img src="${e.target.result}" alt="${file.name}">
|
||
<button class="mc-preview-remove" data-index="${index}" title="Entfernen">×</button>
|
||
<span class="mc-preview-name">${file.name}</span>
|
||
</div>
|
||
`);
|
||
$preview.append($item);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
});
|
||
|
||
updateFileCount();
|
||
}
|
||
|
||
function updateFileCount() {
|
||
const count = selectedFiles.length;
|
||
|
||
$('#mc-file-name').css('color', '').removeClass('mc-msg-error-text');
|
||
$('#mc-btn-final-upload').prop('disabled', false).removeClass('mc-btn-disabled');
|
||
$('.mc-file-drop').css({
|
||
'border-color': '',
|
||
'background': ''
|
||
});
|
||
|
||
if (count === 0) {
|
||
$('#mc-file-name').text('Keine Bilder gewählt');
|
||
} else if (count > maxUploads) {
|
||
$('#mc-file-name')
|
||
.html(`<strong>${count} / ${maxUploads} Bilder</strong> (Zu viele!)`)
|
||
.css('color', 'var(--mc-error)')
|
||
.addClass('mc-msg-error-text');
|
||
$('#mc-btn-final-upload')
|
||
.prop('disabled', true)
|
||
.addClass('mc-btn-disabled');
|
||
$('.mc-file-drop').css({
|
||
'border-color': 'var(--mc-error)',
|
||
'background': 'rgba(239, 68, 68, 0.05)'
|
||
});
|
||
} else {
|
||
$('#mc-file-name')
|
||
.html(`<strong>${count} Bild${count > 1 ? 'er' : ''}</strong> ausgewählt`)
|
||
.css('color', 'var(--mc-text-main)');
|
||
$('.mc-file-drop').css({
|
||
'border-color': 'var(--mc-primary)',
|
||
'background': 'rgba(16, 185, 129, 0.05)'
|
||
});
|
||
}
|
||
|
||
$('#mc-upload-btn-text').text(count > 0 ? `${count} Bild${count > 1 ? 'er' : ''} hochladen` : 'Bilder hochladen');
|
||
}
|
||
|
||
function openModal() {
|
||
$('#mc-upload-modal').addClass('open').attr('aria-hidden', 'false');
|
||
originalBodyPadding = $('body').css('padding-right');
|
||
const width = getScrollbarWidth();
|
||
|
||
$('html').css('overflow', 'hidden');
|
||
$('body').css('padding-right', (parseInt(originalBodyPadding) || 0) + width + 'px');
|
||
|
||
resetModal();
|
||
loadServers();
|
||
}
|
||
|
||
function closeModal() {
|
||
$('#mc-upload-modal').removeClass('open').attr('aria-hidden', 'true');
|
||
$('html').css('overflow', '');
|
||
$('body').css('padding-right', originalBodyPadding);
|
||
|
||
setTimeout(resetModal, 300);
|
||
}
|
||
|
||
$(document).ready(function () {
|
||
|
||
loadServers();
|
||
|
||
$('#mc-open-upload-modal').on('click', function(e) {
|
||
e.preventDefault();
|
||
openModal();
|
||
});
|
||
|
||
$('.mc-modal-close, .mc-modal-backdrop').on('click', function() {
|
||
closeModal();
|
||
});
|
||
|
||
$(document).on('keydown', function(e) {
|
||
if (e.key === 'Escape' && $('#mc-upload-modal').hasClass('open')) {
|
||
closeModal();
|
||
}
|
||
});
|
||
|
||
$('#mc-btn-generate').on('click', function () {
|
||
const username = $('#mc-upload-username').val().trim();
|
||
const serverId = $('#mc-upload-server').val();
|
||
|
||
if (!username) {
|
||
showFeedback('Bitte gib deinen Minecraft-Namen ein.', 'error');
|
||
$('#mc-upload-username').focus();
|
||
return;
|
||
}
|
||
|
||
if (!serverId || serverId === '') {
|
||
showFeedback('Bitte wähle einen Server aus.', 'error');
|
||
return;
|
||
}
|
||
|
||
const $btn = $(this);
|
||
const originalText = $btn.text();
|
||
$btn.prop('disabled', true).html('<span class="mc-loading"></span> Starte Session...');
|
||
|
||
fetch(api + '/request-token', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
username: username,
|
||
server_id: parseInt(serverId, 10)
|
||
})
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
$btn.prop('disabled', false).text(originalText);
|
||
|
||
if (data.success && data.data && data.data.token) {
|
||
sessionData.token = data.data.token;
|
||
sessionData.username = username;
|
||
sessionData.serverId = parseInt(serverId, 10);
|
||
|
||
$('#mc-token-text').text(data.data.token);
|
||
$('#mc_form_token').val(data.data.token);
|
||
$('#mc_form_username').val(username);
|
||
$('#mc_form_server').val(serverId);
|
||
|
||
showFeedback('✓ Session-Token erstellt! Gültig für 1 Stunde.', 'success');
|
||
setTimeout(() => switchStep(2), 600);
|
||
} else {
|
||
showFeedback(data.message || 'Fehler beim Token-Erstellen', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Token generation error:', error);
|
||
$btn.prop('disabled', false).text(originalText);
|
||
showFeedback('Netzwerkfehler beim Token-Erstellen', 'error');
|
||
});
|
||
});
|
||
|
||
$('.mc-copy-btn').on('click', function() {
|
||
const text = $('#mc-token-text').text();
|
||
const $btn = $(this);
|
||
|
||
if (text === 'Waiting...' || !text) {
|
||
showFeedback('Kein Token zum Kopieren verfügbar', 'error');
|
||
return;
|
||
}
|
||
|
||
navigator.clipboard.writeText(text)
|
||
.then(() => {
|
||
const original = $btn.text();
|
||
$btn.text('✓');
|
||
setTimeout(() => $btn.text(original), 2000);
|
||
})
|
||
.catch(() => {
|
||
showFeedback('Kopieren fehlgeschlagen', 'error');
|
||
});
|
||
});
|
||
|
||
$('#mc-btn-check').on('click', function () {
|
||
const token = $('#mc_form_token').val();
|
||
|
||
if (!token) {
|
||
showFeedback('Kein Token vorhanden', 'error');
|
||
return;
|
||
}
|
||
|
||
const $btn = $(this);
|
||
const originalText = $btn.text();
|
||
$btn.prop('disabled', true).html('<span class="mc-loading"></span> Prüfe...');
|
||
|
||
fetch(api + '/check-token', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ token: token })
|
||
})
|
||
.then(response => response.json().then(data => {
|
||
if (!response.ok) throw new Error(data.message || 'Verifizierung fehlgeschlagen.');
|
||
return data;
|
||
}))
|
||
.then(data => {
|
||
$btn.prop('disabled', false).text(originalText);
|
||
|
||
if (data.success && data.data && data.data.claimed) {
|
||
sessionData.verified = true;
|
||
$('#mc-session-user').text(data.data.claimed_by);
|
||
showFeedback(`✓ Erfolgreich verifiziert als <strong>${data.data.claimed_by}</strong>!`, 'success');
|
||
setTimeout(() => {
|
||
switchStep(3);
|
||
loadAlbums();
|
||
}, 800);
|
||
} else {
|
||
sessionData.verified = false;
|
||
showFeedback('⚠ Noch nicht verifiziert. Gib <strong>/verify [Token]</strong> im Spiel ein.', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Check token error:', error);
|
||
$btn.prop('disabled', false).text(originalText);
|
||
sessionData.verified = false;
|
||
showFeedback(`❌ ${error.message}`, 'error');
|
||
});
|
||
});
|
||
|
||
$('#mc-upload-file').on('change', function() {
|
||
let files = Array.from(this.files);
|
||
|
||
// FIX: NUR BILDER ZULASSEN (Client Side Filter)
|
||
files = files.filter(function(f) {
|
||
return f.type.startsWith('image/');
|
||
});
|
||
|
||
if (files.length > 0) {
|
||
// Wenn Dateien gefiltert wurden (User hat PDF ausgewählt), aktualisiere Input
|
||
if (files.length !== this.files.length) {
|
||
const dataTransfer = new DataTransfer();
|
||
files.forEach(file => dataTransfer.items.add(file));
|
||
this.files = dataTransfer.files;
|
||
showFeedback('❌ Nur Bilder sind erlaubt! PDFs/Zip wurden entfernt.', 'error');
|
||
}
|
||
selectedFiles = files;
|
||
renderFilePreview();
|
||
}
|
||
});
|
||
|
||
$(document).on('click', '.mc-preview-remove', function() {
|
||
const index = $(this).data('index');
|
||
selectedFiles.splice(index, 1);
|
||
renderFilePreview();
|
||
|
||
const dataTransfer = new DataTransfer();
|
||
selectedFiles.forEach(file => dataTransfer.items.add(file));
|
||
$('#mc-upload-file')[0].files = dataTransfer.files;
|
||
});
|
||
|
||
$('#mc-btn-new-album').on('click', function() {
|
||
$('#mc-new-album-form').slideToggle();
|
||
});
|
||
|
||
$('#mc-btn-create-album').on('click', function() {
|
||
const albumName = $('#mc-new-album-name').val().trim();
|
||
|
||
if (!albumName) {
|
||
showFeedback('Bitte gib einen Album-Namen ein', 'error');
|
||
return;
|
||
}
|
||
|
||
const $btn = $(this);
|
||
$btn.prop('disabled', true).html('<span class="mc-loading"></span> Erstelle...');
|
||
|
||
const formData = new FormData();
|
||
formData.append('action', 'mc_gallery_create_album');
|
||
formData.append('mc_upload_nonce', mcGalleryPro.nonce);
|
||
formData.append('mc_token', sessionData.token);
|
||
formData.append('mc_username', sessionData.username);
|
||
formData.append('mc_server_id', sessionData.serverId);
|
||
formData.append('album_name', albumName);
|
||
|
||
fetch(ajaxUrl, {
|
||
method: 'POST',
|
||
body: formData,
|
||
credentials: 'same-origin'
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
const $select = $('#mc-upload-album');
|
||
$select.append($('<option>')
|
||
.val(data.data.album.id)
|
||
.text(data.data.album.title)
|
||
);
|
||
$select.val(data.data.album.id);
|
||
$('#mc-new-album-name').val('');
|
||
$('#mc-new-album-form').slideUp();
|
||
showFeedback('✓ Album erfolgreich erstellt!', 'success');
|
||
} else {
|
||
showFeedback('Fehler: ' + (data.data?.message || 'Unbekannt'), 'error');
|
||
}
|
||
$btn.prop('disabled', false).text('Album erstellen');
|
||
})
|
||
.catch(error => {
|
||
console.error('Create album error:', error);
|
||
$btn.prop('disabled', false).text('Album erstellen');
|
||
showFeedback('Netzwerkfehler', 'error');
|
||
});
|
||
});
|
||
|
||
$('#mc-btn-final-upload').on('click', function () {
|
||
if (selectedFiles.length === 0) {
|
||
showFeedback('Bitte wähle mindestens ein Bild aus', 'error');
|
||
return;
|
||
}
|
||
|
||
if (selectedFiles.length > maxUploads) {
|
||
showFeedback('Du kannst nur ' + maxUploads + ' Bilder gleichzeitig hochladen.', 'error');
|
||
return;
|
||
}
|
||
|
||
const formData = new FormData();
|
||
formData.append('action', 'mc_gallery_upload');
|
||
formData.append('mc_upload_nonce', mcGalleryPro.nonce);
|
||
formData.append('mc_token', sessionData.token);
|
||
formData.append('mc_username', sessionData.username);
|
||
formData.append('mc_server_id', sessionData.serverId);
|
||
formData.append('mc_album_id', $('#mc-upload-album').val() || '');
|
||
|
||
selectedFiles.forEach((file) => {
|
||
formData.append('mc_images[]', file);
|
||
});
|
||
|
||
const $btn = $(this);
|
||
$btn.prop('disabled', true).hide();
|
||
$('#mc-upload-progress').show();
|
||
$('#mc-progress-text').text(`Lade ${selectedFiles.length} Bild${selectedFiles.length > 1 ? 'er' : ''} hoch...`);
|
||
|
||
let progress = 0;
|
||
const progressInterval = setInterval(() => {
|
||
progress += 5;
|
||
if (progress > 90) progress = 90;
|
||
$('#mc-progress-fill').css('width', progress + '%');
|
||
}, 200);
|
||
|
||
fetch(ajaxUrl, {
|
||
method: 'POST',
|
||
body: formData,
|
||
credentials: 'same-origin'
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
clearInterval(progressInterval);
|
||
$('#mc-progress-fill').css('width', '100%');
|
||
|
||
if (data.success) {
|
||
const uploaded = data.data.uploaded || [];
|
||
const errors = data.data.errors || [];
|
||
|
||
let msg = `✓ ${uploaded.length} Bild${uploaded.length > 1 ? 'er' : ''} erfolgreich hochgeladen!`;
|
||
if (errors.length > 0) {
|
||
msg += `<br>⚠ ${errors.length} Fehler: ${errors.join(', ')}`;
|
||
}
|
||
|
||
showFeedback(msg, 'success');
|
||
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 1500);
|
||
|
||
} else {
|
||
throw new Error(data.data?.message || data.message || 'Upload fehlgeschlagen');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
clearInterval(progressInterval);
|
||
console.error('Upload error:', error);
|
||
$('#mc-upload-progress').hide();
|
||
$('#mc-progress-fill').css('width', '0%');
|
||
$btn.show().prop('disabled', false);
|
||
showFeedback(`❌ Upload Fehler: ${error.message}`, 'error');
|
||
});
|
||
});
|
||
|
||
$('#mc-btn-upload-more').on('click', function() {
|
||
$(this).hide();
|
||
$('#mc-feedback-msg').hide();
|
||
$('#mc-upload-file').click();
|
||
});
|
||
|
||
// === LIGHTBOX & VIEW COUNT ===
|
||
$(document).on('click', '.mc-gallery-item', function (e) {
|
||
e.preventDefault();
|
||
|
||
const $item = $(this);
|
||
const href = $item.attr('href');
|
||
|
||
if (!href) return;
|
||
|
||
// View Count Trigger
|
||
// Wir lesen die ID aus data-attach (müssen wir im Shortcode hinzufügen) oder versuchen sie aus der URL zu ermitteln
|
||
// Besser: Wir übergeben die Attach-ID im data-Attribut
|
||
const attachId = $item.data('attach-id');
|
||
const $badge = $item.find('.mc-views-badge');
|
||
|
||
if (attachId && $badge.length) {
|
||
incrementViewCount(attachId, $badge);
|
||
}
|
||
|
||
const player = $item.data('player') || $item.find('.mc-watermark').text().trim();
|
||
const date = $item.data('date') || '';
|
||
const album = $item.data('album') || '';
|
||
const views = $item.data('views') || 0;
|
||
|
||
const $lightbox = $('<div class="mc-lightbox active"></div>');
|
||
const $content = $('<div class="mc-lightbox-content"></div>');
|
||
const $img = $('<img>').attr({
|
||
'src': href,
|
||
'alt': player
|
||
});
|
||
const $close = $('<button class="mc-lightbox-close" aria-label="Schließen">×</button>');
|
||
|
||
let infoHtml = '';
|
||
if (player) infoHtml += `👤 ${player}`;
|
||
if (date && player) infoHtml += ' • ';
|
||
if (date) infoHtml += `📅 ${date}`;
|
||
if (album) infoHtml += ` • 📁 ${album}`;
|
||
// Views auch in Lightbox zeigen
|
||
if (views) infoHtml += ' • 👁️ ' + views;
|
||
|
||
if (infoHtml) {
|
||
const $info = $('<div class="mc-lightbox-info"></div>').html(infoHtml);
|
||
$content.append($info);
|
||
}
|
||
|
||
$content.append($close).append($img);
|
||
$lightbox.append($content).appendTo('body');
|
||
|
||
$lightbox.on('click', function(e) {
|
||
if (e.target === this) {
|
||
$(this).removeClass('active');
|
||
setTimeout(() => $(this).remove(), 300);
|
||
}
|
||
});
|
||
|
||
$close.on('click', function() {
|
||
$lightbox.removeClass('active');
|
||
setTimeout(() => $lightbox.remove(), 300);
|
||
});
|
||
|
||
$(document).on('keydown.lightbox', function(e) {
|
||
if (e.key === 'Escape') {
|
||
$lightbox.removeClass('active');
|
||
setTimeout(() => $lightbox.remove(), 300);
|
||
$(document).off('keydown.lightbox');
|
||
}
|
||
});
|
||
});
|
||
|
||
});
|
||
|
||
})(jQuery); |