Compare commits

..

15 Commits

16 changed files with 766 additions and 325 deletions

View File

@ -3,6 +3,7 @@ package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
@ -90,6 +91,15 @@ func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime {
timeUntilAiring
episode
}
tags{
id
name
description
rank
isMediaSpoiler
isAdult
}
isAdult
}
status
startedAt{
@ -180,6 +190,15 @@ func (a *App) AniListSearch(query string) any {
timeUntilAiring
episode
}
tags{
id
name
description
rank
isMediaSpoiler
isAdult
}
isAdult
}
}
}
@ -256,6 +275,15 @@ func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) Ani
timeUntilAiring
episode
}
tags{
id
name
description
rank
isMediaSpoiler
isAdult
}
isAdult
}
status
startedAt {
@ -330,7 +358,7 @@ func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) Ani
func (a *App) AniListUpdateEntry(
mediaId int,
progress string,
progress int,
status string,
score float64,
repeat int,
@ -354,7 +382,7 @@ func (a *App) AniListUpdateEntry(
}
type Variables struct {
MediaId int `json:"mediaId"`
Progress string `json:"progress"`
Progress int `json:"progress"`
Status string `json:"status"`
Score float64 `json:"score"`
Repeat int `json:"repeat"`
@ -363,10 +391,10 @@ func (a *App) AniListUpdateEntry(
CompletedAt CompletedAt `json:"completedAt"`
}
body := struct {
Mutation string `json:"mutation"`
Query string `json:"query"`
Variables Variables `json:"variables"`
}{
Mutation: `
Query: `
mutation(
$mediaId:Int,
$progress:Int,
@ -427,6 +455,8 @@ func (a *App) AniListUpdateEntry(
returnedBody, _ := AniListQuery(body, true)
fmt.Println(string(returnedBody))
var post interface{}
err := json.Unmarshal(returnedBody, &post)
if err != nil {

View File

@ -68,6 +68,15 @@ type MediaList struct {
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"`
} `json:"media"`
Status string `json:"status"`
StartedAt struct {
@ -80,10 +89,10 @@ type MediaList struct {
Month int `json:"month"`
Day int `json:"day"`
} `json:"completedAt"`
Notes string `json:"notes"`
Progress int `json:"progress"`
Score int `json:"score"`
Repeat int `json:"repeat"`
Notes string `json:"notes"`
Progress int `json:"progress"`
Score float64 `json:"score"`
Repeat int `json:"repeat"`
User struct {
ID int `json:"id"`
Name string `json:"name"`
@ -103,66 +112,66 @@ type MediaList struct {
} `json:"user"`
}
var MediaListSort = struct {
MediaId string
MediaIdDesc string
Score string
ScoreDesc string
Status string
StatusDesc string
Progress string
ProgressDesc string
ProgressVolumes string
ProgressVolumesDesc string
Repeat string
RepeatDesc string
Priority string
PriorityDesc string
StartedOn string
StartedOnDesc string
FinishedOn string
FinishedOnDesc string
AddedTime string
AddedTimeDesc string
UpdatedTime string
UpdatedTimeDesc string
MediaTitleRomaji string
MediaTitleRomajiDesc string
MediaTitleEnglish string
MediaTitleEnglishDesc string
MediaTitleNative string
MediaTitleNativeDesc string
MediaPopularity string
MediaPopularityDesc string
}{
MediaId: "MEDIA_ID",
MediaIdDesc: "MEDIA_ID_DESC",
Score: "SCORE",
ScoreDesc: "SCORE_DESC",
Status: "STATUS",
StatusDesc: "STATUS_DESC",
Progress: "PROGRESS",
ProgressDesc: "PROGRESS_DESC",
ProgressVolumes: "PROGRESS_VOLUMES",
ProgressVolumesDesc: "PROGRESS_VOLUMES_DESC",
Repeat: "REPEAT",
RepeatDesc: "REPEAT_DESC",
Priority: "PRIORITY",
PriorityDesc: "PRIORITY_DESC",
StartedOn: "STARTED_ON",
StartedOnDesc: "STARTED_ON_DESC",
FinishedOn: "FINISHED_ON",
FinishedOnDesc: "FINISHED_ON_DESC",
AddedTime: "ADDED_TIME",
AddedTimeDesc: "ADDED_TIME_DESC",
UpdatedTime: "UPDATED_TIME",
UpdatedTimeDesc: "UPDATED_TIME_DESC",
MediaTitleRomaji: "MEDIA_TITLE_ROMAJI",
MediaTitleRomajiDesc: "MEDIA_TITLE_ROMAJI_DESC",
MediaTitleEnglish: "MEDIA_TITLE_ENGLISH",
MediaTitleEnglishDesc: "MEDIA_TITLE_ENGLISH_DESC",
MediaTitleNative: "MEDIA_TITLE_NATIVE",
MediaTitleNativeDesc: "MEDIA_TITLE_NATIVE_DESC",
MediaPopularity: "MEDIA_POPULARITY",
MediaPopularityDesc: "MEDIA_POPULARITY_DESC",
}
//var MediaListSort = struct {
// MediaId string
// MediaIdDesc string
// Score string
// ScoreDesc string
// Status string
// StatusDesc string
// Progress string
// ProgressDesc string
// ProgressVolumes string
// ProgressVolumesDesc string
// Repeat string
// RepeatDesc string
// Priority string
// PriorityDesc string
// StartedOn string
// StartedOnDesc string
// FinishedOn string
// FinishedOnDesc string
// AddedTime string
// AddedTimeDesc string
// UpdatedTime string
// UpdatedTimeDesc string
// MediaTitleRomaji string
// MediaTitleRomajiDesc string
// MediaTitleEnglish string
// MediaTitleEnglishDesc string
// MediaTitleNative string
// MediaTitleNativeDesc string
// MediaPopularity string
// MediaPopularityDesc string
//}{
// MediaId: "MEDIA_ID",
// MediaIdDesc: "MEDIA_ID_DESC",
// Score: "SCORE",
// ScoreDesc: "SCORE_DESC",
// Status: "STATUS",
// StatusDesc: "STATUS_DESC",
// Progress: "PROGRESS",
// ProgressDesc: "PROGRESS_DESC",
// ProgressVolumes: "PROGRESS_VOLUMES",
// ProgressVolumesDesc: "PROGRESS_VOLUMES_DESC",
// Repeat: "REPEAT",
// RepeatDesc: "REPEAT_DESC",
// Priority: "PRIORITY",
// PriorityDesc: "PRIORITY_DESC",
// StartedOn: "STARTED_ON",
// StartedOnDesc: "STARTED_ON_DESC",
// FinishedOn: "FINISHED_ON",
// FinishedOnDesc: "FINISHED_ON_DESC",
// AddedTime: "ADDED_TIME",
// AddedTimeDesc: "ADDED_TIME_DESC",
// UpdatedTime: "UPDATED_TIME",
// UpdatedTimeDesc: "UPDATED_TIME_DESC",
// MediaTitleRomaji: "MEDIA_TITLE_ROMAJI",
// MediaTitleRomajiDesc: "MEDIA_TITLE_ROMAJI_DESC",
// MediaTitleEnglish: "MEDIA_TITLE_ENGLISH",
// MediaTitleEnglishDesc: "MEDIA_TITLE_ENGLISH_DESC",
// MediaTitleNative: "MEDIA_TITLE_NATIVE",
// MediaTitleNativeDesc: "MEDIA_TITLE_NATIVE_DESC",
// MediaPopularity: "MEDIA_POPULARITY",
// MediaPopularityDesc: "MEDIA_POPULARITY_DESC",
//}

View File

@ -28,14 +28,14 @@ type SimklUser struct {
type SimklWatchList struct {
Anime []struct {
LastWatchedAt string `json:"last_watched_at" ts_type:"last_watched_at"`
Status string `json:"status" ts_type:"status"`
UserRating int `json:"user_rating" ts_type:"user_rating"`
LastWatched string `json:"last_watched" ts_type:"last_watched"`
NextToWatch string `json:"next_to_watch" ts_type:"next_to_watch"`
WatchedEpisodesCount int `json:"watched_episodes_count" ts_type:"watched_episodes_count"`
TotalEpisodesCount int `json:"total_episodes_count" ts_type:"total_episodes_count"`
NotAiredEpisodesCount int `json:"not_aired_episodes_count" ts_type:"not_aired_episodes_count"`
LastWatchedAt string `json:"last_watched_at" ts_type:"last_watched_at"`
Status string `json:"status" ts_type:"status"`
UserRating float64 `json:"user_rating" ts_type:"user_rating"`
LastWatched string `json:"last_watched" ts_type:"last_watched"`
NextToWatch string `json:"next_to_watch" ts_type:"next_to_watch"`
WatchedEpisodesCount int `json:"watched_episodes_count" ts_type:"watched_episodes_count"`
TotalEpisodesCount int `json:"total_episodes_count" ts_type:"total_episodes_count"`
NotAiredEpisodesCount int `json:"not_aired_episodes_count" ts_type:"not_aired_episodes_count"`
Show struct {
Title string `json:"title" ts_type:"title"`
Poster string `json:"poster" ts_type:"poster"`

View File

@ -157,8 +157,6 @@ func getSimklAuthorizationToken(content string) SimklJWT {
func (a *App) GetSimklLoggedInUser() SimklUser {
a.SimklLogin()
fmt.Println("Token: ", simklJwt.AccessToken)
client := &http.Client{}
req, _ := http.NewRequest("POST", "https://api.simkl.com/users/settings", nil)

View File

@ -24,6 +24,14 @@ body:graphql {
media {
id
idMal
tags{
id
name
description
rank
isMediaSpoiler
isAdult
}
title {
romaji
english
@ -42,6 +50,7 @@ body:graphql {
timeUntilAiring
episode
}
isAdult
}
status
startedAt {

View File

@ -6,5 +6,6 @@ vars {
}
vars:secret [
code,
SIMKL_AUTH_TOKEN
SIMKL_AUTH_TOKEN,
ANILIST_ACCESS_TOKEN
]

View File

@ -27,6 +27,7 @@
"@ernane/svelte-star-rating": "^1.1.7",
"@popperjs/core": "^2.11.8",
"flowbite": "^2.4.1",
"flowbite-svelte": "^0.46.15"
"flowbite-svelte": "^0.46.15",
"moment": "^2.30.1"
}
}

View File

@ -1,53 +1,39 @@
<script lang="ts">
import {anilistModal, GetAniListSingleItemAndOpenModal, title} from "./GetAniListSingleItemAndOpenModal.svelte";
import {
anilistModal,
GetAniListSingleItemAndOpenModal,
title,
simklWatchList,
aniListLoggedIn,
simklLoggedIn
} from "./GlobalVariablesAndHelperFunctions.svelte";
import {
CheckIfAniListLoggedIn,
CheckIfSimklLoggedIn,
GetAniListLoggedInUser,
GetAniListUserWatchingList,
GetSimklLoggedInUser, SimklGetUserWatchlist,
GetSimklLoggedInUser,
SimklGetUserWatchlist,
} from "../wailsjs/go/main/App";
import {type AniListUser, MediaListSort} from "./anilist/types/AniListTypes";
import type {AniListCurrentUserWatchList} from "./anilist/types/AniListCurrentUserWatchListType"
import Header from "./Header.svelte";
import StarRatting from '@ernane/svelte-star-rating'
import {Button, Modal} from "flowbite-svelte";
import {Button, Rating} from "flowbite-svelte";
import {default as Modal} from "./modal/Modal.svelte"
import ChangeDataDialogue from "./ChangeDataDialogue.svelte";
import {onMount} from "svelte";
import type {SimklUser, SimklWatchList} from "./simkl/types/simklTypes";
import {writable} from "svelte/store";
import type {SimklUser} from "./simkl/types/simklTypes";
const config = {
readOnly: false,
countStars: 5,
range: {
min: 0,
max: 5,
step: 0.5
},
score: 0.0,
showScore: true,
scoreFormat: function () {
return `(${this.score.toFixed(1)}/${this.countStars})`
},
name: "",
starConfig: {
size: 20,
fillColor: '#F9ED4F',
strokeColor: "#e2c714",
unfilledColor: '#FFF',
strokeUnfilledColor: '#000'
}
}
let aniListLoggedIn = false
let aniListPrimary = true
let simklUser: SimklUser
let simklLoggedIn = false
let aniListUser: AniListUser
let aniListWatchlist: AniListCurrentUserWatchList
export let simklWatchList = writable({} as SimklWatchList)
let isAniListLoggedIn: boolean
let isSimklLoggedIn: boolean
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
simklLoggedIn.subscribe((value) => isSimklLoggedIn = value)
let page = 1
let perPage = 20
const size = "xl"
@ -60,10 +46,10 @@
if (aniListPrimary) {
GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((result) => {
aniListWatchlist = result
aniListLoggedIn = true
aniListLoggedIn.set(true)
})
} else {
aniListLoggedIn = result
aniListLoggedIn.set(result)
}
})
}
@ -75,7 +61,7 @@
simklUser = result
SimklGetUserWatchlist().then(result => {
simklWatchList.set(result)
simklLoggedIn = result
simklLoggedIn.set(result)
})
})
}
@ -85,38 +71,38 @@
function loginToSimkl(): void {
GetSimklLoggedInUser().then(result => {
simklUser = result
simklLoggedIn = true
simklLoggedIn.set(true)
})
}
function loginToAniList(): void {
GetAniListLoggedInUser().then(result => {
aniListUser = result
aniListLoggedIn = true
aniListLoggedIn.set(true)
if (aniListPrimary) {
GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then(result => aniListWatchlist = result)
}
})
}
function anilistGetUserWatchlist(): void {
GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((result) => {
aniListWatchlist = result
aniListLoggedIn = true
})
}
let count = 1;
const decrement = () => {
if (count > 0) {
count--
}
}
const increment = () => {
count++
}
// function anilistGetUserWatchlist(): void {
// GetAniListUserWatchingList(page, perPage, MediaListSort.UpdatedTimeDesc).then((result) => {
// aniListWatchlist = result
// aniListLoggedIn.set(true)
// })
// }
//
// let count = 1;
//
// const decrement = () => {
// if (count > 0) {
// count--
// }
// }
//
// const increment = () => {
// count++
// }
</script>
@ -124,88 +110,56 @@
<Header/>
<main>
{#if aniListLoggedIn}
<div>You are logged into AniList, {aniListWatchlist.data.Page.mediaList[0].user.name}!</div>
{#if isAniListLoggedIn}
<div>You are logged into AniList, {aniListUser.data.Viewer.name}!</div>
{:else}
<button class="btn" on:click={loginToAniList}>Login to AniList</button>
{/if}
{#if simklLoggedIn}
{#if isSimklLoggedIn}
<div>You are logged into Simkl, {simklUser.user.name}</div>
{:else}
<Button class="btn" on:click={loginToSimkl}>Login to Simkl</Button>
{/if}
{#if aniListLoggedIn}
<div class="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24 lg:max-w-7xl lg:px-8">
<h1>Your Watching List</h1>
{#if isAniListLoggedIn}
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8">
<h1 class="text-left text-xl font-bold mb-4">Your Watching List</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 aniListWatchlist.data.Page.mediaList as media}
<div class="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg xl:aspect-h-8 xl:aspect-w-7">
<button on:click={() => GetAniListSingleItemAndOpenModal(media.media.id, true)} class="group">
<div class="flex flex-col items-center">
<div class="flex flex-col items-center group">
<button on:click={() => GetAniListSingleItemAndOpenModal(media.media.id, true)}>
<img class="rounded-lg" src={media.media.coverImage.large} alt={
media.media.title.english === "" ?
media.media.title.romaji :
media.media.title.english
}/>
{config.score = media.score / 2.0}
<StarRatting {config}/>
<h3 class="mt-4 text-sm text-white-700">{
</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={() => GetAniListSingleItemAndOpenModal(media.media.id, true)}>
{
media.media.title.english === "" ?
media.media.title.romaji :
media.media.title.english
}</h3>
<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>
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>
</div>
{/each}
</div>
</div>
{/if}
<div class="flex items-center justify-center">
<button on:click={decrement}
class="flex justify-center items-center w-10 h-10 rounded-full text-white focus:outline-none bg-gray-400 hover:bg-gray-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12H4"></path>
</svg>
</button>
<input bind:value={count} class="text-2xl font-bold mx-4"/>
<button on:click={increment}
class="flex justify-center items-center w-10 h-10 rounded-full text-white focus:outline-none bg-indigo-500 hover:bg-indigo-600">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v12M6 12h12"></path>
</svg>
</button>
</div>
<!-- <div class="relative max-w-sm">-->
<!-- <div class="absolute inset-y-0 start-0 flex items-center ps-3.5 pointer-events-none">-->
<!-- <svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">-->
<!-- <path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>-->
<!-- </svg>-->
<!-- </div>-->
<!-- <input-->
<!-- datepicker-->
<!-- datepicker-buttons-->
<!-- datepicker-autoselect-today-->
<!-- datepicker-autohide-->
<!-- datepicker-title="Started At"-->
<!-- id="startedAt"-->
<!-- type="text"-->
<!-- class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500-->
<!-- focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600-->
<!-- dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"-->
<!-- placeholder="Select date">-->
<!-- </div>-->
<Modal title={$title} bind:open={$anilistModal} {size} autoclose={false}>
<ChangeDataDialogue/>
</Modal>

View File

@ -1,7 +1,90 @@
<script lang="ts">
import {anime} from "./GetAniListSingleItemAndOpenModal.svelte";
import {
anilistModal,
simklWatchList,
aniListLoggedIn,
simklLoggedIn
} from "./GlobalVariablesAndHelperFunctions.svelte";
import {aniListAnime} from "./GlobalVariablesAndHelperFunctions.svelte";
import {Button} from "flowbite-svelte";
// @ts-ignore
import StarRatting from "@ernane/svelte-star-rating"
import moment from 'moment'
import { Table, TableBody, TableBodyCell, TableBodyRow, TableHead, TableHeadCell } from 'flowbite-svelte';
import { writable } from 'svelte/store';
import type {SimklAnime} from "./simkl/types/simklTypes";
import { get } from 'svelte/store';
import {AniListUpdateEntry} from "../wailsjs/go/main/App";
const simklWatch = get(simklWatchList);
let isAniListLoggedIn: boolean
let isSimklLoggedIn: boolean
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
simklLoggedIn.subscribe((value) => isSimklLoggedIn = value)
const simklAnime: SimklAnime | undefined = simklWatch.anime.filter((x) => Number(x.show.ids.mal) === aniListAnime.data.MediaList.media.idMal)[0]
let items = [];
if(isAniListLoggedIn) {
items.push({
id: aniListAnime.data.MediaList.id,
service: "AniList",
progress: aniListAnime.data.MediaList.progress,
status: aniListAnime.data.MediaList.status,
startedAt: `${aniListAnime.data.MediaList.startedAt.month}-${aniListAnime.data.MediaList.startedAt.day}-${aniListAnime.data.MediaList.startedAt.year}`,
completedAt: `${aniListAnime.data.MediaList.completedAt.month}-${aniListAnime.data.MediaList.completedAt.day}-${aniListAnime.data.MediaList.completedAt.year}`,
score: aniListAnime.data.MediaList.score,
repeat: aniListAnime.data.MediaList.repeat,
notes: aniListAnime.data.MediaList.notes
})
}
if(isSimklLoggedIn && simklAnime !== undefined) {
items.push({
id: simklAnime.show.ids.simkl,
service: "Simkl",
progress: simklAnime.watched_episodes_count,
status: simklAnime.status,
startedAt: "",
completedAt: "",
score: simklAnime.user_rating,
repeat: 0,
notes: ""
})
}
const sortKey = writable('service'); // default sort key
const sortDirection = writable(1); // default sort direction (ascending)
const sortItems = writable(items.slice()); // make a copy of the items array
// Define a function to sort the items
const sortTable = (key: any) => {
// If the same key is clicked, reverse the sort direction
if ($sortKey === key) {
sortDirection.update((val) => -val);
} else {
sortKey.set(key);
sortDirection.set(1);
}
};
$: {
const key = $sortKey;
const direction = $sortDirection;
const sorted = [...$sortItems].sort((a, b) => {
const aVal = a[key];
const bVal = b[key];
if (aVal < bVal) {
return -direction;
} else if (aVal > bVal) {
return direction;
}
return 0;
});
sortItems.set(sorted);
}
const ratingInWords = {
0: "Not Reviewed",
@ -17,9 +100,14 @@
10: "Masterpiece",
}
const title = anime.data.MediaList.media.title.english !== "" ?
anime.data.MediaList.media.title.english :
anime.data.MediaList.media.title.romaji
const hide = (e) => {
e.preventDefault();
anilistModal.set(false)
};
const title = aniListAnime.data.MediaList.media.title.english !== "" ?
aniListAnime.data.MediaList.media.title.english :
aniListAnime.data.MediaList.media.title.romaji
let config = {
readOnly: false,
@ -29,7 +117,7 @@
max: 5,
step: 0.5
},
score: anime.data.MediaList.score / 2,
score: aniListAnime.data.MediaList.score / 2,
showScore: false,
scoreFormat: function () {
return `(${this.score.toFixed(1)}/${this.countStars})`
@ -45,42 +133,37 @@
}
let values = {
progress: anime.data.MediaList.progress,
status: anime.data.MediaList.status,
progress: aniListAnime.data.MediaList.progress,
status: aniListAnime.data.MediaList.status,
startedAt: {
year: anime.data.MediaList.startedAt.year,
month: anime.data.MediaList.startedAt.month,
day: anime.data.MediaList.startedAt.day
year: aniListAnime.data.MediaList.startedAt.year,
month: aniListAnime.data.MediaList.startedAt.month,
day: aniListAnime.data.MediaList.startedAt.day
},
completedAt: {
year: anime.data.MediaList.completedAt.year,
month: anime.data.MediaList.completedAt.month,
day: anime.data.MediaList.completedAt.day
year: aniListAnime.data.MediaList.completedAt.year,
month: aniListAnime.data.MediaList.completedAt.month,
day: aniListAnime.data.MediaList.completedAt.day
},
repeat: anime.data.MediaList.repeat,
score: anime.data.MediaList.score,
notes: anime.data.MediaList.notes
repeat: aniListAnime.data.MediaList.repeat,
score: aniListAnime.data.MediaList.score,
notes: aniListAnime.data.MediaList.notes
}
let startedAtDate: string
let completedAtDate: string
const changeRating = (e) => {
config.score = e.target.valueAsNumber
values.score = e.target.valueAsNumber * 2
}
let count = 1;
const decrement = () => {
if (count > 0) {
count--
}
if (values.startedAt.year > 0) {
let startedAtISODate = new Date(values.startedAt.year, values.startedAt.month - 1, values.startedAt.day)
let startedAtMoment = moment(startedAtISODate)
startedAtDate = startedAtMoment.format('YYYY-MM-DD')
}
const increment = () => {
count++
}
let startedAtDate = `${values.startedAt.year}-${values.startedAt.month}-${values.startedAt.day}`
const transformStartedAtDate = (e) => {
const re = /^([0-9]{4})-([0-9]{2})-([0-9]{2})/
const date = re.exec(e.target.value)
@ -89,31 +172,62 @@
values.startedAt.day = Number(date[3])
}
console.log(startedAtDate)
if (values.completedAt.year > 0) {
let completedAtISODate = new Date(values.completedAt.year, values.completedAt.month - 1, values.completedAt.day)
let completedAtMoment = moment(completedAtISODate)
completedAtDate = completedAtMoment.format('YYYY-MM-DD')
}
const transformCompletedAtDate = (e) => {
const re = /^([0-9]{4})-([0-9]{2})-([0-9]{2})/
const date = re.exec(e.target.value)
values.completedAt.year = Number(date[1])
values.completedAt.month = Number(date[2])
values.completedAt.day = Number(date[3])
}
const submitData = async () => {
await AniListUpdateEntry(
aniListAnime.data.MediaList.mediaId,
values.progress,
values.status,
values.score,
values.repeat,
values.notes,
values.startedAt.year,
values.startedAt.month,
values.startedAt.day,
values.completedAt.year,
values.completedAt.month,
values.completedAt.day
).then((value) => {
console.log(value)
})
}
</script>
<div>
<div class="grid grid-rows-2 grid-cols-10 grid-flow-col gap-4 mt-10">
<div class="row-span-2 col-span-2 space-y-3">
<img class="rounded-lg" src={anime.data.MediaList.media.coverImage.large} alt="{title} Cover Image">
<div id="inapp-data">
<div class="grid grid-cols-1 md:grid-cols-10 grid-flow-col gap-4">
<div class="md:col-span-2 space-y-3">
<img class="rounded-lg" src={aniListAnime.data.MediaList.media.coverImage.large} alt="{title} Cover Image">
<StarRatting bind:config on:change={changeRating}/>
<p>Rating: {config.score * 2}</p>
<p>{ratingInWords[config.score * 2]}</p>
</div>
<div class="col-span-8 z-30">
<div class="flex flex-row p-10 justify-center gap-x-56">
<div class="mr-4">
<label for="episodes" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Episode Progress</label>
<div class="md:col-span-8 ">
<div class="flex flex-col md:flex-row md:pl-10 md:pr-10 pt-5 pb-5 justify-center md:gap-x-24 lg:gap-x-56">
<div>
<label for="episodes" class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white">Episode
Progress</label>
<input
type="number"
name="episodes"
min="0"
id="episodes"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600
focus:border-primary-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400
focus:border-primary-600 block w-24 p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400
dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
bind:value={values.progress}
required>
@ -121,13 +235,13 @@
<div>
<label for="status" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select
your
country</label>
<label for="status"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white">Status</label>
<select id="status"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500
focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400
dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
bind:value={values.status}
>
<option>CURRENT</option>
@ -139,58 +253,141 @@
</select>
</div>
</div>
<div class="flex flex-row p-10 justify-center">
<div 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">
<div class="relative z-40 max-w-sm">
<div class="absolute inset-y-0 start-0 flex items-center ps-3.5 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
</svg>
</div>
<!-- <input-->
<!-- datepicker-->
<!-- datepicker-buttons-->
<!-- datepicker-autoselect-today-->
<!-- datepicker-autohide-->
<!-- datepicker-title="Started At"-->
<!-- id="startedAt"-->
<!-- type="text"-->
<!-- name="startedAt"-->
<!-- class="z-50 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500-->
<!-- focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600-->
<!-- dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"-->
<!-- value={`${values.startedAt.year}-${values.startedAt.month}-${values.startedAt.day}`}-->
<!-- on:change={transformStartedAtDate}-->
<!-- >-->
<input
id="startedAt"
type="date"
name="startedAt"
class="z-50 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500
<div>
<label for="startedAt" class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white">Date
Started</label>
<div class="relative max-w-sm">
<div class="absolute inset-y-0 start-0 flex items-center ps-3.5 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
</svg>
</div>
<input
id="startedAt"
type="date"
name="startedAt"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500
focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
value={startedAtDate}
on:change={transformStartedAtDate}
>
value={startedAtDate}
placeholder="Date Started"
on:change={transformStartedAtDate}
>
</div>
</div>
<div>
<label for="completedAt" class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white">Date
Completed</label>
<div class="relative max-w-sm">
<div class="absolute inset-y-0 start-0 flex items-center ps-3.5 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
</svg>
</div>
<input
id="completedAt"
type="date"
name="completedAt"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500
focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
value={completedAtDate}
placeholder="Date Completed"
on:change={transformCompletedAtDate}
>
</div>
</div>
<div>
<label for="repeat"
class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white">Rewatched</label>
<input
type="number"
name="repeat"
min="0"
id="repeat"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600
focus:border-primary-600 block w-24 p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400
dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
bind:value={values.repeat}
required>
</div>
</div>
<div class="flex flex-col md:flex-row md:pl-10 md:pr-10 pt-5 pb-5 justify-center">
<div class="w-full">
<label for="notes" class="text-left block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your
notes</label>
<textarea id="notes" rows="3"
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Write your thoughts here..."
bind:value={values.notes}></textarea>
</div>
</div>
</div>
</div>
<footer class="bg-white rounded-lg shadow m-4 dark:bg-gray-800">
<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-gray-900 dark:text-white">AniList</h2>
</div>
</div>
<Table hoverable={true}>
<TableHead>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('id')}>ID</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('service')}>Service</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('progress')}>Episode Progress</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('status')}>Status</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('startedAt')}>Date Started</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('completedAt')}>Date Completed</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('score')}>Rating</TableHeadCell>
<TableHeadCell class="cursor-pointer" on:click={() => sortTable('repeat')}>Rewatches</TableHeadCell>
<TableHeadCell>Notes</TableHeadCell>
</TableHead>
<TableBody tableBodyClass="divide-y">
{#each $sortItems as item}
<TableBodyRow>
<TableBodyCell class="overflow-x-auto">{item.id}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.service}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.progress}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.status}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.startedAt}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.completedAt}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.score}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.repeat}</TableBodyCell>
<TableBodyCell class="overflow-x-auto">{item.notes}</TableBodyCell>
</TableBodyRow>
{/each}
</TableBody>
</Table>
<div class="bg-white rounded-lg shadow max-w-4-4 dark:bg-gray-800">
<div class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-end">
<Button
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium
rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none
dark:focus:ring-blue-800"
on:click={() => alert('Handle "success"')}>Sync Changes
on:click={submitData}>Sync Changes
</Button>
<Button
class="text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4
focus:ring-gray-100 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">
dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700"
on:click={hide}>
Cancel
</Button>
</div>
</footer>
</div>
<div>
<h3 class="text-2xl">
Summary
</h3>
<p>{@html aniListAnime.data.MediaList.media.description}</p>
</div>
</div>

View File

@ -2,17 +2,21 @@
import {GetAniListItem} from "../wailsjs/go/main/App";
import type {AniListGetSingleAnime} from "./anilist/types/AniListCurrentUserWatchListType.js";
import {writable} from 'svelte/store'
import type {SimklWatchList} from "./simkl/types/simklTypes";
export let anime: AniListGetSingleAnime
export let aniListAnime: AniListGetSingleAnime
export let title = writable("")
export let anilistModal = writable(false);
export let aniListLoggedIn = writable(false)
export let simklLoggedIn = writable(false)
export let simklWatchList = writable({} as SimklWatchList)
export function GetAniListSingleItemAndOpenModal(aniId: number, login: boolean): void {
GetAniListItem(aniId, login).then(result => {
anime = result
title.set(anime.data.MediaList.media.title.english === "" ?
anime.data.MediaList.media.title.romaji :
anime.data.MediaList.media.title.english)
aniListAnime = result
title.set(aniListAnime.data.MediaList.media.title.english === "" ?
aniListAnime.data.MediaList.media.title.romaji :
aniListAnime.data.MediaList.media.title.english)
anilistModal.set(true)
})
}

View File

@ -2,7 +2,7 @@
import {AniListSearch} from "../wailsjs/go/main/App";
import type {AniSearchList} from "./anilist/types/AniListTypes";
import {GetAniListSingleItemAndOpenModal} from "./GetAniListSingleItemAndOpenModal.svelte";
import {GetAniListSingleItemAndOpenModal} from "./GlobalVariablesAndHelperFunctions.svelte";
let aniSearch = ""
let aniListSearch: AniSearchList
@ -51,14 +51,18 @@
aria-labelledby="aniListSearchButton">
{#each aniListSearch.data.Page.media as media}
<li class="w-full">
<button on:click={() => {
GetAniListSingleItemAndOpenModal(media.id, false)
}}
class="flex w-full items-start p-1 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white rounded-lg">
<img class="rounded-bl-lg rounded-tl-lg max-w-24 max-h-24" src={media.coverImage.large}
alt="{media.title.english === '' || media.title.english === null ? media.title.romaji : media.title.english} Cover">
<p class="bg-gray-800 text-left w-full h-24 p-2 rounded-tr-lg rounded-br-lg">{media.title.english === '' || media.title.english === null ? media.title.romaji : media.title.english }</p>
</button>
<div class="flex w-full items-start p-1 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white rounded-lg">
<button on:click={() => {
GetAniListSingleItemAndOpenModal(media.id, false)
}}
>
<img class="rounded-bl-lg rounded-tl-lg max-w-24 max-h-24" src={media.coverImage.large}
alt="{media.title.english === '' || media.title.english === null ? media.title.romaji : media.title.english} Cover">
</button>
<button class="rounded-bl-lg rounded-tl-lg w-full h-24" on:click={() => {
GetAniListSingleItemAndOpenModal(media.id, false)
}} >{media.title.english === '' || media.title.english === null ? media.title.romaji : media.title.english }</button>
</div>
</li>
{/each}
</ul>

View File

@ -0,0 +1,155 @@
<script>import { twMerge } from "tailwind-merge";
import { Frame } from "flowbite-svelte";
import { createEventDispatcher } from "svelte";
import {CloseButton} from "flowbite-svelte";
import focusTrap from "../../node_modules/flowbite-svelte/dist/utils/focusTrap.js";
export let open = false;
export let title = "";
export let size = "md";
export let color = "default";
export let placement = "center";
export let autoclose = false;
export let outsideclose = false;
export let dismissable = true;
export let backdropClass = "fixed inset-0 z-20 bg-gray-900 bg-opacity-50 dark:bg-opacity-80";
export let classBackdrop = void 0;
export let dialogClass = "fixed top-0 start-0 end-0 h-modal md:inset-0 md:h-full z-30 w-full p-4 flex";
export let classDialog = void 0;
export let defaultClass = "relative flex flex-col mx-auto";
export let headerClass = "flex justify-between items-center p-4 md:p-5 rounded-t-lg";
export let classHeader = void 0;
export let bodyClass = "p-4 md:p-5 space-y-4 flex-1 overflow-y-auto overscroll-contain";
export let classBody = void 0;
export let footerClass = "flex items-center p-4 md:p-5 space-x-3 rtl:space-x-reverse rounded-b-lg";
export let classFooter = void 0;
const dispatch = createEventDispatcher();
$: dispatch(open ? "open" : "close");
function prepareFocus(node) {
const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT);
let n;
while (n = walker.nextNode()) {
if (n instanceof HTMLElement) {
const el = n;
const [x, y] = isScrollable(el);
if (x || y) el.tabIndex = 0;
}
}
node.focus();
}
const getPlacementClasses = (placement2) => {
switch (placement2) {
case "top-left":
return ["justify-start", "items-start"];
case "top-center":
return ["justify-center", "items-start"];
case "top-right":
return ["justify-end", "items-start"];
case "center-left":
return ["justify-start", "items-center"];
case "center":
return ["justify-center", "items-center"];
case "center-right":
return ["justify-end", "items-center"];
case "bottom-left":
return ["justify-start", "items-end"];
case "bottom-center":
return ["justify-center", "items-end"];
case "bottom-right":
return ["justify-end", "items-end"];
default:
return ["justify-center", "items-center"];
}
};
const sizes = {
xs: "max-w-md",
sm: "max-w-lg",
md: "max-w-2xl",
lg: "max-w-4xl",
xl: "max-w-6xl"
};
const onAutoClose = (e) => {
const target = e.target;
if (autoclose && target?.tagName === "BUTTON") hide(e);
};
const onOutsideClose = (e) => {
const target = e.target;
if (outsideclose && target === e.currentTarget) hide(e);
};
const hide = (e) => {
e.preventDefault();
open = false;
};
const isScrollable = (e) => [e.scrollWidth > e.clientWidth && ["scroll", "auto"].indexOf(getComputedStyle(e).overflowX) >= 0, e.scrollHeight > e.clientHeight && ["scroll", "auto"].indexOf(getComputedStyle(e).overflowY) >= 0];
function handleKeys(e) {
if (e.key === "Escape" && dismissable) return hide(e);
}
$: backdropCls = twMerge(backdropClass, classBackdrop);
$: dialogCls = twMerge(dialogClass, classDialog, getPlacementClasses(placement));
$: frameCls = twMerge(defaultClass, "w-full divide-y", $$props.class);
$: headerCls = twMerge(headerClass, classHeader);
$: bodyCls = twMerge(bodyClass, classBody);
$: footerCls = twMerge(footerClass, classFooter);
</script>
{#if open}
<!-- backdrop -->
<div class={backdropCls}></div>
<!-- dialog -->
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<div on:keydown={handleKeys} on:wheel|preventDefault|nonpassive use:prepareFocus use:focusTrap on:click={onAutoClose} on:mousedown={onOutsideClose} class={dialogCls} tabindex="-1" aria-modal="true" role="dialog">
<div class="flex relative {sizes[size]} w-full max-h-full">
<!-- Modal content -->
<Frame rounded shadow {...$$restProps} class={frameCls} {color}>
<!-- Modal header -->
{#if $$slots.header || title}
<Frame class={headerCls} {color}>
<slot name="header">
<h3 class="text-xl font-semibold {color === 'default' ? '' : 'text-gray-900 dark:text-white'} p-0">
{title}
</h3>
</slot>
{#if dismissable}<CloseButton name="Close modal" {color} on:click={hide} />{/if}
</Frame>
{/if}
<!-- Modal body -->
<div class={bodyCls} role="document" on:keydown|stopPropagation={handleKeys} on:wheel|stopPropagation|passive>
{#if dismissable && !$$slots.header && !title}
<CloseButton name="Close modal" class="absolute top-3 end-2.5" {color} on:click={hide} />
{/if}
<slot></slot>
</div>
<!-- Modal footer -->
{#if $$slots.footer}
<Frame class={footerCls} {color}>
<slot name="footer"></slot>
</Frame>
{/if}
</Frame>
</div>
</div>
{/if}
<!--
@component
[Go to docs](https://flowbite-svelte.com/)
## Props
@prop export let open: boolean = false;
@prop export let title: string = '';
@prop export let size: SizeType = 'md';
@prop export let color: ComponentProps<Frame>['color'] = 'default';
@prop export let placement: ModalPlacementType = 'center';
@prop export let autoclose: boolean = false;
@prop export let outsideclose: boolean = false;
@prop export let dismissable: boolean = true;
@prop export let backdropClass: string = 'fixed inset-0 z-40 bg-gray-900 bg-opacity-50 dark:bg-opacity-80';
@prop export let classBackdrop: string | undefined = undefined;
@prop export let dialogClass: string = 'fixed top-0 start-0 end-0 h-modal md:inset-0 md:h-full z-50 w-full p-4 flex';
@prop export let classDialog: string | undefined = undefined;
@prop export let defaultClass: string = 'relative flex flex-col mx-auto';
@prop export let headerClass: string = 'flex justify-between items-center p-4 md:p-5 rounded-t-lg';
@prop export let classHeader: string | undefined = undefined;
@prop export let bodyClass: string = 'p-4 md:p-5 space-y-4 flex-1 overflow-y-auto overscroll-contain';
@prop export let classBody: string | undefined = undefined;
@prop export let footerClass: string = 'flex items-center p-4 md:p-5 space-x-3 rtl:space-x-reverse rounded-b-lg';
@prop export let classFooter: string | undefined = undefined;
-->

77
frontend/src/modal/Modal.svelte.d.ts vendored Normal file
View File

@ -0,0 +1,77 @@
import { SvelteComponentTyped } from "svelte";
import type { Dismissable, SizeType } from '../types';
import type { ModalPlacementType } from '../types';
declare const __propDef: {
props: import("svelte/elements").HTMLAnchorAttributes & {
tag?: string;
color?: import("../utils/Frame.svelte").FrameColor;
rounded?: boolean;
border?: boolean;
shadow?: boolean;
node?: HTMLElement | undefined;
use?: import("svelte/action").Action<HTMLElement, any>;
options?: object;
class?: string;
role?: string;
open?: boolean;
transition?: (node: HTMLElement, params: any) => import("svelte/transition").TransitionConfig;
params?: any;
} & Dismissable & {
open?: boolean;
title?: string;
size?: SizeType;
placement?: ModalPlacementType;
autoclose?: boolean;
outsideclose?: boolean;
backdropClass?: string;
classBackdrop?: string;
dialogClass?: string;
classDialog?: string;
defaultClass?: string;
headerClass?: string;
classHeader?: string;
bodyClass?: string;
classBody?: string;
footerClass?: string;
classFooter?: string;
};
events: {
wheel: WheelEvent;
} & {
[evt: string]: CustomEvent<any>;
};
slots: {
header: {};
default: {};
footer: {};
};
};
export type ModalProps = typeof __propDef.props;
export type ModalEvents = typeof __propDef.events;
export type ModalSlots = typeof __propDef.slots;
/**
* [Go to docs](https://flowbite-svelte.com/)
* ## Props
* @prop export let open: boolean = false;
* @prop export let title: string = '';
* @prop export let size: SizeType = 'md';
* @prop export let color: ComponentProps<Frame>['color'] = 'default';
* @prop export let placement: ModalPlacementType = 'center';
* @prop export let autoclose: boolean = false;
* @prop export let outsideclose: boolean = false;
* @prop export let dismissable: boolean = true;
* @prop export let backdropClass: string = 'fixed inset-0 z-40 bg-gray-900 bg-opacity-50 dark:bg-opacity-80';
* @prop export let classBackdrop: string | undefined = undefined;
* @prop export let dialogClass: string = 'fixed top-0 start-0 end-0 h-modal md:inset-0 md:h-full z-50 w-full p-4 flex';
* @prop export let classDialog: string | undefined = undefined;
* @prop export let defaultClass: string = 'relative flex flex-col mx-auto';
* @prop export let headerClass: string = 'flex justify-between items-center p-4 md:p-5 rounded-t-lg';
* @prop export let classHeader: string | undefined = undefined;
* @prop export let bodyClass: string = 'p-4 md:p-5 space-y-4 flex-1 overflow-y-auto overscroll-contain';
* @prop export let classBody: string | undefined = undefined;
* @prop export let footerClass: string = 'flex items-center p-4 md:p-5 space-x-3 rtl:space-x-reverse rounded-b-lg';
* @prop export let classFooter: string | undefined = undefined;
*/
export default class Modal extends SvelteComponentTyped<ModalProps, ModalEvents, ModalSlots> {
}
export {};

View File

@ -19,41 +19,43 @@ export type SimklUser = {
}
export type SimklWatchList = {
anime: [{
last_watched_at: string,
status: string
user_rating: number,
last_watched: string,
next_to_watch: string,
watched_episodes_count: number,
total_episodes_count: number,
not_aired_episodes_count: number,
show: {
title: string,
poster: string,
ids: {
simkl: number,
slug: string,
offjp: string,
tw: string,
ann: string,
mal: string,
wikien: string,
wikijp: string,
allcin: string,
imdb: string,
offen: string,
crunchyroll: string,
tvdbslug: string,
anilist: string,
animeplanet: string,
anisearch: string,
kitsu: string,
livechart: string,
traktslug: string,
anidb: string,
}
},
anime_type: string
}]
anime: [SimklAnime]
}
export type SimklAnime = {
last_watched_at: string,
status: string
user_rating: number,
last_watched: string,
next_to_watch: string,
watched_episodes_count: number,
total_episodes_count: number,
not_aired_episodes_count: number,
show: {
title: string,
poster: string,
ids: {
simkl: number,
slug: string,
offjp: string,
tw: string,
ann: string,
mal: string,
wikien: string,
wikijp: string,
allcin: string,
imdb: string,
offen: string,
crunchyroll: string,
tvdbslug: string,
anilist: string,
animeplanet: string,
anisearch: string,
kitsu: string,
livechart: string,
traktslug: string,
anidb: string,
}
},
anime_type: string
}

View File

@ -6,7 +6,7 @@ export function AniListLogin():Promise<void>;
export function AniListSearch(arg1:string):Promise<any>;
export function AniListUpdateEntry(arg1:number,arg2:string,arg3:string,arg4:number,arg5:number,arg6:string,arg7:number,arg8:number,arg9:number,arg10:number,arg11:number,arg12:number):Promise<any>;
export function AniListUpdateEntry(arg1:number,arg2:number,arg3:string,arg4:number,arg5:number,arg6:string,arg7:number,arg8:number,arg9:number,arg10:number,arg11:number,arg12:number):Promise<any>;
export function CheckIfAniListLoggedIn():Promise<boolean>;

View File

@ -95,7 +95,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\"" }
// 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\"" }
media: any;
status: string;
// Go type: struct { Year int "json:\"year\""; Month int "json:\"month\""; Day int "json:\"day\"" }