mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-19 00:12:13 +00:00
feat: multiple RSS feeds #164, fix search not resetting on empty
This commit is contained in:
parent
9a60b7aad2
commit
b02d0645f5
6 changed files with 73 additions and 41 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue