When the app starts it verifies all three services sequentially, which could leave the other two login controls looking idle or trigger login actions before their real state is known. Track which service is currently being checked and reflect it in the header: - Add a serviceLoggingIn store (plus setServiceLoggingIn and isServiceLoggingIn helpers) to GlobalVariablesAndHelperFunctions. - Have the loginTo* functions and the startup CheckIf* functions toggle their service in the store (seed all three at startup, clear each as it resolves). - In Header, the login buttons show a spinner with 'Checking AniList' / 'Checking MAL' / 'Checking Simkl' and are disabled while that service is being checked, reverting to the normal 'AniList Login' style label once its state is known. - In the avatar menu, the 'Login to X' row shows a spinner with the matching 'Checking X' text while that service is logging in.
245 lines
7.5 KiB
Svelte
245 lines
7.5 KiB
Svelte
<script lang="ts" context="module">
|
|
import {
|
|
GetAniListItem,
|
|
GetAniListLoggedInUser,
|
|
GetAniListUserWatchingList,
|
|
GetMyAnimeListAnime,
|
|
GetMyAnimeListLoggedInUser,
|
|
GetSimklLoggedInUser,
|
|
LogoutAniList,
|
|
LogoutMyAnimeList,
|
|
LogoutSimkl,
|
|
SimklGetUserWatchlist,
|
|
SimklSearch,
|
|
} from "../../wailsjs/go/main/App";
|
|
import type {
|
|
AniListCurrentUserWatchList,
|
|
AniListGetSingleAnime,
|
|
} from "../anilist/types/AniListCurrentUserWatchListType.js";
|
|
import { writable } from "svelte/store";
|
|
import type {
|
|
SimklAnime,
|
|
SimklUser,
|
|
SimklWatchList,
|
|
} from "../simkl/types/simklTypes";
|
|
import {
|
|
type AniListUser,
|
|
MediaListSort,
|
|
} from "../anilist/types/AniListTypes";
|
|
import type {
|
|
MALAnime,
|
|
MALWatchlist,
|
|
MyAnimeListUser,
|
|
} from "../mal/types/MALTypes";
|
|
import type { TableItems } from "../helperTypes/TableTypes";
|
|
import { AniListGetSingleAnimeDefaultData } from "../helperDefaults/AniListGetSingleAnime";
|
|
|
|
export let aniListAnime = writable(AniListGetSingleAnimeDefaultData);
|
|
export let title = writable("");
|
|
export let aniListLoggedIn = writable(false);
|
|
export let simklLoggedIn = writable(false);
|
|
export let malLoggedIn = writable(false);
|
|
export const serviceLoggingIn = writable([] as string[]);
|
|
export let simklWatchList = writable({} as SimklWatchList);
|
|
export let aniListPrimary = writable(true);
|
|
export let simklPrimary = writable(false);
|
|
export let malPrimary = writable(false);
|
|
export let simklUser = writable({} as SimklUser);
|
|
export let aniListUser = writable({} as AniListUser);
|
|
export let malUser = writable({} as MyAnimeListUser);
|
|
export let aniListWatchlist = writable({} as AniListCurrentUserWatchList);
|
|
export let malWatchList = writable({} as MALWatchlist);
|
|
export let malAnime = writable({} as MALAnime);
|
|
export let simklAnime = writable({} as SimklAnime);
|
|
export let loading = writable(false);
|
|
export let tableItems = writable([] as TableItems);
|
|
export let watchlistNeedsRefresh = writable(false);
|
|
export let aniListSort = writable(MediaListSort.UpdatedTimeDesc);
|
|
|
|
export let watchListPage = writable(1);
|
|
export let animePerPage = writable(20);
|
|
|
|
let isAniListPrimary: boolean;
|
|
let page: number;
|
|
let perPage: number;
|
|
let sort: string;
|
|
let aniWatchlist: AniListCurrentUserWatchList;
|
|
let currentAniListAnime: AniListGetSingleAnime;
|
|
|
|
let isMalLoggedIn: boolean;
|
|
let isSimklLoggedIn: boolean;
|
|
|
|
aniListPrimary.subscribe((value) => (isAniListPrimary = value));
|
|
watchListPage.subscribe((value) => (page = value));
|
|
animePerPage.subscribe((value) => (perPage = value));
|
|
aniListWatchlist.subscribe((value) => (aniWatchlist = value));
|
|
malLoggedIn.subscribe((value) => (isMalLoggedIn = value));
|
|
simklLoggedIn.subscribe((value) => (isSimklLoggedIn = value));
|
|
aniListAnime.subscribe((value) => (currentAniListAnime = value));
|
|
aniListSort.subscribe((value) => (sort = value));
|
|
|
|
export interface ApiError {
|
|
service: string;
|
|
message: string;
|
|
statusCode?: string;
|
|
canRetry: boolean;
|
|
}
|
|
export const apiError = writable<ApiError | null>(null);
|
|
export const isApiDown = writable(false);
|
|
export function setApiError(
|
|
service: string,
|
|
message: string,
|
|
statusCode?: string,
|
|
canRetry: boolean = true,
|
|
) {
|
|
apiError.set({
|
|
service,
|
|
message,
|
|
statusCode,
|
|
canRetry,
|
|
});
|
|
isApiDown.set(true);
|
|
}
|
|
export function clearApiError() {
|
|
apiError.set(null);
|
|
isApiDown.set(false);
|
|
}
|
|
|
|
export async function GetAnimeSingleItem(
|
|
aniId: number,
|
|
login: boolean,
|
|
): Promise<""> {
|
|
await GetAniListItem(aniId, login).then((aniListResult) => {
|
|
let finalResult: AniListGetSingleAnime;
|
|
finalResult = aniListResult;
|
|
if (login === false) {
|
|
finalResult.data.MediaList.status = "";
|
|
finalResult.data.MediaList.score = 0;
|
|
finalResult.data.MediaList.progress = 0;
|
|
finalResult.data.MediaList.notes = "";
|
|
finalResult.data.MediaList.repeat = 0;
|
|
finalResult.data.MediaList.startedAt.day = 0;
|
|
finalResult.data.MediaList.startedAt.month = 0;
|
|
finalResult.data.MediaList.startedAt.year = 0;
|
|
finalResult.data.MediaList.completedAt.day = 0;
|
|
finalResult.data.MediaList.completedAt.month = 0;
|
|
finalResult.data.MediaList.completedAt.year = 0;
|
|
}
|
|
aniListAnime.set(finalResult);
|
|
title.set(
|
|
currentAniListAnime.data.MediaList.media.title.english === ""
|
|
? currentAniListAnime.data.MediaList.media.title.romaji
|
|
: currentAniListAnime.data.MediaList.media.title.english,
|
|
);
|
|
});
|
|
if (isMalLoggedIn) {
|
|
await GetMyAnimeListAnime(
|
|
currentAniListAnime.data.MediaList.media.idMal,
|
|
).then((malResult) => {
|
|
malAnime.set(malResult);
|
|
});
|
|
}
|
|
if (isSimklLoggedIn) {
|
|
await SimklSearch(currentAniListAnime.data.MediaList).then(
|
|
(value: SimklAnime) => {
|
|
simklAnime.set(value);
|
|
},
|
|
);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
export function setServiceLoggingIn(service: string, isLoggingIn: boolean): void {
|
|
serviceLoggingIn.update((services) => {
|
|
if (isLoggingIn) {
|
|
return services.includes(service) ? services : [...services, service];
|
|
}
|
|
return services.filter((s) => s !== service);
|
|
});
|
|
}
|
|
|
|
export function isServiceLoggingIn(service: string): boolean {
|
|
let loggingIn = false;
|
|
serviceLoggingIn.subscribe((services) => {
|
|
loggingIn = services.includes(service);
|
|
})();
|
|
return loggingIn;
|
|
}
|
|
|
|
export function loginToSimkl(): void {
|
|
setServiceLoggingIn("simkl", true);
|
|
GetSimklLoggedInUser()
|
|
.then((user) => {
|
|
if (Object.keys(user).length === 0) {
|
|
simklLoggedIn.set(false);
|
|
} else {
|
|
simklUser.set(user);
|
|
SimklGetUserWatchlist().then((result) => {
|
|
simklWatchList.set(result);
|
|
simklLoggedIn.set(true);
|
|
});
|
|
}
|
|
})
|
|
.finally(() => setServiceLoggingIn("simkl", false));
|
|
}
|
|
|
|
export function loginToAniList(): void {
|
|
setServiceLoggingIn("anilist", true);
|
|
GetAniListLoggedInUser()
|
|
.then((result) => {
|
|
aniListUser.set(result);
|
|
if (isAniListPrimary) {
|
|
GetAniListUserWatchingList(page, perPage, sort).then((result) => {
|
|
aniListWatchlist.set(result);
|
|
aniListLoggedIn.set(true);
|
|
});
|
|
} else {
|
|
aniListLoggedIn.set(true);
|
|
}
|
|
})
|
|
.finally(() => setServiceLoggingIn("anilist", false));
|
|
}
|
|
|
|
export function loginToMAL(): void {
|
|
setServiceLoggingIn("mal", true);
|
|
GetMyAnimeListLoggedInUser()
|
|
.then((result) => {
|
|
if (!result.name) {
|
|
malUser.set({} as MyAnimeListUser);
|
|
malLoggedIn.set(false);
|
|
return;
|
|
}
|
|
malUser.set(result);
|
|
malLoggedIn.set(true);
|
|
})
|
|
.finally(() => setServiceLoggingIn("mal", false));
|
|
}
|
|
|
|
export function logoutOfAniList(): void {
|
|
LogoutAniList().then((result) => {
|
|
console.log(result);
|
|
if (Object.keys(aniWatchlist).length !== 0) {
|
|
aniListWatchlist.set({} as AniListCurrentUserWatchList);
|
|
}
|
|
aniListUser.set({} as AniListUser);
|
|
aniListLoggedIn.set(false);
|
|
});
|
|
}
|
|
|
|
export function logoutOfMAL(): void {
|
|
LogoutMyAnimeList().then((result) => {
|
|
console.log(result);
|
|
malUser.set({} as MyAnimeListUser);
|
|
malLoggedIn.set(false);
|
|
});
|
|
}
|
|
|
|
export function logoutOfSimkl(): void {
|
|
LogoutSimkl().then((result) => {
|
|
console.log(result);
|
|
simklUser.set({} as SimklUser);
|
|
simklLoggedIn.set(false);
|
|
});
|
|
}
|
|
</script>
|