Magnet input: keydown
This commit is contained in:
parent
5a30b3fb0c
commit
74ae3cfca2
9 changed files with 59 additions and 49 deletions
2
crates/librqbit/webui/dist/assets/index.css
vendored
2
crates/librqbit/webui/dist/assets/index.css
vendored
File diff suppressed because one or more lines are too long
16
crates/librqbit/webui/dist/assets/index.js
vendored
16
crates/librqbit/webui/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
6
crates/librqbit/webui/dist/manifest.json
vendored
6
crates/librqbit/webui/dist/manifest.json
vendored
|
|
@ -4,14 +4,14 @@
|
||||||
"src": "assets/logo.svg"
|
"src": "assets/logo.svg"
|
||||||
},
|
},
|
||||||
"index.css": {
|
"index.css": {
|
||||||
"file": "assets/index-bc066ae5.css",
|
"file": "assets/index-458d2033.css",
|
||||||
"src": "index.css"
|
"src": "index.css"
|
||||||
},
|
},
|
||||||
"index.html": {
|
"index.html": {
|
||||||
"css": [
|
"css": [
|
||||||
"assets/index-bc066ae5.css"
|
"assets/index-458d2033.css"
|
||||||
],
|
],
|
||||||
"file": "assets/index-9469b905.js",
|
"file": "assets/index-1daa8daf.js",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "index.html"
|
"src": "index.html"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
export const Button: React.FC<{
|
export const Button: React.FC<{
|
||||||
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
onClick: () => void;
|
||||||
variant?: "cancel" | "primary" | "secondary" | "danger" | "none";
|
variant?: "cancel" | "primary" | "secondary" | "danger" | "none";
|
||||||
className?: string;
|
className?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}> = ({ onClick, children, className, disabled, variant }) => {
|
}> = ({ onClick, children, className, disabled, variant }) => {
|
||||||
let variantClassNames = {
|
let variantClassNames = {
|
||||||
secondary:
|
secondary: "hover:bg-blue-500 transition-colors hover:text-white",
|
||||||
"hover:bg-blue-600 transition-colors duration-100 hover:text-white",
|
|
||||||
danger:
|
danger:
|
||||||
"bg-red-500 text-white border-green-50 hover:border-red-700 hover:bg-red-600",
|
"bg-red-400 text-white border-green-50 hover:border-red-700 hover:bg-red-600",
|
||||||
primary: "bg-blue-400 text-white hover:bg-blue-600",
|
primary: "bg-blue-600 text-white hover:bg-blue-800 disabled:bg-blue-200",
|
||||||
cancel: "bg-slate-50 hover:bg-slate-200",
|
cancel: "hover:bg-slate-200",
|
||||||
none: "",
|
none: "",
|
||||||
}[variant ?? "secondary"];
|
}[variant ?? "secondary"];
|
||||||
return (
|
return (
|
||||||
|
|
@ -21,7 +20,7 @@ export const Button: React.FC<{
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClick(e);
|
onClick();
|
||||||
}}
|
}}
|
||||||
className={`flex inline-flex items-center gap-1 border rounded-lg border disabled:cursor-not-allowed px-2 py-1 transition-colors duration-300 ${variantClassNames} ${className}`}
|
className={`flex inline-flex items-center gap-1 border rounded-lg border disabled:cursor-not-allowed px-2 py-1 transition-colors duration-300 ${variantClassNames} ${className}`}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@ export const MagnetInput = ({ className }: { className?: string }) => {
|
||||||
const [inputValue, setInputValue] = useState("");
|
const [inputValue, setInputValue] = useState("");
|
||||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
setMagnet(inputValue);
|
||||||
|
setInputValue("");
|
||||||
|
setModalIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
setModalIsOpen(false);
|
setModalIsOpen(false);
|
||||||
setMagnet(null);
|
setMagnet(null);
|
||||||
|
|
@ -38,6 +44,11 @@ export const MagnetInput = ({ className }: { className?: string }) => {
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
name="magnet"
|
name="magnet"
|
||||||
onChange={(e) => setInputValue(e.target.value)}
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter" && !!inputValue) {
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}}
|
||||||
placeholder="magnet:?xt=urn:btih:..."
|
placeholder="magnet:?xt=urn:btih:..."
|
||||||
help="Enter magnet or HTTP(S) URL to the .torrent"
|
help="Enter magnet or HTTP(S) URL to the .torrent"
|
||||||
/>
|
/>
|
||||||
|
|
@ -47,15 +58,7 @@ export const MagnetInput = ({ className }: { className?: string }) => {
|
||||||
<Button variant="cancel" onClick={clear}>
|
<Button variant="cancel" onClick={clear}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button disabled={!inputValue} variant="primary" onClick={submit}>
|
||||||
disabled={!inputValue}
|
|
||||||
variant="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setMagnet(inputValue);
|
|
||||||
setInputValue("");
|
|
||||||
setModalIsOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,17 @@ export const Fieldset = ({
|
||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
label: string;
|
label?: string;
|
||||||
help?: string;
|
help?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<fieldset className={`mb-4 ${className}`}>
|
<fieldset className={`mb-4 ${className}`}>
|
||||||
<label className="text-md font-md mb-3 block">{label}</label>
|
{label && (
|
||||||
|
<label className="text-md font-md mb-3 block pb-1 border-b">
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
{children}
|
{children}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export const FormInput: React.FC<{
|
||||||
autoFocus?: boolean;
|
autoFocus?: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
inputType?: string;
|
inputType?: string;
|
||||||
|
onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
help?: string;
|
help?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
@ -16,13 +17,14 @@ export const FormInput: React.FC<{
|
||||||
name,
|
name,
|
||||||
disabled,
|
disabled,
|
||||||
onChange,
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
label,
|
label,
|
||||||
help,
|
help,
|
||||||
inputType,
|
inputType,
|
||||||
placeholder,
|
placeholder,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2 text-sm mb-6">
|
<div className="flex flex-col gap-2 text-sm mb-2">
|
||||||
<label htmlFor={name}>{label}</label>
|
<label htmlFor={name}>{label}</label>
|
||||||
<input
|
<input
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
|
|
@ -33,9 +35,10 @@ export const FormInput: React.FC<{
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={value}
|
value={value}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
{help && <div className="text-xs text-slate-500 mb-3">{help}</div>}
|
{help && <div className="text-xs text-slate-500">{help}</div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ export const FileSelectionModal = (props: {
|
||||||
const [outputFolder, setOutputFolder] = useState<string>("");
|
const [outputFolder, setOutputFolder] = useState<string>("");
|
||||||
const ctx = useContext(AppContext);
|
const ctx = useContext(AppContext);
|
||||||
const API = useContext(APIContext);
|
const API = useContext(APIContext);
|
||||||
// const [Modal, , , closeModal] = useModal({ fullScreen: true });
|
|
||||||
|
|
||||||
const selectAll = () => {
|
const selectAll = () => {
|
||||||
setSelectedFiles(
|
setSelectedFiles(
|
||||||
|
|
@ -108,7 +107,16 @@ export const FileSelectionModal = (props: {
|
||||||
} else if (listTorrentResponse) {
|
} else if (listTorrentResponse) {
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<Fieldset className="mb-4" label="Pick the files to download">
|
<FormInput
|
||||||
|
label="Output folder"
|
||||||
|
name="output_folder"
|
||||||
|
inputType="text"
|
||||||
|
value={outputFolder}
|
||||||
|
onChange={(e) => setOutputFolder(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Fieldset>
|
||||||
|
<label className="text-sm mb-2 block">Select files</label>
|
||||||
<div className="mb-3 flex gap-2">
|
<div className="mb-3 flex gap-2">
|
||||||
<Button onClick={selectAll} className="text-sm">
|
<Button onClick={selectAll} className="text-sm">
|
||||||
Select all
|
Select all
|
||||||
|
|
@ -127,15 +135,8 @@ export const FileSelectionModal = (props: {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
<Fieldset label="Options">
|
|
||||||
<FormInput
|
|
||||||
label="Output folder"
|
|
||||||
name="output_folder"
|
|
||||||
inputType="text"
|
|
||||||
value={outputFolder}
|
|
||||||
onChange={(e) => setOutputFolder(e.target.value)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
{/* <Fieldset label="Options">
|
||||||
<FormCheckbox
|
<FormCheckbox
|
||||||
label="Increase timeouts"
|
label="Increase timeouts"
|
||||||
checked={unpopularTorrent}
|
checked={unpopularTorrent}
|
||||||
|
|
@ -143,7 +144,7 @@ export const FileSelectionModal = (props: {
|
||||||
help="This might be useful for unpopular torrents with few peers. It will slow down fast torrents though."
|
help="This might be useful for unpopular torrents with few peers. It will slow down fast torrents though."
|
||||||
name="increase_timeouts"
|
name="increase_timeouts"
|
||||||
/>
|
/>
|
||||||
</Fieldset>
|
</Fieldset> */}
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ export const ConfigModal: React.FC<{
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="DHT" currentTab={tab}>
|
<Tab name="DHT" currentTab={tab}>
|
||||||
<Fieldset label="DHT config">
|
<Fieldset>
|
||||||
<FormCheck
|
<FormCheck
|
||||||
label="Enable DHT"
|
label="Enable DHT"
|
||||||
name="dht.disable"
|
name="dht.disable"
|
||||||
|
|
@ -241,7 +241,7 @@ export const ConfigModal: React.FC<{
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="TCP Listen" currentTab={tab}>
|
<Tab name="TCP Listen" currentTab={tab}>
|
||||||
<Fieldset label="TCP Listener config">
|
<Fieldset>
|
||||||
<FormCheck
|
<FormCheck
|
||||||
label="Listen on TCP"
|
label="Listen on TCP"
|
||||||
name="tcp_listen.disable"
|
name="tcp_listen.disable"
|
||||||
|
|
@ -281,7 +281,7 @@ export const ConfigModal: React.FC<{
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="Session" currentTab={tab}>
|
<Tab name="Session" currentTab={tab}>
|
||||||
<Fieldset label="Session persistence">
|
<Fieldset>
|
||||||
<FormCheck
|
<FormCheck
|
||||||
label="Enable persistence"
|
label="Enable persistence"
|
||||||
name="persistence.disable"
|
name="persistence.disable"
|
||||||
|
|
@ -302,7 +302,7 @@ export const ConfigModal: React.FC<{
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="Peer options" currentTab={tab}>
|
<Tab name="Peer options" currentTab={tab}>
|
||||||
<Fieldset label="Peer connection options">
|
<Fieldset>
|
||||||
<FormInput
|
<FormInput
|
||||||
label="Connect timeout (seconds)"
|
label="Connect timeout (seconds)"
|
||||||
inputType="number"
|
inputType="number"
|
||||||
|
|
@ -324,7 +324,7 @@ export const ConfigModal: React.FC<{
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab name="HTTP API" currentTab={tab}>
|
<Tab name="HTTP API" currentTab={tab}>
|
||||||
<Fieldset label="HTTP API config">
|
<Fieldset>
|
||||||
<FormCheck
|
<FormCheck
|
||||||
label="Enable HTTP API"
|
label="Enable HTTP API"
|
||||||
name="http_api.disable"
|
name="http_api.disable"
|
||||||
|
|
@ -365,7 +365,7 @@ export const ConfigModal: React.FC<{
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
{!!handleCancel && (
|
{!!handleCancel && (
|
||||||
<Button variant="secondary" onClick={handleCancel}>
|
<Button variant="cancel" onClick={handleCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue