2024-04-16 20:20:30 +02:00
|
|
|
<template>
|
2024-05-01 01:45:45 +02:00
|
|
|
<div class="relative h-screen overflow-hidden">
|
|
|
|
<MainHeader />
|
2024-05-04 01:12:58 +02:00
|
|
|
<Updater />
|
2024-05-01 01:45:45 +02:00
|
|
|
<div class="flex flex-col text-white gap-5 mt-14 p-5 overflow-y-scroll h-[calc(100vh-3.5rem)]">
|
|
|
|
<div v-for="p in playlist" class="relative flex flex-row gap-4 min-h-36 bg-[#63636383] rounded-xl font-dm overflow-hidden">
|
|
|
|
<div
|
|
|
|
class="absolute top-0 left-0 w-full h-full bg-[#a1a1a141] transition-all duration-300"
|
|
|
|
:style="`width: calc((${p.partsdownloaded} / ${p.partsleft}) * 100%);`"
|
|
|
|
></div>
|
|
|
|
<div class="absolute h-full w-full flex flex-row gap-3 p-3.5">
|
|
|
|
<div v-if="p.service === 'CR'" class="flex w-48 min-w-48">
|
|
|
|
<img :src="(p.media as CrunchyEpisode).images.thumbnail[0].find((p) => p.height === 1080)?.source" alt="Image" class="object-cover rounded-lg" />
|
|
|
|
</div>
|
|
|
|
<div v-if="p.service === 'ADN'" class="flex min-w-52 w-52">
|
|
|
|
<img :src="(p.media as ADNEpisode).image2x" alt="Image" class="object-cover rounded-lg" />
|
|
|
|
</div>
|
|
|
|
<div class="flex flex-col w-full">
|
|
|
|
<div class="flex flex-row h-full">
|
|
|
|
<div class="flex flex-col">
|
2024-05-23 15:17:01 +02:00
|
|
|
<div class="flex flex-row">
|
|
|
|
<div v-if="p.status === 'failed'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#863232] rounded-lg">
|
|
|
|
<Icon name="bitcoin-icons:cross-filled" class="h-3.5 w-3.5 text-white" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div v-if="p.status === 'waiting'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
|
|
|
<Icon name="mdi:clock" class="h-3.5 w-3.5 text-white" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div v-if="p.status === 'preparing'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg">
|
|
|
|
<Icon name="mdi:clock" class="h-3.5 w-3.5 text-white" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
v-if="p.status === 'waiting for playlist'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
v-if="p.status === 'waiting for sub playlist'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
v-if="p.status === 'waiting for dub playlist'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div v-if="p.status === 'downloading'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#60501b] rounded-lg">
|
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
2024-05-24 00:19:30 +02:00
|
|
|
<div
|
|
|
|
v-if="p.status === 'downloading video'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#60501b] rounded-lg"
|
|
|
|
>
|
2024-05-23 15:17:01 +02:00
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
2024-05-23 23:04:58 +02:00
|
|
|
<div
|
|
|
|
v-if="p.status === 'merging video'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
v-if="p.status === 'decrypting video'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
2024-05-23 15:17:01 +02:00
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
2024-05-23 23:04:58 +02:00
|
|
|
<div
|
|
|
|
v-if="p.status === 'awaiting all dubs downloaded'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
2024-05-23 15:17:01 +02:00
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
2024-05-23 23:04:58 +02:00
|
|
|
<div
|
|
|
|
v-if="p.status === 'merging video & audio'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
2024-05-23 15:17:01 +02:00
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div v-if="p.status === 'completed'" class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#266326] rounded-lg">
|
|
|
|
<Icon name="material-symbols:check" class="h-3.5 w-3.5 text-white" />
|
|
|
|
{{ p.status }}
|
|
|
|
</div>
|
|
|
|
<div v-for="a in p.audiosdownloading">
|
2024-05-23 23:04:58 +02:00
|
|
|
<div
|
2024-05-24 00:19:30 +02:00
|
|
|
v-if="a.status && a.audio && a.status !== 'finished' && a.status !== 'failed'"
|
2024-05-23 23:04:58 +02:00
|
|
|
class="ml-2 flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#866332] rounded-lg"
|
|
|
|
>
|
|
|
|
<Icon name="mdi:loading" class="h-3.5 w-3.5 text-white animate-spin" />
|
|
|
|
{{ a.status }} Audio {{ a.audio }}
|
|
|
|
</div>
|
2024-05-24 00:19:30 +02:00
|
|
|
<div
|
|
|
|
v-if="a.status && a.audio && a.status === 'failed'"
|
|
|
|
class="flex flex-row items-center justify-center gap-1 text-xs capitalize p-1.5 bg-[#863232] rounded-lg"
|
|
|
|
>
|
|
|
|
<Icon name="bitcoin-icons:cross-filled" class="h-3.5 w-3.5 text-white" />
|
|
|
|
{{ a.status }} Audio {{ a.audio }}
|
|
|
|
</div>
|
2024-05-23 15:17:01 +02:00
|
|
|
</div>
|
2024-05-01 01:45:45 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="text-xs capitalize ml-auto">
|
|
|
|
{{ p.service === 'CR' ? 'Crunchyroll' : 'ADN' }}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div v-if="p.service === 'CR'" class="text-base capitalize h-full flex items-center">
|
|
|
|
{{ (p.media as CrunchyEpisode).series_title }} Season {{ (p.media as CrunchyEpisode).season_number }} Episode
|
|
|
|
{{ (p.media as CrunchyEpisode).episode_number }}
|
|
|
|
</div>
|
|
|
|
<div v-if="p.service === 'ADN'" class="text-base capitalize h-full">
|
|
|
|
{{ (p.media as ADNEpisode).show.title }} Season {{ (p.media as ADNEpisode).season ? (p.media as ADNEpisode).season : 1 }} Episode
|
|
|
|
{{ (p.media as ADNEpisode).shortNumber }}
|
|
|
|
</div>
|
2024-05-15 23:48:45 +02:00
|
|
|
<div class="relative flex flex-row gap-2 h-full items-end">
|
2024-05-01 01:45:45 +02:00
|
|
|
<div class="text-xs">{{ p.quality }}p</div>
|
|
|
|
<div class="text-xs uppercase">{{ p.format }}</div>
|
|
|
|
<div class="text-xs">Dubs: {{ p.dub.map((t) => t.name).join(', ') }}</div>
|
2024-05-23 15:17:01 +02:00
|
|
|
<div class="text-xs mr-20">Subs: {{ p.sub.length !== 0 ? p.sub.map((t) => t.name).join(', ') : '-' }}</div>
|
2024-05-15 23:48:45 +02:00
|
|
|
<div class="absolute flex flex-col ml-auto gap-0.5 right-0 bottom-0">
|
2024-05-20 02:44:14 +02:00
|
|
|
<div v-if="p.totaldownloaded && p.status === 'downloading'" class="text-xs ml-auto"
|
|
|
|
>{{ (p.totaldownloaded / Math.pow(1024, 2)).toFixed(2) }} MB</div
|
|
|
|
>
|
2024-05-01 01:45:45 +02:00
|
|
|
<div v-if="p.partsleft && p.status === 'downloading'" class="text-xs ml-auto">{{ p.partsdownloaded }}/{{ p.partsleft }}</div>
|
2024-05-15 23:48:45 +02:00
|
|
|
<div v-if="p.downloadspeed && p.status === 'downloading'" class="text-xs ml-auto">{{ p.downloadspeed }} MB/s</div>
|
2024-05-01 01:45:45 +02:00
|
|
|
</div>
|
2024-05-20 18:31:36 +02:00
|
|
|
<button @click="openFolder(p.installDir)" v-if="p.status === 'completed'" class="ml-auto h-9 w-9 hover:bg-[#ffffff2c] rounded-xl transition-all">
|
|
|
|
<Icon name="ph:folder-open" class="h-5 w-5 text-white" />
|
|
|
|
</button>
|
2024-05-01 01:45:45 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-04-26 15:40:08 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-04-16 20:20:30 +02:00
|
|
|
</div>
|
2024-04-23 00:27:24 +02:00
|
|
|
</div>
|
2024-04-16 20:20:30 +02:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2024-04-23 00:27:24 +02:00
|
|
|
import type { ADNEpisode } from '~/components/ADN/Types'
|
2024-04-16 20:20:30 +02:00
|
|
|
import type { CrunchyEpisode } from '~/components/Episode/Types'
|
2024-05-04 01:12:58 +02:00
|
|
|
import Updater from '~/components/Updater.vue'
|
2024-04-16 20:20:30 +02:00
|
|
|
|
|
|
|
const playlist = ref<
|
|
|
|
Array<{
|
2024-05-01 01:45:45 +02:00
|
|
|
id: number
|
|
|
|
status: string
|
|
|
|
media: CrunchyEpisode | ADNEpisode
|
|
|
|
dub: Array<{ locale: string; name: string }>
|
|
|
|
sub: Array<{ locale: string; name: string }>
|
|
|
|
dir: string
|
2024-05-20 18:31:36 +02:00
|
|
|
installDir: string
|
2024-05-01 01:45:45 +02:00
|
|
|
partsleft: number
|
|
|
|
partsdownloaded: number
|
|
|
|
downloadspeed: number
|
2024-05-15 23:48:45 +02:00
|
|
|
totaldownloaded: number
|
2024-05-01 01:45:45 +02:00
|
|
|
quality: number
|
|
|
|
service: string
|
|
|
|
format: string
|
2024-05-23 15:17:01 +02:00
|
|
|
audiosdownloading: {
|
2024-05-23 23:04:58 +02:00
|
|
|
status: string
|
|
|
|
audio: string
|
|
|
|
}[]
|
2024-04-16 20:20:30 +02:00
|
|
|
}>
|
2024-05-01 01:45:45 +02:00
|
|
|
>()
|
2024-04-16 20:20:30 +02:00
|
|
|
|
2024-05-01 01:45:45 +02:00
|
|
|
const getPlaylist = async () => {
|
|
|
|
const { data, error } = await useFetch<
|
|
|
|
Array<{
|
|
|
|
id: number
|
|
|
|
status: string
|
|
|
|
media: CrunchyEpisode | ADNEpisode
|
|
|
|
dub: Array<{ locale: string; name: string }>
|
|
|
|
sub: Array<{ locale: string; name: string }>
|
|
|
|
dir: string
|
2024-05-20 18:31:36 +02:00
|
|
|
installDir: string
|
2024-05-01 01:45:45 +02:00
|
|
|
partsleft: number
|
|
|
|
partsdownloaded: number
|
|
|
|
downloadspeed: number
|
2024-05-15 23:48:45 +02:00
|
|
|
totaldownloaded: number
|
2024-05-01 01:45:45 +02:00
|
|
|
quality: number
|
|
|
|
service: string
|
|
|
|
format: string
|
2024-05-23 15:17:01 +02:00
|
|
|
audiosdownloading: {
|
2024-05-23 23:04:58 +02:00
|
|
|
status: string
|
2024-05-23 15:17:01 +02:00
|
|
|
audio: string
|
|
|
|
}[]
|
2024-05-01 01:45:45 +02:00
|
|
|
}>
|
2024-05-08 03:18:15 +02:00
|
|
|
>('http://localhost:9941/api/service/playlist')
|
2024-05-01 01:45:45 +02:00
|
|
|
|
|
|
|
if (error.value) {
|
|
|
|
alert(error.value)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data.value) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
playlist.value = data.value
|
2024-04-16 20:20:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
onMounted(() => {
|
2024-05-01 01:45:45 +02:00
|
|
|
getPlaylist()
|
2024-04-16 20:20:30 +02:00
|
|
|
|
2024-05-01 01:45:45 +02:00
|
|
|
setInterval(getPlaylist, 1000)
|
2024-04-16 20:20:30 +02:00
|
|
|
})
|
2024-05-20 18:31:36 +02:00
|
|
|
|
|
|
|
const openFolder = (dir: string) => {
|
|
|
|
if (process.client) {
|
|
|
|
;(window as any).myAPI.openFolder(dir)
|
|
|
|
}
|
|
|
|
}
|
2024-04-16 20:20:30 +02:00
|
|
|
</script>
|
|
|
|
|
2024-04-26 15:40:08 +02:00
|
|
|
<style>
|
|
|
|
body {
|
2024-05-01 01:45:45 +02:00
|
|
|
background: none;
|
|
|
|
background-color: none;
|
|
|
|
background: transparent;
|
|
|
|
background-color: transparent;
|
2024-04-26 15:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.font-dm {
|
2024-05-01 01:45:45 +02:00
|
|
|
font-family: 'DM Sans', sans-serif;
|
2024-04-26 15:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.font-protest {
|
2024-05-01 01:45:45 +02:00
|
|
|
font-family: 'Protest Riot', sans-serif;
|
|
|
|
font-weight: 400;
|
|
|
|
font-style: normal;
|
2024-04-26 15:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.font-dm-big {
|
2024-05-01 01:45:45 +02:00
|
|
|
font-family: 'DM Sans', sans-serif;
|
|
|
|
font-weight: 1000;
|
|
|
|
font-style: normal;
|
2024-04-26 15:40:08 +02:00
|
|
|
}
|
|
|
|
|
2024-04-16 20:20:30 +02:00
|
|
|
.loading-a {
|
2024-05-01 01:45:45 +02:00
|
|
|
animation: animation infinite 3s;
|
2024-04-16 20:20:30 +02:00
|
|
|
}
|
|
|
|
|
2024-04-21 04:21:43 +02:00
|
|
|
::-webkit-scrollbar-track {
|
2024-05-01 01:45:45 +02:00
|
|
|
background: #383838;
|
2024-04-21 04:21:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle */
|
|
|
|
::-webkit-scrollbar-thumb {
|
2024-05-01 01:45:45 +02:00
|
|
|
background: #cac9c9;
|
2024-04-21 04:21:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle on hover */
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
2024-05-01 01:45:45 +02:00
|
|
|
background: #555;
|
2024-04-21 04:21:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
::-webkit-scrollbar {
|
2024-05-01 01:45:45 +02:00
|
|
|
width: 10px;
|
2024-04-21 04:21:43 +02:00
|
|
|
}
|
|
|
|
|
2024-04-16 20:20:30 +02:00
|
|
|
@keyframes animation {
|
2024-05-01 01:45:45 +02:00
|
|
|
0% {
|
|
|
|
left: 0%;
|
|
|
|
}
|
2024-04-16 20:20:30 +02:00
|
|
|
|
2024-05-01 01:45:45 +02:00
|
|
|
50% {
|
|
|
|
left: 88%;
|
|
|
|
}
|
2024-04-16 20:20:30 +02:00
|
|
|
|
2024-05-01 01:45:45 +02:00
|
|
|
100% {
|
|
|
|
left: 0%;
|
|
|
|
}
|
2024-04-16 20:20:30 +02:00
|
|
|
}
|
2024-04-30 03:20:47 +02:00
|
|
|
|
|
|
|
@keyframes fadein {
|
2024-05-01 01:45:45 +02:00
|
|
|
from {
|
|
|
|
opacity: 0;
|
|
|
|
}
|
|
|
|
to {
|
|
|
|
opacity: 1;
|
|
|
|
}
|
2024-04-30 03:20:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
body {
|
2024-05-01 01:45:45 +02:00
|
|
|
animation: fadein 0.5s;
|
2024-04-30 03:20:47 +02:00
|
|
|
}
|
2024-04-16 20:20:30 +02:00
|
|
|
</style>
|