mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-13 00:20:21 +00:00
optimise the fuck out of card creation!
This commit is contained in:
parent
56785317e2
commit
40db9bdd83
4 changed files with 115 additions and 94 deletions
|
|
@ -776,6 +776,53 @@
|
|||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<template id="skeletonCardTemplate">
|
||||
<div class="card m-0 p-0">
|
||||
<div class="row h-full">
|
||||
<div class="col-4 skeloader"></div>
|
||||
<div class="col-8 bg-very-dark px-15 py-10">
|
||||
<p class="skeloader w-300 h-25 rounded bg-dark"></p>
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark"></p>
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template id="bareCardTemplate">
|
||||
<div class="card m-0 p-0">
|
||||
<div class="row h-full">
|
||||
<div class="col-4 skeloader"></div>
|
||||
<div class="col-8 bg-very-dark px-15 py-10">
|
||||
<h5 class="m-0 text-capitalize font-weight-bold pb-10"></h5>
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark"></p>
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template id="fullCardTemplate">
|
||||
<div class="card m-0 p-0">
|
||||
<div class="row h-full">
|
||||
<div class="col-4">
|
||||
<img loading="lazy" src="" class="cover-img w-full h-full">
|
||||
</div>
|
||||
<div class="col-8 h-full card-grid">
|
||||
<div class="px-15 py-10 bg-very-dark">
|
||||
<h5 class="m-0 text-capitalize font-weight-bold"></h5>
|
||||
<span class='text-muted font-weight-bold'></span>
|
||||
<p class="text-muted m-0 text-capitalize details">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="overflow-y-auto px-15 pb-5 bg-very-dark card-desc"></div>
|
||||
<div class="px-15 pb-10 pt-5 genres"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script src="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.1.1/js/halfmoon.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/matroska-subtitles@latest/dist/matroska-subtitles.min.js"></script>
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/indexeddb-chunk-store@latest/idbchunkstore.min.js"></script> -->
|
||||
|
|
|
|||
|
|
@ -303,24 +303,20 @@ mutation ($id: Int, $status: MediaListStatus, $episode: Int, $repeat: Int) {
|
|||
}
|
||||
let alResponse
|
||||
async function searchAnime (a) { // search bar functionality
|
||||
const frag = document.createDocumentFragment()
|
||||
const cards = []
|
||||
const browse = document.querySelector('.browse')
|
||||
browse.innerHTML = ''
|
||||
browse.appendChild(skeletonCard)
|
||||
// browse.appendChild(skeletonCard) // TODO: fix
|
||||
a ? alResponse = await alRequest({ method: 'SearchName', name: a }) : alResponse = await alRequest({ method: 'Trending' })
|
||||
try {
|
||||
alResponse.data.Page.media.forEach(media => {
|
||||
const template = cardCreator({ media: media })
|
||||
template.onclick = () => {
|
||||
viewAnime(media)
|
||||
}
|
||||
frag.appendChild(template)
|
||||
cards.push(cardCreator({ media: media, onclick: () => viewAnime(media) }))
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
browse.innerHTML = ''
|
||||
browse.appendChild(frag)
|
||||
browse.append(...cards)
|
||||
}
|
||||
|
||||
// these really shouldnt be global
|
||||
|
|
@ -482,53 +478,6 @@ function countdown (s) {
|
|||
(d || h || m) && tmp.push(m + 'm')
|
||||
return tmp.join(' ')
|
||||
}
|
||||
function cardCreator (opts) {
|
||||
const template = document.createElement('div')
|
||||
template.classList.add('card', 'm-0', 'p-0')
|
||||
if (opts?.media) {
|
||||
template.innerHTML = `
|
||||
<div class="row h-full" style="--color:${opts.media.coverImage.color || '#1890ff'};">
|
||||
<div class="col-4">
|
||||
<img loading="lazy" src="${opts.media.coverImage.extraLarge || ''}"
|
||||
class="cover-img w-full h-full">
|
||||
</div>
|
||||
<div class="col-8 h-full card-grid">
|
||||
<div class="px-15 py-10 bg-very-dark">
|
||||
<h5 class="m-0 text-capitalize font-weight-bold">${opts.media.title.userPreferred}${opts.episodeNumber ? ' - ' + opts.episodeNumber : ''}</h5>
|
||||
${opts.schedule && opts.media.nextAiringEpisode ? "<span class='text-muted font-weight-bold'>EP " + opts.media.nextAiringEpisode.episode + ' in ' + countdown(opts.media.nextAiringEpisode.timeUntilAiring) + '</span>' : ''}
|
||||
<p class="text-muted m-0 text-capitalize details">
|
||||
${(opts.media.format ? (opts.media.format === 'TV' ? '<span>' + opts.media.format + ' Show' : '<span>' + opts.media.format.toLowerCase().replace(/_/g, ' ')) : '') + '</span>'}
|
||||
${opts.media.episodes ? '<span>' + opts.media.episodes + ' Episodes</span>' : opts.media.duration ? '<span>' + opts.media.duration + ' Minutes</span>' : ''}
|
||||
${opts.media.status ? '<span>' + opts.media.status.toLowerCase().replace(/_/g, ' ') + '</span>' : ''}
|
||||
${opts.media.season || opts.media.seasonYear ? '<span>' + ((opts.media.season.toLowerCase() || '') + ' ') + (opts.media.seasonYear || '') + '</span>' : ''}
|
||||
</p>
|
||||
</div>
|
||||
<div class="overflow-y-auto px-15 pb-5 bg-very-dark card-desc">
|
||||
${opts.media.description}
|
||||
</div>
|
||||
<div class="px-15 pb-10 pt-5">
|
||||
${opts.media.genres.map(key => (`<span class="badge badge-pill badge-color text-dark mt-5 font-weight-bold">${key}</span> `)).join('')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
} else {
|
||||
template.innerHTML = `
|
||||
<div class="row h-full">
|
||||
<div class="col-4 skeloader">
|
||||
</div>
|
||||
<div class="col-8 bg-very-dark px-15 py-10">
|
||||
${opts?.parseObject ? `<h5 class="m-0 text-capitalize font-weight-bold pb-10">${opts.parseObject.anime_title + ' - ' + opts.parseObject.episode_number}</h5>` : '<p class="skeloader w-300 h-25 rounded bg-dark">'}
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark"></p>
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark"></p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
return template
|
||||
}
|
||||
const skeletonCard = cardCreator({})
|
||||
|
||||
const DOMPARSER = new DOMParser().parseFromString.bind(new DOMParser())
|
||||
|
||||
|
|
@ -713,8 +662,9 @@ function getRSSurl () {
|
|||
return settings.torrent4 + settings.torrent1 // add custom RSS
|
||||
}
|
||||
}
|
||||
async function releasesCards (items, frag, limit) {
|
||||
async function releasesCards (items, limit) {
|
||||
const mediaItems = []
|
||||
const cards = []
|
||||
for (let l = 0; l < (limit || items.length); l++) {
|
||||
const i = items[l].querySelector.bind(items[l])
|
||||
mediaItems.push(resolveFileMedia({ fileName: i('title').innerHTML, method: 'SearchName', isRelease: true }))
|
||||
|
|
@ -722,25 +672,25 @@ async function releasesCards (items, frag, limit) {
|
|||
await Promise.all(mediaItems).then(results => {
|
||||
results.forEach((mediaInformation, index) => {
|
||||
const o = items[index].querySelector.bind(items[index])
|
||||
template = cardCreator(mediaInformation)
|
||||
template.onclick = () => client.addTorrent(o('link').innerHTML, { media: mediaInformation, episode: mediaInformation.episode })
|
||||
frag.appendChild(template)
|
||||
mediaInformation.onclick = () => client.addTorrent(o('link').innerHTML, { media: mediaInformation, episode: mediaInformation.episode })
|
||||
cards.push(cardCreator(mediaInformation))
|
||||
})
|
||||
})
|
||||
localStorage.setItem('store', JSON.stringify(store))
|
||||
return cards
|
||||
}
|
||||
async function releasesRss (limit) {
|
||||
const frag = document.createDocumentFragment()
|
||||
let cards
|
||||
await fetch(getRSSurl()).then(res => res.text().then(async xmlTxt => {
|
||||
try {
|
||||
const doc = DOMPARSER(xmlTxt, 'text/xml')
|
||||
const items = doc.querySelectorAll('item')
|
||||
await releasesCards(items, frag, limit)
|
||||
cards = await releasesCards(items, limit)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}))
|
||||
return frag
|
||||
return cards
|
||||
}
|
||||
let alID // login icon
|
||||
async function loadAnime () {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ async function loadHomePage () {
|
|||
},
|
||||
releases: async function () {
|
||||
gallerySkeleton(browseGallery)
|
||||
const frag = await releasesRss()
|
||||
browseGallery.innerHTML = ''
|
||||
const cards = await releasesRss()
|
||||
browseGallery.textContent = ''
|
||||
browseGallery.append(...cards)
|
||||
browse.classList.remove('loading')
|
||||
browseGallery.appendChild(frag)
|
||||
browseGallery.scrollTop = 0
|
||||
browse.onscroll = undefined
|
||||
},
|
||||
|
|
@ -57,12 +57,11 @@ async function loadHomePage () {
|
|||
releases: async function () { // this could be cleaner, but oh well
|
||||
await fetch(getRSSurl()).then(res => res.text().then(async xmlTxt => {
|
||||
const doc = DOMPARSER(xmlTxt, 'text/xml')
|
||||
const pubDate = doc.querySelector('pubDate').innerHTML
|
||||
const pubDate = doc.querySelector('pubDate').textContent
|
||||
if (lastRSSDate !== pubDate) {
|
||||
if (lastRSSDate) {
|
||||
homeReleases.innerHTML = ''
|
||||
homeReleases.appendChild(gallerySkeletonFrag(5))
|
||||
resolveFileMedia({ fileName: doc.querySelector('item').querySelector('title').innerHTML, method: 'SearchName', isRelease: true }).then(mediaInformation => {
|
||||
homeReleases.append(...gallerySkeletonFrag(5))
|
||||
resolveFileMedia({ fileName: doc.querySelector('item').querySelector('title').textContent, method: 'SearchName', isRelease: true }).then(mediaInformation => {
|
||||
if (settings.other1) {
|
||||
const notification = new Notification(mediaInformation.media.title.userPreferred, {
|
||||
body: `Episode ${mediaInformation.episode} was just released!`,
|
||||
|
|
@ -70,17 +69,16 @@ async function loadHomePage () {
|
|||
})
|
||||
notification.onclick = async () => {
|
||||
window.parent.focus()
|
||||
client.addTorrent(doc.querySelector('item').querySelector('link').innerHTML, { media: mediaInformation, episode: mediaInformation.episode })
|
||||
client.addTorrent(doc.querySelector('item').querySelector('link').textContent, { media: mediaInformation, episode: mediaInformation.episode })
|
||||
store[mediaInformation.parseObject.anime_title] = await alRequest({ id: mediaInformation.media.id, method: 'SearchIDSingle' }).then(res => res.data.Media)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const frag = document.createDocumentFragment()
|
||||
lastRSSDate = pubDate
|
||||
await releasesCards(doc.querySelectorAll('item'), frag, 5)
|
||||
homeReleases.innerHTML = ''
|
||||
homeReleases.appendChild(frag)
|
||||
const cards = await releasesCards(doc.querySelectorAll('item'), 5)
|
||||
homeReleases.textContent = ''
|
||||
homeReleases.append(...cards)
|
||||
}
|
||||
}))
|
||||
setTimeout(homePreviewFunctions.releases, 30000)
|
||||
|
|
@ -107,11 +105,11 @@ async function loadHomePage () {
|
|||
}
|
||||
}
|
||||
const gallerySkeletonFrag = function (limit) {
|
||||
const frag = document.createDocumentFragment()
|
||||
for (let i = 0; i < limit; i++) {
|
||||
frag.appendChild(cardCreator({}))
|
||||
const cards = []
|
||||
while (limit--) {
|
||||
cards.push(skeletonCard.cloneNode(true))
|
||||
}
|
||||
return frag
|
||||
return cards
|
||||
}
|
||||
let loadTimeout
|
||||
let lastDate
|
||||
|
|
@ -120,8 +118,7 @@ async function loadHomePage () {
|
|||
|
||||
function gallerySkeleton (gallery) {
|
||||
browse.classList.add('loading')
|
||||
gallery.innerHTML = ''
|
||||
gallery.appendChild(gallerySkeletonFrag(10))
|
||||
gallery.append(...gallerySkeletonFrag(10))
|
||||
}
|
||||
function galleryAppend (opts) {
|
||||
if (opts.page === 1) {
|
||||
|
|
@ -139,26 +136,24 @@ async function loadHomePage () {
|
|||
}
|
||||
}
|
||||
if (!opts.page || opts.page === 1) {
|
||||
opts.gallery.innerHTML = ''
|
||||
opts.gallery.textContent = ''
|
||||
}
|
||||
const frag = document.createDocumentFragment()
|
||||
const date = new Date()
|
||||
const cards = []
|
||||
opts.media.forEach(media => {
|
||||
if (opts.schedule) {
|
||||
if (media.timeUntilAiring && (!lastDate || (new Date(+date + media.timeUntilAiring * 1000).getDay() !== lastDate.getDay()))) {
|
||||
const div = document.createElement('div')
|
||||
lastDate = new Date(+date + media.timeUntilAiring * 1000)
|
||||
div.classList.add('day-row', 'font-size-24', 'font-weight-bold', 'h-50', 'd-flex', 'align-items-end')
|
||||
div.innerHTML = lastDate.toLocaleDateString('en-US', { weekday: 'long' })
|
||||
frag.appendChild(div)
|
||||
div.textContent = lastDate.toLocaleDateString('en-US', { weekday: 'long' })
|
||||
cards.push(div)
|
||||
}
|
||||
media = media.media
|
||||
}
|
||||
const template = cardCreator({ media: media, schedule: opts.schedule })
|
||||
template.onclick = () => viewAnime(media)
|
||||
frag.appendChild(template)
|
||||
cards.push(cardCreator({ media: media, schedule: opts.schedule, onclick: () => viewAnime(media) }))
|
||||
})
|
||||
opts.gallery.appendChild(frag)
|
||||
opts.gallery.append(...cards)
|
||||
canScroll = true
|
||||
}
|
||||
|
||||
|
|
@ -173,10 +168,40 @@ async function loadHomePage () {
|
|||
navHome.onclick = () => {
|
||||
lastRSSDate = undefined
|
||||
for (const item of homePreviewElements) {
|
||||
item.innerHTML = ''
|
||||
item.appendChild(gallerySkeletonFrag(5))
|
||||
item.textContent = ''
|
||||
item.append(...gallerySkeletonFrag(5))
|
||||
homePreviewFunctions[item.dataset.function]()
|
||||
}
|
||||
document.querySelector('.browse').innerHTML = ''
|
||||
document.querySelector('.browse').textContent = ''
|
||||
}
|
||||
}
|
||||
|
||||
const skeletonCard = skeletonCardTemplate.cloneNode(true).content
|
||||
const bareCard = bareCardTemplate.cloneNode(true).content
|
||||
const fullCard = fullCardTemplate.cloneNode(true).content
|
||||
function cardCreator (opts) {
|
||||
if (opts.media) {
|
||||
const card = fullCard.cloneNode(true)
|
||||
const nodes = card.querySelectorAll('*')
|
||||
nodes[0].onclick = () => opts.onclick()
|
||||
nodes[0].style = `--color:${opts.media.coverImage.color || '#1890ff'};`
|
||||
nodes[3].src = opts.media.coverImage.extraLarge || ''
|
||||
nodes[6].textContent = [opts.media.title.userPreferred, opts.episodeNumber].filter(s => s).join(' - ')
|
||||
if (opts.schedule && opts.media.nextAiringEpisode) nodes[7] = opts.media.nextAiringEpisode.episode + ' in ' + countdown(opts.media.nextAiringEpisode.timeUntilAiring)
|
||||
nodes[8].innerHTML = '<span>' + [
|
||||
opts.media.format === 'TV' ? 'TV Show' : opts.media.format?.toLowerCase().replace(/_/g, ' '),
|
||||
opts.media.episodes ? opts.media.episodes + ' Episodes' : opts.media.duration ? opts.media.duration + ' Minutes' : undefined,
|
||||
opts.media.status?.toLowerCase().replace(/_/g, ' '),
|
||||
[opts.media.season?.toLowerCase(), opts.media.seasonYear].filter(s => s).join(' ')
|
||||
].filter(s => s).join('</span><span>') + '</span>'
|
||||
nodes[13].innerHTML = opts.media.description
|
||||
nodes[14].innerHTML = opts.media.genres.map(key => (`<span class="badge badge-pill badge-color text-dark mt-5 font-weight-bold">${key}</span> `)).join('')
|
||||
return card
|
||||
} else if (opts.parseObject) {
|
||||
const card = bareCard.cloneNode(true)
|
||||
card.querySelector('h5').textContent = [opts.parseObject.anime_title, opts.parseObject.episode_number].filter(s => s).join(' - ')
|
||||
return card
|
||||
} else {
|
||||
return skeletonCard.cloneNode(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -987,8 +987,7 @@ Style: Default,${options.defaultSSAStyles || 'Roboto Medium,26,&H00FFFFFF,&H0000
|
|||
const frag = document.createDocumentFragment()
|
||||
for (const file of this.videoFiles) {
|
||||
const mediaInformation = await resolveFileMedia({ fileName: file.name, method: 'SearchName' })
|
||||
const template = cardCreator(mediaInformation)
|
||||
template.onclick = () => {
|
||||
mediaInformation.onclick = () => {
|
||||
this.cleanupVideo()
|
||||
this.buildVideo(torrent, {
|
||||
media: mediaInformation,
|
||||
|
|
@ -1039,8 +1038,8 @@ Style: Default,${options.defaultSSAStyles || 'Roboto Medium,26,&H00FFFFFF,&H0000
|
|||
localStorage.setItem('offlineTorrents', JSON.stringify(this.offlineTorrents))
|
||||
}
|
||||
const mediaInformation = await resolveFileMedia({ fileName: torrent.name, method: 'SearchName' })
|
||||
mediaInformation.onclick = () => this.addTorrent(torrent, { media: mediaInformation, episode: mediaInformation.episode })
|
||||
const template = cardCreator(mediaInformation)
|
||||
template.onclick = () => this.addTorrent(torrent, { media: mediaInformation, episode: mediaInformation.episode })
|
||||
document.querySelector('.downloads').appendChild(template)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue