style(reader): améliorer la toolbar et l'UI du mode scroll
- Corriger la troncature de la toolbar (max-height 4rem → 5rem) - Animer la toolbar en translateY pour un effet "bloc uni" avec le header - Corriger le bug d'auto-hide du header après switch simple → scroll - Augmenter la taille du titre de chapitre dans la toolbar (text-sm font-medium) - Harmoniser le bouton scroll-to-top avec le style des ToolbarButtons - Ajouter support de prop `class` sur les labels de ToolbarSection
This commit is contained in:
parent
cc702cff19
commit
9c47c717d0
@@ -9,19 +9,6 @@
|
||||
</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"
|
||||
@@ -36,28 +23,8 @@
|
||||
: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>
|
||||
@@ -68,8 +35,6 @@ import { useHeaderStore } from '../../../../shared/stores/headerStore';
|
||||
import { useUserPreferencesStore } from '../../../../domain/setting/application/store/userPreferencesStore';
|
||||
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({
|
||||
@@ -87,28 +52,20 @@ import SingleModeReader from './SingleModeReader.vue';
|
||||
const headerStore = useHeaderStore();
|
||||
const prefs = useUserPreferencesStore();
|
||||
|
||||
// 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);
|
||||
prefs.setReadingMode(newMode === 'infinite' ? 'scroll' : 'single');
|
||||
|
||||
// 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
|
||||
headerStore.disableReaderToolbarAutoHide();
|
||||
} else {
|
||||
// En mode infini : utiliser la logique d'InfiniteReader
|
||||
headerStore.enableReaderToolbarAutoHide();
|
||||
headerStore.enableAutoHide();
|
||||
showButtonsWithTimer();
|
||||
}
|
||||
};
|
||||
@@ -117,100 +74,40 @@ import SingleModeReader from './SingleModeReader.vue';
|
||||
const newDir = store.readingDirection === 'ltr' ? 'rtl' : 'ltr';
|
||||
store.setReadingDirection(newDir);
|
||||
prefs.setReadingDirection(newDir);
|
||||
resetButtonsTimer();
|
||||
};
|
||||
|
||||
const zoomIn = () => {
|
||||
store.setZoom(Math.min(store.zoom + 0.1, 2));
|
||||
resetButtonsTimer();
|
||||
};
|
||||
const zoomIn = () => store.setZoom(Math.min(store.zoom + 0.1, 2));
|
||||
const zoomOut = () => store.setZoom(Math.max(store.zoom - 0.1, 0.5));
|
||||
|
||||
const zoomOut = () => {
|
||||
store.setZoom(Math.max(store.zoom - 0.1, 0.5));
|
||||
resetButtonsTimer();
|
||||
};
|
||||
const handleZoomChange = (zoom) => store.setZoom(zoom);
|
||||
|
||||
const handleZoomChange = (zoom) => {
|
||||
store.setZoom(zoom);
|
||||
resetButtonsTimer();
|
||||
};
|
||||
const handleDoublePageModeChange = (mode) => store.setDoublePageMode(mode);
|
||||
const handleDoublePageAutoDetectChange = (enabled) => store.setDoublePageAutoDetect(enabled);
|
||||
const handleDetectionThresholdChange = (threshold) => store.setDoublePageDetectionThreshold(threshold);
|
||||
const handleResetPreferences = () => store.resetPreferences();
|
||||
|
||||
// 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 => {
|
||||
@@ -222,38 +119,46 @@ import SingleModeReader from './SingleModeReader.vue';
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// Charger les préférences sauvegardées
|
||||
store.loadPreferences();
|
||||
|
||||
window.addEventListener('keydown', handleKeyPress);
|
||||
|
||||
// Auto-hide header si activé dans les préférences
|
||||
if (prefs.autoHideHeaderReader) {
|
||||
headerStore.enableAutoHide();
|
||||
}
|
||||
|
||||
// Auto-fullscreen si activé dans les préférences
|
||||
if (store.readingMode === 'infinite') {
|
||||
headerStore.enableReaderToolbarAutoHide();
|
||||
}
|
||||
|
||||
if (prefs.autoFullscreen && document.documentElement.requestFullscreen) {
|
||||
document.documentElement.requestFullscreen().catch(() => {});
|
||||
}
|
||||
|
||||
// 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);
|
||||
headerStore.disableReaderToolbarAutoHide();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
toggleReadingMode,
|
||||
toggleReadingDirection,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
handleZoomChange,
|
||||
handleDoublePageModeChange,
|
||||
handleDoublePageAutoDetectChange,
|
||||
handleDetectionThresholdChange,
|
||||
handleResetPreferences,
|
||||
resetButtonsTimer,
|
||||
showButtonsWithTimer,
|
||||
});
|
||||
</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;
|
||||
@apply w-full h-full flex flex-col bg-gray-900 text-white;
|
||||
}
|
||||
|
||||
.loading {
|
||||
@@ -265,8 +170,7 @@ import SingleModeReader from './SingleModeReader.vue';
|
||||
}
|
||||
|
||||
.reader-content {
|
||||
@apply w-full h-full flex flex-col;
|
||||
@apply p-0 sm:p-2;
|
||||
@apply w-full flex-1 flex flex-col min-h-0;
|
||||
}
|
||||
|
||||
.rtl {
|
||||
|
||||
Reference in New Issue
Block a user