feat: ajout du lecteur de chapitres avec gestion des pages, des modes de lecture et des paramètres de zoom

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-03-26 22:52:48 +01:00
parent bf8ca79290
commit 85abca7906
10 changed files with 3500 additions and 2 deletions

View File

@@ -0,0 +1,187 @@
import { defineStore } from 'pinia';
import { Chapter } from '../../domain/entities/Chapter';
import { ApiChapterRepository } from '../../infrastructure/repository/ApiChapterRepository';
export const useReaderStore = defineStore('reader', {
state: () => ({
currentChapter: null,
currentPage: 0,
readingMode: 'single', // 'single' ou 'infinite'
readingDirection: 'ltr', // 'ltr' ou 'rtl'
zoom: 1,
isLoading: false,
error: null,
pages: [],
totalPages: 0,
_debug: {
lastUpdate: Date.now(),
lastAction: null
}
}),
getters: {
isFirstPage: state => state.currentPage === 0,
isLastPage: state => state.currentPage === state.totalPages - 1,
currentPageData: state => {
const data = state.pages[state.currentPage];
console.log('Getting currentPageData:', {
currentPage: state.currentPage,
hasData: !!data,
totalPages: state.totalPages,
pagesLength: state.pages.length,
lastUpdate: state._debug.lastUpdate,
lastAction: state._debug.lastAction
});
return data;
}
},
actions: {
async loadChapter(chapterId) {
console.log('Loading chapter:', chapterId);
this.isLoading = true;
this.error = null;
this._debug.lastAction = 'loadChapter';
try {
const repository = new ApiChapterRepository();
// Charger les informations du chapitre
console.log('Fetching chapter info...');
const chapterData = await repository.getChapter(chapterId);
console.log('Chapter data received:', chapterData);
this.currentChapter = Chapter.create(chapterData);
// Charger la liste des pages
console.log('Fetching pages info...');
const pagesData = await repository.getChapterPages(chapterId);
console.log('Pages data received:', pagesData);
// Initialiser le tableau avec des placeholders
this.pages = new Array(pagesData.totalItems).fill(null);
this.totalPages = pagesData.totalItems;
this._debug.lastUpdate = Date.now();
console.log('Pages array initialized:', {
length: this.pages.length,
totalPages: this.totalPages
});
// Charger la première page
if (this.totalPages > 0) {
console.log('Loading first page...');
this.currentPage = 0;
await this.loadCurrentPageData();
} else {
console.warn('No pages available for this chapter');
}
} catch (error) {
console.error('Error loading chapter:', error);
this.error = error.message;
} finally {
this.isLoading = false;
}
},
async loadCurrentPageData() {
if (!this.currentChapter) {
console.error('No current chapter loaded');
return;
}
if (this.currentPage < 0 || this.currentPage >= this.totalPages) {
console.error('Invalid page index:', this.currentPage);
return;
}
const pageNumber = this.currentPage + 1; // Convertir en 1-based pour l'API
console.log('Loading page data:', {
pageNumber,
chapterId: this.currentChapter.id
});
if (this.pages[this.currentPage]?.base64Content) {
console.log('Page already loaded, skipping fetch');
return;
}
this.isLoading = true;
this.error = null;
this._debug.lastAction = 'loadCurrentPageData';
try {
const repository = new ApiChapterRepository();
console.log('Fetching page from API...');
const pageData = await repository.getChapterPage(this.currentChapter.id, pageNumber);
console.log('Page data received:', {
hasContent: !!pageData?.base64Content,
mimeType: pageData?.mimeType,
pageNumber: pageData?.pageNumber
});
// Vérifier que les données sont valides
if (!pageData || !pageData.base64Content) {
throw new Error("Données de page invalides reçues de l'API");
}
// Créer une nouvelle référence du tableau pour déclencher la réactivité
const newPages = [...this.pages];
newPages[this.currentPage] = {
id: pageData.id,
pageNumber: pageData.pageNumber,
base64Content: pageData.base64Content,
mimeType: pageData.mimeType,
dimensions: pageData.dimensions
};
this.pages = newPages;
this._debug.lastUpdate = Date.now();
console.log('Page data updated in store:', {
pageIndex: this.currentPage,
hasContent: !!this.pages[this.currentPage]?.base64Content
});
} catch (error) {
console.error('Error loading page:', error);
this.error = error.message;
} finally {
this.isLoading = false;
}
},
async nextPage() {
if (!this.isLastPage) {
console.log('Moving to next page');
this.currentPage++;
this._debug.lastAction = 'nextPage';
this._debug.lastUpdate = Date.now();
await this.loadCurrentPageData();
}
},
async previousPage() {
if (!this.isFirstPage) {
console.log('Moving to previous page');
this.currentPage--;
this._debug.lastAction = 'previousPage';
this._debug.lastUpdate = Date.now();
await this.loadCurrentPageData();
}
},
setReadingMode(mode) {
this.readingMode = mode;
this._debug.lastAction = 'setReadingMode';
this._debug.lastUpdate = Date.now();
},
setReadingDirection(direction) {
this.readingDirection = direction;
this._debug.lastAction = 'setReadingDirection';
this._debug.lastUpdate = Date.now();
},
setZoom(level) {
this.zoom = level;
this._debug.lastAction = 'setZoom';
this._debug.lastUpdate = Date.now();
}
}
});