5 Commits
0.5.3 ... 0.6.0

Author SHA1 Message Date
b2a8a504f3 fix: resolve syntax error in App.svelte
Fixed TypeScript compilation error caused by import statement and function declaration being on the same line.

Changes:
- Separated import statement and onMount declaration onto different lines
- Resolved svelte-preprocess type error
- File now compiles correctly

This was a typo from previous commit where the loc import line was incorrectly merged with the existing onMount function declaration.
2026-03-21 13:28:33 -04:00
c85a53a278 chore: remove VSCode extensions.json
Removed the .vscode/extensions.json file from the frontend directory.

This file contained workspace-level VSCode extension recommendations which are better managed:
- At user level through personal VSCode settings
- Through project README documentation
- Via devcontainer or editors preferences if needed

Cleanup reduces repository clutter and avoids imposing specific extension recommendations on contributors.
2026-03-21 13:25:49 -04:00
2cf3844e76 chore: bump version to 0.6.0
Incremented version from 0.5.3 to 0.6.0 for release with new features.

This release includes:
- Smart watchlist refresh on navigation
- Improved WatchList UI with manual refresh button
- Client-side routing for logo navigation
- Better UX with automatic data updates

Version bump reflects significant feature additions and improvements to the user experience.
2026-03-21 13:25:46 -04:00
6ed5fe8b71 feat: improve WatchList UI with refresh button
Enhanced the WatchList component with better layout and manual refresh functionality.

Changes:
- Added Refresh WatchList button with loading state handling
- Restructured header layout using flexbox with justify-between
- Title on left, refresh button on right, vertically aligned with items-center
- Improved button styling with consistent py-2 px-4 padding
- Added CheckIfAniListLoggedInAndLoadWatchList import for refresh functionality
- Maintained mb-4 spacing for consistent vertical rhythm

This gives users manual control over watchlist updates and provides better visual balance to the header section.

UI improvements:
- Horizontal flex container for proper left/right alignment
- Responsive button sizing
- Clear visual separation between title and action
2026-03-21 13:25:45 -04:00
8a8baf7f8f feat: implement smart watchlist refresh on navigation
Added intelligent watchlist refresh mechanism that only refetches data when changes are actually made, preventing unnecessary API calls and improving performance.

Changes:
- Added watchlistNeedsRefresh store to track when watchlist data has changed
- Implemented reactive watcher in App.svelte that uses svelte-spa-router's loc store to detect navigation to home
- Set dirty flag in Anime.svelte after successful status updates and entry deletions
- Added conditional refresh logic that checks user's primary service (AniList, MAL, or Simkl)
- Parallel refresh support for multiple services when logged in

This resolves the issue where clicking the logo would cause full page reloads and unnecessary re-authentication checks, while also ensuring watchlist data stays current when users make changes.

Technical details:
- Uses $loc.location to detect route changes
- IIFE pattern for async operations in reactive statements
- Only refreshes for logged-in primary services
- Flag resets after successful refresh

Related to: Header.svelte client-side routing fix
2026-03-21 13:25:43 -04:00
6 changed files with 330 additions and 247 deletions

View File

@@ -1,5 +0,0 @@
{
"recommendations": [
"svelte.svelte-vscode"
]
}

View File

@@ -3,40 +3,68 @@
aniListLoggedIn, aniListLoggedIn,
malLoggedIn, malLoggedIn,
simklLoggedIn, simklLoggedIn,
watchlistNeedsRefresh,
aniListPrimary,
malPrimary,
simklPrimary,
malWatchList,
simklWatchList,
} from "./helperModules/GlobalVariablesAndHelperFunctions.svelte"; } from "./helperModules/GlobalVariablesAndHelperFunctions.svelte";
import {onMount} from "svelte"; import { onMount } from "svelte";
import Router from "svelte-spa-router" import Router from "svelte-spa-router";
import Home from "./routes/Home.svelte"; import Home from "./routes/Home.svelte";
import {wrap} from "svelte-spa-router/wrap"; import { wrap } from "svelte-spa-router/wrap";
import Spinner from "./helperComponents/Spinner.svelte"; import Spinner from "./helperComponents/Spinner.svelte";
import Header from "./helperComponents/Header.svelte"; import Header from "./helperComponents/Header.svelte";
import {CheckIfAniListLoggedInAndLoadWatchList} from "./helperModules/CheckIfAniListLoggedInAndLoadWatchList.svelte"; import { CheckIfAniListLoggedInAndLoadWatchList } from "./helperModules/CheckIfAniListLoggedInAndLoadWatchList.svelte";
import { CheckIfMALLoggedInAndSetUser } from "./helperModules/CheckIfMyAnimeListLoggedIn.svelte"; import { CheckIfMALLoggedInAndSetUser } from "./helperModules/CheckIfMyAnimeListLoggedIn.svelte";
import {CheckIfSimklLoggedInAndSetUser} from "./helperModules/CheckIsSimklLoggedIn.svelte" import { CheckIfSimklLoggedInAndSetUser } from "./helperModules/CheckIsSimklLoggedIn.svelte";
import {CheckIfAniListLoggedIn} from "../wailsjs/go/main/App"; import {
CheckIfAniListLoggedIn,
GetMyAnimeList,
SimklGetUserWatchlist,
} from "../wailsjs/go/main/App";
import { loc } from "svelte-spa-router";
onMount(async () => { onMount(async () => {
let isAniListLoggedIn: boolean let isAniListLoggedIn: boolean;
let isMALLoggedIn: boolean let isMALLoggedIn: boolean;
let isSimklLoggedIn: boolean let isSimklLoggedIn: boolean;
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value) aniListLoggedIn.subscribe((value) => (isAniListLoggedIn = value));
malLoggedIn.subscribe((value) => isMALLoggedIn = value) malLoggedIn.subscribe((value) => (isMALLoggedIn = value));
simklLoggedIn.subscribe((value) => isSimklLoggedIn = value) simklLoggedIn.subscribe((value) => (isSimklLoggedIn = value));
console.log(isAniListLoggedIn) !isAniListLoggedIn && (await CheckIfAniListLoggedInAndLoadWatchList());
!isAniListLoggedIn && await CheckIfAniListLoggedInAndLoadWatchList() !isMALLoggedIn && (await CheckIfMALLoggedInAndSetUser());
!isMALLoggedIn && await CheckIfMALLoggedInAndSetUser() !isSimklLoggedIn && (await CheckIfSimklLoggedInAndSetUser());
!isSimklLoggedIn && await CheckIfSimklLoggedInAndSetUser() });
})
$: if ($loc?.location === "/" && $watchlistNeedsRefresh) {
(async () => {
if ($aniListLoggedIn && $aniListPrimary) {
await CheckIfAniListLoggedInAndLoadWatchList();
}
if ($malLoggedIn && $malPrimary) {
await GetMyAnimeList(1000).then((w) => malWatchList.set(w));
}
if ($simklLoggedIn && $simklPrimary) {
await SimklGetUserWatchlist().then((w) => simklWatchList.set(w));
}
watchlistNeedsRefresh.set(false);
})();
}
</script> </script>
<Header /> <Header />
<Router routes={{ <Router
'/': Home, routes={{
'/anime/:id': wrap({ "/": Home,
asyncComponent: () => import('./routes/AnimeRoutePage.svelte'), "/anime/:id": wrap({
asyncComponent: () => import("./routes/AnimeRoutePage.svelte"),
conditions: [async () => await CheckIfAniListLoggedIn()], conditions: [async () => await CheckIfAniListLoggedIn()],
loadingComponent: Spinner loadingComponent: Spinner,
}), }),
// '*': "Not Found" // '*': "Not Found"
}} /> }}
/>

View File

@@ -6,6 +6,7 @@
malLoggedIn, malLoggedIn,
simklAnime, simklAnime,
simklLoggedIn, simklLoggedIn,
watchlistNeedsRefresh,
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"; } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import WebsiteLink from "./WebsiteLink.svelte"; import WebsiteLink from "./WebsiteLink.svelte";
@@ -362,6 +363,7 @@
} finally { } finally {
submitting.set(false); submitting.set(false);
submitSuccess.set(true); submitSuccess.set(true);
watchlistNeedsRefresh.set(true);
setTimeout(() => submitSuccess.set(false), 2000); setTimeout(() => submitSuccess.set(false), 2000);
} }
}; };
@@ -422,6 +424,7 @@
} finally { } finally {
submitting.set(false); submitting.set(false);
submitSuccess.set(true); submitSuccess.set(true);
watchlistNeedsRefresh.set(true);
setTimeout(() => submitSuccess.set(false), 2000); setTimeout(() => submitSuccess.set(false), 2000);
} }
}; };
@@ -702,6 +705,7 @@
Sync Changes Sync Changes
</button> </button>
<button <button
type="button"
class="text-white bg-gray-800 border border-gray-600 focus:outline-none hover:bg-gray-700 focus:ring-4 class="text-white bg-gray-800 border border-gray-600 focus:outline-none hover:bg-gray-700 focus:ring-4
focus:ring-gray-700 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 focus:ring-gray-700 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2
hover:border-gray-600" hover:border-gray-600"

View File

@@ -5,31 +5,51 @@
GetAnimeSingleItem, GetAnimeSingleItem,
loading, loading,
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"; } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
import {push} from "svelte-spa-router"; import { push } from "svelte-spa-router";
import type {AniListCurrentUserWatchList} from "../anilist/types/AniListCurrentUserWatchListType" import type { AniListCurrentUserWatchList } from "../anilist/types/AniListCurrentUserWatchListType";
import {Rating} from "flowbite-svelte"; import { Rating } from "flowbite-svelte";
import loader from '../helperFunctions/loader' import loader from "../helperFunctions/loader";
import { CheckIfAniListLoggedInAndLoadWatchList } from "../helperModules/CheckIfAniListLoggedInAndLoadWatchList.svelte";
let isAniListLoggedIn: boolean;
let aniListWatchListLoaded: AniListCurrentUserWatchList;
let isAniListLoggedIn: boolean aniListLoggedIn.subscribe((value) => (isAniListLoggedIn = value));
let aniListWatchListLoaded: AniListCurrentUserWatchList aniListWatchlist.subscribe((value) => (aniListWatchListLoaded = value));
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
aniListWatchlist.subscribe((value) => aniListWatchListLoaded = value)
</script> </script>
<div> <div>
{#if isAniListLoggedIn} {#if isAniListLoggedIn}
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center"> <div
<h1 class="text-left text-xl font-bold mb-4">Your AniList WatchList</h1> class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center"
>
<div class="flex justify-between items-center mb-4">
<h1 class="text-left text-xl font-bold">Your AniList WatchList</h1>
<button
type="button"
class="py-2 px-4 bg-gray-700 rounded-lg"
on:click={async () => {
loading.set(true);
await CheckIfAniListLoggedInAndLoadWatchList();
loading.set(false);
}}
>
Refresh WatchList
</button>
</div>
<div class="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8"> <div
class="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8"
>
{#each aniListWatchListLoaded.data.Page.mediaList as media} {#each aniListWatchListLoaded.data.Page.mediaList as media}
<div use:loader={loading} class="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg xl:aspect-h-8 xl:aspect-w-7"> <div
use:loader={loading}
class="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg xl:aspect-h-8 xl:aspect-w-7"
>
<div class="flex flex-col items-center group"> <div class="flex flex-col items-center group">
<button on:click={() => { <button
push(`#/anime/${media.media.id}`) on:click={() => {
push(`#/anime/${media.media.id}`);
// loading.set(true) // loading.set(true)
// GetAniListSingleItem(media.media.id, true).then(() => { // GetAniListSingleItem(media.media.id, true).then(() => {
// loading.set(false) // loading.set(false)
@@ -37,27 +57,38 @@
// }) // })
}} }}
> >
<img class="rounded-lg" src={media.media.coverImage.large} alt={ <img
media.media.title.english === "" ? class="rounded-lg"
media.media.title.romaji : src={media.media.coverImage.large}
media.media.title.english alt={media.media.title.english === ""
}/> ? media.media.title.romaji
: media.media.title.english}
/>
</button> </button>
<Rating id="anime-rating" total={5} size={35} rating={media.score/2.0}/> <Rating
<button class="mt-4 text-md font-semibold text-white-700" id="anime-rating"
on:click={() => GetAnimeSingleItem(media.media.id, true)}> total={5}
{ size={35}
media.media.title.english === "" ? rating={media.score / 2.0}
media.media.title.romaji : />
media.media.title.english <button
} class="mt-4 text-md font-semibold text-white-700"
on:click={() => GetAnimeSingleItem(media.media.id, true)}
>
{media.media.title.english === ""
? media.media.title.romaji
: media.media.title.english}
</button> </button>
<p class="mt-1 text-lg font-medium text-white-900">{media.progress} <p class="mt-1 text-lg font-medium text-white-900">
/ {media.media.nextAiringEpisode.episode !== 0 ? {media.progress}
media.media.nextAiringEpisode.episode - 1 : media.media.episodes}</p> / {media.media.nextAiringEpisode.episode !== 0
? media.media.nextAiringEpisode.episode - 1
: media.media.episodes}
</p>
{#if media.media.episodes > 0} {#if media.media.episodes > 0}
<p class="mt-1 text-lg font-medium text-white-900">Total <p class="mt-1 text-lg font-medium text-white-900">
Episodes: {media.media.episodes}</p> Total Episodes: {media.media.episodes}
</p>
{/if} {/if}
</div> </div>
</div> </div>

View File

@@ -10,153 +10,178 @@
LogoutMyAnimeList, LogoutMyAnimeList,
LogoutSimkl, LogoutSimkl,
SimklGetUserWatchlist, SimklGetUserWatchlist,
SimklSearch SimklSearch,
} from "../../wailsjs/go/main/App"; } from "../../wailsjs/go/main/App";
import type { import type {
AniListCurrentUserWatchList, AniListCurrentUserWatchList,
AniListGetSingleAnime AniListGetSingleAnime,
} from "../anilist/types/AniListCurrentUserWatchListType.js"; } from "../anilist/types/AniListCurrentUserWatchListType.js";
import {writable} from 'svelte/store' import { writable } from "svelte/store";
import type {SimklAnime, SimklUser, SimklWatchList} from "../simkl/types/simklTypes"; import type {
import {type AniListUser, MediaListSort} from "../anilist/types/AniListTypes"; SimklAnime,
import type {MALAnime, MALWatchlist, MyAnimeListUser} from "../mal/types/MALTypes"; SimklUser,
import type {TableItems} from "../helperTypes/TableTypes"; SimklWatchList,
import {AniListGetSingleAnimeDefaultData} from "../helperDefaults/AniListGetSingleAnime"; } 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 aniListAnime = writable(AniListGetSingleAnimeDefaultData);
export let title = writable("") export let title = writable("");
export let aniListLoggedIn = writable(false) export let aniListLoggedIn = writable(false);
export let simklLoggedIn = writable(false) export let simklLoggedIn = writable(false);
export let malLoggedIn = writable(false) export let malLoggedIn = writable(false);
export let simklWatchList = writable({} as SimklWatchList) export let simklWatchList = writable({} as SimklWatchList);
export let aniListPrimary = writable(true) export let aniListPrimary = writable(true);
export let simklPrimary = writable(false) export let simklPrimary = writable(false);
export let malPrimary = writable(false) export let malPrimary = writable(false);
export let simklUser = writable({} as SimklUser) export let simklUser = writable({} as SimklUser);
export let aniListUser = writable({} as AniListUser) export let aniListUser = writable({} as AniListUser);
export let malUser = writable({} as MyAnimeListUser) export let malUser = writable({} as MyAnimeListUser);
export let aniListWatchlist = writable({} as AniListCurrentUserWatchList) export let aniListWatchlist = writable({} as AniListCurrentUserWatchList);
export let malWatchList = writable({} as MALWatchlist) export let malWatchList = writable({} as MALWatchlist);
export let malAnime = writable({} as MALAnime) export let malAnime = writable({} as MALAnime);
export let simklAnime = writable({} as SimklAnime) export let simklAnime = writable({} as SimklAnime);
export let loading = writable(false) export let loading = writable(false);
export let tableItems = writable([] as TableItems) export let tableItems = writable([] as TableItems);
export let watchlistNeedsRefresh = writable(false);
export let watchListPage = writable(1) export let watchListPage = writable(1);
export let animePerPage = writable(20) export let animePerPage = writable(20);
let isAniListPrimary: boolean let isAniListPrimary: boolean;
let page: number let page: number;
let perPage: number let perPage: number;
let aniWatchlist: AniListCurrentUserWatchList let aniWatchlist: AniListCurrentUserWatchList;
let currentAniListAnime: AniListGetSingleAnime let currentAniListAnime: AniListGetSingleAnime;
let isMalLoggedIn: boolean let isMalLoggedIn: boolean;
let isSimklLoggedIn: boolean let isSimklLoggedIn: boolean;
aniListPrimary.subscribe(value => isAniListPrimary = value) aniListPrimary.subscribe((value) => (isAniListPrimary = value));
watchListPage.subscribe(value => page = value) watchListPage.subscribe((value) => (page = value));
animePerPage.subscribe(value => perPage = value) animePerPage.subscribe((value) => (perPage = value));
aniListWatchlist.subscribe(value => aniWatchlist = value) aniListWatchlist.subscribe((value) => (aniWatchlist = value));
malLoggedIn.subscribe(value => isMalLoggedIn = value) malLoggedIn.subscribe((value) => (isMalLoggedIn = value));
simklLoggedIn.subscribe(value => isSimklLoggedIn = value) simklLoggedIn.subscribe((value) => (isSimklLoggedIn = value));
aniListAnime.subscribe(value => currentAniListAnime = value) aniListAnime.subscribe((value) => (currentAniListAnime = value));
export async function GetAnimeSingleItem(
export async function GetAnimeSingleItem(aniId: number, login: boolean): Promise<""> { aniId: number,
await GetAniListItem(aniId, login).then(aniListResult => { login: boolean,
let finalResult: AniListGetSingleAnime ): Promise<""> {
finalResult = aniListResult await GetAniListItem(aniId, login).then((aniListResult) => {
let finalResult: AniListGetSingleAnime;
finalResult = aniListResult;
if (login === false) { if (login === false) {
finalResult.data.MediaList.status = "" finalResult.data.MediaList.status = "";
finalResult.data.MediaList.score = 0 finalResult.data.MediaList.score = 0;
finalResult.data.MediaList.progress = 0 finalResult.data.MediaList.progress = 0;
finalResult.data.MediaList.notes = "" finalResult.data.MediaList.notes = "";
finalResult.data.MediaList.repeat = 0 finalResult.data.MediaList.repeat = 0;
finalResult.data.MediaList.startedAt.day = 0 finalResult.data.MediaList.startedAt.day = 0;
finalResult.data.MediaList.startedAt.month = 0 finalResult.data.MediaList.startedAt.month = 0;
finalResult.data.MediaList.startedAt.year = 0 finalResult.data.MediaList.startedAt.year = 0;
finalResult.data.MediaList.completedAt.day = 0 finalResult.data.MediaList.completedAt.day = 0;
finalResult.data.MediaList.completedAt.month = 0 finalResult.data.MediaList.completedAt.month = 0;
finalResult.data.MediaList.completedAt.year = 0 finalResult.data.MediaList.completedAt.year = 0;
} }
aniListAnime.set(finalResult) aniListAnime.set(finalResult);
title.set(currentAniListAnime.data.MediaList.media.title.english === "" ? title.set(
currentAniListAnime.data.MediaList.media.title.romaji : currentAniListAnime.data.MediaList.media.title.english === ""
currentAniListAnime.data.MediaList.media.title.english) ? currentAniListAnime.data.MediaList.media.title.romaji
}) : currentAniListAnime.data.MediaList.media.title.english,
);
});
if (isMalLoggedIn) { if (isMalLoggedIn) {
await GetMyAnimeListAnime(currentAniListAnime.data.MediaList.media.idMal).then(malResult => { await GetMyAnimeListAnime(
malAnime.set(malResult) currentAniListAnime.data.MediaList.media.idMal,
}) ).then((malResult) => {
malAnime.set(malResult);
});
} }
if (isSimklLoggedIn) { if (isSimklLoggedIn) {
await SimklSearch(currentAniListAnime.data.MediaList).then((value: SimklAnime) => { await SimklSearch(currentAniListAnime.data.MediaList).then(
simklAnime.set(value) (value: SimklAnime) => {
}) simklAnime.set(value);
},
);
} }
return "" return "";
} }
export function loginToSimkl(): void { export function loginToSimkl(): void {
GetSimklLoggedInUser().then(user => { GetSimklLoggedInUser().then((user) => {
if (Object.keys(user).length === 0) { if (Object.keys(user).length === 0) {
simklLoggedIn.set(false) simklLoggedIn.set(false);
} else { } else {
simklUser.set(user) simklUser.set(user);
SimklGetUserWatchlist().then(result => { SimklGetUserWatchlist().then((result) => {
simklWatchList.set(result) simklWatchList.set(result);
simklLoggedIn.set(true) simklLoggedIn.set(true);
}) });
} }
}) });
} }
export function loginToAniList(): void { export function loginToAniList(): void {
GetAniListLoggedInUser().then(result => { GetAniListLoggedInUser().then((result) => {
aniListUser.set(result) aniListUser.set(result);
if (isAniListPrimary) { if (isAniListPrimary) {
GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((result) => { GetAniListUserWatchingList(
aniListWatchlist.set(result) page,
aniListLoggedIn.set(true) perPage,
}) MediaListSort.UpdatedTimeDesc,
).then((result) => {
aniListWatchlist.set(result);
aniListLoggedIn.set(true);
});
} else { } else {
aniListLoggedIn.set(true) aniListLoggedIn.set(true);
} }
}) });
} }
export function loginToMAL(): void { export function loginToMAL(): void {
GetMyAnimeListLoggedInUser().then(result => { GetMyAnimeListLoggedInUser().then((result) => {
malUser.set(result) malUser.set(result);
malLoggedIn.set(true) malLoggedIn.set(true);
}) });
} }
export function logoutOfAniList(): void { export function logoutOfAniList(): void {
LogoutAniList().then(result => { LogoutAniList().then((result) => {
console.log(result) console.log(result);
if (Object.keys(aniWatchlist).length !== 0) { if (Object.keys(aniWatchlist).length !== 0) {
aniListWatchlist.set({} as AniListCurrentUserWatchList) aniListWatchlist.set({} as AniListCurrentUserWatchList);
} }
aniListUser.set({} as AniListUser) aniListUser.set({} as AniListUser);
aniListLoggedIn.set(false) aniListLoggedIn.set(false);
}) });
} }
export function logoutOfMAL(): void { export function logoutOfMAL(): void {
LogoutMyAnimeList().then(result => { LogoutMyAnimeList().then((result) => {
console.log(result) console.log(result);
malUser.set({} as MyAnimeListUser) malUser.set({} as MyAnimeListUser);
malLoggedIn.set(false) malLoggedIn.set(false);
}) });
} }
export function logoutOfSimkl(): void { export function logoutOfSimkl(): void {
LogoutSimkl().then(result => { LogoutSimkl().then((result) => {
console.log(result) console.log(result);
simklUser.set({} as SimklUser) simklUser.set({} as SimklUser);
simklLoggedIn.set(false) simklLoggedIn.set(false);
}) });
} }
</script> </script>

View File

@@ -12,6 +12,6 @@
}, },
"info": { "info": {
"productName": "AniTrack", "productName": "AniTrack",
"productVersion": "0.5.3" "productVersion": "0.6.0"
} }
} }