From 40db9bdd8310e040fe56f9694e849e2c136928e6 Mon Sep 17 00:00:00 2001 From: ThaUnknown Date: Mon, 19 Apr 2021 14:20:17 +0200 Subject: [PATCH] optimise the fuck out of card creation! --- app/index.html | 47 ++++++++++++++++++++++++ app/js/animeHandler.js | 74 ++++++------------------------------- app/js/interface.js | 83 +++++++++++++++++++++++++++--------------- app/js/player.js | 5 +-- 4 files changed, 115 insertions(+), 94 deletions(-) diff --git a/app/index.html b/app/index.html index 015d7e6..151dfda 100644 --- a/app/index.html +++ b/app/index.html @@ -776,6 +776,53 @@ + + + diff --git a/app/js/animeHandler.js b/app/js/animeHandler.js index 6b5252f..4c0d61d 100644 --- a/app/js/animeHandler.js +++ b/app/js/animeHandler.js @@ -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 = ` -
-
- -
-
-
-
${opts.media.title.userPreferred}${opts.episodeNumber ? ' - ' + opts.episodeNumber : ''}
- ${opts.schedule && opts.media.nextAiringEpisode ? "EP " + opts.media.nextAiringEpisode.episode + ' in ' + countdown(opts.media.nextAiringEpisode.timeUntilAiring) + '' : ''} -

- ${(opts.media.format ? (opts.media.format === 'TV' ? '' + opts.media.format + ' Show' : '' + opts.media.format.toLowerCase().replace(/_/g, ' ')) : '') + ''} - ${opts.media.episodes ? '' + opts.media.episodes + ' Episodes' : opts.media.duration ? '' + opts.media.duration + ' Minutes' : ''} - ${opts.media.status ? '' + opts.media.status.toLowerCase().replace(/_/g, ' ') + '' : ''} - ${opts.media.season || opts.media.seasonYear ? '' + ((opts.media.season.toLowerCase() || '') + ' ') + (opts.media.seasonYear || '') + '' : ''} -

-
-
- ${opts.media.description} -
-
- ${opts.media.genres.map(key => (`${key} `)).join('')} -
-
-
- ` - } else { - template.innerHTML = ` -
-
-
-
- ${opts?.parseObject ? `
${opts.parseObject.anime_title + ' - ' + opts.parseObject.episode_number}
` : '

'} -

-

-

-
-
- ` - } - 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 () { diff --git a/app/js/interface.js b/app/js/interface.js index 659376e..2750c11 100644 --- a/app/js/interface.js +++ b/app/js/interface.js @@ -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 = '' + [ + 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('') + '' + nodes[13].innerHTML = opts.media.description + nodes[14].innerHTML = opts.media.genres.map(key => (`${key} `)).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) } } diff --git a/app/js/player.js b/app/js/player.js index 221060a..469ddec 100644 --- a/app/js/player.js +++ b/app/js/player.js @@ -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) }) }