mirror of
https://github.com/NoCrypt/migu.git
synced 2026-08-19 05:35:46 +00:00
fix: preview card trailers
feat: preview card trailer volume toggle fix: dont resolve trusted media fix: episode list air dates and numbers
This commit is contained in:
parent
665d4a3748
commit
36e2672a13
9 changed files with 59 additions and 23 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Miru",
|
||||
"version": "4.2.7",
|
||||
"version": "4.2.8",
|
||||
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
||||
"description": "Stream anime torrents, real-time with no waiting for downloads.",
|
||||
"main": "build/main.js",
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@
|
|||
position: absolute;
|
||||
left: 0 ; bottom: 0;
|
||||
width: 100%; height: 100%;
|
||||
background: linear-gradient(180deg, #0000 0%, #0000 76%, #25292fdd 97%, #25292f);
|
||||
background: linear-gradient(180deg, #0000 0%, #25292f00 80%, #25292f 95%, #25292f 100%);
|
||||
}
|
||||
.list-status-circle {
|
||||
background: var(--statusColor);
|
||||
|
|
|
|||
|
|
@ -45,9 +45,13 @@
|
|||
if (media.status === 'NOT_YET_RELEASED') return
|
||||
playMedia(media)
|
||||
}
|
||||
// TODO: add a volume toggle icon for trailer
|
||||
|
||||
function volume (video) {
|
||||
video.volume = 0.05
|
||||
video.volume = 0.1
|
||||
}
|
||||
let muted = true
|
||||
function toggleMute () {
|
||||
muted = !muted
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -55,16 +59,17 @@
|
|||
<div class='banner position-relative overflow-hidden bg-black'>
|
||||
<img src={media.bannerImage || ' '} alt='banner' class='img-cover w-full h-full' />
|
||||
{#if media.trailer?.id}
|
||||
<div class='material-symbols-outlined filled position-absolute z-10 top-0 right-0 p-15 font-size-22' class:d-none={hide} use:click={toggleMute}>{muted ? 'volume_off' : 'volume_up'}</div>
|
||||
<!-- for now we use some invidious instance, would be nice to somehow get these links outselves, this redirects straight to some google endpoint -->
|
||||
<!-- `https://yewtu.be/latest_version?id=${media.trailer.id}&itag=18` -->
|
||||
<!-- eslint-disable-next-line svelte/valid-compile -->
|
||||
<video src={`https://proxy2.vnxservers.com/youtube/${media.trailer.id}`}
|
||||
<video src={`https://yewtu.be/latest_version?id=${media.trailer.id}&itag=18`}
|
||||
class='w-full position-absolute left-0'
|
||||
class:d-none={hide}
|
||||
playsinline
|
||||
preload='none'
|
||||
loop
|
||||
muted
|
||||
use:volume
|
||||
bind:muted
|
||||
on:loadeddata={() => { hide = false }}
|
||||
autoplay />
|
||||
<!-- <iframe
|
||||
|
|
@ -150,7 +155,7 @@
|
|||
position: absolute;
|
||||
left: 0 ; bottom: 0;
|
||||
width: 100%; height: 100% ;
|
||||
background: linear-gradient(180deg, #0000 0%, #25292faa 76%, #25292f 97%, #25292f 100%);
|
||||
background: linear-gradient(180deg, #0000 0%, #25292f00 80%, #25292fe3 95%, #25292f 100%);
|
||||
}
|
||||
@keyframes load-in {
|
||||
from {
|
||||
|
|
|
|||
|
|
@ -413,6 +413,17 @@ query($page: Int, $perPage: Int, $from: Int, $to: Int){
|
|||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
break
|
||||
} case 'Episodes': {
|
||||
query = /* js */`
|
||||
query($id: Int){
|
||||
Page(page: 1, perPage: 1000){
|
||||
airingSchedules(mediaId: $id){
|
||||
airingAt,
|
||||
episode
|
||||
}
|
||||
}
|
||||
}`
|
||||
break
|
||||
} case 'Search': {
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ window.addEventListener('paste', ({ clipboardData }) => { // WAIT image lookup o
|
|||
if (!type.startsWith('text')) return
|
||||
item.getAsString(text => {
|
||||
if (torrentRx.exec(text)) {
|
||||
add(text)
|
||||
media.set(null)
|
||||
add(text)
|
||||
} else {
|
||||
let src = null
|
||||
if (type === 'text/html') {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ async function getAniDBEpisodeFromAL ({ media, episode }, { episodes, episodeCou
|
|||
const res = await alRequest({ method: 'EpisodeDate', id: media.id, ep: episode })
|
||||
const alDate = new Date((res.data.AiringSchedule?.airingAt || 0) * 1000)
|
||||
|
||||
return getEpisodeNumberByAirDate(alDate, episodes, episode)
|
||||
}
|
||||
|
||||
export function getEpisodeNumberByAirDate (alDate, episodes, episode) {
|
||||
if (!+alDate) return episodes[Number(episode)] || episodes[1] // what the fuck, are you braindead anilist?, the source episode number to play is from an array created from AL ep count, so how come it's missing?
|
||||
|
||||
// find closest episodes by air date, multiple episodes can have the same air date distance
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@
|
|||
otherFiles.push(file)
|
||||
}
|
||||
}
|
||||
let nowPlaying = get(media)
|
||||
|
||||
const resolved = await resolveFileMedia(videoFiles.map(file => file.name))
|
||||
|
||||
videoFiles.map(file => {
|
||||
|
|
@ -91,9 +93,13 @@
|
|||
|
||||
videoFiles = videoFiles.filter(file => !TYPE_EXCLUSIONS.includes(file.media.parseObject.anime_type))
|
||||
|
||||
console.info('MediaHandler: resolved video files', { videoFiles })
|
||||
if (nowPlaying?.verified && videoFiles.length === 1) {
|
||||
console.info('Media was verified, skipping verification')
|
||||
videoFiles[0].media.media = nowPlaying.media
|
||||
if (nowPlaying.episode) videoFiles[0].media.episode = nowPlaying.episode
|
||||
}
|
||||
|
||||
let nowPlaying = get(media)
|
||||
console.info('MediaHandler: resolved video files', { videoFiles })
|
||||
|
||||
if (!nowPlaying) {
|
||||
const max = highestOccurence(videoFiles, file => file.media.media?.id).media
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
entries.sort((a, b) => b.seeders - a.seeders)
|
||||
if (settings.rssAutoplay) {
|
||||
const best = entries.find(entry => entry.best)
|
||||
if (best?.seeders > 20) { // only play best if it actually has a lot of seeders, 20 might be too little for those overkill blurays
|
||||
if (best?.seeders >= 15) { // only play best if it actually has a lot of seeders, 20 might be too little for those overkill blurays
|
||||
play(best)
|
||||
} else {
|
||||
play(entries[0])
|
||||
|
|
@ -110,7 +110,8 @@
|
|||
}
|
||||
function play (entry) {
|
||||
$media = $rss
|
||||
if (entry.seeders !== '?' && entry.seeders <= 15) {
|
||||
$media.verified = entry.verified
|
||||
if (entry.seeders !== '?' && entry.seeders < 15) {
|
||||
toast('Availability Warning', {
|
||||
description: 'This release is poorly seeded and likely will have playback issues such as buffering!'
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<script>
|
||||
import { since } from '@/modules/util'
|
||||
import { click } from '@/modules/click.js'
|
||||
import { getEpisodeNumberByAirDate } from '@/modules/providers/tosho.js'
|
||||
import { alRequest } from '@/modules/anilist'
|
||||
import { media } from '../Player/MediaHandler.svelte'
|
||||
|
||||
export let id
|
||||
|
||||
|
|
@ -14,15 +17,18 @@
|
|||
|
||||
const episodeList = Array.from({ length: episodeCount }, (_, i) => ({ episode: i + 1 }))
|
||||
async function load () {
|
||||
const episodesPromise = alRequest({ method: 'Episodes', id })
|
||||
const res = await fetch('https://api.ani.zip/mappings?anilist_id=' + id)
|
||||
const { episodes } = await res.json()
|
||||
for (const { episode, image, summary, rating, title, length, airdate } of Object.values(episodes)) {
|
||||
const episodeNumber = Number(episode)
|
||||
if (!episodeNumber) continue
|
||||
const { episodes, specialCount, episodeCount } = await res.json()
|
||||
const settled = (await episodesPromise).data.Page?.airingSchedules
|
||||
const alEpisodes = settled?.length ? settled : episodeList
|
||||
for (const { episode, airingAt } of alEpisodes) {
|
||||
const airdate = new Date((airingAt || 0) * 1000)
|
||||
|
||||
// TODO: AL airing times
|
||||
const needsValidation = !(!specialCount || (media.episodes && media.episodes === episodeCount && episodes[Number(episode)]))
|
||||
const { image, summary, rating, title, length } = needsValidation ? getEpisodeNumberByAirDate(airdate, episodes, episode) : (episodes[Number(episode)] || {})
|
||||
|
||||
episodeList[episodeNumber - 1] = { episode: episodeNumber, image, summary, rating, title, length: length || duration, airdate }
|
||||
episodeList[episode - 1] = { episode, image, summary, rating, title, length: length || duration, airdate }
|
||||
}
|
||||
}
|
||||
load()
|
||||
|
|
@ -31,11 +37,11 @@
|
|||
{#each episodeList as { episode, image, summary, rating, title, length, airdate }}
|
||||
{@const completed = userProgress >= episode}
|
||||
{@const target = userProgress + 1 === episode}
|
||||
<div class='w-full my-20 content-visibility-auto scale' class:px-20={!target} class:h-150={image || summary} use:click={() => play(episode)}>
|
||||
<div class='rounded w-full h-full overflow-hidden d-flex flex-row pointer' class:bg-dark-light={completed} class:bg-dark={!completed}>
|
||||
<div class='w-full my-20 content-visibility-auto scale' class:opacity-half={completed} class:px-20={!target} class:h-150={image || summary} use:click={() => play(episode)}>
|
||||
<div class='rounded w-full h-full overflow-hidden d-flex flex-row pointer' class:border={target} class:bg-black={completed} class:bg-dark={!completed}>
|
||||
{#if image}
|
||||
<div class='w-450 h-full'>
|
||||
<img alt='thumbnail' src={image} class='img-cover h-full w-full' class:opacity-half={completed} />
|
||||
<img alt='thumbnail' src={image} class='img-cover h-full w-full' />
|
||||
</div>
|
||||
{/if}
|
||||
<div class='h-full w-full px-20 py-15 d-flex flex-column'>
|
||||
|
|
@ -69,7 +75,7 @@
|
|||
|
||||
<style>
|
||||
.opacity-half {
|
||||
opacity: 50%;
|
||||
opacity: 30%;
|
||||
}
|
||||
.title {
|
||||
display: -webkit-box !important;
|
||||
|
|
@ -82,4 +88,7 @@
|
|||
.scale:hover{
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.border {
|
||||
--dm-border-color: white
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue