mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-14 20:02:18 +02:00
fixed downloading enqueing in web-ui view
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import ApiService, {DefaultApiService} from "./api-service";
|
||||
import {Observable, throwError} from "rxjs";
|
||||
import {FileDownloadInfo, FileDownloadRequest, FileDownloadResponse} from "../model/file-download";
|
||||
import {FileDownloadInfo, FileDownloadRequest} from "../model/file-download";
|
||||
import {first} from "rxjs/operators";
|
||||
|
||||
//const FILE_API_PATH = 'file';
|
||||
@@ -8,14 +8,14 @@ const FILE_DOWNLOAD_API_PATH = 'file/download';
|
||||
const FILE_DOWNLOAD_INFO_API_PATH =FILE_DOWNLOAD_API_PATH + '/info';
|
||||
|
||||
export default interface FileApiService extends ApiService {
|
||||
download(req: FileDownloadRequest): Observable<FileDownloadResponse>;
|
||||
download(req: FileDownloadRequest): Observable<FileDownloadInfo>;
|
||||
getDownloadInfo(): Observable<FileDownloadInfo>;
|
||||
}
|
||||
|
||||
export class DefaultFileApiService extends DefaultApiService implements FileApiService {
|
||||
download(req: FileDownloadRequest): Observable<FileDownloadResponse> {
|
||||
download(req: FileDownloadRequest): Observable<FileDownloadInfo> {
|
||||
if (req.url) {
|
||||
return this.post<FileDownloadResponse>(FILE_DOWNLOAD_API_PATH, req);
|
||||
return this.post<FileDownloadInfo>(FILE_DOWNLOAD_API_PATH, req);
|
||||
}
|
||||
return throwError(() => new Error('Invalid arguments'));
|
||||
}
|
||||
|
||||
@@ -73,7 +73,16 @@ export default function FileDownload(props: FileDownloadProps) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const sub = services.file().subscribeDownloadNotification(() => startPoll());
|
||||
const sub = services.file().subscribeDownloadNotification((info: FileDownloadInfo) => {
|
||||
setDownloads((downloads: any) => {
|
||||
if (!downloads[info.uuid]) {
|
||||
downloads[info.uuid] = info;
|
||||
return {...downloads};
|
||||
}
|
||||
return downloads;
|
||||
});
|
||||
startPoll();
|
||||
});
|
||||
return () => sub.unsubscribe();
|
||||
}, [services, startPoll])
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {useSnackbar} from "notistack";
|
||||
import {getIconByName} from "../../icons/icons";
|
||||
import {useServices} from "../../provider/service-provider";
|
||||
import ServerConfig from "../../model/server-config";
|
||||
import {FileDownloadResponse} from "../../model/file-download";
|
||||
import {FileDownloadInfo} from "../../model/file-download";
|
||||
|
||||
const VALID_VIDEO_FILES = ['mkv', 'mp4', 'avi'];
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function PlaylistTree(props: PlaylistTreeProps) {
|
||||
url: item.header.url,
|
||||
filename: filename + '.' + ext
|
||||
}).pipe(first()).subscribe({
|
||||
next: (_: FileDownloadResponse) => {},
|
||||
next: (_: FileDownloadInfo) => {},
|
||||
error: _ => enqueueSnackbar("Download failed!", {variant: 'error'}),
|
||||
complete: noop,
|
||||
});
|
||||
|
||||
@@ -3,10 +3,6 @@ export interface FileDownloadRequest {
|
||||
filename: string;
|
||||
}
|
||||
|
||||
export interface FileDownloadResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export interface DownloadErrorInfo {
|
||||
uuid: string;
|
||||
filename: string;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {PlaylistItem, PlaylistGroup} from "../model/playlist";
|
||||
import FileSaver from "file-saver";
|
||||
import {Observer, Observable, Subject, Subscription, tap} from "rxjs";
|
||||
import {Observable, Subject, Subscription, tap} from "rxjs";
|
||||
import FileApiService, {DefaultFileApiService} from "../api/file-api-service";
|
||||
import {FileDownloadInfo, FileDownloadRequest, FileDownloadResponse} from "../model/file-download";
|
||||
import {FileDownloadInfo, FileDownloadRequest} from "../model/file-download";
|
||||
|
||||
export default class FileService {
|
||||
|
||||
private downloadNotification = new Subject<boolean>();
|
||||
private downloadNotification = new Subject<FileDownloadInfo>();
|
||||
constructor(private fileApiService: FileApiService = new DefaultFileApiService()) {
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ export default class FileService {
|
||||
return this.downloadNotification.subscribe(observer as any);
|
||||
}
|
||||
|
||||
private notifyDownload() {
|
||||
this.downloadNotification.next(true);
|
||||
private notifyDownload(info: FileDownloadInfo) {
|
||||
this.downloadNotification.next(info);
|
||||
}
|
||||
|
||||
save(playlist: PlaylistGroup[]) {
|
||||
@@ -30,8 +30,8 @@ export default class FileService {
|
||||
FileSaver.saveAs(blob, "playlist.m3u");
|
||||
}
|
||||
|
||||
download(req: FileDownloadRequest): Observable<FileDownloadResponse> {
|
||||
return this.fileApiService.download(req).pipe(tap((result) => result?.success && this.notifyDownload() ));
|
||||
download(req: FileDownloadRequest): Observable<FileDownloadInfo> {
|
||||
return this.fileApiService.download(req).pipe(tap((result) => this.notifyDownload(result) ));
|
||||
}
|
||||
|
||||
getDownloadInfo(): Observable<FileDownloadInfo> {
|
||||
|
||||
+15
-5
@@ -55,15 +55,25 @@ impl FileDownload {
|
||||
Ok(url) => {
|
||||
let filename_re = download_cfg._re_filename.as_ref().unwrap();
|
||||
let tmp_filename = filename_re.replace_all(&unidecode(req_filename)
|
||||
.replace(' ', "_"), "").to_string();
|
||||
let filname_path = Path::new(&tmp_filename);
|
||||
let file_stem = filname_path.file_stem().and_then(OsStr::to_str).unwrap_or("");
|
||||
let file_ext = filname_path.extension().and_then(OsStr::to_str).unwrap_or("");
|
||||
.replace(' ', "_"), "")
|
||||
.replace("__", "_")
|
||||
.replace("_-_", "-").to_string();
|
||||
let filename_path = Path::new(&tmp_filename);
|
||||
let file_stem = filename_path.file_stem().and_then(OsStr::to_str).unwrap_or("").trim_matches(FILENAME_TRIM_PATTERNS);
|
||||
let file_ext = filename_path.extension().and_then(OsStr::to_str).unwrap_or("");
|
||||
|
||||
let filename = format!("{}.{}", file_stem.trim_matches(FILENAME_TRIM_PATTERNS), file_ext);
|
||||
let mut filename = format!("{}.{}", file_stem, file_ext);
|
||||
let file_dir = get_download_directory(download_cfg, file_stem);
|
||||
let mut file_path: PathBuf = file_dir.clone();
|
||||
file_path.push(&filename);
|
||||
let mut x: usize = 1;
|
||||
while file_path.is_file() {
|
||||
filename = format!("{}_{}.{}", file_stem, x, file_ext);
|
||||
file_path = file_dir.clone();
|
||||
file_path.push(&filename);
|
||||
x += 1;
|
||||
}
|
||||
|
||||
file_path.to_str()?;
|
||||
|
||||
Some(FileDownload {
|
||||
|
||||
+10
-5
@@ -4,7 +4,7 @@ use std::io::{ErrorKind, Write};
|
||||
use std::ops::Deref;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use actix_web::{HttpResponse, web};
|
||||
use serde_json::{json};
|
||||
use serde_json::{json, Value};
|
||||
use crate::api::api_model::{AppState, DownloadErrorInfo, DownloadQueue, FileDownload, FileDownloadRequest};
|
||||
use crate::model::config::{VideoDownloadConfig};
|
||||
use crate::utils::{bytes_to_megabytes, get_request_headers};
|
||||
@@ -93,6 +93,12 @@ fn run_download_queue(download_cfg: &VideoDownloadConfig, download_queue: Arc<Do
|
||||
Ok(())
|
||||
}
|
||||
|
||||
macro_rules! download_info_response {
|
||||
($file_download:expr, $errors:expr) => {
|
||||
HttpResponse::Ok().json(json!({"uuid": $file_download.uuid, "filename": $file_download.filename, "filesize": $file_download.size, "errors": $errors}))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn queue_download_file(
|
||||
req: web::Json<FileDownloadRequest>,
|
||||
_app_state: web::Data<AppState>,
|
||||
@@ -103,7 +109,7 @@ pub(crate) async fn queue_download_file(
|
||||
}
|
||||
match FileDownload::new(req.url.as_str(), req.filename.as_str(), download_cfg) {
|
||||
Some(file_download) => {
|
||||
let file_name = file_download.filename.to_owned();
|
||||
let response = download_info_response!(file_download, Value::Null);
|
||||
_app_state.downloads.queue.lock().unwrap().push(file_download);
|
||||
if _app_state.downloads.active.read().unwrap().is_none() {
|
||||
match run_download_queue(download_cfg, Arc::clone(&_app_state.downloads)) {
|
||||
@@ -111,7 +117,7 @@ pub(crate) async fn queue_download_file(
|
||||
Err(err) => return HttpResponse::InternalServerError().json(json!({"error": err})),
|
||||
}
|
||||
}
|
||||
HttpResponse::Ok().json(json!({"success": file_name}))
|
||||
response
|
||||
}
|
||||
None => HttpResponse::BadRequest().json(json!({"error": "Invalid Arguments"})),
|
||||
}
|
||||
@@ -120,7 +126,6 @@ pub(crate) async fn queue_download_file(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub(crate) async fn download_file_info(
|
||||
_app_state: web::Data<AppState>,
|
||||
) -> HttpResponse {
|
||||
@@ -133,6 +138,6 @@ pub(crate) async fn download_file_info(
|
||||
match &*_app_state.downloads.active.read().unwrap() {
|
||||
None => HttpResponse::Ok().json(json!({"finished": true, "errors": errors})),
|
||||
Some(file_download) =>
|
||||
HttpResponse::Ok().json(json!({"uuid": file_download.uuid, "filename": file_download.filename, "filesize": file_download.size, "errors": errors}))
|
||||
download_info_response!(file_download, errors)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user