323 lines
12 KiB
JavaScript
323 lines
12 KiB
JavaScript
/**
|
|
* FavMasToKey - Script JavaScript principal
|
|
*/
|
|
|
|
// Attendre que le DOM soit chargé
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Éléments DOM
|
|
const uploadForm = document.getElementById('upload-form');
|
|
const misskeyForm = document.getElementById('misskey-form');
|
|
const jsonFileInput = document.getElementById('json-file');
|
|
const step1 = document.getElementById('step1');
|
|
const step2 = document.getElementById('step2');
|
|
const step3 = document.getElementById('step3');
|
|
const fileSummary = document.getElementById('file-summary');
|
|
const backToStep1 = document.getElementById('back-to-step1');
|
|
const startMigration = document.getElementById('start-migration');
|
|
const pauseMigration = document.getElementById('pause-migration');
|
|
const cancelMigration = document.getElementById('cancel-migration');
|
|
const globalProgress = document.getElementById('global-progress');
|
|
const currentProgress = document.getElementById('current-progress');
|
|
const operationLog = document.getElementById('operation-log');
|
|
|
|
// Variables globales
|
|
let favoritesList = [];
|
|
let currentIndex = 0;
|
|
let totalItems = 0;
|
|
let isProcessing = false;
|
|
let isPaused = false;
|
|
|
|
// Gérer le téléchargement et l'analyse du fichier JSON
|
|
if (uploadForm) {
|
|
uploadForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const file = jsonFileInput.files[0];
|
|
if (!file) {
|
|
alert('Veuillez sélectionner un fichier JSON.');
|
|
return;
|
|
}
|
|
|
|
// Vérifier l'extension du fichier
|
|
if (!file.name.endsWith('.json')) {
|
|
alert('Le fichier doit être au format JSON.');
|
|
return;
|
|
}
|
|
|
|
// Lire le fichier
|
|
const reader = new FileReader();
|
|
reader.onload = function(event) {
|
|
try {
|
|
const json = JSON.parse(event.target.result);
|
|
|
|
// Vérifier la structure du fichier
|
|
if (!json['@context'] || !json.type || !json.orderedItems) {
|
|
alert('Le format du fichier JSON n\'est pas celui attendu pour un export de favoris Mastodon.');
|
|
return;
|
|
}
|
|
|
|
favoritesList = json.orderedItems;
|
|
totalItems = favoritesList.length;
|
|
|
|
// Afficher un résumé
|
|
fileSummary.innerHTML = `
|
|
<strong>${totalItems}</strong> favoris trouvés dans votre fichier Mastodon.
|
|
`;
|
|
|
|
// Passer à l'étape 2
|
|
step1.classList.add('d-none');
|
|
step2.classList.remove('d-none');
|
|
|
|
// Stocker les données dans localStorage pour les conserver
|
|
localStorage.setItem('favmastokey_favorites', JSON.stringify(favoritesList));
|
|
|
|
} catch (error) {
|
|
alert('Erreur lors de l\'analyse du fichier JSON: ' + error.message);
|
|
}
|
|
};
|
|
|
|
reader.onerror = function() {
|
|
alert('Erreur lors de la lecture du fichier.');
|
|
};
|
|
|
|
reader.readAsText(file);
|
|
});
|
|
}
|
|
|
|
// Gestion du retour à l'étape 1
|
|
if (backToStep1) {
|
|
backToStep1.addEventListener('click', function() {
|
|
step2.classList.add('d-none');
|
|
step1.classList.remove('d-none');
|
|
});
|
|
}
|
|
|
|
// Gérer la connexion à Misskey
|
|
if (misskeyForm) {
|
|
misskeyForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const instanceInput = document.getElementById('misskey-instance');
|
|
let instance = instanceInput.value.trim();
|
|
|
|
// Vérifier que l'instance est valide
|
|
if (!instance) {
|
|
alert('Veuillez entrer l\'URL de votre instance Misskey.');
|
|
return;
|
|
}
|
|
|
|
// Supprimer le protocole et les slash de fin si présents
|
|
instance = instance.replace(/^https?:\/\//, '').replace(/\/$/, '');
|
|
|
|
// Vérifier que l'URL semble valide
|
|
if (!/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(instance)) {
|
|
alert('L\'URL de l\'instance Misskey semble invalide.');
|
|
return;
|
|
}
|
|
|
|
// Rediriger vers l'authentification OAuth
|
|
window.location.href = `oauth.php?instance=${encodeURIComponent(instance)}`;
|
|
});
|
|
}
|
|
|
|
// Gérer le processus de migration
|
|
if (startMigration) {
|
|
startMigration.addEventListener('click', function() {
|
|
if (isProcessing) return;
|
|
|
|
// Récupérer les favoris depuis localStorage si nécessaire
|
|
if (favoritesList.length === 0 && localStorage.getItem('favmastokey_favorites')) {
|
|
favoritesList = JSON.parse(localStorage.getItem('favmastokey_favorites'));
|
|
totalItems = favoritesList.length;
|
|
}
|
|
|
|
if (favoritesList.length === 0) {
|
|
addLogEntry('Aucun favori à migrer. Veuillez d\'abord télécharger votre fichier JSON.', 'error');
|
|
return;
|
|
}
|
|
|
|
// Démarrer la migration
|
|
isProcessing = true;
|
|
isPaused = false;
|
|
startMigration.classList.add('d-none');
|
|
pauseMigration.classList.remove('d-none');
|
|
|
|
addLogEntry('Démarrage de la migration...', 'info');
|
|
|
|
// Lancer le processus de migration
|
|
processBatch();
|
|
});
|
|
}
|
|
|
|
// Gérer la pause de la migration
|
|
if (pauseMigration) {
|
|
pauseMigration.addEventListener('click', function() {
|
|
if (!isProcessing) return;
|
|
|
|
isPaused = !isPaused;
|
|
|
|
if (isPaused) {
|
|
pauseMigration.textContent = 'Reprendre';
|
|
addLogEntry('Migration en pause.', 'warning');
|
|
currentProgress.classList.remove('active');
|
|
} else {
|
|
pauseMigration.textContent = 'Pause';
|
|
addLogEntry('Reprise de la migration...', 'info');
|
|
currentProgress.classList.add('active');
|
|
processBatch();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Gérer l'annulation de la migration
|
|
if (cancelMigration) {
|
|
cancelMigration.addEventListener('click', function() {
|
|
if (!isProcessing && currentIndex === 0) {
|
|
// Retour à l'étape 1 si rien n'a commencé
|
|
step3.classList.add('d-none');
|
|
step1.classList.remove('d-none');
|
|
return;
|
|
}
|
|
|
|
const confirmCancel = confirm('Êtes-vous sûr de vouloir annuler la migration en cours ?');
|
|
if (confirmCancel) {
|
|
isProcessing = false;
|
|
isPaused = false;
|
|
addLogEntry('Migration annulée.', 'error');
|
|
|
|
// Réinitialiser l'interface
|
|
startMigration.classList.remove('d-none');
|
|
pauseMigration.classList.add('d-none');
|
|
pauseMigration.textContent = 'Pause';
|
|
currentProgress.classList.remove('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Traite un lot de favoris
|
|
*/
|
|
function processBatch() {
|
|
if (!isProcessing || isPaused || currentIndex >= totalItems) {
|
|
if (currentIndex >= totalItems) {
|
|
// Migration terminée
|
|
isProcessing = false;
|
|
addLogEntry('Migration terminée avec succès !', 'success');
|
|
startMigration.classList.remove('d-none');
|
|
startMigration.textContent = 'Terminer';
|
|
startMigration.addEventListener('click', function() {
|
|
// Nettoyer localStorage et retourner à l'étape 1
|
|
localStorage.removeItem('favmastokey_favorites');
|
|
step3.classList.add('d-none');
|
|
step1.classList.remove('d-none');
|
|
});
|
|
pauseMigration.classList.add('d-none');
|
|
|
|
// Mettre à jour la progression à 100%
|
|
updateProgress(100);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Nombre d'éléments à traiter dans ce lot
|
|
const batchSize = 5;
|
|
const endIndex = Math.min(currentIndex + batchSize, totalItems);
|
|
|
|
// Préparer les éléments du lot
|
|
const batch = favoritesList.slice(currentIndex, endIndex);
|
|
|
|
// Mettre à jour la progression actuelle
|
|
currentProgress.classList.add('active');
|
|
updateProgress();
|
|
|
|
// Simuler le traitement (à remplacer par l'appel API réel)
|
|
addLogEntry(`Traitement du lot ${currentIndex + 1} à ${endIndex}...`, 'info');
|
|
|
|
// Envoyer la requête au serveur
|
|
fetch('process.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
batch: batch,
|
|
currentIndex: currentIndex,
|
|
totalItems: totalItems
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Traiter les résultats
|
|
if (data.results && data.results.length) {
|
|
data.results.forEach(result => {
|
|
addLogEntry(result.message, result.status);
|
|
});
|
|
}
|
|
|
|
// Mettre à jour l'index
|
|
currentIndex = endIndex;
|
|
|
|
// Mettre à jour la progression
|
|
updateProgress();
|
|
|
|
// Traiter le lot suivant après un court délai
|
|
setTimeout(processBatch, 1000);
|
|
} else {
|
|
// Gérer l'erreur
|
|
addLogEntry('Erreur: ' + data.message, 'error');
|
|
|
|
// Pause en cas d'erreur
|
|
isPaused = true;
|
|
pauseMigration.textContent = 'Reprendre';
|
|
currentProgress.classList.remove('active');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
// Gérer l'erreur réseau
|
|
addLogEntry('Erreur de connexion: ' + error.message, 'error');
|
|
|
|
// Pause en cas d'erreur
|
|
isPaused = true;
|
|
pauseMigration.textContent = 'Reprendre';
|
|
currentProgress.classList.remove('active');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Met à jour la barre de progression
|
|
*/
|
|
function updateProgress(forcedValue = null) {
|
|
const progress = forcedValue !== null ? forcedValue : (currentIndex / totalItems) * 100;
|
|
globalProgress.style.width = progress + '%';
|
|
globalProgress.textContent = Math.round(progress) + '%';
|
|
globalProgress.setAttribute('aria-valuenow', progress);
|
|
|
|
if (forcedValue === null) {
|
|
// Mettre à jour la progression actuelle
|
|
const batchProgress = ((currentIndex % 5) / 5) * 100;
|
|
currentProgress.style.width = batchProgress + '%';
|
|
currentProgress.setAttribute('aria-valuenow', batchProgress);
|
|
} else {
|
|
currentProgress.style.width = '100%';
|
|
currentProgress.setAttribute('aria-valuenow', 100);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ajoute une entrée dans le journal des opérations
|
|
*/
|
|
function addLogEntry(message, status = 'info') {
|
|
const entry = document.createElement('div');
|
|
entry.className = `log-entry ${status}`;
|
|
|
|
const timestamp = new Date().toLocaleTimeString();
|
|
entry.textContent = `[${timestamp}] ${message}`;
|
|
|
|
operationLog.appendChild(entry);
|
|
|
|
// Scroll vers le bas pour voir la dernière entrée
|
|
const logContainer = document.getElementById('log-container');
|
|
logContainer.scrollTop = logContainer.scrollHeight;
|
|
}
|
|
}); |