improvements in tracking and anilist integration

This commit is contained in:
Daniel Bulant 2023-10-07 14:21:18 +02:00
parent e3bff9f33b
commit bc16f2b279
9 changed files with 93 additions and 90 deletions

View file

@ -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"
} }
} }

View file

@ -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'

View file

@ -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;

View file

@ -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;
} }

View file

@ -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 // Set the service environment
// environment: import.meta.env.VITE_SENTRY_ENVIRONMENT || 'production' environment: import.meta.env.VITE_SENTRY_ENVIRONMENT || 'production'
// }); });
// } }
// export const apm = apm_; export const apm = apm_;

View file

@ -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;

View file

@ -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;

View file

@ -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>

View file

@ -79,3 +79,32 @@ 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;
}