- 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
179 lines
6.9 KiB
Vue
179 lines
6.9 KiB
Vue
<template>
|
|
<Toolbar :config="toolbarConfig">
|
|
<template #center>
|
|
<!-- Mode simple : navigation entre pages -->
|
|
<div v-if="store.readingMode === 'single'" class="flex items-center gap-1">
|
|
<button
|
|
@click="store.previousPage()"
|
|
:disabled="store.isFirstPage"
|
|
class="nav-btn"
|
|
title="Page précédente"
|
|
>
|
|
<ChevronLeftIcon class="h-4 w-4" />
|
|
</button>
|
|
<span class="text-white text-sm w-16 text-center">
|
|
{{ store.currentPage + 1 }} / {{ store.totalPages }}
|
|
</span>
|
|
<button
|
|
@click="store.nextPage()"
|
|
:disabled="store.isLastPage"
|
|
class="nav-btn"
|
|
title="Page suivante"
|
|
>
|
|
<ChevronRightIcon class="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Mode scroll : navigation entre chapitres (ordre inversé en RTL) -->
|
|
<div v-else class="flex items-center gap-1">
|
|
<button
|
|
@click="leftChapterAction"
|
|
:disabled="!canGoLeftChapter || store.isLoading"
|
|
class="chapter-nav-btn"
|
|
:title="store.readingDirection === 'rtl' ? 'Chapitre suivant' : 'Chapitre précédent'"
|
|
>
|
|
<ChevronDoubleLeftIcon class="h-4 w-4 flex-shrink-0" />
|
|
<span class="text-xs">{{ store.readingDirection === 'rtl' ? 'Suivant' : 'Précédent' }}</span>
|
|
</button>
|
|
<button
|
|
@click="rightChapterAction"
|
|
:disabled="!canGoRightChapter || store.isLoading"
|
|
class="chapter-nav-btn"
|
|
:title="store.readingDirection === 'rtl' ? 'Chapitre précédent' : 'Chapitre suivant'"
|
|
>
|
|
<span class="text-xs">{{ store.readingDirection === 'rtl' ? 'Précédent' : 'Suivant' }}</span>
|
|
<ChevronDoubleRightIcon class="h-4 w-4 flex-shrink-0" />
|
|
</button>
|
|
</div>
|
|
</template>
|
|
</Toolbar>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {
|
|
ArrowLeftIcon,
|
|
ChevronDoubleLeftIcon,
|
|
ChevronDoubleRightIcon,
|
|
ChevronLeftIcon,
|
|
ChevronRightIcon,
|
|
DocumentIcon,
|
|
EyeIcon,
|
|
EyeSlashIcon,
|
|
ListBulletIcon,
|
|
MinusIcon,
|
|
PlusIcon
|
|
} from '@heroicons/vue/24/outline';
|
|
import { computed } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
|
|
import { useHeaderStore } from '../../../../shared/stores/headerStore';
|
|
import { useReaderStore } from '../../application/store/readerStore';
|
|
|
|
const props = defineProps({
|
|
chapterReaderRef: {
|
|
type: Object,
|
|
default: null
|
|
}
|
|
});
|
|
|
|
const store = useReaderStore();
|
|
const headerStore = useHeaderStore();
|
|
const router = useRouter();
|
|
|
|
// Vue auto-unwrap les refs dans le template : chapterReaderRef est déjà l'instance
|
|
const reader = computed(() => props.chapterReaderRef);
|
|
|
|
const goBack = () => {
|
|
const mangaId = store.currentChapter?.mangaId;
|
|
if (mangaId) {
|
|
router.push({ name: 'manga-details', params: { id: mangaId } });
|
|
} else {
|
|
router.back();
|
|
}
|
|
};
|
|
|
|
const toggleReadingMode = () => reader.value?.toggleReadingMode();
|
|
const toggleReadingDirection = () => reader.value?.toggleReadingDirection();
|
|
const zoomIn = () => store.setZoom(Math.min(store.zoom + 0.1, 2));
|
|
const zoomOut = () => store.setZoom(Math.max(store.zoom - 0.1, 0.5));
|
|
|
|
// En RTL, le bouton gauche (◄◄) avance dans l'histoire (chapitre suivant)
|
|
const isRtl = computed(() => store.readingDirection === 'rtl');
|
|
const leftChapterAction = () => isRtl.value ? store.goToNextChapter() : store.goToPreviousChapter();
|
|
const rightChapterAction = () => isRtl.value ? store.goToPreviousChapter() : store.goToNextChapter();
|
|
const canGoLeftChapter = computed(() => isRtl.value ? store.hasNextChapter : store.hasPreviousChapter);
|
|
const canGoRightChapter = computed(() => isRtl.value ? store.hasPreviousChapter : store.hasNextChapter);
|
|
|
|
const toolbarConfig = computed(() => ({
|
|
leftSection: [
|
|
{
|
|
type: 'button',
|
|
icon: ArrowLeftIcon,
|
|
label: 'Retour',
|
|
onClick: goBack,
|
|
},
|
|
{
|
|
type: 'label',
|
|
text: store.currentChapter?.title || '',
|
|
class: 'text-sm font-medium',
|
|
},
|
|
...(store.currentChapter?.number != null ? [{
|
|
type: 'label',
|
|
text: `Ch.${store.currentChapter.number}`,
|
|
}] : []),
|
|
],
|
|
rightSection: [
|
|
{
|
|
type: 'button',
|
|
icon: store.readingMode === 'single' ? ListBulletIcon : DocumentIcon,
|
|
label: store.readingMode === 'single' ? 'Scroll' : 'Simple',
|
|
active: store.readingMode === 'infinite',
|
|
onClick: toggleReadingMode,
|
|
},
|
|
{
|
|
type: 'button',
|
|
label: store.readingDirection.toUpperCase(),
|
|
active: store.readingDirection === 'rtl',
|
|
onClick: toggleReadingDirection,
|
|
},
|
|
{ type: 'divider' },
|
|
{
|
|
type: 'button',
|
|
icon: MinusIcon,
|
|
disabled: store.zoom <= 0.5,
|
|
onClick: zoomOut,
|
|
},
|
|
{
|
|
type: 'label',
|
|
text: `${Math.round(store.zoom * 100)}%`,
|
|
},
|
|
{
|
|
type: 'button',
|
|
icon: PlusIcon,
|
|
disabled: store.zoom >= 2,
|
|
onClick: zoomIn,
|
|
},
|
|
...(store.readingMode === 'infinite' ? [
|
|
{ type: 'divider' },
|
|
{
|
|
type: 'button',
|
|
icon: headerStore.isReaderToolbarAutoHideEnabled ? EyeSlashIcon : EyeIcon,
|
|
active: headerStore.isReaderToolbarAutoHideEnabled,
|
|
title: headerStore.isReaderToolbarAutoHideEnabled ? 'Toolbar auto-masquée' : 'Toolbar toujours visible',
|
|
onClick: () => headerStore.toggleReaderToolbarAutoHide(),
|
|
},
|
|
] : []),
|
|
],
|
|
}));
|
|
</script>
|
|
|
|
<style lang="postcss" scoped>
|
|
.nav-btn {
|
|
@apply flex items-center justify-center w-7 h-7 rounded bg-gray-700 hover:bg-gray-600 disabled:opacity-40 disabled:cursor-not-allowed transition-colors text-white;
|
|
}
|
|
|
|
.chapter-nav-btn {
|
|
@apply flex items-center justify-between gap-1 h-7 w-28 px-2 rounded bg-gray-700 hover:bg-gray-600 disabled:opacity-40 disabled:cursor-not-allowed transition-colors text-white;
|
|
}
|
|
</style>
|