feat: mise à jour des règles de configuration pour l'API Platform et ajout de nouveaux composants pour le lecteur, incluant la gestion des pages infinies et des contrôles de lecture

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-03-27 10:59:53 +01:00
parent d123166dcb
commit 346fede878
11 changed files with 417 additions and 100 deletions

View File

@@ -9,43 +9,44 @@
</div>
<div v-else class="reader-content">
<div class="reader-controls">
<button @click="store.previousPage" :disabled="store.isFirstPage">
<ChevronLeftIcon class="h-6 w-6" />
</button>
<div class="page-info"> {{ store.currentPage + 1 }} / {{ store.totalPages }} </div>
<button @click="store.nextPage" :disabled="store.isLastPage">
<ChevronRightIcon class="h-6 w-6" />
</button>
</div>
<ReaderControls
v-if="store.readingMode === 'single'"
:current-page="store.currentPage"
:total-pages="store.totalPages"
:is-first-page="store.isFirstPage"
:is-last-page="store.isLastPage"
@previous="store.previousPage"
@next="store.nextPage" />
<div class="page-container" :style="{ transform: `scale(${store.zoom})` }">
<div v-if="!store.currentPageData" class="error"> Aucune donnée d'image disponible </div>
<div v-else-if="!store.currentPageData.base64Content" class="error"> Contenu de l'image manquant </div>
<img v-else :src="imageSource" :alt="`Page ${store.currentPage + 1}`" class="page-image" />
</div>
<template v-if="store.readingMode === 'single'">
<ReaderPage
:page-data="store.currentPageData"
:page-number="store.currentPage + 1"
:zoom="store.zoom" />
</template>
<template v-else>
<InfiniteReader :pages="store.pages" :zoom="store.zoom" @page-visible="store.handlePageVisible" />
</template>
<div class="reader-settings">
<button @click="toggleReadingMode">
{{ store.readingMode === 'single' ? 'Mode Infini' : 'Mode Simple' }}
</button>
<button @click="toggleReadingDirection">
{{ store.readingDirection === 'ltr' ? 'RTL' : 'LTR' }}
</button>
<div class="zoom-controls">
<button @click="zoomOut">-</button>
<span>{{ Math.round(store.zoom * 100) }}%</span>
<button @click="zoomIn">+</button>
</div>
</div>
<ReaderSettings
:reading-mode="store.readingMode"
:reading-direction="store.readingDirection"
:zoom="store.zoom"
@toggle-reading-mode="toggleReadingMode"
@toggle-reading-direction="toggleReadingDirection"
@zoom-in="zoomIn"
@zoom-out="zoomOut" />
</div>
</div>
</template>
<script setup>
import { onMounted, onUnmounted, computed, watch } from 'vue';
import { onMounted, onUnmounted, watch } from 'vue';
import { useReaderStore } from '../../application/store/readerStore';
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/vue/24/outline';
import ReaderControls from './ReaderControls.vue';
import ReaderPage from './ReaderPage.vue';
import ReaderSettings from './ReaderSettings.vue';
import InfiniteReader from './InfiniteReader.vue';
const props = defineProps({
chapterId: {
@@ -56,13 +57,6 @@
const store = useReaderStore();
const imageSource = computed(() => {
if (!store.currentPageData?.base64Content || !store.currentPageData?.mimeType) {
return '';
}
return `data:${store.currentPageData.mimeType};base64,${store.currentPageData.base64Content}`;
});
const toggleReadingMode = () => {
store.setReadingMode(store.readingMode === 'single' ? 'infinite' : 'single');
};
@@ -80,10 +74,12 @@
};
const handleKeyPress = event => {
if (event.key === 'ArrowRight') {
store.nextPage();
} else if (event.key === 'ArrowLeft') {
store.previousPage();
if (store.readingMode === 'single') {
if (event.key === 'ArrowRight') {
store.nextPage();
} else if (event.key === 'ArrowLeft') {
store.previousPage();
}
}
};
@@ -123,39 +119,6 @@
@apply w-full h-full flex flex-col;
}
.reader-controls {
@apply flex items-center justify-between p-4 bg-gray-800;
}
.page-info {
@apply text-lg font-medium;
}
.page-container {
@apply flex-1 flex items-center justify-center overflow-hidden;
transform-origin: center;
}
.page-image {
@apply max-w-full max-h-full object-contain;
}
.reader-settings {
@apply flex items-center justify-center gap-4 p-4 bg-gray-800;
}
.zoom-controls {
@apply flex items-center gap-2;
}
button {
@apply px-4 py-2 bg-gray-700 rounded hover:bg-gray-600 transition-colors;
}
button:disabled {
@apply opacity-50 cursor-not-allowed;
}
.rtl {
direction: rtl;
}