Made changes for Desktop app to work

This commit is contained in:
Igor Katson 2023-12-02 21:12:15 +00:00
parent fe04e17d63
commit 28c2db2a37
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
15 changed files with 74 additions and 38 deletions

2
Cargo.lock generated
View file

@ -1313,6 +1313,7 @@ name = "librqbit-core"
version = "3.1.0"
dependencies = [
"anyhow",
"directories",
"hex 0.4.3",
"itertools 0.12.0",
"librqbit-bencode",
@ -1335,7 +1336,6 @@ dependencies = [
"backoff",
"chrono",
"dashmap",
"directories",
"futures",
"hex 0.4.3",
"indexmap 2.1.0",

View file

@ -31,7 +31,6 @@ backoff = "0.4.0"
futures = "0.3"
rand = "0.8"
indexmap = "2"
directories = "5"
dashmap = {version = "5.5.3", features = ["serde"]}
clone_to_owned = {path="../clone_to_owned", package="librqbit-clone-to-owned", version = "2.2.1"}

View file

@ -1,5 +1,6 @@
// TODO: this now stores only the routing table, but we also need AT LEAST the same socket address...
use librqbit_core::directories::get_configuration_directory;
use librqbit_core::spawn_utils::spawn;
use serde::{Deserialize, Serialize};
use std::fs::OpenOptions;
@ -72,8 +73,7 @@ impl PersistentDht {
let config_filename = match config.config_filename.take() {
Some(config_filename) => config_filename,
None => {
let dirs = directories::ProjectDirs::from("com", "rqbit", "dht")
.context("cannot determine project directory for com.rqbit.dht")?;
let dirs = get_configuration_directory("dht")?;
let path = dirs.cache_dir().join("dht.json");
info!("will store DHT routing table to {:?} periodically", &path);
path

View file

@ -143,8 +143,10 @@ impl Api {
info,
only_files,
seen_peers,
output_folder,
}) => ApiAddTorrentResponse {
id: None,
output_folder: output_folder.to_string_lossy().into_owned(),
seen_peers: Some(seen_peers),
details: make_torrent_details(&info_hash, &info, only_files.as_deref())
.context("error making torrent details")?,
@ -159,6 +161,7 @@ impl Api {
ApiAddTorrentResponse {
id: Some(id),
details,
output_folder: handle.info().out_dir.to_string_lossy().into_owned(),
seen_peers: None,
}
}
@ -227,6 +230,7 @@ pub struct TorrentDetailsResponse {
pub struct ApiAddTorrentResponse {
pub id: Option<usize>,
pub details: TorrentDetailsResponse,
pub output_folder: String,
pub seen_peers: Option<Vec<SocketAddr>>,
}

View file

@ -14,6 +14,7 @@ use bencode::{bencode_serialize_to_writer, BencodeDeserializer};
use buffers::ByteString;
use dht::{Dht, DhtBuilder, Id20, PersistentDht, PersistentDhtConfig, RequestPeersStream};
use librqbit_core::{
directories::get_configuration_directory,
magnet::Magnet,
peer_id::generate_peer_id,
torrent_metainfo::{torrent_from_bytes, TorrentMetaV1Info, TorrentMetaV1Owned},
@ -66,7 +67,7 @@ impl SessionDatabase {
fn serialize(&self) -> SerializedSessionDatabase {
SerializedSessionDatabase {
torrents_v2: self
torrents: self
.torrents
.iter()
.map(|(id, torrent)| {
@ -135,7 +136,7 @@ where
#[derive(Serialize, Deserialize)]
struct SerializedSessionDatabase {
torrents_v2: HashMap<usize, SerializedTorrent>,
torrents: HashMap<usize, SerializedTorrent>,
}
pub struct Session {
@ -208,9 +209,11 @@ pub struct ListOnlyResponse {
pub info_hash: Id20,
pub info: TorrentMetaV1Info<ByteString>,
pub only_files: Option<Vec<usize>>,
pub output_folder: PathBuf,
pub seen_peers: Vec<SocketAddr>,
}
#[allow(clippy::large_enum_variant)]
pub enum AddTorrentResponse {
AlreadyManaged(TorrentId, ManagedTorrentHandle),
ListOnly(ListOnlyResponse),
@ -276,7 +279,6 @@ pub struct SessionOptions {
pub disable_dht: bool,
pub disable_dht_persistence: bool,
pub persistence: bool,
// Will default to output_folder/.rqbit-session.json
pub persistence_filename: Option<PathBuf>,
pub dht_config: Option<PersistentDhtConfig>,
pub peer_id: Option<Id20>,
@ -308,9 +310,12 @@ impl Session {
Some(dht)
};
let peer_opts = opts.peer_opts.unwrap_or_default();
let persistence_filename = opts
.persistence_filename
.unwrap_or_else(|| output_folder.join(".rqbit-session.json"));
let persistence_filename = match opts.persistence_filename {
Some(filename) => filename,
None => get_configuration_directory("session")?
.data_dir()
.join("session.json"),
};
let session = Arc::new(Self {
persistence_filename,
peer_id,
@ -322,6 +327,10 @@ impl Session {
});
if opts.persistence {
info!(
"will use {:?} for session persistence",
session.persistence_filename
);
if let Some(parent) = session.persistence_filename.parent() {
std::fs::create_dir_all(parent).with_context(|| {
format!("couldn't create directory {:?} for session storage", parent)
@ -391,7 +400,7 @@ impl Session {
let db: SerializedSessionDatabase =
serde_json::from_reader(&mut rdr).context("error deserializing session database")?;
let mut futures = Vec::new();
for (id, storrent) in db.torrents_v2.into_iter() {
for (id, storrent) in db.torrents.into_iter() {
let trackers: Vec<ByteString> = storrent
.trackers
.into_iter()
@ -646,15 +655,6 @@ impl Session {
let only_files = get_only_files(opts.only_files, opts.only_files_regex, opts.list_only)?;
if opts.list_only {
return Ok(AddTorrentResponse::ListOnly(ListOnlyResponse {
info_hash,
info,
only_files,
seen_peers: initial_peers,
}));
}
let sub_folder = opts.sub_folder.map(PathBuf::from).unwrap_or_default();
let output_folder = opts
.output_folder
@ -662,6 +662,16 @@ impl Session {
.unwrap_or_else(|| self.output_folder.clone())
.join(sub_folder);
if opts.list_only {
return Ok(AddTorrentResponse::ListOnly(ListOnlyResponse {
info_hash,
info,
only_files,
output_folder,
seen_peers: initial_peers,
}));
}
let mut builder = ManagedTorrentBuilder::new(info, info_hash, output_folder.clone());
builder
.overwrite(opts.overwrite)

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

View file

@ -4,7 +4,7 @@
"src": "assets/logo.svg"
},
"index.html": {
"file": "assets/index-386e9e08.js",
"file": "assets/index-3e661b92.js",
"isEntry": true,
"src": "index.html"
}

View file

@ -19,6 +19,7 @@ export interface TorrentDetails {
export interface AddTorrentResponse {
id: number | null;
details: TorrentDetails;
output_folder: string,
seen_peers?: Array<string>;
}

View file

@ -72,6 +72,9 @@ export const API: RqbitAPI = {
if (opts?.initial_peers) {
url += `&initial_peers=${opts.initial_peers.join(',')}`;
}
if (opts?.output_folder) {
url += `&output_folder=${opts.output_folder}`;
}
if (typeof data === 'string') {
url += '&is_url=true';
}

View file

@ -6,7 +6,7 @@ import { API } from "./http-api";
ReactDOM.createRoot(document.getElementById('app') as HTMLInputElement).render(
<StrictMode>
<APIContext.Provider value={API}>
<RqbitWebUI />
<RqbitWebUI title="rqbit web UI - version 4.0.0-beta.3" />
</APIContext.Provider>
</StrictMode>
);

View file

@ -349,7 +349,7 @@ const TorrentsList = (props: { torrents: Array<TorrentId> | null, loading: boole
</>;
};
export const RqbitWebUI = () => {
export const RqbitWebUI = (props: { title: string }) => {
const [closeableError, setCloseableError] = useState<Error | null>(null);
const [otherError, setOtherError] = useState<Error | null>(null);
@ -382,7 +382,7 @@ export const RqbitWebUI = () => {
return <AppContext.Provider value={context}>
<div className='text-center'>
<h1 className="mt-3 mb-4">rqbit web 4.0.0-beta.0</h1>
<h1 className="mt-3 mb-4">{props.title}</h1>
<RootContent
closeableError={closeableError}
otherError={otherError}
@ -591,11 +591,14 @@ const FileSelectionModal = (props: {
const [uploading, setUploading] = useState(false);
const [uploadError, setUploadError] = useState<Error | null>(null);
const [unpopularTorrent, setUnpopularTorrent] = useState(false);
const [outputFolder, setOutputFolder] = useState<string>('');
const ctx = useContext(AppContext);
const API = useContext(APIContext);
useEffect(() => {
console.log(listTorrentResponse);
setSelectedFiles(listTorrentResponse ? listTorrentResponse.details.files.map((_, id) => id) : []);
setOutputFolder(listTorrentResponse?.output_folder || '');
}, [listTorrentResponse]);
const clear = () => {
@ -623,6 +626,7 @@ const FileSelectionModal = (props: {
overwrite: true,
only_files: selectedFiles,
initial_peers: initialPeers,
output_folder: outputFolder,
};
if (unpopularTorrent) {
opts.peer_opts = {
@ -647,7 +651,7 @@ const FileSelectionModal = (props: {
return <ErrorComponent error={listTorrentError}></ErrorComponent>;
} else if (listTorrentResponse) {
return <Form>
<fieldset className='mb-5'>
<fieldset className='mb-4'>
<legend>Pick the files to download</legend>
{listTorrentResponse.details.files.map((file, index) => (
<Form.Group key={index} controlId={`check-${index}`}>
@ -661,9 +665,16 @@ const FileSelectionModal = (props: {
))}
</fieldset>
<fieldset>
<legend>Other options</legend>
<Form.Group controlId='unpopular-torrent'>
<legend>Options</legend>
<Form.Group controlId='output-folder' className="mb-3">
<Form.Label>Output folder</Form.Label>
<Form.Control
type="text"
value={outputFolder}
onChange={(e) => setOutputFolder(e.target.value)}
/>
</Form.Group>
<Form.Group controlId='unpopular-torrent' className="mb-3">
<Form.Check
type="checkbox"
label="Increase timeouts"
@ -673,7 +684,7 @@ const FileSelectionModal = (props: {
<small id="emailHelp" className="form-text text-muted">This might be useful for unpopular torrents with few peers. It will slow down fast torrents though.</small>
</Form.Group>
</fieldset>
</Form >
</Form>
}
};

View file

@ -29,6 +29,7 @@ buffers = {path="../buffers", package="librqbit-buffers", version = "2.2.1"}
bencode = {path = "../bencode", default-features=false, package="librqbit-bencode", version="2.2.1"}
clone_to_owned = {path="../clone_to_owned", package="librqbit-clone-to-owned", version = "2.2.1"}
itertools = "0.12"
directories = "5"
[dev-dependencies]
serde_json = "1"
serde_json = "1"

View file

@ -0,0 +1,6 @@
use anyhow::Context;
pub fn get_configuration_directory(application: &str) -> anyhow::Result<directories::ProjectDirs> {
directories::ProjectDirs::from("com", "rqbit", application)
.with_context(|| format!("cannot determine project directory for com.rqbit.{application}"))
}

View file

@ -1,4 +1,5 @@
pub mod constants;
pub mod directories;
pub mod id20;
pub mod lengths;
pub mod magnet;