mirror of
https://github.com/danbulant/Mangades
synced 2026-05-24 12:22:10 +00:00
improvements in tracking and anilist integration
This commit is contained in:
parent
e3bff9f33b
commit
bc16f2b279
9 changed files with 93 additions and 90 deletions
|
|
@ -29,14 +29,10 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/apm-rum": "^5.12.0",
|
"@elastic/apm-rum": "^5.12.0",
|
||||||
"@sentry/browser": "^7.25.0",
|
|
||||||
"@sentry/svelte": "^7.25.0",
|
|
||||||
"@sentry/tracing": "^7.25.0",
|
|
||||||
"fflate": "^0.8.0",
|
"fflate": "^0.8.0",
|
||||||
"streamsaver": "^2.0.6",
|
"streamsaver": "^2.0.6",
|
||||||
"svelte-local-storage-store": "^0.3.1",
|
"svelte-local-storage-store": "^0.3.1",
|
||||||
"svelte-markdown": "^0.2.3",
|
"svelte-markdown": "^0.2.3",
|
||||||
"swiper": "^8.3.2",
|
"swiper": "^8.3.2"
|
||||||
"toucan-js": "^3.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,6 @@
|
||||||
import { Toucan } from 'toucan-js';
|
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').HandleClientError} */
|
/** @type {import('@sveltejs/kit').HandleClientError} */
|
||||||
export function handleError({ error, event }) {
|
export function handleError({ error, event }) {
|
||||||
// @ts-ignore
|
|
||||||
if(import.meta.env.VITE_SENTRY_DSN !== undefined) {
|
|
||||||
const sentry = new Toucan({
|
|
||||||
// @ts-ignore
|
|
||||||
dsn: import.meta.env.VITE_SENTRY_DSN,
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
environment: import.meta.env.VITE_SENTRY_ENVIRONMENT,
|
|
||||||
// @ts-ignore
|
|
||||||
release: import.meta.env.VITE_SENTRY_RELEASE,
|
|
||||||
request: event.request,
|
|
||||||
requestDataOptions: {
|
|
||||||
allowedHeaders: [
|
|
||||||
'user-agent',
|
|
||||||
'cf-challenge',
|
|
||||||
'accept-encoding',
|
|
||||||
'accept-language',
|
|
||||||
'cf-ray',
|
|
||||||
'content-length',
|
|
||||||
'content-type',
|
|
||||||
'x-real-ip',
|
|
||||||
'host',
|
|
||||||
],
|
|
||||||
allowedSearchParams: /(.*)/
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sentry.captureException(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...error,
|
...error,
|
||||||
code: error?.code ?? 'UNKNOWN'
|
code: error?.code ?? 'UNKNOWN'
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
export var selected;
|
export var selected;
|
||||||
export var disabledDownload = false;
|
export var disabledDownload = false;
|
||||||
export var progress = 0;
|
export var progress = 0;
|
||||||
|
export var read;
|
||||||
var scanlationGroup = chapter.relationships.find(t => t.type === "scanlation_group")?.attributes.name;
|
var scanlationGroup = chapter.relationships.find(t => t.type === "scanlation_group")?.attributes.name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,7 +26,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<tr class="chapter item" on:mouseenter={mouseenter} on:click={click} class:selected={selected} style="background-image: linear-gradient(to right, rgba(0, 255, 0, 0.247) {progress * 100}%, transparent {progress * 100}%)">
|
<tr class="chapter item" class:read on:mouseenter={mouseenter} on:click={click} class:selected={selected} style="background-image: linear-gradient(to right, rgba(0, 255, 0, 0.247) {progress * 100}%, transparent {progress * 100}%)">
|
||||||
<td class="no-wrap">{chapter.attributes.volume ? "Vol " + chapter.attributes.volume : ""}</td>
|
<td class="no-wrap">{chapter.attributes.volume ? "Vol " + chapter.attributes.volume : ""}</td>
|
||||||
<td class="no-wrap">{chapter.attributes.chapter ? "Chapter " + chapter.attributes.chapter : ""}</td>
|
<td class="no-wrap">{chapter.attributes.chapter ? "Chapter " + chapter.attributes.chapter : ""}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -43,6 +44,9 @@
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
.read {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
.scanlation {
|
.scanlation {
|
||||||
color: grey;
|
color: grey;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import * as Sentry from "@sentry/browser";
|
import { apm } from "./tracing";
|
||||||
// import { apm } from "./tracing";
|
|
||||||
|
|
||||||
var isLogedInCache: boolean | null = null;
|
var isLogedInCache: boolean | null = null;
|
||||||
var isLogedInCacheTime: number | null = null;
|
var isLogedInCacheTime: number | null = null;
|
||||||
|
|
@ -22,8 +21,7 @@ export function isLogedIn() {
|
||||||
export function getUserID() {
|
export function getUserID() {
|
||||||
const token = localStorage.getItem("token")!;
|
const token = localStorage.getItem("token")!;
|
||||||
let data = JSON.parse(atob(token.substring(token.indexOf(".") + 1, token.lastIndexOf("."))));
|
let data = JSON.parse(atob(token.substring(token.indexOf(".") + 1, token.lastIndexOf("."))));
|
||||||
Sentry.setUser({ id: data.sub });
|
apm.setUserContext({ id: data.sub });
|
||||||
// apm.setUserContext({ id: data.sub });
|
|
||||||
return data.sub;
|
return data.sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
// import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
// import { ApmBase, init as initApm } from '@elastic/apm-rum'
|
import { ApmBase, init as initApm } from '@elastic/apm-rum'
|
||||||
|
|
||||||
// var apm_: ApmBase;
|
var apm_: ApmBase;
|
||||||
|
|
||||||
// if(browser) {
|
if(browser) {
|
||||||
// apm_ = initApm({
|
apm_ = initApm({
|
||||||
// // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)
|
// Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)
|
||||||
// serviceName: 'mangades',
|
serviceName: 'mangades',
|
||||||
|
|
||||||
// // Set custom APM Server URL (default: http://localhost:8200)
|
// Set custom APM Server URL (default: http://localhost:8200)
|
||||||
// serverUrl: 'https://apm.elasticsearch.danbulant.cloud',
|
serverUrl: 'https://apm.elasticsearch.danbulant.cloud',
|
||||||
|
|
||||||
// // Set the service version (required for source map feature)
|
// Set the service version (required for source map feature)
|
||||||
// serviceVersion: import.meta.env.VITE_SENTRY_RELEASE,
|
// serviceVersion: import.meta.env.VITE_SENTRY_RELEASE,
|
||||||
|
|
||||||
// // Set the service environment
|
|
||||||
// environment: import.meta.env.VITE_SENTRY_ENVIRONMENT || 'production'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export const apm = apm_;
|
// Set the service environment
|
||||||
|
environment: import.meta.env.VITE_SENTRY_ENVIRONMENT || 'production'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apm = apm_;
|
||||||
|
|
@ -2,34 +2,14 @@
|
||||||
import { afterNavigate } from "$app/navigation";
|
import { afterNavigate } from "$app/navigation";
|
||||||
import { logs } from "$lib/util/logs";
|
import { logs } from "$lib/util/logs";
|
||||||
import PageTransition from "./pageTransition.svelte";
|
import PageTransition from "./pageTransition.svelte";
|
||||||
import * as Sentry from '@sentry/svelte';
|
|
||||||
import { BrowserTracing } from "@sentry/tracing";
|
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
// import { apm } from "$lib/util/tracing";
|
import { apm } from "$lib/util/tracing";
|
||||||
// import { page } from "$app/stores";
|
import { page } from "$app/stores";
|
||||||
|
|
||||||
export var data;
|
export var data;
|
||||||
// @ts-ignore
|
if(browser) {
|
||||||
if(import.meta.env.VITE_SENTRY_DSN && browser) {
|
apm.setInitialPageLoadName($page.route.id);
|
||||||
Sentry.init({
|
|
||||||
// @ts-ignore
|
|
||||||
dsn: import.meta.env.VITE_SENTRY_DSN,
|
|
||||||
// @ts-ignore
|
|
||||||
environment: import.meta.env.VITE_SENTRY_ENVIRONMENT,
|
|
||||||
// @ts-ignore
|
|
||||||
release: import.meta.env.VITE_SENTRY_RELEASE,
|
|
||||||
integrations: [
|
|
||||||
new BrowserTracing({
|
|
||||||
tracePropagationTargets: ["localhost", "manga.danbulant.eu", "tachiyomi.manga-d7tp.pages.dev", "manga-d7tp.pages.dev", /^\/.*/]
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
tracesSampleRate: 1,
|
|
||||||
autoSessionTracking: false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// if(browser) {
|
|
||||||
// apm.setInitialPageLoadName($page.route.id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
let skipFirst = true;
|
let skipFirst = true;
|
||||||
let last = typeof window !== "undefined" && window.location.pathname;
|
let last = typeof window !== "undefined" && window.location.pathname;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
import Favicon from "./favicon.svelte";
|
import Favicon from "./favicon.svelte";
|
||||||
import RelatedManga from "./relatedManga.svelte";
|
import RelatedManga from "./relatedManga.svelte";
|
||||||
import { anilistInfo } from "./anilistInfo";
|
import { anilistInfo } from "./anilistInfo";
|
||||||
|
import { isLogedIn } from "$lib/util/anilist";
|
||||||
|
|
||||||
export var data;
|
export var data;
|
||||||
|
|
||||||
|
|
@ -275,6 +276,7 @@
|
||||||
var scrollY, innerHeight;
|
var scrollY, innerHeight;
|
||||||
|
|
||||||
let additionalImages = [];
|
let additionalImages = [];
|
||||||
|
let alReadProgress
|
||||||
|
|
||||||
$: if(anilistData) anilistData.then(data => {
|
$: if(anilistData) anilistData.then(data => {
|
||||||
if(data && data.bannerImage && !additionalImages.find(t => t.src === data.bannerImage)) {
|
if(data && data.bannerImage && !additionalImages.find(t => t.src === data.bannerImage)) {
|
||||||
|
|
@ -293,6 +295,7 @@
|
||||||
width: 3
|
width: 3
|
||||||
});
|
});
|
||||||
additionalImages = additionalImages;
|
additionalImages = additionalImages;
|
||||||
|
alReadProgress = data.mediaListEntry?.progress;
|
||||||
tabs = [...defaultTabs, "Characters"];
|
tabs = [...defaultTabs, "Characters"];
|
||||||
}
|
}
|
||||||
}); else {
|
}); else {
|
||||||
|
|
@ -318,13 +321,18 @@
|
||||||
var selectedCharacter = null;
|
var selectedCharacter = null;
|
||||||
|
|
||||||
$: if(!selectedImage) selectedCharacter = null;
|
$: if(!selectedImage) selectedCharacter = null;
|
||||||
|
|
||||||
|
let expanded = false;
|
||||||
|
|
||||||
|
let uniqueChapterCount;
|
||||||
|
$: uniqueChapterCount = chapters?.data.filter((t, i, a) => a.findIndex(t2 => Math.floor(t2.attributes.chapter) === Math.floor(t.attributes.chapter)) === i).length;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:beforeunload={beforeUnload} bind:innerWidth={width} bind:scrollY bind:innerHeight />
|
<svelte:window on:beforeunload={beforeUnload} bind:innerWidth={width} bind:scrollY bind:innerHeight />
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>{title} - Chapter list</title>
|
<title>{title} - Chapter list</title>
|
||||||
<meta name="description" value="Read {title} online, or download it as EPUB or CBZ file. Free of charge as well as free of ads." />
|
<meta name="description" content="Read {title} online, or download it as EPUB or CBZ file. Free of charge as well as free of ads." />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<Navbar transparent={scrollY < 0.2*innerHeight} {title} />
|
<Navbar transparent={scrollY < 0.2*innerHeight} {title} />
|
||||||
|
|
@ -402,12 +410,12 @@
|
||||||
|
|
||||||
{#if smallScreenMode && manga.description.en}
|
{#if smallScreenMode && manga.description.en}
|
||||||
<div class="fulldescription">
|
<div class="fulldescription">
|
||||||
<ExpandableDescription source={manga.description.en} />
|
<ExpandableDescription source={manga.description.en} bind:expanded />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if manga.tags}
|
{#if manga.tags}
|
||||||
<div class="tags">
|
<div class="tags" class:expanded>
|
||||||
{#each manga.tags as tag}
|
{#each manga.tags as tag}
|
||||||
<span class="tag">{tag.attributes.name.en || tag.attributes.name.jp || Object.values(tag.attributes.name)[0]}</span>
|
<span class="tag">{tag.attributes.name.en || tag.attributes.name.jp || Object.values(tag.attributes.name)[0]}</span>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
@ -416,7 +424,23 @@
|
||||||
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="linklist">
|
<div class="linklist">
|
||||||
<a href="https://mangadex.org/title/{mangaId}">Mangadex.org</a>
|
{#if anilistData && isLogedIn()} {#await anilistData then data}
|
||||||
|
<a href="{data.siteUrl}" target="_blank" rel="noreferrer">
|
||||||
|
AL:
|
||||||
|
{#if data?.mediaListEntry?.status}{({
|
||||||
|
CURRENT: "Reading",
|
||||||
|
PLANNING: "Plan to read",
|
||||||
|
COMPLETED: "Completed",
|
||||||
|
DROPPED: "Dropped",
|
||||||
|
PAUSED: "Paused",
|
||||||
|
REPEATING: "Repeating"
|
||||||
|
}[data.mediaListEntry.status])}
|
||||||
|
CH {data.mediaListEntry.progress}/{data.chapters || "-"} ({uniqueChapterCount})
|
||||||
|
{:else}
|
||||||
|
Not tracking
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/await} {/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="copyright-header" class:copyright-header-active={copyrightOpen} on:click={() => copyrightOpen = !copyrightOpen}>Copyright infringement? (click)</div>
|
<div class="copyright-header" class:copyright-header-active={copyrightOpen} on:click={() => copyrightOpen = !copyrightOpen}>Copyright infringement? (click)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -489,7 +513,7 @@
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each chapters.data as chapter}
|
{#each chapters.data as chapter}
|
||||||
<Chapter progress={(progressMap.get(chapter.id) || 0) / chapter.attributes.pages} {chapter} disabledDownload={!!progress} selected={selected.includes(chapter)} on:select={() => select(chapter)} on:download={() => downloadSingle(chapter)} />
|
<Chapter read={alReadProgress && alReadProgress >= parseInt(chapter.attributes.chapter)} progress={(progressMap.get(chapter.id) || 0) / chapter.attributes.pages} {chapter} disabledDownload={!!progress} selected={selected.includes(chapter)} on:select={() => select(chapter)} on:download={() => downloadSingle(chapter)} />
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
@ -497,13 +521,13 @@
|
||||||
</div>
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
<SwiperSlide>
|
<SwiperSlide>
|
||||||
<div class="art-list" style="min-height: 30rem;">
|
<div class="art-list" style="min-height: 30rem; overflow: hidden;">
|
||||||
<ArtList {mangaId} bind:selectedImage additionalList={additionalImages} />
|
<ArtList {mangaId} bind:selectedImage additionalList={additionalImages} />
|
||||||
</div>
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
<SwiperSlide>
|
<SwiperSlide>
|
||||||
<div class="more-info" style="min-height: 30rem;">
|
<div class="more-info" style="min-height: 30rem;">
|
||||||
<div class="flex-wrapped">
|
<div class="flex-wrapped" style="margin-bottom: 0.5rem;">
|
||||||
{#if anilistData} {#await anilistData then data} {#if data}
|
{#if anilistData} {#await anilistData then data} {#if data}
|
||||||
<div>
|
<div>
|
||||||
<b>Genres</b>: {data.genres.join(", ")}
|
<b>Genres</b>: {data.genres.join(", ")}
|
||||||
|
|
@ -646,6 +670,9 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
.tags.expanded {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
.tag {
|
.tag {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
export var source: string;
|
export var source: string;
|
||||||
|
|
||||||
export var expanded = false;
|
export var expanded: boolean = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="description" class:expanded>
|
<div class="description" class:expanded>
|
||||||
|
|
|
||||||
|
|
@ -78,4 +78,33 @@ button:focus, .button:focus, button:hover, .button:hover {
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(255,255,255,0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(255,255,255,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:active {
|
||||||
|
background: rgba(255,255,255,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-corner {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue