Skip to content

Commit

Permalink
Tweak some things so that we can embed Web UI into Tauri
Browse files Browse the repository at this point in the history
  • Loading branch information
ikatson committed Dec 2, 2023
1 parent 950ed81 commit 137d12c
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 44 deletions.
35 changes: 17 additions & 18 deletions crates/librqbit/src/http_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,22 @@ pub struct ApiAddTorrentResponse {
}

pub struct OnlyFiles(Vec<usize>);
pub struct InitialPeers(pub Vec<SocketAddr>);

#[derive(Serialize, Deserialize, Default)]
pub struct TorrentAddQueryParams {
pub overwrite: Option<bool>,
pub output_folder: Option<String>,
pub sub_folder: Option<String>,
pub only_files_regex: Option<String>,
pub only_files: Option<OnlyFiles>,
pub peer_connect_timeout: Option<u64>,
pub peer_read_write_timeout: Option<u64>,
pub initial_peers: Option<InitialPeers>,
// Will force interpreting the content as a URL.
pub is_url: Option<bool>,
pub list_only: Option<bool>,
}

impl Serialize for OnlyFiles {
fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
Expand Down Expand Up @@ -348,8 +364,6 @@ impl<'de> Deserialize<'de> for OnlyFiles {
}
}

pub struct InitialPeers(pub Vec<SocketAddr>);

impl<'de> Deserialize<'de> for InitialPeers {
fn deserialize<D>(deserializer: D) -> std::prelude::v1::Result<Self, D::Error>
where
Expand Down Expand Up @@ -378,23 +392,8 @@ impl Serialize for InitialPeers {
}
}

#[derive(Serialize, Deserialize, Default)]
pub struct TorrentAddQueryParams {
pub overwrite: Option<bool>,
pub output_folder: Option<String>,
pub sub_folder: Option<String>,
pub only_files_regex: Option<String>,
pub only_files: Option<OnlyFiles>,
pub peer_connect_timeout: Option<u64>,
pub peer_read_write_timeout: Option<u64>,
pub initial_peers: Option<InitialPeers>,
// Will force interpreting the content as a URL.
pub is_url: Option<bool>,
pub list_only: Option<bool>,
}

impl TorrentAddQueryParams {
fn into_add_torrent_options(self) -> AddTorrentOptions {
pub fn into_add_torrent_options(self) -> AddTorrentOptions {
AddTorrentOptions {
overwrite: self.overwrite.unwrap_or(false),
only_files_regex: self.only_files_regex,
Expand Down
2 changes: 2 additions & 0 deletions crates/librqbit/src/http_api_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl Serialize for ApiError {
error_kind: &'a str,
human_readable: String,
status: u16,
status_text: String,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<usize>,
}
Expand All @@ -85,6 +86,7 @@ impl Serialize for ApiError {
},
human_readable: format!("{self}"),
status: self.status().as_u16(),
status_text: self.status().to_string(),
..Default::default()
};
if let ApiErrorKind::TorrentNotFound(id) = &self.kind {
Expand Down
2 changes: 1 addition & 1 deletion crates/librqbit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod dht_utils;
pub mod file_ops;
pub mod http_api;
pub mod http_api_client;
mod http_api_error;
pub mod http_api_error;
pub mod peer_connection;
pub mod peer_info_reader;
pub mod session;
Expand Down
Empty file.
20 changes: 10 additions & 10 deletions crates/librqbit/webui/dist/assets/index.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion crates/librqbit/webui/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

<body>
<div id="app"></div>


</body>

Expand Down
2 changes: 1 addition & 1 deletion crates/librqbit/webui/dist/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"src": "assets/logo.svg"
},
"index.html": {
"file": "assets/index-3dee43e7.js",
"file": "assets/index-48d4950c.js",
"isEntry": true,
"src": "index.html"
}
Expand Down
13 changes: 13 additions & 0 deletions crates/librqbit/webui/src/api-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ export interface ListTorrentsResponse {
torrents: Array<TorrentId>;
}

export interface TorrentAddQueryParams {
overwrite?: boolean | null;
output_folder?: string | null;
sub_folder?: string | null;
only_files_regex?: string | null;
only_files?: string,
peer_connect_timeout?: number | null;
peer_read_write_timeout?: number | null;
initial_peers?: string | null;
is_url?: boolean | null;
list_only?: boolean | null;
}

// Interface for the Torrent Stats API response
export interface LiveTorrentStats {
snapshot: {
Expand Down
74 changes: 61 additions & 13 deletions crates/librqbit/webui/src/rqbit-web.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { StrictMode, createContext, useContext, useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom/client';
import { createContext, useContext, useEffect, useRef, useState } from 'react';
import { ProgressBar, Button, Container, Row, Col, Alert, Modal, Form, Spinner } from 'react-bootstrap';
import { AddTorrentResponse, TorrentDetails, TorrentId, TorrentStats, ErrorDetails, STATE_INITIALIZING, STATE_LIVE, STATE_PAUSED, STATE_ERROR, RqbitAPI } from './api-types';
import { AddTorrentResponse, TorrentDetails, TorrentId, TorrentStats, ErrorDetails as ApiErrorDetails, STATE_INITIALIZING, STATE_LIVE, STATE_PAUSED, STATE_ERROR, RqbitAPI } from './api-types';

declare const API: RqbitAPI;

interface Error {
text: string,
details?: ErrorDetails,
details?: ApiErrorDetails,
}

interface ContextType {
Expand Down Expand Up @@ -352,7 +351,7 @@ export const RqbitWebUI = () => {
</AppContext.Provider >
}

const ErrorDetails = (props: { details: ErrorDetails }) => {
const ErrorDetails = (props: { details: ApiErrorDetails }) => {
let { details } = props;
if (!details) {
return null;
Expand Down Expand Up @@ -431,22 +430,71 @@ const UploadButton = ({ buttonText, onClick, data, resetData, variant }) => {
);
};

const UrlPromptModal: React.FC<{
show: boolean,
setUrl: (_: string) => void,
cancel: () => void,
}> = ({ show, setUrl, cancel }) => {
let [inputValue, setInputValue] = useState('');
return <Modal show={show} onHide={cancel} size='lg'>
<Modal.Header closeButton>
<Modal.Title>Add torrent</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group className="mb-3" controlId="url">
<Form.Label>Enter magnet or HTTP(S) URL to the .torrent</Form.Label>
<Form.Control value={inputValue} placeholder="magnet:?xt=urn:btih:..." onChange={(u) => { setInputValue(u.target.value) }} />
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
onClick={() => { setUrl(inputValue); setInputValue(''); }}
disabled={inputValue.length == 0}>
OK
</Button>
<Button variant="secondary" onClick={cancel}>
Cancel
</Button>
</Modal.Footer>
</Modal >
}

const MagnetInput = () => {
let [magnet, setMagnet] = useState(null);

let [showModal, setShowModal] = useState(null);

const onClick = () => {
const m = prompt('Enter magnet link or HTTP(s) URL');
setMagnet(m === '' ? null : m);
};

return (
<UploadButton
variant='primary'
buttonText="Add Torrent from Magnet / URL"
onClick={onClick}
data={magnet}
resetData={() => setMagnet(null)}
/>
<>
<UploadButton
variant='primary'
buttonText="Add Torrent from Magnet / URL"
onClick={() => {
setShowModal(true);
}}
data={magnet}
resetData={() => setMagnet(null)}
/>

<UrlPromptModal
show={showModal}
setUrl={(url) => {
setShowModal(null);
setMagnet(url);
}}
cancel={() => {
setShowModal(null);
setMagnet(null);
}} />
</>
);
};

Expand Down Expand Up @@ -598,7 +646,7 @@ const Buttons = () => {
);
};

const RootContent = (props: { closeableError: ErrorDetails, otherError: ErrorDetails, torrents: Array<TorrentId>, torrentsLoading: boolean }) => {
const RootContent = (props: { closeableError: ApiErrorDetails, otherError: ApiErrorDetails, torrents: Array<TorrentId>, torrentsLoading: boolean }) => {
let ctx = useContext(AppContext);
return <Container>
<ErrorComponent error={props.closeableError} remove={() => ctx.setCloseableError(null)} />
Expand Down

0 comments on commit 137d12c

Please sign in to comment.