Files
Mangarr/assets/vue/app/domain/reader/presentation/components/ChapterReader.vue

261 lines
8.9 KiB
Vue

<template>
<div class="chapter-reader" :class="{ rtl: store.readingDirection === 'rtl' }">
<div v-if="store.isLoading" class="loading">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
<div v-else-if="store.error" class="error">
{{ store.error }}
</div>
<div v-else class="reader-content">
<ReaderControls
v-if="store.readingMode === 'single'"
:current-page="store.currentPage"
:total-pages="store.totalPages"
:is-first-page="store.isFirstPage"
:is-last-page="store.isLastPage"
:available-chapters="availableChapters"
:settings-open="settingsOpen"
@previous="store.previousPage"
@next="store.nextPage"
@chapter-selected="handleChapterSelected"
@toggle-settings="toggleSettings" />
<template v-if="store.readingMode === 'single'">
<SingleModeReader
:page-data="store.currentPageData"
:page-number="store.currentPage + 1"
:zoom="store.zoom"
:double-page-mode="store.effectiveDoublePageMode"
@button-click="showButtonsWithTimer" />
</template>
<template v-else>
<InfiniteReader
:pages="store.pages"
:zoom="store.zoom"
:double-page-mode="store.effectiveDoublePageMode"
@page-visible="store.handlePageVisible"
@buttons-visibility-change="handleButtonsVisibilityChange"
ref="infiniteReaderRef" />
</template>
<ReaderSettings
:reading-mode="store.readingMode"
:reading-direction="store.readingDirection"
:zoom="store.zoom"
:double-page-mode="store.effectiveDoublePageMode"
:double-page-settings="store.doublePageSettings"
:visible="showFloatingButtons"
:force-open="store.readingMode === 'single' ? settingsOpen : null"
@toggle-reading-mode="toggleReadingMode"
@toggle-reading-direction="toggleReadingDirection"
@zoom-in="zoomIn"
@zoom-out="zoomOut"
@zoom-change="handleZoomChange"
@double-page-mode-change="handleDoublePageModeChange"
@double-page-auto-detect-change="handleDoublePageAutoDetectChange"
@detection-threshold-change="handleDetectionThresholdChange"
@reset-preferences="handleResetPreferences"
@button-click="resetButtonsTimer" />
</div>
</div>
</template>
<script setup>
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { useHeaderStore } from '../../../../shared/stores/headerStore';
import { useReaderStore } from '../../application/store/readerStore';
import InfiniteReader from './InfiniteReader.vue';
import ReaderControls from './ReaderControls.vue';
import ReaderSettings from './ReaderSettings.vue';
import SingleModeReader from './SingleModeReader.vue';
const props = defineProps({
chapterId: {
type: String,
required: true
},
availableChapters: {
type: Array,
default: () => []
}
});
const store = useReaderStore();
const headerStore = useHeaderStore();
// Référence vers InfiniteReader pour accéder à ses méthodes
const infiniteReaderRef = ref(null);
// État pour la visibilité des boutons (géré par InfiniteReader en mode infini, localement en mode simple)
const showFloatingButtons = ref(false);
const settingsOpen = ref(false); // Nouvel état pour gérer l'ouverture des paramètres
let localButtonsTimer = null;
// Actions de l'interface lecteur
const toggleReadingMode = () => {
const newMode = store.readingMode === 'single' ? 'infinite' : 'single';
store.setReadingMode(newMode);
// Gérer la visibilité selon le mode
if (newMode === 'single') {
headerStore.disableAutoHide();
// En mode simple : toujours visible
showFloatingButtons.value = true;
clearTimeout(localButtonsTimer); // Annuler tout timer local
} else {
// En mode infini : utiliser la logique d'InfiniteReader
showButtonsWithTimer();
}
};
const toggleReadingDirection = () => {
store.setReadingDirection(store.readingDirection === 'ltr' ? 'rtl' : 'ltr');
resetButtonsTimer();
};
const zoomIn = () => {
store.setZoom(Math.min(store.zoom + 0.1, 2));
resetButtonsTimer();
};
const zoomOut = () => {
store.setZoom(Math.max(store.zoom - 0.1, 0.5));
resetButtonsTimer();
};
const handleZoomChange = (zoom) => {
store.setZoom(zoom);
resetButtonsTimer();
};
// Fonctions pour les doubles pages
const handleDoublePageModeChange = (mode) => {
store.setDoublePageMode(mode);
resetButtonsTimer();
};
const handleDoublePageAutoDetectChange = (enabled) => {
store.setDoublePageAutoDetect(enabled);
resetButtonsTimer();
};
const handleDetectionThresholdChange = (threshold) => {
store.setDoublePageDetectionThreshold(threshold);
resetButtonsTimer();
};
const handleResetPreferences = () => {
store.resetPreferences();
resetButtonsTimer();
};
// Fonction pour afficher les boutons avec timer (avec fallback pour mode simple)
const showButtonsWithTimer = () => {
if (store.readingMode === 'infinite' && infiniteReaderRef.value) {
// Mode infini : utiliser la logique d'InfiniteReader
infiniteReaderRef.value.showButtonsWithTimer();
} else {
// Mode simple : toujours visible, pas de timer
showFloatingButtons.value = true;
}
};
// Fonction centralisée pour réinitialiser le timer
const resetButtonsTimer = () => {
if (store.readingMode === 'infinite' && infiniteReaderRef.value) {
// Mode infini : utiliser la logique d'InfiniteReader
infiniteReaderRef.value.resetButtonsTimer();
} else {
// Mode simple : toujours visible, pas de timer
showFloatingButtons.value = true;
}
};
// Gestionnaire pour les changements de visibilité des boutons
const handleButtonsVisibilityChange = (visible) => {
if (store.readingMode === 'infinite') {
showFloatingButtons.value = visible;
}
// En mode simple, on ignore les changements et on reste toujours visible
};
const handleKeyPress = event => {
if (store.readingMode === 'single') {
if (event.key === 'ArrowRight') {
store.nextPage();
showButtonsWithTimer(); // Afficher les boutons lors de la navigation clavier
} else if (event.key === 'ArrowLeft') {
store.previousPage();
showButtonsWithTimer(); // Afficher les boutons lors de la navigation clavier
}
}
};
const handleChapterSelected = (chapterId) => {
// La navigation est déjà gérée par le ChapterSelector via le store
// Cette fonction est là pour d'éventuelles actions supplémentaires
console.log('Chapitre sélectionné:', chapterId);
resetButtonsTimer();
};
// Gestion des paramètres via le bouton intégré
const toggleSettings = () => {
settingsOpen.value = !settingsOpen.value;
resetButtonsTimer(); // Réinitialiser le timer lors de l'interaction
};
watch(
() => props.chapterId,
newId => {
if (newId) {
store.loadChapter(newId);
}
},
{ immediate: true }
);
onMounted(() => {
// Charger les préférences sauvegardées
store.loadPreferences();
window.addEventListener('keydown', handleKeyPress);
// Afficher les boutons au démarrage
showButtonsWithTimer();
});
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyPress);
// S'assurer que l'auto-hide est désactivé en quittant le lecteur
headerStore.disableAutoHide();
// Nettoyer le timer local
clearTimeout(localButtonsTimer);
});
</script>
<style lang="postcss" scoped>
.chapter-reader {
@apply w-full h-full flex flex-col items-center justify-center bg-gray-900 text-white;
@apply p-0 sm:p-2;
}
.loading {
@apply flex items-center justify-center h-full;
}
.error {
@apply text-red-500 text-xl;
}
.reader-content {
@apply w-full h-full flex flex-col;
@apply p-0 sm:p-2;
}
.rtl {
direction: rtl;
}
</style>