Add a button to increase peer timeouts
This commit is contained in:
parent
dc50de31dc
commit
a0feee27a6
6 changed files with 61 additions and 28 deletions
|
|
@ -12,12 +12,14 @@ use librqbit_core::torrent_metainfo::TorrentMetaV1Info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
|
||||||
use crate::http_api_error::{ApiError, ApiErrorExt};
|
use crate::http_api_error::{ApiError, ApiErrorExt};
|
||||||
|
use crate::peer_connection::PeerConnectionOptions;
|
||||||
use crate::session::{
|
use crate::session::{
|
||||||
AddTorrent, AddTorrentOptions, AddTorrentResponse, ListOnlyResponse, Session, TorrentId,
|
AddTorrent, AddTorrentOptions, AddTorrentResponse, ListOnlyResponse, Session, TorrentId,
|
||||||
};
|
};
|
||||||
|
|
@ -322,13 +324,15 @@ impl<'de> Deserialize<'de> for OnlyFiles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Default)]
|
||||||
pub struct TorrentAddQueryParams {
|
pub struct TorrentAddQueryParams {
|
||||||
pub overwrite: Option<bool>,
|
pub overwrite: Option<bool>,
|
||||||
pub output_folder: Option<String>,
|
pub output_folder: Option<String>,
|
||||||
pub sub_folder: Option<String>,
|
pub sub_folder: Option<String>,
|
||||||
pub only_files_regex: Option<String>,
|
pub only_files_regex: Option<String>,
|
||||||
pub only_files: Option<OnlyFiles>,
|
pub only_files: Option<OnlyFiles>,
|
||||||
|
pub peer_connect_timeout: Option<u64>,
|
||||||
|
pub peer_read_write_timeout: Option<u64>,
|
||||||
pub list_only: Option<bool>,
|
pub list_only: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,6 +345,11 @@ impl TorrentAddQueryParams {
|
||||||
output_folder: self.output_folder,
|
output_folder: self.output_folder,
|
||||||
sub_folder: self.sub_folder,
|
sub_folder: self.sub_folder,
|
||||||
list_only: self.list_only.unwrap_or(false),
|
list_only: self.list_only.unwrap_or(false),
|
||||||
|
peer_opts: Some(PeerConnectionOptions {
|
||||||
|
connect_timeout: self.peer_connect_timeout.map(Duration::from_secs),
|
||||||
|
read_write_timeout: self.peer_read_write_timeout.map(Duration::from_secs),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ impl HttpApiClient {
|
||||||
output_folder: opts.output_folder,
|
output_folder: opts.output_folder,
|
||||||
sub_folder: opts.sub_folder,
|
sub_folder: opts.sub_folder,
|
||||||
list_only: Some(opts.list_only),
|
list_only: Some(opts.list_only),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let qs = serde_urlencoded::to_string(¶ms).unwrap();
|
let qs = serde_urlencoded::to_string(¶ms).unwrap();
|
||||||
let url = format!("{}torrents?{}", &self.base_url, qs);
|
let url = format!("{}torrents?{}", &self.base_url, qs);
|
||||||
|
|
|
||||||
14
crates/librqbit/webui/dist/assets/index.js
vendored
14
crates/librqbit/webui/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
2
crates/librqbit/webui/dist/manifest.json
vendored
2
crates/librqbit/webui/dist/manifest.json
vendored
|
|
@ -4,7 +4,7 @@
|
||||||
"src": "assets/logo.svg"
|
"src": "assets/logo.svg"
|
||||||
},
|
},
|
||||||
"index.html": {
|
"index.html": {
|
||||||
"file": "assets/index-1c38bddb.js",
|
"file": "assets/index-b3c336f4.js",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "index.html"
|
"src": "index.html"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ export const API = {
|
||||||
},
|
},
|
||||||
|
|
||||||
uploadTorrent: (data: string | File, opts?: {
|
uploadTorrent: (data: string | File, opts?: {
|
||||||
listOnly?: boolean, selectedFiles?: Array<number>
|
listOnly?: boolean, selectedFiles?: Array<number>, unpopularTorrent?: boolean,
|
||||||
}): Promise<AddTorrentResponse> => {
|
}): Promise<AddTorrentResponse> => {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
let url = '/torrents?&overwrite=true';
|
let url = '/torrents?&overwrite=true';
|
||||||
|
|
@ -157,6 +157,9 @@ export const API = {
|
||||||
if (opts.selectedFiles != null) {
|
if (opts.selectedFiles != null) {
|
||||||
url += `&only_files=${opts.selectedFiles.join(',')}`;
|
url += `&only_files=${opts.selectedFiles.join(',')}`;
|
||||||
}
|
}
|
||||||
|
if (opts.unpopularTorrent) {
|
||||||
|
url += '&peer_connect_timeout=20&peer_read_write_timeout=60';
|
||||||
|
}
|
||||||
return makeRequest('POST', url, data)
|
return makeRequest('POST', url, data)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ const MagnetInput = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UploadButton variant='primary' buttonText="Add Torrent from Magnet Link" onClick={onClick} data={magnet} resetData={() => setMagnet(null)} />
|
<UploadButton variant='primary' buttonText="Add Torrent from Magnet / URL" onClick={onClick} data={magnet} resetData={() => setMagnet(null)} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -481,6 +481,7 @@ const FileSelectionModal = (props: {
|
||||||
const [selectedFiles, setSelectedFiles] = useState([]);
|
const [selectedFiles, setSelectedFiles] = useState([]);
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
const [uploadError, setUploadError] = useState<Error>(null);
|
const [uploadError, setUploadError] = useState<Error>(null);
|
||||||
|
const [unpopularTorrent, setUnpopularTorrent] = useState(false);
|
||||||
const ctx = useContext(AppContext);
|
const ctx = useContext(AppContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -504,7 +505,7 @@ const FileSelectionModal = (props: {
|
||||||
|
|
||||||
const handleUpload = async () => {
|
const handleUpload = async () => {
|
||||||
setUploading(true);
|
setUploading(true);
|
||||||
API.uploadTorrent(data, { selectedFiles }).then(
|
API.uploadTorrent(data, { selectedFiles, unpopularTorrent }).then(
|
||||||
() => {
|
() => {
|
||||||
onHide();
|
onHide();
|
||||||
ctx.refreshTorrents();
|
ctx.refreshTorrents();
|
||||||
|
|
@ -518,24 +519,43 @@ const FileSelectionModal = (props: {
|
||||||
return (
|
return (
|
||||||
<Modal show={show} onHide={clear} size='lg'>
|
<Modal show={show} onHide={clear} size='lg'>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
{!!fileListError || <Modal.Title>Select Files</Modal.Title>}
|
{!!fileListError || <Modal.Title>Add torrent</Modal.Title>}
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
{fileListLoading ? <Spinner />
|
<Form>
|
||||||
: fileListError ? <ErrorComponent error={fileListError}></ErrorComponent> :
|
<fieldset className='mb-5'>
|
||||||
<Form>
|
<legend>Pick the files to download</legend>
|
||||||
{fileList.map((file, index) => (
|
{fileListLoading ? <Spinner />
|
||||||
<Form.Group key={index} controlId={`check-${index}`}>
|
: fileListError ? <ErrorComponent error={fileListError}></ErrorComponent> :
|
||||||
<Form.Check
|
<>
|
||||||
type="checkbox"
|
{fileList.map((file, index) => (
|
||||||
label={`${file.name} (${formatBytes(file.length)})`}
|
<Form.Group key={index} controlId={`check-${index}`}>
|
||||||
checked={selectedFiles.includes(index)}
|
<Form.Check
|
||||||
onChange={() => handleToggleFile(index)}>
|
type="checkbox"
|
||||||
</Form.Check>
|
label={`${file.name} (${formatBytes(file.length)})`}
|
||||||
</Form.Group>
|
checked={selectedFiles.includes(index)}
|
||||||
))}
|
onChange={() => handleToggleFile(index)}>
|
||||||
</Form>
|
</Form.Check>
|
||||||
}
|
</Form.Group>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Other options</legend>
|
||||||
|
|
||||||
|
<Form.Group controlId='unpopular-torrent'>
|
||||||
|
<Form.Check
|
||||||
|
type="checkbox"
|
||||||
|
label="Increase timeouts"
|
||||||
|
checked={unpopularTorrent}
|
||||||
|
onChange={() => setUnpopularTorrent(!unpopularTorrent)}>
|
||||||
|
</Form.Check>
|
||||||
|
<small id="emailHelp" className="form-text text-muted">This might be useful for unpopular torrents with few peers.</small>
|
||||||
|
</Form.Group>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
</Form>
|
||||||
<ErrorComponent error={uploadError} />
|
<ErrorComponent error={uploadError} />
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
<Modal.Footer>
|
<Modal.Footer>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue