fix: renders media exists badge on movie results
This commit is contained in:
@@ -20,8 +20,10 @@ export default class extends Controller {
|
||||
|
||||
options = []
|
||||
optionsLoaded = false
|
||||
resultCountEl = null
|
||||
|
||||
async connect() {
|
||||
this.resultCountEl = document.querySelector('#movie_results_count');
|
||||
await this.setOptions();
|
||||
}
|
||||
|
||||
@@ -36,6 +38,7 @@ export default class extends Controller {
|
||||
this.options.forEach((option) => option.querySelector('.download-btn').dataset['title'] = this.titleValue);
|
||||
this.dispatch('optionsLoaded', {detail: {options: this.options}})
|
||||
this.loadingIconOutlet.toggleIcon();
|
||||
this.resultCountEl.innerText = this.options.length;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -102,5 +105,6 @@ export default class extends Controller {
|
||||
count = count + 1;
|
||||
}
|
||||
});
|
||||
this.resultCountEl.innerText = count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace App\Library\Action\Handler;
|
||||
use App\Base\Service\MediaFiles;
|
||||
use App\Library\Action\Command\LibrarySearchCommand;
|
||||
use App\Library\Action\Result\LibrarySearchResult;
|
||||
use App\Library\Dto\MediaFileDto;
|
||||
use Nihilarr\PTN;
|
||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||
@@ -16,6 +18,7 @@ class LibrarySearchHandler implements HandlerInterface
|
||||
{
|
||||
private array $searchTypes = [
|
||||
'episode_by_title' => 'episodeByTitle',
|
||||
'movie_by_title' => 'movieByTitle',
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
@@ -31,6 +34,14 @@ class LibrarySearchHandler implements HandlerInterface
|
||||
|
||||
private function getSearchType(CommandInterface $command): ?string
|
||||
{
|
||||
if (!is_null($command->title) &&
|
||||
is_null($command->imdbId) &&
|
||||
is_null($command->season) &&
|
||||
is_null($command->episode)
|
||||
) {
|
||||
return 'movie_by_title';
|
||||
}
|
||||
|
||||
if ((!is_null($command->title) || is_null($command->imdbId)) &&
|
||||
!is_null($command->season) &&
|
||||
!is_null($command->episode)
|
||||
@@ -47,14 +58,26 @@ class LibrarySearchHandler implements HandlerInterface
|
||||
(int) $command->season,
|
||||
(int) $command->episode,
|
||||
);
|
||||
|
||||
$exists = $result instanceof \SplFileInfo;
|
||||
|
||||
|
||||
return new LibrarySearchResult(
|
||||
input: $command,
|
||||
exists: $exists,
|
||||
file: true === $exists ? $result->getFileInfo() : null,
|
||||
file: true === $exists ? MediaFileDto::fromSplFileInfo($result) : null,
|
||||
ptn: true === $exists ? (object) new PTN()->parse($result->getFilename()) : null,
|
||||
);
|
||||
}
|
||||
|
||||
private function movieByTitle(CommandInterface $command): ?LibrarySearchResult
|
||||
{
|
||||
$result = $this->mediaFiles->movieExists($command->title);
|
||||
$exists = $result instanceof \SplFileInfo;
|
||||
|
||||
return new LibrarySearchResult(
|
||||
input: $command,
|
||||
exists: $exists,
|
||||
file: true === $exists ? MediaFileDto::fromSplFileInfo($result) : null,
|
||||
ptn: true === $exists ? (object) new PTN()->parse($result->getFilename()) : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Library\Action\Result;
|
||||
|
||||
use App\Library\Dto\MediaFileDto;
|
||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||
|
||||
class LibrarySearchResult implements ResultInterface
|
||||
@@ -9,7 +10,7 @@ class LibrarySearchResult implements ResultInterface
|
||||
public function __construct(
|
||||
public object|array $input,
|
||||
public bool $exists,
|
||||
public ?\SplFileInfo $file = null,
|
||||
public ?MediaFileDto $file = null,
|
||||
public ?object $ptn = null,
|
||||
) {}
|
||||
}
|
||||
|
||||
23
src/Library/Dto/MediaFileDto.php
Normal file
23
src/Library/Dto/MediaFileDto.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Library\Dto;
|
||||
|
||||
readonly class MediaFileDto
|
||||
{
|
||||
public function __construct(
|
||||
public string $path,
|
||||
public string $filename,
|
||||
public string $extension,
|
||||
public string $size,
|
||||
) {}
|
||||
|
||||
public static function fromSplFileInfo(\SplFileInfo $fileInfo): self
|
||||
{
|
||||
return new static(
|
||||
path: $fileInfo->getRealPath(),
|
||||
filename: $fileInfo->getFilename(),
|
||||
extension: $fileInfo->getExtension(),
|
||||
size: $fileInfo->getSize(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,8 @@ final class WebController extends AbstractController
|
||||
public function result(
|
||||
GetMediaInfoInput $input,
|
||||
?int $season = null,
|
||||
): Response {
|
||||
): Response
|
||||
{
|
||||
$result = $this->getMediaInfoHandler->handle($input->toCommand());
|
||||
|
||||
return $this->render('search/result.html.twig', [
|
||||
@@ -52,32 +53,4 @@ final class WebController extends AbstractController
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
private function warmDownloadOptionCache(TmdbResult $result)
|
||||
{
|
||||
if ($result->mediaType === 'tvshows') {
|
||||
// dispatches a job to get the download options
|
||||
// for each episode and load them in cache
|
||||
foreach ($result->episodes as $season => $episodes) {
|
||||
// Only do the first 2 seasons, so we reduce
|
||||
// getting rate-limited by Torrentio
|
||||
if ($season > 2) {
|
||||
return;
|
||||
}
|
||||
foreach ($episodes as $episode) {
|
||||
$this->bus->dispatch(new GetTvShowOptionsCommand(
|
||||
tmdbId: $result->tmdbId,
|
||||
imdbId: $result->imdbId,
|
||||
season: $season,
|
||||
episode: $episode['episode_number'],
|
||||
));
|
||||
}
|
||||
}
|
||||
} elseif ($result->mediaType === 'movies') {
|
||||
$this->bus->dispatch(new GetMovieOptionsCommand(
|
||||
$result->tmdbId,
|
||||
$result->imdbId,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +301,7 @@ class Tmdb
|
||||
description: $data['overview'],
|
||||
year: (new \DateTime($data['release_date']))->format('Y'),
|
||||
mediaType: "movies",
|
||||
episodeAirDate: (new \DateTime($data['release_date']))->format('m/d/Y'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<template data-popover-target="content">
|
||||
<div data-popover-target="card"
|
||||
class="absolute z-40 p-1 bg-stone-400 p-1 text-black rounded-md m-1 animate-fade">
|
||||
<p class="font-bold text-sm text-left">Existing file(s) for this episode:</p>
|
||||
<p class="font-bold text-sm text-left">Existing file(s) for this media:</p>
|
||||
<ul class="list-disc ml-3">
|
||||
<li class="font-normal">{{ result.file.filename|strip_media_path }} — <strong>{{ result.file.size|filesize }}</strong></li>
|
||||
</ul>
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
{% if result.exists == false %}
|
||||
<small class="py-1 px-1.5 mr-1 grow-0 font-bold bg-rose-600 rounded-lg text-white"
|
||||
title="Episode has not been downloaded yet.">
|
||||
title="Media has not been downloaded yet.">
|
||||
missing
|
||||
</small>
|
||||
{% endif %}
|
||||
|
||||
@@ -49,9 +49,32 @@
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<p class="text-gray-50">
|
||||
{{ results.media.description }}
|
||||
</p>
|
||||
|
||||
{% if "movies" == results.media.mediaType %}
|
||||
<div class="flex flex-row justify-start items-end grow">
|
||||
<span class="py-1 px-1.5 mr-1 grow-0 font-bold text-xs bg-green-600 rounded-lg hover:cursor-pointer hover:bg-green-700 text-white">
|
||||
<span id="movie_results_count">-</span> results
|
||||
</span>
|
||||
|
||||
<small class="py-1 px-1.5 mr-1 grow-0 font-bold bg-gray-700 rounded-lg font-normal text-white" title="Release date {{ results.media.episodeAirDate }}">
|
||||
{{ results.media.episodeAirDate|date(null, 'UTC') }}
|
||||
</small>
|
||||
|
||||
<twig:Turbo:Frame id="meb_{{ results.media.imdbId }}" src="{{ path('api.library.search', {
|
||||
title: results.media.title,
|
||||
block: 'media_exists_badge',
|
||||
target: "meb_" ~ results.media.imdbId
|
||||
}) }}">
|
||||
<small class="py-1 px-1.5 mr-1 grow-0 font-bold bg-rose-600 rounded-lg text-white" title="Movie has not been downloaded yet.">
|
||||
missing
|
||||
</small>
|
||||
</twig:Turbo:Frame>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello TorrentioController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code>/var/www/src/Controller/TorrentioController.php</code></li>
|
||||
<li>Your template at <code>/var/www/templates/torrentio/index.html.twig</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,13 +1,4 @@
|
||||
<div class="p-4 flex flex-col gap-6 bg-orange-500 bg-clip-padding backdrop-filter backdrop-blur-md bg-opacity-60 rounded-md">
|
||||
{% if results.file != false %}
|
||||
<div class="p-3 bg-stone-400 p-1 text-black rounded-md m-1 animate-fade">
|
||||
<p class="font-bold text-sm text-left">Existing file(s) for this movie:</p>
|
||||
<ul class="list-disc ml-3 overflow-scroll">
|
||||
<li class="font-normal">{{ results.file.realPath|strip_media_path }} — <strong>{{ results.file.size|filesize }}</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="overflow-hidden rounded-md">
|
||||
{{ include('torrentio/partial/option-table.html.twig', {controller: 'movie-results'}) }}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user