wip: returns movie results in turbo frames

This commit is contained in:
2025-07-14 16:20:36 -05:00
parent 47108af1f8
commit f2971eee9c
4 changed files with 48 additions and 19 deletions

View File

@@ -24,23 +24,15 @@ export default class extends Controller {
async connect() { async connect() {
this.resultCountEl = document.querySelector('#movie_results_count'); this.resultCountEl = document.querySelector('#movie_results_count');
await this.setOptions();
} }
async setOptions() { async listTargetConnected() {
if (false === this.optionsLoaded) { this.optionsLoaded = true;
this.optionsLoaded = true; this.options = this.element.querySelectorAll('tbody tr');
await fetch(`/torrentio/movies/${this.tmdbIdValue}/${this.imdbIdValue}`) this.options.forEach((option) => option.querySelector('.download-btn').dataset['title'] = this.titleValue);
.then(res => res.text()) this.dispatch('optionsLoaded', {detail: {options: this.options}})
.then(response => { this.loadingIconOutlet.toggleIcon();
this.element.innerHTML = response; this.resultCountEl.innerText = this.options.length;
this.options = this.element.querySelectorAll('tbody tr');
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;
});
}
} }
// Keeps compatible with Filter & TV Shows // Keeps compatible with Filter & TV Shows

View File

@@ -9,12 +9,14 @@ use App\Torrentio\Action\Input\GetMovieOptionsInput;
use App\Torrentio\Action\Input\GetTvShowOptionsInput; use App\Torrentio\Action\Input\GetTvShowOptionsInput;
use App\Torrentio\Exception\TorrentioRateLimitException; use App\Torrentio\Exception\TorrentioRateLimitException;
use Carbon\Carbon; use Carbon\Carbon;
use OneToMany\RichBundle\Contract\ResultInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface; use Symfony\Contracts\Cache\ItemInterface;
use Symfony\UX\Turbo\TurboBundle;
final class WebController extends AbstractController final class WebController extends AbstractController
{ {
@@ -25,7 +27,7 @@ final class WebController extends AbstractController
) {} ) {}
#[Route('/torrentio/movies/{tmdbId}/{imdbId}', name: 'app_torrentio_movies')] #[Route('/torrentio/movies/{tmdbId}/{imdbId}', name: 'app_torrentio_movies')]
public function movieOptions(GetMovieOptionsInput $input, CacheInterface $cache): Response public function movieOptions(GetMovieOptionsInput $input, CacheInterface $cache, Request $request): Response
{ {
$cacheId = sprintf( $cacheId = sprintf(
"page.torrentio.movies.%s.%s", "page.torrentio.movies.%s.%s",
@@ -33,13 +35,18 @@ final class WebController extends AbstractController
$input->imdbId $input->imdbId
); );
return $cache->get($cacheId, function (ItemInterface $item) use ($input) { // return $cache->get($cacheId, function (ItemInterface $item) use ($input, $request) {
$item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0)); // $item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0));
$results = $this->getMovieOptionsHandler->handle($input->toCommand()); $results = $this->getMovieOptionsHandler->handle($input->toCommand());
if ($request->headers->get('Turbo-Frame')) {
return $this->sendFragmentResponse($results, $request);
}
return $this->render('torrentio/movies.html.twig', [ return $this->render('torrentio/movies.html.twig', [
'results' => $results, 'results' => $results,
]); ]);
}); //});
} }
#[Route('/torrentio/tvshows/{tmdbId}/{imdbId}/{season?}/{episode?}', name: 'app_torrentio_tvshows')] #[Route('/torrentio/tvshows/{tmdbId}/{imdbId}/{season?}/{episode?}', name: 'app_torrentio_tvshows')]
@@ -98,4 +105,17 @@ final class WebController extends AbstractController
]); ]);
}); });
} }
private function sendFragmentResponse(ResultInterface $result, Request $request): Response
{
$request->setRequestFormat(TurboBundle::STREAM_FORMAT);
return $this->renderBlock(
'torrentio/fragments.html.twig',
$request->query->get('block'),
[
'results' => $result,
'target' => $request->query->get('target')
]
);
}
} }

View File

@@ -85,6 +85,12 @@
{{ stimulus_controller('movie_results', {title: results.media.title, tmdbId: results.media.tmdbId, imdbId: results.media.imdbId}) }} {{ stimulus_controller('movie_results', {title: results.media.title, tmdbId: results.media.tmdbId, imdbId: results.media.imdbId}) }}
data-movie-results-loading-icon-outlet=".loading-icon" data-movie-results-loading-icon-outlet=".loading-icon"
> >
<twig:Turbo:Frame id="movie_results_frame" src="{{ path('app_torrentio_movies', {
tmdbId: results.media.tmdbId,
imdbId: results.media.imdbId,
target: 'movie_results_frame',
block: 'movie_results'
}) }}" />
</div> </div>
{% elseif "tvshows" == results.media.mediaType %} {% elseif "tvshows" == results.media.mediaType %}
<twig:TvEpisodeList <twig:TvEpisodeList

View File

@@ -0,0 +1,11 @@
{% block movie_results %}
<turbo-stream action="replace" targets="#{{ target }}">
<template>
<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">
<div class="overflow-hidden rounded-md">
{{ include('torrentio/partial/option-table.html.twig', {controller: 'movie-results'}) }}
</div>
</div>
</template>
</turbo-stream>
{% endblock %}