feat: multiple RSS feeds #164, fix search not resetting on empty

This commit is contained in:
ThaUnknown 2022-06-10 18:33:54 +02:00
parent 9a60b7aad2
commit b02d0645f5
6 changed files with 73 additions and 41 deletions

View file

@ -1,6 +1,6 @@
{
"name": "Miru",
"version": "2.6.1",
"version": "2.7.0",
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
"main": "src/index.js",
"homepage": "https://github.com/ThaUnknown/miru#readme",

View file

@ -35,7 +35,7 @@
}
export function getRSSContent (url) {
return fetch(url)
return url && fetch(url)
.then(res => {
if (res.ok) {
return res.text().then(xmlTxt => {
@ -59,9 +59,9 @@
NanDesuKa: 'https://nyaa.si/?page=rss&c=0_0&f=0&u=NanDesuKa&q='
}
const epstring = ep => `"E${pl(ep)}+"|"E${pl(ep)}v"|"+${pl(ep)}+"|"+${pl(ep)}v"`
export function getReleasesRSSurl () {
const rss = rssmap[settings.rssFeed] || settings.rssFeed
return new URL(`${rss}${settings.rssQuality ? `"${settings.rssQuality}"` : ''}`)
export function getReleasesRSSurl (val) {
const rss = rssmap[val] || val
return rss && new URL(rssmap[val] ? `${rss}${settings.rssQuality ? `"${settings.rssQuality}"` : ''}` : rss)
}
// matches: OP01 ED01 EP01 E01 01v -01- _01_ with spaces and stuff
const epNumRx = /[EO]?[EPD _-]\d{2}[v _-]|\d{2}[-~]\d{2}/i

View file

@ -6,7 +6,7 @@
playerPause: true,
playerAutocomplete: true,
rssQuality: '1080',
rssFeed: 'SubsPlease',
rssFeeds: [['New Releases', 'SubsPlease']],
rssAutoplay: true,
rssTrusted: true,
rssBatch: false,
@ -17,6 +17,13 @@
}
localStorage.removeItem('relations') // TODO: remove
export let set = JSON.parse(localStorage.getItem('settings')) || { ...defaults }
if (!set.rssFeeds) { // TODO: remove ;-;
if (set.rssFeed) {
set.rssFeeds = [['New Releases', set.rssFeed]]
} else {
set.rssFeeds = [['New Releases', 'SubsPlease']]
}
}
window.addEventListener('paste', ({ clipboardData }) => {
if (clipboardData.items?.[0]) {
if (clipboardData.items[0].type === 'text/plain' && clipboardData.items[0].kind === 'string') {
@ -180,20 +187,29 @@
</Tab>
<Tab>
<div class="root">
<div
class="input-group mb-10 w-600 form-control-lg"
data-toggle="tooltip"
data-placement="bottom"
data-title="What RSS Feed To Fetch Releases From, Allows For Custom CORS Enabled Feeds">
<div class="input-group-prepend">
<span class="input-group-text w-100 justify-content-center">Feed</span>
{#each settings.rssFeeds as _, i}
<div
class="input-group mb-10 w-700 form-control-lg"
data-toggle="tooltip"
data-placement="bottom"
data-title="What RSS Feed To Fetch Releases From, Allows For Custom CORS Enabled Feeds">
<div class="input-group-prepend">
<span class="input-group-text w-100 justify-content-center">Feed</span>
</div>
<input type="text" class="form-control form-control-lg w-150 flex-reset" placeholder='New Releases' autocomplete="off" bind:value={settings.rssFeeds[i][0]} />
<input id="rss-feed-{i}" type="text" list="rss-feed-list-{i}" class="w-400 form-control form-control-lg" placeholder='https://nyaa.si/?page=rss&c=0_0&f=0&q=' autocomplete="off" bind:value={settings.rssFeeds[i][1]} />
<datalist id="rss-feed-list-{i}">
<option value="SubsPlease">https://nyaa.si/?page=rss&c=0_0&f=0&u=subsplease&q=</option>
<option value="Erai-raws [Multi-Sub]">https://nyaa.si/?page=rss&c=0_0&f=0&u=Erai-raws&q=</option>
<option value="NanDesuKa">https://nyaa.si/?page=rss&c=0_0&f=0&u=NanDesuKa&q=</option>
</datalist>
<div class="input-group-append">
<button type="button" on:click={() => { settings.rssFeeds.splice(i, 1); settings.rssFeeds = settings.rssFeeds }} class="btn btn-danger btn-lg input-group-append">Remove</button>
</div>
</div>
<input id="rss-feed" type="text" list="rss-feed-list" class="form-control form-control-lg" autocomplete="off" bind:value={settings.rssFeed} />
<datalist id="rss-feed-list">
<option value="SubsPlease">https://nyaa.si/?page=rss&c=0_0&f=0&u=subsplease&q=</option>
<option value="Erai-raws [Multi-Sub]">https://nyaa.si/?page=rss&c=0_0&f=0&u=Erai-raws&q=</option>
<option value="NanDesuKa">https://nyaa.si/?page=rss&c=0_0&f=0&u=NanDesuKa&q=</option>
</datalist>
{/each}
<div class="input-group input-group-lg form-control-lg mb-10 w-500">
<button type="button" on:click={() => { settings.rssFeeds[settings.rssFeeds.length] = ['New Releases', null] }} class="btn btn-lg btn-primary mb-10">Add Feed</button>
</div>
<div class="input-group mb-10 w-300 form-control-lg" data-toggle="tooltip" data-placement="top" data-title="What Quality To Find Torrents In">
<div class="input-group-prepend">
@ -287,3 +303,9 @@
</div>
</div>
</Tabs>
<style>
select.form-control:invalid {
color: var(--dm-input-placeholder-text-color);
}
</style>

View file

@ -23,7 +23,7 @@
</div>
{/each}
{:then cards}
{#each cards as card}
{#each cards || [] as card}
{#if typeof card === 'string'}
<div class="day-row font-size-24 font-weight-bold h-50 d-flex align-items-end">{card}</div>
{:else if !card.media}

View file

@ -3,7 +3,7 @@
import Section from './Section.svelte'
import Gallery from './Gallery.svelte'
import { add } from '@/modules/torrent.js'
import { alToken } from '../Settings.svelte'
import { alToken, set } from '../Settings.svelte'
import { alRequest } from '@/modules/anilist.js'
import { resolveFileMedia } from '@/modules/anime.js'
import { getRSSContent, getReleasesRSSurl } from '@/lib/RSSView.svelte'
@ -17,14 +17,14 @@
let hasNext = true
let container = null
function sanitiseObject(object) {
function sanitiseObject (object) {
const safe = {}
for (const [key, value] of Object.entries(object)) {
if (value) safe[key] = value
}
return safe
}
function customFilter(mediaList) {
function customFilter (mediaList) {
return mediaList?.filter(({ media }) => {
let condition = true
if (!media) return condition
@ -43,7 +43,7 @@
return condition
})
}
async function infiniteScroll() {
async function infiniteScroll () {
if (current && canScroll && hasNext && this.scrollTop + this.clientHeight > this.scrollHeight - 800) {
canScroll = false
const res = sections[current].load(++page)
@ -54,7 +54,7 @@
}
}
async function loadCurrent(initial = true) {
async function loadCurrent (initial = true) {
page = 1
canScroll = false
const res = sections[current].load(1, 50, initial)
@ -64,7 +64,7 @@
}
$: load(current)
async function load(current) {
async function load (current) {
if (sections[current]) {
loadCurrent()
} else {
@ -84,7 +84,7 @@
let lastDate = null
function processMedia(res) {
function processMedia (res) {
hasNext = res?.data?.Page.pageInfo.hasNextPage
return res?.data?.Page.media.map(media => {
return { media }
@ -92,8 +92,8 @@
}
let lastRSSDate = 0
async function releasesCards(page, limit, force) {
const doc = await getRSSContent(getReleasesRSSurl())
async function releasesCards (page, limit, force, val) {
const doc = await getRSSContent(getReleasesRSSurl(val))
if (doc) {
const pubDate = doc.querySelector('pubDate').textContent
if (force || lastRSSDate !== pubDate) {
@ -114,7 +114,7 @@
}
const seasons = ['WINTER', 'SPRING', 'SUMMER', 'FALL']
const getSeason = d => seasons[Math.floor((d.getMonth() / 12) * 4) % 4]
const sections = {
let sections = {
continue: {
title: 'Continue Watching',
load: (page = 1, perPage = 50, initial = false) => {
@ -132,14 +132,6 @@
},
hide: !alToken
},
releases: {
title: 'New Releases',
releases: true,
load: async (page = 1, perPage = 20, initial = false, force = true) => {
if (initial) search.sort = 'START_DATE_DESC'
return customFilter(await releasesCards(page, perPage, force))
}
},
planning: {
title: 'Your List',
load: (page = 1, perPage = 50, initial = false) => {
@ -243,7 +235,7 @@
const entries = customFilter(res?.data?.Page.airingSchedules.filter(entry => entry.media.countryOfOrigin !== 'CN' && !entry.media.isAdult) || []).slice(0, perPage)
const media = []
hasNext = res?.data?.Page.pageInfo.hasNextPage
let date = new Date()
const date = new Date()
for (const entry of entries) {
if (entry.timeUntilAiring && perPage !== 6 && (!lastDate || new Date(+date + entry.timeUntilAiring * 1000).getDay() !== lastDate.getDay())) {
lastDate = new Date(+date + entry.timeUntilAiring * 1000)
@ -270,6 +262,20 @@
}
}
}
for (let i = 0; i < set.rssFeeds.length; ++i) {
const [title, val] = set.rssFeeds[i]
sections = {
['releases-' + i]: {
title,
releases: true,
load: async (page = 1, perPage = 20, initial = false, force = true) => {
if (initial) search.sort = 'START_DATE_DESC'
return customFilter(await releasesCards(page, perPage, force, val))
}
},
...sections
}
}
</script>
<div class="d-flex h-full flex-column overflow-y-scroll root" on:scroll={infiniteScroll} bind:this={container}>
@ -279,7 +285,7 @@
<Gallery {media} />
{:else}
<div>
{#each Object.entries(sections) as [key, opts] (opts.title)}
{#each Object.entries(sections) as [key, opts] (key)}
{#if !opts.hide}
<Section opts={{ ...opts, onclick: () => (current = key) }} />
{/if}

View file

@ -25,7 +25,11 @@
if (current === null) {
if (Object.values(search).filter(v => v).length) current = 'search'
} else {
loadCurrent(false)
if (Object.values(search).filter(v => v).length) {
loadCurrent(false)
} else {
current = null
}
}
searchTimeout = null
}, 500)