added mangaupdates integration

cleanup db related code
cleanup ui
ui eye candy
This commit is contained in:
wea_ondara
2023-09-26 16:47:08 +02:00
parent 641a4425aa
commit 7f28012520
36 changed files with 1435 additions and 168 deletions

View File

@@ -1,70 +0,0 @@
import {Pinia, Store} from 'pinia-class-component';
import type {User} from '@/models/User';
import type {MangaListCollection} from '@/models/MangaListCollection';
@Store({
id: 'AniListStore',
name: 'AniListStore',
})
export class AniListStore extends Pinia {
//data
private x_manga: MangaListCollection | null = null;
private userNameUpdateTrigger: string | null = null;
private x_user: User | null = null;
//getter
get manga(): MangaListCollection | null {
return this.x_manga;
}
get userName(): string | null {
this.userNameUpdateTrigger;
return window.localStorage.getItem('userName');
}
get user(): User | null {
return this.x_user;
}
//actions
setUserName(userName: string | null) {
this.userNameUpdateTrigger = userName;
if (userName) {
window.localStorage.setItem('userName', userName ?? '');
} else {
window.localStorage.removeItem('userName');
}
}
async reload(): Promise<void> {
if (!this.userName) {
return;
}
let res = await fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
'query': 'query($id:Int,$name:String){User(id:$id,name:$name){id name previousNames{name updatedAt}avatar{large}bannerImage about isFollowing isFollower donatorTier donatorBadge createdAt moderatorRoles isBlocked bans options{profileColor restrictMessagesToFollowing}mediaListOptions{scoreFormat}statistics{anime{count meanScore standardDeviation minutesWatched episodesWatched genrePreview:genres(limit:10,sort:COUNT_DESC){genre count}}manga{count meanScore standardDeviation chaptersRead volumesRead genrePreview:genres(limit:10,sort:COUNT_DESC){genre count}}}stats{activityHistory{date amount level}}favourites{anime{edges{favouriteOrder node{id type status(version:2)format isAdult bannerImage title{userPreferred}coverImage{large}startDate{year}}}}manga{edges{favouriteOrder node{id type status(version:2)format isAdult bannerImage title{userPreferred}coverImage{large}startDate{year}}}}characters{edges{favouriteOrder node{id name{userPreferred}image{large}}}}staff{edges{favouriteOrder node{id name{userPreferred}image{large}}}}studios{edges{favouriteOrder node{id name}}}}}}',
'variables': {'name': this.userName},
}),
});
this.x_user = (await res.json()).data.User;
console.log(this.user);
res = await fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
'query': 'query($userId:Int,$userName:String,$type:MediaType){MediaListCollection(userId:$userId,userName:$userName,type:$type){lists{name isCustomList isCompletedList:isSplitCompletedList entries{...mediaListEntry}}user{id name avatar{large}mediaListOptions{scoreFormat rowOrder animeList{sectionOrder customLists splitCompletedSectionByFormat theme}mangaList{sectionOrder customLists splitCompletedSectionByFormat theme}}}}}fragment mediaListEntry on MediaList{id mediaId status score progress progressVolumes repeat priority private hiddenFromStatusLists customLists advancedScores notes updatedAt startedAt{year month day}completedAt{year month day}media{id title{userPreferred romaji english native}coverImage{extraLarge large}type format status(version:2)episodes volumes chapters averageScore popularity isAdult countryOfOrigin genres bannerImage startDate{year month day}}}',
'variables': {'userId': this.user!.id, 'type': 'MANGA'},
}),
});
this.x_manga = (await res.json()).data.MediaListCollection;
console.log(this.manga);
}
}

28
src/stores/DbStore.ts Normal file
View File

@@ -0,0 +1,28 @@
import {Pinia, Store} from 'pinia-class-component';
import AniListMangaRepository from '@/data/repository/aniList/AniListMangaRepository';
import AniListUserRepository from '@/data/repository/aniList/AniListUserRepository';
import MangaUpdatesRepository from '@/data/repository/mangaUpdates/MangaUpdatesRepository';
@Store({
id: 'DbStore',
name: 'DbStore',
})
export class DbStore extends Pinia {
//data
private readonly intAniListMangaRepository = new AniListMangaRepository();
private readonly intAniListUserRepository = new AniListUserRepository();
private readonly intMangaUpdatesRepository = new MangaUpdatesRepository();
//getter
get aniListMangaRepository(): AniListMangaRepository {
return this.intAniListMangaRepository;
}
get aniListUserRepository(): AniListUserRepository {
return this.intAniListUserRepository;
}
get mangaUpdatesRepository(): MangaUpdatesRepository {
return this.intMangaUpdatesRepository;
}
}

162
src/stores/MangaStore.ts Normal file
View File

@@ -0,0 +1,162 @@
import {Pinia, Store} from 'pinia-class-component';
import type {AniListUser} from '@/data/models/anilist/AniListUser';
import {DbStore} from '@/stores/DbStore';
import type {AniListMangaListEntry} from '@/data/models/anilist/AniListMangaListEntry';
import type {AniListMedia} from '@/data/models/anilist/AniListMedia';
import type {AniListMangaList} from '@/data/models/anilist/AniListMangaList';
import type {MangaUpdatesRelation} from '@/data/models/mangaupdates/MangaUpdatesRelation';
import type {MangaUpdatesChapter} from '@/data/models/mangaupdates/MangaUpdatesChapter';
import type {MangaUpdatesSeries} from '@/data/models/mangaupdates/MangaUpdatesSeries';
@Store({
id: 'MangaStore',
name: 'MangaStore',
})
export class MangaStore extends Pinia {
//update trigger
private cachedAniListLists: AniListMangaList[] = [];
private cachedAniListManga = new Map<string, AniListMangaListEntry[]>();
private cachedAniListMedia: AniListMedia[] = [];
private cachedAniListUser: AniListUser | null = null;
private cachedMangaUpdatesChapters: MangaUpdatesChapter[] = [];
private cachedMangaUpdatesSeries: MangaUpdatesSeries[] = [];
private cachedMangaUpdatesRelations: MangaUpdatesRelation[] = [];
private cachedUserName: string | null = null;
constructor() {
super();
this.updateUserName(window.localStorage.getItem('userName'));
}
//getter
get aniListLists(): AniListMangaList[] {
return this.cachedAniListLists;
}
get aniListManga(): Map<string, AniListMangaListEntry[]> {
return this.cachedAniListManga;
}
get aniListMedia(): AniListMedia[] {
return this.cachedAniListMedia;
}
get aniListUser(): AniListUser | null {
return this.cachedAniListUser;
}
get mangaUpdatesChapters(): MangaUpdatesChapter[] {
return this.cachedMangaUpdatesChapters;
}
get mangaUpdatesRelations(): MangaUpdatesRelation[] {
return this.cachedMangaUpdatesRelations;
}
get mangaUpdatesSeries(): MangaUpdatesSeries[] {
return this.cachedMangaUpdatesSeries;
}
get userName(): string | null {
return this.cachedUserName;
}
//stores
private get dbStore(): DbStore {
return new DbStore();
}
//actions
async updateAniListLists(userId: number, lists: AniListMangaList[]): Promise<void> {
await this.dbStore.aniListMangaRepository.patchLists(userId, lists);
if (this.aniListUser?.id === userId) {
this.cachedAniListLists.splice(0);
this.cachedAniListLists.push(...lists);
}
}
async updateAniListManga(userId: number, manga: Map<string, AniListMangaListEntry[]>): Promise<void> {
await this.dbStore.aniListMangaRepository.patchManga(userId, manga);
if (this.aniListUser?.id === userId) {
this.cachedAniListManga.clear();
manga.forEach((v, k) => this.cachedAniListManga.set(k, v));
}
}
async updateAniListMedia(media: AniListMedia[]): Promise<void> {
await this.dbStore.aniListMangaRepository.updateMedia(media);
this.cachedAniListMedia.splice(0);
this.cachedAniListMedia.push(...media);
}
async updateAniListUser(user: AniListUser): Promise<void> {
await this.dbStore.aniListUserRepository.updateUser(user);
if (user.name === this.userName) {
this.cachedAniListUser = user;
}
}
async updateMangaUpdatesChapters(chapters: MangaUpdatesChapter[]): Promise<void> {
await this.dbStore.mangaUpdatesRepository.updateChapters(chapters);
// update cache
const cachedById = Map.groupBy(this.cachedMangaUpdatesChapters, c => c.series_id);
const chaptersById = Map.groupBy(chapters, c => c.series_id);
chaptersById.forEach((v, k) => cachedById.set(k, v));
this.cachedMangaUpdatesChapters.splice(0);
this.cachedMangaUpdatesChapters.push(...Array.from(cachedById.values()).flat());
}
async updateMangaUpdatesSeries(media: MangaUpdatesSeries[]): Promise<void> {
await this.dbStore.mangaUpdatesRepository.updateSeries(media);
// update cache
const cachedById = new Map<number, MangaUpdatesSeries>(this.cachedMangaUpdatesSeries.map(e => [e.series_id, e]));
media.forEach(m => cachedById.set(m.series_id, m));
this.cachedMangaUpdatesSeries.splice(0);
this.cachedMangaUpdatesSeries.push(...Array.from(cachedById.values()));
}
async addMangaUpdatesRelations(relations: MangaUpdatesRelation[]): Promise<void> {
await this.dbStore.mangaUpdatesRepository.addRelations(relations);
this.cachedMangaUpdatesRelations.push(...relations);
}
updateUserName(userName: string | null): void {
if (userName) {
window.localStorage.setItem('userName', userName ?? '');
} else {
window.localStorage.removeItem('userName');
}
this.clearCache();
this.cachedUserName = userName;
}
clearCache(): void {
this.cachedAniListManga.clear();
this.cachedAniListLists.splice(0);
this.cachedAniListMedia.splice(0);
this.cachedAniListUser = null;
this.cachedMangaUpdatesChapters.splice(0);
this.cachedMangaUpdatesSeries.splice(0);
this.cachedMangaUpdatesRelations.splice(0);
}
async reloadCache(): Promise<void> {
this.clearCache();
this.cachedAniListMedia.push(...await this.dbStore.aniListMangaRepository.getMedia());
if (this.userName) {
this.cachedAniListUser = await this.dbStore.aniListUserRepository.getUser(this.userName);
if (this.aniListUser) {
this.cachedAniListLists.push(...await this.dbStore.aniListMangaRepository.getMangaLists(this.aniListUser.id));
const manga = await this.dbStore.aniListMangaRepository.getManga(this.aniListUser.id);
manga.forEach((v, k) => this.cachedAniListManga.set(k, v));
}
}
this.cachedMangaUpdatesChapters.push(...await this.dbStore.mangaUpdatesRepository.getChapters());
this.cachedMangaUpdatesSeries.push(...await this.dbStore.mangaUpdatesRepository.getSeries());
this.cachedMangaUpdatesRelations.push(...await this.dbStore.mangaUpdatesRepository.getRelations());
}
}

View File

@@ -0,0 +1,22 @@
import {Pinia, Store} from 'pinia-class-component';
import AniListDataService from '@/data/service/AniListDataService';
import MangaUpdatesDataService from '@/data/service/MangaUpdatesDataService';
@Store({
id: 'ServiceStore',
name: 'ServiceStore',
})
export class ServiceStore extends Pinia {
//data
private readonly intAniListDataService = new AniListDataService();
private readonly intMangaUpdatesDataService = new MangaUpdatesDataService();
//getter
get aniListDataService(): AniListDataService {
return this.intAniListDataService;
}
get mangaUpdatesDataService(): MangaUpdatesDataService {
return this.intMangaUpdatesDataService;
}
}