wip: download single episode

This commit is contained in:
2025-07-24 16:24:21 -05:00
parent 56c5156380
commit a27fcf334a
7 changed files with 50 additions and 15 deletions

View File

@@ -2,6 +2,9 @@ export default class DownloadOptionTr extends HTMLTableRowElement {
H264_CODECS = ['h264', 'h.264', 'x264'] H264_CODECS = ['h264', 'h.264', 'x264']
H265_CODECS = ['h265', 'h.265', 'x265', 'hevc'] H265_CODECS = ['h265', 'h.265', 'x265', 'hevc']
#downloadBtnEl;
url;
size; size;
quality; quality;
resolution; resolution;
@@ -12,20 +15,31 @@ export default class DownloadOptionTr extends HTMLTableRowElement {
mediaType; mediaType;
season; season;
episode; episode;
filename;
imdbId;
episodeId;
mediaTitle;
constructor() { constructor() {
super(); super();
this.url = this.getAttribute('url');
this.size = this.getAttribute('size'); this.size = this.getAttribute('size');
this.quality = this.getAttribute('quality'); this.quality = this.getAttribute('quality');
this.resolution = this.getAttribute('resolution'); this.resolution = this.getAttribute('resolution');
this.codec = this.getAttribute('codec'); this.codec = this.getAttribute('codec');
this.seeders = this.getAttribute('seeders'); this.seeders = this.getAttribute('seeders');
this.provider = this.getAttribute('provider'); this.provider = this.getAttribute('provider');
this.filename = this.getAttribute('filename');
this.imdbId = this.getAttribute('imdb-id');
this.languages = JSON.parse(this.getAttribute('languages')); this.languages = JSON.parse(this.getAttribute('languages'));
this.mediaType = this.getAttribute('media-type'); this.mediaType = this.getAttribute('media-type');
this.mediaTitle = this.getAttribute('media-title');
this.season = this.getAttribute('season') ?? null; this.season = this.getAttribute('season') ?? null;
this.episode = this.getAttribute('episode') ?? null; this.episode = this.getAttribute('episode') ?? null;
this.episodeId = this.getAttribute('episode-id') ?? null;
this.#downloadBtnEl = this.querySelector('.download-btn');
this.#downloadBtnEl.addEventListener('click', () => this.download());
// document.addEventListener('filterDownloadOptions', this.filter.bind(this)); // document.addEventListener('filterDownloadOptions', this.filter.bind(this));
} }
connectedCallback() { connectedCallback() {
@@ -90,4 +104,27 @@ export default class DownloadOptionTr extends HTMLTableRowElement {
return include; return include;
} }
download() {
console.log('Downloading dis bihh')
fetch('/api/download', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
url: this.url,
title: this.mediaTitle,
filename: this.filename,
mediaType: this.mediaType,
imdbId: this.imdbId,
episodeId: this.episodeId
})
})
.then(res => res.json())
.then(json => {
console.log(json)
})
}
} }

View File

@@ -3,6 +3,7 @@ export default class EpisodeContainer extends HTMLElement {
H265_CODECS = ['h265', 'h.265', 'x265', 'hevc'] H265_CODECS = ['h265', 'h.265', 'x265', 'hevc']
options = []; options = [];
showTitle;
#episodeSelectorEl; #episodeSelectorEl;
#resultsToggleBtnEl; #resultsToggleBtnEl;
@@ -12,6 +13,7 @@ export default class EpisodeContainer extends HTMLElement {
constructor() { constructor() {
super(); super();
this.showTitle = this.getAttribute('show-title');
this.#resultsTableEl = this.querySelector('.results-container'); this.#resultsTableEl = this.querySelector('.results-container');
this.#resultsToggleBtnEl = this.querySelector('.dropdown-button'); this.#resultsToggleBtnEl = this.querySelector('.dropdown-button');
this.#resultsCountBadgeEl = this.querySelector('.results-count-badge'); this.#resultsCountBadgeEl = this.querySelector('.results-count-badge');

View File

@@ -38,10 +38,6 @@ export default class extends Controller {
} }
} }
isSelected() {
return this.episodeSelectorTarget.checked;
}
download() { download() {
this.element.options.forEach(option => { this.element.options.forEach(option => {
const optionSelector = option.querySelector('input[type="checkbox"]'); const optionSelector = option.querySelector('input[type="checkbox"]');

View File

@@ -28,6 +28,7 @@ class GetTvShowOptionsHandler implements HandlerInterface
$file = $this->mediaFiles->episodeExists($parentShow->title, $command->season, $command->episode); $file = $this->mediaFiles->episodeExists($parentShow->title, $command->season, $command->episode);
return new GetTvShowOptionsResult( return new GetTvShowOptionsResult(
parentShow: $parentShow,
media: $media, media: $media,
file: MediaFileDto::fromSplFileInfo($file), file: MediaFileDto::fromSplFileInfo($file),
season: $command->season, season: $command->season,

View File

@@ -9,6 +9,7 @@ use OneToMany\RichBundle\Contract\ResultInterface;
class GetTvShowOptionsResult implements ResultInterface class GetTvShowOptionsResult implements ResultInterface
{ {
public function __construct( public function __construct(
public TmdbResult $parentShow,
public TmdbResult $media, public TmdbResult $media,
public MediaFileDto|false $file, public MediaFileDto|false $file,
public string $season, public string $season,

View File

@@ -4,6 +4,7 @@
<div data-live-id="{{ uniqid() }}" class="episode-container flex flex-col gap-4"> <div data-live-id="{{ uniqid() }}" class="episode-container flex flex-col gap-4">
{% for episode in this.getEpisodes().items %} {% for episode in this.getEpisodes().items %}
<episode-container id="{{ episode_anchor(episode['season_number'], episode['episode_number']) }}" class="results" <episode-container id="{{ episode_anchor(episode['season_number'], episode['episode_number']) }}" class="results"
show-title="{{ this.title }}"
data-tv-results-loading-icon-outlet=".loading-icon" data-tv-results-loading-icon-outlet=".loading-icon"
data-download-button-outlet=".download-btn" data-download-button-outlet=".download-btn"
{{ stimulus_controller('tv_results', { {{ stimulus_controller('tv_results', {

View File

@@ -43,6 +43,7 @@
{% for result in results.results %} {% for result in results.results %}
<tr is="dl-tr" <tr is="dl-tr"
class="download-option bg-white dark:bg-slate-700 flex flex-col flex-no wrap r-tablerow border-b border-gray-500" class="download-option bg-white dark:bg-slate-700 flex flex-col flex-no wrap r-tablerow border-b border-gray-500"
url="{{ result.url }}"
size="{{ result.size }}" size="{{ result.size }}"
quality="{{ result.quality }}" quality="{{ result.quality }}"
resolution="{{ result.resolution }}" resolution="{{ result.resolution }}"
@@ -51,10 +52,16 @@
provider="{{ result.provider }}" provider="{{ result.provider }}"
languages="{{ result.languages|json_encode }}" languages="{{ result.languages|json_encode }}"
media-type="{{ results.media.mediaType }}" media-type="{{ results.media.mediaType }}"
imdb-id="{{ results.media.imdbId }}"
filename="{{ result.filename }}"
data-local-id="{{ result.localId }}" data-local-id="{{ result.localId }}"
{% if "tvshows" == results.media.mediaType %} {% if "tvshows" == results.media.mediaType %}
season="{{ result.season }}" season="{{ result.season }}"
episode="{{ result.episodeNumber }}" episode="{{ result.episodeNumber }}"
episode-id="{{ episode_id(result.season, result.episodeNumber) }}"
media-title="{{ results.parentShow.title }}"
{% else %}
media-title="{{ results.media.title }}"
{% endif %} {% endif %}
> >
<td id="size" class="px-4 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50"> <td id="size" class="px-4 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
@@ -79,17 +86,7 @@
{{ result.languageFlags|raw }} {{ result.languageFlags|raw }}
</td> </td>
<td class="px-4 py-4 whitespace-nowrap text-sm text-end text-gray-800 dark:text-gray-50 flex flex-row gap-2 items-center justify-start mb:justify-end"> <td class="px-4 py-4 whitespace-nowrap text-sm text-end text-gray-800 dark:text-gray-50 flex flex-row gap-2 items-center justify-start mb:justify-end">
<button class="download-btn p-1.5 bg-green-600 rounded-md text-gray-50" <button class="download-btn p-1.5 bg-green-600 rounded-md text-gray-50">
{{ stimulus_controller('download_button', {
url: result.url,
title: results.media.title,
filename: result.filename,
mediaType: results.media.mediaType,
imdbId: results.media.imdbId ?? app.current_route_parameters.imdbId,
episodeId: results|episode_id_from_results
}) }}
{{ stimulus_action('download_button', 'download', 'click') }}
>
Download Download
</button> </button>
<label for="select"> <label for="select">