refactor index schema and metadata format and directory tree

This commit is contained in:
2026-05-30 01:05:27 +00:00
parent 550f67531a
commit 900fcea638
23 changed files with 879 additions and 458 deletions
+1 -1
View File
@@ -570,7 +570,7 @@ function getRatingClass(item: MediaItem): string {
function getResolution(item: MediaItem): string | null {
if (item.type === "movies") {
const movie = item.data as Movie
return Object.values(movie.torrents || {})[0]?.resolution ?? null
return Object.values(movie.files || {})[0]?.resolution ?? null
}
return null
}
+15 -6
View File
@@ -124,7 +124,7 @@
>
<img
v-if="castMember.profile_path && !castMember.profile_path.startsWith('/')"
:src="getCoverUrl(castMember.profile_path, item.root_id)"
:src="getCastProfileUrl(castMember.profile_path)"
:alt="castMember.name"
class="cast-photo"
/>
@@ -202,7 +202,7 @@
<script setup lang="ts">
import { computed, ref, watch, onMounted, onUnmounted, nextTick } from "vue"
import type { CastMember, MediaItem, Movie, Series, Torrent } from "../types"
import type { CastMember, MediaItem, Movie, MovieUi, Series, Torrent } from "../types"
import {
getCoverUrl,
getVideoPreviewUrl,
@@ -499,7 +499,7 @@ function getShowreelSourceAttributes(path: string): VideoSourceAttributes {
const movieVersions = computed((): Torrent[] => {
if (props.item.type !== "movies") return []
const movie = props.item.data as Movie
return sortTorrentsByPreference(Object.values(movie.torrents || {}))
return sortTorrentsByPreference(Object.values(movie.files || {}))
})
// Page backdrop background
@@ -583,6 +583,15 @@ function getCastPlaceholderUrl(gender?: CastMember["gender"]): string {
return gender === "female" ? castPlaceholderFemaleUrl : castPlaceholderMaleUrl
}
function getCastProfileUrl(profilePath: string | null): string {
if (!profilePath) return ""
if (profilePath.includes("/")) {
return getCoverUrl(profilePath, props.item.root_id)
}
const castPath = `.mediahive/people/${profilePath}`
return getCoverUrl(castPath, props.item.root_id)
}
function formatRuntime(minutes: number): string {
const hours = Math.floor(minutes / 60)
const mins = minutes % 60
@@ -656,7 +665,7 @@ function handlePlayVersion(filePath: string | null) {
function handleVersionContextMenu(event: MouseEvent, version: Torrent) {
event.preventDefault()
event.stopPropagation()
const rootId = version.root_id || ((props.item.data as Movie).root_id ?? props.item.root_id)
const rootId = version.root_id || ((props.item.data as MovieUi).root_id ?? props.item.root_id)
versionActionMenu.value = {
visible: true,
x: event.clientX,
@@ -675,7 +684,7 @@ function handleVersionContextMenu(event: MouseEvent, version: Torrent) {
function handleVersionShortcutKeydown(event: KeyboardEvent, version: Torrent) {
if (!version.playable_file) return
const rootId = version.root_id || ((props.item.data as Movie).root_id ?? props.item.root_id)
const rootId = version.root_id || ((props.item.data as MovieUi).root_id ?? props.item.root_id)
const key = event.key.toLowerCase()
if (key === "e" && (event.metaKey || event.ctrlKey)) {
event.preventDefault()
@@ -718,7 +727,7 @@ function handlePlay(filePath: string | null) {
function handleVersionActivate(version: Torrent, event: MouseEvent | KeyboardEvent) {
if (!version.playable_file) return
const rootId = version.root_id || ((props.item.data as Movie).root_id ?? props.item.root_id)
const rootId = version.root_id || ((props.item.data as MovieUi).root_id ?? props.item.root_id)
if (event.altKey) {
handleOpenFolder(version.playable_file, rootId)
return
@@ -218,7 +218,7 @@ function normalizeQualityBadge(value: string): string {
const hasDolbyVision = computed(() => {
return (
props.torrent.has_dolby_vision === true ||
props.torrent.dovi === true ||
hasAnyTag(
dolbyVisionPattern,
props.torrent.quality,
@@ -231,7 +231,7 @@ const hasDolbyVision = computed(() => {
const hasDolbyAtmos = computed(() => {
return (
props.torrent.has_dolby_atmos === true ||
props.torrent.atmos === true ||
hasAnyTag(
dolbyAtmosPattern,
props.torrent.quality,
@@ -244,7 +244,7 @@ const hasDolbyAtmos = computed(() => {
const hasHdr = computed(() => {
return (
props.torrent.is_hdr === true ||
props.torrent.hdr === true ||
hasAnyTag(
hdrPattern,
props.torrent.quality,
+5 -5
View File
@@ -148,9 +148,9 @@
<div class="context-menu-header">
{{ contextMenu.episode.name || `Episode ${contextMenu.episode.episode_number}` }}
</div>
<div v-if="Object.values(contextMenu.episode.torrents || {}).length > 0">
<div v-if="Object.values(contextMenu.episode.files || {}).length > 0">
<ReleaseVersionCard
v-for="(torrent, index) in sortTorrentsByPreference(Object.values(contextMenu.episode.torrents || {}))"
v-for="(torrent, index) in sortTorrentsByPreference(Object.values(contextMenu.episode.files || {}))"
:key="index"
class="context-menu-version"
:torrent="torrent"
@@ -556,8 +556,8 @@ function handleEpisodeHover(key: string, isEntering: boolean) {
// Backdrop URL - only use backdrop_path, fall back to collage (handled in template)
const backdropUrl = computed(() => {
if (props.series.info?.backdrop_path) {
return getCoverUrl(props.series.info.backdrop_path, props.series.root_id)
if (props.series.backdrop_path) {
return getCoverUrl(props.series.backdrop_path, props.series.root_id)
}
return null
})
@@ -643,7 +643,7 @@ function truncate(text: string, maxLength: number): string {
// Handle play
function handlePlay(episode: Episode) {
const playableFile = Object.values(episode.torrents || {})[0]?.playable_file
const playableFile = Object.values(episode.files || {})[0]?.playable_file
if (playableFile) {
emit("play", playableFile)
}