You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
3.6 KiB

<script setup lang="ts">
import type { FeedItem } from '@/feed'
import jfapi, { type View } from '@/jfapi'
import { getImageLink, getDisplayDuration } from '../utils'
import { onBeforeMount, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import ScrollerItemPortrait from './ScrollerItemPortrait.vue'
const route = useRoute()
const viewId = String(route.params.id)
let index = 0
let totalItems = 0
console.log(viewId)
const Items = async (viewId: string, type: string): Promise<FeedItem[]> => {
return new Promise(async (resolve) => {
const feed: FeedItem[] = []
const userid = localStorage.getItem('jf_userid')
const data = await jfapi.GetItemsInView(userid ? userid : '', viewId, type, index)
if (data !== null) {
index = data.StartIndex + 100
totalItems = data.TotalRecordCount
if (index > totalItems) {
index = totalItems
}
console.log('Index =>', index)
for (const item of data.Items) {
if (userid === null) {
window.location.href = '/login'
}
feed.push({
title: item.SeriesName || item.Name,
subtext: item.SeriesName
? `S${item.ParentIndexNumber}:E${item.IndexNumber} - ${item.Name}`
: String(item.ProductionYear),
image: getImageLink(item),
summary: item.Overview,
infoSubtext: item.OriginalTitle == item.Name ? '' : item.OriginalTitle,
imdbRating: String(item.CommunityRating),
runtime: getDisplayDuration(item.RunTimeTicks),
date: String(item.ProductionYear),
MPAA: item.OfficialRating,
tag:
item.UserData?.UnplayedItemCount !== undefined
? String(item.UserData.UnplayedItemCount)
: '',
itemId: item.Id,
type: item.Type,
})
}
console.log('MediaGrid.vue =>', feed)
resolve(feed)
}
})
}
const items = ref<FeedItem[]>()
const views = ref<View[]>()
const viewstring = ref<string | null>('')
const viewType = ref('')
let loading = false
views.value = undefined
onBeforeMount(async () => {
viewstring.value = localStorage.getItem('jf_views')
views.value = JSON.parse(viewstring.value || '')
for (const view of views.value || []) {
if (view.Id === viewId) {
if (view.CollectionType.toLowerCase() === 'movies') {
viewType.value = 'Movie'
} else if (view.CollectionType.toLowerCase() === 'tvshows') {
viewType.value = 'Series'
}
}
}
console.log('ItemType =>', viewType)
const data = ref<FeedItem[]>()
console.log(viewType)
data.value = await Items(viewId, viewType.value)
items.value = data.value
})
const onLoadMore = async () => {
if (index === totalItems || loading) {
return
}
loading = true
const more = await Items(viewId, viewType.value)
items.value?.push(...more)
loading = false
}
onMounted(() => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
onLoadMore()
}
})
const el = document.querySelector('.loading-trigger')
if (el) {
console.log('observing!')
observer.observe(el)
}
})
</script>
<template>
<div class="media-grid">
<div class="grid-wrapper">
<ScrollerItemPortrait
v-for="item in items"
:item="item"
:key="item.itemId"
class="scroller-item"
/>
<div class="loading-trigger"></div>
</div>
</div>
</template>
<style scoped>
.media-grid {
max-width: 80%;
margin: auto;
margin-top: 3em;
}
.grid-wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1em;
}
</style>