import { Component, linkEvent } from 'inferno'; import moment from 'moment'; import { endpoint } from '../env'; import { SearchParams, Results, Torrent } from '../interfaces'; import { humanFileSize, magnetLink, getFileName } from '../utils'; interface State { results: Results; searchParams: SearchParams; searching: Boolean; } export class Search extends Component { state: State = { results: { torrents: [] }, searchParams: { q: "", page: 1, sort_key: 'Name', sort_dir: 'Desc', type_: 'torrent' }, searching: false }; constructor(props: any, context: any) { super(props, context); } componentDidMount() { this.state.searchParams = { page: Number(this.props.match.params.page), q: this.props.match.params.q, sort_key: this.props.match.params.sort_key, sort_dir: this.props.match.params.sort_dir, type_: this.props.match.params.type_ } this.search(); } // Re-do search if the props have changed componentDidUpdate(lastProps: any) { if (lastProps.match && lastProps.match.params !== this.props.match.params) { this.state.searchParams = { page: Number(this.props.match.params.page), q: this.props.match.params.q, sort_key: this.props.match.params.sort_key, sort_dir: this.props.match.params.sort_dir, type_: this.props.match.params.type_ } this.search(); } } search() { if (!!this.state.searchParams.q) { this.setState({ searching: true, results: { torrents: [] } }); this.fetchData(this.state.searchParams) .then(torrents => { if (!!torrents) { this.setState({ results: { torrents: torrents } }); } }).catch(error => { console.error('request failed', error); }).then(() => this.setState({ searching: false })); } else { this.setState({ results: { torrents: [] } }); } } fetchData(searchParams: SearchParams): Promise> { let q = encodeURI(searchParams.q); return fetch(`${endpoint}/service/search?q=${q}&page=${searchParams.page}&sort_key=${searchParams.sort_key}&sort_dir=${searchParams.sort_dir}&type_=${searchParams.type_}`) .then(data => data.json()); } render() { return (
{ this.state.searching ? this.spinner() : this.state.results.torrents[0] ? this.torrentsTable() : this.noResults() }
); } spinner() { return (
); } noResults() { return (

No Results

) } sortLink(sortKey: string) { return ( {sortKey} {this.sortLinkIcon(sortKey)} ) } buildSortURL(sortKey: string) { const searchParams = this.state.searchParams; let page, sortDir; if (sortKey === searchParams.sort_key) { page = searchParams.page; sortDir = searchParams.sort_dir === "Asc" ? "Desc" : "Asc"; } else { page = 1; sortDir = "Desc"; } return `/#/search/${searchParams.type_}/${searchParams.q}/${page}/${sortKey}/${sortDir}`; } sortLinkIcon(sortKey: string) { const searchParams = this.state.searchParams; if (searchParams.sort_key !== sortKey) { return ""; } if (searchParams.sort_dir === "Asc") { return ( ) } else { return ( ) } } torrentsTable() { return (
{this.state.results.torrents.map(torrent => ( { !torrent.name ? ( ) : ( )} ))}
{this.sortLink("Name")} {this.sortLink("Size")} {this.sortLink("Seeds")} {this.sortLink("Leeches")} {this.sortLink("Scraped")}
{getFileName(torrent.path)} {torrent.name} {humanFileSize(torrent.size_bytes, false)} {torrent.seeders} {torrent.leechers} {moment(torrent.scraped_date * 1000).fromNow()}
{this.paginator()}
); } paginator() { return ( ); } switchPage(a: { i: Search, nextPage: boolean }) { let newSearch = a.i.state.searchParams; newSearch.page += (a.nextPage) ? 1 : -1; a.i.props.history.push(`/search/${newSearch.type_}/${newSearch.q}/${newSearch.page}/${newSearch.sort_key}/${newSearch.sort_dir}`); } copyLink(evt) { const href = evt.currentTarget.dataset.href; try { navigator.clipboard.writeText(href) .then(() => alert("Copied magnet URL to clipboard")); } catch(err) { alert("Could not copy magnet URL: " + href) } } }