Enhance synchronization logic and offline handling

- Refactor components to support conditional offline and online CRUD operations.
- Introduce `addToQueue` mechanism for syncing offline changes to the server.
- Add `isChapterContentExist` method and related existence checks in repositories.
- Consolidate data structures and streamline book, chapter, character, and guideline synchronization workflows.
- Encrypt additional character fields and adjust repository inserts for offline data.
This commit is contained in:
natreex
2026-01-07 20:43:34 -05:00
parent fa05d6dbae
commit 8eab6fd771
21 changed files with 557 additions and 578 deletions

View File

@@ -1611,10 +1611,11 @@ export default class Book {
const encryptedLastName: string | null = character.last_name ? System.encryptDataWithUserKey(character.last_name, userKey) : null;
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userKey);
const encryptedCharTitle: string | null = character.title ? System.encryptDataWithUserKey(character.title, userKey) : null;
const encryptedImage: string | null = character.image ? System.encryptDataWithUserKey(character.image, userKey) : null;
const encryptedRole: string | null = character.role ? System.encryptDataWithUserKey(character.role, userKey) : null;
const encryptedBiography: string | null = character.biography ? System.encryptDataWithUserKey(character.biography, userKey) : null;
const encryptedCharHistory: string | null = character.history ? System.encryptDataWithUserKey(character.history, userKey) : null;
return BookRepo.insertSyncCharacter(character.character_id, character.book_id, userId, encryptedFirstName, encryptedLastName, encryptedCategory, encryptedCharTitle, character.image, encryptedRole, encryptedBiography, encryptedCharHistory, character.last_update, lang);
return BookRepo.insertSyncCharacter(character.character_id, character.book_id, userId, encryptedFirstName, encryptedLastName, encryptedCategory, encryptedCharTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedCharHistory, character.last_update, lang);
});
if (!charactersInserted) return false;
@@ -2064,10 +2065,18 @@ export default class Book {
if (chapterContents && chapterContents.length > 0) {
for (const chapterContent of chapterContents) {
const isExist: boolean = ChapterRepo.isChapterContentExist(userId, chapterContent.content_id, lang);
const content: string = System.encryptDataWithUserKey(chapterContent.content ? JSON.stringify(chapterContent.content) : '', userKey);
const updated: boolean = ChapterRepo.updateChapterContent(userId, chapterContent.chapter_id, chapterContent.version, content, chapterContent.words_count, chapterContent.last_update);
if (!updated) {
return false;
if (isExist) {
const updated: boolean = ChapterRepo.updateChapterContent(userId, chapterContent.chapter_id, chapterContent.version, content, chapterContent.words_count, chapterContent.last_update);
if (!updated) {
return false;
}
} else {
const insert: boolean = BookRepo.insertSyncChapterContent(chapterContent.content_id, chapterContent.chapter_id, userId, chapterContent.version, content, chapterContent.words_count, chapterContent.time_on_it, chapterContent.last_update, lang);
if (!insert) {
return false;
}
}
}
}
@@ -2083,7 +2092,7 @@ export default class Book {
return false;
}
} else {
const insert: boolean = BookRepo.insertSyncChapterInfo(chapterInfo.chapter_info_id, chapterInfo.chapter_id, chapterInfo.act_id, chapterInfo.incident_id, chapterInfo.plot_point_id, bookId, chapterInfo.author_id, chapterInfo.summary, chapterInfo.goal, chapterInfo.last_update,lang);
const insert: boolean = BookRepo.insertSyncChapterInfo(chapterInfo.chapter_info_id, chapterInfo.chapter_id, chapterInfo.act_id, chapterInfo.incident_id, chapterInfo.plot_point_id, bookId, chapterInfo.author_id, summary, goal, chapterInfo.last_update,lang);
if (!insert) {
return false;
}

View File

@@ -441,4 +441,20 @@ export default class ChapterRepo{
}
}
}
static isChapterContentExist(userId: string, content_id: string, lang: "fr" | "en"): boolean {
try {
const db: Database = System.getDb();
const result: QueryResult | null = db.get('SELECT 1 FROM `book_chapter_content` WHERE `content_id`=? AND `author_id`=?', [content_id, userId]) || null;
return result !== null;
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
throw new Error(lang === 'fr' ? `Impossible de vérifier l'existence du contenu du chapitre.` : `Unable to check chapter content existence.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
}