Expand character model with additional attributes and advanced customization options
- Added fields such as `nickname`, `age`, `gender`, `species`, `nationality`, `status`, and others to enhance character customization. - Modified localization files to include new field labels and placeholders. - Updated `CharacterComponent` and `CharacterDetail` components with UI elements for the newly added attributes. - Introduced "Advanced Mode" toggle to manage visibility of extended customization options. - Refactored database models and repository methods (`addNewCharacter`, `updateCharacter`, and `fetchCharacters`) to handle the extended schema. - Improved data encryption and decryption workflows for secure storage of added attributes. - Enhanced user experience by reorganizing character customization layouts.
This commit is contained in:
@@ -13,6 +13,12 @@ export interface CharacterPropsPost {
|
||||
id: string | null;
|
||||
name: string;
|
||||
lastName: string;
|
||||
nickname: string;
|
||||
age: string;
|
||||
gender: string;
|
||||
species: string;
|
||||
nationality: string;
|
||||
status: 'alive' | 'dead' | 'unknown';
|
||||
category: CharacterCategory;
|
||||
title: string;
|
||||
image: string;
|
||||
@@ -24,9 +30,24 @@ export interface CharacterPropsPost {
|
||||
strengths: { name: string }[];
|
||||
goals: { name: string }[];
|
||||
motivations: { name: string }[];
|
||||
arc: { name: string }[];
|
||||
secrets: { name: string }[];
|
||||
fears: { name: string }[];
|
||||
flaws: { name: string }[];
|
||||
beliefs: { name: string }[];
|
||||
conflicts: { name: string }[];
|
||||
quotes: { name: string }[];
|
||||
distinguishingMarks: { name: string }[];
|
||||
items: { name: string }[];
|
||||
affiliations: { name: string }[];
|
||||
role: string;
|
||||
biography?: string;
|
||||
history?: string;
|
||||
speechPattern?: string;
|
||||
catchphrase?: string;
|
||||
residence?: string;
|
||||
notes?: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +55,23 @@ export interface CharacterProps {
|
||||
id: string;
|
||||
name: string;
|
||||
lastName: string;
|
||||
nickname: string;
|
||||
age: string;
|
||||
gender: string;
|
||||
species: string;
|
||||
nationality: string;
|
||||
status: string;
|
||||
title: string;
|
||||
category: string;
|
||||
image: string;
|
||||
role: string;
|
||||
biography: string;
|
||||
history: string;
|
||||
speechPattern: string;
|
||||
catchphrase: string;
|
||||
residence: string;
|
||||
notes: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface CharacterListResponse {
|
||||
@@ -51,12 +83,23 @@ export interface CompleteCharacterProps {
|
||||
id?: string;
|
||||
name: string;
|
||||
lastName: string;
|
||||
nickname?: string;
|
||||
age?: string;
|
||||
gender?: string;
|
||||
species?: string;
|
||||
nationality?: string;
|
||||
status?: string;
|
||||
title: string;
|
||||
category: string;
|
||||
image?: string;
|
||||
role: string;
|
||||
biography: string;
|
||||
history: string;
|
||||
speechPattern?: string;
|
||||
catchphrase?: string;
|
||||
residence?: string;
|
||||
notes?: string;
|
||||
color?: string;
|
||||
[key: string]: Attribute[] | string | undefined;
|
||||
}
|
||||
|
||||
@@ -108,12 +151,23 @@ export default class Character {
|
||||
id: encryptedCharacter.character_id,
|
||||
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
||||
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
||||
nickname: encryptedCharacter.nickname ? System.decryptDataWithUserKey(encryptedCharacter.nickname, userEncryptionKey) : '',
|
||||
age: encryptedCharacter.age ? System.decryptDataWithUserKey(encryptedCharacter.age, userEncryptionKey) : '',
|
||||
gender: encryptedCharacter.gender ? System.decryptDataWithUserKey(encryptedCharacter.gender, userEncryptionKey) : '',
|
||||
species: encryptedCharacter.species ? System.decryptDataWithUserKey(encryptedCharacter.species, userEncryptionKey) : '',
|
||||
nationality: encryptedCharacter.nationality ? System.decryptDataWithUserKey(encryptedCharacter.nationality, userEncryptionKey) : '',
|
||||
status: encryptedCharacter.status ? System.decryptDataWithUserKey(encryptedCharacter.status, userEncryptionKey) : 'alive',
|
||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
||||
image: encryptedCharacter.image ? System.decryptDataWithUserKey(encryptedCharacter.image, userEncryptionKey) : '',
|
||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
||||
speechPattern: encryptedCharacter.speech_pattern ? System.decryptDataWithUserKey(encryptedCharacter.speech_pattern, userEncryptionKey) : '',
|
||||
catchphrase: encryptedCharacter.catchphrase ? System.decryptDataWithUserKey(encryptedCharacter.catchphrase, userEncryptionKey) : '',
|
||||
residence: encryptedCharacter.residence ? System.decryptDataWithUserKey(encryptedCharacter.residence, userEncryptionKey) : '',
|
||||
notes: encryptedCharacter.notes ? System.decryptDataWithUserKey(encryptedCharacter.notes, userEncryptionKey) : '',
|
||||
color: encryptedCharacter.color ? System.decryptDataWithUserKey(encryptedCharacter.color, userEncryptionKey) : '',
|
||||
})
|
||||
}
|
||||
return { characters: decryptedCharacterList, enabled };
|
||||
@@ -132,15 +186,30 @@ export default class Character {
|
||||
public static addNewCharacter(userId: string, character: CharacterPropsPost, bookId: string, lang: 'fr' | 'en' = 'fr', existingCharacterId?: string): string {
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const characterId: string = existingCharacterId || System.createUniqueId();
|
||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userEncryptionKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userEncryptionKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userEncryptionKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userEncryptionKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userEncryptionKey);
|
||||
CharacterRepo.addNewCharacter(userId, characterId, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, bookId, lang);
|
||||
|
||||
const characterData = {
|
||||
firstName: System.encryptDataWithUserKey(character.name, userEncryptionKey),
|
||||
lastName: System.encryptDataWithUserKey(character.lastName, userEncryptionKey),
|
||||
nickname: System.encryptDataWithUserKey(character.nickname || '', userEncryptionKey),
|
||||
age: System.encryptDataWithUserKey(character.age || '', userEncryptionKey),
|
||||
gender: System.encryptDataWithUserKey(character.gender || '', userEncryptionKey),
|
||||
species: System.encryptDataWithUserKey(character.species || '', userEncryptionKey),
|
||||
nationality: System.encryptDataWithUserKey(character.nationality || '', userEncryptionKey),
|
||||
status: System.encryptDataWithUserKey(character.status || 'alive', userEncryptionKey),
|
||||
title: System.encryptDataWithUserKey(character.title, userEncryptionKey),
|
||||
category: System.encryptDataWithUserKey(character.category, userEncryptionKey),
|
||||
image: System.encryptDataWithUserKey(character.image, userEncryptionKey),
|
||||
role: System.encryptDataWithUserKey(character.role, userEncryptionKey),
|
||||
biography: System.encryptDataWithUserKey(character.biography || '', userEncryptionKey),
|
||||
history: System.encryptDataWithUserKey(character.history || '', userEncryptionKey),
|
||||
speechPattern: System.encryptDataWithUserKey(character.speechPattern || '', userEncryptionKey),
|
||||
catchphrase: System.encryptDataWithUserKey(character.catchphrase || '', userEncryptionKey),
|
||||
residence: System.encryptDataWithUserKey(character.residence || '', userEncryptionKey),
|
||||
notes: System.encryptDataWithUserKey(character.notes || '', userEncryptionKey),
|
||||
color: System.encryptDataWithUserKey(character.color || '', userEncryptionKey),
|
||||
};
|
||||
|
||||
CharacterRepo.addNewCharacter(userId, characterId, characterData, bookId, lang);
|
||||
const characterPropertyKeys: string[] = Object.keys(character);
|
||||
for (const propertyKey of characterPropertyKeys) {
|
||||
if (Array.isArray(character[propertyKey as keyof CharacterPropsPost])) {
|
||||
@@ -170,15 +239,30 @@ export default class Character {
|
||||
if (!character.id) {
|
||||
return false;
|
||||
}
|
||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userEncryptionKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userEncryptionKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userEncryptionKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userEncryptionKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userEncryptionKey);
|
||||
return CharacterRepo.updateCharacter(userId, character.id, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds(), lang);
|
||||
|
||||
const characterData = {
|
||||
firstName: System.encryptDataWithUserKey(character.name, userEncryptionKey),
|
||||
lastName: System.encryptDataWithUserKey(character.lastName, userEncryptionKey),
|
||||
nickname: System.encryptDataWithUserKey(character.nickname || '', userEncryptionKey),
|
||||
age: System.encryptDataWithUserKey(character.age || '', userEncryptionKey),
|
||||
gender: System.encryptDataWithUserKey(character.gender || '', userEncryptionKey),
|
||||
species: System.encryptDataWithUserKey(character.species || '', userEncryptionKey),
|
||||
nationality: System.encryptDataWithUserKey(character.nationality || '', userEncryptionKey),
|
||||
status: System.encryptDataWithUserKey(character.status || 'alive', userEncryptionKey),
|
||||
title: System.encryptDataWithUserKey(character.title, userEncryptionKey),
|
||||
category: System.encryptDataWithUserKey(character.category, userEncryptionKey),
|
||||
image: System.encryptDataWithUserKey(character.image, userEncryptionKey),
|
||||
role: System.encryptDataWithUserKey(character.role, userEncryptionKey),
|
||||
biography: System.encryptDataWithUserKey(character.biography || '', userEncryptionKey),
|
||||
history: System.encryptDataWithUserKey(character.history || '', userEncryptionKey),
|
||||
speechPattern: System.encryptDataWithUserKey(character.speechPattern || '', userEncryptionKey),
|
||||
catchphrase: System.encryptDataWithUserKey(character.catchphrase || '', userEncryptionKey),
|
||||
residence: System.encryptDataWithUserKey(character.residence || '', userEncryptionKey),
|
||||
notes: System.encryptDataWithUserKey(character.notes || '', userEncryptionKey),
|
||||
color: System.encryptDataWithUserKey(character.color || '', userEncryptionKey),
|
||||
};
|
||||
|
||||
return CharacterRepo.updateCharacter(userId, character.id, characterData, System.timeStampInSeconds(), lang);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,11 +369,22 @@ export default class Character {
|
||||
id: '',
|
||||
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
||||
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
||||
nickname: encryptedCharacter.nickname ? System.decryptDataWithUserKey(encryptedCharacter.nickname as string, userEncryptionKey) : '',
|
||||
age: encryptedCharacter.age ? System.decryptDataWithUserKey(encryptedCharacter.age as string, userEncryptionKey) : '',
|
||||
gender: encryptedCharacter.gender ? System.decryptDataWithUserKey(encryptedCharacter.gender as string, userEncryptionKey) : '',
|
||||
species: encryptedCharacter.species ? System.decryptDataWithUserKey(encryptedCharacter.species as string, userEncryptionKey) : '',
|
||||
nationality: encryptedCharacter.nationality ? System.decryptDataWithUserKey(encryptedCharacter.nationality as string, userEncryptionKey) : '',
|
||||
status: encryptedCharacter.status ? System.decryptDataWithUserKey(encryptedCharacter.status as string, userEncryptionKey) : 'alive',
|
||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title as string, userEncryptionKey) : '',
|
||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category as string, userEncryptionKey) : '',
|
||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role as string, userEncryptionKey) : '',
|
||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography as string, userEncryptionKey) : '',
|
||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history as string, userEncryptionKey) : '',
|
||||
speechPattern: encryptedCharacter.speech_pattern ? System.decryptDataWithUserKey(encryptedCharacter.speech_pattern as string, userEncryptionKey) : '',
|
||||
catchphrase: encryptedCharacter.catchphrase ? System.decryptDataWithUserKey(encryptedCharacter.catchphrase as string, userEncryptionKey) : '',
|
||||
residence: encryptedCharacter.residence ? System.decryptDataWithUserKey(encryptedCharacter.residence as string, userEncryptionKey) : '',
|
||||
notes: encryptedCharacter.notes ? System.decryptDataWithUserKey(encryptedCharacter.notes as string, userEncryptionKey) : '',
|
||||
color: encryptedCharacter.color ? System.decryptDataWithUserKey(encryptedCharacter.color as string, userEncryptionKey) : '',
|
||||
physical: [],
|
||||
psychological: [],
|
||||
relations: [],
|
||||
@@ -297,7 +392,17 @@ export default class Character {
|
||||
weaknesses: [],
|
||||
strengths: [],
|
||||
goals: [],
|
||||
motivations: []
|
||||
motivations: [],
|
||||
arc: [],
|
||||
secrets: [],
|
||||
fears: [],
|
||||
flaws: [],
|
||||
beliefs: [],
|
||||
conflicts: [],
|
||||
quotes: [],
|
||||
distinguishingMarks: [],
|
||||
items: [],
|
||||
affiliations: []
|
||||
};
|
||||
completeCharactersMap.set(encryptedCharacter.character_id, decryptedCharacter);
|
||||
}
|
||||
|
||||
@@ -106,15 +106,28 @@ export default class Download {
|
||||
if (!chapterInfosInserted) return false;
|
||||
|
||||
const charactersInserted: boolean = data.characters.every((character: BookCharactersTable): boolean => {
|
||||
const encryptedCharacterFirstName: string = System.encryptDataWithUserKey(character.first_name, userEncryptionKey);
|
||||
const encryptedCharacterLastName: string | null = character.last_name ? System.encryptDataWithUserKey(character.last_name, userEncryptionKey) : null;
|
||||
const encryptedCharacterCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
||||
const encryptedCharacterTitle: string | null = character.title ? System.encryptDataWithUserKey(character.title, userEncryptionKey) : null;
|
||||
const encryptedCharacterImage: string | null = character.image ? System.encryptDataWithUserKey(character.image, userEncryptionKey) : null;
|
||||
const encryptedCharacterRole: string | null = character.role ? System.encryptDataWithUserKey(character.role, userEncryptionKey) : null;
|
||||
const encryptedCharacterBiography: string | null = character.biography ? System.encryptDataWithUserKey(character.biography, userEncryptionKey) : null;
|
||||
const encryptedCharacterHistory: string | null = character.history ? System.encryptDataWithUserKey(character.history, userEncryptionKey) : null;
|
||||
return CharacterRepo.insertSyncCharacter(character.character_id, character.book_id, userId, encryptedCharacterFirstName, encryptedCharacterLastName, encryptedCharacterCategory, encryptedCharacterTitle, encryptedCharacterImage, encryptedCharacterRole, encryptedCharacterBiography, encryptedCharacterHistory, character.last_update, lang);
|
||||
const characterData = {
|
||||
firstName: System.encryptDataWithUserKey(character.first_name, userEncryptionKey),
|
||||
lastName: character.last_name ? System.encryptDataWithUserKey(character.last_name, userEncryptionKey) : null,
|
||||
nickname: character.nickname ? System.encryptDataWithUserKey(character.nickname, userEncryptionKey) : null,
|
||||
age: character.age ? System.encryptDataWithUserKey(character.age, userEncryptionKey) : null,
|
||||
gender: character.gender ? System.encryptDataWithUserKey(character.gender, userEncryptionKey) : null,
|
||||
species: character.species ? System.encryptDataWithUserKey(character.species, userEncryptionKey) : null,
|
||||
nationality: character.nationality ? System.encryptDataWithUserKey(character.nationality, userEncryptionKey) : null,
|
||||
status: character.status ? System.encryptDataWithUserKey(character.status, userEncryptionKey) : null,
|
||||
category: System.encryptDataWithUserKey(character.category, userEncryptionKey),
|
||||
title: character.title ? System.encryptDataWithUserKey(character.title, userEncryptionKey) : null,
|
||||
image: character.image ? System.encryptDataWithUserKey(character.image, userEncryptionKey) : null,
|
||||
role: character.role ? System.encryptDataWithUserKey(character.role, userEncryptionKey) : null,
|
||||
biography: character.biography ? System.encryptDataWithUserKey(character.biography, userEncryptionKey) : null,
|
||||
history: character.history ? System.encryptDataWithUserKey(character.history, userEncryptionKey) : null,
|
||||
speechPattern: character.speech_pattern ? System.encryptDataWithUserKey(character.speech_pattern, userEncryptionKey) : null,
|
||||
catchphrase: character.catchphrase ? System.encryptDataWithUserKey(character.catchphrase, userEncryptionKey) : null,
|
||||
residence: character.residence ? System.encryptDataWithUserKey(character.residence, userEncryptionKey) : null,
|
||||
notes: character.notes ? System.encryptDataWithUserKey(character.notes, userEncryptionKey) : null,
|
||||
color: character.color ? System.encryptDataWithUserKey(character.color, userEncryptionKey) : null
|
||||
};
|
||||
return CharacterRepo.insertSyncCharacter(character.character_id, character.book_id, userId, characterData, character.last_update, lang);
|
||||
});
|
||||
if (!charactersInserted) return false;
|
||||
|
||||
|
||||
@@ -200,11 +200,22 @@ export default class Sync {
|
||||
...characterRecord,
|
||||
first_name: System.decryptDataWithUserKey(characterRecord.first_name, userEncryptionKey),
|
||||
last_name: characterRecord.last_name ? System.decryptDataWithUserKey(characterRecord.last_name, userEncryptionKey) : null,
|
||||
nickname: characterRecord.nickname ? System.decryptDataWithUserKey(characterRecord.nickname, userEncryptionKey) : null,
|
||||
age: characterRecord.age ? System.decryptDataWithUserKey(characterRecord.age, userEncryptionKey) : null,
|
||||
gender: characterRecord.gender ? System.decryptDataWithUserKey(characterRecord.gender, userEncryptionKey) : null,
|
||||
species: characterRecord.species ? System.decryptDataWithUserKey(characterRecord.species, userEncryptionKey) : null,
|
||||
nationality: characterRecord.nationality ? System.decryptDataWithUserKey(characterRecord.nationality, userEncryptionKey) : null,
|
||||
status: characterRecord.status ? System.decryptDataWithUserKey(characterRecord.status, userEncryptionKey) : null,
|
||||
category: System.decryptDataWithUserKey(characterRecord.category, userEncryptionKey),
|
||||
title: characterRecord.title ? System.decryptDataWithUserKey(characterRecord.title, userEncryptionKey) : null,
|
||||
role: characterRecord.role ? System.decryptDataWithUserKey(characterRecord.role, userEncryptionKey) : null,
|
||||
biography: characterRecord.biography ? System.decryptDataWithUserKey(characterRecord.biography, userEncryptionKey) : null,
|
||||
history: characterRecord.history ? System.decryptDataWithUserKey(characterRecord.history, userEncryptionKey) : null
|
||||
history: characterRecord.history ? System.decryptDataWithUserKey(characterRecord.history, userEncryptionKey) : null,
|
||||
speech_pattern: characterRecord.speech_pattern ? System.decryptDataWithUserKey(characterRecord.speech_pattern, userEncryptionKey) : null,
|
||||
catchphrase: characterRecord.catchphrase ? System.decryptDataWithUserKey(characterRecord.catchphrase, userEncryptionKey) : null,
|
||||
residence: characterRecord.residence ? System.decryptDataWithUserKey(characterRecord.residence, userEncryptionKey) : null,
|
||||
notes: characterRecord.notes ? System.decryptDataWithUserKey(characterRecord.notes, userEncryptionKey) : null,
|
||||
color: characterRecord.color ? System.decryptDataWithUserKey(characterRecord.color, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -562,21 +573,34 @@ export default class Sync {
|
||||
if (serverCharacters && serverCharacters.length > 0) {
|
||||
for (const serverCharacter of serverCharacters) {
|
||||
const characterExists: boolean = CharacterRepo.isCharacterExist(userId, serverCharacter.character_id, lang);
|
||||
const encryptedFirstName: string = System.encryptDataWithUserKey(serverCharacter.first_name, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(serverCharacter.last_name ? serverCharacter.last_name : '', userEncryptionKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(serverCharacter.category, userEncryptionKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(serverCharacter.title ? serverCharacter.title : '', userEncryptionKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(serverCharacter.role ? serverCharacter.role : '', userEncryptionKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(serverCharacter.image ? serverCharacter.image : '', userEncryptionKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(serverCharacter.biography ? serverCharacter.biography : '', userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(serverCharacter.history ? serverCharacter.history : '', userEncryptionKey);
|
||||
const characterData = {
|
||||
firstName: System.encryptDataWithUserKey(serverCharacter.first_name, userEncryptionKey),
|
||||
lastName: System.encryptDataWithUserKey(serverCharacter.last_name ? serverCharacter.last_name : '', userEncryptionKey),
|
||||
nickname: System.encryptDataWithUserKey(serverCharacter.nickname ? serverCharacter.nickname : '', userEncryptionKey),
|
||||
age: System.encryptDataWithUserKey(serverCharacter.age ? serverCharacter.age : '', userEncryptionKey),
|
||||
gender: System.encryptDataWithUserKey(serverCharacter.gender ? serverCharacter.gender : '', userEncryptionKey),
|
||||
species: System.encryptDataWithUserKey(serverCharacter.species ? serverCharacter.species : '', userEncryptionKey),
|
||||
nationality: System.encryptDataWithUserKey(serverCharacter.nationality ? serverCharacter.nationality : '', userEncryptionKey),
|
||||
status: System.encryptDataWithUserKey(serverCharacter.status ? serverCharacter.status : 'alive', userEncryptionKey),
|
||||
category: System.encryptDataWithUserKey(serverCharacter.category, userEncryptionKey),
|
||||
title: System.encryptDataWithUserKey(serverCharacter.title ? serverCharacter.title : '', userEncryptionKey),
|
||||
image: System.encryptDataWithUserKey(serverCharacter.image ? serverCharacter.image : '', userEncryptionKey),
|
||||
role: System.encryptDataWithUserKey(serverCharacter.role ? serverCharacter.role : '', userEncryptionKey),
|
||||
biography: System.encryptDataWithUserKey(serverCharacter.biography ? serverCharacter.biography : '', userEncryptionKey),
|
||||
history: System.encryptDataWithUserKey(serverCharacter.history ? serverCharacter.history : '', userEncryptionKey),
|
||||
speechPattern: System.encryptDataWithUserKey(serverCharacter.speech_pattern ? serverCharacter.speech_pattern : '', userEncryptionKey),
|
||||
catchphrase: System.encryptDataWithUserKey(serverCharacter.catchphrase ? serverCharacter.catchphrase : '', userEncryptionKey),
|
||||
residence: System.encryptDataWithUserKey(serverCharacter.residence ? serverCharacter.residence : '', userEncryptionKey),
|
||||
notes: System.encryptDataWithUserKey(serverCharacter.notes ? serverCharacter.notes : '', userEncryptionKey),
|
||||
color: System.encryptDataWithUserKey(serverCharacter.color ? serverCharacter.color : '', userEncryptionKey)
|
||||
};
|
||||
if (characterExists) {
|
||||
const updateSuccessful: boolean = CharacterRepo.updateCharacter(userId, serverCharacter.character_id, encryptedFirstName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, serverCharacter.last_update);
|
||||
const updateSuccessful: boolean = CharacterRepo.updateCharacter(userId, serverCharacter.character_id, characterData, serverCharacter.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = CharacterRepo.insertSyncCharacter(serverCharacter.character_id, bookId, userId, encryptedFirstName, encryptedLastName, encryptedCategory, encryptedTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, serverCharacter.last_update, lang);
|
||||
const insertSuccessful: boolean = CharacterRepo.insertSyncCharacter(serverCharacter.character_id, bookId, userId, characterData, serverCharacter.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -168,11 +168,22 @@ export default class Upload {
|
||||
...character,
|
||||
first_name: System.decryptDataWithUserKey(character.first_name, userEncryptionKey),
|
||||
last_name: character.last_name ? System.decryptDataWithUserKey(character.last_name, userEncryptionKey) : null,
|
||||
nickname: character.nickname ? System.decryptDataWithUserKey(character.nickname, userEncryptionKey) : null,
|
||||
age: character.age ? System.decryptDataWithUserKey(character.age, userEncryptionKey) : null,
|
||||
gender: character.gender ? System.decryptDataWithUserKey(character.gender, userEncryptionKey) : null,
|
||||
species: character.species ? System.decryptDataWithUserKey(character.species, userEncryptionKey) : null,
|
||||
nationality: character.nationality ? System.decryptDataWithUserKey(character.nationality, userEncryptionKey) : null,
|
||||
status: character.status ? System.decryptDataWithUserKey(character.status, userEncryptionKey) : null,
|
||||
category: System.decryptDataWithUserKey(character.category, userEncryptionKey),
|
||||
title: character.title ? System.decryptDataWithUserKey(character.title, userEncryptionKey) : null,
|
||||
role: character.role ? System.decryptDataWithUserKey(character.role, userEncryptionKey) : null,
|
||||
biography: character.biography ? System.decryptDataWithUserKey(character.biography, userEncryptionKey) : null,
|
||||
history: character.history ? System.decryptDataWithUserKey(character.history, userEncryptionKey) : null
|
||||
history: character.history ? System.decryptDataWithUserKey(character.history, userEncryptionKey) : null,
|
||||
speech_pattern: character.speech_pattern ? System.decryptDataWithUserKey(character.speech_pattern, userEncryptionKey) : null,
|
||||
catchphrase: character.catchphrase ? System.decryptDataWithUserKey(character.catchphrase, userEncryptionKey) : null,
|
||||
residence: character.residence ? System.decryptDataWithUserKey(character.residence, userEncryptionKey) : null,
|
||||
notes: character.notes ? System.decryptDataWithUserKey(character.notes, userEncryptionKey) : null,
|
||||
color: character.color ? System.decryptDataWithUserKey(character.color, userEncryptionKey) : null
|
||||
}));
|
||||
|
||||
const characterAttributes: BookCharactersAttributesTable[] = encryptedCharacterAttributes.map((attribute: BookCharactersAttributesTable): BookCharactersAttributesTable => ({
|
||||
|
||||
@@ -7,12 +7,23 @@ export interface BookCharactersTable extends Record<string, SQLiteValue> {
|
||||
user_id: string;
|
||||
first_name: string;
|
||||
last_name: string | null;
|
||||
nickname: string | null;
|
||||
age: string | null;
|
||||
gender: string | null;
|
||||
species: string | null;
|
||||
nationality: string | null;
|
||||
status: string | null;
|
||||
category: string;
|
||||
title: string | null;
|
||||
image: string | null;
|
||||
role: string | null;
|
||||
biography: string | null;
|
||||
history: string | null;
|
||||
speech_pattern: string | null;
|
||||
catchphrase: string | null;
|
||||
residence: string | null;
|
||||
notes: string | null;
|
||||
color: string | null;
|
||||
last_update: number;
|
||||
}
|
||||
|
||||
@@ -43,12 +54,23 @@ export interface CharacterResult extends Record<string, SQLiteValue> {
|
||||
character_id: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
nickname: string;
|
||||
age: string;
|
||||
gender: string;
|
||||
species: string;
|
||||
nationality: string;
|
||||
status: string;
|
||||
title: string;
|
||||
category: string;
|
||||
image: string;
|
||||
role: string;
|
||||
biography: string;
|
||||
history: string;
|
||||
speech_pattern: string;
|
||||
catchphrase: string;
|
||||
residence: string;
|
||||
notes: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface AttributeResult extends Record<string, SQLiteValue> {
|
||||
@@ -81,7 +103,7 @@ export default class CharacterRepo {
|
||||
public static fetchCharacters(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): CharacterResult[] {
|
||||
try {
|
||||
const db: Database = System.getDb();
|
||||
const query: string = 'SELECT character_id, first_name, last_name, title, category, image, role, biography, history FROM book_characters WHERE book_id=? AND user_id=?';
|
||||
const query: string = 'SELECT character_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color FROM book_characters WHERE book_id=? AND user_id=?';
|
||||
const params: SQLiteValue[] = [bookId, userId];
|
||||
const characters: CharacterResult[] = db.all(query, params) as CharacterResult[];
|
||||
return characters;
|
||||
@@ -100,23 +122,48 @@ export default class CharacterRepo {
|
||||
* Adds a new character to the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param characterId - The unique identifier for the new character
|
||||
* @param encryptedName - The encrypted first name of the character
|
||||
* @param encryptedLastName - The encrypted last name of the character
|
||||
* @param encryptedTitle - The encrypted title of the character
|
||||
* @param encryptedCategory - The encrypted category of the character
|
||||
* @param encryptedImage - The encrypted image path of the character
|
||||
* @param encryptedRole - The encrypted role of the character
|
||||
* @param encryptedBiography - The encrypted biography of the character
|
||||
* @param encryptedHistory - The encrypted history of the character
|
||||
* @param characterData - Object containing all encrypted character fields
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns The character ID if successful
|
||||
*/
|
||||
public static addNewCharacter(userId: string, characterId: string, encryptedName: string, encryptedLastName: string, encryptedTitle: string, encryptedCategory: string, encryptedImage: string, encryptedRole: string, encryptedBiography: string, encryptedHistory: string, bookId: string, lang: 'fr' | 'en' = 'fr'): string {
|
||||
public static addNewCharacter(userId: string, characterId: string, characterData: {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
nickname: string;
|
||||
age: string;
|
||||
gender: string;
|
||||
species: string;
|
||||
nationality: string;
|
||||
status: string;
|
||||
title: string;
|
||||
category: string;
|
||||
image: string;
|
||||
role: string;
|
||||
biography: string;
|
||||
history: string;
|
||||
speechPattern: string;
|
||||
catchphrase: string;
|
||||
residence: string;
|
||||
notes: string;
|
||||
color: string;
|
||||
}, bookId: string, lang: 'fr' | 'en' = 'fr'): string {
|
||||
try {
|
||||
const db: Database = System.getDb();
|
||||
const query: string = 'INSERT INTO `book_characters` (character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)';
|
||||
const params: SQLiteValue[] = [characterId, bookId, userId, encryptedName, encryptedLastName, encryptedCategory, encryptedTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds()];
|
||||
const query: string = `INSERT INTO book_characters (
|
||||
character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`;
|
||||
const params: SQLiteValue[] = [
|
||||
characterId, bookId, userId,
|
||||
characterData.firstName, characterData.lastName, characterData.nickname,
|
||||
characterData.age, characterData.gender, characterData.species,
|
||||
characterData.nationality, characterData.status, characterData.category,
|
||||
characterData.title, characterData.image, characterData.role,
|
||||
characterData.biography, characterData.history, characterData.speechPattern,
|
||||
characterData.catchphrase, characterData.residence, characterData.notes,
|
||||
characterData.color, System.timeStampInSeconds()
|
||||
];
|
||||
const insertResult: RunResult = db.run(query, params);
|
||||
if (!insertResult || insertResult.changes === 0) {
|
||||
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout du personnage.` : `Error adding character.`);
|
||||
@@ -168,23 +215,48 @@ export default class CharacterRepo {
|
||||
* Updates an existing character's information.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param id - The unique identifier of the character to update
|
||||
* @param encryptedName - The encrypted first name of the character
|
||||
* @param encryptedLastName - The encrypted last name of the character
|
||||
* @param encryptedTitle - The encrypted title of the character
|
||||
* @param encryptedCategory - The encrypted category of the character
|
||||
* @param encryptedImage - The encrypted image path of the character
|
||||
* @param encryptedRole - The encrypted role of the character
|
||||
* @param encryptedBiography - The encrypted biography of the character
|
||||
* @param encryptedHistory - The encrypted history of the character
|
||||
* @param characterData - Object containing all encrypted character fields
|
||||
* @param lastUpdate - The timestamp of the last update
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the update was successful, false otherwise
|
||||
*/
|
||||
static updateCharacter(userId: string, id: string, encryptedName: string, encryptedLastName: string, encryptedTitle: string, encryptedCategory: string, encryptedImage: string, encryptedRole: string, encryptedBiography: string, encryptedHistory: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
static updateCharacter(userId: string, id: string, characterData: {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
nickname: string;
|
||||
age: string;
|
||||
gender: string;
|
||||
species: string;
|
||||
nationality: string;
|
||||
status: string;
|
||||
title: string;
|
||||
category: string;
|
||||
image: string;
|
||||
role: string;
|
||||
biography: string;
|
||||
history: string;
|
||||
speechPattern: string;
|
||||
catchphrase: string;
|
||||
residence: string;
|
||||
notes: string;
|
||||
color: string;
|
||||
}, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
try {
|
||||
const db: Database = System.getDb();
|
||||
const query: string = 'UPDATE `book_characters` SET `first_name`=?,`last_name`=?,`title`=?,`category`=?,`image`=?,`role`=?,`biography`=?,`history`=?,`last_update`=? WHERE `character_id`=? AND `user_id`=?';
|
||||
const params: SQLiteValue[] = [encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, lastUpdate, id, userId];
|
||||
const query: string = `UPDATE book_characters SET
|
||||
first_name=?, last_name=?, nickname=?, age=?, gender=?, species=?, nationality=?, status=?,
|
||||
title=?, category=?, image=?, role=?, biography=?, history=?,
|
||||
speech_pattern=?, catchphrase=?, residence=?, notes=?, color=?, last_update=?
|
||||
WHERE character_id=? AND user_id=?`;
|
||||
const params: SQLiteValue[] = [
|
||||
characterData.firstName, characterData.lastName, characterData.nickname,
|
||||
characterData.age, characterData.gender, characterData.species,
|
||||
characterData.nationality, characterData.status, characterData.title,
|
||||
characterData.category, characterData.image, characterData.role,
|
||||
characterData.biography, characterData.history, characterData.speechPattern,
|
||||
characterData.catchphrase, characterData.residence, characterData.notes,
|
||||
characterData.color, lastUpdate, id, userId
|
||||
];
|
||||
const updateResult: RunResult = db.run(query, params);
|
||||
return updateResult.changes > 0;
|
||||
} catch (error: unknown) {
|
||||
@@ -396,7 +468,9 @@ export default class CharacterRepo {
|
||||
static async fetchBookCharacters(userId: string, bookId: string, lang: 'fr' | 'en'): Promise<BookCharactersTable[]> {
|
||||
try {
|
||||
const db: Database = System.getDb();
|
||||
const query: string = 'SELECT character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update FROM book_characters WHERE user_id=? AND book_id=?';
|
||||
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||
FROM book_characters WHERE user_id=? AND book_id=?`;
|
||||
const params: SQLiteValue[] = [userId, bookId];
|
||||
const characters: BookCharactersTable[] = db.all(query, params) as BookCharactersTable[];
|
||||
return characters;
|
||||
@@ -487,24 +561,48 @@ export default class CharacterRepo {
|
||||
* @param characterId - The unique identifier of the character
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param firstName - The first name of the character
|
||||
* @param lastName - The last name of the character (nullable)
|
||||
* @param category - The category of the character
|
||||
* @param title - The title of the character (nullable)
|
||||
* @param image - The image path of the character (nullable)
|
||||
* @param role - The role of the character (nullable)
|
||||
* @param biography - The biography of the character (nullable)
|
||||
* @param history - The history of the character (nullable)
|
||||
* @param characterData - Object containing all character fields
|
||||
* @param lastUpdate - The timestamp of the last update
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the insertion was successful, false otherwise
|
||||
*/
|
||||
static insertSyncCharacter(characterId: string, bookId: string, userId: string, firstName: string, lastName: string | null, category: string, title: string | null, image: string | null, role: string | null, biography: string | null, history: string | null, lastUpdate: number, lang: 'fr' | 'en'): boolean {
|
||||
static insertSyncCharacter(characterId: string, bookId: string, userId: string, characterData: {
|
||||
firstName: string;
|
||||
lastName: string | null;
|
||||
nickname: string | null;
|
||||
age: string | null;
|
||||
gender: string | null;
|
||||
species: string | null;
|
||||
nationality: string | null;
|
||||
status: string | null;
|
||||
category: string;
|
||||
title: string | null;
|
||||
image: string | null;
|
||||
role: string | null;
|
||||
biography: string | null;
|
||||
history: string | null;
|
||||
speechPattern: string | null;
|
||||
catchphrase: string | null;
|
||||
residence: string | null;
|
||||
notes: string | null;
|
||||
color: string | null;
|
||||
}, lastUpdate: number, lang: 'fr' | 'en'): boolean {
|
||||
try {
|
||||
const db: Database = System.getDb();
|
||||
const query: string = `INSERT INTO book_characters (character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||
const params: SQLiteValue[] = [characterId, bookId, userId, firstName, lastName, category, title, image, role, biography, history, lastUpdate];
|
||||
const query: string = `INSERT INTO book_characters (
|
||||
character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||
const params: SQLiteValue[] = [
|
||||
characterId, bookId, userId,
|
||||
characterData.firstName, characterData.lastName, characterData.nickname,
|
||||
characterData.age, characterData.gender, characterData.species,
|
||||
characterData.nationality, characterData.status, characterData.category,
|
||||
characterData.title, characterData.image, characterData.role,
|
||||
characterData.biography, characterData.history, characterData.speechPattern,
|
||||
characterData.catchphrase, characterData.residence, characterData.notes,
|
||||
characterData.color, lastUpdate
|
||||
];
|
||||
const insertResult: RunResult = db.run(query, params);
|
||||
return insertResult.changes > 0;
|
||||
} catch (error: unknown) {
|
||||
@@ -555,7 +653,8 @@ export default class CharacterRepo {
|
||||
static async fetchCompleteCharacterById(id: string, lang: "fr" | "en"): Promise<BookCharactersTable[]> {
|
||||
try {
|
||||
const db: Database = System.getDb();
|
||||
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update
|
||||
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||
FROM book_characters
|
||||
WHERE character_id = ?`;
|
||||
const params: SQLiteValue[] = [id];
|
||||
|
||||
@@ -13,13 +13,26 @@ type Database = sqlite3.Database;
|
||||
// MIGRATIONS
|
||||
// =============================================================================
|
||||
|
||||
const schemaVersion = 1;
|
||||
const schemaVersion = 2;
|
||||
|
||||
/**
|
||||
* DEV ONLY - S'exécute à chaque refresh, pas besoin de version
|
||||
* Mets ta query, test, efface après
|
||||
*/
|
||||
const devQueries: string[] = [];
|
||||
const devQueries: string[] = [
|
||||
// Nouveaux champs de personnages
|
||||
`ALTER TABLE book_characters ADD COLUMN nickname TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN age TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN gender TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN species TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN nationality TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN status TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN speech_pattern TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN catchphrase TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN residence TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN notes TEXT DEFAULT NULL`,
|
||||
`ALTER TABLE book_characters ADD COLUMN color TEXT DEFAULT NULL`,
|
||||
];
|
||||
|
||||
const isDev:boolean = !app.isPackaged;
|
||||
|
||||
@@ -86,6 +99,19 @@ function migrateFromOldSystem(db: Database): void {
|
||||
// Add spells_enabled column to book_tools if missing
|
||||
addColumn(db, 'book_tools', 'spells_enabled', 'INTEGER NOT NULL DEFAULT 0');
|
||||
|
||||
// Add new character fields if missing
|
||||
addColumn(db, 'book_characters', 'nickname', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'age', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'gender', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'species', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'nationality', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'status', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'speech_pattern', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'catchphrase', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'residence', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'notes', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');
|
||||
|
||||
// Create book_spell_tags table if missing
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS book_spell_tags (
|
||||
@@ -208,6 +234,21 @@ export function runMigrations(db: Database): void {
|
||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);
|
||||
}
|
||||
|
||||
// v2 - Add new character fields (nickname, age, gender, species, nationality, status, etc.)
|
||||
if (currentVersion < 2) {
|
||||
addColumn(db, 'book_characters', 'nickname', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'age', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'gender', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'species', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'nationality', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'status', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'speech_pattern', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'catchphrase', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'residence', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'notes', 'TEXT DEFAULT NULL');
|
||||
addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');
|
||||
}
|
||||
|
||||
setDbVersion(db, schemaVersion);
|
||||
}
|
||||
|
||||
@@ -346,12 +387,23 @@ export function initializeSchema(db: Database): void {
|
||||
user_id TEXT NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT,
|
||||
nickname TEXT,
|
||||
age TEXT,
|
||||
gender TEXT,
|
||||
species TEXT,
|
||||
nationality TEXT,
|
||||
status TEXT,
|
||||
category TEXT NOT NULL,
|
||||
title TEXT,
|
||||
image TEXT,
|
||||
role TEXT,
|
||||
biography TEXT,
|
||||
history TEXT,
|
||||
speech_pattern TEXT,
|
||||
catchphrase TEXT,
|
||||
residence TEXT,
|
||||
notes TEXT,
|
||||
color TEXT,
|
||||
last_update INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user