Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3bfb31f8bf | |||
| 4739fb4344 | |||
| f4382304df | |||
| 4400dfd637 | |||
| b90d8eb2d3 | |||
| 1f796189b4 | |||
| 18daf41bf9 | |||
| d70153064f | |||
| 7960f8e26d | |||
| 2e5a4a4493 | |||
| 874b3952ee | |||
| 60eac10545 | |||
| 6d66d711ff | |||
| cd62e6c658 | |||
| 063c5016f3 | |||
| 5c4caf68e6 | |||
| c10e853564 | |||
| cd043d093f | |||
| 6db01f7f9f | |||
| 8460d56d55 | |||
| 8fedbe4607 | |||
| e069c47242 | |||
| aba0f2d1d5 | |||
| af6cb7f08a | |||
| 487e5ee5a8 | |||
| 631bd8b885 | |||
| b35be6926a | |||
| 5a9f4391dc | |||
| 72004c98b4 | |||
| 3db25bc33a | |||
| f3a1536953 | |||
| dc01aa314c | |||
| baed9a4a67 | |||
| 0e00120778 | |||
| 697692c277 | |||
| 3e82677c2c | |||
| b81549e5a6 | |||
| fd806df0a9 | |||
| 26f85dd412 | |||
| 4d9c54a116 | |||
| 068e568ec6 | |||
| 4e6f910e74 | |||
| b39f19f03a | |||
| 1a083deb54 | |||
| 61f8f5dd84 | |||
| 4509e479bc | |||
| ee8dd2e866 | |||
| 0c6a8a40c3 | |||
| 45845c2a69 | |||
| 3ec5eb1a03 | |||
| a2aa90edec | |||
| 0475d39c6c |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -29,4 +29,7 @@ package.json.md5
|
||||
package-lock.json
|
||||
.idea
|
||||
.env
|
||||
environment.go
|
||||
environment.go
|
||||
|
||||
# REST (http files)
|
||||
http-client.private.env.json
|
||||
|
||||
@@ -93,6 +93,7 @@ func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime {
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
genres
|
||||
tags{
|
||||
id
|
||||
name
|
||||
@@ -202,7 +203,7 @@ func (a *App) AniListSearch(query string) any {
|
||||
perPage
|
||||
}
|
||||
media (search: $search, type: $listType) {
|
||||
id
|
||||
id
|
||||
idMal
|
||||
title {
|
||||
romaji
|
||||
@@ -222,6 +223,7 @@ func (a *App) AniListSearch(query string) any {
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
genres
|
||||
tags{
|
||||
id
|
||||
name
|
||||
@@ -307,6 +309,7 @@ func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) Ani
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
genres
|
||||
tags{
|
||||
id
|
||||
name
|
||||
@@ -415,8 +418,8 @@ func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) AniListGetSi
|
||||
}{
|
||||
Query: `
|
||||
mutation(
|
||||
$mediaId:Int,
|
||||
$progress:Int,
|
||||
$mediaId:Int,
|
||||
$progress:Int,
|
||||
$status:MediaListStatus,
|
||||
$score:Float,
|
||||
$repeat:Int,
|
||||
@@ -425,15 +428,15 @@ func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) AniListGetSi
|
||||
$completedAt:FuzzyDateInput,
|
||||
){
|
||||
SaveMediaListEntry(
|
||||
mediaId:$mediaId,
|
||||
progress:$progress,
|
||||
mediaId:$mediaId,
|
||||
progress:$progress,
|
||||
status:$status,
|
||||
score:$score,
|
||||
repeat:$repeat,
|
||||
notes:$notes,
|
||||
startedAt:$startedAt
|
||||
completedAt:$completedAt
|
||||
){
|
||||
){
|
||||
id
|
||||
mediaId
|
||||
userId
|
||||
@@ -528,7 +531,7 @@ func (a *App) AniListDeleteEntry(mediaListId int) DeleteAniListReturn {
|
||||
){
|
||||
DeleteMediaListEntry(
|
||||
id:$id,
|
||||
){
|
||||
){
|
||||
deleted
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ type MediaList struct {
|
||||
TimeUntilAiring int `json:"timeUntilAiring"`
|
||||
Episode int `json:"episode"`
|
||||
} `json:"nextAiringEpisode"`
|
||||
Tags []struct {
|
||||
Genres []string `json:"genres"`
|
||||
Tags []struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
|
||||
@@ -308,7 +308,16 @@ func refreshMyAnimeListAuthorizationToken() {
|
||||
|
||||
func (a *App) GetMyAnimeListLoggedInUser() MyAnimeListUser {
|
||||
a.MyAnimeListLogin()
|
||||
user := createUser()
|
||||
if user.Name == "" {
|
||||
refreshMyAnimeListAuthorizationToken()
|
||||
user = createUser()
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
func createUser() MyAnimeListUser {
|
||||
client := &http.Client{}
|
||||
|
||||
req, _ := http.NewRequest("GET", "https://api.myanimelist.net/v2/users/@me?fields=anime_statistics", nil)
|
||||
@@ -335,6 +344,7 @@ func (a *App) GetMyAnimeListLoggedInUser() MyAnimeListUser {
|
||||
}
|
||||
|
||||
return user
|
||||
|
||||
}
|
||||
|
||||
func (a *App) LogoutMyAnimeList() string {
|
||||
|
||||
@@ -262,7 +262,6 @@ func (a *App) SimklSearch(aniListAnime MediaList) SimklAnime {
|
||||
if len(anime) == 0 {
|
||||
url = "https://api.simkl.com/search/id?mal=" + strconv.Itoa(aniListAnime.Media.IDMal)
|
||||
respBody = SimklHelper("GET", url, nil)
|
||||
fmt.Println(string(respBody))
|
||||
err = json.Unmarshal(respBody, &anime)
|
||||
}
|
||||
|
||||
|
||||
15
app.go
15
app.go
@@ -3,9 +3,11 @@ package main
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
@@ -43,3 +45,14 @@ func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceDa
|
||||
runtime.Show(*wailsContext)
|
||||
go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs)
|
||||
}
|
||||
|
||||
func (a *App) ShowVersion() {
|
||||
version := gjson.Get(wailsJSON, "info.productVersion")
|
||||
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
|
||||
Title: "Version",
|
||||
Message: "AniTrack Version: " + version.String(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ body:graphql {
|
||||
media {
|
||||
id
|
||||
idMal
|
||||
genres
|
||||
tags {
|
||||
id
|
||||
name
|
||||
|
||||
@@ -33,6 +33,7 @@ body:graphql {
|
||||
english
|
||||
native
|
||||
}
|
||||
genre
|
||||
description
|
||||
coverImage {
|
||||
large
|
||||
|
||||
@@ -12,7 +12,7 @@ post {
|
||||
|
||||
headers {
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
}
|
||||
|
||||
body:form-urlencoded {
|
||||
@@ -20,7 +20,7 @@ body:form-urlencoded {
|
||||
client_id: {{ANILIST_APP_ID}}
|
||||
client_secret: {{ANILIST_SECRET_TOKEN}}
|
||||
redirect_uri: http://localhost:6734/callback
|
||||
code: {{code}}
|
||||
code: {{ANILIST_CODE}}
|
||||
}
|
||||
|
||||
body:multipart-form {
|
||||
|
||||
@@ -9,7 +9,7 @@ vars {
|
||||
}
|
||||
vars:secret [
|
||||
ANILIST_ACCESS_TOKEN,
|
||||
code,
|
||||
ANILIST_CODE,
|
||||
SIMKL_AUTH_TOKEN,
|
||||
MAL_CODE,
|
||||
MAL_VERIFIER,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 53 KiB |
BIN
build/icon/128/AniTrack.png
Normal file
BIN
build/icon/128/AniTrack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
BIN
build/icon/32/AniTrack.png
Normal file
BIN
build/icon/32/AniTrack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
build/icon/48/AniTrack.png
Normal file
BIN
build/icon/48/AniTrack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
build/icon/64/AniTrack.png
Normal file
BIN
build/icon/64/AniTrack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
26
build/install_linux.sh
Executable file
26
build/install_linux.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# copy desktop file
|
||||
if [ -e "~/.local/share/applications/AniTrack.desktop" ]; then
|
||||
if [ -d "~/.local/share/applications/" ]; then
|
||||
cp ./AniTrack.desktop ~/.local/share/applications/
|
||||
else
|
||||
mkdir -p ~/.local/share/applications/
|
||||
cp ./AniTrack.desktop ~/.local/share/applications/
|
||||
fi
|
||||
fi
|
||||
|
||||
# copy icons to xdg folders
|
||||
for size in 32 48 64 128; do
|
||||
xdg-icon-resource install --novendor --context apps --size $size ./icon/$size/AniTrack.png AniTrack
|
||||
done
|
||||
|
||||
# copy AniTrack Binary to $HOME/Applications/
|
||||
if ! [ -d "~/Applications" ]; then
|
||||
mkdir -p ~/Applications
|
||||
cp ./bin/AniTrack ~/Applications/
|
||||
elif ! [[ -e ~/Applications/AniTrack ]]; then
|
||||
cp ./bin/AniTrack ~/Applications/
|
||||
fi
|
||||
|
||||
echo "AniTrack has been successfully installed."
|
||||
@@ -16,7 +16,7 @@
|
||||
"postcss": "^8.4.45",
|
||||
"svelte": "^4.0.0",
|
||||
"svelte-check": "^3.4.3",
|
||||
"svelte-headless-table": "^0.18.2",
|
||||
"svelte-headless-table": "^0.18.3",
|
||||
"svelte-preprocess": "^5.0.3",
|
||||
"svelte-spa-router": "^4.0.1",
|
||||
"tailwind-merge": "^2.5.2",
|
||||
|
||||
@@ -1,44 +1,27 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
aniListAnime,
|
||||
GetAnimeSingleItem,
|
||||
} from "./helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {onMount} from "svelte";
|
||||
import {userStore} from "./helperFunctions/userStore"
|
||||
import Router from "svelte-spa-router"
|
||||
import Home from "./routes/Home.svelte";
|
||||
import {wrap} from "svelte-spa-router/wrap";
|
||||
import Spinner from "./helperComponents/Spinner.svelte";
|
||||
import Header from "./helperComponents/Header.svelte";
|
||||
import {CheckIfAniListLoggedInAndLoadWatchList} from "./helperModules/CheckIfAniListLoggedInAndLoadWatchList.svelte";
|
||||
import { CheckIfMALLoggedInAndSetUser } from "./helperModules/CheckIfMyAnimeListLoggedIn.svelte";
|
||||
import {CheckIfSimklLoggedInAndSetUser} from "./helperModules/CheckIsSimklLoggedIn.svelte"
|
||||
import {CheckIfAniListLoggedIn} from "../wailsjs/go/main/App";
|
||||
import {AniListGetSingleAnimeDefaultData} from "./helperDefaults/AniListGetSingleAnime";
|
||||
|
||||
onMount(async () => {
|
||||
await CheckIfAniListLoggedInAndLoadWatchList()
|
||||
await CheckIfMALLoggedInAndSetUser()
|
||||
await CheckIfSimklLoggedInAndSetUser()
|
||||
await userStore.checkProvider('anilist')
|
||||
await userStore.checkProvider('mal')
|
||||
await userStore.checkProvider('simkl')
|
||||
})
|
||||
</script>
|
||||
|
||||
<Header />
|
||||
<Router routes={{
|
||||
'/': Home,
|
||||
'/anime/:id': wrap({
|
||||
asyncComponent: () => import('./routes/AnimeRoutePage.svelte'),
|
||||
conditions: [
|
||||
async () => await CheckIfAniListLoggedIn(),
|
||||
async (detail) => {
|
||||
aniListAnime.update(value => {
|
||||
value = AniListGetSingleAnimeDefaultData
|
||||
return value
|
||||
})
|
||||
await GetAnimeSingleItem(Number(detail.params.id), true)
|
||||
return Object.keys($aniListAnime).length!==0
|
||||
},
|
||||
],
|
||||
loadingComponent: Spinner
|
||||
}),
|
||||
// '*': "Not Found"
|
||||
}} />
|
||||
{#if $userStore.anilist.isLoggedIn}
|
||||
<Header />
|
||||
<Router routes={{
|
||||
'/': Home,
|
||||
'/anime/:id': wrap({
|
||||
asyncComponent: () => import('./routes/AnimeRoutePage.svelte'),
|
||||
loadingComponent: Spinner
|
||||
}),
|
||||
// '*': "Not Found"
|
||||
}} />
|
||||
{/if}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
export interface AniListCurrentUserWatchList {
|
||||
data: {
|
||||
Page: {
|
||||
pageInfo: {
|
||||
total: number
|
||||
perPage: number
|
||||
currentPage: number
|
||||
lastPage: number
|
||||
hasNextPage: boolean
|
||||
},
|
||||
mediaList: MediaList[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface AniListGetSingleAnime {
|
||||
data: {
|
||||
MediaList: MediaList
|
||||
}
|
||||
}
|
||||
|
||||
export interface MediaList {
|
||||
id: number
|
||||
mediaId: number
|
||||
userId: number
|
||||
media: {
|
||||
id: number
|
||||
idMal: number
|
||||
title: {
|
||||
romaji: string
|
||||
english?: string
|
||||
native: string
|
||||
}
|
||||
description: string
|
||||
coverImage: {
|
||||
large: string
|
||||
}
|
||||
season: string
|
||||
seasonYear: number
|
||||
status: string
|
||||
episodes?: number
|
||||
nextAiringEpisode?: {
|
||||
airingAt: number
|
||||
timeUntilAiring: number
|
||||
episode: number
|
||||
}
|
||||
}
|
||||
status: string
|
||||
startedAt: {
|
||||
year: number
|
||||
month: number
|
||||
day: number
|
||||
}
|
||||
completedAt: {
|
||||
year?: number
|
||||
month?: number
|
||||
day?: number
|
||||
}
|
||||
notes?: string
|
||||
progress: number
|
||||
score: number
|
||||
repeat: number
|
||||
user: {
|
||||
id: number
|
||||
name: string
|
||||
avatar: {
|
||||
large: string
|
||||
medium: string
|
||||
}
|
||||
statistics: {
|
||||
anime: {
|
||||
count: number
|
||||
statuses: [{
|
||||
status: string
|
||||
count: number
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import type {AniListGetSingleAnime} from "../anilist/types/AniListCurrentUserWatchListType";
|
||||
import type {AniListGetSingleAnime} from "../types/AniListCurrentUserWatchListType";
|
||||
|
||||
export const AniListGetSingleAnimeDefaultData: AniListGetSingleAnime = {
|
||||
export const AniListGetSingleAnimeDefaultData: AniListGetSingleAnime = {
|
||||
data: {
|
||||
MediaList: {
|
||||
id: 0,
|
||||
@@ -26,7 +26,18 @@ export const AniListGetSingleAnimeDefaultData: AniListGetSingleAnime = {
|
||||
airingAt: 0,
|
||||
timeUntilAiring: 0,
|
||||
episode: 0,
|
||||
}
|
||||
},
|
||||
tags: [
|
||||
{
|
||||
id: 0,
|
||||
name: "",
|
||||
description: "",
|
||||
rank: 0,
|
||||
isMediaSpoiler: false,
|
||||
isAdult: false
|
||||
}
|
||||
],
|
||||
isAdult: false
|
||||
},
|
||||
status: "",
|
||||
startedAt: {
|
||||
89
frontend/src/defaults/AniListWatchListDefaultData.ts
Normal file
89
frontend/src/defaults/AniListWatchListDefaultData.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type {AniListCurrentUserWatchList} from "../types/AniListCurrentUserWatchListType"
|
||||
|
||||
export const AniListWatchListDefaultData: AniListCurrentUserWatchList = {
|
||||
data: {
|
||||
Page: {
|
||||
pageInfo: {
|
||||
total: 0,
|
||||
perPage: 0,
|
||||
currentPage: 0,
|
||||
lastPage: 0,
|
||||
hasNextPage: false
|
||||
},
|
||||
mediaList: [
|
||||
{
|
||||
id: 0,
|
||||
mediaId: 0,
|
||||
userId: 0,
|
||||
media: {
|
||||
id: 0,
|
||||
idMal: 0,
|
||||
title: {
|
||||
romaji: "",
|
||||
english: "",
|
||||
native: "",
|
||||
},
|
||||
description: "",
|
||||
coverImage: {
|
||||
large: "",
|
||||
},
|
||||
season: "",
|
||||
seasonYear: 0,
|
||||
status: "",
|
||||
episodes: 0,
|
||||
nextAiringEpisode: {
|
||||
airingAt: 0,
|
||||
timeUntilAiring: 0,
|
||||
episode: 0,
|
||||
},
|
||||
tags: [
|
||||
{
|
||||
id: 0,
|
||||
name: "",
|
||||
description: "",
|
||||
rank: 0,
|
||||
isMediaSpoiler: false,
|
||||
isAdult: false,
|
||||
},
|
||||
],
|
||||
isAdult: false,
|
||||
},
|
||||
status: "",
|
||||
startedAt: {
|
||||
year: 0,
|
||||
month: 0,
|
||||
day: 0,
|
||||
},
|
||||
completedAt: {
|
||||
year: 0,
|
||||
month: 0,
|
||||
day: 0,
|
||||
},
|
||||
notes: "",
|
||||
progress: 0,
|
||||
score: 0,
|
||||
repeat: 0,
|
||||
user: {
|
||||
id: 0,
|
||||
name: "",
|
||||
avatar: {
|
||||
large: "",
|
||||
medium: "",
|
||||
},
|
||||
statistics: {
|
||||
anime: {
|
||||
count: 0,
|
||||
statuses: [
|
||||
{
|
||||
status: "",
|
||||
count: 0,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
67
frontend/src/defaults/UserTypes.ts
Normal file
67
frontend/src/defaults/UserTypes.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import type {AniListUser} from "../types/AniListTypes";
|
||||
import type {MyAnimeListUser} from "../types/MALTypes";
|
||||
import type {SimklUser} from "../types/simklTypes";
|
||||
|
||||
export const AniListUserDefaultData: AniListUser = {
|
||||
"data": {
|
||||
"Viewer": {
|
||||
id: 0,
|
||||
name: "",
|
||||
avatar: {
|
||||
large: "",
|
||||
medium: "",
|
||||
},
|
||||
bannerImage: "",
|
||||
siteUrl: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const MALUserDefaultData: MyAnimeListUser = {
|
||||
id: 0,
|
||||
name: "",
|
||||
picture: "",
|
||||
gender: "",
|
||||
birthday: "",
|
||||
location: "",
|
||||
joinedAt: "",
|
||||
AnimeStatistics: {
|
||||
numItemsWatching: 0,
|
||||
numItemsCompleted: 0,
|
||||
numItemsOnHold: 0,
|
||||
numItemsDropped: 0,
|
||||
numItemsPlanToWatch: 0,
|
||||
numItems: 0,
|
||||
numDaysWatched: 0,
|
||||
numDaysWatching: 0,
|
||||
numDaysCompleted: 0,
|
||||
numDaysOnHold: 0,
|
||||
numDaysDropped: 0,
|
||||
numDays: 0,
|
||||
numEpisodes: 0,
|
||||
numTimesRewatched: 0,
|
||||
meanScore: 0
|
||||
},
|
||||
timeZone: "",
|
||||
isSupporter: false
|
||||
}
|
||||
|
||||
export const SimklUserDefaultData: SimklUser = {
|
||||
user: {
|
||||
name: "",
|
||||
joined_at: "",
|
||||
gender: "",
|
||||
avatar: "",
|
||||
bio: "",
|
||||
loc: "",
|
||||
age: "",
|
||||
},
|
||||
account: {
|
||||
id: 0,
|
||||
timezone: "",
|
||||
type: "",
|
||||
},
|
||||
connections: {
|
||||
facebook: false
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
aniListAnime,
|
||||
aniListLoggedIn,
|
||||
malAnime,
|
||||
malLoggedIn,
|
||||
simklAnime,
|
||||
simklLoggedIn,
|
||||
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {userStore} from "../helperFunctions/userStore"
|
||||
import { push } from "svelte-spa-router";
|
||||
import { Button } from "flowbite-svelte";
|
||||
<<<<<<< HEAD
|
||||
import type { AniListGetSingleAnime } from "../types/AniListCurrentUserWatchListType";
|
||||
=======
|
||||
import WebsiteLink from "./WebsiteLink.svelte";
|
||||
import type { AniListGetSingleAnime } from "../anilist/types/AniListCurrentUserWatchListType";
|
||||
>>>>>>> a222c6b (feat(frontend): add genre display UI and enhance link component)
|
||||
import Rating from "./Rating.svelte";
|
||||
import {
|
||||
convertAniListDateToString,
|
||||
@@ -20,18 +22,15 @@
|
||||
MALAnime,
|
||||
MalListStatus,
|
||||
MALUploadStatus,
|
||||
} from "../mal/types/MALTypes";
|
||||
import type { SimklAnime } from "../simkl/types/simklTypes";
|
||||
} from "../types/MALTypes";
|
||||
import type { SimklAnime } from "../types/simklTypes";
|
||||
import { writable } from "svelte/store";
|
||||
import type {
|
||||
StatusOption,
|
||||
StatusOptions,
|
||||
} from "../helperTypes/StatusTypes";
|
||||
import type { AniListUpdateVariables } from "../anilist/types/AniListTypes";
|
||||
import {
|
||||
convertDateStringToAniList,
|
||||
convertDateToAniList,
|
||||
} from "../helperFunctions/convertDateToAniList";
|
||||
} from "../types/StatusTypes";
|
||||
import type { AniListUpdateVariables } from "../types/AniListTypes";
|
||||
import { convertDateToAniList } from "../helperFunctions/convertDateToAniList";
|
||||
import {
|
||||
AniListDeleteEntry,
|
||||
AniListUpdateEntry,
|
||||
@@ -43,13 +42,10 @@
|
||||
SimklSyncStatus,
|
||||
} from "../../wailsjs/go/main/App";
|
||||
import { AddAnimeServiceToTable } from "../helperModules/AddAnimeServiceToTable.svelte";
|
||||
import { CheckIfAniListLoggedInAndLoadWatchList } from "../helperModules/CheckIfAniListLoggedInAndLoadWatchList.svelte";
|
||||
import Datepicker from "./Datepicker.svelte";
|
||||
import { Badge, Tooltip } from "flowbite-svelte";
|
||||
const re = /^([0-9]{4})-([0-9]{2})-([0-9]{2})/;
|
||||
|
||||
let isAniListLoggedIn: boolean;
|
||||
let isMalLoggedIn: boolean;
|
||||
let isSimklLoggedIn: boolean;
|
||||
let currentAniListAnime: AniListGetSingleAnime;
|
||||
let currentMalAnime: MALAnime;
|
||||
let currentSimklAnime: SimklAnime;
|
||||
@@ -57,9 +53,6 @@
|
||||
let isSubmitting: boolean;
|
||||
let submitSuccess = writable(false);
|
||||
|
||||
aniListLoggedIn.subscribe((value) => (isAniListLoggedIn = value));
|
||||
malLoggedIn.subscribe((value) => (isMalLoggedIn = value));
|
||||
simklLoggedIn.subscribe((value) => (isSimklLoggedIn = value));
|
||||
aniListAnime.subscribe((value) => (currentAniListAnime = value));
|
||||
malAnime.subscribe((value) => (currentMalAnime = value));
|
||||
simklAnime.subscribe((value) => (currentSimklAnime = value));
|
||||
@@ -93,7 +86,7 @@
|
||||
currentAniListAnime.data.MediaList.completedAt,
|
||||
);
|
||||
|
||||
if (isAniListLoggedIn)
|
||||
if ($userStore.anilist.isLoggedIn)
|
||||
AddAnimeServiceToTable({
|
||||
id: `a-${currentAniListAnime.data.MediaList.mediaId}`,
|
||||
title,
|
||||
@@ -111,7 +104,7 @@
|
||||
notes: currentAniListAnime.data.MediaList.notes,
|
||||
});
|
||||
|
||||
if (isMalLoggedIn) {
|
||||
if ($userStore.mal.isLoggedIn) {
|
||||
let startDate = "";
|
||||
let finishDate = "";
|
||||
if (currentMalAnime.my_list_status.start_date !== "") {
|
||||
@@ -140,7 +133,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (isSimklLoggedIn && Object.keys(currentSimklAnime).length > 0)
|
||||
if ($userStore.simkl.isLoggedIn && Object.keys(currentSimklAnime).length > 0)
|
||||
AddAnimeServiceToTable({
|
||||
id: `s-${currentSimklAnime.show.ids.simkl}`,
|
||||
title: currentSimklAnime.show.title,
|
||||
@@ -201,7 +194,7 @@
|
||||
}
|
||||
|
||||
if (
|
||||
isAniListLoggedIn &&
|
||||
$userStore.anilist.isLoggedIn &&
|
||||
currentAniListAnime.data.MediaList.mediaId !== 0
|
||||
) {
|
||||
let body: AniListUpdateVariables = {
|
||||
@@ -216,9 +209,8 @@
|
||||
};
|
||||
await AniListUpdateEntry(body).then(
|
||||
(value: AniListGetSingleAnime) => {
|
||||
/* TODO in future when you inevitably add tags to typescript, until Anilist fixes the api bug
|
||||
where tags break the SaveMediaListEntry return, you'll want to use this delete line
|
||||
delete value.data.MediaList.media.tags */
|
||||
value.data.MediaList.media.tags =
|
||||
currentAniListAnime.data.MediaList.media.tags;
|
||||
aniListAnime.update((newValue) => {
|
||||
newValue = value;
|
||||
return newValue;
|
||||
@@ -243,7 +235,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
if (malLoggedIn && currentMalAnime.id !== 0) {
|
||||
if ($userStore.mal.isLoggedIn && currentMalAnime.id !== 0) {
|
||||
let body: MALUploadStatus = {
|
||||
status: submitData.status.mal,
|
||||
is_rewatching: submitData.repeat > 0,
|
||||
@@ -299,7 +291,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
if (simklLoggedIn && currentSimklAnime.show.ids.simkl !== 0) {
|
||||
if ($userStore.simkl.isLoggedIn && currentSimklAnime.show.ids.simkl !== 0) {
|
||||
if (
|
||||
currentSimklAnime.watched_episodes_count !== submitData.episodes
|
||||
) {
|
||||
@@ -383,7 +375,7 @@
|
||||
const deleteEntries = async () => {
|
||||
submitting.set(true);
|
||||
if (
|
||||
isAniListLoggedIn &&
|
||||
$userStore.anilist.isLoggedIn &&
|
||||
currentAniListAnime.data.MediaList.mediaId !== 0
|
||||
) {
|
||||
await AniListDeleteEntry(currentAniListAnime.data.MediaList.id);
|
||||
@@ -400,7 +392,7 @@
|
||||
notes: "",
|
||||
});
|
||||
}
|
||||
if (malLoggedIn && currentMalAnime.id !== 0) {
|
||||
if ($userStore.mal.isLoggedIn && currentMalAnime.id !== 0) {
|
||||
await DeleteMyAnimeListEntry(currentMalAnime.id);
|
||||
AddAnimeServiceToTable({
|
||||
id: `m-${currentMalAnime.id}`,
|
||||
@@ -415,7 +407,7 @@
|
||||
notes: "",
|
||||
});
|
||||
}
|
||||
if (simklLoggedIn && currentSimklAnime.show.ids.simkl !== 0) {
|
||||
if ($userStore.simkl.isLoggedIn && currentSimklAnime.show.ids.simkl !== 0) {
|
||||
await SimklSyncRemove(currentSimklAnime);
|
||||
AddAnimeServiceToTable({
|
||||
id: `s-${currentSimklAnime.show.ids.simkl}`,
|
||||
@@ -448,6 +440,7 @@
|
||||
currentAniListAnime.data.MediaList.media.nextAiringEpisode.episode -
|
||||
1;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={handleSubmit} class="container pt-3 pb-10">
|
||||
@@ -479,12 +472,27 @@
|
||||
type="button"
|
||||
id="decrement-button"
|
||||
data-input-counter-decrement="quantity-input"
|
||||
on:click={() =>
|
||||
(currentAniListAnime.data.MediaList.progress -= 1)}
|
||||
class="bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 hover:bg-gray-200 border border-gray-300 rounded-s-lg p-3 h-11 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none"
|
||||
on:click={() => {
|
||||
currentAniListAnime.data.MediaList.progress -= 1;
|
||||
if (
|
||||
currentAniListAnime.data.MediaList
|
||||
.progress <
|
||||
currentAniListAnime.data.MediaList.media
|
||||
.episodes
|
||||
) {
|
||||
startingAnilistStatusOption =
|
||||
statusOptions[0];
|
||||
if (
|
||||
currentAniListAnime.data.MediaList
|
||||
.repeat === 0
|
||||
)
|
||||
completedAtDate = null;
|
||||
}
|
||||
}}
|
||||
class="bg-gray-700 hover:bg-gray-600 border-gray-600 border rounded-s-lg p-3 h-11 focus:ring-gray-700 focus:ring-2 focus:outline-none"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 text-gray-900 dark:text-white"
|
||||
class="w-3 h-3 text-white"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
@@ -519,7 +527,7 @@
|
||||
.nextAiringEpisode.episode -
|
||||
1)
|
||||
? 'border-red-500 border-[2px] text-rose-300 focus:ring-red-500 focus:border-red-500'
|
||||
: 'bg-gray-700 hover:bg-gray-600 border-gray-600 text-white focus:ring-blue-500 focus:border-blue-500'} w-24"
|
||||
: 'bg-gray-700 hover:bg-gray-600 border-gray-600 text-white focus:ring-blue-500 focus:border-blue-500'}"
|
||||
bind:value={
|
||||
currentAniListAnime.data.MediaList.progress
|
||||
}
|
||||
@@ -529,12 +537,33 @@
|
||||
type="button"
|
||||
id="increment-button"
|
||||
data-input-counter-increment="quantity-input"
|
||||
on:click={() =>
|
||||
(currentAniListAnime.data.MediaList.progress += 1)}
|
||||
class="bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 hover:bg-gray-200 border border-gray-300 rounded-e-lg p-3 h-11 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none"
|
||||
on:click={() => {
|
||||
currentAniListAnime.data.MediaList.progress += 1;
|
||||
if (
|
||||
currentAniListAnime.data.MediaList.media
|
||||
.episodes ===
|
||||
currentAniListAnime.data.MediaList.progress
|
||||
) {
|
||||
startingAnilistStatusOption =
|
||||
statusOptions[2];
|
||||
completedAtDate = new Date();
|
||||
}
|
||||
if (
|
||||
currentAniListAnime.data.MediaList
|
||||
.progress -
|
||||
1 ===
|
||||
0
|
||||
) {
|
||||
startingAnilistStatusOption =
|
||||
statusOptions[0];
|
||||
if (startedAtDate === null)
|
||||
startedAtDate = new Date();
|
||||
}
|
||||
}}
|
||||
class="bg-gray-700 hover:bg-gray-600 border-gray-600 border rounded-e-lg p-3 h-11 focus:ring-gray-700 focus:ring-2 focus:outline-none"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 text-gray-900 dark:text-white"
|
||||
class="w-3 h-3 text-white"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
@@ -564,11 +593,10 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="status"
|
||||
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
||||
class="text-left block mb-2 text-sm font-medium text-white"
|
||||
>Status</label
|
||||
>
|
||||
<select
|
||||
@@ -636,7 +664,7 @@
|
||||
class="border {currentAniListAnime.data.MediaList
|
||||
.repeat < 0
|
||||
? 'border-red-500 border-[2px] text-rose-300 focus:ring-red-500 focus:border-red-500'
|
||||
: 'border-gray-500 text-white focus:ring-blue-500 focus:border-blue-500'} text-sm rounded-lg block w-24 p-2.5 bg-gray-600 placeholder-gray-400 text-white"
|
||||
: 'border-gray-500 focus:ring-blue-500 focus:border-blue-500'} text-sm rounded-lg block w-24 p-2.5 bg-gray-600 placeholder-gray-400 text-white"
|
||||
bind:value={currentAniListAnime.data.MediaList.repeat}
|
||||
required
|
||||
/>
|
||||
@@ -663,63 +691,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="external-data">
|
||||
<div
|
||||
id="anilist-data"
|
||||
class="flex flex-col md:flex-row md:pl-10 md:pr-10 pt-5 pb-5 justify-center md:gap-x-16 lg:gap-x-36 group"
|
||||
>
|
||||
<h2 class="text-left mb-1 text-base font-semibold text-white">
|
||||
AniList
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AnimeTable />
|
||||
|
||||
<div class="flex rounded-lg shadow max-w-4-4 bg-gray-800">
|
||||
<div
|
||||
class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-start"
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
id="delete-button"
|
||||
class="text-white bg-red-700 {$submitSuccess
|
||||
? 'bg-green-600 dark:bg-green-600 hover:bg-green-700 dark:hover:bg-green-700 focus:ring-4 focus:ring-green-800 dark:focus:ring-green-800'
|
||||
: 'bg-red-600 dark:bg-red-600 hover:bg-red-700 dark:hover:bg-red-700 focus:ring-4 focus:ring-red-800 dark:focus:ring-red-800'} font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 focus:outline-none"
|
||||
on:click={deleteEntries}
|
||||
>
|
||||
<svg
|
||||
id="submit-loader"
|
||||
aria-hidden="true"
|
||||
role="status"
|
||||
class="{isSubmitting
|
||||
? 'inline'
|
||||
: 'hidden'} w-4 h-4 me-3 text-white animate-spin"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="#E5E7EB"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
Delete Entries
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex mb-4 rounded-lg shadow max-w-4-4 bg-gray-800">
|
||||
<div
|
||||
class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-end"
|
||||
>
|
||||
<Button
|
||||
<button
|
||||
disabled={isSubmitting}
|
||||
id="sync-button"
|
||||
class="text-white {$submitSuccess
|
||||
? 'bg-green-600 dark:bg-green-600 hover:bg-green-700 dark:hover:bg-green-700 focus:ring-4 focus:ring-green-800 dark:focus:ring-green-800'
|
||||
: 'bg-blue-600 dark:bg-blue-600 hover:bg-blue-700 dark:hover:bg-blue-700 focus:ring-4 focus:ring-blue-800 dark:focus:ring-blue-800'} font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 focus:outline-none"
|
||||
class="text-white focus:ring-4 {$submitSuccess
|
||||
? 'bg-green-600 hover:bg-green-700 focus:ring-green-800'
|
||||
: 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-800'} font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 focus:outline-none"
|
||||
type="submit"
|
||||
>
|
||||
<svg
|
||||
@@ -743,23 +724,142 @@
|
||||
/>
|
||||
</svg>
|
||||
Sync Changes
|
||||
</Button>
|
||||
<Button
|
||||
</button>
|
||||
<button
|
||||
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 dark:bg-gray-800 dark:text-white
|
||||
dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700"
|
||||
focus:ring-gray-700 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2
|
||||
hover:border-gray-600"
|
||||
on:click={async () => {
|
||||
await CheckIfAniListLoggedInAndLoadWatchList();
|
||||
return push("/");
|
||||
}}
|
||||
>
|
||||
Go Home
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<AnimeTable />
|
||||
|
||||
<div class="flex rounded-lg shadow max-w-4-4 bg-gray-800">
|
||||
<div
|
||||
class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-start"
|
||||
>
|
||||
<button
|
||||
disabled={isSubmitting}
|
||||
id="delete-button"
|
||||
class="text-white focus:ring-4 {$submitSuccess
|
||||
? 'bg-green-600 hover:bg-green-700 focus:ring-green-800'
|
||||
: 'bg-red-600 hover:bg-red-700 focus:ring-red-800'} font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 focus:outline-none"
|
||||
on:click={deleteEntries}
|
||||
>
|
||||
<svg
|
||||
id="submit-loader"
|
||||
aria-hidden="true"
|
||||
role="status"
|
||||
class="{isSubmitting
|
||||
? 'inline'
|
||||
: 'hidden'} w-4 h-4 me-3 text-white animate-spin"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="#E5E7EB"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
Delete Entries
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-end"
|
||||
>
|
||||
<button
|
||||
disabled={isSubmitting}
|
||||
id="sync-button"
|
||||
class="text-white focus:ring-4 {$submitSuccess
|
||||
? 'bg-green-600 hover:bg-green-700 focus:ring-green-800'
|
||||
: 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-800'} font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 focus:outline-none"
|
||||
type="submit"
|
||||
>
|
||||
<svg
|
||||
id="submit-loader"
|
||||
aria-hidden="true"
|
||||
role="status"
|
||||
class="{isSubmitting
|
||||
? 'inline'
|
||||
: 'hidden'} w-4 h-4 me-3 text-white animate-spin"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="#E5E7EB"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
Sync Changes
|
||||
</button>
|
||||
<button
|
||||
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
|
||||
hover:border-gray-600"
|
||||
on:click={async () => {
|
||||
return push("/");
|
||||
}}
|
||||
>
|
||||
Go Home
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-2xl">Summary</h3>
|
||||
<p>{@html currentAniListAnime.data.MediaList.media.description}</p>
|
||||
<div class="flex m-5">
|
||||
<div>
|
||||
<h3 class="text-2xl">Genres</h3>
|
||||
{#each currentAniListAnime.data.MediaList.media.genres as genre}
|
||||
<div>
|
||||
<Badge large border color="blue" class="m-1 w-52">
|
||||
<div>
|
||||
<WebsiteLink
|
||||
id={genre}
|
||||
url="https://anilist.co/search/anime/{genre}"
|
||||
/>
|
||||
</div>
|
||||
</Badge>
|
||||
<Tooltip>{genre}</Tooltip>
|
||||
</div>
|
||||
{/each}
|
||||
<h3 class="text-2xl">Tags</h3>
|
||||
<div class="mt-2">
|
||||
{#each currentAniListAnime.data.MediaList.media.tags as tag}
|
||||
<div>
|
||||
<Badge large border color="blue" class="m-1 w-52">
|
||||
<div>
|
||||
<WebsiteLink
|
||||
id={tag.name}
|
||||
url="https://anilist.co/search/anime/?genres={tag.name}"
|
||||
/>
|
||||
<span class="text-xs">({tag.rank}%)</span>
|
||||
</div>
|
||||
</Badge>
|
||||
<Tooltip>{tag.description}</Tooltip>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ml-5">
|
||||
<h3 class="text-2xl">Summary</h3>
|
||||
<p class="rounded border border-gray-700 p-2 mt-2">
|
||||
{@html currentAniListAnime.data.MediaList.media.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
createTable,
|
||||
Render,
|
||||
Subscribe,
|
||||
} from "svelte-headless-table"
|
||||
} from "svelte-headless-table";
|
||||
// @ts-ignore
|
||||
import { addSortBy } from "svelte-headless-table/plugins"
|
||||
import { tableItems } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"
|
||||
import WebsiteLink from "./WebsiteLink.svelte"
|
||||
import { addSortBy } from "svelte-headless-table/plugins";
|
||||
import { tableItems } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import WebsiteLink from "./WebsiteLink.svelte";
|
||||
|
||||
//when adding sort here is code { sort: addSortBy() }
|
||||
const table = createTable(tableItems, { sort: addSortBy() })
|
||||
const table = createTable(tableItems, { sort: addSortBy() });
|
||||
|
||||
const columns = table.createColumns([
|
||||
table.column({
|
||||
header: "Service Id",
|
||||
cell: ({ value }) => createRender(WebsiteLink, {id: value}),
|
||||
cell: ({ value }) => createRender(WebsiteLink, { id: value }),
|
||||
accessor: "id",
|
||||
}),
|
||||
table.column({
|
||||
@@ -55,11 +55,11 @@
|
||||
header: "Notes",
|
||||
accessor: "notes",
|
||||
}),
|
||||
])
|
||||
]);
|
||||
|
||||
//add pluginStates when add sort back
|
||||
const { headerRows, rows, tableAttrs, tableBodyAttrs } =
|
||||
table.createViewModel(columns)
|
||||
table.createViewModel(columns);
|
||||
</script>
|
||||
|
||||
<div class="relative overflow-x-auto rounded-lg mb-5">
|
||||
|
||||
@@ -1,49 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { Avatar } from "flowbite-svelte";
|
||||
import type { AniListUser } from "../anilist/types/AniListTypes";
|
||||
import {
|
||||
aniListLoggedIn,
|
||||
aniListUser,
|
||||
malUser,
|
||||
simklUser,
|
||||
malLoggedIn,
|
||||
simklLoggedIn,
|
||||
loginToAniList,
|
||||
loginToMAL,
|
||||
loginToSimkl,
|
||||
logoutOfAniList,
|
||||
logoutOfMAL,
|
||||
logoutOfSimkl,
|
||||
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {userStore} from "../helperFunctions/userStore"
|
||||
import * as runtime from "../../wailsjs/runtime";
|
||||
import type {MyAnimeListUser} from "../mal/types/MALTypes";
|
||||
import type {SimklUser} from "../simkl/types/simklTypes";
|
||||
|
||||
let currentAniListUser: AniListUser;
|
||||
let currentMALUser: MyAnimeListUser;
|
||||
let currentSimklUser: SimklUser;
|
||||
let isAniListLoggedIn: boolean;
|
||||
let isSimklLoggedIn: boolean;
|
||||
let isMALLoggedIn: boolean;
|
||||
|
||||
aniListUser.subscribe((value) => (currentAniListUser = value));
|
||||
malUser.subscribe((value) => (currentMALUser = value))
|
||||
simklUser.subscribe(value => currentSimklUser = value)
|
||||
aniListLoggedIn.subscribe((value) => (isAniListLoggedIn = value));
|
||||
simklLoggedIn.subscribe((value) => (isSimklLoggedIn = value));
|
||||
malLoggedIn.subscribe((value) => (isMALLoggedIn = value));
|
||||
import { ShowVersion } from "../../wailsjs/go/main/App";
|
||||
|
||||
function dropdownUser(): void {
|
||||
let dropdown = document.querySelector("#userDropdown");
|
||||
dropdown.classList.toggle("hidden");
|
||||
|
||||
if (!dropdown.classList.contains("hidden")) {
|
||||
document.addEventListener("click", clickOutside)
|
||||
}
|
||||
}
|
||||
|
||||
function clickOutside(event: Event): void {
|
||||
let dropdown = document.querySelector("#userDropdown")
|
||||
let toggleBtn = document.querySelector("#userDropdownButton")
|
||||
|
||||
if (!dropdown.contains(event.target as Node) && !toggleBtn.contains(event.target as Node)) {
|
||||
dropdown.classList.add("hidden")
|
||||
document.removeEventListener("click", clickOutside)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="relative">
|
||||
<button id="userDropdownButton" on:click={dropdownUser}>
|
||||
{#if isAniListLoggedIn}
|
||||
{#if $userStore.anilist.isLoggedIn}
|
||||
<Avatar
|
||||
src={currentAniListUser.data.Viewer.avatar.medium}
|
||||
src={$userStore.anilist.user.data.Viewer.avatar.medium}
|
||||
class="cursor-pointer"
|
||||
dot={{ color: "green" }}
|
||||
/>
|
||||
@@ -56,8 +41,8 @@
|
||||
class="absolute hidden right-0 2xl:left-1/2 2xl:-translate-x-1/2 z-10 divide-y rounded-lg shadow w-44 bg-gray-700 divide-gray-600"
|
||||
>
|
||||
<div class="px-4 py-3 text-sm text-white">
|
||||
{#if isAniListLoggedIn}
|
||||
<div>{currentAniListUser.data.Viewer.name}</div>
|
||||
{#if $userStore.anilist.isLoggedIn}
|
||||
<div>{$userStore.anilist.user.data.Viewer.name}</div>
|
||||
{:else}
|
||||
<div>You are not logged into AniList</div>
|
||||
{/if}
|
||||
@@ -66,52 +51,61 @@
|
||||
class="py-2 text-sm text-gray-200"
|
||||
aria-labelledby="dropdownUserAvatarButton"
|
||||
>
|
||||
{#if isAniListLoggedIn}
|
||||
{#if $userStore.anilist.isLoggedIn}
|
||||
<li>
|
||||
<button
|
||||
on:click={logoutOfAniList}
|
||||
on:click={() => userStore.logout("anilist")}
|
||||
class="block px-4 py-2 w-full hover:bg-gray-600 truncate bg-green-800 hover:text-white"
|
||||
>
|
||||
<span class="maple-font text-lg text-green-200 mr-4">A</span>Logout {currentAniListUser.data.Viewer.name}
|
||||
<span class="maple-font text-lg text-green-200 mr-4">A</span>Logout {$userStore.anilist.user.data.Viewer.name}
|
||||
</button>
|
||||
</li>
|
||||
{:else}
|
||||
<li>
|
||||
<button on:click={loginToAniList}
|
||||
<button on:click={() => {
|
||||
dropdownUser()
|
||||
userStore.checkProvider("anilist")
|
||||
}}
|
||||
class="block px-4 py-2 w-full hover:bg-gray-600 truncate hover:text-white">
|
||||
<span class="maple-font text-lg mr-4">A</span>Login to AniList
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
{#if isMALLoggedIn}
|
||||
{#if $userStore.mal.isLoggedIn}
|
||||
<li>
|
||||
<button
|
||||
on:click={logoutOfMAL}
|
||||
on:click={() => userStore.logout("mal")}
|
||||
class="block px-4 py-2 w-full hover:bg-gray-600 truncate bg-blue-800 hover:text-white"
|
||||
>
|
||||
<span class="maple-font text-lg text-blue-200 mr-4">M</span>Logout {currentMALUser.name}
|
||||
<span class="maple-font text-lg text-blue-200 mr-4">M</span>Logout {$userStore.mal.user.name}
|
||||
</button>
|
||||
</li>
|
||||
{:else}
|
||||
<li>
|
||||
<button on:click={loginToMAL}
|
||||
<button on:click={() => {
|
||||
dropdownUser()
|
||||
userStore.checkProvider("mal")
|
||||
}}
|
||||
class="block px-4 py-2 w-full hover:bg-gray-600 truncate hover:text-white">
|
||||
<span class="maple-font text-lg mr-4">M</span>Login to MyAnimeList
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
{#if isSimklLoggedIn}
|
||||
{#if $userStore.simkl.isLoggedIn}
|
||||
<li>
|
||||
<button
|
||||
on:click={logoutOfSimkl}
|
||||
on:click={() => userStore.logout("simkl")}
|
||||
class="block px-4 py-2 w-full hover:bg-gray-600 truncate bg-indigo-800 hover:text-white"
|
||||
>
|
||||
<span class="maple-font text-lg text-indigo-200 mr-4">S</span>Logout {currentSimklUser.user.name}
|
||||
<span class="maple-font text-lg text-indigo-200 mr-4">S</span>Logout {$userStore.simkl.user.user.name}
|
||||
</button>
|
||||
</li>
|
||||
{:else}
|
||||
<li>
|
||||
<button on:click={loginToSimkl}
|
||||
<button on:click={() => {
|
||||
dropdownUser()
|
||||
userStore.checkProvider("simkl")
|
||||
}}
|
||||
class="block px-4 py-2 w-full hover:bg-gray-600 truncate hover:text-white">
|
||||
<span class="maple-font text-lg mr-4">S</span>Login to Simkl
|
||||
</button>
|
||||
@@ -119,6 +113,15 @@
|
||||
{/if}
|
||||
</ul>
|
||||
<div class="py-2">
|
||||
<button
|
||||
on:click={() => {
|
||||
dropdownUser()
|
||||
ShowVersion()
|
||||
}}
|
||||
class="block px-4 py-2 w-full text-sm hover:bg-gray-600 text-gray-200 over:text-white"
|
||||
>
|
||||
Version
|
||||
</button>
|
||||
<button
|
||||
on:click={() => runtime.Quit()}
|
||||
class="block px-4 py-2 w-full text-sm hover:bg-gray-600 text-gray-200 over:text-white"
|
||||
|
||||
@@ -50,19 +50,19 @@
|
||||
function getFocusRingClass(color: Button["color"]): string {
|
||||
switch (color) {
|
||||
case "primary":
|
||||
return "focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400";
|
||||
return "focus:ring-2 focus:ring-primary-400";
|
||||
case "blue":
|
||||
return "focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400";
|
||||
return "focus:ring-2 focus:ring-blue-400";
|
||||
case "red":
|
||||
return "focus:ring-2 focus:ring-red-500 dark:focus:ring-red-400";
|
||||
return "focus:ring-2 focus:ring-red-400";
|
||||
case "green":
|
||||
return "focus:ring-2 focus:ring-green-500 dark:focus:ring-green-400";
|
||||
return "focus:ring-2 focus:ring-green-400";
|
||||
case "yellow":
|
||||
return "focus:ring-2 focus:ring-yellow-500 dark:focus:ring-yellow-400";
|
||||
return "focus:ring-2 focus:ring-yellow-400";
|
||||
case "purple":
|
||||
return "focus:ring-2 focus:ring-purple-500 dark:focus:ring-purple-400";
|
||||
return "focus:ring-2 focus:ring-purple-400";
|
||||
case "slate":
|
||||
return "focus:ring-2 focus:ring-slate-500 dark:focus:ring-slate-400";
|
||||
return "focus:ring-2 focus:ring-slate-400";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -71,19 +71,19 @@
|
||||
function getRangeBackgroundClass(color: Button["color"]): string {
|
||||
switch (color) {
|
||||
case "primary":
|
||||
return "bg-primary-100 dark:bg-primary-900";
|
||||
return "bg-primary-900";
|
||||
case "blue":
|
||||
return "bg-blue-100 dark:bg-blue-900";
|
||||
return "bg-blue-900";
|
||||
case "red":
|
||||
return "bg-red-100 dark:bg-red-900";
|
||||
return "bg-red-900";
|
||||
case "green":
|
||||
return "bg-green-100 dark:bg-green-900";
|
||||
return "bg-green-900";
|
||||
case "yellow":
|
||||
return "bg-yellow-100 dark:bg-yellow-900";
|
||||
return "bg-yellow-900";
|
||||
case "purple":
|
||||
return "bg-purple-100 dark:bg-purple-900";
|
||||
return "bg-purple-900";
|
||||
case "slate":
|
||||
return "bg-slate-100 dark:bg-slate-900";
|
||||
return "bg-slate-900";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -297,7 +297,7 @@
|
||||
<input
|
||||
bind:this={inputElement}
|
||||
type="text"
|
||||
class="w-full px-4 py-3 text-sm border rounded-md focus:outline-none dark:bg-gray-700 dark:text-white dark:border-gray-600 {getFocusRingClass(
|
||||
class="w-full px-4 py-3 text-sm border rounded-md focus:outline-none bg-gray-700 text-white border-gray-600 {getFocusRingClass(
|
||||
color,
|
||||
)} {inputClass}"
|
||||
{placeholder}
|
||||
@@ -313,13 +313,13 @@
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="absolute inset-y-0 right-0 flex items-center px-3 text-gray-500 dark:text-gray-400 focus:outline-none"
|
||||
class="absolute inset-y-0 right-0 flex items-center px-3 text-gray-400 focus:outline-none"
|
||||
on:click={() => (isOpen = !isOpen)}
|
||||
{disabled}
|
||||
aria-label={isOpen ? "Close date picker" : "Open date picker"}
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 text-gray-500 dark:text-gray-400"
|
||||
class="w-4 h-4 text-gray-400"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
@@ -339,14 +339,14 @@
|
||||
id="datepicker-dropdown"
|
||||
class="
|
||||
{inline ? '' : 'absolute z-10 mt-1'}
|
||||
bg-white dark:bg-gray-800 rounded-md shadow-lg"
|
||||
bg-gray-800 rounded-md shadow-lg"
|
||||
transition:fade={{ duration: 100 }}
|
||||
role="dialog"
|
||||
aria-label="Calendar"
|
||||
>
|
||||
<div class="p-4" role="application">
|
||||
{#if title}
|
||||
<h2 class="text-lg font-semibold mb-4 dark:text-white">
|
||||
<h2 class="text-lg font-semibold mb-4 text-white">
|
||||
{title}
|
||||
</h2>
|
||||
{/if}
|
||||
@@ -358,7 +358,7 @@
|
||||
aria-label="Previous month"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 rtl:rotate-180 text-white dark:text-white"
|
||||
class="w-3 h-3 rtl:rotate-180 text-white"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
@@ -373,7 +373,7 @@
|
||||
>
|
||||
</Button>
|
||||
<h3
|
||||
class="text-lg font-semibold dark:text-white"
|
||||
class="text-lg font-semibold text-white"
|
||||
aria-live="polite"
|
||||
>
|
||||
{currentMonth.toLocaleString(locale, {
|
||||
@@ -388,7 +388,7 @@
|
||||
aria-label="Next month"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 rtl:rotate-180 text-white dark:text-white"
|
||||
class="w-3 h-3 rtl:rotate-180 text-white"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
@@ -406,7 +406,7 @@
|
||||
<div class="grid grid-cols-7 gap-1" role="grid">
|
||||
{#each weekdays as day}
|
||||
<div
|
||||
class="text-center text-sm font-medium text-gray-500 dark:text-gray-400"
|
||||
class="text-center text-sm font-medium text-gray-400"
|
||||
role="columnheader"
|
||||
>
|
||||
{day}
|
||||
@@ -418,7 +418,7 @@
|
||||
size="sm"
|
||||
class="w-full h-8 {day.getMonth() !==
|
||||
currentMonth.getMonth()
|
||||
? 'text-gray-300 dark:text-gray-600'
|
||||
? 'text-gray-600'
|
||||
: ''} {isToday(day)
|
||||
? 'font-bold'
|
||||
: ''} {isInRange(day)
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Search from "./Search.svelte"
|
||||
import {
|
||||
aniListLoggedIn,
|
||||
loginToAniList,
|
||||
loginToMAL,
|
||||
loginToSimkl,
|
||||
malLoggedIn,
|
||||
simklLoggedIn,
|
||||
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"
|
||||
import AvatarMenu from "./AvatarMenu.svelte";
|
||||
import logo from "../assets/images/AniTrackLogo.svg"
|
||||
import {userStore} from "../helperFunctions/userStore"
|
||||
|
||||
let isAniListLoggedIn: boolean
|
||||
let isSimklLoggedIn: boolean
|
||||
let isMALLoggedIn: boolean
|
||||
|
||||
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
|
||||
simklLoggedIn.subscribe((value) => isSimklLoggedIn = value)
|
||||
malLoggedIn.subscribe((value) => isMALLoggedIn = value)
|
||||
</script>
|
||||
|
||||
<nav class="border-gray-200 bg-gray-900">
|
||||
@@ -47,22 +34,22 @@
|
||||
<div class="hidden items-center justify-between w-full pb-4 min-[950px]:pb-0 min-[950px]:flex min-[950px]:w-auto min-[950px]:order-1 border border-gray-700 min-[950px]:border-0 bg-gray-800 min-[950px]:bg-transparent rounded-lg" id="navbar-user">
|
||||
<ul class="flex flex-col font-medium pb-6 min-[950px]:p-0 mt-4 min-[950px]:space-x-8 rtl:space-x-reverse min-[950px]:flex-row min-[950px]:mt-0">
|
||||
<li>
|
||||
{#if !isAniListLoggedIn}
|
||||
<button on:click={loginToAniList}>
|
||||
{#if !$userStore.anilist.isLoggedIn}
|
||||
<button on:click={() => userStore.checkProvider("anilist")}>
|
||||
<!-- class="block py-2 px-3 w-full min-[950px]:w-auto rounded text-gray-300 min-[950px]:hover:text-blue-500 hover:bg-gray-700 hover:text-white min-[950px]:hover:bg-transparent border-gray-700">-->
|
||||
AniList Login
|
||||
</button>
|
||||
{/if}
|
||||
{#if !isMALLoggedIn}
|
||||
<button on:click={loginToMAL}>
|
||||
{#if !$userStore.mal.isLoggedIn}
|
||||
<button on:click={() => userStore.checkProvider("mal")}>
|
||||
<!-- class="block py-2 px-3 w-full min-[950px]:w-auto rounded min-[950px]:p-0 text-gray-300 min-[950px]:hover:text-blue-500 hover:bg-gray-700 hover:text-white min-[950px]:hover:bg-transparent border-gray-700">-->
|
||||
MyAnimeList Login
|
||||
</button>
|
||||
{/if}
|
||||
</li>
|
||||
<li>
|
||||
{#if !isSimklLoggedIn}
|
||||
<button on:click={loginToSimkl}>
|
||||
{#if !$userStore.simkl.isLoggedIn}
|
||||
<button on:click={() => userStore.checkProvider("simkl")}>
|
||||
<!-- class="block py-2 px-3 w-full min-[950px]:w-auto rounded min-[950px]:p-0 text-gray-300 min-[950px]:hover:text-blue-500 hover:bg-gray-700 hover:text-white min-[950px]:hover:bg-transparent border-gray-700">-->
|
||||
Simkl Login
|
||||
</button>
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
watchListPage,
|
||||
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
|
||||
import type {AniListCurrentUserWatchList} from "../anilist/types/AniListCurrentUserWatchListType"
|
||||
import type {AniListCurrentUserWatchList} from "../types/AniListCurrentUserWatchListType"
|
||||
import {GetAniListUserWatchingList} from "../../wailsjs/go/main/App";
|
||||
import {MediaListSort} from "../anilist/types/AniListTypes";
|
||||
import {MediaListSort} from "../types/AniListTypes";
|
||||
|
||||
let aniListWatchListLoaded: AniListCurrentUserWatchList
|
||||
let page: number
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
|
||||
import {AniListSearch} from "../../wailsjs/go/main/App";
|
||||
import type {AniSearchList} from "../anilist/types/AniListTypes";
|
||||
import type {AniSearchList} from "../types/AniListTypes";
|
||||
import {push} from "svelte-spa-router";
|
||||
|
||||
let aniSearch = ""
|
||||
|
||||
@@ -1,68 +1,59 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
aniListLoggedIn,
|
||||
aniListWatchlist,
|
||||
GetAnimeSingleItem,
|
||||
loading,
|
||||
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {push} from "svelte-spa-router";
|
||||
import type {AniListCurrentUserWatchList} from "../anilist/types/AniListCurrentUserWatchListType"
|
||||
import type {AniListCurrentUserWatchList} from "../types/AniListCurrentUserWatchListType"
|
||||
import {Rating} from "flowbite-svelte";
|
||||
import loader from '../helperFunctions/loader'
|
||||
|
||||
|
||||
let isAniListLoggedIn: boolean
|
||||
let aniListWatchListLoaded: AniListCurrentUserWatchList
|
||||
|
||||
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
|
||||
aniListWatchlist.subscribe((value) => aniListWatchListLoaded = value)
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if isAniListLoggedIn}
|
||||
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center">
|
||||
<h1 class="text-left text-xl font-bold mb-4">Your AniList WatchList</h1>
|
||||
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center">
|
||||
<h1 class="text-left text-xl font-bold mb-4">Your AniList WatchList</h1>
|
||||
|
||||
<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}
|
||||
<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">
|
||||
<button on:click={() => {
|
||||
<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}
|
||||
<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">
|
||||
<button on:click={() => {
|
||||
push(`#/anime/${media.media.id}`)
|
||||
// loading.set(true)
|
||||
// GetAniListSingleItem(media.media.id, true).then(() => {
|
||||
// loading.set(false)
|
||||
//
|
||||
// })
|
||||
}}
|
||||
>
|
||||
<img class="rounded-lg" src={media.media.coverImage.large} alt={
|
||||
>
|
||||
<img class="rounded-lg" src={media.media.coverImage.large} alt={
|
||||
media.media.title.english === "" ?
|
||||
media.media.title.romaji :
|
||||
media.media.title.english
|
||||
}/>
|
||||
</button>
|
||||
<Rating id="anime-rating" total={5} size={35} rating={media.score/2.0}/>
|
||||
<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>
|
||||
<p class="mt-1 text-lg font-medium text-white-900">{media.progress}
|
||||
/ {media.media.nextAiringEpisode.episode !== 0 ?
|
||||
media.media.nextAiringEpisode.episode - 1 : media.media.episodes}</p>
|
||||
{#if media.media.episodes > 0}
|
||||
<p class="mt-1 text-lg font-medium text-white-900">Total
|
||||
Episodes: {media.media.episodes}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
<Rating id="anime-rating" total={5} size={35} rating={media.score/2.0}/>
|
||||
<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>
|
||||
<p class="mt-1 text-lg font-medium text-white-900">{media.progress}
|
||||
/ {media.media.nextAiringEpisode.episode !== 0 ?
|
||||
media.media.nextAiringEpisode.episode - 1 : media.media.episodes}</p>
|
||||
{#if media.media.episodes > 0}
|
||||
<p class="mt-1 text-lg font-medium text-white-900">Total
|
||||
Episodes: {media.media.episodes}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
<script lang="ts">
|
||||
import {BrowserOpenURL} from "../../wailsjs/runtime"
|
||||
import { BrowserOpenURL } from "../../wailsjs/runtime";
|
||||
|
||||
export let id: string
|
||||
let url = ""
|
||||
let isAniList = false
|
||||
let isMAL = false
|
||||
let isSimkl = false
|
||||
let newId = id
|
||||
let re = /[ams]?-?(.*)/
|
||||
if (id !== undefined && id.length > 0) {
|
||||
isAniList = id.includes("a-")
|
||||
isMAL = id.includes("m-")
|
||||
isSimkl = id.includes("s-")
|
||||
newId = id.match(re)[1]
|
||||
}
|
||||
export let id: string;
|
||||
export let url = "";
|
||||
let isAniList = false;
|
||||
let isMAL = false;
|
||||
let isSimkl = false;
|
||||
let newId = id;
|
||||
let re = /[ams]?-?(.*)/;
|
||||
if (id !== undefined && id.length > 0) {
|
||||
isAniList = id.includes("a-");
|
||||
isMAL = id.includes("m-");
|
||||
isSimkl = id.includes("s-");
|
||||
if (isAniList || isMAL || isSimkl) newId = id.match(re)[1];
|
||||
else newId = id;
|
||||
}
|
||||
|
||||
|
||||
if (isAniList) url = `https://anilist.co/anime/${newId}`
|
||||
if (isMAL) url = `https://myanimelist.net/anime/${newId}`
|
||||
if (isSimkl) url = `https://simkl.com/anime/${newId}`
|
||||
if (isAniList) url = `https://anilist.co/anime/${newId}`;
|
||||
if (isMAL) url = `https://myanimelist.net/anime/${newId}`;
|
||||
if (isSimkl) url = `https://simkl.com/anime/${newId}`;
|
||||
</script>
|
||||
|
||||
{#if url.length > 0}
|
||||
<button class="underline underline-offset-2 px-4 py-1" on:click={() => BrowserOpenURL(url)}>{newId}</button>
|
||||
<button
|
||||
type="button"
|
||||
class="underline underline-offset-2 px-4 py-1"
|
||||
on:click={() => BrowserOpenURL(url)}>{newId}</button
|
||||
>
|
||||
{:else}
|
||||
{id}
|
||||
{id}
|
||||
{/if}
|
||||
|
||||
121
frontend/src/helperFunctions/userStore.ts
Normal file
121
frontend/src/helperFunctions/userStore.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
// stores/user.ts
|
||||
import {get, writable} from 'svelte/store';
|
||||
import type {SimklUser, SimklWatchList} from "../types/simklTypes";
|
||||
import type {AniListUser} from "../types/AniListTypes";
|
||||
import type {MALWatchlist, MyAnimeListUser} from "../types/MALTypes";
|
||||
import {
|
||||
GetAniListLoggedInUser,
|
||||
GetMyAnimeList,
|
||||
GetMyAnimeListLoggedInUser,
|
||||
GetSimklLoggedInUser,
|
||||
LogoutAniList,
|
||||
LogoutMyAnimeList,
|
||||
LogoutSimkl,
|
||||
SimklGetUserWatchlist
|
||||
} from "../../wailsjs/go/main/App";
|
||||
import {LoadAniListWatchList} from "../helperModules/LoadAniListWatchList.svelte";
|
||||
import {aniListWatchlist, malWatchList, simklWatchList} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"
|
||||
import type {AniListCurrentUserWatchList} from "../types/AniListCurrentUserWatchListType";
|
||||
import {AniListUserDefaultData, MALUserDefaultData, SimklUserDefaultData} from "../defaults/UserTypes";
|
||||
|
||||
let aniWatchlist: AniListCurrentUserWatchList
|
||||
aniListWatchlist.subscribe(value => aniWatchlist = value)
|
||||
|
||||
interface UserState {
|
||||
simkl: { user: SimklUser; isLoggedIn: boolean; isPrimary: boolean };
|
||||
anilist: { user: AniListUser; isLoggedIn: boolean; isPrimary: boolean };
|
||||
mal: { user: MyAnimeListUser; isLoggedIn: boolean; isPrimary: boolean };
|
||||
}
|
||||
|
||||
const createUserStore = () => {
|
||||
const {subscribe, update} = writable<UserState>({
|
||||
anilist: {user: AniListUserDefaultData, isLoggedIn: false, isPrimary: true},
|
||||
mal: {user: MALUserDefaultData, isLoggedIn: false, isPrimary: false},
|
||||
simkl: {user: SimklUserDefaultData, isLoggedIn: false, isPrimary: false}
|
||||
});
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
setAniListUser: (user: AniListUser, isPrimary = true) =>
|
||||
update(s => ({
|
||||
...s,
|
||||
anilist: {user, isLoggedIn: true, isPrimary}
|
||||
})),
|
||||
setMalUser: (user: MyAnimeListUser, isPrimary = false) =>
|
||||
update(s => ({
|
||||
...s,
|
||||
mal: {user, isLoggedIn: true, isPrimary}
|
||||
})),
|
||||
setSimklUser: (user: SimklUser, isPrimary = false) =>
|
||||
update(s => ({
|
||||
...s,
|
||||
simkl: {user, isLoggedIn: true, isPrimary}
|
||||
})),
|
||||
setPrimary: (provider: 'simkl' | 'anilist' | 'mal') =>
|
||||
update(s => ({
|
||||
...s,
|
||||
simkl: {...s.simkl, isPrimary: provider === 'simkl'},
|
||||
anilist: {...s.anilist, isPrimary: provider === 'anilist'},
|
||||
mal: {...s.mal, isPrimary: provider === 'mal'}
|
||||
})),
|
||||
checkProvider: async (provider: 'simkl' | 'anilist' | 'mal') => {
|
||||
const state = get(userStore);
|
||||
if (state[provider].isLoggedIn) return;
|
||||
|
||||
if (provider === 'anilist') {
|
||||
const user: AniListUser = await GetAniListLoggedInUser();
|
||||
console.log(user)
|
||||
userStore.setAniListUser(user, state.anilist.isPrimary);
|
||||
console.log(state.anilist.isPrimary)
|
||||
if (state.anilist.isPrimary) await LoadAniListWatchList();
|
||||
} else if (provider === 'mal') {
|
||||
const user: MyAnimeListUser = await GetMyAnimeListLoggedInUser();
|
||||
userStore.setMalUser(user, state.mal.isPrimary);
|
||||
if (state.mal.isPrimary) {
|
||||
const watchList = await GetMyAnimeList(1000);
|
||||
malWatchList.set(watchList);
|
||||
}
|
||||
} else if (provider === 'simkl') {
|
||||
const user: SimklUser = await GetSimklLoggedInUser();
|
||||
userStore.setSimklUser(user, state.simkl.isPrimary);
|
||||
if (state.simkl.isPrimary) {
|
||||
const watchList = await SimklGetUserWatchlist();
|
||||
simklWatchList.set(watchList)
|
||||
}
|
||||
}
|
||||
},
|
||||
logout: async (provider: 'simkl' | 'anilist' | 'mal') => {
|
||||
update(s => {
|
||||
s[provider].user = {} as SimklUser | AniListUser | MyAnimeListUser
|
||||
s[provider].isLoggedIn = false;
|
||||
if (s[provider].isPrimary) {
|
||||
s[provider].isPrimary = false;
|
||||
const others = ['simkl', 'anilist', 'mal'] as const;
|
||||
const newPrimary = others.find(p => p !== provider && s[p].isLoggedIn);
|
||||
if (newPrimary) s[newPrimary].isPrimary = true;
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
||||
// Clear provider-specific watchlist
|
||||
if (provider === 'anilist') {
|
||||
if (Object.keys(aniWatchlist).length !== 0) {
|
||||
aniListWatchlist.set({} as AniListCurrentUserWatchList)
|
||||
}
|
||||
await LogoutAniList();
|
||||
} else if (provider === 'mal') {
|
||||
if (Object.keys(aniWatchlist).length !== 0) {
|
||||
malWatchList.set({} as MALWatchlist);
|
||||
}
|
||||
await LogoutMyAnimeList();
|
||||
} else if (provider === 'simkl') {
|
||||
if (Object.keys(aniWatchlist).length !== 0) {
|
||||
simklWatchList.set({} as SimklWatchList);
|
||||
}
|
||||
await LogoutSimkl();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const userStore = createUserStore();
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" context="module">
|
||||
import type {TableItem} from "../helperTypes/TableTypes";
|
||||
import type {TableItem} from "../types/TableTypes";
|
||||
import { tableItems } from "./GlobalVariablesAndHelperFunctions.svelte"
|
||||
|
||||
export function AddAnimeServiceToTable(animeItem: TableItem) {
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<script lang="ts" context="module">
|
||||
import {CheckIfAniListLoggedIn, GetAniListLoggedInUser, GetAniListUserWatchingList} from "../../wailsjs/go/main/App";
|
||||
import {MediaListSort} from "../anilist/types/AniListTypes";
|
||||
import { aniListUser, watchListPage, animePerPage, aniListPrimary, aniListLoggedIn, aniListWatchlist } from "./GlobalVariablesAndHelperFunctions.svelte"
|
||||
|
||||
let isAniListPrimary: boolean
|
||||
let page: number
|
||||
let perPage: number
|
||||
|
||||
aniListPrimary.subscribe(value => isAniListPrimary = value)
|
||||
watchListPage.subscribe(value => page = value)
|
||||
animePerPage.subscribe(value => perPage = value)
|
||||
|
||||
export const LoadAniListUser = async () => {
|
||||
await GetAniListLoggedInUser().then(user => {
|
||||
aniListUser.set(user)
|
||||
})
|
||||
}
|
||||
|
||||
export const LoadAniListWatchList = async () => {
|
||||
await GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((watchList) => {
|
||||
aniListWatchlist.set(watchList)
|
||||
})
|
||||
}
|
||||
|
||||
export const CheckIfAniListLoggedInAndLoadWatchList = async () => {
|
||||
const loggedIn = await CheckIfAniListLoggedIn()
|
||||
if (loggedIn) {
|
||||
await LoadAniListUser()
|
||||
if (isAniListPrimary) await LoadAniListWatchList()
|
||||
}
|
||||
aniListLoggedIn.set(loggedIn)
|
||||
}
|
||||
</script>
|
||||
@@ -1,25 +0,0 @@
|
||||
<script lang="ts" context="module">
|
||||
import {CheckIfMyAnimeListLoggedIn, GetMyAnimeList, GetMyAnimeListLoggedInUser} from "../../wailsjs/go/main/App";
|
||||
import {malUser, malPrimary, malWatchList, malLoggedIn} from "./GlobalVariablesAndHelperFunctions.svelte"
|
||||
|
||||
let isMalPrimary: boolean
|
||||
malPrimary.subscribe(value => isMalPrimary = value)
|
||||
|
||||
export const CheckIfMALLoggedInAndSetUser = async () => {
|
||||
await CheckIfMyAnimeListLoggedIn().then(loggedIn => {
|
||||
if (loggedIn) {
|
||||
GetMyAnimeListLoggedInUser().then(user => {
|
||||
malUser.set(user)
|
||||
if (isMalPrimary) {
|
||||
GetMyAnimeList(1000).then(watchList => {
|
||||
malWatchList.set(watchList)
|
||||
malLoggedIn.set(loggedIn)
|
||||
})
|
||||
} else {
|
||||
malLoggedIn.set(loggedIn)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -1,29 +0,0 @@
|
||||
<script lang="ts" context="module">
|
||||
import {CheckIfSimklLoggedIn, GetSimklLoggedInUser, SimklGetUserWatchlist} from "../../wailsjs/go/main/App";
|
||||
import { simklLoggedIn, simklUser, simklPrimary, simklWatchList } from "./GlobalVariablesAndHelperFunctions.svelte";
|
||||
|
||||
let isSimklPrimary: boolean
|
||||
simklPrimary.subscribe(value => isSimklPrimary = value)
|
||||
|
||||
export const CheckIfSimklLoggedInAndSetUser = async () => {
|
||||
await CheckIfSimklLoggedIn().then(loggedIn => {
|
||||
if (loggedIn) {
|
||||
GetSimklLoggedInUser().then(user => {
|
||||
if (Object.keys(user).length === 0) {
|
||||
simklLoggedIn.set(false)
|
||||
} else {
|
||||
simklUser.set(user)
|
||||
if (isSimklPrimary) {
|
||||
SimklGetUserWatchlist().then(result => {
|
||||
simklWatchList.set(result)
|
||||
simklLoggedIn.set(loggedIn)
|
||||
})
|
||||
} else {
|
||||
simklLoggedIn.set(loggedIn)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -1,41 +1,25 @@
|
||||
<script lang="ts" context="module">
|
||||
import {
|
||||
GetAniListItem,
|
||||
GetAniListLoggedInUser,
|
||||
GetAniListUserWatchingList,
|
||||
GetMyAnimeListAnime,
|
||||
GetMyAnimeListLoggedInUser,
|
||||
GetSimklLoggedInUser,
|
||||
LogoutAniList,
|
||||
LogoutMyAnimeList,
|
||||
LogoutSimkl,
|
||||
SimklGetUserWatchlist,
|
||||
SimklSearch
|
||||
} from "../../wailsjs/go/main/App";
|
||||
import {userStore} from "../helperFunctions/userStore";
|
||||
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";
|
||||
} from "../types/AniListCurrentUserWatchListType.js";
|
||||
import {get, writable} from 'svelte/store'
|
||||
import type {SimklAnime, SimklWatchList} from "../types/simklTypes";
|
||||
import type {MALAnime, MALWatchlist} from "../types/MALTypes";
|
||||
import type {TableItems} from "../types/TableTypes";
|
||||
import {AniListGetSingleAnimeDefaultData} from "../defaults/AniListGetSingleAnime";
|
||||
import {AniListWatchListDefaultData} from "../defaults/AniListWatchListDefaultData";
|
||||
|
||||
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 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 aniListWatchlist = writable(AniListWatchListDefaultData)
|
||||
export let malWatchList = writable({} as MALWatchlist)
|
||||
export let malAnime = writable({} as MALAnime)
|
||||
export let simklAnime = writable({} as SimklAnime)
|
||||
@@ -45,25 +29,14 @@
|
||||
export let watchListPage = writable(1)
|
||||
export let animePerPage = writable(20)
|
||||
|
||||
let isAniListPrimary: boolean
|
||||
let page: number
|
||||
let perPage: number
|
||||
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)
|
||||
|
||||
|
||||
export async function GetAnimeSingleItem(aniId: number, login: boolean): Promise<""> {
|
||||
const store = get(userStore)
|
||||
if (store.anilist.isLoggedIn)
|
||||
await GetAniListItem(aniId, login).then(aniListResult => {
|
||||
let finalResult: AniListGetSingleAnime
|
||||
finalResult = aniListResult
|
||||
@@ -85,78 +58,16 @@
|
||||
currentAniListAnime.data.MediaList.media.title.romaji :
|
||||
currentAniListAnime.data.MediaList.media.title.english)
|
||||
})
|
||||
if (isMalLoggedIn) {
|
||||
if (store.mal.isLoggedIn) {
|
||||
await GetMyAnimeListAnime(currentAniListAnime.data.MediaList.media.idMal).then(malResult => {
|
||||
malAnime.set(malResult)
|
||||
})
|
||||
}
|
||||
if (isSimklLoggedIn) {
|
||||
if (store.simkl.isLoggedIn) {
|
||||
await SimklSearch(currentAniListAnime.data.MediaList).then((value: SimklAnime) => {
|
||||
simklAnime.set(value)
|
||||
})
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
export function loginToSimkl(): void {
|
||||
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)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function loginToAniList(): void {
|
||||
GetAniListLoggedInUser().then(result => {
|
||||
aniListUser.set(result)
|
||||
if (isAniListPrimary) {
|
||||
GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((result) => {
|
||||
aniListWatchlist.set(result)
|
||||
aniListLoggedIn.set(true)
|
||||
})
|
||||
} else {
|
||||
aniListLoggedIn.set(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function loginToMAL(): void {
|
||||
GetMyAnimeListLoggedInUser().then(result => {
|
||||
malUser.set(result)
|
||||
malLoggedIn.set(true)
|
||||
})
|
||||
}
|
||||
|
||||
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>
|
||||
17
frontend/src/helperModules/LoadAniListWatchList.svelte
Normal file
17
frontend/src/helperModules/LoadAniListWatchList.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script lang="ts" context="module">
|
||||
import {GetAniListUserWatchingList} from "../../wailsjs/go/main/App";
|
||||
import {MediaListSort} from "../types/AniListTypes";
|
||||
import { watchListPage, animePerPage, aniListWatchlist } from "./GlobalVariablesAndHelperFunctions.svelte"
|
||||
|
||||
let page: number
|
||||
let perPage: number
|
||||
|
||||
watchListPage.subscribe(value => page = value)
|
||||
animePerPage.subscribe(value => perPage = value)
|
||||
|
||||
export const LoadAniListWatchList = async () => {
|
||||
await GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((watchList) => {
|
||||
aniListWatchlist.set(watchList)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -1,9 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { aniListAnime, GetAnimeSingleItem } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import Anime from "../helperComponents/Anime.svelte"
|
||||
import { AniListGetSingleAnimeDefaultData } from "../defaults/AniListGetSingleAnime";
|
||||
import Spinner from "../helperComponents/Spinner.svelte";
|
||||
|
||||
export let params: Record<string, string>
|
||||
let loadPromise = load(params.id)
|
||||
$: loadPromise = load(params.id)
|
||||
|
||||
async function load(id: string) {
|
||||
aniListAnime.update(() => AniListGetSingleAnimeDefaultData)
|
||||
await GetAnimeSingleItem(Number(id), true)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#key params.id}
|
||||
<Anime />
|
||||
{#await loadPromise}
|
||||
<Spinner />
|
||||
{:then _}
|
||||
<Anime />
|
||||
{/await}
|
||||
{/key}
|
||||
@@ -2,19 +2,13 @@
|
||||
import Pagination from "../helperComponents/Pagination.svelte";
|
||||
import WatchList from "../helperComponents/WatchList.svelte";
|
||||
import {
|
||||
aniListLoggedIn,
|
||||
aniListPrimary,
|
||||
loading,
|
||||
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
|
||||
import loader from '../helperFunctions/loader'
|
||||
import {userStore} from "../helperFunctions/userStore";
|
||||
|
||||
let isAniListPrimary: boolean
|
||||
let isAniListLoggedIn: boolean
|
||||
|
||||
aniListPrimary.subscribe((value) => isAniListPrimary = value)
|
||||
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
|
||||
</script>
|
||||
{#if isAniListLoggedIn && isAniListPrimary}
|
||||
{#if $userStore.anilist.isLoggedIn && $userStore.anilist.isPrimary}
|
||||
<div class="container py-10">
|
||||
<Pagination />
|
||||
<WatchList />
|
||||
|
||||
94
frontend/src/types/AniListCurrentUserWatchListType.ts
Normal file
94
frontend/src/types/AniListCurrentUserWatchListType.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
export interface AniListCurrentUserWatchList {
|
||||
data: {
|
||||
Page: {
|
||||
pageInfo: {
|
||||
total: number;
|
||||
perPage: number;
|
||||
currentPage: number;
|
||||
lastPage: number;
|
||||
hasNextPage: boolean;
|
||||
};
|
||||
mediaList: MediaList[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface AniListGetSingleAnime {
|
||||
data: {
|
||||
MediaList: MediaList;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MediaList {
|
||||
id: number;
|
||||
mediaId: number;
|
||||
userId: number;
|
||||
media: {
|
||||
id: number;
|
||||
idMal: number;
|
||||
title: {
|
||||
romaji: string;
|
||||
english?: string;
|
||||
native: string;
|
||||
};
|
||||
description: string;
|
||||
coverImage: {
|
||||
large: string;
|
||||
};
|
||||
season: string;
|
||||
seasonYear: number;
|
||||
status: string;
|
||||
episodes?: number;
|
||||
nextAiringEpisode?: {
|
||||
airingAt: number;
|
||||
timeUntilAiring: number;
|
||||
episode: number;
|
||||
};
|
||||
genres: string[];
|
||||
tags: [
|
||||
{
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
rank: number;
|
||||
isMediaSpoiler: boolean;
|
||||
isAdult: boolean;
|
||||
},
|
||||
];
|
||||
isAdult: boolean;
|
||||
};
|
||||
status: string;
|
||||
startedAt: {
|
||||
year: number;
|
||||
month: number;
|
||||
day: number;
|
||||
};
|
||||
completedAt: {
|
||||
year?: number;
|
||||
month?: number;
|
||||
day?: number;
|
||||
};
|
||||
notes?: string;
|
||||
progress: number;
|
||||
score: number;
|
||||
repeat: number;
|
||||
user: {
|
||||
id: number;
|
||||
name: string;
|
||||
avatar: {
|
||||
large: string;
|
||||
medium: string;
|
||||
};
|
||||
statistics: {
|
||||
anime: {
|
||||
count: number;
|
||||
statuses: [
|
||||
{
|
||||
status: string;
|
||||
count: number;
|
||||
},
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
2
frontend/wailsjs/go/main/App.d.ts
vendored
2
frontend/wailsjs/go/main/App.d.ts
vendored
@@ -42,6 +42,8 @@ export function MyAnimeListLogin():Promise<void>;
|
||||
|
||||
export function MyAnimeListUpdate(arg1:main.MALAnime,arg2:main.MALUploadStatus):Promise<main.MalListStatus>;
|
||||
|
||||
export function ShowVersion():Promise<void>;
|
||||
|
||||
export function SimklGetUserWatchlist():Promise<main.SimklWatchListType>;
|
||||
|
||||
export function SimklLogin():Promise<void>;
|
||||
|
||||
@@ -82,6 +82,10 @@ export function MyAnimeListUpdate(arg1, arg2) {
|
||||
return window['go']['main']['App']['MyAnimeListUpdate'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function ShowVersion() {
|
||||
return window['go']['main']['App']['ShowVersion']();
|
||||
}
|
||||
|
||||
export function SimklGetUserWatchlist() {
|
||||
return window['go']['main']['App']['SimklGetUserWatchlist']();
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ export namespace main {
|
||||
id: number;
|
||||
mediaId: number;
|
||||
userId: number;
|
||||
// Go type: struct { ID int "json:\"id\""; IDMal int "json:\"idMal\""; Title struct { Romaji string "json:\"romaji\""; English string "json:\"english\""; Native string "json:\"native\"" } "json:\"title\""; Description string "json:\"description\""; CoverImage struct { Large string "json:\"large\"" } "json:\"coverImage\""; Season string "json:\"season\""; SeasonYear int "json:\"seasonYear\""; Status string "json:\"status\""; Episodes int "json:\"episodes\""; NextAiringEpisode struct { AiringAt int "json:\"airingAt\""; TimeUntilAiring int "json:\"timeUntilAiring\""; Episode int "json:\"episode\"" } "json:\"nextAiringEpisode\""; Tags []struct { Id int "json:\"id\""; Name string "json:\"name\""; Description string "json:\"description\""; Rank int "json:\"rank\""; IsMediaSpoiler bool "json:\"isMediaSpoiler\""; IsAdult bool "json:\"isAdult\"" } "json:\"tags\""; IsAdult bool "json:\"isAdult\"" }
|
||||
// Go type: struct { ID int "json:\"id\""; IDMal int "json:\"idMal\""; Title struct { Romaji string "json:\"romaji\""; English string "json:\"english\""; Native string "json:\"native\"" } "json:\"title\""; Description string "json:\"description\""; CoverImage struct { Large string "json:\"large\"" } "json:\"coverImage\""; Season string "json:\"season\""; SeasonYear int "json:\"seasonYear\""; Status string "json:\"status\""; Episodes int "json:\"episodes\""; NextAiringEpisode struct { AiringAt int "json:\"airingAt\""; TimeUntilAiring int "json:\"timeUntilAiring\""; Episode int "json:\"episode\"" } "json:\"nextAiringEpisode\""; Genres []string "json:\"genres\""; Tags []struct { Id int "json:\"id\""; Name string "json:\"name\""; Description string "json:\"description\""; Rank int "json:\"rank\""; IsMediaSpoiler bool "json:\"isMediaSpoiler\""; IsAdult bool "json:\"isAdult\"" } "json:\"tags\""; IsAdult bool "json:\"isAdult\"" }
|
||||
media: any;
|
||||
status: string;
|
||||
// Go type: struct { Year int "json:\"year\""; Month int "json:\"month\""; Day int "json:\"day\"" }
|
||||
|
||||
2
frontend/wailsjs/runtime/runtime.d.ts
vendored
2
frontend/wailsjs/runtime/runtime.d.ts
vendored
@@ -134,7 +134,7 @@ export function WindowIsFullscreen(): Promise<boolean>;
|
||||
|
||||
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
|
||||
// Sets the width and height of the window.
|
||||
export function WindowSetSize(width: number, height: number): Promise<Size>;
|
||||
export function WindowSetSize(width: number, height: number): void;
|
||||
|
||||
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
|
||||
// Gets the width and height of the window.
|
||||
|
||||
16
go.mod
16
go.mod
@@ -1,11 +1,11 @@
|
||||
module AniTrack
|
||||
|
||||
go 1.23
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/99designs/keyring v1.2.2
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/wailsapp/wails/v2 v2.9.2
|
||||
github.com/wailsapp/wails/v2 v2.10.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -31,7 +31,7 @@ require (
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/samber/lo v1.47.0 // indirect
|
||||
github.com/samber/lo v1.49.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tkrajina/go-reflector v0.5.8 // indirect
|
||||
@@ -39,11 +39,11 @@ require (
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/wailsapp/go-webview2 v1.0.19 // indirect
|
||||
github.com/wailsapp/mimetype v1.4.1 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/term v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/crypto v0.45.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
)
|
||||
|
||||
// replace github.com/wailsapp/wails/v2 v2.9.1 => /home/nymusicman/go/pkg/mod
|
||||
|
||||
31
go.sum
31
go.sum
@@ -23,8 +23,9 @@ github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NM
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
|
||||
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
@@ -59,8 +60,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
@@ -82,26 +83,26 @@ github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyT
|
||||
github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/wailsapp/wails/v2 v2.9.2 h1:Xb5YRTos1w5N7DTMyYegWaGukCP2fIaX9WF21kPPF2k=
|
||||
github.com/wailsapp/wails/v2 v2.9.2/go.mod h1:uehvlCwJSFcBq7rMCGfk4rxca67QQGsbg5Nm4m9UnBs=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
github.com/wailsapp/wails/v2 v2.10.1 h1:QWHvWMXII2nI/nXz77gpPG8P3ehl6zKe+u4su5BWIns=
|
||||
github.com/wailsapp/wails/v2 v2.10.1/go.mod h1:zrebnFV6MQf9kx8HI4iAv63vsR5v67oS7GTEZ7Pz1TY=
|
||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
79
rest/AniTrack/Get Items/AniChart.http
Normal file
79
rest/AniTrack/Get Items/AniChart.http
Normal file
@@ -0,0 +1,79 @@
|
||||
# @name AniChart
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
|
||||
query ($page: Int, $perPage: Int, $airingAt_greater:Int) {
|
||||
Page(page: $page, perPage: $perPage) {
|
||||
pageInfo {
|
||||
total
|
||||
perPage
|
||||
currentPage
|
||||
lastPage
|
||||
hasNextPage
|
||||
}
|
||||
airingSchedules(airingAt_greater:$airingAt_greater){
|
||||
id
|
||||
airingAt
|
||||
timeUntilAiring
|
||||
episode
|
||||
mediaId
|
||||
media{
|
||||
id
|
||||
title{
|
||||
english
|
||||
romaji
|
||||
native
|
||||
}
|
||||
type
|
||||
format
|
||||
status
|
||||
startDate{
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
endDate{
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
season
|
||||
seasonYear
|
||||
episodes
|
||||
duration
|
||||
coverImage{
|
||||
medium
|
||||
large
|
||||
color
|
||||
extraLarge
|
||||
}
|
||||
bannerImage
|
||||
genres
|
||||
averageScore
|
||||
meanScore
|
||||
popularity
|
||||
trending
|
||||
favourites
|
||||
tags{
|
||||
id
|
||||
name
|
||||
description
|
||||
category
|
||||
rank
|
||||
isGeneralSpoiler
|
||||
isMediaSpoiler
|
||||
isAdult
|
||||
}
|
||||
isAdult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"page": 50,
|
||||
"perPage": 20,
|
||||
"airingAt_greater": 1730260800
|
||||
}
|
||||
83
rest/AniTrack/Get Items/AniList Item.http
Normal file
83
rest/AniTrack/Get Items/AniList Item.http
Normal file
@@ -0,0 +1,83 @@
|
||||
# @name AniList Item
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
Authorization: Bearer {{ANILIST_ACCESS_TOKEN}}
|
||||
|
||||
query ($userId: Int, $mediaId: Int, $listType: MediaType) {
|
||||
MediaList(mediaId: $mediaId, userId: $userId, type: $listType) {
|
||||
id
|
||||
mediaId
|
||||
userId
|
||||
media {
|
||||
id
|
||||
idMal
|
||||
tags {
|
||||
id
|
||||
name
|
||||
description
|
||||
rank
|
||||
isMediaSpoiler
|
||||
isAdult
|
||||
}
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
native
|
||||
}
|
||||
description
|
||||
coverImage {
|
||||
large
|
||||
}
|
||||
season
|
||||
seasonYear
|
||||
status
|
||||
episodes
|
||||
nextAiringEpisode {
|
||||
airingAt
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
isAdult
|
||||
}
|
||||
status
|
||||
startedAt {
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
completedAt {
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
notes
|
||||
progress
|
||||
score
|
||||
repeat
|
||||
user {
|
||||
id
|
||||
name
|
||||
avatar {
|
||||
large
|
||||
medium
|
||||
}
|
||||
statistics {
|
||||
anime {
|
||||
count
|
||||
statuses {
|
||||
status
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"userId": 413504,
|
||||
"mediaId": 170998,
|
||||
"listType": "ANIME"
|
||||
}
|
||||
70
rest/AniTrack/Get Items/AniList MediaList User Query.http
Normal file
70
rest/AniTrack/Get Items/AniList MediaList User Query.http
Normal file
@@ -0,0 +1,70 @@
|
||||
# @name AniList MediaList User Query
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
|
||||
query(
|
||||
$page: Int
|
||||
$perPage: Int
|
||||
$userId: Int
|
||||
$listType: MediaType
|
||||
$status: MediaListStatus
|
||||
) {
|
||||
Page(page: $page, perPage: $perPage) {
|
||||
pageInfo {
|
||||
total
|
||||
perPage
|
||||
currentPage
|
||||
lastPage
|
||||
hasNextPage
|
||||
}
|
||||
mediaList(userId: $userId, type: $listType, status: $status) {
|
||||
id
|
||||
mediaId
|
||||
userId
|
||||
media {
|
||||
id
|
||||
idMal
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
native
|
||||
}
|
||||
description
|
||||
coverImage {
|
||||
large
|
||||
}
|
||||
season
|
||||
seasonYear
|
||||
episodes
|
||||
}
|
||||
status
|
||||
notes
|
||||
progress
|
||||
score
|
||||
repeat
|
||||
user {
|
||||
id
|
||||
statistics {
|
||||
anime {
|
||||
count
|
||||
statuses {
|
||||
status
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
"page": 1,
|
||||
"perPage": 20,
|
||||
"userId": 413504,
|
||||
"listType": "ANIME",
|
||||
"status": "CURRENT"
|
||||
}
|
||||
44
rest/AniTrack/Get Items/AniList Search.http
Normal file
44
rest/AniTrack/Get Items/AniList Search.http
Normal file
@@ -0,0 +1,44 @@
|
||||
# @name AniList Search
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
|
||||
query ($search: String!, $listType: MediaType) {
|
||||
Page (page: 1, perPage: 100) {
|
||||
pageInfo {
|
||||
total
|
||||
currentPage
|
||||
lastPage
|
||||
hasNextPage
|
||||
perPage
|
||||
}
|
||||
media (search: $search, type: $listType) {
|
||||
id
|
||||
idMal
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
native
|
||||
}
|
||||
description
|
||||
coverImage {
|
||||
large
|
||||
}
|
||||
season
|
||||
seasonYear
|
||||
status
|
||||
episodes
|
||||
nextAiringEpisode{
|
||||
airingAt
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"search": "dan-da-dan",
|
||||
"listType": "ANIME"
|
||||
}
|
||||
93
rest/AniTrack/Get Items/GetAniListUserWatchingList.http
Normal file
93
rest/AniTrack/Get Items/GetAniListUserWatchingList.http
Normal file
@@ -0,0 +1,93 @@
|
||||
# @name GetAniListUserWatchList
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
|
||||
query (
|
||||
$page: Int
|
||||
$perPage: Int
|
||||
$userId: Int
|
||||
$listType: MediaType
|
||||
$status: MediaListStatus
|
||||
$sort: [MediaListSort]
|
||||
) {
|
||||
Page(page: $page, perPage: $perPage) {
|
||||
pageInfo {
|
||||
total
|
||||
perPage
|
||||
currentPage
|
||||
lastPage
|
||||
hasNextPage
|
||||
}
|
||||
mediaList(userId: $userId, type: $listType, status: $status, sort: $sort) {
|
||||
id
|
||||
mediaId
|
||||
userId
|
||||
media {
|
||||
id
|
||||
idMal
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
native
|
||||
}
|
||||
description
|
||||
coverImage {
|
||||
large
|
||||
}
|
||||
season
|
||||
seasonYear
|
||||
status
|
||||
episodes
|
||||
nextAiringEpisode {
|
||||
airingAt
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
}
|
||||
status
|
||||
startedAt {
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
completedAt {
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
notes
|
||||
progress
|
||||
score
|
||||
repeat
|
||||
user {
|
||||
id
|
||||
name
|
||||
avatar {
|
||||
large
|
||||
medium
|
||||
}
|
||||
statistics {
|
||||
anime {
|
||||
count
|
||||
statuses {
|
||||
status
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
"page": 1,
|
||||
"perPage": 20,
|
||||
"userId": 413504,
|
||||
"listType": "ANIME",
|
||||
"status": "CURRENT",
|
||||
"sort": "UPDATED_TIME_DESC"
|
||||
}
|
||||
3
rest/AniTrack/GetAuthorizationToken.http
Normal file
3
rest/AniTrack/GetAuthorizationToken.http
Normal file
@@ -0,0 +1,3 @@
|
||||
# @name GetAuthorizationToken
|
||||
|
||||
GET https://anilist.co/api/v2/oauth/authorize?client_id={{ANILIST_APP_ID}}&redirect_uri=http://localhost:6734/callback&response_type=code
|
||||
11
rest/AniTrack/Load AniList Oauth Page.http
Normal file
11
rest/AniTrack/Load AniList Oauth Page.http
Normal file
@@ -0,0 +1,11 @@
|
||||
# @name Load AniList Oauth Token
|
||||
|
||||
POST https://anilist.co/api/v2/oauth/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept: application/json
|
||||
|
||||
grant_type=authorization_code
|
||||
client_id={{ANILIST_APP_ID}}
|
||||
client_secret={{ANILIST_SECRET_ID}}
|
||||
redirect_uri=http://localhost:6734/callback
|
||||
code={{ANILIST_CODE}}
|
||||
76
rest/AniTrack/Set Items/AniList Change Episode Watched.http
Normal file
76
rest/AniTrack/Set Items/AniList Change Episode Watched.http
Normal file
@@ -0,0 +1,76 @@
|
||||
# @name AniList Change Episode Watched
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Content-Type: applicaton/json
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
Authorization: Bearer {{ANILIST_ACCESS_TOKEN}}
|
||||
|
||||
mutation($mediaId:Int, $progress:Int, $status:MediaListStatus){
|
||||
SaveMediaListEntry(mediaId:$mediaId, progress:$progress, status:$status){
|
||||
id
|
||||
mediaId
|
||||
userId
|
||||
media {
|
||||
id
|
||||
idMal
|
||||
title {
|
||||
romaji
|
||||
english
|
||||
native
|
||||
}
|
||||
description
|
||||
coverImage {
|
||||
large
|
||||
}
|
||||
season
|
||||
seasonYear
|
||||
status
|
||||
episodes
|
||||
nextAiringEpisode {
|
||||
airingAt
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
isAdult
|
||||
}
|
||||
status
|
||||
startedAt{
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
completedAt{
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
notes
|
||||
progress
|
||||
score
|
||||
repeat
|
||||
user {
|
||||
id
|
||||
name
|
||||
avatar{
|
||||
large
|
||||
medium
|
||||
}
|
||||
statistics{
|
||||
anime{
|
||||
count
|
||||
statuses{
|
||||
status
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"mediaId": 169417,
|
||||
"progress": 12,
|
||||
"status":"COMPLETED"
|
||||
}
|
||||
19
rest/AniTrack/Set Items/AniList Change Status.http
Normal file
19
rest/AniTrack/Set Items/AniList Change Status.http
Normal file
@@ -0,0 +1,19 @@
|
||||
# @name AniList Change Status
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Content-Type: applicaton/json
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
Authorization: Bearer {{ANILIST_ACCESS_TOKEN}}
|
||||
|
||||
mutation($mediaId:Int, $status:MediaListStatus){
|
||||
SaveMediaListEntry(mediaId:$mediaId, status:$status){
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"mediaId": 1,
|
||||
"status": "CURRENT"
|
||||
}
|
||||
65
rest/AniTrack/Set Items/Change Episode Count.http
Normal file
65
rest/AniTrack/Set Items/Change Episode Count.http
Normal file
@@ -0,0 +1,65 @@
|
||||
# @name AniList Change Count
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Content-Type: applicaton/json
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
Authorization: Bearer {{ANILIST_ACCESS_TOKEN}}
|
||||
|
||||
mutation (
|
||||
$mediaId: Int
|
||||
$progress: Int
|
||||
$status: MediaListStatus
|
||||
$score: Float
|
||||
$repeat: Int
|
||||
$notes: String
|
||||
$startedAt: FuzzyDateInput
|
||||
$completedAt: FuzzyDateInput
|
||||
) {
|
||||
SaveMediaListEntry(
|
||||
mediaId: $mediaId
|
||||
progress: $progress
|
||||
status: $status
|
||||
score: $score
|
||||
repeat: $repeat
|
||||
notes: $notes
|
||||
startedAt: $startedAt
|
||||
completedAt: $completedAt
|
||||
) {
|
||||
mediaId
|
||||
progress
|
||||
status
|
||||
score
|
||||
repeat
|
||||
notes
|
||||
startedAt {
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
completedAt {
|
||||
year
|
||||
month
|
||||
day
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"mediaId": 170998,
|
||||
"progress": 5,
|
||||
"status": "CURRENT",
|
||||
"score": 9.0,
|
||||
"repeat": 0,
|
||||
"notes": ",malSync::eyJ1IjoiaHR0cHM6Ly93d3cuY3J1bmNoeXJvbGwuY29tL3Nlcmllcy9HVkRIWDg1Wk4vI3NlYXNvbj1HNjNWQzJHUUsiLCJwIjoiIn0=::",
|
||||
"startedAt": {
|
||||
"year": 2024,
|
||||
"month": 7,
|
||||
"day": 10
|
||||
},
|
||||
"completedAt": {
|
||||
"year": 0,
|
||||
"month": 0,
|
||||
"day": 0
|
||||
}
|
||||
}
|
||||
17
rest/AniTrack/Set Items/Delete Media.http
Normal file
17
rest/AniTrack/Set Items/Delete Media.http
Normal file
@@ -0,0 +1,17 @@
|
||||
# @name AniList Delete Media
|
||||
|
||||
POST https://graphql.anilist.co
|
||||
Content-Type: applicaton/json
|
||||
Accept: applicaton/json
|
||||
X-REQUEST-TYPE: Graphql
|
||||
Authorization: Bearer {{ANILIST_ACCESS_TOKEN}}
|
||||
|
||||
mutation ($id: Int) {
|
||||
DeleteMediaListEntry(id: $id) {
|
||||
deleted
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"id": 430978266
|
||||
}
|
||||
6
rest/MAL/Get AnimeList.http
Normal file
6
rest/MAL/Get AnimeList.http
Normal file
@@ -0,0 +1,6 @@
|
||||
# @name Get AnimeList
|
||||
|
||||
GET https://api.myanimelist.net/v2/users/{{MAL_USER}}/animelist?fields=list_status&status=watching&limit=1000
|
||||
Content-Type application/x-www-form-urlencoded
|
||||
Accept: application/json
|
||||
Authorization: Bearer {{MAL_ACCESS_TOKEN}}
|
||||
12
rest/MAL/Get Authorization.http
Normal file
12
rest/MAL/Get Authorization.http
Normal file
@@ -0,0 +1,12 @@
|
||||
# @name Get Authorization
|
||||
|
||||
POST https://myanimelist.net/v1/oauth2/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept: application/json
|
||||
|
||||
grant_type=authorization_code&
|
||||
client_id={{MAL_CLIENT_ID}}&
|
||||
client_secret={{MAL_CLIENT_SECRET}}&
|
||||
redirect_uri=http://localhost:6734/callback&
|
||||
code={{MAL_CODE}}&
|
||||
code_verifier={{MAL_VERIFIER}}
|
||||
5
rest/MAL/Get Single Anime.http
Normal file
5
rest/MAL/Get Single Anime.http
Normal file
@@ -0,0 +1,5 @@
|
||||
# @name Get Single Anime
|
||||
|
||||
GET https://api.myanimelist.net/v2/anime/57380?fields=id,title,main_picture,alternative_titles,start_date,end_date,synopsis,mean,rank,popularity,num_list_users,num_scoring_users,nsfw,genres,created_at,updated_at,media_type,status,my_list_status,num_episodes,start_season,broadcast,source,average_episode_duration,rating,pictures,background,related_anime,recommendations,studios,statistics
|
||||
Accept: application/json
|
||||
Authorization: Bearer {{MAL_ACCESS_TOKEN}}
|
||||
5
rest/MAL/MAL Oauth Page.http
Normal file
5
rest/MAL/MAL Oauth Page.http
Normal file
@@ -0,0 +1,5 @@
|
||||
# @name MAL Oauth Page
|
||||
|
||||
GET https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id={{MAL_CLIENT_ID}}&redirect_uri={{MAL_CALLBACK_URI}}
|
||||
cookie MALSESSIONID=5ad688aafb78239bfd84752752ce193f; MALHLOGSESSID=632f67c3955267b4e57fc3d74b373ebb
|
||||
Accept: application/json
|
||||
8
rest/MAL/Update Anime Status.http
Normal file
8
rest/MAL/Update Anime Status.http
Normal file
@@ -0,0 +1,8 @@
|
||||
# @name Update Anime Status
|
||||
|
||||
PATCH https://api.myanimelist.net/v2/anime/50205/my_list_status
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept: application/json
|
||||
Authorization: Bearer {{MAL_ACCESS_TOKEN}}
|
||||
|
||||
num_watched_episodes=3
|
||||
3
rest/Simkl/Get Code.http
Normal file
3
rest/Simkl/Get Code.http
Normal file
@@ -0,0 +1,3 @@
|
||||
# @name Get Code
|
||||
|
||||
GET https://simkl.com/oauth/authorize?response_type=code&client_id={{SIMKL_CLIENT_ID}}&redirect_uri=http://localhost:6734/callback
|
||||
5
rest/Simkl/Get Items/Get Anime Full Info.http
Normal file
5
rest/Simkl/Get Items/Get Anime Full Info.http
Normal file
@@ -0,0 +1,5 @@
|
||||
# @name Get Anime Full Info
|
||||
|
||||
GET https://api.simkl.com/anime/40084?extended=full
|
||||
Accept application/json
|
||||
simkl-api-key {{SIMKL_CLIENT_ID}}
|
||||
7
rest/Simkl/Get Items/GetUser WatchList.http
Normal file
7
rest/Simkl/Get Items/GetUser WatchList.http
Normal file
@@ -0,0 +1,7 @@
|
||||
# @name GetUser WatchList
|
||||
|
||||
GET https://api.simkl.com/sync/all-items/anime/
|
||||
Content-Type application/json
|
||||
Accept application/json
|
||||
simkl-api-key {{SIMKL_CLIENT_ID}}
|
||||
Authorization Bearer {{SIMKL_AUTH_TOKEN}}
|
||||
@@ -0,0 +1,5 @@
|
||||
# @name Search By MALID to Get Simkl ID
|
||||
|
||||
GET https://api.simkl.com/search/id?anilist=174576
|
||||
Accept application/json
|
||||
simkl-api-key {{SIMKL_CLIENT_ID}}
|
||||
17
rest/Simkl/Post Items/Delete Entry.http
Normal file
17
rest/Simkl/Post Items/Delete Entry.http
Normal file
@@ -0,0 +1,17 @@
|
||||
# @name Delete Entry
|
||||
|
||||
GET https://api.simkl.com/sync/history/remove
|
||||
Content-Type application/json
|
||||
Accept application/json
|
||||
simkl-api-key {{SIMKL_CLIENT_ID}}
|
||||
Authorization Bearer {{SIMKL_AUTH_TOKEN}}
|
||||
|
||||
{
|
||||
"shows": [
|
||||
{
|
||||
"ids": {
|
||||
"simkl": 909121
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
40
rest/Simkl/Post Items/Update Episode.http
Normal file
40
rest/Simkl/Post Items/Update Episode.http
Normal file
@@ -0,0 +1,40 @@
|
||||
# @name Update Episode
|
||||
|
||||
GET https://api.simkl.com/sync/history
|
||||
Content-Type application/json
|
||||
Accept application/json
|
||||
simkl-api-key {{SIMKL_CLIENT_ID}}
|
||||
Authorization Bearer {{SIMKL_AUTH_TOKEN}}
|
||||
|
||||
{
|
||||
"shows": [
|
||||
{
|
||||
"title": "Ramen Aka Neko",
|
||||
"ids": {
|
||||
"simkl": 2307708,
|
||||
"mal": "57325",
|
||||
"anilist": "170998"
|
||||
},
|
||||
"episodes": [
|
||||
{
|
||||
"number": 1
|
||||
},
|
||||
{
|
||||
"number": 2
|
||||
},
|
||||
{
|
||||
"number": 3
|
||||
},
|
||||
{
|
||||
"number": 4
|
||||
},
|
||||
{
|
||||
"number": 5
|
||||
},
|
||||
{
|
||||
"number": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
rest/Simkl/SimklGetAuthorizationToken.http
Normal file
12
rest/Simkl/SimklGetAuthorizationToken.http
Normal file
@@ -0,0 +1,12 @@
|
||||
# @name SimklGetAuthorizationToken
|
||||
|
||||
POST https://api.simkl.com/oauth/token
|
||||
Content-Type application/json
|
||||
|
||||
{
|
||||
"grant_type": "authorization_code",
|
||||
"client_id": "{{SIMKL_CLIENT_ID}}",
|
||||
"client_secret": "{{SIMKL_CLIENT_SECRET}}",
|
||||
"redirect_uri": "http://localhost:6734/callback",
|
||||
"code": {{SIMKL_CODE}}
|
||||
}
|
||||
19
rest/http-client.env.json
Normal file
19
rest/http-client.env.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/mistweaverco/kulala.nvim/main/schemas/http-client.env.schema.json",
|
||||
"dev": {
|
||||
"ANILIST_ACCESS_TOKEN": "",
|
||||
"ANILIST_APP_ID": "",
|
||||
"ANILIST_SECRET": "",
|
||||
"ANILSIT_CODE": "",
|
||||
"MAL_ACCESS_TOKEN": "",
|
||||
"MAL_CLIENT_ID": "",
|
||||
"MAL_CLIENT_SECRET": "",
|
||||
"MAL_CODE": "",
|
||||
"MAL_USER": "",
|
||||
"MAL_VERIFIER": "",
|
||||
"SIMKL_AUTH_TOKEN": "",
|
||||
"SIMKL_CODE": "",
|
||||
"SIMKL_CLIENT_ID": "",
|
||||
"SIMKL_CLIENT_SECRET": ""
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,6 @@
|
||||
},
|
||||
"info": {
|
||||
"productName": "AniTrack",
|
||||
"productVersion": "0.1.6"
|
||||
"productVersion": "0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user