- Introduced foundational UI components (`Badge`, `LockCard`, `SectionHeader`, `AvatarIcon`, etc.) for flexible layouts and consistent design. - Added migration support with the `MigrationModal` component and backend integration for exporting/importing data between Electron and Tauri. - Extended form components with `TextAreaInput`, `OrderInput`, `ToggleField`, and `ToolbarSelect` for improved input handling. - Updated `ScribeShell` with migration popup logic to prompt users for data migration. - Integrated `AlertStack` for better alert handling and notification management. - Enhanced Rust/Tauri services with migration command implementations. - Added translations and styles for new components.
766 lines
30 KiB
TypeScript
766 lines
30 KiB
TypeScript
import {invoke as tauriInvoke} from '@tauri-apps/api/core';
|
|
|
|
async function invoke<T>(command: string, args?: Record<string, unknown>): Promise<T> {
|
|
try {
|
|
return await tauriInvoke<T>(command, args);
|
|
} catch (e: unknown) {
|
|
if (e instanceof Error) throw e;
|
|
if (typeof e === 'string') throw new Error(e);
|
|
if (typeof e === 'object' && e !== null && 'message' in e) throw new Error(String((e as {message: string}).message));
|
|
throw new Error(String(e));
|
|
}
|
|
}
|
|
|
|
export {invoke};
|
|
|
|
// ─── Types ─────────────────────────────────────────────────
|
|
|
|
import {BookProps, GuideLine, GuideLineAI} from '@/lib/types/book';
|
|
import {ChapterProps} from '@/lib/types/chapter';
|
|
import {UserProps} from '@/lib/types/user';
|
|
|
|
export interface InitUserResult {
|
|
success: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
export interface OfflineResult {
|
|
success: boolean;
|
|
error: string | null;
|
|
userId: string | null;
|
|
}
|
|
|
|
export interface OfflineModeStatus {
|
|
enabled: boolean;
|
|
syncInterval: number;
|
|
hasPin: boolean;
|
|
lastUserId: string | null;
|
|
}
|
|
|
|
export interface SyncCheckResult {
|
|
shouldSync: boolean;
|
|
daysSinceSync: number | null;
|
|
syncInterval: number | null;
|
|
}
|
|
|
|
export interface TombstoneRecord {
|
|
table_name: string;
|
|
entity_id: string;
|
|
book_id: string | null;
|
|
deleted_at: number;
|
|
}
|
|
|
|
// ─── User & Auth ───────────────────────────────────────────
|
|
|
|
export async function initUser(userId: string): Promise<InitUserResult> {
|
|
return invoke<InitUserResult>('init_user', {data: {userId}});
|
|
}
|
|
|
|
export async function dbInitialize(userId: string, encryptionKey: string): Promise<boolean> {
|
|
return invoke<boolean>('db_initialize', {userId, encryptionKey});
|
|
}
|
|
|
|
export async function getToken(): Promise<string | null> {
|
|
return invoke<string | null>('get_token');
|
|
}
|
|
|
|
export async function setToken(token: string): Promise<void> {
|
|
return invoke<void>('set_token', {token});
|
|
}
|
|
|
|
export async function removeToken(): Promise<void> {
|
|
return invoke<void>('remove_token');
|
|
}
|
|
|
|
export async function getUserEncryptionKey(userId: string): Promise<string | null> {
|
|
return invoke<string | null>('get_user_encryption_key', {userId});
|
|
}
|
|
|
|
export async function getPlatform(): Promise<string> {
|
|
return invoke<string>('get_platform');
|
|
}
|
|
|
|
export async function getUserInfo(): Promise<UserProps> {
|
|
return invoke<UserProps>('get_user_info');
|
|
}
|
|
|
|
export async function syncUser(data: {
|
|
userId: string;
|
|
username: string;
|
|
email: string;
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('sync_user', {data});
|
|
}
|
|
|
|
// ─── Dev ──────────────────────────────────────────────────
|
|
|
|
export async function devResetAll(): Promise<boolean> {
|
|
return invoke<boolean>('dev_reset_all');
|
|
}
|
|
|
|
// ─── Offline ───────────────────────────────────────────────
|
|
|
|
export async function offlinePinSet(pin: string): Promise<OfflineResult> {
|
|
return invoke<OfflineResult>('offline_pin_set', {data: {pin}});
|
|
}
|
|
|
|
export async function offlinePinVerify(pin: string): Promise<OfflineResult> {
|
|
return invoke<OfflineResult>('offline_pin_verify', {data: {pin}});
|
|
}
|
|
|
|
export async function offlineModeGet(): Promise<OfflineModeStatus> {
|
|
return invoke<OfflineModeStatus>('offline_mode_get');
|
|
}
|
|
|
|
export async function offlineModeSet(enabled: boolean, syncIntervalDays: number): Promise<boolean> {
|
|
return invoke<boolean>('offline_mode_set', {data: {enabled, syncIntervalDays}});
|
|
}
|
|
|
|
export async function offlineSyncCheck(): Promise<SyncCheckResult> {
|
|
return invoke<SyncCheckResult>('offline_sync_check');
|
|
}
|
|
|
|
// ─── Book ──────────────────────────────────────────────────
|
|
|
|
export async function getBooks(): Promise<BookProps[]> {
|
|
return invoke<BookProps[]>('get_books');
|
|
}
|
|
|
|
export async function getBook(bookId: string): Promise<BookProps> {
|
|
return invoke<BookProps>('get_book', {bookId});
|
|
}
|
|
|
|
export async function createBook(data: {
|
|
title: string;
|
|
subTitle?: string;
|
|
summary?: string;
|
|
type: string;
|
|
serieId?: number;
|
|
desiredReleaseDate?: string;
|
|
desiredWordCount?: number;
|
|
}): Promise<string> {
|
|
return invoke<string>('create_book', {data});
|
|
}
|
|
|
|
export async function updateBookBasicInfo(data: {
|
|
bookId: string;
|
|
title: string;
|
|
subTitle: string;
|
|
summary: string;
|
|
publicationDate: string;
|
|
wordCount: number;
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('update_book_basic_info', {data});
|
|
}
|
|
|
|
export async function deleteBook(id: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_book', {data: {id, deletedAt}});
|
|
}
|
|
|
|
export async function updateBookToolSetting(bookId: string, toolName: string, enabled: boolean): Promise<boolean> {
|
|
return invoke<boolean>('update_book_tool_setting', {data: {bookId, toolName, enabled}});
|
|
}
|
|
|
|
export async function getBookStory(bookId: string): Promise<unknown> {
|
|
return invoke<unknown>('get_book_story', {data: {bookId}});
|
|
}
|
|
|
|
export async function updateBookStory(data: {
|
|
bookId: string;
|
|
acts: unknown[];
|
|
mainChapters: unknown[];
|
|
issues: unknown[];
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('update_book_story', {data});
|
|
}
|
|
|
|
export async function addIncident(bookId: string, name: string, incidentId?: string): Promise<string> {
|
|
return invoke<string>('add_incident', {data: {bookId, name, incidentId}});
|
|
}
|
|
|
|
export async function removeIncident(bookId: string, incidentId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_incident', {data: {bookId, incidentId, deletedAt}});
|
|
}
|
|
|
|
export async function addPlotPoint(bookId: string, name: string, incidentId: string, plotId?: string): Promise<string> {
|
|
return invoke<string>('add_plot_point', {data: {bookId, name, incidentId, plotId}});
|
|
}
|
|
|
|
export async function removePlotPoint(plotId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_plot_point', {data: {plotId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function addIssue(bookId: string, name: string, issueId?: string): Promise<string> {
|
|
return invoke<string>('add_issue', {data: {bookId, name, issueId}});
|
|
}
|
|
|
|
export async function removeIssue(bookId: string, issueId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_issue', {data: {bookId, issueId, deletedAt}});
|
|
}
|
|
|
|
export async function getBookBasicInformation(bookId: string): Promise<BookProps> {
|
|
return invoke<BookProps>('get_book_basic_information', {bookId});
|
|
}
|
|
|
|
export async function getBookExportInfo(bookId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_book_export_info', {data: {bookId}});
|
|
}
|
|
|
|
export async function exportBook(data: {
|
|
bookId: string;
|
|
format: string;
|
|
selections: unknown[] | null;
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('export_book', {data});
|
|
}
|
|
|
|
// ─── Book Guidelines ────────────────────────────────────────
|
|
|
|
|
|
export async function getGuideLine(bookId: string): Promise<GuideLine> {
|
|
return invoke<GuideLine>('get_guideline', {data: {id: bookId}});
|
|
}
|
|
|
|
export async function getAIGuideLine(bookId: string): Promise<GuideLineAI> {
|
|
return invoke<GuideLineAI>('get_ai_guideline', {data: {id: bookId}});
|
|
}
|
|
|
|
export async function updateGuideLine(data: {
|
|
bookId: string;
|
|
tone: string;
|
|
atmosphere: string;
|
|
writingStyle: string;
|
|
themes: string;
|
|
symbolism: string;
|
|
motifs: string;
|
|
narrativeVoice: string;
|
|
pacing: string;
|
|
intendedAudience: string;
|
|
keyMessages: string;
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('update_guideline', {data});
|
|
}
|
|
|
|
export async function updateAIGuideLine(data: {
|
|
bookId: string;
|
|
plotSummary: string;
|
|
verbTense: string;
|
|
narrativeType: string;
|
|
dialogueType: string;
|
|
toneAtmosphere: string;
|
|
language: string;
|
|
themes: string;
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('update_ai_guideline', {data});
|
|
}
|
|
|
|
// ─── Chapter ───────────────────────────────────────────────
|
|
|
|
export async function getChapters(bookId: string): Promise<ChapterProps[]> {
|
|
return invoke<ChapterProps[]>('get_chapters', {bookId});
|
|
}
|
|
|
|
export async function getWholeChapter(id: string, version: number, bookId: string): Promise<ChapterProps> {
|
|
return invoke<ChapterProps>('get_whole_chapter', {data: {id, version, bookId}});
|
|
}
|
|
|
|
export async function getChapterStory(chapterId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_chapter_story', {chapterId});
|
|
}
|
|
|
|
export async function getCompanionContent(chapterId: string, version: number): Promise<unknown> {
|
|
return invoke<unknown>('get_companion_content', {data: {chapterId, version}});
|
|
}
|
|
|
|
export async function getChapterContent(chapterId: string, version: number): Promise<string> {
|
|
return invoke<string>('get_chapter_content', {data: {chapterId, version}});
|
|
}
|
|
|
|
export async function saveChapterContent(data: {
|
|
chapterId: string;
|
|
version: number;
|
|
content: unknown;
|
|
totalWordCount: number;
|
|
contentId: string;
|
|
}): Promise<boolean> {
|
|
return invoke<boolean>('save_chapter_content', {data});
|
|
}
|
|
|
|
export async function getLastChapter(bookId: string): Promise<ChapterProps | null> {
|
|
return invoke<ChapterProps | null>('get_last_chapter', {bookId});
|
|
}
|
|
|
|
export async function addChapter(data: {
|
|
bookId: string;
|
|
title: string;
|
|
chapterOrder: number;
|
|
chapterId?: string;
|
|
}): Promise<string> {
|
|
return invoke<string>('add_chapter', {data});
|
|
}
|
|
|
|
export async function removeChapter(chapterId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_chapter', {data: {chapterId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function updateChapter(chapterId: string, title: string, chapterOrder: number): Promise<boolean> {
|
|
return invoke<boolean>('update_chapter', {data: {chapterId, title, chapterOrder}});
|
|
}
|
|
|
|
export async function addChapterInformation(data: {
|
|
chapterId: string;
|
|
actId: number;
|
|
bookId: string;
|
|
plotId?: string;
|
|
incidentId?: string;
|
|
chapterInfoId?: string;
|
|
}): Promise<string> {
|
|
return invoke<string>('add_chapter_information', {data});
|
|
}
|
|
|
|
export async function removeChapterInformation(chapterInfoId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_chapter_information', {data: {chapterInfoId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function getBookTags(bookId: string): Promise<unknown> {
|
|
return invoke<unknown>('get_book_tags', {bookId});
|
|
}
|
|
|
|
// ─── Character ─────────────────────────────────────────────
|
|
|
|
export async function getCharacterList(bookId: string, enabled: boolean): Promise<unknown> {
|
|
return invoke<unknown>('get_character_list', {data: {bookId, enabled}});
|
|
}
|
|
|
|
export async function getCharacterAttributes(characterId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_character_attributes', {data: {characterId}});
|
|
}
|
|
|
|
export async function createCharacter(character: unknown, bookId: string, id?: string): Promise<string> {
|
|
return invoke<string>('create_character', {data: {character, bookId, id}});
|
|
}
|
|
|
|
export async function addCharacterAttribute(characterId: string, type: string, name: string, id?: string): Promise<string> {
|
|
return invoke<string>('add_character_attribute', {data: {characterId, type, name, id}});
|
|
}
|
|
|
|
export async function deleteCharacterAttribute(attributeId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_character_attribute', {data: {attributeId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function updateCharacter(character: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_character', {data: {character}});
|
|
}
|
|
|
|
export async function deleteCharacter(characterId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_character', {data: {characterId, bookId, deletedAt}});
|
|
}
|
|
|
|
// ─── Location ──────────────────────────────────────────────
|
|
|
|
export async function getAllLocations(bookId: string, enabled: boolean): Promise<unknown> {
|
|
return invoke<unknown>('get_all_locations', {data: {bookId, enabled}});
|
|
}
|
|
|
|
export async function addLocationSection(locationName: string, bookId: string, id?: string, seriesLocationId?: string): Promise<string> {
|
|
return invoke<string>('add_location_section', {data: {locationName, bookId, id, seriesLocationId}});
|
|
}
|
|
|
|
export async function addLocationElement(locationId: string, elementName: string, id?: string): Promise<string> {
|
|
return invoke<string>('add_location_element', {data: {locationId, elementName, id}});
|
|
}
|
|
|
|
export async function addLocationSubElement(elementId: string, subElementName: string, id?: string): Promise<string> {
|
|
return invoke<string>('add_location_sub_element', {data: {elementId, subElementName, id}});
|
|
}
|
|
|
|
export async function updateLocations(locations: unknown[]): Promise<unknown> {
|
|
return invoke<unknown>('update_locations', {data: {locations}});
|
|
}
|
|
|
|
export async function updateLocationSectionWithSeriesLink(sectionId: string, sectionName?: string, seriesLocationId?: string): Promise<boolean> {
|
|
return invoke<boolean>('update_location_section_with_series_link', {data: {sectionId, sectionName, seriesLocationId}});
|
|
}
|
|
|
|
export async function deleteLocationSection(locationId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_location_section', {data: {locationId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function deleteLocationElement(elementId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_location_element', {data: {elementId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function deleteLocationSubElement(subElementId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_location_sub_element', {data: {subElementId, bookId, deletedAt}});
|
|
}
|
|
|
|
// ─── Spell ─────────────────────────────────────────────────
|
|
|
|
export async function getSpellList(bookId: string, enabled: boolean): Promise<unknown> {
|
|
return invoke<unknown>('get_spell_list', {data: {bookId, enabled}});
|
|
}
|
|
|
|
export async function getSpellTags(bookId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_spell_tags', {data: {bookId}});
|
|
}
|
|
|
|
export async function getSpellDetail(spellId: string): Promise<unknown> {
|
|
return invoke<unknown>('get_spell_detail', {data: {spellId}});
|
|
}
|
|
|
|
export async function createSpell(bookId: string, spell: unknown): Promise<unknown> {
|
|
return invoke<unknown>('create_spell', {data: {bookId, spell}});
|
|
}
|
|
|
|
export async function updateSpell(spellId: string, spell: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_spell', {data: {spellId, spell}});
|
|
}
|
|
|
|
export async function deleteSpell(spellId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_spell', {data: {spellId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function createSpellTag(bookId: string, name: string, color?: string, id?: string): Promise<unknown> {
|
|
return invoke<unknown>('create_spell_tag', {data: {bookId, name, color, id}});
|
|
}
|
|
|
|
export async function updateSpellTag(tagId: string, name: string, color?: string): Promise<boolean> {
|
|
return invoke<boolean>('update_spell_tag', {data: {tagId, name, color}});
|
|
}
|
|
|
|
export async function deleteSpellTag(tagId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_spell_tag', {data: {tagId, bookId, deletedAt}});
|
|
}
|
|
|
|
// ─── World ─────────────────────────────────────────────────
|
|
|
|
export async function getWorlds(bookId: string, enabled: boolean): Promise<unknown> {
|
|
return invoke<unknown>('get_worlds', {data: {bookId, enabled}});
|
|
}
|
|
|
|
export async function addWorld(bookId: string, worldName: string, id?: string, seriesWorldId?: string): Promise<string> {
|
|
return invoke<string>('add_world', {data: {bookId, worldName, id, seriesWorldId}});
|
|
}
|
|
|
|
export async function addWorldElement(worldId: string, elementName: string, elementType: string, id?: string): Promise<string> {
|
|
return invoke<string>('add_world_element', {data: {worldId, elementName, elementType, id}});
|
|
}
|
|
|
|
export async function removeWorldElement(elementId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_world_element', {data: {elementId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function updateWorld(world: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_world', {data: {world}});
|
|
}
|
|
|
|
// ─── Series ────────────────────────────────────────────────
|
|
|
|
export async function getSeriesList(): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_series_list');
|
|
}
|
|
|
|
export async function getSeriesDetail(seriesId: string): Promise<unknown> {
|
|
return invoke<unknown>('get_series_detail', {data: {seriesId}});
|
|
}
|
|
|
|
export async function createSeries(data: unknown): Promise<string> {
|
|
return invoke<string>('create_series', {data});
|
|
}
|
|
|
|
export async function updateSeries(data: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_series', {data});
|
|
}
|
|
|
|
export async function deleteSeries(seriesId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series', {data: {seriesId, deletedAt}});
|
|
}
|
|
|
|
export async function getSeriesBooks(seriesId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_series_books', {data: {seriesId}});
|
|
}
|
|
|
|
export async function addBookToSeries(seriesId: string, bookId: string): Promise<boolean> {
|
|
return invoke<boolean>('add_book_to_series', {data: {seriesId, bookId}});
|
|
}
|
|
|
|
export async function removeBookFromSeries(seriesId: string, bookId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('remove_book_from_series', {data: {seriesId, bookId, deletedAt}});
|
|
}
|
|
|
|
export async function reorderSeriesBooks(seriesId: string, bookIds: string[]): Promise<boolean> {
|
|
return invoke<boolean>('reorder_series_books', {data: {seriesId, bookIds}});
|
|
}
|
|
|
|
export async function getSeriesForBook(bookId: string): Promise<string | null> {
|
|
return invoke<string | null>('get_series_for_book', {data: {bookId}});
|
|
}
|
|
|
|
// ─── Series Characters ─────────────────────────────────────
|
|
|
|
export async function getSeriesCharacterList(seriesId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_series_character_list', {data: {seriesId}});
|
|
}
|
|
|
|
export async function getSeriesCharacterAttributes(characterId: string): Promise<unknown> {
|
|
return invoke<unknown>('get_series_character_attributes', {data: {characterId}});
|
|
}
|
|
|
|
export async function addSeriesCharacter(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_character', {data});
|
|
}
|
|
|
|
export async function updateSeriesCharacter(data: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_series_character', {data});
|
|
}
|
|
|
|
export async function deleteSeriesCharacter(characterId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_character', {data: {characterId, deletedAt}});
|
|
}
|
|
|
|
export async function addSeriesCharacterAttribute(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_character_attribute', {data});
|
|
}
|
|
|
|
export async function deleteSeriesCharacterAttribute(attributeId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_character_attribute', {data: {attributeId, deletedAt}});
|
|
}
|
|
|
|
// ─── Series Locations ──────────────────────────────────────
|
|
|
|
export async function getSeriesLocationList(seriesId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_series_location_list', {data: {seriesId}});
|
|
}
|
|
|
|
export async function addSeriesLocationSection(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_location_section', {data});
|
|
}
|
|
|
|
export async function addSeriesLocationElement(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_location_element', {data});
|
|
}
|
|
|
|
export async function addSeriesLocationSubElement(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_location_sub_element', {data});
|
|
}
|
|
|
|
export async function deleteSeriesLocation(locationId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_location', {data: {locationId, deletedAt}});
|
|
}
|
|
|
|
export async function deleteSeriesLocationElement(elementId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_location_element', {data: {elementId, deletedAt}});
|
|
}
|
|
|
|
export async function deleteSeriesLocationSubElement(subElementId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_location_sub_element', {data: {subElementId, deletedAt}});
|
|
}
|
|
|
|
// ─── Series Worlds ─────────────────────────────────────────
|
|
|
|
export async function getSeriesWorldList(seriesId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_series_world_list', {data: {seriesId}});
|
|
}
|
|
|
|
export async function addSeriesWorld(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_world', {data});
|
|
}
|
|
|
|
export async function updateSeriesWorld(data: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_series_world', {data});
|
|
}
|
|
|
|
export async function addSeriesWorldElement(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_world_element', {data});
|
|
}
|
|
|
|
export async function deleteSeriesWorldElement(elementId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_world_element', {data: {elementId, deletedAt}});
|
|
}
|
|
|
|
// ─── Series Spells ─────────────────────────────────────────
|
|
|
|
export async function getSeriesSpellList(seriesId: string): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_series_spell_list', {data: {seriesId}});
|
|
}
|
|
|
|
export async function getSeriesSpellDetail(spellId: string): Promise<unknown> {
|
|
return invoke<unknown>('get_series_spell_detail', {data: {spellId}});
|
|
}
|
|
|
|
export async function addSeriesSpell(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_spell', {data});
|
|
}
|
|
|
|
export async function updateSeriesSpell(data: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_series_spell', {data});
|
|
}
|
|
|
|
export async function deleteSeriesSpell(spellId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_spell', {data: {spellId, deletedAt}});
|
|
}
|
|
|
|
export async function addSeriesSpellTag(data: unknown): Promise<string> {
|
|
return invoke<string>('add_series_spell_tag', {data});
|
|
}
|
|
|
|
export async function updateSeriesSpellTag(data: unknown): Promise<boolean> {
|
|
return invoke<boolean>('update_series_spell_tag', {data});
|
|
}
|
|
|
|
export async function deleteSeriesSpellTag(tagId: string, deletedAt: number): Promise<boolean> {
|
|
return invoke<boolean>('delete_series_spell_tag', {data: {tagId, deletedAt}});
|
|
}
|
|
|
|
// ─── Sync (books/series) ───────────────────────────────────
|
|
|
|
export async function getSyncedBooks(): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_synced_books');
|
|
}
|
|
|
|
export async function getSyncedSeries(): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_synced_series');
|
|
}
|
|
|
|
export async function uploadBookToServer(bookId: string): Promise<unknown> {
|
|
return invoke<unknown>('upload_book_to_server', {bookId});
|
|
}
|
|
|
|
export async function syncSaveBook(book: unknown): Promise<boolean> {
|
|
return invoke<boolean>('sync_save_book', {data: book});
|
|
}
|
|
|
|
export async function syncBookToClient(book: unknown): Promise<boolean> {
|
|
return invoke<boolean>('sync_book_to_client', {data: book});
|
|
}
|
|
|
|
export async function syncBookToServer(bookToSync: unknown): Promise<unknown> {
|
|
return invoke<unknown>('sync_book_to_server', {data: bookToSync});
|
|
}
|
|
|
|
export async function uploadSeriesToServer(seriesId: string): Promise<unknown> {
|
|
return invoke<unknown>('upload_series_to_server', {seriesId});
|
|
}
|
|
|
|
export async function syncSaveSeries(series: unknown): Promise<boolean> {
|
|
return invoke<boolean>('sync_save_series', {data: series});
|
|
}
|
|
|
|
export async function syncSeriesToClient(series: unknown): Promise<boolean> {
|
|
return invoke<boolean>('sync_series_to_client', {data: series});
|
|
}
|
|
|
|
export async function syncSeriesToServer(seriesToSync: unknown): Promise<unknown> {
|
|
return invoke<unknown>('sync_series_to_server', {data: seriesToSync});
|
|
}
|
|
|
|
export async function seriesSyncUpload(data: {
|
|
type: string;
|
|
bookElementId: string;
|
|
field: string;
|
|
value: string;
|
|
}): Promise<unknown> {
|
|
return invoke<unknown>('series_sync_upload', {data});
|
|
}
|
|
|
|
// ─── Tombstones ────────────────────────────────────────────
|
|
|
|
export async function getTombstonesSince(since: number): Promise<unknown[]> {
|
|
return invoke<unknown[]>('get_tombstones_since', {since});
|
|
}
|
|
|
|
export async function applyBookTombstones(tombstones: TombstoneRecord[]): Promise<void> {
|
|
return invoke<void>('apply_book_tombstones', {tombstones});
|
|
}
|
|
|
|
export async function applySeriesTombstones(tombstones: TombstoneRecord[]): Promise<void> {
|
|
return invoke<void>('apply_series_tombstones', {tombstones});
|
|
}
|
|
|
|
// ─── Migration ────────────────────────────────────────────────
|
|
|
|
export interface MigrationCheckResult {
|
|
found: boolean;
|
|
userId: string | null;
|
|
hasDb: boolean;
|
|
migrationPath: string | null;
|
|
}
|
|
|
|
export interface MigrationResult {
|
|
success: boolean;
|
|
userId: string | null;
|
|
error: string | null;
|
|
}
|
|
|
|
export async function checkElectronMigration(migrationFilePath: string): Promise<MigrationCheckResult> {
|
|
return invoke<MigrationCheckResult>('check_electron_migration', {migrationFilePath});
|
|
}
|
|
|
|
export async function importFromElectron(migrationFilePath: string): Promise<MigrationResult> {
|
|
return invoke<MigrationResult>('import_from_electron', {data: {migrationFilePath}});
|
|
}
|
|
|
|
// ─── Window Management ──────────────────────────────────────
|
|
|
|
let loginWindowOpening = false;
|
|
|
|
export async function openLoginWindow(): Promise<void> {
|
|
if (loginWindowOpening) return;
|
|
loginWindowOpening = true;
|
|
|
|
const {WebviewWindow} = await import('@tauri-apps/api/webviewWindow');
|
|
const {getCurrentWindow} = await import('@tauri-apps/api/window');
|
|
|
|
const existing = await WebviewWindow.getByLabel('login');
|
|
if (existing) {
|
|
await existing.setFocus();
|
|
await getCurrentWindow().hide();
|
|
loginWindowOpening = false;
|
|
return;
|
|
}
|
|
|
|
const loginWindow = new WebviewWindow('login', {
|
|
url: '/login/login/',
|
|
title: 'ERitors - Connexion',
|
|
width: 500,
|
|
height: 900,
|
|
resizable: false,
|
|
center: true,
|
|
decorations: true,
|
|
});
|
|
|
|
loginWindow.once('tauri://created', async function () {
|
|
loginWindowOpening = false;
|
|
await getCurrentWindow().hide();
|
|
});
|
|
}
|
|
|
|
export async function loginSuccess(): Promise<void> {
|
|
const {WebviewWindow} = await import('@tauri-apps/api/webviewWindow');
|
|
const {getCurrentWindow} = await import('@tauri-apps/api/window');
|
|
|
|
const currentLabel = getCurrentWindow().label;
|
|
|
|
if (currentLabel === 'login') {
|
|
const mainWindow = await WebviewWindow.getByLabel('main');
|
|
if (mainWindow) {
|
|
await mainWindow.show();
|
|
await mainWindow.setFocus();
|
|
await mainWindow.emit('auth-success');
|
|
}
|
|
getCurrentWindow().close();
|
|
} else {
|
|
window.location.reload();
|
|
}
|
|
}
|
|
|
|
export async function logout(): Promise<void> {
|
|
await removeToken();
|
|
await openLoginWindow();
|
|
}
|
|
|
|
export async function openExternal(url: string): Promise<void> {
|
|
const {open} = await import('@tauri-apps/plugin-shell');
|
|
return open(url);
|
|
}
|