fix eslint
This commit is contained in:
@ -4,17 +4,17 @@ import Page from './page';
|
|||||||
import RecentTorrents from './recent-torrents'
|
import RecentTorrents from './recent-torrents'
|
||||||
|
|
||||||
export default class ActivityPage extends Page {
|
export default class ActivityPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Rats On The Boat - Content Search Engine');
|
this.setTitle('Rats On The Boat - Content Search Engine');
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='column center'>
|
<div className='column center'>
|
||||||
<div className='column center w100p pad0-75'>
|
<div className='column center w100p pad0-75'>
|
||||||
<RecentTorrents />
|
<RecentTorrents />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,52 +20,52 @@ if(typeof WEB !== 'undefined')
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const { ipcRenderer, remote } = require('electron');
|
const { ipcRenderer, remote } = require('electron');
|
||||||
window.currentWindow = remote.getCurrentWindow()
|
window.currentWindow = remote.getCurrentWindow()
|
||||||
|
|
||||||
window.torrentSocket = {}
|
window.torrentSocket = {}
|
||||||
window.torrentSocket.callbacks = {}
|
window.torrentSocket.callbacks = {}
|
||||||
window.torrentSocket.listeners = {}
|
window.torrentSocket.listeners = {}
|
||||||
window.torrentSocket.on = (name, func) => {
|
window.torrentSocket.on = (name, func) => {
|
||||||
const newListener = (event, ...data) => {
|
const newListener = (event, ...data) => {
|
||||||
func(...data)
|
func(...data)
|
||||||
}
|
|
||||||
window.torrentSocket.listeners[func] = newListener
|
|
||||||
ipcRenderer.on(name, newListener);
|
|
||||||
}
|
|
||||||
window.torrentSocket.off = (name, func) => {
|
|
||||||
if(!func)
|
|
||||||
ipcRenderer.removeAllListeners(name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const realListener = window.torrentSocket.listeners[func]
|
|
||||||
if(realListener)
|
|
||||||
{
|
|
||||||
ipcRenderer.removeListener(name, realListener);
|
|
||||||
delete window.torrentSocket.listeners[func]
|
|
||||||
}
|
}
|
||||||
}
|
window.torrentSocket.listeners[func] = newListener
|
||||||
}
|
ipcRenderer.on(name, newListener);
|
||||||
window.torrentSocket.emit = (name, ...data) => {
|
}
|
||||||
if(typeof data[data.length - 1] === 'function')
|
window.torrentSocket.off = (name, func) => {
|
||||||
{
|
if(!func)
|
||||||
const id = Math.random().toString(36).substring(5)
|
ipcRenderer.removeAllListeners(name);
|
||||||
window.torrentSocket.callbacks[id] = data[data.length - 1];
|
else
|
||||||
data[data.length - 1] = {callback: id}
|
{
|
||||||
}
|
const realListener = window.torrentSocket.listeners[func]
|
||||||
ipcRenderer.send(name, data)
|
if(realListener)
|
||||||
}
|
{
|
||||||
ipcRenderer.on('callback', (event, id, data) => {
|
ipcRenderer.removeListener(name, realListener);
|
||||||
const callback = window.torrentSocket.callbacks[id]
|
delete window.torrentSocket.listeners[func]
|
||||||
if(callback)
|
}
|
||||||
callback(data)
|
}
|
||||||
delete window.torrentSocket.callbacks[id]
|
}
|
||||||
});
|
window.torrentSocket.emit = (name, ...data) => {
|
||||||
|
if(typeof data[data.length - 1] === 'function')
|
||||||
|
{
|
||||||
|
const id = Math.random().toString(36).substring(5)
|
||||||
|
window.torrentSocket.callbacks[id] = data[data.length - 1];
|
||||||
|
data[data.length - 1] = {callback: id}
|
||||||
|
}
|
||||||
|
ipcRenderer.send(name, data)
|
||||||
|
}
|
||||||
|
ipcRenderer.on('callback', (event, id, data) => {
|
||||||
|
const callback = window.torrentSocket.callbacks[id]
|
||||||
|
if(callback)
|
||||||
|
callback(data)
|
||||||
|
delete window.torrentSocket.callbacks[id]
|
||||||
|
});
|
||||||
|
|
||||||
ipcRenderer.on('url', (event, url) => {
|
ipcRenderer.on('url', (event, url) => {
|
||||||
console.log('url', url)
|
console.log('url', url)
|
||||||
router(url)
|
router(url)
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,8 +164,8 @@ class App extends Component {
|
|||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
checkNotModal
|
checkNotModal
|
||||||
&&
|
&&
|
||||||
<Header />
|
<Header />
|
||||||
}
|
}
|
||||||
<PagesPie />
|
<PagesPie />
|
||||||
<Footer />
|
<Footer />
|
||||||
|
@ -1,259 +1,259 @@
|
|||||||
const XXX_BLOCK_WORDS = ['incestcash', 'asacp', 'xondemand', 'yankscash', 'klixxx', 'cybersitter', 'safesurf',
|
const XXX_BLOCK_WORDS = ['incestcash', 'asacp', 'xondemand', 'yankscash', 'klixxx', 'cybersitter', 'safesurf',
|
||||||
'surfwatch', 'netcash', 'watersport', 'fuck', 'threesome', 'tits',
|
'surfwatch', 'netcash', 'watersport', 'fuck', 'threesome', 'tits',
|
||||||
'masturbating', 'incest', 'bestiality', 'analintercourse', 'analsex', 'animesex',
|
'masturbating', 'incest', 'bestiality', 'analintercourse', 'analsex', 'animesex',
|
||||||
'anitablonde', 'autosex', 'blackass', 'blackasses', 'boner', 'boobcruise',
|
'anitablonde', 'autosex', 'blackass', 'blackasses', 'boner', 'boobcruise',
|
||||||
'boobies', 'bordello', 'braless', 'brothel', 'callgirl', 'callgirls',
|
'boobies', 'bordello', 'braless', 'brothel', 'callgirl', 'callgirls',
|
||||||
'clit', 'clitoris', 'clits', 'cums', 'cybererotic', 'cybererotica',
|
'clit', 'clitoris', 'clits', 'cums', 'cybererotic', 'cybererotica',
|
||||||
'cybersex', 'cybersexx', 'ejaculation', 'erotica', 'eroticfilm', 'eroticfilms',
|
'cybersex', 'cybersexx', 'ejaculation', 'erotica', 'eroticfilm', 'eroticfilms',
|
||||||
'eroticism', 'eroticphoto', 'eroticphotography', 'eroticphotos', 'erotics', 'eroticsex',
|
'eroticism', 'eroticphoto', 'eroticphotography', 'eroticphotos', 'erotics', 'eroticsex',
|
||||||
'eroticsexstories', 'eroticstories', 'eroticstory', 'erotik', 'erotika', 'antasysex',
|
'eroticsexstories', 'eroticstories', 'eroticstory', 'erotik', 'erotika', 'antasysex',
|
||||||
'gaysex', 'gruppensex', 'horny', 'jackoff', 'lesbo', 'lesbos',
|
'gaysex', 'gruppensex', 'horny', 'jackoff', 'lesbo', 'lesbos',
|
||||||
'makinglove', 'motherfucker', 'horsesex', 'dogsex', 'snakesex', 'sextracker',
|
'makinglove', 'motherfucker', 'horsesex', 'dogsex', 'snakesex', 'sextracker',
|
||||||
'tranny', 'bdsm', 'porn', 'beastality', 'bizarre', 'blowjob',
|
'tranny', 'bdsm', 'porn', 'beastality', 'bizarre', 'blowjob',
|
||||||
'bondage', 'bondages', 'celebs', 'cum', 'cunt', 'transsexual',
|
'bondage', 'bondages', 'celebs', 'cum', 'cunt', 'transsexual',
|
||||||
'transsexuals', 'cumbath', 'cumshot', 'dildo', 'dildos', 'transvestites',
|
'transsexuals', 'cumbath', 'cumshot', 'dildo', 'dildos', 'transvestites',
|
||||||
'transvestite', 'dominatrix', 'spank', 'dungeon', 'sexbilder', 'dungeons',
|
'transvestite', 'dominatrix', 'spank', 'dungeon', 'sexbilder', 'dungeons',
|
||||||
'pussie', 'ebony', 'fisting', 'gayshop', 'facesitting', 'sexshop',
|
'pussie', 'ebony', 'fisting', 'gayshop', 'facesitting', 'sexshop',
|
||||||
'pussy', 'bukkake', 'escort', 'blowjobs', 'facial', 'facialized',
|
'pussy', 'bukkake', 'escort', 'blowjobs', 'facial', 'facialized',
|
||||||
'facials', 'fetish', 'footfetish', 'fuckingpussy', 'fucking', 'hardcore',
|
'facials', 'fetish', 'footfetish', 'fuckingpussy', 'fucking', 'hardcore',
|
||||||
'hentai', 'hustlerlatex', 'latex', 'lolita', 'lolitas', 'mlm',
|
'hentai', 'hustlerlatex', 'latex', 'lolita', 'lolitas', 'mlm',
|
||||||
'oralsex', 'peepshow', 'peepshows', 'phonesex', 'pornstars', 'preteen',
|
'oralsex', 'peepshow', 'peepshows', 'phonesex', 'pornstars', 'preteen',
|
||||||
'preteens', 'pussies', 'shemale', 'shemales', 'sluts', 'whores',
|
'preteens', 'pussies', 'shemale', 'shemales', 'sluts', 'whores',
|
||||||
'whore', 'spanking', 'strapon', 'twinks', 'upskirts', 'voyeur',
|
'whore', 'spanking', 'strapon', 'twinks', 'upskirts', 'voyeur',
|
||||||
'whip', 'whipping', 'xxx', 'sexkey', 'femdom', 'gangbang',
|
'whip', 'whipping', 'xxx', 'sexkey', 'femdom', 'gangbang',
|
||||||
'gloryhole', 'adultbuffet', 'adultcartoons', 'adultchat', 'adultchatnetwork', 'adultdvd',
|
'gloryhole', 'adultbuffet', 'adultcartoons', 'adultchat', 'adultchatnetwork', 'adultdvd',
|
||||||
'adultentertainment', 'adultentertainmenthouse', 'adulterotica', 'adultfilms', 'adultfree', 'adultfreepics',
|
'adultentertainment', 'adultentertainmenthouse', 'adulterotica', 'adultfilms', 'adultfree', 'adultfreepics',
|
||||||
'adultfreepix', 'adultfun', 'adulthardcore', 'adultimages', 'adultjpeg', 'adultlink',
|
'adultfreepix', 'adultfun', 'adulthardcore', 'adultimages', 'adultjpeg', 'adultlink',
|
||||||
'adultlinks', 'adultmovie', 'adultmovies', 'adultmpeg', 'adultmpegs', 'adultpass',
|
'adultlinks', 'adultmovie', 'adultmovies', 'adultmpeg', 'adultmpegs', 'adultpass',
|
||||||
'adultpersonals', 'adultphotos', 'adultpic', 'adultpics', 'adultpicture', 'adultpictures',
|
'adultpersonals', 'adultphotos', 'adultpic', 'adultpics', 'adultpicture', 'adultpictures',
|
||||||
'adultpix', 'adultporn', 'adultpornography', 'adultsearch', 'adultsex', 'adultsights',
|
'adultpix', 'adultporn', 'adultpornography', 'adultsearch', 'adultsex', 'adultsights',
|
||||||
'adultsites', 'adultsonly', 'adultstars', 'adultstories', 'adultvideo', 'adultvideos',
|
'adultsites', 'adultsonly', 'adultstars', 'adultstories', 'adultvideo', 'adultvideos',
|
||||||
'adultweb', 'adultxxx', 'alt.sex', 'altsex', 'alt.sex.exhibitionism', 'alt.sex.pictures',
|
'adultweb', 'adultxxx', 'alt.sex', 'altsex', 'alt.sex.exhibitionism', 'alt.sex.pictures',
|
||||||
'altsexst', 'alt.sex.stories', 'alt.sex.voyeurism', 'amateurerotica', 'amateurfotos', 'amateurhardcore',
|
'altsexst', 'alt.sex.stories', 'alt.sex.voyeurism', 'amateurerotica', 'amateurfotos', 'amateurhardcore',
|
||||||
'amateurindex', 'amateurnaked', 'amateurnudes', 'amateurporn', 'amateurpussy', 'amateursex',
|
'amateurindex', 'amateurnaked', 'amateurnudes', 'amateurporn', 'amateurpussy', 'amateursex',
|
||||||
'amateursxxx', 'amatuerhardcore', 'amatuersex', 'ampland', 'analaction', 'analcum',
|
'amateursxxx', 'amatuerhardcore', 'amatuersex', 'ampland', 'analaction', 'analcum',
|
||||||
'analfuck', 'analfucking', 'analgallery', 'analingus', 'analpics', 'analpicture',
|
'analfuck', 'analfucking', 'analgallery', 'analingus', 'analpics', 'analpicture',
|
||||||
'analsex', 'analsexpics', 'analsexpictures', 'analxxx', 'animalbeastiality', 'animehentai',
|
'analsex', 'analsexpics', 'analsexpictures', 'analxxx', 'animalbeastiality', 'animehentai',
|
||||||
'animeporno', 'animexxx', 'asiacarrera', 'assfuck', 'assfucking', 'asshole',
|
'animeporno', 'animexxx', 'asiacarrera', 'assfuck', 'assfucking', 'asshole',
|
||||||
'assholes', 'asslick', 'asspics', 'assworship', 'autofellatio', 'babepix',
|
'assholes', 'asslick', 'asspics', 'assworship', 'autofellatio', 'babepix',
|
||||||
'badgirls', 'bakedchicks', 'baldcunt', 'baldpussies', 'baldpussy', 'barecelebs',
|
'badgirls', 'bakedchicks', 'baldcunt', 'baldpussies', 'baldpussy', 'barecelebs',
|
||||||
'barenaked', 'barepussy', 'beastiality', 'beaverboy', 'beavershots', 'bigballs',
|
'barenaked', 'barepussy', 'beastiality', 'beaverboy', 'beavershots', 'bigballs',
|
||||||
'bigblackboobs', 'bigblackcocks', 'bigblackdicks', 'bigblacktits', 'bigboob', 'bigboobs',
|
'bigblackboobs', 'bigblackcocks', 'bigblackdicks', 'bigblacktits', 'bigboob', 'bigboobs',
|
||||||
'bigbreast', 'bigbreastlovers', 'bigbreasts', 'bigbutt', 'bigbutts', 'bigclit',
|
'bigbreast', 'bigbreastlovers', 'bigbreasts', 'bigbutt', 'bigbutts', 'bigclit',
|
||||||
'bigclitoris', 'bigclits', 'bigcock', 'bigcocks', 'bigcunt', 'bigcunts',
|
'bigclitoris', 'bigclits', 'bigcock', 'bigcocks', 'bigcunt', 'bigcunts',
|
||||||
'bigdick', 'bigdicks', 'biggestboobs', 'biggestdick', 'biggesttit', 'biggesttits',
|
'bigdick', 'bigdicks', 'biggestboobs', 'biggestdick', 'biggesttit', 'biggesttits',
|
||||||
'bighairyballs', 'bighardons', 'bighooters', 'bignipples', 'bigpussies', 'bigpussy',
|
'bighairyballs', 'bighardons', 'bighooters', 'bignipples', 'bigpussies', 'bigpussy',
|
||||||
'bigtit', 'bigtits', 'bigtitties', 'bigtitts', 'bizarresex', 'bizarrexxx',
|
'bigtit', 'bigtits', 'bigtitties', 'bigtitts', 'bizarresex', 'bizarrexxx',
|
||||||
'bizzaresex', 'blackbondage', 'blackboobs', 'blackbooty', 'blackbutt', 'blackcock',
|
'bizzaresex', 'blackbondage', 'blackboobs', 'blackbooty', 'blackbutt', 'blackcock',
|
||||||
'blackcocks', 'blackcum', 'blackcunt', 'blackcunts', 'blackdick', 'blackdicks',
|
'blackcocks', 'blackcum', 'blackcunt', 'blackcunts', 'blackdick', 'blackdicks',
|
||||||
'blackerotica', 'blackhardcore', 'blacknudes', 'blackonblondes', 'blackporn', 'blackporno',
|
'blackerotica', 'blackhardcore', 'blacknudes', 'blackonblondes', 'blackporn', 'blackporno',
|
||||||
'blackpornography', 'blackpussy', 'blacksex', 'blacksluts', 'blacksonblondes', 'blacktit',
|
'blackpornography', 'blackpussy', 'blacksex', 'blacksluts', 'blacksonblondes', 'blacktit',
|
||||||
'blacktits', 'blacktwat', 'blackxxx', 'blondepussy', 'blondsgay', 'bondagefree',
|
'blacktits', 'blacktwat', 'blackxxx', 'blondepussy', 'blondsgay', 'bondagefree',
|
||||||
'bondagegallery', 'bondagelinks', 'bondagepics', 'bondagepictures', 'bondagesex', 'bondagestories',
|
'bondagegallery', 'bondagelinks', 'bondagepics', 'bondagepictures', 'bondagesex', 'bondagestories',
|
||||||
'bondagestory', 'bukake', 'bustybabes', 'bustyblondes', 'bustyceleb', 'butt-fuck',
|
'bondagestory', 'bukake', 'bustybabes', 'bustyblondes', 'bustyceleb', 'butt-fuck',
|
||||||
'buttfuck', 'buttfucker', 'buttfuckers', 'buttfucking', 'buttholes', 'buttman',
|
'buttfuck', 'buttfucker', 'buttfuckers', 'buttfucking', 'buttholes', 'buttman',
|
||||||
'buttpics', 'buttplug', 'buttthumbnails', 'cartoonporn', 'cartoonsex', 'cartoonsxxx',
|
'buttpics', 'buttplug', 'buttthumbnails', 'cartoonporn', 'cartoonsex', 'cartoonsxxx',
|
||||||
'cartoonxxx', 'celebritiesnaked', 'celebritiesnude', 'celebritiesxxx', 'celebritybush', 'celebritybutts',
|
'cartoonxxx', 'celebritiesnaked', 'celebritiesnude', 'celebritiesxxx', 'celebritybush', 'celebritybutts',
|
||||||
'celebritynude', 'celebritynudes', 'celebrityporn', 'celebritypussy', 'celebritysex', 'celebrityxxx',
|
'celebritynude', 'celebritynudes', 'celebrityporn', 'celebritypussy', 'celebritysex', 'celebrityxxx',
|
||||||
'celebsxxx', 'celebxxx', 'centerfolds', 'chaseylain', 'chatsex', 'cheerleadersxxx',
|
'celebsxxx', 'celebxxx', 'centerfolds', 'chaseylain', 'chatsex', 'cheerleadersxxx',
|
||||||
'cheerleaderxxx', 'chickswithdicks', 'christycanyon', 'cicciolina', 'clitpics', 'clitpictures',
|
'cheerleaderxxx', 'chickswithdicks', 'christycanyon', 'cicciolina', 'clitpics', 'clitpictures',
|
||||||
'closeuppussy', 'comixxx', 'crotchless', 'cruisingforsex', 'cumbaths', 'cumcoveredcunts',
|
'closeuppussy', 'comixxx', 'crotchless', 'cruisingforsex', 'cumbaths', 'cumcoveredcunts',
|
||||||
'cumcunt', 'cumdrinker', 'cumdrinkers', 'cumdrinking', 'cumdrops', 'cumeater',
|
'cumcunt', 'cumdrinker', 'cumdrinkers', 'cumdrinking', 'cumdrops', 'cumeater',
|
||||||
'cumeaters', 'cumeating', 'cumface', 'cumfaces', 'cumfacial', 'cumfacials',
|
'cumeaters', 'cumeating', 'cumface', 'cumfaces', 'cumfacial', 'cumfacials',
|
||||||
'cumgallery', 'cumgargle', 'cumguzzlers', 'cumincunt', 'cumjunkies', 'cumlovers',
|
'cumgallery', 'cumgargle', 'cumguzzlers', 'cumincunt', 'cumjunkies', 'cumlovers',
|
||||||
'cummpeg', 'cumpic', 'cumpics', 'cumpicture', 'cumpictures', 'cumpussy',
|
'cummpeg', 'cumpic', 'cumpics', 'cumpicture', 'cumpictures', 'cumpussy',
|
||||||
'cumsluts', 'cumsucker', 'cumsuckers', 'cumsucking', 'cumswallow', 'cumswallowers',
|
'cumsluts', 'cumsucker', 'cumsuckers', 'cumsucking', 'cumswallow', 'cumswallowers',
|
||||||
'cumswallowing', 'cumtasting', 'cumthumbnails', 'cunilingus', 'cunnilingus', 'cuntcum',
|
'cumswallowing', 'cumtasting', 'cumthumbnails', 'cunilingus', 'cunnilingus', 'cuntcum',
|
||||||
'cuntfuck', 'cuntfucking', 'cuntjuice', 'cuntlapper', 'cuntlick', 'cuntlickers',
|
'cuntfuck', 'cuntfucking', 'cuntjuice', 'cuntlapper', 'cuntlick', 'cuntlickers',
|
||||||
'cuntlicking', 'cuntpics', 'cuntpictures', 'cunts', 'cuntstories', 'cuntsuckers',
|
'cuntlicking', 'cuntpics', 'cuntpictures', 'cunts', 'cuntstories', 'cuntsuckers',
|
||||||
'cuntz', 'cyberlust', 'cybernude', 'cyberporn', 'cyberpornlinks', 'cyberpornsexlinks',
|
'cuntz', 'cyberlust', 'cybernude', 'cyberporn', 'cyberpornlinks', 'cyberpornsexlinks',
|
||||||
'cyberslut', 'd’amateur', 'danniashe', 'dicksex', 'dicksuckers', 'dicksucking',
|
'cyberslut', 'd’amateur', 'danniashe', 'dicksex', 'dicksuckers', 'dicksucking',
|
||||||
'digixxx', 'directporn', 'dirtypictures', 'dirtysex', 'doggiestyle', 'doggystyle',
|
'digixxx', 'directporn', 'dirtypictures', 'dirtysex', 'doggiestyle', 'doggystyle',
|
||||||
'domatrix', 'dominatrixes', 'downblouse', 'drinkingcum', 'drippingcunt', 'drippingcunts',
|
'domatrix', 'dominatrixes', 'downblouse', 'drinkingcum', 'drippingcunt', 'drippingcunts',
|
||||||
'drippingpussy', 'easypic.com', 'eatcum', 'eatingcum', 'eatingpussy', 'eatpussy',
|
'drippingpussy', 'easypic.com', 'eatcum', 'eatingcum', 'eatingpussy', 'eatpussy',
|
||||||
'ebony+ayres', 'ebonyporn', 'ebonypussy', 'ebonysex', 'ebonyxxx', 'enormoustits',
|
'ebony+ayres', 'ebonyporn', 'ebonypussy', 'ebonysex', 'ebonyxxx', 'enormoustits',
|
||||||
'erosvillage', 'eroticanime', 'eroticart', 'eroticas', 'eroticastories', 'eroticfiction',
|
'erosvillage', 'eroticanime', 'eroticart', 'eroticas', 'eroticastories', 'eroticfiction',
|
||||||
'eroticlesbianstories', 'eroticmovie', 'eroticmovies', 'erotico', 'eroticos', 'eroticpics',
|
'eroticlesbianstories', 'eroticmovie', 'eroticmovies', 'erotico', 'eroticos', 'eroticpics',
|
||||||
'eroticpicture', 'eroticpictures', 'eroticsites', 'eroticsounds', 'erotictales', 'erotictext',
|
'eroticpicture', 'eroticpictures', 'eroticsites', 'eroticsounds', 'erotictales', 'erotictext',
|
||||||
'eroticvideo', 'eroticvideos', 'eroticwomen', 'eroticwriting', 'erotikchat', 'erotique',
|
'eroticvideo', 'eroticvideos', 'eroticwomen', 'eroticwriting', 'erotikchat', 'erotique',
|
||||||
'erotismo', 'escortservice', 'escortservices', 'eurosex', 'explicitsex', 'facecum',
|
'erotismo', 'escortservice', 'escortservices', 'eurosex', 'explicitsex', 'facecum',
|
||||||
'facesit', 'facesitters', 'fastporn', 'fatass', 'fatsex', 'feetfetish',
|
'facesit', 'facesitters', 'fastporn', 'fatass', 'fatsex', 'feetfetish',
|
||||||
'feetsex', 'felatio', 'fellatio', 'fellations', 'fetishwear', 'fettegirls',
|
'feetsex', 'felatio', 'fellatio', 'fellations', 'fetishwear', 'fettegirls',
|
||||||
'fingerbang', 'fingerfuck', 'flesh4free', 'footjobs', 'footlicking', 'footworship',
|
'fingerbang', 'fingerfuck', 'flesh4free', 'footjobs', 'footlicking', 'footworship',
|
||||||
'fornication', 'freeanal', 'freeanalsex', 'freeass', 'freebigboobs', 'freebigtit',
|
'fornication', 'freeanal', 'freeanalsex', 'freeass', 'freebigboobs', 'freebigtit',
|
||||||
'freebigtits', 'freeblackcunt', 'freeblackpussy', 'freeblowjob', 'freeblowjobs', 'freebondage',
|
'freebigtits', 'freeblackcunt', 'freeblackpussy', 'freeblowjob', 'freeblowjobs', 'freebondage',
|
||||||
'freeboobs', 'freecum', 'freecumshot', 'freecumshots', 'freecunt', 'freecunts',
|
'freeboobs', 'freecum', 'freecumshot', 'freecumshots', 'freecunt', 'freecunts',
|
||||||
'freedick', 'freeerotic', 'freeerotica', 'freeeroticstories', 'freefuck', 'freefucking',
|
'freedick', 'freeerotic', 'freeerotica', 'freeeroticstories', 'freefuck', 'freefucking',
|
||||||
'freefuckpics', 'freegay', 'freegaypics', 'freehardcore', 'freehardcorepics', 'freehardcorepictures',
|
'freefuckpics', 'freegay', 'freegaypics', 'freehardcore', 'freehardcorepics', 'freehardcorepictures',
|
||||||
'freehardcoreporn', 'freehardcoresex', 'freehardcoresexpics', 'freehentai', 'freehooters', 'freelargehooters',
|
'freehardcoreporn', 'freehardcoresex', 'freehardcoresexpics', 'freehentai', 'freehooters', 'freelargehooters',
|
||||||
'freelesbian', 'freelesbianporn', 'freelesbiansex', 'freenakedpic', 'freenakedpics', 'freenakedpictures',
|
'freelesbian', 'freelesbianporn', 'freelesbiansex', 'freenakedpic', 'freenakedpics', 'freenakedpictures',
|
||||||
'freenakedwomen', 'freenude', 'freenudecelebs', 'freenudephotos', 'freenudepics', 'freenudes',
|
'freenakedwomen', 'freenude', 'freenudecelebs', 'freenudephotos', 'freenudepics', 'freenudes',
|
||||||
'freeporn', 'freepornmovies', 'freeporno', 'freepornography', 'freepornopics', 'freepornopictures',
|
'freeporn', 'freepornmovies', 'freeporno', 'freepornography', 'freepornopics', 'freepornopictures',
|
||||||
'freepornos', 'freepornpic', 'freepornpics', 'freepornpictures', 'freeporns', 'freepornsite',
|
'freepornos', 'freepornpic', 'freepornpics', 'freepornpictures', 'freeporns', 'freepornsite',
|
||||||
'freepornsites', 'freepussy', 'freepussypic', 'freepussypics', 'freepussypictures', 'freesex',
|
'freepornsites', 'freepussy', 'freepussypic', 'freepussypics', 'freepussypictures', 'freesex',
|
||||||
'freesexchat', 'freesexmovies', 'freesexnet', 'freesexphotos', 'freesexpic', 'freesexpics',
|
'freesexchat', 'freesexmovies', 'freesexnet', 'freesexphotos', 'freesexpic', 'freesexpics',
|
||||||
'freesexpicture', 'freesexpictures', 'freesexsites', 'freesexstories', 'freesexvideos', 'freesexycam',
|
'freesexpicture', 'freesexpictures', 'freesexsites', 'freesexstories', 'freesexvideos', 'freesexycam',
|
||||||
'freeshemale', 'freesmut', 'freetit', 'freetits', 'freevoyeur', 'freexxx',
|
'freeshemale', 'freesmut', 'freetit', 'freetits', 'freevoyeur', 'freexxx',
|
||||||
'freexxxmovie', 'freexxxmovies', 'freexxxmpeg', 'freexxxphotos', 'freexxxpic', 'freexxxpics',
|
'freexxxmovie', 'freexxxmovies', 'freexxxmpeg', 'freexxxphotos', 'freexxxpic', 'freexxxpics',
|
||||||
'freexxxpicture', 'freexxxpictures', 'freexxxstories', 'freexxxvideo', 'freexxxx', 'fuking',
|
'freexxxpicture', 'freexxxpictures', 'freexxxstories', 'freexxxvideo', 'freexxxx', 'fuking',
|
||||||
'gangbangs', 'gratishardcoregalerie', 'hardcorecelebs', 'hardcorefisting', 'hardcorefree', 'hardcorefucking',
|
'gangbangs', 'gratishardcoregalerie', 'hardcorecelebs', 'hardcorefisting', 'hardcorefree', 'hardcorefucking',
|
||||||
'hardcorehooters', 'hardcorejunkie', 'hardcorejunky', 'hardcoremovie', 'hardcoremovies', 'hardcorepic',
|
'hardcorehooters', 'hardcorejunkie', 'hardcorejunky', 'hardcoremovie', 'hardcoremovies', 'hardcorepic',
|
||||||
'hardcorepics', 'hardcorepictures', 'hardcorepix', 'hardcoreporn', 'hardcoreporno', 'hardcorepornography',
|
'hardcorepics', 'hardcorepictures', 'hardcorepix', 'hardcoreporn', 'hardcoreporno', 'hardcorepornography',
|
||||||
'hardcorepornos', 'hardcorepussy', 'hardcoresamples', 'hardcoresex', 'hardcoresexpictures', 'hardcorestories',
|
'hardcorepornos', 'hardcorepussy', 'hardcoresamples', 'hardcoresex', 'hardcoresexpictures', 'hardcorestories',
|
||||||
'hardcorethumbnails', 'hardcorevideo', 'hardcorevideos', 'hardcorexxx', 'harddicks', 'hardnipples',
|
'hardcorethumbnails', 'hardcorevideo', 'hardcorevideos', 'hardcorexxx', 'harddicks', 'hardnipples',
|
||||||
'hardons', 'hardporn', 'indiasex', 'interacialhardcore', 'interacialsex', 'interacialxxx',
|
'hardons', 'hardporn', 'indiasex', 'interacialhardcore', 'interacialsex', 'interacialxxx',
|
||||||
'intercoursepositions', 'internetsex', 'interracialfucking', 'interracialhardcore', 'interracialporn', 'interracialpornography',
|
'intercoursepositions', 'internetsex', 'interracialfucking', 'interracialhardcore', 'interracialporn', 'interracialpornography',
|
||||||
'interracialsex', 'interracialsexstories', 'interracialxxx', 'intimatesex', 'ittybittytitty', 'japaneseporn',
|
'interracialsex', 'interracialsexstories', 'interracialxxx', 'intimatesex', 'ittybittytitty', 'japaneseporn',
|
||||||
'japanesesex', 'japansex', 'japanxxx', 'jennacam.com', 'jennajameson', 'jennicam',
|
'japanesesex', 'japansex', 'japanxxx', 'jennacam.com', 'jennajameson', 'jennicam',
|
||||||
'jerkoff', 'jism', 'jiz', 'jizz', 'juicycunts', 'juicypussy',
|
'jerkoff', 'jism', 'jiz', 'jizz', 'juicycunts', 'juicypussy',
|
||||||
'justhardcore', 'karasamateurs', 'karasxxx', 'kascha', 'kaylakleevage', 'kobetai',
|
'justhardcore', 'karasamateurs', 'karasxxx', 'kascha', 'kaylakleevage', 'kobetai',
|
||||||
'koreasex', 'lapdance', 'largeclits', 'largecunts', 'largedicks', 'largehooters',
|
'koreasex', 'lapdance', 'largeclits', 'largecunts', 'largedicks', 'largehooters',
|
||||||
'largepussy', 'largetit', 'largetits', 'latinapussy', 'latinasex', 'latinosex',
|
'largepussy', 'largetit', 'largetits', 'latinapussy', 'latinasex', 'latinosex',
|
||||||
'latinoxxx', 'latinxxx', 'legsex', 'lesbianerotica', 'lesbianhardcore', 'lesbianorgies',
|
'latinoxxx', 'latinxxx', 'legsex', 'lesbianerotica', 'lesbianhardcore', 'lesbianorgies',
|
||||||
'lesbianorgy', 'lesbianpics', 'lesbianpink', 'lesbianporn', 'lesbian-porno', 'lesbianporno',
|
'lesbianorgy', 'lesbianpics', 'lesbianpink', 'lesbianporn', 'lesbian-porno', 'lesbianporno',
|
||||||
'lesbianpornography', 'lesbianpornos', 'lesbianpussy', 'lesbiansex', 'lesbiansexpics', 'lesbiansexstories',
|
'lesbianpornography', 'lesbianpornos', 'lesbianpussy', 'lesbiansex', 'lesbiansexpics', 'lesbiansexstories',
|
||||||
'lesbianxxx', 'lickadick', 'lickingpussy', 'lindalovelace', 'lingeriexxx', 'literotica',
|
'lesbianxxx', 'lickadick', 'lickingpussy', 'lindalovelace', 'lingeriexxx', 'literotica',
|
||||||
'littleboobs', 'littlepussy', 'littletits', 'livefucking', 'liveporn', 'livesex',
|
'littleboobs', 'littlepussy', 'littletits', 'livefucking', 'liveporn', 'livesex',
|
||||||
'livesexcam', 'livesexcams', 'longdicks', 'lovedoll', 'lovedolls', 'magazinessex',
|
'livesexcam', 'livesexcams', 'longdicks', 'lovedoll', 'lovedolls', 'magazinessex',
|
||||||
'makinglove', 'malaysex', 'malenudes', 'malesex', 'mangaporno', 'mangax',
|
'makinglove', 'malaysex', 'malenudes', 'malesex', 'mangaporno', 'mangax',
|
||||||
'mangaxxx', 'manpics', 'mansex', 'marilynchambers', 'massivecocks', 'masterbating',
|
'mangaxxx', 'manpics', 'mansex', 'marilynchambers', 'massivecocks', 'masterbating',
|
||||||
'masturbation', 'masturbationvideos', 'maturefucking', 'maturesex', 'maturexxx', 'megaboobs',
|
'masturbation', 'masturbationvideos', 'maturefucking', 'maturesex', 'maturexxx', 'megaboobs',
|
||||||
'megaporno', 'megapussy', 'megatits', 'mensdicks', 'mensex', 'm.i.l.f.',
|
'megaporno', 'megapussy', 'megatits', 'mensdicks', 'mensex', 'm.i.l.f.',
|
||||||
'milf', 'milfhunterpic', 'milfmpegsample', 'modelsex', 'mondoporn', 'monstercocks',
|
'milf', 'milfhunterpic', 'milfmpegsample', 'modelsex', 'mondoporn', 'monstercocks',
|
||||||
'monsterdicks', 'motherfucker', 'moviepost.com', 'mpegsex', 'mpegxxx', 'muffdiving',
|
'monsterdicks', 'motherfucker', 'moviepost.com', 'mpegsex', 'mpegxxx', 'muffdiving',
|
||||||
'myslutwife', 'nacktfotos', 'nakedbabes', 'nakedblackwomen', 'nakedcelebrity', 'nakedcelebs',
|
'myslutwife', 'nacktfotos', 'nakedbabes', 'nakedblackwomen', 'nakedcelebrity', 'nakedcelebs',
|
||||||
'nakedcheerleader', 'nakedchicks', 'nakedgirls', 'nakedguys', 'nakedladies', 'nakedlady',
|
'nakedcheerleader', 'nakedchicks', 'nakedgirls', 'nakedguys', 'nakedladies', 'nakedlady',
|
||||||
'nakedman', 'nakedmen', 'nakedness', 'nakedphotographs', 'nakedphotography', 'nakedphotos',
|
'nakedman', 'nakedmen', 'nakedness', 'nakedphotographs', 'nakedphotography', 'nakedphotos',
|
||||||
'nakedpic', 'nakedpics', 'nakedpicture', 'nakedpictures', 'nakedpussy', 'nakedstars',
|
'nakedpic', 'nakedpics', 'nakedpicture', 'nakedpictures', 'nakedpussy', 'nakedstars',
|
||||||
'nakedwife', 'nakedwoman', 'nakedwomen', 'nastychat', 'nastypussy', 'nastysex',
|
'nakedwife', 'nakedwoman', 'nakedwomen', 'nastychat', 'nastypussy', 'nastysex',
|
||||||
'nastythumbs', 'naturaltits', 'naughty.com', 'naughtylinks', 'naughtylinx', 'naughtylynx',
|
'nastythumbs', 'naturaltits', 'naughty.com', 'naughtylinks', 'naughtylinx', 'naughtylynx',
|
||||||
'naughtynurses', 'netsex', 'niceass', 'nicetits', 'nikkinova', 'nikkityler',
|
'naughtynurses', 'netsex', 'niceass', 'nicetits', 'nikkinova', 'nikkityler',
|
||||||
'nipples', 'nookie', 'nookies', 'nudeactress', 'nudeactresses', 'nudeamateur',
|
'nipples', 'nookie', 'nookies', 'nudeactress', 'nudeactresses', 'nudeamateur',
|
||||||
'nudeamateurs', 'nudeasianwomen', 'nudebabes', 'nudebigboobs', 'nudeblack', 'nudeblackwomen',
|
'nudeamateurs', 'nudeasianwomen', 'nudebabes', 'nudebigboobs', 'nudeblack', 'nudeblackwomen',
|
||||||
'nudeblondes', 'nudeceleb', 'nudeceleberties', 'nudecelebraties', 'nudecelebrites', 'nudecelebrities',
|
'nudeblondes', 'nudeceleb', 'nudeceleberties', 'nudecelebraties', 'nudecelebrites', 'nudecelebrities',
|
||||||
'nudecelebrity', 'nudecelebs', 'nudecollegegirls', 'nudefemale', 'nudefemales', 'nudefree',
|
'nudecelebrity', 'nudecelebs', 'nudecollegegirls', 'nudefemale', 'nudefemales', 'nudefree',
|
||||||
'nudegay', 'nudeimages', 'nudeladies', 'nudelesbians', 'nudemale', 'nudemales',
|
'nudegay', 'nudeimages', 'nudeladies', 'nudelesbians', 'nudemale', 'nudemales',
|
||||||
'nudeman', 'nudemen', 'nudepic', 'nudepics', 'nudepicture', 'nudepictures',
|
'nudeman', 'nudemen', 'nudepic', 'nudepics', 'nudepicture', 'nudepictures',
|
||||||
'nudepornography', 'nudepussy', 'nuderaider', 'nuderedheads', 'nudes', 'nudesex',
|
'nudepornography', 'nudepussy', 'nuderaider', 'nuderedheads', 'nudes', 'nudesex',
|
||||||
'nudestar', 'nudestars', 'nudevideoconferencing', 'nudewoman', 'nudewomen', 'nudism',
|
'nudestar', 'nudestars', 'nudevideoconferencing', 'nudewoman', 'nudewomen', 'nudism',
|
||||||
'nudist', 'nudists', 'nudity', 'nylonfetish', 'nylonsex', 'nympho',
|
'nudist', 'nudists', 'nudity', 'nylonfetish', 'nylonsex', 'nympho',
|
||||||
'nymphos', 'olderbabes', 'oldersex', 'oldersluts', 'oldpussy', 'oldsex',
|
'nymphos', 'olderbabes', 'oldersex', 'oldersluts', 'oldpussy', 'oldsex',
|
||||||
'oldsluts', 'openlegs', 'openpussy', 'oral4free', 'oral-sex', 'oralsexpictures',
|
'oldsluts', 'openlegs', 'openpussy', 'oral4free', 'oral-sex', 'oralsexpictures',
|
||||||
'orgie', 'orgies', 'orgypics', 'orgys', 'pantyhosefetish', 'pantyhosesex',
|
'orgie', 'orgies', 'orgypics', 'orgys', 'pantyhosefetish', 'pantyhosesex',
|
||||||
'peepcam', 'persiankitty', 'persiankitty.com', 'perverted', 'picsxxx', 'picturesex',
|
'peepcam', 'persiankitty', 'persiankitty.com', 'perverted', 'picsxxx', 'picturesex',
|
||||||
'picturesofsex', 'picturessex', 'pimpserver', 'pimpserver.com', 'pinkpussy', 'pissing',
|
'picturesofsex', 'picturessex', 'pimpserver', 'pimpserver.com', 'pinkpussy', 'pissing',
|
||||||
'pixxx', 'poontang', 'pornagraphy', 'porncast', 'porncity', 'porndirectory',
|
'pixxx', 'poontang', 'pornagraphy', 'porncast', 'porncity', 'porndirectory',
|
||||||
'porne', 'pornfree', 'pornmovies', 'pornno', 'pornnude', 'porno',
|
'porne', 'pornfree', 'pornmovies', 'pornno', 'pornnude', 'porno',
|
||||||
'pornoadult', 'pornocartoons', 'pornochat', 'pornodeluxe', 'pornoe', 'pornofilms',
|
'pornoadult', 'pornocartoons', 'pornochat', 'pornodeluxe', 'pornoe', 'pornofilms',
|
||||||
'pornofree', 'pornogame', 'pornografi', 'pornografia', 'pornografie', 'pornografy',
|
'pornofree', 'pornogame', 'pornografi', 'pornografia', 'pornografie', 'pornografy',
|
||||||
'pornograph', 'pornographi', 'pornographia', 'pornographic', 'pornographicpictures', 'pornographics',
|
'pornograph', 'pornographi', 'pornographia', 'pornographic', 'pornographicpictures', 'pornographics',
|
||||||
'pornographicvideo', 'pornographicvideos', 'pornographie', 'pornography', 'pornographyfree', 'pornographyphotos',
|
'pornographicvideo', 'pornographicvideos', 'pornographie', 'pornography', 'pornographyfree', 'pornographyphotos',
|
||||||
'pornographypictures', 'pornography-sex', 'pornographysex', 'pornoland', 'pornolinks', 'pornolynx',
|
'pornographypictures', 'pornography-sex', 'pornographysex', 'pornoland', 'pornolinks', 'pornolynx',
|
||||||
'pornomagazines', 'pornomovies', 'pornompeg', 'pornophotos', 'pornopic', 'pornopics',
|
'pornomagazines', 'pornomovies', 'pornompeg', 'pornophotos', 'pornopic', 'pornopics',
|
||||||
'pornopicture', 'pornopictures', 'pornos', 'pornosex', 'pornosite', 'pornosites',
|
'pornopicture', 'pornopictures', 'pornos', 'pornosex', 'pornosite', 'pornosites',
|
||||||
'pornostar', 'pornostories', 'pornovideo', 'pornovideos', 'pornoxxx', 'pornphotos',
|
'pornostar', 'pornostories', 'pornovideo', 'pornovideos', 'pornoxxx', 'pornphotos',
|
||||||
'pornpics', 'pornpictures', 'pornpix', 'pornpost', 'pornqueens', 'pornrated',
|
'pornpics', 'pornpictures', 'pornpix', 'pornpost', 'pornqueens', 'pornrated',
|
||||||
'porns', 'pornsex', 'pornstar', 'pornstories', 'porntrack', 'pornvideo',
|
'porns', 'pornsex', 'pornstar', 'pornstories', 'porntrack', 'pornvideo',
|
||||||
'pornvideos', 'pornypics', 'porstars', 'privatesex', 'privatex', 'privatexx',
|
'pornvideos', 'pornypics', 'porstars', 'privatesex', 'privatex', 'privatexx',
|
||||||
'privatexxx', 'prono', 'pronography', 'publicnudity', 'puffynipples', 'purple+passion',
|
'privatexxx', 'prono', 'pronography', 'publicnudity', 'puffynipples', 'purple+passion',
|
||||||
'pussyboard', 'pussycam', 'pussycams', 'pussycloseup', 'pussycloseups', 'pussycum',
|
'pussyboard', 'pussycam', 'pussycams', 'pussycloseup', 'pussycloseups', 'pussycum',
|
||||||
'pussycunt', 'pussyeater', 'pussyeaters', 'pussyeating', 'pussyfuck', 'pussyfucking',
|
'pussycunt', 'pussyeater', 'pussyeaters', 'pussyeating', 'pussyfuck', 'pussyfucking',
|
||||||
'pussyhair', 'pussyheaven', 'pussyjuice', 'pussylickers', 'pussylicking', 'pussylink',
|
'pussyhair', 'pussyheaven', 'pussyjuice', 'pussylickers', 'pussylicking', 'pussylink',
|
||||||
'pussylips', 'pussyphotos', 'pussyporno', 'pussys', 'pussysex', 'pussyshots',
|
'pussylips', 'pussyphotos', 'pussyporno', 'pussys', 'pussysex', 'pussyshots',
|
||||||
'pussythumbnails', 'pussytits', 'pusy', 'racqueldarrian', 'rape', 'rawlinks',
|
'pussythumbnails', 'pussytits', 'pusy', 'racqueldarrian', 'rape', 'rawlinks',
|
||||||
'rawpussy', 'rawsex', 'realhardcore', 'realsex', 'redneckporn', 'redpussy',
|
'rawpussy', 'rawsex', 'realhardcore', 'realsex', 'redneckporn', 'redpussy',
|
||||||
'rubberfetish', 'russianxxx', 'scat', 'schiffernude', 'seka', 'seniorsex',
|
'rubberfetish', 'russianxxx', 'scat', 'schiffernude', 'seka', 'seniorsex',
|
||||||
'sex4free', 'sex66', 'sexacts', 'sexadult', 'sexaids', 'sexamateur',
|
'sex4free', 'sex66', 'sexacts', 'sexadult', 'sexaids', 'sexamateur',
|
||||||
'sexanal', 'sexandpictures', 'sexaphone', 'sexaudio', 'sexavi', 'sexbondage',
|
'sexanal', 'sexandpictures', 'sexaphone', 'sexaudio', 'sexavi', 'sexbondage',
|
||||||
'sexboner', 'sexbuttfucker', 'sexcam', 'sexcams', 'sexchat', 'sexchatrooms',
|
'sexboner', 'sexbuttfucker', 'sexcam', 'sexcams', 'sexchat', 'sexchatrooms',
|
||||||
'sexcites', 'sexclub', 'sexclubs', 'sex.com', 'sexdating', 'sexe',
|
'sexcites', 'sexclub', 'sexclubs', 'sex.com', 'sexdating', 'sexe',
|
||||||
'sexfantasies', 'sexfantasy', 'sexfilm', 'sexgallery', 'sexgame', 'sexgames',
|
'sexfantasies', 'sexfantasy', 'sexfilm', 'sexgallery', 'sexgame', 'sexgames',
|
||||||
'sexgirl', 'sexgirls', 'sexgroup', 'sexguide', 'sexhardcore', 'sexhphoto',
|
'sexgirl', 'sexgirls', 'sexgroup', 'sexguide', 'sexhardcore', 'sexhphoto',
|
||||||
'sexhungry', 'sexhungryjoe', 'sexhungryjoes', 'sexi', 'seximages', 'sexis',
|
'sexhungry', 'sexhungryjoe', 'sexhungryjoes', 'sexi', 'seximages', 'sexis',
|
||||||
'sexjapan', 'sex.jpg', 'sexlinda', 'sexlinks', 'sexlinx', 'sexlive',
|
'sexjapan', 'sex.jpg', 'sexlinda', 'sexlinks', 'sexlinx', 'sexlive',
|
||||||
'sexmagazine', 'sexmagazines', 'sexmature', 'sexmelayu', 'sexmodels', 'sexmovie',
|
'sexmagazine', 'sexmagazines', 'sexmature', 'sexmelayu', 'sexmodels', 'sexmovie',
|
||||||
'sexmovies', 'sexmpeg', 'sexnude', 'sexnudity', 'sexo', 'sexoanal',
|
'sexmovies', 'sexmpeg', 'sexnude', 'sexnudity', 'sexo', 'sexoanal',
|
||||||
'sexole', 'sexontheinternet', 'sexoral', 'sexpasswords', 'sexphoto', 'sexphotos',
|
'sexole', 'sexontheinternet', 'sexoral', 'sexpasswords', 'sexphoto', 'sexphotos',
|
||||||
'sexpic', 'sexpicnet', 'sexpics', 'sexpicture', 'sexpictures', 'sexpicturesfree',
|
'sexpic', 'sexpicnet', 'sexpics', 'sexpicture', 'sexpictures', 'sexpicturesfree',
|
||||||
'sexpix', 'sexplaza', 'sexporn', 'sexporno', 'sexpositions', 'sexpussy',
|
'sexpix', 'sexplaza', 'sexporn', 'sexporno', 'sexpositions', 'sexpussy',
|
||||||
'sexroulette', 'sexs', 'sexsamples', 'sexsearch', 'sexsex', 'sexsexsex',
|
'sexroulette', 'sexs', 'sexsamples', 'sexsearch', 'sexsex', 'sexsexsex',
|
||||||
'sexshare', 'sexshops', 'sexshow', 'sexshows', 'sexsite', 'sexsites',
|
'sexshare', 'sexshops', 'sexshow', 'sexshows', 'sexsite', 'sexsites',
|
||||||
'sexslave', 'sexsound', 'sexsounds', 'sexsource', 'sexspaces', 'sexspaces.com',
|
'sexslave', 'sexsound', 'sexsounds', 'sexsource', 'sexspaces', 'sexspaces.com',
|
||||||
'sexstories', 'sexstory', 'sexstorys', 'sextalk', 'sexteen', 'sexthumbnails',
|
'sexstories', 'sexstory', 'sexstorys', 'sextalk', 'sexteen', 'sexthumbnails',
|
||||||
'sex-toons', 'sextoons', 'sextour', 'sextoy', 'sextoys', 'sextpus',
|
'sex-toons', 'sextoons', 'sextour', 'sextoy', 'sextoys', 'sextpus',
|
||||||
'sextracker.com', 'sextropolis', 'sexualbondage', 'sexualfantasies', 'sexualfantasy', 'sexualintercourse',
|
'sextracker.com', 'sextropolis', 'sexualbondage', 'sexualfantasies', 'sexualfantasy', 'sexualintercourse',
|
||||||
'sexualpictures', 'sexualpleasure', 'sexualpositions', 'sexuncensored', 'sexvideo', 'sexvision',
|
'sexualpictures', 'sexualpleasure', 'sexualpositions', 'sexuncensored', 'sexvideo', 'sexvision',
|
||||||
'sexvote', 'sexwomen', 'sexworld', 'sexx', 'sexxx', 'sexxxx',
|
'sexvote', 'sexwomen', 'sexworld', 'sexx', 'sexxx', 'sexxxx',
|
||||||
'sexxxxx', 'sexyamateurs', 'sexybabes', 'sexyblack', 'sexyboobs', 'sexybookmark',
|
'sexxxxx', 'sexyamateurs', 'sexybabes', 'sexyblack', 'sexyboobs', 'sexybookmark',
|
||||||
'sexybookmarka', 'sexybookmarks', 'sexybutts', 'sexycunts', 'sexygirl', 'sexygirls',
|
'sexybookmarka', 'sexybookmarks', 'sexybutts', 'sexycunts', 'sexygirl', 'sexygirls',
|
||||||
'sexyladies', 'sexylady', 'sexylegs', 'sexylingerie', 'sexymen', 'sexyphotos',
|
'sexyladies', 'sexylady', 'sexylegs', 'sexylingerie', 'sexymen', 'sexyphotos',
|
||||||
'sexypics', 'sexypictures', 'sexypost', 'sexypussies', 'sexypussy', 'sexysites',
|
'sexypics', 'sexypictures', 'sexypost', 'sexypussies', 'sexypussy', 'sexysites',
|
||||||
'sexystories', 'sexywoman', 'sexywomen', 'shavedcunt', 'shavedcunts', 'shavedpussies',
|
'sexystories', 'sexywoman', 'sexywomen', 'shavedcunt', 'shavedcunts', 'shavedpussies',
|
||||||
'shavedpussy', 'shavedpussypics', 'shavedsluts', 'shavedwomen', 'shavenpussies', 'shavenpussy',
|
'shavedpussy', 'shavedpussypics', 'shavedsluts', 'shavedwomen', 'shavenpussies', 'shavenpussy',
|
||||||
'shavepussy', 'sheboy', 'she-male', 'shemale+video', 'shemaleyum', 'showcam',
|
'shavepussy', 'sheboy', 'she-male', 'shemale+video', 'shemaleyum', 'showcam',
|
||||||
'showcams', 'showercam', 'showercams', 'slavesex', 'smallboobs', 'smallbreasts',
|
'showcams', 'showercam', 'showercams', 'slavesex', 'smallboobs', 'smallbreasts',
|
||||||
'smalldicks', 'smallpussy', 'smalltits', 'smut', 'smut69', 'smutland',
|
'smalldicks', 'smallpussy', 'smalltits', 'smut', 'smut69', 'smutland',
|
||||||
'smutserver', 'smutshack', 'softcore', 'softporn', 'softpornography', 'spankingpage',
|
'smutserver', 'smutshack', 'softcore', 'softporn', 'softpornography', 'spankingpage',
|
||||||
'spreadpussy', 'spycamadult', 'stockingsex', 'storieserotic', 'storiessex', 'straightsex',
|
'spreadpussy', 'spycamadult', 'stockingsex', 'storieserotic', 'storiessex', 'straightsex',
|
||||||
'stretchedcunt', 'stripclub', 'stripclubs', 'stripshow', 'striptease', 'strokeit',
|
'stretchedcunt', 'stripclub', 'stripclubs', 'stripshow', 'striptease', 'strokeit',
|
||||||
'strokeme', 'suckdick', 'sucksex', 'superchicken', 'supersex', 'supertits',
|
'strokeme', 'suckdick', 'sucksex', 'superchicken', 'supersex', 'supertits',
|
||||||
'swallowcum', 'swinger', 'swingerclub', 'swingers', 'swollenclits', 'syberporn',
|
'swallowcum', 'swinger', 'swingerclub', 'swingers', 'swollenclits', 'syberporn',
|
||||||
'sylviasaint', 'teenanal', 'teenanalsex', 'teenhardcore', 'teenie', 'teenies',
|
'sylviasaint', 'teenanal', 'teenanalsex', 'teenhardcore', 'teenie', 'teenies',
|
||||||
'teennude', 'teenpics', 'teenporn', 'teenporno', 'teenpussy', 'teensex',
|
'teennude', 'teenpics', 'teenporn', 'teenporno', 'teenpussy', 'teensex',
|
||||||
'teenslut', 'teensluts', 'teensuck', 'teenxxx', 'tgp', 'thaipussy',
|
'teenslut', 'teensluts', 'teensuck', 'teenxxx', 'tgp', 'thaipussy',
|
||||||
'thaisex', 'thehun', 'threesomes', 'thumblords', 'thumbnailssex', 'thumbzilla',
|
'thaisex', 'thehun', 'threesomes', 'thumblords', 'thumbnailssex', 'thumbzilla',
|
||||||
'tiffanytowers', 'tightcunt', 'tightpussies', 'tightpussy', 'tinypussy', 'tinytits',
|
'tiffanytowers', 'tightcunt', 'tightpussies', 'tightpussy', 'tinypussy', 'tinytits',
|
||||||
'tinytitties', 'tisandass', 'tit', 'titbondage', 'titfuck', 'titfucking',
|
'tinytitties', 'tisandass', 'tit', 'titbondage', 'titfuck', 'titfucking',
|
||||||
'tities', 'titman', 'titsandass', 'titsass', 'titties', 'titts',
|
'tities', 'titman', 'titsandass', 'titsass', 'titties', 'titts',
|
||||||
'titty', 'tittyfuck', 'tittyfucking', 'tittys', 'tokyotopless', 'tommysbookmark',
|
'titty', 'tittyfuck', 'tittyfucking', 'tittys', 'tokyotopless', 'tommysbookmark',
|
||||||
'toplesswomen', 'trannies', 'transexual', 'transsexuels', 'twat', 'twats',
|
'toplesswomen', 'trannies', 'transexual', 'transsexuels', 'twat', 'twats',
|
||||||
'twink', 'ultradonkey', 'ultrahardcore', 'uncutcocks', 'vaginalintercourse', 'vaginapictures',
|
'twink', 'ultradonkey', 'ultrahardcore', 'uncutcocks', 'vaginalintercourse', 'vaginapictures',
|
||||||
'videoporno', 'videosex', 'videoxxx', 'vintageporn', 'virtualsex', 'vividtv',
|
'videoporno', 'videosex', 'videoxxx', 'vintageporn', 'virtualsex', 'vividtv',
|
||||||
'wank', 'wankers', 'wanking', 'wendywhoppers', 'wetcunt', 'wetcunts',
|
'wank', 'wankers', 'wanking', 'wendywhoppers', 'wetcunt', 'wetcunts',
|
||||||
'wetdick', 'wetpanties', 'wetpussies', 'wetpussy', 'wetsex', 'wetvagina',
|
'wetdick', 'wetpanties', 'wetpussies', 'wetpussy', 'wetsex', 'wetvagina',
|
||||||
'whitepussy', 'whitesex', 'whitetits', 'whitexxx', 'wifesharing', 'wifeswapping',
|
'whitepussy', 'whitesex', 'whitetits', 'whitexxx', 'wifesharing', 'wifeswapping',
|
||||||
'wildpussy', 'wildsex', 'womensex', 'worldsex', 'worldsexguide', 'x-rated',
|
'wildpussy', 'wildsex', 'womensex', 'worldsex', 'worldsexguide', 'x-rated',
|
||||||
'xrated', 'x-ratedmovie', 'x-ratedmovies', 'x-ratedvideo', 'x-ratedvideos', 'xxx4free',
|
'xrated', 'x-ratedmovie', 'x-ratedmovies', 'x-ratedvideo', 'x-ratedvideos', 'xxx4free',
|
||||||
'xxxadult', 'xxxadultmovies', 'xxxadultvideo', 'xxxadultvideos', 'xxxbabes', 'xxxcam',
|
'xxxadult', 'xxxadultmovies', 'xxxadultvideo', 'xxxadultvideos', 'xxxbabes', 'xxxcam',
|
||||||
'xxxcelebrities', 'xxxfree', 'xxxfreepics', 'xxxgalleries', 'xxxhardcore', 'xxxjapan',
|
'xxxcelebrities', 'xxxfree', 'xxxfreepics', 'xxxgalleries', 'xxxhardcore', 'xxxjapan',
|
||||||
'xxxlinks', 'xxxmodels', 'xxxmovie', 'xxxmovies', 'xxxmpeg', 'xxxpassword',
|
'xxxlinks', 'xxxmodels', 'xxxmovie', 'xxxmovies', 'xxxmpeg', 'xxxpassword',
|
||||||
'xxxphoto', 'xxxphotos', 'xxxpic', 'xxx-pics', 'xxxpics', 'xxxpicture',
|
'xxxphoto', 'xxxphotos', 'xxxpic', 'xxx-pics', 'xxxpics', 'xxxpicture',
|
||||||
'xxxpictures', 'xxxpicturesfree', 'xxxpicx', 'xxxpirtures', 'xxxporn', 'xxxporno',
|
'xxxpictures', 'xxxpicturesfree', 'xxxpicx', 'xxxpirtures', 'xxxporn', 'xxxporno',
|
||||||
'xxxpussy', 'xxx-rated', 'xxxrated', 'xxxsex', 'xxxsites', 'xxxsluts',
|
'xxxpussy', 'xxx-rated', 'xxxrated', 'xxxsex', 'xxxsites', 'xxxsluts',
|
||||||
'xxxstories', 'xxxteen', 'xxxthumbnails', 'xxxthumbs', 'xxxtoons', 'xxxtoys',
|
'xxxstories', 'xxxteen', 'xxxthumbnails', 'xxxthumbs', 'xxxtoons', 'xxxtoys',
|
||||||
'xxxvideo', 'xxxvideos', 'xxxwomen', 'xxxx', 'xxxxx', 'xxxxxx',
|
'xxxvideo', 'xxxvideos', 'xxxwomen', 'xxxx', 'xxxxx', 'xxxxxx',
|
||||||
'filthyfarm', 'adultcheck', 'erotic', 'mistresses', 'naughty',
|
'filthyfarm', 'adultcheck', 'erotic', 'mistresses', 'naughty',
|
||||||
'adult', 'amateur', 'amateurs', 'anal', 'analau', 'poker',
|
'adult', 'amateur', 'amateurs', 'anal', 'analau', 'poker',
|
||||||
'anally', 'asian', 'swinging', 'ass', 'orgy', 'sexvideos',
|
'anally', 'asian', 'swinging', 'ass', 'orgy', 'sexvideos',
|
||||||
'babe', 'babes', 'bare', 'glamour', 'casino', 'bed',
|
'babe', 'babes', 'bare', 'glamour', 'casino', 'bed',
|
||||||
'vibrator', 'bikini', 'bisexual', 'blonde', 'breasted', 'breasts',
|
'vibrator', 'bikini', 'bisexual', 'blonde', 'breasted', 'breasts',
|
||||||
'busty', 'butts', 'candy', 'caning', 'caps', 'catholic',
|
'busty', 'butts', 'candy', 'caning', 'caps', 'catholic',
|
||||||
'chained', 'chested', 'chubby', 'close-ups', 'coupling',
|
'chained', 'chested', 'chubby', 'close-ups', 'coupling',
|
||||||
'cucumber', 'doll', 'dolls', 'dolly', 'dominating', 'drinking',
|
'cucumber', 'doll', 'dolls', 'dolly', 'dominating', 'drinking',
|
||||||
'drunk', 'fat', 'feet', 'fingering', 'fishnet', 'flasher',
|
'drunk', 'fat', 'feet', 'fingering', 'fishnet', 'flasher',
|
||||||
'footjob', 'foreplay', 'foreplaying', 'girlfriend', 'girlfriends', 'gymnast',
|
'footjob', 'foreplay', 'foreplaying', 'girlfriend', 'girlfriends', 'gymnast',
|
||||||
'hairy', 'holly', 'horse', 'housewife', 'houswife', 'insertion',
|
'hairy', 'holly', 'horse', 'housewife', 'houswife', 'insertion',
|
||||||
'insertions', 'interracial', 'jerka', 'juicy', 'kissing', 'kitty',
|
'insertions', 'interracial', 'jerka', 'juicy', 'kissing', 'kitty',
|
||||||
'lactating', 'ladyboy', 'lance', 'latina', 'latins', 'leather',
|
'lactating', 'ladyboy', 'lance', 'latina', 'latins', 'leather',
|
||||||
'legs', 'lesbian', 'lesbians', 'licking', 'lingerie', 'lubricants',
|
'legs', 'lesbian', 'lesbians', 'licking', 'lingerie', 'lubricants',
|
||||||
'mature', 'midget', 'minor', 'mistress', 'nude',
|
'mature', 'midget', 'minor', 'mistress', 'nude',
|
||||||
'older', 'olez', 'oral', 'panties', 'pantyhose', 'pedro',
|
'older', 'olez', 'oral', 'panties', 'pantyhose', 'pedro',
|
||||||
'peeing', 'penetration', 'pigtailed', 'pleasure', 'plump',
|
'peeing', 'penetration', 'pigtailed', 'pleasure', 'plump',
|
||||||
'plumper', 'poser', 'posers', 'poses', 'posing', 'prosecuted',
|
'plumper', 'poser', 'posers', 'poses', 'posing', 'prosecuted',
|
||||||
'punishment', 'reproducing', 'sex', 'shaved', 'shock', 'slave',
|
'punishment', 'reproducing', 'sex', 'shaved', 'shock', 'slave',
|
||||||
'sleeping', 'speculums', 'spread', 'spreading', 'squirting', 'stripper',
|
'sleeping', 'speculums', 'spread', 'spreading', 'squirting', 'stripper',
|
||||||
'stripping', 'swapping', 'thong', 'topless', 'toying',
|
'stripping', 'swapping', 'thong', 'topless', 'toying',
|
||||||
'trix', 'undressing', 'uniform', 'whipcream', 'brazzers', 'порно',
|
'trix', 'undressing', 'uniform', 'whipcream', 'brazzers', 'порно',
|
||||||
'порн', 'лесб', 'гей', 'геи', 'прон'
|
'порн', 'лесб', 'гей', 'геи', 'прон'
|
||||||
];
|
];
|
||||||
|
|
||||||
const XXX_VERY_BAD_WORDS = [
|
const XXX_VERY_BAD_WORDS = [
|
||||||
'catgoddess', 'gracel', 'fatman', 'falko', 'pthc',
|
'catgoddess', 'gracel', 'fatman', 'falko', 'pthc',
|
||||||
'ptsc', 'yukikax', 'ls-models', '3yo', '4yo', '5yo', '6yo', '7yo', '8yo', '9yo',
|
'ptsc', 'yukikax', 'ls-models', '3yo', '4yo', '5yo', '6yo', '7yo', '8yo', '9yo',
|
||||||
'10yo', '11yo', '12yo', '13yo', '14yo', '15yo', '16yo'
|
'10yo', '11yo', '12yo', '13yo', '14yo', '15yo', '16yo'
|
||||||
]
|
]
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
XXX_BLOCK_WORDS,
|
XXX_BLOCK_WORDS,
|
||||||
XXX_VERY_BAD_WORDS
|
XXX_VERY_BAD_WORDS
|
||||||
};
|
};
|
||||||
|
@ -4,23 +4,23 @@ import ReactMarkdown from 'react-markdown'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
export default class ChangeLog extends Page {
|
export default class ChangeLog extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Changelog');
|
this.setTitle('Changelog');
|
||||||
|
|
||||||
let changelogPath = 'CHANGELOG.md'
|
let changelogPath = 'CHANGELOG.md'
|
||||||
if(!fs.existsSync(changelogPath))
|
if(!fs.existsSync(changelogPath))
|
||||||
changelogPath = 'resources/CHANGELOG.md'
|
changelogPath = 'resources/CHANGELOG.md'
|
||||||
|
|
||||||
this.changelog = fs.readFileSync(changelogPath)
|
this.changelog = fs.readFileSync(changelogPath)
|
||||||
if(!this.changelog)
|
if(!this.changelog)
|
||||||
throw new Error('no changelog file')
|
throw new Error('no changelog file')
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='pad0-75'>
|
<div className='pad0-75'>
|
||||||
<ReactMarkdown skipHtml={true} source={this.changelog} />
|
<ReactMarkdown skipHtml={true} source={this.changelog} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ export default class BTComponent extends Component {
|
|||||||
// Свайп действия
|
// Свайп действия
|
||||||
if(
|
if(
|
||||||
this.props.onSwipeLeft ||
|
this.props.onSwipeLeft ||
|
||||||
this.props.onSwipeRight ||
|
this.props.onSwipeRight ||
|
||||||
this.props.onSwipeTop ||
|
this.props.onSwipeTop ||
|
||||||
this.props.onSwipeBottom ||
|
this.props.onSwipeBottom ||
|
||||||
this.onSwipeLeft ||
|
this.onSwipeLeft ||
|
||||||
this.onSwipeRight ||
|
this.onSwipeRight ||
|
||||||
this.onSwipeTop ||
|
this.onSwipeTop ||
|
||||||
this.onSwipeBottom
|
this.onSwipeBottom
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.swipeFunctions = listenSwipe(this, {
|
this.swipeFunctions = listenSwipe(this, {
|
||||||
|
@ -9,302 +9,302 @@ import Slider from 'material-ui/Slider'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
let dialog
|
let dialog
|
||||||
if(typeof WEB === 'undefined')
|
if(typeof WEB === 'undefined')
|
||||||
dialog = require('electron').remote.dialog
|
dialog = require('electron').remote.dialog
|
||||||
|
|
||||||
export default class ConfigPage extends Page {
|
export default class ConfigPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Rats settings');
|
this.setTitle('Rats settings');
|
||||||
this.options = {}
|
this.options = {}
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.loadSettings()
|
this.loadSettings()
|
||||||
}
|
}
|
||||||
loadSettings() {
|
loadSettings() {
|
||||||
window.torrentSocket.emit('config', window.customLoader((options) => {
|
window.torrentSocket.emit('config', window.customLoader((options) => {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
console.log(this.options)
|
console.log(this.options)
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
saveSettings() {
|
saveSettings() {
|
||||||
window.torrentSocket.emit('setConfig', this.options)
|
window.torrentSocket.emit('setConfig', this.options)
|
||||||
this.settingsSavedMessage = true
|
this.settingsSavedMessage = true
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.settingsSavedMessage = false
|
this.settingsSavedMessage = false
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='row center pad0-75'>
|
<div className='row center pad0-75'>
|
||||||
<RaisedButton label={__('Back to main page')} primary={true} onClick={() => {
|
<RaisedButton label={__('Back to main page')} primary={true} onClick={() => {
|
||||||
window.router('/')
|
window.router('/')
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
<div className='column center w100p pad0-75'>
|
<div className='column center w100p pad0-75'>
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Enabled network scanning')}
|
label={__('Enabled network scanning')}
|
||||||
toggled={this.options.indexer}
|
toggled={this.options.indexer}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.indexer = checked
|
this.options.indexer = checked
|
||||||
if(!this.options.indexer)
|
if(!this.options.indexer)
|
||||||
this.options.p2p = false
|
this.options.p2p = false
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Scanning port')}</div>
|
<div style={{flex: 1}}>{__('Scanning port')}</div>
|
||||||
<TextField
|
<TextField
|
||||||
style={{width: 65}}
|
style={{width: 65}}
|
||||||
hintText={__('Port')}
|
hintText={__('Port')}
|
||||||
errorText={this.options.spiderPort > 0 ? undefined : __('This field is required')}
|
errorText={this.options.spiderPort > 0 ? undefined : __('This field is required')}
|
||||||
value={this.options.spiderPort}
|
value={this.options.spiderPort}
|
||||||
onChange={(e, value) => {
|
onChange={(e, value) => {
|
||||||
if(!value)
|
if(!value)
|
||||||
value = 0
|
value = 0
|
||||||
if(value > 65535)
|
if(value > 65535)
|
||||||
value = 65535
|
value = 65535
|
||||||
|
|
||||||
this.options.spiderPort = parseInt(value)
|
this.options.spiderPort = parseInt(value)
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('For current work TCP and UDP ports must be fully open and forward in case of router usage')}</div>
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('For current work TCP and UDP ports must be fully open and forward in case of router usage')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Trackers responce port')}</div>
|
<div style={{flex: 1}}>{__('Trackers responce port')}</div>
|
||||||
<TextField
|
<TextField
|
||||||
style={{width: 65}}
|
style={{width: 65}}
|
||||||
hintText="Port"
|
hintText="Port"
|
||||||
errorText={this.options.udpTrackersPort > 0 ? undefined : __('This field is required')}
|
errorText={this.options.udpTrackersPort > 0 ? undefined : __('This field is required')}
|
||||||
value={this.options.udpTrackersPort}
|
value={this.options.udpTrackersPort}
|
||||||
onChange={(e, value) => {
|
onChange={(e, value) => {
|
||||||
if(!value)
|
if(!value)
|
||||||
value = 0
|
value = 0
|
||||||
if(value > 65535)
|
if(value > 65535)
|
||||||
value = 65535
|
value = 65535
|
||||||
|
|
||||||
this.options.udpTrackersPort = parseInt(value)
|
this.options.udpTrackersPort = parseInt(value)
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('For current work UDP port must be fully open and forward in case of router usage')}</div>
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('For current work UDP port must be fully open and forward in case of router usage')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Enabled UPnP')}
|
label={__('Enabled UPnP')}
|
||||||
toggled={this.options.upnp}
|
toggled={this.options.upnp}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.upnp = checked
|
this.options.upnp = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Collection directory')}</div>
|
<div style={{flex: 1}}>{__('Collection directory')}</div>
|
||||||
<TextField
|
<TextField
|
||||||
hintText={__('Db path')}
|
hintText={__('Db path')}
|
||||||
errorText={this.options.dbPath && this.options.dbPath.length > 0 ? undefined : __('This field is required')}
|
errorText={this.options.dbPath && this.options.dbPath.length > 0 ? undefined : __('This field is required')}
|
||||||
value={this.options.dbPath}
|
value={this.options.dbPath}
|
||||||
onChange={(e, value) => {
|
onChange={(e, value) => {
|
||||||
if(!fs.existsSync(value))
|
if(!fs.existsSync(value))
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.dbPath = value
|
this.options.dbPath = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<RaisedButton style={{marginLeft: 20}} label={__('Browse')} primary={true} onClick={() => {
|
<RaisedButton style={{marginLeft: 20}} label={__('Browse')} primary={true} onClick={() => {
|
||||||
if(!dialog)
|
if(!dialog)
|
||||||
return
|
return
|
||||||
const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0]
|
const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0]
|
||||||
if(dir)
|
if(dir)
|
||||||
{
|
{
|
||||||
this.options.dbPath = dir
|
this.options.dbPath = dir
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}
|
}
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Download torrents directory')}</div>
|
<div style={{flex: 1}}>{__('Download torrents directory')}</div>
|
||||||
<TextField
|
<TextField
|
||||||
hintText={__('Download path')}
|
hintText={__('Download path')}
|
||||||
value={this.options.client && this.options.client.downloadPath}
|
value={this.options.client && this.options.client.downloadPath}
|
||||||
onChange={(e, value) => {
|
onChange={(e, value) => {
|
||||||
if(!fs.existsSync(value))
|
if(!fs.existsSync(value))
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.client.downloadPath = value
|
this.options.client.downloadPath = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<RaisedButton style={{marginLeft: 20}} label={__('Browse')} primary={true} onClick={() => {
|
<RaisedButton style={{marginLeft: 20}} label={__('Browse')} primary={true} onClick={() => {
|
||||||
if(!dialog)
|
if(!dialog)
|
||||||
return
|
return
|
||||||
const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0]
|
const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0]
|
||||||
if(dir)
|
if(dir)
|
||||||
{
|
{
|
||||||
this.options.client.downloadPath = dir
|
this.options.client.downloadPath = dir
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}
|
}
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Hide to tray on application minimize')}
|
label={__('Hide to tray on application minimize')}
|
||||||
toggled={this.options.trayOnMinimize}
|
toggled={this.options.trayOnMinimize}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.trayOnMinimize = checked
|
this.options.trayOnMinimize = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Hide to tray on application close')}
|
label={__('Hide to tray on application close')}
|
||||||
toggled={this.options.trayOnClose}
|
toggled={this.options.trayOnClose}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.trayOnClose = checked
|
this.options.trayOnClose = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{marginTop: 10}}>{__('P2P Rats network settings')}:</div>
|
<div style={{marginTop: 10}}>{__('P2P Rats network settings')}:</div>
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Enabled p2p search')}
|
label={__('Enabled p2p search')}
|
||||||
toggled={this.options.p2p}
|
toggled={this.options.p2p}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.p2p = this.options.indexer && checked
|
this.options.p2p = this.options.indexer && checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Enabled bootstrap peers')}
|
label={__('Enabled bootstrap peers')}
|
||||||
toggled={this.options.p2pBootstrap}
|
toggled={this.options.p2pBootstrap}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.p2pBootstrap = checked
|
this.options.p2pBootstrap = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('Use extrnral bootstrap nodes to get p2p peers when network setted wrong or need external source')}</div>
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('Use extrnral bootstrap nodes to get p2p peers when network setted wrong or need external source')}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Max peers limit')} ({__('current')}: {this.options.p2pConnections})</div>
|
<div style={{flex: 1}}>{__('Max peers limit')} ({__('current')}: {this.options.p2pConnections})</div>
|
||||||
<Slider
|
<Slider
|
||||||
min={10}
|
min={10}
|
||||||
max={25}
|
max={25}
|
||||||
step={1}
|
step={1}
|
||||||
style={{width: 300}}
|
style={{width: 300}}
|
||||||
value={this.options.p2pConnections}
|
value={this.options.p2pConnections}
|
||||||
onChange={(event, value) => {
|
onChange={(event, value) => {
|
||||||
this.options.p2pConnections = value
|
this.options.p2pConnections = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('P2P torrents replication')}
|
label={__('P2P torrents replication')}
|
||||||
toggled={this.options.p2pReplication}
|
toggled={this.options.p2pReplication}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
this.options.p2pReplication = checked
|
this.options.p2pReplication = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('Enable torrents replication from another rats clients. Dont recomended if torrent scanner works correct')}.</div>
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('Enable torrents replication from another rats clients. Dont recomended if torrent scanner works correct')}.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div style={{marginTop: 10}}>{__('Torrent network scanner settings')}:</div>
|
<div style={{marginTop: 10}}>{__('Torrent network scanner settings')}:</div>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Scanner walk speed')} ({__('current')}: {this.options.spider && this.options.spider.walkInterval}) [{__('affected after program reload')}]</div>
|
<div style={{flex: 1}}>{__('Scanner walk speed')} ({__('current')}: {this.options.spider && this.options.spider.walkInterval}) [{__('affected after program reload')}]</div>
|
||||||
<Slider
|
<Slider
|
||||||
min={1}
|
min={1}
|
||||||
max={150}
|
max={150}
|
||||||
step={1}
|
step={1}
|
||||||
style={{width: 300}}
|
style={{width: 300}}
|
||||||
value={this.options.spider && this.options.spider.walkInterval}
|
value={this.options.spider && this.options.spider.walkInterval}
|
||||||
onChange={(event, value) => {
|
onChange={(event, value) => {
|
||||||
this.options.spider.walkInterval = value
|
this.options.spider.walkInterval = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('Low value')} - {__('fast initial scanning and high cpu usage')}. {__('High Value')} - {__('low cpu usage but very slow scanning')}.
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('Low value')} - {__('fast initial scanning and high cpu usage')}. {__('High Value')} - {__('low cpu usage but very slow scanning')}.
|
||||||
{__('Good value between')} 3-60. {__('Defaul value')}: 5</div>
|
{__('Good value between')} 3-60. {__('Defaul value')}: 5</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Nodes usage')} ({__('current')}: {this.options.spider && this.options.spider.nodesUsage})</div>
|
<div style={{flex: 1}}>{__('Nodes usage')} ({__('current')}: {this.options.spider && this.options.spider.nodesUsage})</div>
|
||||||
<Slider
|
<Slider
|
||||||
min={0}
|
min={0}
|
||||||
max={1000}
|
max={1000}
|
||||||
step={1}
|
step={1}
|
||||||
style={{width: 300}}
|
style={{width: 300}}
|
||||||
value={this.options.spider && this.options.spider.nodesUsage}
|
value={this.options.spider && this.options.spider.nodesUsage}
|
||||||
onChange={(event, value) => {
|
onChange={(event, value) => {
|
||||||
this.options.spider.nodesUsage = value
|
this.options.spider.nodesUsage = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('Low Value')} - {__('very low usage of nodes, low network traffic, slow torrent scanning')}. {__('High value')} - {__('high traffic, fast scanning, high routers usage')}.
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('Low Value')} - {__('very low usage of nodes, low network traffic, slow torrent scanning')}. {__('High value')} - {__('high traffic, fast scanning, high routers usage')}.
|
||||||
{__('Recomended value between')} 10-1000. {__('Defaul value')}: 100. 0 - {__('Ignore this option')} ({__('no limit')}).
|
{__('Recomended value between')} 10-1000. {__('Defaul value')}: 100. 0 - {__('Ignore this option')} ({__('no limit')}).
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Reduce network packages')} ({__('current')}: {this.options.spider && this.options.spider.packagesLimit})</div>
|
<div style={{flex: 1}}>{__('Reduce network packages')} ({__('current')}: {this.options.spider && this.options.spider.packagesLimit})</div>
|
||||||
<Slider
|
<Slider
|
||||||
min={0}
|
min={0}
|
||||||
max={2000}
|
max={2000}
|
||||||
step={1}
|
step={1}
|
||||||
style={{width: 300}}
|
style={{width: 300}}
|
||||||
value={this.options.spider && this.options.spider.packagesLimit}
|
value={this.options.spider && this.options.spider.packagesLimit}
|
||||||
onChange={(event, value) => {
|
onChange={(event, value) => {
|
||||||
this.options.spider.packagesLimit = value
|
this.options.spider.packagesLimit = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* {__('Low Value')} - {__('ignore more usless network packages, lower traffic and routers usage')}. {__('High Value')} - {__('high traffic and router usage in prospect')}.
|
<div className='fs0-75' style={{color: 'grey'}}>* {__('Low Value')} - {__('ignore more usless network packages, lower traffic and routers usage')}. {__('High Value')} - {__('high traffic and router usage in prospect')}.
|
||||||
{__('Recomended value between')} 300-2000. {__('Defaul value')}: 500. 0 - {__('Ignore this option')} ({__('no limit')}).
|
{__('Recomended value between')} 300-2000. {__('Defaul value')}: 500. 0 - {__('Ignore this option')} ({__('no limit')}).
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
this.settingsSavedMessage
|
this.settingsSavedMessage
|
||||||
&&
|
&&
|
||||||
<div style={{color: 'green'}}>{__('Settings saved')}</div>
|
<div style={{color: 'green'}}>{__('Settings saved')}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className='row center pad0-75'>
|
<div className='row center pad0-75'>
|
||||||
<RaisedButton label={__('Save Settings')} primary={true} onClick={() => {
|
<RaisedButton label={__('Save Settings')} primary={true} onClick={() => {
|
||||||
this.saveSettings()
|
this.saveSettings()
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ const ContentCategoryProp = 'contentCategory';
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
XXX_BLOCK_WORDS,
|
XXX_BLOCK_WORDS,
|
||||||
XXX_VERY_BAD_WORDS
|
XXX_VERY_BAD_WORDS
|
||||||
} = require('./bad-words');
|
} = require('./bad-words');
|
||||||
|
|
||||||
// блокируем порнографию
|
// блокируем порнографию
|
||||||
@ -304,7 +304,7 @@ const torrentTypeDetect = (torrent, files) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let priority = Object.keys(typesPriority).sort(function(a, b){
|
let priority = Object.keys(typesPriority).sort(function(a, b){
|
||||||
return typesPriority[b] - typesPriority[a]
|
return typesPriority[b] - typesPriority[a]
|
||||||
});
|
});
|
||||||
if(priority.length > 0)
|
if(priority.length > 0)
|
||||||
torrent[ContentTypeProp] = priority[0];
|
torrent[ContentTypeProp] = priority[0];
|
||||||
|
@ -7,27 +7,27 @@ import NavigationClose from 'material-ui/svg-icons/navigation/close';
|
|||||||
|
|
||||||
export default class DMCAPage extends Page {
|
export default class DMCAPage extends Page {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='w100p column'>
|
<div className='w100p column'>
|
||||||
<AppBar
|
<AppBar
|
||||||
title="DMCA / Copyright"
|
title="DMCA / Copyright"
|
||||||
iconElementLeft={<IconButton onClick={()=>{ window.router('/') }}><NavigationClose /></IconButton>}
|
iconElementLeft={<IconButton onClick={()=>{ window.router('/') }}><NavigationClose /></IconButton>}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='column w100p pad1 center'>
|
<div className='column w100p pad1 center'>
|
||||||
<div>RatsOnTheBoat.org is in compliance with 17 U.S.C. § 512, the Digital Millennium Copyright Act ("DMCA") and the Directive 2001/29/EC of the European Parliament.</div>
|
<div>RatsOnTheBoat.org is in compliance with 17 U.S.C. § 512, the Digital Millennium Copyright Act ("DMCA") and the Directive 2001/29/EC of the European Parliament.</div>
|
||||||
|
|
||||||
<div className='fs1-5 pad0-75'>Content status</div>
|
<div className='fs1-5 pad0-75'>Content status</div>
|
||||||
|
|
||||||
Our main goal is collect and make analysis of information from the torrent network. We don't save/distribute any real content/data and also don't save any torrents files - we are respect DMCA law.
|
Our main goal is collect and make analysis of information from the torrent network. We don't save/distribute any real content/data and also don't save any torrents files - we are respect DMCA law.
|
||||||
Information collected automaticly and the real source are torrent clients based on torrent protocol.
|
Information collected automaticly and the real source are torrent clients based on torrent protocol.
|
||||||
|
|
||||||
<div className='fs1-5 pad0-75'>Block mechanisms (for rightholders)</div>
|
<div className='fs1-5 pad0-75'>Block mechanisms (for rightholders)</div>
|
||||||
|
|
||||||
Right holders can block/remove content that they responsible for. Contact administration or left application about content removal.
|
Right holders can block/remove content that they responsible for. Contact administration or left application about content removal.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,48 +10,48 @@ export default class TopPage extends Page {
|
|||||||
downloads = []
|
downloads = []
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Current Downloads');
|
this.setTitle('Current Downloads');
|
||||||
}
|
}
|
||||||
getDownloads()
|
getDownloads()
|
||||||
{
|
{
|
||||||
window.torrentSocket.emit('downloads', window.customLoader((downloads) => {
|
window.torrentSocket.emit('downloads', window.customLoader((downloads) => {
|
||||||
this.downloads = downloads
|
this.downloads = downloads
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
super.componentDidMount();
|
super.componentDidMount();
|
||||||
this.getDownloads()
|
this.getDownloads()
|
||||||
this.downloading = () => this.getDownloads()
|
this.downloading = () => this.getDownloads()
|
||||||
window.torrentSocket.on('downloading', this.downloading);
|
window.torrentSocket.on('downloading', this.downloading);
|
||||||
this.downloadDone = () => this.getDownloads()
|
this.downloadDone = () => this.getDownloads()
|
||||||
window.torrentSocket.on('downloadDone', this.downloadDone);
|
window.torrentSocket.on('downloadDone', this.downloadDone);
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
if(this.downloading)
|
if(this.downloading)
|
||||||
window.torrentSocket.off('downloading', this.downloading);
|
window.torrentSocket.off('downloading', this.downloading);
|
||||||
if(this.downloadDone)
|
if(this.downloadDone)
|
||||||
window.torrentSocket.off('downloadDone', this.downloadDone);
|
window.torrentSocket.off('downloadDone', this.downloadDone);
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='column center w100p pad0-75'>
|
<div className='column center w100p pad0-75'>
|
||||||
<RaisedButton label={__('Back to main page')} primary={true} onClick={() => {
|
<RaisedButton label={__('Back to main page')} primary={true} onClick={() => {
|
||||||
window.router('/')
|
window.router('/')
|
||||||
}} />
|
}} />
|
||||||
<List style={{paddingBottom: '70px'}} className='animated recent-torrents'>
|
<List style={{paddingBottom: '70px'}} className='animated recent-torrents'>
|
||||||
{
|
{
|
||||||
this.downloads.map((download, index) => {
|
this.downloads.map((download, index) => {
|
||||||
return <TorrentLine key={index} torrent={download.torrentObject} download={download} />
|
return <TorrentLine key={index} torrent={download.torrentObject} download={download} />
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</List>
|
</List>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,89 +8,89 @@ import MenuItem from 'material-ui/MenuItem';
|
|||||||
import Feed from './feed';
|
import Feed from './feed';
|
||||||
|
|
||||||
export default class FeedPage extends Page {
|
export default class FeedPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Rats On The Boat - Content Search Engine');
|
this.setTitle('Rats On The Boat - Content Search Engine');
|
||||||
}
|
}
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
Search.instance().onSearchUpdate = () => this.forceUpdate()
|
Search.instance().onSearchUpdate = () => this.forceUpdate()
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
Search.instance().onSearchUpdate = () => {}
|
Search.instance().onSearchUpdate = () => {}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const orderText = (text, field) => {
|
const orderText = (text, field) => {
|
||||||
if(field !== Search.instance().state.orderBy)
|
if(field !== Search.instance().state.orderBy)
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
if(Search.instance().state.orderDesc)
|
if(Search.instance().state.orderDesc)
|
||||||
return text + ' ⇩'
|
return text + ' ⇩'
|
||||||
else
|
else
|
||||||
return text + ' ⇧'
|
return text + ' ⇧'
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='index-window' className='column center'>
|
<div id='index-window' className='column center'>
|
||||||
<div className='torrents-container'>
|
<div className='torrents-container'>
|
||||||
<SearchResults
|
<SearchResults
|
||||||
torrentsSearchResults={Search.instance().searchTorrents}
|
torrentsSearchResults={Search.instance().searchTorrents}
|
||||||
filesSearchResults={Search.instance().searchFiles}
|
filesSearchResults={Search.instance().searchFiles}
|
||||||
currentSearching={Search.instance().state.searchingIndicator}
|
currentSearching={Search.instance().state.searchingIndicator}
|
||||||
searchText={Search.instance().currentSearch}
|
searchText={Search.instance().currentSearch}
|
||||||
resultSelector={
|
resultSelector={
|
||||||
<SelectField
|
<SelectField
|
||||||
floatingLabelText={__("Sort by")}
|
floatingLabelText={__("Sort by")}
|
||||||
floatingLabelFixed={true}
|
floatingLabelFixed={true}
|
||||||
value={Search.instance().state.orderBy}
|
value={Search.instance().state.orderBy}
|
||||||
onChange={(event, index, value) => {
|
onChange={(event, index, value) => {
|
||||||
event.preventDefault(); // fix overclick on torrent
|
event.preventDefault(); // fix overclick on torrent
|
||||||
if(value === 'none') {
|
if(value === 'none') {
|
||||||
Search.instance().setState({orderBy: null}, () => {
|
Search.instance().setState({orderBy: null}, () => {
|
||||||
Search.instance().search(true)
|
Search.instance().search(true)
|
||||||
})
|
})
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(value === Search.instance().state.orderBy)
|
if(value === Search.instance().state.orderBy)
|
||||||
{
|
{
|
||||||
Search.instance().setState({orderDesc: !Search.instance().state.orderDesc}, () => {
|
Search.instance().setState({orderDesc: !Search.instance().state.orderDesc}, () => {
|
||||||
Search.instance().search(true)
|
Search.instance().search(true)
|
||||||
})
|
})
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Search.instance().setState({
|
Search.instance().setState({
|
||||||
orderBy: value,
|
orderBy: value,
|
||||||
orderDesc: (value === 'seeders' || value === 'completed' || value === 'added') ? true : Search.instance().state.orderDesc
|
orderDesc: (value === 'seeders' || value === 'completed' || value === 'added') ? true : Search.instance().state.orderDesc
|
||||||
}, () => {
|
}, () => {
|
||||||
Search.instance().search(true)
|
Search.instance().search(true)
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value='none' primaryText={__('None')} />
|
<MenuItem value='none' primaryText={__('None')} />
|
||||||
<MenuItem value='seeders' primaryText={orderText(__('Seeders'), 'seeders')} />
|
<MenuItem value='seeders' primaryText={orderText(__('Seeders'), 'seeders')} />
|
||||||
<MenuItem value='name' primaryText={orderText(__('Name'), 'name')} />
|
<MenuItem value='name' primaryText={orderText(__('Name'), 'name')} />
|
||||||
<MenuItem value='files' primaryText={orderText(__('Files'), 'files')} />
|
<MenuItem value='files' primaryText={orderText(__('Files'), 'files')} />
|
||||||
<MenuItem value='size' primaryText={orderText(__('Size'), 'size')} />
|
<MenuItem value='size' primaryText={orderText(__('Size'), 'size')} />
|
||||||
<MenuItem value='added' primaryText={orderText(__('Added date'), 'added')} />
|
<MenuItem value='added' primaryText={orderText(__('Added date'), 'added')} />
|
||||||
<MenuItem value='completed' primaryText={orderText(__('Completed'), 'completed')} />
|
<MenuItem value='completed' primaryText={orderText(__('Completed'), 'completed')} />
|
||||||
</SelectField>
|
</SelectField>
|
||||||
}
|
}
|
||||||
|
|
||||||
moreTorrentsEnabled={Search.instance().moreSearchTorrents && !Search.instance().state.searchingIndicator}
|
moreTorrentsEnabled={Search.instance().moreSearchTorrents && !Search.instance().state.searchingIndicator}
|
||||||
moreFilesEnabled={Search.instance().moreSearchFiles && !Search.instance().state.searchingIndicator}
|
moreFilesEnabled={Search.instance().moreSearchFiles && !Search.instance().state.searchingIndicator}
|
||||||
onMoreTorrents={() => Search.instance().moreTorrents()}
|
onMoreTorrents={() => Search.instance().moreTorrents()}
|
||||||
onMoreFiles={() => Search.instance().moreFiles()}
|
onMoreFiles={() => Search.instance().moreFiles()}
|
||||||
moreTorrentsIndicator={Search.instance().state.moreTorrentsIndicator}
|
moreTorrentsIndicator={Search.instance().state.moreTorrentsIndicator}
|
||||||
moreFilesIndicator={Search.instance().state.moreFilesIndicator}
|
moreFilesIndicator={Search.instance().state.moreFilesIndicator}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='column center w100p pad0-75'>
|
<div className='column center w100p pad0-75'>
|
||||||
<Feed />
|
<Feed />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,32 +5,32 @@ import Divider from 'material-ui/Divider';
|
|||||||
import Subheader from 'material-ui/Subheader';
|
import Subheader from 'material-ui/Subheader';
|
||||||
|
|
||||||
export default class RecentTorrents extends Component {
|
export default class RecentTorrents extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.torrents = [];
|
this.torrents = [];
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.torrentSocket.emit('feed', window.customLoader((data) => {
|
window.torrentSocket.emit('feed', window.customLoader((data) => {
|
||||||
if(data) {
|
if(data) {
|
||||||
this.torrents = data;
|
this.torrents = data;
|
||||||
console.log(data)
|
console.log(data)
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<List className='animated torrents-container'>
|
<List className='animated torrents-container'>
|
||||||
<Subheader className='recent-title' inset={true}>
|
<Subheader className='recent-title' inset={true}>
|
||||||
{__('Feed')}
|
{__('Feed')}
|
||||||
</Subheader>
|
</Subheader>
|
||||||
<Divider />
|
<Divider />
|
||||||
{
|
{
|
||||||
this.torrents.map((torrent, index) =>{
|
this.torrents.map((torrent, index) =>{
|
||||||
return <TorrentLine key={index} torrent={torrent} />;
|
return <TorrentLine key={index} torrent={torrent} />;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,182 +11,182 @@ import MenuItem from 'material-ui/MenuItem';
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
export default class ConfigPage extends Page {
|
export default class ConfigPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Rats filters');
|
this.setTitle('Rats filters');
|
||||||
this.options = {}
|
this.options = {}
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.loadSettings()
|
this.loadSettings()
|
||||||
}
|
}
|
||||||
loadSettings() {
|
loadSettings() {
|
||||||
window.torrentSocket.emit('config', window.customLoader((options) => {
|
window.torrentSocket.emit('config', window.customLoader((options) => {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
console.log(this.options)
|
console.log(this.options)
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
saveSettings() {
|
saveSettings() {
|
||||||
window.torrentSocket.emit('setConfig', this.options)
|
window.torrentSocket.emit('setConfig', this.options)
|
||||||
this.settingsSavedMessage = true
|
this.settingsSavedMessage = true
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.settingsSavedMessage = false
|
this.settingsSavedMessage = false
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='row center pad0-75'>
|
<div className='row center pad0-75'>
|
||||||
<RaisedButton label={__("Back to main page")} primary={true} onClick={() => {
|
<RaisedButton label={__("Back to main page")} primary={true} onClick={() => {
|
||||||
window.router('/')
|
window.router('/')
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='column center w100p pad0-75'>
|
<div className='column center w100p pad0-75'>
|
||||||
|
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Max files per torrent')} ({__('current')}: {this.options.filters && this.options.filters.maxFiles})</div>
|
<div style={{flex: 1}}>{__('Max files per torrent')} ({__('current')}: {this.options.filters && this.options.filters.maxFiles})</div>
|
||||||
<Slider
|
<Slider
|
||||||
min={0}
|
min={0}
|
||||||
max={50000}
|
max={50000}
|
||||||
step={1}
|
step={1}
|
||||||
style={{width: 300}}
|
style={{width: 300}}
|
||||||
value={this.options.spider && this.options.filters.maxFiles}
|
value={this.options.spider && this.options.filters.maxFiles}
|
||||||
onChange={(event, value) => {
|
onChange={(event, value) => {
|
||||||
this.options.filters.maxFiles = value
|
this.options.filters.maxFiles = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
hintText={__('Max files')}
|
hintText={__('Max files')}
|
||||||
className='pad0-75'
|
className='pad0-75'
|
||||||
style={{width: 200}}
|
style={{width: 200}}
|
||||||
value={this.options.filters && this.options.filters.maxFiles}
|
value={this.options.filters && this.options.filters.maxFiles}
|
||||||
onChange={(e, value) => {
|
onChange={(e, value) => {
|
||||||
if(!this.options.filters)
|
if(!this.options.filters)
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.filters.maxFiles = parseInt(value)
|
this.options.filters.maxFiles = parseInt(value)
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>* 0 - {__('Disabled')}.
|
<div className='fs0-75' style={{color: 'grey'}}>* 0 - {__('Disabled')}.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<div style={{flex: 1}}>{__('Torrent name regular extension filtering')}</div>
|
<div style={{flex: 1}}>{__('Torrent name regular extension filtering')}</div>
|
||||||
<TextField
|
<TextField
|
||||||
hintText="regex"
|
hintText="regex"
|
||||||
className='pad0-75'
|
className='pad0-75'
|
||||||
style={{width: 400}}
|
style={{width: 400}}
|
||||||
value={this.options.filters && this.options.filters.namingRegExp}
|
value={this.options.filters && this.options.filters.namingRegExp}
|
||||||
onChange={(e, value) => {
|
onChange={(e, value) => {
|
||||||
if(!this.options.filters)
|
if(!this.options.filters)
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.filters.namingRegExp = value
|
this.options.filters.namingRegExp = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SelectField
|
<SelectField
|
||||||
style={{marginLeft: 15}}
|
style={{marginLeft: 15}}
|
||||||
floatingLabelText={__('Examples')}
|
floatingLabelText={__('Examples')}
|
||||||
value={this.options.filters && this.options.filters.namingRegExp}
|
value={this.options.filters && this.options.filters.namingRegExp}
|
||||||
onChange={(event, index, value) => {
|
onChange={(event, index, value) => {
|
||||||
if(!this.options.filters)
|
if(!this.options.filters)
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.filters.namingRegExp = value
|
this.options.filters.namingRegExp = value
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value={String.raw`^[А-Яа-я0-9A-Za-z.!@?#"$%&:;() *\+,\/;\-=[\\\]\^_{|}<>\u0400-\u04FF]+$`} primaryText={__('Russian + English only (With symbols)')} />
|
<MenuItem value={String.raw`^[А-Яа-я0-9A-Za-z.!@?#"$%&:;() *\+,\/;\-=[\\\]\^_{|}<>\u0400-\u04FF]+$`} primaryText={__('Russian + English only (With symbols)')} />
|
||||||
<MenuItem value={'^[0-9A-Za-z.!@?#"$%&:;() *\+,\/;\-=[\\\]\^_{|}<>]+$'} primaryText={__('English only (With symbols)')} />
|
<MenuItem value={'^[0-9A-Za-z.!@?#"$%&:;() *\+,\/;\-=[\\\]\^_{|}<>]+$'} primaryText={__('English only (With symbols)')} />
|
||||||
<MenuItem value={'^((?!badword).)*$'} primaryText={__('Ignore badword')} />
|
<MenuItem value={'^((?!badword).)*$'} primaryText={__('Ignore badword')} />
|
||||||
</SelectField>
|
</SelectField>
|
||||||
</div>
|
</div>
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Negative regular extension filtering')}
|
label={__('Negative regular extension filtering')}
|
||||||
toggled={this.options.filters && this.options.filters.namingRegExpNegative}
|
toggled={this.options.filters && this.options.filters.namingRegExpNegative}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
if(!this.options.filters)
|
if(!this.options.filters)
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.filters.namingRegExpNegative = checked
|
this.options.filters.namingRegExpNegative = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='fs0-75' style={{color: 'grey'}}>
|
<div className='fs0-75' style={{color: 'grey'}}>
|
||||||
* - {__('clean string means disabled')}
|
* - {__('clean string means disabled')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Toggle
|
<Toggle
|
||||||
style={{marginTop: '10px'}}
|
style={{marginTop: '10px'}}
|
||||||
label={__('Adult filter')}
|
label={__('Adult filter')}
|
||||||
toggled={this.options.filters && this.options.filters.adultFilter}
|
toggled={this.options.filters && this.options.filters.adultFilter}
|
||||||
onToggle={(e, checked) => {
|
onToggle={(e, checked) => {
|
||||||
if(!this.options.filters)
|
if(!this.options.filters)
|
||||||
return
|
return
|
||||||
|
|
||||||
this.options.filters.adultFilter = checked
|
this.options.filters.adultFilter = checked
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
this.toRemoveProbably && this.toRemoveProbably > 0
|
this.toRemoveProbably && this.toRemoveProbably > 0
|
||||||
?
|
?
|
||||||
<div style={{color: 'orange'}}>{__('Torrents to clean')}: {this.toRemoveProbably}</div>
|
<div style={{color: 'orange'}}>{__('Torrents to clean')}: {this.toRemoveProbably}</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.toRemove && this.toRemove > 0
|
this.toRemove && this.toRemove > 0
|
||||||
?
|
?
|
||||||
<div style={{color: 'red'}}>{__('Torrents cleaned')}: {this.toRemove}</div>
|
<div style={{color: 'red'}}>{__('Torrents cleaned')}: {this.toRemove}</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
this.settingsSavedMessage
|
this.settingsSavedMessage
|
||||||
&&
|
&&
|
||||||
<div style={{color: 'green'}}>{__('Settings saved')}</div>
|
<div style={{color: 'green'}}>{__('Settings saved')}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className='row center pad0-75'>
|
<div className='row center pad0-75'>
|
||||||
<RaisedButton label={__('Check torrents')} primary={true} onClick={() => {
|
<RaisedButton label={__('Check torrents')} primary={true} onClick={() => {
|
||||||
window.torrentSocket.emit('removeTorrents', true, window.customLoader((toRemove) => {
|
window.torrentSocket.emit('removeTorrents', true, window.customLoader((toRemove) => {
|
||||||
this.toRemoveProbably = toRemove
|
this.toRemoveProbably = toRemove
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}));
|
}));
|
||||||
}} />
|
}} />
|
||||||
<RaisedButton label={__('Clean torrents')} secondary={true} onClick={() => {
|
<RaisedButton label={__('Clean torrents')} secondary={true} onClick={() => {
|
||||||
window.torrentSocket.emit('removeTorrents', false, window.customLoader((toRemove) => {
|
window.torrentSocket.emit('removeTorrents', false, window.customLoader((toRemove) => {
|
||||||
this.toRemove = toRemove
|
this.toRemove = toRemove
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}));
|
}));
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row center pad0-75'>
|
<div className='row center pad0-75'>
|
||||||
<RaisedButton label={__('Save Settings')} primary={true} onClick={() => {
|
<RaisedButton label={__('Save Settings')} primary={true} onClick={() => {
|
||||||
this.saveSettings()
|
this.saveSettings()
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,18 @@ import React from 'react';
|
|||||||
export default (props) => {
|
export default (props) => {
|
||||||
return (
|
return (
|
||||||
<div className='column center' style={{color: 'grey', marginTop: '12px'}}>
|
<div className='column center' style={{color: 'grey', marginTop: '12px'}}>
|
||||||
<svg style={{height: '100px', fill: 'grey'}} viewBox="0 0 264.725 264.725">
|
<svg style={{height: '100px', fill: 'grey'}} viewBox="0 0 264.725 264.725">
|
||||||
<path d="M220.195,71.427c-0.589-7.654-9.135-15.619-17.979-16.209c-8.844-0.584-17.398,0.301-12.087,6.483
|
<path d="M220.195,71.427c-0.589-7.654-9.135-15.619-17.979-16.209c-8.844-0.584-17.398,0.301-12.087,6.483
|
||||||
c5.308,6.188,7.074,12.091,4.423,11.212c-2.66-0.896-13.267-7.08-45.104-2.066c-4.126,1.17-21.221-12.682-44.513-12.977
|
c5.308,6.188,7.074,12.091,4.423,11.212c-2.66-0.896-13.267-7.08-45.104-2.066c-4.126,1.17-21.221-12.682-44.513-12.977
|
||||||
c-23.283-0.295-40.381,6.346-64.85,72.296c-2.356,5.828-18.866,19.386-27.71,25.865C3.536,162.529,0.007,169.787,0,182.763
|
c-23.283-0.295-40.381,6.346-64.85,72.296c-2.356,5.828-18.866,19.386-27.71,25.865C3.536,162.529,0.007,169.787,0,182.763
|
||||||
c-0.018,18.158,25.934,27.187,81.648,26.889c55.715-0.292,85.195-9.388,85.195-9.388c-62.789,6.773-158.907,10.52-158.907-18.687
|
c-0.018,18.158,25.934,27.187,81.648,26.889c55.715-0.292,85.195-9.388,85.195-9.388c-62.789,6.773-158.907,10.52-158.907-18.687
|
||||||
c0-20.641,28.321-28.47,36.281-28.184c7.958,0.3,13.562,12.673,33.307,5.603c3.247-0.295,1.48,4.423-1.18,7.369
|
c0-20.641,28.321-28.47,36.281-28.184c7.958,0.3,13.562,12.673,33.307,5.603c3.247-0.295,1.48,4.423-1.18,7.369
|
||||||
c-2.651,2.942-0.586,6.487,9.73,6.487c10.315,0,41.183,0.295,47.707,0c6.531-0.299,11.839-11.792-9.384-12.68
|
c-2.651,2.942-0.586,6.487,9.73,6.487c10.315,0,41.183,0.295,47.707,0c6.531-0.299,11.839-11.792-9.384-12.68
|
||||||
c-18.548,0.311,12.023-5.773,15.915-21.813c0.709-3.927,8.84-4.139,15.918-4.119c20.777,0.029,34.485,38.193,38.912,38.338
|
c-18.548,0.311,12.023-5.773,15.915-21.813c0.709-3.927,8.84-4.139,15.918-4.119c20.777,0.029,34.485,38.193,38.912,38.338
|
||||||
c4.416,0.15,17.979,1.621,17.683-4.273c-0.292-5.897-11.491-3.241-13.854-6.487c-2.359-3.234-10.023-15.504-7.366-21.104
|
c4.416,0.15,17.979,1.621,17.683-4.273c-0.292-5.897-11.491-3.241-13.854-6.487c-2.359-3.234-10.023-15.504-7.366-21.104
|
||||||
c2.65-5.59,12.674-21.229,24.463-22.988c11.789-1.777,42.451,7.361,47.459,0c5.012-7.372-6.783-11.512-15.918-28.611
|
c2.65-5.59,12.674-21.229,24.463-22.988c11.789-1.777,42.451,7.361,47.459,0c5.012-7.372-6.783-11.512-15.918-28.611
|
||||||
C243.779,80.572,238.768,71.728,220.195,71.427z"/>
|
C243.779,80.572,238.768,71.728,220.195,71.427z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
export default function formatBytes(bytes,decimals) {
|
export default function formatBytes(bytes,decimals) {
|
||||||
if(bytes == 0) return '0 Byte';
|
if(bytes == 0) return '0 Byte';
|
||||||
var k = 1000; // or 1024 for binary
|
var k = 1000; // or 1024 for binary
|
||||||
var dm = decimals + 1 || 3;
|
var dm = decimals + 1 || 3;
|
||||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||||
}
|
}
|
@ -5,64 +5,64 @@ import RaisedButton from 'material-ui/RaisedButton';
|
|||||||
import Search from './search'
|
import Search from './search'
|
||||||
|
|
||||||
class Header extends React.Component {
|
class Header extends React.Component {
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
this.header = React.createRef();
|
this.header = React.createRef();
|
||||||
}
|
}
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
window.onscroll = () => {
|
window.onscroll = () => {
|
||||||
if (window.pageYOffset >= 15)
|
if (window.pageYOffset >= 15)
|
||||||
{
|
{
|
||||||
const scrollHeight = Math.max(
|
const scrollHeight = Math.max(
|
||||||
document.body.scrollHeight, document.documentElement.scrollHeight,
|
document.body.scrollHeight, document.documentElement.scrollHeight,
|
||||||
document.body.offsetHeight, document.documentElement.offsetHeight,
|
document.body.offsetHeight, document.documentElement.offsetHeight,
|
||||||
document.body.clientHeight, document.documentElement.clientHeight
|
document.body.clientHeight, document.documentElement.clientHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
if(scrollHeight - 240 < document.documentElement.clientHeight)
|
if(scrollHeight - 240 < document.documentElement.clientHeight)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.stickyHeader)
|
if(!this.stickyHeader)
|
||||||
{
|
{
|
||||||
this.stickyHeader = true
|
this.stickyHeader = true
|
||||||
this.header.current.classList.add("sticky");
|
this.header.current.classList.add("sticky");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(this.stickyHeader)
|
if(this.stickyHeader)
|
||||||
{
|
{
|
||||||
this.stickyHeader = false
|
this.stickyHeader = false
|
||||||
this.header.current.classList.remove("sticky");
|
this.header.current.classList.remove("sticky");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
window.onscroll = null
|
window.onscroll = null
|
||||||
}
|
}
|
||||||
|
|
||||||
render()
|
render()
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<div ref={this.header} className='header'>
|
<div ref={this.header} className='header'>
|
||||||
<Card className='w100p header-main' style={{position: 'fixed', zIndex: 2}}>
|
<Card className='w100p header-main' style={{position: 'fixed', zIndex: 2}}>
|
||||||
<CardMedia
|
<CardMedia
|
||||||
overlay={<CardTitle className='header-title' title={__('Yarrr, Landlubbers!')} style={{paddingTop: 2}} subtitle={
|
overlay={<CardTitle className='header-title' title={__('Yarrr, Landlubbers!')} style={{paddingTop: 2}} subtitle={
|
||||||
<div>
|
<div>
|
||||||
<div className='row' style={{position: 'absolute', top: -65}}>
|
<div className='row' style={{position: 'absolute', top: -65}}>
|
||||||
<svg className='clickable'
|
<svg className='clickable'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.router('/config')
|
window.router('/config')
|
||||||
}}
|
}}
|
||||||
fill='white' style={{height: 45, margin: 4}} viewBox="0 0 932.179 932.179">
|
fill='white' style={{height: 45, margin: 4}} viewBox="0 0 932.179 932.179">
|
||||||
<g>
|
<g>
|
||||||
<path d="M61.2,341.538c4.9,16.8,11.7,33,20.3,48.2l-24.5,30.9c-8,10.1-7.1,24.5,1.9,33.6l42.2,42.2c9.1,9.1,23.5,9.899,33.6,1.899
|
<path d="M61.2,341.538c4.9,16.8,11.7,33,20.3,48.2l-24.5,30.9c-8,10.1-7.1,24.5,1.9,33.6l42.2,42.2c9.1,9.1,23.5,9.899,33.6,1.899
|
||||||
l30.7-24.3c15.8,9.101,32.6,16.2,50.1,21.2l4.6,39.5c1.5,12.8,12.3,22.4,25.1,22.4h59.7c12.8,0,23.6-9.601,25.1-22.4l4.4-38.1
|
l30.7-24.3c15.8,9.101,32.6,16.2,50.1,21.2l4.6,39.5c1.5,12.8,12.3,22.4,25.1,22.4h59.7c12.8,0,23.6-9.601,25.1-22.4l4.4-38.1
|
||||||
c18.8-4.9,36.8-12.2,53.7-21.7l29.7,23.5c10.1,8,24.5,7.1,33.6-1.9l42.2-42.2c9.1-9.1,9.9-23.5,1.9-33.6l-23.1-29.3
|
c18.8-4.9,36.8-12.2,53.7-21.7l29.7,23.5c10.1,8,24.5,7.1,33.6-1.9l42.2-42.2c9.1-9.1,9.9-23.5,1.9-33.6l-23.1-29.3
|
||||||
c9.6-16.601,17.1-34.3,22.1-52.8l35.6-4.1c12.801-1.5,22.4-12.3,22.4-25.1v-59.7c0-12.8-9.6-23.6-22.4-25.1l-35.1-4.1
|
c9.6-16.601,17.1-34.3,22.1-52.8l35.6-4.1c12.801-1.5,22.4-12.3,22.4-25.1v-59.7c0-12.8-9.6-23.6-22.4-25.1l-35.1-4.1
|
||||||
@ -71,7 +71,7 @@ class Header extends React.Component {
|
|||||||
c-19.8,5.3-38.7,13.3-56.3,23.8l-27.5-21.8c-10.1-8-24.5-7.1-33.6,1.9l-42.2,42.2c-9.1,9.1-9.9,23.5-1.9,33.6l23,29.1
|
c-19.8,5.3-38.7,13.3-56.3,23.8l-27.5-21.8c-10.1-8-24.5-7.1-33.6,1.9l-42.2,42.2c-9.1,9.1-9.9,23.5-1.9,33.6l23,29.1
|
||||||
c-9.2,16.6-16.2,34.3-20.8,52.7l-36.8,4.2c-12.8,1.5-22.4,12.3-22.4,25.1v59.7c0,12.8,9.6,23.6,22.4,25.1L61.2,341.538z
|
c-9.2,16.6-16.2,34.3-20.8,52.7l-36.8,4.2c-12.8,1.5-22.4,12.3-22.4,25.1v59.7c0,12.8,9.6,23.6,22.4,25.1L61.2,341.538z
|
||||||
M277.5,180.038c54.4,0,98.7,44.3,98.7,98.7s-44.3,98.7-98.7,98.7c-54.399,0-98.7-44.3-98.7-98.7S223.1,180.038,277.5,180.038z"/>
|
M277.5,180.038c54.4,0,98.7,44.3,98.7,98.7s-44.3,98.7-98.7,98.7c-54.399,0-98.7-44.3-98.7-98.7S223.1,180.038,277.5,180.038z"/>
|
||||||
<path d="M867.699,356.238l-31.5-26.6c-9.699-8.2-24-7.8-33.199,0.9l-17.4,16.3c-14.699-7.1-30.299-12.1-46.4-15l-4.898-24
|
<path d="M867.699,356.238l-31.5-26.6c-9.699-8.2-24-7.8-33.199,0.9l-17.4,16.3c-14.699-7.1-30.299-12.1-46.4-15l-4.898-24
|
||||||
c-2.5-12.4-14-21-26.602-20l-41.1,3.5c-12.6,1.1-22.5,11.4-22.9,24.1l-0.799,24.4c-15.801,5.7-30.701,13.5-44.301,23.3
|
c-2.5-12.4-14-21-26.602-20l-41.1,3.5c-12.6,1.1-22.5,11.4-22.9,24.1l-0.799,24.4c-15.801,5.7-30.701,13.5-44.301,23.3
|
||||||
l-20.799-13.8c-10.602-7-24.701-5-32.9,4.7l-26.6,31.7c-8.201,9.7-7.801,24,0.898,33.2l18.201,19.399
|
l-20.799-13.8c-10.602-7-24.701-5-32.9,4.7l-26.6,31.7c-8.201,9.7-7.801,24,0.898,33.2l18.201,19.399
|
||||||
c-6.301,14.2-10.801,29.101-13.4,44.4l-26,5.3c-12.4,2.5-21,14-20,26.601l3.5,41.1c1.1,12.6,11.4,22.5,24.1,22.9l28.1,0.899
|
c-6.301,14.2-10.801,29.101-13.4,44.4l-26,5.3c-12.4,2.5-21,14-20,26.601l3.5,41.1c1.1,12.6,11.4,22.5,24.1,22.9l28.1,0.899
|
||||||
@ -82,7 +82,7 @@ class Header extends React.Component {
|
|||||||
c-5.201-14.6-12.201-28.399-20.9-41.2l13.699-20.6C879.4,378.638,877.4,364.438,867.699,356.238z M712.801,593.837
|
c-5.201-14.6-12.201-28.399-20.9-41.2l13.699-20.6C879.4,378.638,877.4,364.438,867.699,356.238z M712.801,593.837
|
||||||
c-44.4,3.801-83.602-29.3-87.301-73.699c-3.801-44.4,29.301-83.601,73.699-87.301c44.4-3.8,83.602,29.301,87.301,73.7
|
c-44.4,3.801-83.602-29.3-87.301-73.699c-3.801-44.4,29.301-83.601,73.699-87.301c44.4-3.8,83.602,29.301,87.301,73.7
|
||||||
C790.301,550.938,757.199,590.138,712.801,593.837z"/>
|
C790.301,550.938,757.199,590.138,712.801,593.837z"/>
|
||||||
<path d="M205,704.438c-12.6,1.3-22.3,11.899-22.4,24.6l-0.3,25.3c-0.2,12.7,9.2,23.5,21.8,25.101l18.6,2.399
|
<path d="M205,704.438c-12.6,1.3-22.3,11.899-22.4,24.6l-0.3,25.3c-0.2,12.7,9.2,23.5,21.8,25.101l18.6,2.399
|
||||||
c3.1,11.301,7.5,22.101,13.2,32.301l-12,14.8c-8,9.899-7.4,24.1,1.5,33.2l17.7,18.1c8.9,9.1,23.1,10.1,33.2,2.3l14.899-11.5
|
c3.1,11.301,7.5,22.101,13.2,32.301l-12,14.8c-8,9.899-7.4,24.1,1.5,33.2l17.7,18.1c8.9,9.1,23.1,10.1,33.2,2.3l14.899-11.5
|
||||||
c10.5,6.2,21.601,11.101,33.2,14.5l2,19.2c1.3,12.6,11.9,22.3,24.6,22.4l25.301,0.3c12.699,0.2,23.5-9.2,25.1-21.8l2.3-18.2
|
c10.5,6.2,21.601,11.101,33.2,14.5l2,19.2c1.3,12.6,11.9,22.3,24.6,22.4l25.301,0.3c12.699,0.2,23.5-9.2,25.1-21.8l2.3-18.2
|
||||||
c12.601-3.101,24.601-7.8,36-14l14,11.3c9.9,8,24.101,7.4,33.201-1.5l18.1-17.7c9.1-8.899,10.1-23.1,2.301-33.2L496.6,818.438
|
c12.601-3.101,24.601-7.8,36-14l14,11.3c9.9,8,24.101,7.4,33.201-1.5l18.1-17.7c9.1-8.899,10.1-23.1,2.301-33.2L496.6,818.438
|
||||||
@ -93,47 +93,47 @@ class Header extends React.Component {
|
|||||||
l-18.2,17.801c-9.1,8.899-10.1,23.1-2.3,33.199l10.7,13.801c-6.2,11-11.1,22.699-14.3,35L205,704.438z M368.3,675.837
|
l-18.2,17.801c-9.1,8.899-10.1,23.1-2.3,33.199l10.7,13.801c-6.2,11-11.1,22.699-14.3,35L205,704.438z M368.3,675.837
|
||||||
c36.3,0.4,65.399,30.301,65,66.601c-0.4,36.3-30.301,65.399-66.601,65c-36.3-0.4-65.399-30.3-65-66.601
|
c36.3,0.4,65.399,30.301,65,66.601c-0.4,36.3-30.301,65.399-66.601,65c-36.3-0.4-65.399-30.3-65-66.601
|
||||||
C302.1,704.538,332,675.438,368.3,675.837z"/>
|
C302.1,704.538,332,675.438,368.3,675.837z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<svg className='clickable'
|
<svg className='clickable'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.router('/filters')
|
window.router('/filters')
|
||||||
}}
|
}}
|
||||||
fill='white' style={{height: 45, margin: 4}} viewBox="0 0 512 512">
|
fill='white' style={{height: 45, margin: 4}} viewBox="0 0 512 512">
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M256,103.536c-58.559,0-106.2,47.641-106.2,106.2c0,4.512,3.657,8.169,8.169,8.169s8.169-3.658,8.169-8.169
|
<path d="M256,103.536c-58.559,0-106.2,47.641-106.2,106.2c0,4.512,3.657,8.169,8.169,8.169s8.169-3.658,8.169-8.169
|
||||||
c0-49.55,40.313-89.862,89.862-89.862c49.549,0,89.862,40.311,89.862,89.862c0,4.512,3.658,8.169,8.169,8.169
|
c0-49.55,40.313-89.862,89.862-89.862c49.549,0,89.862,40.311,89.862,89.862c0,4.512,3.658,8.169,8.169,8.169
|
||||||
c4.513,0,8.169-3.658,8.169-8.169C362.2,151.177,314.559,103.536,256,103.536z"/>
|
c4.513,0,8.169-3.658,8.169-8.169C362.2,151.177,314.559,103.536,256,103.536z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M256,136.213c-40.541,0-73.523,32.982-73.523,73.523c0,4.512,3.657,8.169,8.169,8.169s8.169-3.658,8.169-8.169
|
<path d="M256,136.213c-40.541,0-73.523,32.982-73.523,73.523c0,4.512,3.657,8.169,8.169,8.169s8.169-3.658,8.169-8.169
|
||||||
c0-31.532,25.654-57.185,57.185-57.185s57.185,25.653,57.185,57.185c0,4.512,3.657,8.169,8.169,8.169
|
c0-31.532,25.654-57.185,57.185-57.185s57.185,25.653,57.185,57.185c0,4.512,3.657,8.169,8.169,8.169
|
||||||
c4.513,0,8.169-3.658,8.169-8.169C329.523,169.195,296.541,136.213,256,136.213z"/>
|
c4.513,0,8.169-3.658,8.169-8.169C329.523,169.195,296.541,136.213,256,136.213z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M503.801,234.245H8.199c-4.513,0-8.169,3.658-8.169,8.169v43.569c0,2.721,1.354,5.263,3.612,6.781L167.331,402.76
|
<path d="M503.801,234.245H8.199c-4.513,0-8.169,3.658-8.169,8.169v43.569c0,2.721,1.354,5.263,3.612,6.781L167.331,402.76
|
||||||
c5.092,3.857,9.699,13.038,9.699,19.379v81.693c0,4.512,3.656,8.169,8.169,8.169h141.6c4.513,0,8.169-3.658,8.169-8.169v-81.693
|
c5.092,3.857,9.699,13.038,9.699,19.379v81.693c0,4.512,3.656,8.169,8.169,8.169h141.6c4.513,0,8.169-3.658,8.169-8.169v-81.693
|
||||||
c0-6.34,4.606-15.522,9.699-19.379l163.691-109.995c2.258-1.517,3.612-4.06,3.612-6.781v-43.569
|
c0-6.34,4.606-15.522,9.699-19.379l163.691-109.995c2.258-1.517,3.612-4.06,3.612-6.781v-43.569
|
||||||
C511.97,237.903,508.313,234.245,503.801,234.245z M495.632,277.815H157.969c-4.513,0-8.169,3.658-8.169,8.169
|
C511.97,237.903,508.313,234.245,503.801,234.245z M495.632,277.815H157.969c-4.513,0-8.169,3.658-8.169,8.169
|
||||||
s3.657,8.169,8.169,8.169h319.028l-141.61,95.159c-0.1,0.068-0.199,0.137-0.296,0.209c-9.383,6.93-16.458,20.951-16.458,32.616
|
s3.657,8.169,8.169,8.169h319.028l-141.61,95.159c-0.1,0.068-0.199,0.137-0.296,0.209c-9.383,6.93-16.458,20.951-16.458,32.616
|
||||||
v73.523H193.37v-73.523c0-11.665-7.076-25.686-16.458-32.616c-0.098-0.072-0.197-0.142-0.296-0.209L35.003,294.153h90.289
|
v73.523H193.37v-73.523c0-11.665-7.076-25.686-16.458-32.616c-0.098-0.072-0.197-0.142-0.296-0.209L35.003,294.153h90.289
|
||||||
c4.513,0,8.169-3.658,8.169-8.169s-3.657-8.169-8.169-8.169H16.368v-27.231h479.263V277.815z"/>
|
c4.513,0,8.169-3.658,8.169-8.169s-3.657-8.169-8.169-8.169H16.368v-27.231h479.263V277.815z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M296.504,397.63h-81.006c-4.513,0-8.169,3.658-8.169,8.169c0,4.512,3.657,8.169,8.169,8.169h81.006
|
<path d="M296.504,397.63h-81.006c-4.513,0-8.169,3.658-8.169,8.169c0,4.512,3.657,8.169,8.169,8.169h81.006
|
||||||
c4.513,0,8.169-3.658,8.169-8.169C304.674,401.288,301.016,397.63,296.504,397.63z"/>
|
c4.513,0,8.169-3.658,8.169-8.169C304.674,401.288,301.016,397.63,296.504,397.63z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path d="M458.171,168.573l-36.481-3.382c-3.895-14.477-9.68-28.351-17.251-41.376l23.416-28.2
|
<path d="M458.171,168.573l-36.481-3.382c-3.895-14.477-9.68-28.351-17.251-41.376l23.416-28.2
|
||||||
c2.696-3.246,2.475-8.011-0.509-10.995l-46.545-46.545c-2.983-2.983-7.749-3.206-10.996-0.509L341.51,61.063
|
c2.696-3.246,2.475-8.011-0.509-10.995l-46.545-46.545c-2.983-2.983-7.749-3.206-10.996-0.509L341.51,61.063
|
||||||
c-13.017-7.52-26.88-13.258-41.343-17.113l-3.386-36.534C296.391,3.213,292.866,0,288.647,0h-65.826
|
c-13.017-7.52-26.88-13.258-41.343-17.113l-3.386-36.534C296.391,3.213,292.866,0,288.647,0h-65.826
|
||||||
c-4.22,0-7.745,3.213-8.134,7.416l-3.401,36.68c-14.413,3.894-28.222,9.657-41.187,17.193L141.73,37.731
|
c-4.22,0-7.745,3.213-8.134,7.416l-3.401,36.68c-14.413,3.894-28.222,9.657-41.187,17.193L141.73,37.731
|
||||||
@ -146,56 +146,56 @@ class Header extends React.Component {
|
|||||||
c2.986,1.866,6.834,1.607,9.545-0.645l27.023-22.438l36.013,36.013l-22.371,26.941c-2.255,2.717-2.511,6.575-0.632,9.565
|
c2.986,1.866,6.834,1.607,9.545-0.645l27.023-22.438l36.013,36.013l-22.371,26.941c-2.255,2.717-2.511,6.575-0.632,9.565
|
||||||
c9.189,14.625,15.814,30.514,19.69,47.225c0.795,3.429,3.699,5.964,7.203,6.287l34.829,3.229v25.582
|
c9.189,14.625,15.814,30.514,19.69,47.225c0.795,3.429,3.699,5.964,7.203,6.287l34.829,3.229v25.582
|
||||||
c0,4.512,3.657,8.169,8.169,8.169s8.169-3.658,8.169-8.169v-33.029C465.586,172.488,462.373,168.963,458.171,168.573z"/>
|
c0,4.512,3.657,8.169,8.169,8.169s8.169-3.658,8.169-8.169v-33.029C465.586,172.488,462.373,168.963,458.171,168.573z"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{__('Welcome to')} ROTB! {__('This is file search engine based on the torrents from the internet')}.
|
{__('Welcome to')} ROTB! {__('This is file search engine based on the torrents from the internet')}.
|
||||||
{__('Here you can easily find torrent or file that you intrested for')}. {__('We are not responsible for any content')}:
|
{__('Here you can easily find torrent or file that you intrested for')}. {__('We are not responsible for any content')}:
|
||||||
{__('this is only information about content that collected automatically')}!
|
{__('this is only information about content that collected automatically')}!
|
||||||
</div>} />}
|
</div>} />}
|
||||||
>
|
>
|
||||||
<div className='row header-row' style={{
|
<div className='row header-row' style={{
|
||||||
padding: '15px',
|
padding: '15px',
|
||||||
background: `url('${Background}') no-repeat`,
|
background: `url('${Background}') no-repeat`,
|
||||||
backgroundSize: 'cover',
|
backgroundSize: 'cover',
|
||||||
transition: '1s'
|
transition: '1s'
|
||||||
}}>
|
}}>
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
label={__('Feed')}
|
label={__('Feed')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.router('/')
|
window.router('/')
|
||||||
}}
|
}}
|
||||||
backgroundColor='#69238c'
|
backgroundColor='#69238c'
|
||||||
labelColor='white'
|
labelColor='white'
|
||||||
style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}}
|
style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}}
|
||||||
buttonStyle={{borderRadius: 5}}
|
buttonStyle={{borderRadius: 5}}
|
||||||
icon={<svg fill='white' style={{height: 28}} viewBox="0 0 64.051 64.051">
|
icon={<svg fill='white' style={{height: 28}} viewBox="0 0 64.051 64.051">
|
||||||
<g>
|
<g>
|
||||||
<path d="M8,0v2c16,0,31.173,7.065,41.472,19.386C57.567,31.065,62.051,43.358,62.051,56h2c0-13.11-4.649-25.858-13.044-35.897
|
<path d="M8,0v2c16,0,31.173,7.065,41.472,19.386C57.567,31.065,62.051,43.358,62.051,56h2c0-13.11-4.649-25.858-13.044-35.897
|
||||||
C40.326,7.327,25,0,8,0z"/>
|
C40.326,7.327,25,0,8,0z"/>
|
||||||
<path d="M50.769,56h2C52.769,31.343,33,11.282,8,11.282v2C32,13.282,50.769,32.445,50.769,56z"/>
|
<path d="M50.769,56h2C52.769,31.343,33,11.282,8,11.282v2C32,13.282,50.769,32.445,50.769,56z"/>
|
||||||
<path d="M8,22.564v2c17,0,31.486,14.102,31.486,31.436h2C41.486,37.563,26,22.564,8,22.564z"/>
|
<path d="M8,22.564v2c17,0,31.486,14.102,31.486,31.436h2C41.486,37.563,26,22.564,8,22.564z"/>
|
||||||
<path d="M30.205,56C30.205,43.784,20,33.846,8,33.846v2c11,0,20.205,9.041,20.205,20.154H30.205z"/>
|
<path d="M30.205,56C30.205,43.784,20,33.846,8,33.846v2c11,0,20.205,9.041,20.205,20.154H30.205z"/>
|
||||||
<path d="M16.103,56c0-4.439-3.612-8.051-8.052-8.051S0,51.561,0,56s3.611,8.051,8.051,8.051S16.103,60.439,16.103,56z M2,56
|
<path d="M16.103,56c0-4.439-3.612-8.051-8.052-8.051S0,51.561,0,56s3.611,8.051,8.051,8.051S16.103,60.439,16.103,56z M2,56
|
||||||
c0-3.336,2.715-6.051,6.051-6.051c3.337,0,6.052,2.715,6.052,6.051s-2.715,6.051-6.052,6.051C4.715,62.051,2,59.336,2,56z"/>
|
c0-3.336,2.715-6.051,6.051-6.051c3.337,0,6.052,2.715,6.052,6.051s-2.715,6.051-6.052,6.051C4.715,62.051,2,59.336,2,56z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
label={__('Downloads')}
|
label={__('Downloads')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.router('/downloads')
|
window.router('/downloads')
|
||||||
}}
|
}}
|
||||||
backgroundColor='#2080E4'
|
backgroundColor='#2080E4'
|
||||||
labelColor='white'
|
labelColor='white'
|
||||||
style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}}
|
style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}}
|
||||||
buttonStyle={{borderRadius: 5}}
|
buttonStyle={{borderRadius: 5}}
|
||||||
icon={<svg fill='white' style={{height: 30}} viewBox="0 0 548.176 548.176">
|
icon={<svg fill='white' style={{height: 30}} viewBox="0 0 548.176 548.176">
|
||||||
<path d="M524.326,297.352c-15.896-19.89-36.21-32.782-60.959-38.684c7.81-11.8,11.704-24.934,11.704-39.399
|
<path d="M524.326,297.352c-15.896-19.89-36.21-32.782-60.959-38.684c7.81-11.8,11.704-24.934,11.704-39.399
|
||||||
c0-20.177-7.139-37.401-21.409-51.678c-14.273-14.272-31.498-21.411-51.675-21.411c-18.083,0-33.879,5.901-47.39,17.703
|
c0-20.177-7.139-37.401-21.409-51.678c-14.273-14.272-31.498-21.411-51.675-21.411c-18.083,0-33.879,5.901-47.39,17.703
|
||||||
c-11.225-27.41-29.171-49.393-53.817-65.95c-24.646-16.562-51.818-24.842-81.514-24.842c-40.349,0-74.802,14.279-103.353,42.83
|
c-11.225-27.41-29.171-49.393-53.817-65.95c-24.646-16.562-51.818-24.842-81.514-24.842c-40.349,0-74.802,14.279-103.353,42.83
|
||||||
c-28.553,28.544-42.825,62.999-42.825,103.351c0,2.474,0.191,6.567,0.571,12.275c-22.459,10.469-40.349,26.171-53.676,47.106
|
c-28.553,28.544-42.825,62.999-42.825,103.351c0,2.474,0.191,6.567,0.571,12.275c-22.459,10.469-40.349,26.171-53.676,47.106
|
||||||
@ -206,82 +206,82 @@ class Header extends React.Component {
|
|||||||
c0-2.474,0.905-4.616,2.712-6.427c1.809-1.805,3.949-2.708,6.423-2.708h54.823c2.478,0,4.609,0.9,6.427,2.708
|
c0-2.474,0.905-4.616,2.712-6.427c1.809-1.805,3.949-2.708,6.423-2.708h54.823c2.478,0,4.609,0.9,6.427,2.708
|
||||||
c1.804,1.811,2.707,3.953,2.707,6.427v100.497h63.954c2.665,0,4.855,0.855,6.563,2.566c1.714,1.711,2.562,3.901,2.562,6.567
|
c1.804,1.811,2.707,3.953,2.707,6.427v100.497h63.954c2.665,0,4.855,0.855,6.563,2.566c1.714,1.711,2.562,3.901,2.562,6.567
|
||||||
C365.438,303.789,364.494,306.064,362.595,308.344z"/>
|
C365.438,303.789,364.494,306.064,362.595,308.344z"/>
|
||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
label={__('Top')}
|
label={__('Top')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.router('/top')
|
window.router('/top')
|
||||||
}}
|
}}
|
||||||
backgroundColor='#B1CE57'
|
backgroundColor='#B1CE57'
|
||||||
labelColor='white'
|
labelColor='white'
|
||||||
style={{height: 60, width: 120, borderRadius: 5, margin: 5, zIndex: 1}}
|
style={{height: 60, width: 120, borderRadius: 5, margin: 5, zIndex: 1}}
|
||||||
buttonStyle={{borderRadius: 5}}
|
buttonStyle={{borderRadius: 5}}
|
||||||
icon={<svg fill='white' style={{height: 30}} viewBox="0 0 284.929 284.929">
|
icon={<svg fill='white' style={{height: 30}} viewBox="0 0 284.929 284.929">
|
||||||
<g>
|
<g>
|
||||||
<path d="M17.128,167.872c1.903,1.902,4.093,2.854,6.567,2.854c2.474,0,4.664-0.952,6.567-2.854L142.466,55.666l112.208,112.206
|
<path d="M17.128,167.872c1.903,1.902,4.093,2.854,6.567,2.854c2.474,0,4.664-0.952,6.567-2.854L142.466,55.666l112.208,112.206
|
||||||
c1.902,1.902,4.093,2.854,6.563,2.854c2.478,0,4.668-0.952,6.57-2.854l14.274-14.277c1.902-1.902,2.847-4.093,2.847-6.563
|
c1.902,1.902,4.093,2.854,6.563,2.854c2.478,0,4.668-0.952,6.57-2.854l14.274-14.277c1.902-1.902,2.847-4.093,2.847-6.563
|
||||||
c0-2.475-0.951-4.665-2.847-6.567L149.028,7.419c-1.901-1.906-4.088-2.853-6.562-2.853s-4.665,0.95-6.567,2.853L2.856,140.464
|
c0-2.475-0.951-4.665-2.847-6.567L149.028,7.419c-1.901-1.906-4.088-2.853-6.562-2.853s-4.665,0.95-6.567,2.853L2.856,140.464
|
||||||
C0.95,142.367,0,144.554,0,147.034c0,2.468,0.953,4.658,2.856,6.561L17.128,167.872z"/>
|
C0.95,142.367,0,144.554,0,147.034c0,2.468,0.953,4.658,2.856,6.561L17.128,167.872z"/>
|
||||||
<path d="M149.028,117.055c-1.901-1.906-4.088-2.856-6.562-2.856s-4.665,0.953-6.567,2.856L2.856,250.1
|
<path d="M149.028,117.055c-1.901-1.906-4.088-2.856-6.562-2.856s-4.665,0.953-6.567,2.856L2.856,250.1
|
||||||
C0.95,252.003,0,254.192,0,256.67c0,2.472,0.953,4.661,2.856,6.564l14.272,14.276c1.903,1.903,4.093,2.848,6.567,2.848
|
C0.95,252.003,0,254.192,0,256.67c0,2.472,0.953,4.661,2.856,6.564l14.272,14.276c1.903,1.903,4.093,2.848,6.567,2.848
|
||||||
c2.474,0,4.664-0.951,6.567-2.848l112.204-112.209l112.208,112.209c1.902,1.903,4.093,2.852,6.563,2.852
|
c2.474,0,4.664-0.951,6.567-2.848l112.204-112.209l112.208,112.209c1.902,1.903,4.093,2.852,6.563,2.852
|
||||||
c2.478,0,4.668-0.948,6.57-2.852l14.274-14.276c1.902-1.903,2.847-4.093,2.847-6.564c0-2.478-0.951-4.667-2.847-6.57
|
c2.478,0,4.668-0.948,6.57-2.852l14.274-14.276c1.902-1.903,2.847-4.093,2.847-6.564c0-2.478-0.951-4.667-2.847-6.57
|
||||||
L149.028,117.055z"/>
|
L149.028,117.055z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
label={__('Activity')}
|
label={__('Activity')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.router('/activity')
|
window.router('/activity')
|
||||||
}}
|
}}
|
||||||
backgroundColor='#2a5cba'
|
backgroundColor='#2a5cba'
|
||||||
labelColor='white'
|
labelColor='white'
|
||||||
style={{height: 60, width: 150, borderRadius: 5, margin: 5, zIndex: 1}}
|
style={{height: 60, width: 150, borderRadius: 5, margin: 5, zIndex: 1}}
|
||||||
buttonStyle={{borderRadius: 5}}
|
buttonStyle={{borderRadius: 5}}
|
||||||
icon={<svg fill='white' style={{height: 30}} viewBox="0 0 352.352 352.352">
|
icon={<svg fill='white' style={{height: 30}} viewBox="0 0 352.352 352.352">
|
||||||
<g>
|
<g>
|
||||||
<path d="M255.432,37.172c-7.956-15.3-20.808-28.152-36.107-36.108c-4.284-2.448-10.404-0.612-11.628,4.896
|
<path d="M255.432,37.172c-7.956-15.3-20.808-28.152-36.107-36.108c-4.284-2.448-10.404-0.612-11.628,4.896
|
||||||
c-1.225,4.284-3.061,8.568-4.896,12.24C153.84-4.444,95.699,20.036,58.979,54.308c-41.616,39.168-62.424,102.816-45.9,157.896
|
c-1.225,4.284-3.061,8.568-4.896,12.24C153.84-4.444,95.699,20.036,58.979,54.308c-41.616,39.168-62.424,102.816-45.9,157.896
|
||||||
c1.837,7.344,12.24,4.283,11.017-3.061c-7.956-51.408,6.12-99.756,40.392-138.924c37.332-42.228,82.008-45.9,133.416-40.392
|
c1.837,7.344,12.24,4.283,11.017-3.061c-7.956-51.408,6.12-99.756,40.392-138.924c37.332-42.228,82.008-45.9,133.416-40.392
|
||||||
c-1.224,3.672-1.836,7.344-1.836,11.016c0,3.06,1.225,4.896,3.673,5.508c0,1.224,0,3.06,0.611,4.284
|
c-1.224,3.672-1.836,7.344-1.836,11.016c0,3.06,1.225,4.896,3.673,5.508c0,1.224,0,3.06,0.611,4.284
|
||||||
c3.672,7.956,12.853,6.732,20.196,5.508c11.016-1.224,22.644-3.672,32.436-8.568C256.656,45.74,257.268,40.231,255.432,37.172z
|
c3.672,7.956,12.853,6.732,20.196,5.508c11.016-1.224,22.644-3.672,32.436-8.568C256.656,45.74,257.268,40.231,255.432,37.172z
|
||||||
M210.144,40.844c-0.611,0-1.224,0-2.447,0c1.224-7.344,5.508-14.688,9.791-22.032c7.345,4.896,13.465,11.016,18.973,18.36
|
M210.144,40.844c-0.611,0-1.224,0-2.447,0c1.224-7.344,5.508-14.688,9.791-22.032c7.345,4.896,13.465,11.016,18.973,18.36
|
||||||
c-5.508,1.836-11.017,2.448-16.524,3.06C216.876,40.844,213.204,40.844,210.144,40.844z"/>
|
c-5.508,1.836-11.017,2.448-16.524,3.06C216.876,40.844,213.204,40.844,210.144,40.844z"/>
|
||||||
<path d="M297.048,318.08c58.752-74.664,80.172-204.408-9.18-265.608c-5.509-3.672-11.628,4.896-6.732,9.18
|
<path d="M297.048,318.08c58.752-74.664,80.172-204.408-9.18-265.608c-5.509-3.672-11.628,4.896-6.732,9.18
|
||||||
c71.604,67.32,63.036,173.196,4.896,246.636c-1.836-1.837-4.284-3.061-6.12-4.284c0-6.12-7.956-11.017-12.853-5.508
|
c71.604,67.32,63.036,173.196,4.896,246.636c-1.836-1.837-4.284-3.061-6.12-4.284c0-6.12-7.956-11.017-12.853-5.508
|
||||||
c-11.016,12.239-14.688,27.539-18.972,43.451c-1.224,4.896,2.448,10.404,7.956,10.404c17.136,0,34.884-3.672,50.796-11.016
|
c-11.016,12.239-14.688,27.539-18.972,43.451c-1.224,4.896,2.448,10.404,7.956,10.404c17.136,0,34.884-3.672,50.796-11.016
|
||||||
c4.284-2.448,4.896-9.181,1.836-12.24C303.78,324.812,300.72,321.752,297.048,318.08z M273.18,314.407
|
c4.284-2.448,4.896-9.181,1.836-12.24C303.78,324.812,300.72,321.752,297.048,318.08z M273.18,314.407
|
||||||
c5.508,4.896,10.404,10.404,15.3,15.912c-7.344,2.448-15.3,3.672-23.256,4.896C267.06,327.872,269.508,320.527,273.18,314.407z"/>
|
c5.508,4.896,10.404,10.404,15.3,15.912c-7.344,2.448-15.3,3.672-23.256,4.896C267.06,327.872,269.508,320.527,273.18,314.407z"/>
|
||||||
<path d="M219.936,321.14c-36.72,14.076-63.648,15.912-100.979-0.612c-27.54-12.239-51.408-31.212-71.604-52.02
|
<path d="M219.936,321.14c-36.72,14.076-63.648,15.912-100.979-0.612c-27.54-12.239-51.408-31.212-71.604-52.02
|
||||||
c4.896-3.672,9.792-7.344,15.3-11.016c4.896-3.673,4.896-9.793,0-13.465c-13.464-9.18-29.376-16.523-45.288-20.808
|
c4.896-3.672,9.792-7.344,15.3-11.016c4.896-3.673,4.896-9.793,0-13.465c-13.464-9.18-29.376-16.523-45.288-20.808
|
||||||
c-4.284-1.224-8.567,1.224-9.792,5.508c-3.06,11.017-4.284,21.42-2.447,33.048c1.224,7.956,5.508,20.809,13.464,24.48
|
c-4.284-1.224-8.567,1.224-9.792,5.508c-3.06,11.017-4.284,21.42-2.447,33.048c1.224,7.956,5.508,20.809,13.464,24.48
|
||||||
c3.672,1.836,9.792,0,9.18-5.508l0,0c3.06-1.836,6.12-3.061,9.18-4.896c19.584,28.764,51.408,50.796,83.232,63.036
|
c3.672,1.836,9.792,0,9.18-5.508l0,0c3.06-1.836,6.12-3.061,9.18-4.896c19.584,28.764,51.408,50.796,83.232,63.036
|
||||||
c30.6,12.24,80.784,22.644,105.264-7.344C229.728,327.26,226.668,318.691,219.936,321.14z M21.035,260.552
|
c30.6,12.24,80.784,22.644,105.264-7.344C229.728,327.26,226.668,318.691,219.936,321.14z M21.035,260.552
|
||||||
c-1.836-6.732-1.224-13.464,0-19.584c9.181,3.06,17.748,7.344,26.316,12.24c-6.732,6.731-14.688,11.628-22.644,17.136
|
c-1.836-6.732-1.224-13.464,0-19.584c9.181,3.06,17.748,7.344,26.316,12.24c-6.732,6.731-14.688,11.628-22.644,17.136
|
||||||
C23.483,266.06,21.647,263.611,21.035,260.552z"/>
|
C23.483,266.06,21.647,263.611,21.035,260.552z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className='fs0-85 pad0-75 column search-panel' style={{
|
<div className='fs0-85 pad0-75 column search-panel' style={{
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
marginTop: '-10px',
|
marginTop: '-10px',
|
||||||
zIndex: 2
|
zIndex: 2
|
||||||
}}>
|
}}>
|
||||||
<Search />
|
<Search />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</CardMedia>
|
||||||
</CardMedia>
|
</Card>
|
||||||
</Card>
|
<div className='clear-header-space' style={{transition: '1.0s'}} />
|
||||||
<div className='clear-header-space' style={{transition: '1.0s'}} />
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Header}
|
export {Header}
|
||||||
|
@ -12,6 +12,6 @@ import './css/izi/animations.css';
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<App />,
|
<App />,
|
||||||
document.getElementById('mount-point')
|
document.getElementById('mount-point')
|
||||||
);
|
);
|
||||||
|
@ -8,65 +8,65 @@ import MenuItem from 'material-ui/MenuItem';
|
|||||||
import Checkbox from 'material-ui/Checkbox';
|
import Checkbox from 'material-ui/Checkbox';
|
||||||
|
|
||||||
export default class InputFilesFilter extends Component {
|
export default class InputFilesFilter extends Component {
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
files: this.props.value || { min: 0, max: 50 },
|
files: this.props.value || { min: 0, max: 50 },
|
||||||
enabled: false || this.props.enabled,
|
enabled: false || this.props.enabled,
|
||||||
filesMax: this.props.filesMax || 100 // 1mb
|
filesMax: this.props.filesMax || 100 // 1mb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setState(val)
|
setState(val)
|
||||||
{
|
{
|
||||||
if(val.filesMax && this.state.files.max > val.filesMax)
|
if(val.filesMax && this.state.files.max > val.filesMax)
|
||||||
val.files = {min: this.state.files.min, max: val.filesMax};
|
val.files = {min: this.state.files.min, max: val.filesMax};
|
||||||
|
|
||||||
if(val.filesMax && this.state.files.min > val.filesMax)
|
if(val.filesMax && this.state.files.min > val.filesMax)
|
||||||
val.files = {min: 0, max: val.files ? val.files.max || this.state.files.max : this.state.files.max };
|
val.files = {min: 0, max: val.files ? val.files.max || this.state.files.max : this.state.files.max };
|
||||||
|
|
||||||
super.setState(val, () => {
|
super.setState(val, () => {
|
||||||
if(this.props.onChange)
|
if(this.props.onChange)
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
enabled: this.state.enabled,
|
enabled: this.state.enabled,
|
||||||
filesMax: this.state.filesMax,
|
filesMax: this.state.filesMax,
|
||||||
files: !this.state.enabled ? {min: 0, max: 0} : this.state.files
|
files: !this.state.enabled ? {min: 0, max: 0} : this.state.files
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='filter-row row inline w100p'>
|
<div className='filter-row row inline w100p'>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={__("Files filter")}
|
label={__("Files filter")}
|
||||||
checked={this.state.enabled}
|
checked={this.state.enabled}
|
||||||
style={{width: 150, display: 'flex', minWidth: 130}}
|
style={{width: 150, display: 'flex', minWidth: 130}}
|
||||||
onCheck={() => this.setState({enabled: !this.state.enabled})}
|
onCheck={() => this.setState({enabled: !this.state.enabled})}
|
||||||
/>
|
/>
|
||||||
<div className='filter-control-row row inline w100p' style={{opacity: this.state.enabled ? 1 : 0.4, transition: '0.5s', paddingLeft: 9}}>
|
<div className='filter-control-row row inline w100p' style={{opacity: this.state.enabled ? 1 : 0.4, transition: '0.5s', paddingLeft: 9}}>
|
||||||
<InputRange
|
<InputRange
|
||||||
maxValue={this.state.filesMax}
|
maxValue={this.state.filesMax}
|
||||||
minValue={0}
|
minValue={0}
|
||||||
value={this.state.files}
|
value={this.state.files}
|
||||||
style={this.props.style}
|
style={this.props.style}
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
onChange={files => this.setState({ files })}
|
onChange={files => this.setState({ files })}
|
||||||
/>
|
/>
|
||||||
<SelectField
|
<SelectField
|
||||||
floatingLabelText={__('Size type')}
|
floatingLabelText={__('Size type')}
|
||||||
value={this.state.filesMax}
|
value={this.state.filesMax}
|
||||||
onChange={(event, index, value) => this.setState({filesMax: value})}
|
onChange={(event, index, value) => this.setState({filesMax: value})}
|
||||||
className='filter-control-border'
|
className='filter-control-border'
|
||||||
>
|
>
|
||||||
<MenuItem value={10} primaryText={"10 " + __("Files or less")} />
|
<MenuItem value={10} primaryText={"10 " + __("Files or less")} />
|
||||||
<MenuItem value={100} primaryText={"100 " + __("Files or less")} />
|
<MenuItem value={100} primaryText={"100 " + __("Files or less")} />
|
||||||
<MenuItem value={1000} primaryText={"1000 " + __("Files or less")} />
|
<MenuItem value={1000} primaryText={"1000 " + __("Files or less")} />
|
||||||
<MenuItem value={10000} primaryText={"10000 " + __("Files or less")} />
|
<MenuItem value={10000} primaryText={"10000 " + __("Files or less")} />
|
||||||
<MenuItem value={100000} primaryText={"100000 " + __("Files or less")} />
|
<MenuItem value={100000} primaryText={"100000 " + __("Files or less")} />
|
||||||
<MenuItem value={1000000} primaryText={"1000000 " + __("Files or less")} />
|
<MenuItem value={1000000} primaryText={"1000000 " + __("Files or less")} />
|
||||||
</SelectField>
|
</SelectField>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,67 +8,67 @@ import MenuItem from 'material-ui/MenuItem';
|
|||||||
import Checkbox from 'material-ui/Checkbox';
|
import Checkbox from 'material-ui/Checkbox';
|
||||||
|
|
||||||
export default class InputSize extends Component {
|
export default class InputSize extends Component {
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
size: this.props.value || { min: 0, max: 500 * 1024 },
|
size: this.props.value || { min: 0, max: 500 * 1024 },
|
||||||
enabled: false || this.props.enabled,
|
enabled: false || this.props.enabled,
|
||||||
maxSize: this.props.maxSize || 1024 * 1024 // 1mb
|
maxSize: this.props.maxSize || 1024 * 1024 // 1mb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setState(val)
|
setState(val)
|
||||||
{
|
{
|
||||||
if(val.maxSize && this.state.size.max > val.maxSize)
|
if(val.maxSize && this.state.size.max > val.maxSize)
|
||||||
val.size = {min: this.state.size.min, max: val.maxSize};
|
val.size = {min: this.state.size.min, max: val.maxSize};
|
||||||
|
|
||||||
if(val.maxSize && this.state.size.min > val.maxSize)
|
if(val.maxSize && this.state.size.min > val.maxSize)
|
||||||
val.size = {min: 0, max: val.size ? val.size.max || this.state.size.max : this.state.size.max };
|
val.size = {min: 0, max: val.size ? val.size.max || this.state.size.max : this.state.size.max };
|
||||||
|
|
||||||
super.setState(val, () => {
|
super.setState(val, () => {
|
||||||
if(this.props.onChange)
|
if(this.props.onChange)
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
enabled: this.state.enabled,
|
enabled: this.state.enabled,
|
||||||
maxSize: this.state.maxSize,
|
maxSize: this.state.maxSize,
|
||||||
size: !this.state.enabled ? {min: 0, max: 0} : this.state.size
|
size: !this.state.enabled ? {min: 0, max: 0} : this.state.size
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='filter-row row inline w100p'>
|
<div className='filter-row row inline w100p'>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={__('Size filter')}
|
label={__('Size filter')}
|
||||||
checked={this.state.enabled}
|
checked={this.state.enabled}
|
||||||
style={{width: 150, display: 'flex', minWidth: 130}}
|
style={{width: 150, display: 'flex', minWidth: 130}}
|
||||||
onCheck={() => this.setState({enabled: !this.state.enabled})}
|
onCheck={() => this.setState({enabled: !this.state.enabled})}
|
||||||
/>
|
/>
|
||||||
<div className='filter-control-row row inline w100p' style={{opacity: this.state.enabled ? 1 : 0.4, transition: '0.5s', paddingLeft: 9}}>
|
<div className='filter-control-row row inline w100p' style={{opacity: this.state.enabled ? 1 : 0.4, transition: '0.5s', paddingLeft: 9}}>
|
||||||
<InputRange
|
<InputRange
|
||||||
maxValue={this.state.maxSize}
|
maxValue={this.state.maxSize}
|
||||||
minValue={0}
|
minValue={0}
|
||||||
value={this.state.size}
|
value={this.state.size}
|
||||||
formatLabel={size => formatBytes(size)}
|
formatLabel={size => formatBytes(size)}
|
||||||
style={this.props.style}
|
style={this.props.style}
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
onChange={size => this.setState({ size })}
|
onChange={size => this.setState({ size })}
|
||||||
/>
|
/>
|
||||||
<SelectField
|
<SelectField
|
||||||
floatingLabelText={__('Size type max')}
|
floatingLabelText={__('Size type max')}
|
||||||
value={this.state.maxSize}
|
value={this.state.maxSize}
|
||||||
onChange={(event, index, value) => this.setState({maxSize: value})}
|
onChange={(event, index, value) => this.setState({maxSize: value})}
|
||||||
className='filter-control-border'
|
className='filter-control-border'
|
||||||
>
|
>
|
||||||
<MenuItem value={1024} primaryText="KB" />
|
<MenuItem value={1024} primaryText="KB" />
|
||||||
<MenuItem value={1024 * 1024} primaryText="MB" />
|
<MenuItem value={1024 * 1024} primaryText="MB" />
|
||||||
<MenuItem value={1024 * 1024 * 100} primaryText="100 MB" />
|
<MenuItem value={1024 * 1024 * 100} primaryText="100 MB" />
|
||||||
<MenuItem value={1024 * 1024 * 1024} primaryText="GB" />
|
<MenuItem value={1024 * 1024 * 1024} primaryText="GB" />
|
||||||
<MenuItem value={10 * 1024 * 1024 * 1024} primaryText="10 GB" />
|
<MenuItem value={10 * 1024 * 1024 * 1024} primaryText="10 GB" />
|
||||||
<MenuItem value={100 * 1024 * 1024 * 1024} primaryText="100 GB" />
|
<MenuItem value={100 * 1024 * 1024 * 1024} primaryText="100 GB" />
|
||||||
<MenuItem value={1024 * 1024 * 1024 * 1024} primaryText="TB" />
|
<MenuItem value={1024 * 1024 * 1024 * 1024} primaryText="TB" />
|
||||||
</SelectField>
|
</SelectField>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,84 +2,84 @@ import React, { Component } from 'react';
|
|||||||
import singleton from './singleton'
|
import singleton from './singleton'
|
||||||
|
|
||||||
class PagesPie extends Component {
|
class PagesPie extends Component {
|
||||||
pie = [];
|
pie = [];
|
||||||
|
|
||||||
open(pages, params) {
|
open(pages, params) {
|
||||||
if (params && params.replace) {
|
if (params && params.replace) {
|
||||||
if (params.replace === 'all') {
|
if (params.replace === 'all') {
|
||||||
this.pie = [];
|
this.pie = [];
|
||||||
} else
|
} else
|
||||||
if (params.replace === 'last') {
|
if (params.replace === 'last') {
|
||||||
this.pie.pop();
|
this.pie.pop();
|
||||||
}
|
}
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
delete params.replace;
|
delete params.replace;
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (Array.isArray(pages)) {
|
if (Array.isArray(pages)) {
|
||||||
for (let i in pages) {
|
for (let i in pages) {
|
||||||
this.pie.push({
|
this.pie.push({
|
||||||
Page: pages[i],
|
Page: pages[i],
|
||||||
params: params
|
params: params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.pie.push({
|
this.pie.push({
|
||||||
Page: pages,
|
Page: pages,
|
||||||
params: params
|
params: params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
close(count) {
|
close(count) {
|
||||||
if (count && typeof count === 'number') {
|
if (count && typeof count === 'number') {
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
this.pie.pop();
|
this.pie.pop();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.pie.pop();
|
this.pie.pop();
|
||||||
}
|
}
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
findOpened(windowType) {
|
findOpened(windowType) {
|
||||||
for (let i in this.refs) {
|
for (let i in this.refs) {
|
||||||
if(this.refs[i] instanceof windowType)
|
if(this.refs[i] instanceof windowType)
|
||||||
return this.refs[i];
|
return this.refs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ОТРИСОВКА
|
// ОТРИСОВКА
|
||||||
render() {
|
render() {
|
||||||
if (this.pie.length > 0) {
|
if (this.pie.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={'pie full-size ' + (this.props.className || '')}
|
className={'pie full-size ' + (this.props.className || '')}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
this.pie.map(({Page, params}, index) => {
|
this.pie.map(({Page, params}, index) => {
|
||||||
let focus = false;
|
let focus = false;
|
||||||
if (index === this.pie.length-1) {
|
if (index === this.pie.length-1) {
|
||||||
focus = true;
|
focus = true;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Page
|
<Page
|
||||||
focused={focus}
|
focused={focus}
|
||||||
closeHandler={() => { index> 0 ? this.close() : null}}
|
closeHandler={() => { index> 0 ? this.close() : null}}
|
||||||
index={index}
|
index={index}
|
||||||
key={index}
|
key={index}
|
||||||
ref={index}
|
ref={index}
|
||||||
{...params}
|
{...params}
|
||||||
>
|
>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default singleton(PagesPie)
|
export default singleton(PagesPie)
|
@ -8,152 +8,152 @@ import FlatButton from 'material-ui/FlatButton';
|
|||||||
import RefreshIndicator from 'material-ui/RefreshIndicator';
|
import RefreshIndicator from 'material-ui/RefreshIndicator';
|
||||||
|
|
||||||
export default class RecentTorrents extends Component {
|
export default class RecentTorrents extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.torrents = [];
|
this.torrents = [];
|
||||||
this.torrentsAssoc = {};
|
this.torrentsAssoc = {};
|
||||||
this.displayQueue = [];
|
this.displayQueue = [];
|
||||||
this.displayQueueAssoc = {};
|
this.displayQueueAssoc = {};
|
||||||
this.maxQueueSize = 1000;
|
this.maxQueueSize = 1000;
|
||||||
this.maxDisplaySize = 10;
|
this.maxDisplaySize = 10;
|
||||||
this.state = {
|
this.state = {
|
||||||
pause: false,
|
pause: false,
|
||||||
searchingIndicator: false
|
searchingIndicator: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.torrentSocket.emit('recentTorrents', window.customLoader((data) => {
|
window.torrentSocket.emit('recentTorrents', window.customLoader((data) => {
|
||||||
if(data) {
|
if(data) {
|
||||||
this.torrents = data;
|
this.torrents = data;
|
||||||
//this.forceUpdate(); // вызывается через searchingIndicator
|
//this.forceUpdate(); // вызывается через searchingIndicator
|
||||||
}
|
}
|
||||||
|
|
||||||
this.displayNewTorrent = () => {
|
this.displayNewTorrent = () => {
|
||||||
if(!this.displayNewTorrent) {
|
if(!this.displayNewTorrent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.displayQueue.length == 0) {
|
if(this.displayQueue.length == 0) {
|
||||||
setTimeout(this.displayNewTorrent, 1000);
|
setTimeout(this.displayNewTorrent, 1000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const speed = 850;
|
const speed = 850;
|
||||||
|
|
||||||
if(this.state.pause) {
|
if(this.state.pause) {
|
||||||
setTimeout(this.displayNewTorrent, speed);
|
setTimeout(this.displayNewTorrent, speed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let torrent = this.displayQueue.shift();
|
let torrent = this.displayQueue.shift();
|
||||||
this.torrents.unshift(torrent);
|
this.torrents.unshift(torrent);
|
||||||
this.torrentsAssoc[torrent.hash] = torrent;
|
this.torrentsAssoc[torrent.hash] = torrent;
|
||||||
if(this.torrents.length > this.maxDisplaySize) {
|
if(this.torrents.length > this.maxDisplaySize) {
|
||||||
let toDelete = this.torrents.pop()
|
let toDelete = this.torrents.pop()
|
||||||
delete this.torrentsAssoc[toDelete.hash];
|
delete this.torrentsAssoc[toDelete.hash];
|
||||||
delete this.displayQueueAssoc[toDelete.hash];
|
delete this.displayQueueAssoc[toDelete.hash];
|
||||||
}
|
}
|
||||||
this.displayTorrentCounterValue = this.displayQueue.length;
|
this.displayTorrentCounterValue = this.displayQueue.length;
|
||||||
|
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
setTimeout(this.displayNewTorrent, speed);
|
setTimeout(this.displayNewTorrent, speed);
|
||||||
}
|
}
|
||||||
this.displayNewTorrent();
|
this.displayNewTorrent();
|
||||||
|
|
||||||
this.displayTorrentCounterValue = 0;
|
this.displayTorrentCounterValue = 0;
|
||||||
this.displayTorrentCounter = setInterval(() => {
|
this.displayTorrentCounter = setInterval(() => {
|
||||||
if(this.displayTorrentCounterValue != this.displayQueue.length) {
|
if(this.displayTorrentCounterValue != this.displayQueue.length) {
|
||||||
this.displayTorrentCounterValue = this.displayQueue.length;
|
this.displayTorrentCounterValue = this.displayQueue.length;
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
}, 40);
|
}, 40);
|
||||||
}, () => {
|
}, () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: true
|
searchingIndicator: true
|
||||||
});
|
});
|
||||||
}, () => {
|
}, () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: false
|
searchingIndicator: false
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
this.newTorrentFunc = (torrent) => {
|
this.newTorrentFunc = (torrent) => {
|
||||||
if(this.displayQueue.length < this.maxQueueSize) {
|
if(this.displayQueue.length < this.maxQueueSize) {
|
||||||
this.displayQueue.push(torrent);
|
this.displayQueue.push(torrent);
|
||||||
this.displayQueueAssoc[torrent.hash] = torrent;
|
this.displayQueueAssoc[torrent.hash] = torrent;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.torrentSocket.on('newTorrent', this.newTorrentFunc);
|
window.torrentSocket.on('newTorrent', this.newTorrentFunc);
|
||||||
|
|
||||||
this.tracketUpdate = (statistic) => {
|
this.tracketUpdate = (statistic) => {
|
||||||
if(statistic.hash in this.displayQueueAssoc)
|
if(statistic.hash in this.displayQueueAssoc)
|
||||||
{
|
{
|
||||||
Object.assign(this.displayQueueAssoc[statistic.hash], statistic);
|
Object.assign(this.displayQueueAssoc[statistic.hash], statistic);
|
||||||
if(statistic.hash in this.torrentsAssoc) {
|
if(statistic.hash in this.torrentsAssoc) {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('trackerTorrentUpdate', this.tracketUpdate);
|
window.torrentSocket.on('trackerTorrentUpdate', this.tracketUpdate);
|
||||||
}
|
}
|
||||||
pauseAndContinue() {
|
pauseAndContinue() {
|
||||||
this.setState({
|
this.setState({
|
||||||
pause: !this.state.pause
|
pause: !this.state.pause
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if(this.newTorrentFunc)
|
if(this.newTorrentFunc)
|
||||||
window.torrentSocket.off('newTorrent', this.newTorrentFunc);
|
window.torrentSocket.off('newTorrent', this.newTorrentFunc);
|
||||||
if(this.tracketUpdate)
|
if(this.tracketUpdate)
|
||||||
window.torrentSocket.off('trackerTorrentUpdate', this.tracketUpdate);
|
window.torrentSocket.off('trackerTorrentUpdate', this.tracketUpdate);
|
||||||
if(this.displayNewTorrent)
|
if(this.displayNewTorrent)
|
||||||
delete this.displayNewTorrent;
|
delete this.displayNewTorrent;
|
||||||
if(this.displayTorrentCounter)
|
if(this.displayTorrentCounter)
|
||||||
clearInterval(this.displayTorrentCounter);
|
clearInterval(this.displayTorrentCounter);
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const style = {
|
const style = {
|
||||||
refresh: {
|
refresh: {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if(this.state.searchingIndicator) {
|
if(this.state.searchingIndicator) {
|
||||||
return (
|
return (
|
||||||
<div className='pad1'>
|
<div className='pad1'>
|
||||||
<RefreshIndicator
|
<RefreshIndicator
|
||||||
size={50}
|
size={50}
|
||||||
left={0}
|
left={0}
|
||||||
top={0}
|
top={0}
|
||||||
loadingColor="#FF9800"
|
loadingColor="#FF9800"
|
||||||
status="loading"
|
status="loading"
|
||||||
style={style.refresh}
|
style={style.refresh}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.torrents || this.torrents.length == 0)
|
if(!this.torrents || this.torrents.length == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List className='animated recent-torrents torrents-container'>
|
<List className='animated recent-torrents torrents-container'>
|
||||||
<Subheader className='recent-title' inset={true}>
|
<Subheader className='recent-title' inset={true}>
|
||||||
<FlatButton style={{marginRight: '8px'}} primary={true} label={__('top')} labelStyle={{color: "#a4c639"}} onClick={() =>{
|
<FlatButton style={{marginRight: '8px'}} primary={true} label={__('top')} labelStyle={{color: "#a4c639"}} onClick={() =>{
|
||||||
window.router('/top');
|
window.router('/top');
|
||||||
}} />
|
}} />
|
||||||
<FlatButton style={{marginRight: '8px'}} label={!this.state.pause ? __('running') : __('stoped')} secondary={this.state.pause} primary={!this.state.pause} onClick={() =>{
|
<FlatButton style={{marginRight: '8px'}} label={!this.state.pause ? __('running') : __('stoped')} secondary={this.state.pause} primary={!this.state.pause} onClick={() =>{
|
||||||
this.pauseAndContinue()
|
this.pauseAndContinue()
|
||||||
}} />
|
}} />
|
||||||
{__('Most recent torrents')}{this.displayQueue.length > 0 ? ` (${__('and')} ${this.displayQueue.length} ${__('more')})` : null}
|
{__('Most recent torrents')}{this.displayQueue.length > 0 ? ` (${__('and')} ${this.displayQueue.length} ${__('more')})` : null}
|
||||||
</Subheader>
|
</Subheader>
|
||||||
<Divider />
|
<Divider />
|
||||||
{
|
{
|
||||||
this.torrents.map((torrent, index) =>{
|
this.torrents.map((torrent, index) =>{
|
||||||
return <TorrentLine key={index} torrent={torrent} />;
|
return <TorrentLine key={index} torrent={torrent} />;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,105 +9,105 @@
|
|||||||
// This link also includes instructions on opting out of this behavior.
|
// This link also includes instructions on opting out of this behavior.
|
||||||
|
|
||||||
const isLocalhost = Boolean(
|
const isLocalhost = Boolean(
|
||||||
window.location.hostname === 'localhost' ||
|
window.location.hostname === 'localhost' ||
|
||||||
// [::1] is the IPv6 localhost address.
|
// [::1] is the IPv6 localhost address.
|
||||||
window.location.hostname === '[::1]' ||
|
window.location.hostname === '[::1]' ||
|
||||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
window.location.hostname.match(
|
window.location.hostname.match(
|
||||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function register() {
|
export default function register() {
|
||||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
// The URL constructor is available in all browsers that support SW.
|
// The URL constructor is available in all browsers that support SW.
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
// from what our page is served on. This might happen if a CDN is used to
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
|
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
if (!isLocalhost) {
|
if (!isLocalhost) {
|
||||||
// Is not local host. Just register service worker
|
// Is not local host. Just register service worker
|
||||||
registerValidSW(swUrl);
|
registerValidSW(swUrl);
|
||||||
} else {
|
} else {
|
||||||
// This is running on localhost. Lets check if a service worker still exists or not.
|
// This is running on localhost. Lets check if a service worker still exists or not.
|
||||||
checkValidServiceWorker(swUrl);
|
checkValidServiceWorker(swUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerValidSW(swUrl) {
|
function registerValidSW(swUrl) {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register(swUrl)
|
.register(swUrl)
|
||||||
.then(registration => {
|
.then(registration => {
|
||||||
registration.onupdatefound = () => {
|
registration.onupdatefound = () => {
|
||||||
const installingWorker = registration.installing;
|
const installingWorker = registration.installing;
|
||||||
installingWorker.onstatechange = () => {
|
installingWorker.onstatechange = () => {
|
||||||
if (installingWorker.state === 'installed') {
|
if (installingWorker.state === 'installed') {
|
||||||
if (navigator.serviceWorker.controller) {
|
if (navigator.serviceWorker.controller) {
|
||||||
// At this point, the old content will have been purged and
|
// At this point, the old content will have been purged and
|
||||||
// the fresh content will have been added to the cache.
|
// the fresh content will have been added to the cache.
|
||||||
// It's the perfect time to display a "New content is
|
// It's the perfect time to display a "New content is
|
||||||
// available; please refresh." message in your web app.
|
// available; please refresh." message in your web app.
|
||||||
console.log('New content is available; please refresh.');
|
console.log('New content is available; please refresh.');
|
||||||
} else {
|
} else {
|
||||||
// At this point, everything has been precached.
|
// At this point, everything has been precached.
|
||||||
// It's the perfect time to display a
|
// It's the perfect time to display a
|
||||||
// "Content is cached for offline use." message.
|
// "Content is cached for offline use." message.
|
||||||
console.log('Content is cached for offline use.');
|
console.log('Content is cached for offline use.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error during service worker registration:', error);
|
console.error('Error during service worker registration:', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkValidServiceWorker(swUrl) {
|
function checkValidServiceWorker(swUrl) {
|
||||||
// Check if the service worker can be found. If it can't reload the page.
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
fetch(swUrl)
|
fetch(swUrl)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
if (
|
if (
|
||||||
response.status === 404 ||
|
response.status === 404 ||
|
||||||
response.headers.get('content-type').indexOf('javascript') === -1
|
response.headers.get('content-type').indexOf('javascript') === -1
|
||||||
) {
|
) {
|
||||||
// No service worker found. Probably a different app. Reload the page.
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
registration.unregister().then(() => {
|
registration.unregister().then(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Service worker found. Proceed as normal.
|
// Service worker found. Proceed as normal.
|
||||||
registerValidSW(swUrl);
|
registerValidSW(swUrl);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
console.log(
|
console.log(
|
||||||
'No internet connection found. App is running in offline mode.'
|
'No internet connection found. App is running in offline mode.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unregister() {
|
export function unregister() {
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
return navigator.serviceWorker.ready.then(registration => {
|
return navigator.serviceWorker.ready.then(registration => {
|
||||||
console.log("Unregister service worker");
|
console.log("Unregister service worker");
|
||||||
return registration.unregister();
|
return registration.unregister();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,52 +5,52 @@ import InputSize from './input-size';
|
|||||||
import FilesFilterInput from './input-files-filter';
|
import FilesFilterInput from './input-files-filter';
|
||||||
|
|
||||||
export default class AdvancedSearchControl extends Component {
|
export default class AdvancedSearchControl extends Component {
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
type: undefined,
|
type: undefined,
|
||||||
size: {min: 0, max: 0},
|
size: {min: 0, max: 0},
|
||||||
maxSize: 1024 * 1024 * 1024,
|
maxSize: 1024 * 1024 * 1024,
|
||||||
sizeEnabled: false,
|
sizeEnabled: false,
|
||||||
filesEnabled: false,
|
filesEnabled: false,
|
||||||
files: {min: 0, max: 0},
|
files: {min: 0, max: 0},
|
||||||
filesMax: 100,
|
filesMax: 100,
|
||||||
}
|
}
|
||||||
if(this.props.state)
|
if(this.props.state)
|
||||||
this.state = Object.assign(this.state, this.props.state)
|
this.state = Object.assign(this.state, this.props.state)
|
||||||
}
|
}
|
||||||
setState(val)
|
setState(val)
|
||||||
{
|
{
|
||||||
super.setState(val, (v) => {
|
super.setState(val, (v) => {
|
||||||
if(this.props.onChange)
|
if(this.props.onChange)
|
||||||
this.props.onChange(this.state)
|
this.props.onChange(this.state)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='column w100p' style={{maxWidth: 750, overflow: 'hidden', padding: '0px 18px 15px', background: 'white', borderRadius: 3}}>
|
<div className='column w100p' style={{maxWidth: 750, overflow: 'hidden', padding: '0px 18px 15px', background: 'white', borderRadius: 3}}>
|
||||||
<SelectField
|
<SelectField
|
||||||
floatingLabelText={__('Filter content type')}
|
floatingLabelText={__('Filter content type')}
|
||||||
value={this.state.type}
|
value={this.state.type}
|
||||||
onChange={(event, index, value) => this.setState({type: value})}
|
onChange={(event, index, value) => this.setState({type: value})}
|
||||||
>
|
>
|
||||||
<MenuItem value={undefined} primaryText="" />
|
<MenuItem value={undefined} primaryText="" />
|
||||||
<MenuItem value='video' primaryText={__('Video')} />
|
<MenuItem value='video' primaryText={__('Video')} />
|
||||||
<MenuItem value='audio' primaryText={__('Audio')} />
|
<MenuItem value='audio' primaryText={__('Audio')} />
|
||||||
<MenuItem value='pictures' primaryText={__('Pictures')} />
|
<MenuItem value='pictures' primaryText={__('Pictures')} />
|
||||||
<MenuItem value='books' primaryText={__('Books')} />
|
<MenuItem value='books' primaryText={__('Books')} />
|
||||||
<MenuItem value='application' primaryText={__('Applications')} />
|
<MenuItem value='application' primaryText={__('Applications')} />
|
||||||
<MenuItem value='archive' primaryText={__('Archives')} />
|
<MenuItem value='archive' primaryText={__('Archives')} />
|
||||||
<MenuItem value='disc' primaryText={__('Disk Images')} />
|
<MenuItem value='disc' primaryText={__('Disk Images')} />
|
||||||
</SelectField>
|
</SelectField>
|
||||||
<div className='w100p'>
|
<div className='w100p'>
|
||||||
<InputSize value={this.state.size} enabled={this.state.sizeEnabled} maxSize={this.state.maxSize} onChange={({size, maxSize, enabled}) => this.setState({size, maxSize, sizeEnabled: enabled})} />
|
<InputSize value={this.state.size} enabled={this.state.sizeEnabled} maxSize={this.state.maxSize} onChange={({size, maxSize, enabled}) => this.setState({size, maxSize, sizeEnabled: enabled})} />
|
||||||
</div>
|
</div>
|
||||||
<div className='w100p'>
|
<div className='w100p'>
|
||||||
<FilesFilterInput value={this.state.files} filesMax={this.state.filesMax} enabled={this.state.filesEnabled} onChange={({files, filesMax, enabled}) => this.setState({files, filesMax, filesEnabled: enabled})} />
|
<FilesFilterInput value={this.state.files} filesMax={this.state.filesMax} enabled={this.state.filesEnabled} onChange={({files, filesMax, enabled}) => this.setState({files, filesMax, filesEnabled: enabled})} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,130 +7,130 @@ import Divider from 'material-ui/Divider';
|
|||||||
import LinearProgress from 'material-ui/LinearProgress';
|
import LinearProgress from 'material-ui/LinearProgress';
|
||||||
|
|
||||||
export default class SearchResults extends Component {
|
export default class SearchResults extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<List style={{minWidth: '20em'}}>
|
<List style={{minWidth: '20em'}}>
|
||||||
{
|
{
|
||||||
(this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0)
|
(this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0)
|
||||||
|| (this.props.filesSearchResults && this.props.filesSearchResults.length > 0)
|
|| (this.props.filesSearchResults && this.props.filesSearchResults.length > 0)
|
||||||
?
|
?
|
||||||
<div>
|
<div>
|
||||||
<Subheader className='row center w100p' style={{paddingLeft: 0}} inset={true}><span>{__('Search results for')}</span> <span style={{marginLeft: '0.4em'}}><b>{this.props.searchText}</b></span></Subheader>
|
<Subheader className='row center w100p' style={{paddingLeft: 0}} inset={true}><span>{__('Search results for')}</span> <span style={{marginLeft: '0.4em'}}><b>{this.props.searchText}</b></span></Subheader>
|
||||||
<div className='w100p row center' style={{marginTop: '-16px'}}>{this.props.resultSelector}</div>
|
<div className='w100p row center' style={{marginTop: '-16px'}}>{this.props.resultSelector}</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0
|
this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0
|
||||||
?
|
?
|
||||||
this.props.torrentsSearchResults.map((torrent, index) =>{
|
this.props.torrentsSearchResults.map((torrent, index) =>{
|
||||||
return(
|
return(
|
||||||
<TorrentLine torrent={torrent} key={index} />
|
<TorrentLine torrent={torrent} key={index} />
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.moreTorrentsEnabled && !this.props.moreTorrentsIndicator
|
this.props.moreTorrentsEnabled && !this.props.moreTorrentsIndicator
|
||||||
?
|
?
|
||||||
<div>
|
<div>
|
||||||
<ListItem innerDivStyle={{textAlign: 'center', padding: '1em'}} primaryText={<span>{__('More Torrents')}</span>} onClick={() => {
|
<ListItem innerDivStyle={{textAlign: 'center', padding: '1em'}} primaryText={<span>{__('More Torrents')}</span>} onClick={() => {
|
||||||
if(this.props.onMoreTorrents)
|
if(this.props.onMoreTorrents)
|
||||||
this.props.onMoreTorrents();
|
this.props.onMoreTorrents();
|
||||||
}} />
|
}} />
|
||||||
<Divider />
|
<Divider />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.moreTorrentsIndicator
|
this.props.moreTorrentsIndicator
|
||||||
?
|
?
|
||||||
<div style={{padding: '0.8em'}}>
|
<div style={{padding: '0.8em'}}>
|
||||||
<LinearProgress mode="indeterminate" />
|
<LinearProgress mode="indeterminate" />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.filesSearchResults && this.props.filesSearchResults.length > 0
|
this.props.filesSearchResults && this.props.filesSearchResults.length > 0
|
||||||
?
|
?
|
||||||
this.props.filesSearchResults.map((torrent, index) =>{
|
this.props.filesSearchResults.map((torrent, index) =>{
|
||||||
return(
|
return(
|
||||||
<TorrentLine torrent={torrent} key={index} />
|
<TorrentLine torrent={torrent} key={index} />
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.moreFilesEnabled && !this.props.moreFilesIndicator
|
this.props.moreFilesEnabled && !this.props.moreFilesIndicator
|
||||||
?
|
?
|
||||||
<div>
|
<div>
|
||||||
<ListItem innerDivStyle={{textAlign: 'center', padding: '1em'}} primaryText={__('More Files')} onClick={() => {
|
<ListItem innerDivStyle={{textAlign: 'center', padding: '1em'}} primaryText={__('More Files')} onClick={() => {
|
||||||
if(this.props.onMoreFiles)
|
if(this.props.onMoreFiles)
|
||||||
this.props.onMoreFiles();
|
this.props.onMoreFiles();
|
||||||
}} />
|
}} />
|
||||||
<Divider />
|
<Divider />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.moreFilesIndicator
|
this.props.moreFilesIndicator
|
||||||
?
|
?
|
||||||
<div style={{padding: '0.8em'}}>
|
<div style={{padding: '0.8em'}}>
|
||||||
<LinearProgress mode="indeterminate" />
|
<LinearProgress mode="indeterminate" />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.props.torrentsSearchResults && this.props.torrentsSearchResults.length == 0
|
this.props.torrentsSearchResults && this.props.torrentsSearchResults.length == 0
|
||||||
&& this.props.filesSearchResults && this.props.filesSearchResults.length == 0
|
&& this.props.filesSearchResults && this.props.filesSearchResults.length == 0
|
||||||
&& !this.props.currentSearching
|
&& !this.props.currentSearching
|
||||||
?
|
?
|
||||||
<div className='row inline center w100p pad0-75'>
|
<div className='row inline center w100p pad0-75'>
|
||||||
<svg style={{fill: 'grey', height: '30px'}} viewBox="0 0 264.695 264.695">
|
<svg style={{fill: 'grey', height: '30px'}} viewBox="0 0 264.695 264.695">
|
||||||
<g>
|
<g>
|
||||||
<path d="M219.171,216.785c-4.762,0-10.322,2.3-16.672,6.881l-35.211-12.968l35.734-12.978
|
<path d="M219.171,216.785c-4.762,0-10.322,2.3-16.672,6.881l-35.211-12.968l35.734-12.978
|
||||||
c6.003,3.888,11.558,5.833,16.682,5.833c5.639,0,9.347-2.917,11.117-8.733c0.351-1.235,0.527-2.57,0.527-3.981
|
c6.003,3.888,11.558,5.833,16.682,5.833c5.639,0,9.347-2.917,11.117-8.733c0.351-1.235,0.527-2.57,0.527-3.981
|
||||||
c0-7.397-4.766-11.378-14.295-11.9c3.876-3.882,5.828-7.687,5.828-11.392c0-3.871-2.039-7.149-6.092-9.797
|
c0-7.397-4.766-11.378-14.295-11.9c3.876-3.882,5.828-7.687,5.828-11.392c0-3.871-2.039-7.149-6.092-9.797
|
||||||
c-2.118-1.049-4.325-1.584-6.615-1.584c-7.769,0-13.064,6.258-15.887,18.797l-61.941,23.039l-61.94-22.504
|
c-2.118-1.049-4.325-1.584-6.615-1.584c-7.769,0-13.064,6.258-15.887,18.797l-61.941,23.039l-61.94-22.504
|
||||||
c-2.823-12.885-8.125-19.332-15.885-19.332c-2.293,0-4.501,0.535-6.62,1.584c-3.876,2.647-5.82,5.926-5.82,9.797
|
c-2.823-12.885-8.125-19.332-15.885-19.332c-2.293,0-4.501,0.535-6.62,1.584c-3.876,2.647-5.82,5.926-5.82,9.797
|
||||||
c0,3.705,1.944,7.51,5.82,11.392c-9.701,0.522-14.555,4.503-14.555,11.901c0,1.41,0.179,2.746,0.526,3.98
|
c0,3.705,1.944,7.51,5.82,11.392c-9.701,0.522-14.555,4.503-14.555,11.901c0,1.41,0.179,2.746,0.526,3.98
|
||||||
c1.946,5.816,5.651,8.733,11.122,8.733c5.113,0,10.671-1.945,16.677-5.832l35.998,12.977l-35.476,12.698
|
c1.946,5.816,5.651,8.733,11.122,8.733c5.113,0,10.671-1.945,16.677-5.832l35.998,12.977l-35.476,12.698
|
||||||
c-6.175-4.406-11.637-6.611-16.402-6.611c-5.654,0-9.623,2.918-11.919,8.733c-0.348,1.235-0.526,2.553-0.526,3.975
|
c-6.175-4.406-11.637-6.611-16.402-6.611c-5.654,0-9.623,2.918-11.919,8.733c-0.348,1.235-0.526,2.553-0.526,3.975
|
||||||
c0,7.405,4.853,11.385,14.555,11.907c-3.876,3.883-5.82,7.688-5.82,11.393c0,3.869,1.944,7.134,5.82,9.797
|
c0,7.405,4.853,11.385,14.555,11.907c-3.876,3.883-5.82,7.688-5.82,11.393c0,3.869,1.944,7.134,5.82,9.797
|
||||||
c2.477,1.412,4.854,2.105,7.153,2.105c7.227,0,12.443-6.176,15.619-18.525l61.673-22.504l61.678,22.504
|
c2.477,1.412,4.854,2.105,7.153,2.105c7.227,0,12.443-6.176,15.619-18.525l61.673-22.504l61.678,22.504
|
||||||
c3.178,12.35,8.475,18.525,15.882,18.525c2.121,0,4.407-0.693,6.884-2.105c4.052-2.663,6.092-5.928,6.092-9.797
|
c3.178,12.35,8.475,18.525,15.882,18.525c2.121,0,4.407-0.693,6.884-2.105c4.052-2.663,6.092-5.928,6.092-9.797
|
||||||
c0-3.705-1.953-7.51-5.828-11.393c9.528-0.522,14.295-4.502,14.295-11.907c0-1.422-0.177-2.739-0.527-3.975
|
c0-3.705-1.953-7.51-5.828-11.393c9.528-0.522,14.295-4.502,14.295-11.907c0-1.422-0.177-2.739-0.527-3.975
|
||||||
C228.702,219.702,224.82,216.785,219.171,216.785z"/>
|
C228.702,219.702,224.82,216.785,219.171,216.785z"/>
|
||||||
<path d="M48.436,128.904c9.703,11.114,23.379,19.242,41.035,24.346v3.986c0,4.936,1.672,9.086,5.025,12.433
|
<path d="M48.436,128.904c9.703,11.114,23.379,19.242,41.035,24.346v3.986c0,4.936,1.672,9.086,5.025,12.433
|
||||||
c3.35,3.358,7.498,5.211,12.441,5.563c5.116,0.357,8.905-0.528,11.378-2.646c3.879,2.817,8.204,4.229,12.974,4.229
|
c3.35,3.358,7.498,5.211,12.441,5.563c5.116,0.357,8.905-0.528,11.378-2.646c3.879,2.817,8.204,4.229,12.974,4.229
|
||||||
c4.41,0,8.474-1.316,12.175-3.963c2.471,1.934,6.087,2.738,10.856,2.381c4.937-0.528,9.089-2.426,12.44-5.689
|
c4.41,0,8.474-1.316,12.175-3.963c2.471,1.934,6.087,2.738,10.856,2.381c4.937-0.528,9.089-2.426,12.44-5.689
|
||||||
c3.35-3.281,5.025-7.371,5.025-12.307v-2.91c19.057-4.945,33.795-13.237,44.21-24.898c10.059-11.109,15.087-24.253,15.087-39.435
|
c3.35-3.281,5.025-7.371,5.025-12.307v-2.91c19.057-4.945,33.795-13.237,44.21-24.898c10.059-11.109,15.087-24.253,15.087-39.435
|
||||||
c0-3.359-0.355-6.886-1.063-10.597c-3.525-22.571-13.938-41.201-31.229-55.844C180.612,7.856,158.464,0,132.347,0
|
c0-3.359-0.355-6.886-1.063-10.597c-3.525-22.571-13.938-41.201-31.229-55.844C180.612,7.856,158.464,0,132.347,0
|
||||||
c-26.123,0-48.27,7.767-66.44,23.282C48.61,38.118,38.289,56.825,34.937,79.396c-0.709,3.711-1.064,7.238-1.064,10.597
|
c-26.123,0-48.27,7.767-66.44,23.282C48.61,38.118,38.289,56.825,34.937,79.396c-0.709,3.711-1.064,7.238-1.064,10.597
|
||||||
C33.873,104.817,38.724,117.778,48.436,128.904L48.436,128.904z M152.865,60.749c5.206-6.085,11.514-9.13,18.922-9.13
|
C33.873,104.817,38.724,117.778,48.436,128.904L48.436,128.904z M152.865,60.749c5.206-6.085,11.514-9.13,18.922-9.13
|
||||||
c7.592,0,13.986,3.045,19.194,9.13c5.2,6.076,7.81,13.446,7.81,22.087c0,8.649-2.609,16.021-7.81,22.108
|
c7.592,0,13.986,3.045,19.194,9.13c5.2,6.076,7.81,13.446,7.81,22.087c0,8.649-2.609,16.021-7.81,22.108
|
||||||
c-5.208,6.097-11.603,9.13-19.194,9.13c-7.408,0-13.716-3.033-18.922-9.13c-5.211-6.087-7.814-13.459-7.814-22.108
|
c-5.208,6.097-11.603,9.13-19.194,9.13c-7.408,0-13.716-3.033-18.922-9.13c-5.211-6.087-7.814-13.459-7.814-22.108
|
||||||
C145.05,74.195,147.654,66.825,152.865,60.749z M124.805,121.428c2.556-3.307,5.065-4.968,7.542-4.968
|
C145.05,74.195,147.654,66.825,152.865,60.749z M124.805,121.428c2.556-3.307,5.065-4.968,7.542-4.968
|
||||||
c2.47,0,4.802,1.831,7.012,5.509c2.205,3.662,3.317,7.145,3.317,10.469c0,5.062-3.361,7.581-10.067,7.581
|
c2.47,0,4.802,1.831,7.012,5.509c2.205,3.662,3.317,7.145,3.317,10.469c0,5.062-3.361,7.581-10.067,7.581
|
||||||
c-4.414,0-7.677-1.136-9.792-3.396c-1.237-1.411-1.849-3.147-1.849-5.249C120.969,128.065,122.245,124.752,124.805,121.428z
|
c-4.414,0-7.677-1.136-9.792-3.396c-1.237-1.411-1.849-3.147-1.849-5.249C120.969,128.065,122.245,124.752,124.805,121.428z
|
||||||
M71.465,60.749c5.295-6.085,11.65-9.13,19.059-9.13c7.406,0,13.762,3.045,19.06,9.13c5.296,6.076,7.948,13.446,7.948,22.087
|
M71.465,60.749c5.295-6.085,11.65-9.13,19.059-9.13c7.406,0,13.762,3.045,19.06,9.13c5.296,6.076,7.948,13.446,7.948,22.087
|
||||||
c0,8.649-2.651,16.021-7.948,22.108c-5.297,6.097-11.654,9.13-19.06,9.13c-7.409,0-13.764-3.033-19.059-9.13
|
c0,8.649-2.651,16.021-7.948,22.108c-5.297,6.097-11.654,9.13-19.06,9.13c-7.409,0-13.764-3.033-19.059-9.13
|
||||||
c-5.292-6.087-7.944-13.459-7.944-22.108C63.521,74.195,66.173,66.825,71.465,60.749z"/>
|
c-5.292-6.087-7.944-13.459-7.944-22.108C63.521,74.195,66.173,66.825,71.465,60.749z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div className='fs0-85 pad0-75' style={{color: 'grey'}}>{__('no torrents for')} <b>{this.props.searchText}</b> {__('were found')}</div>
|
<div className='fs0-85 pad0-75' style={{color: 'grey'}}>{__('no torrents for')} <b>{this.props.searchText}</b> {__('were found')}</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,332 +17,332 @@ import _ from 'lodash'
|
|||||||
import singleton from './singleton';
|
import singleton from './singleton';
|
||||||
|
|
||||||
class Search extends Component {
|
class Search extends Component {
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
this.onSearchUpdate = () => {}
|
this.onSearchUpdate = () => {}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
searchingIndicator: false,
|
searchingIndicator: false,
|
||||||
safeSearchText: __('safe search enabled'),
|
safeSearchText: __('safe search enabled'),
|
||||||
safeSearchColor: 'rgb(0, 188, 212)',
|
safeSearchColor: 'rgb(0, 188, 212)',
|
||||||
moreTorrentsIndicator: false,
|
moreTorrentsIndicator: false,
|
||||||
moreFilesIndicator: false,
|
moreFilesIndicator: false,
|
||||||
orderBy: null,
|
orderBy: null,
|
||||||
orderDesc: false,
|
orderDesc: false,
|
||||||
advancedSearch: false,
|
advancedSearch: false,
|
||||||
}
|
}
|
||||||
this.searchLimit = 10
|
this.searchLimit = 10
|
||||||
this.advanced = {}
|
this.advanced = {}
|
||||||
this.searchError = undefined;
|
this.searchError = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
search(oldSearch) {
|
search(oldSearch) {
|
||||||
window.router('/')
|
window.router('/')
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: true
|
searchingIndicator: true
|
||||||
});
|
});
|
||||||
this.onSearchUpdate('indicator')
|
this.onSearchUpdate('indicator')
|
||||||
|
|
||||||
this.searchTorrents = [];
|
this.searchTorrents = [];
|
||||||
this.moreSearchTorrents = true;
|
this.moreSearchTorrents = true;
|
||||||
this.searchFiles = [];
|
this.searchFiles = [];
|
||||||
this.moreSearchFiles = true;
|
this.moreSearchFiles = true;
|
||||||
this.currentSearch = this.searchValue;
|
this.currentSearch = this.searchValue;
|
||||||
let queries = 2;
|
let queries = 2;
|
||||||
let searchTorrentsParams = {
|
let searchTorrentsParams = {
|
||||||
limit: this.searchLimit,
|
limit: this.searchLimit,
|
||||||
safeSearch: !this.notSafeSearch,
|
safeSearch: !this.notSafeSearch,
|
||||||
orderBy: this.state.orderBy,
|
orderBy: this.state.orderBy,
|
||||||
orderDesc: this.state.orderDesc,
|
orderDesc: this.state.orderDesc,
|
||||||
};
|
};
|
||||||
if(this.state.advancedSearch && this.advanced)
|
if(this.state.advancedSearch && this.advanced)
|
||||||
searchTorrentsParams = Object.assign(searchTorrentsParams, this.advanced);
|
searchTorrentsParams = Object.assign(searchTorrentsParams, this.advanced);
|
||||||
|
|
||||||
window.torrentSocket.emit('searchTorrent', oldSearch ? this.currentSearch : this.searchValue, searchTorrentsParams, window.customLoader((torrents) => {
|
window.torrentSocket.emit('searchTorrent', oldSearch ? this.currentSearch : this.searchValue, searchTorrentsParams, window.customLoader((torrents) => {
|
||||||
if(torrents) {
|
if(torrents) {
|
||||||
this.searchTorrents = torrents;
|
this.searchTorrents = torrents;
|
||||||
if(torrents.length != this.searchLimit)
|
if(torrents.length != this.searchLimit)
|
||||||
this.moreSearchTorrents = false;
|
this.moreSearchTorrents = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.moreSearchTorrents = false;
|
this.moreSearchTorrents = false;
|
||||||
}
|
}
|
||||||
if(--queries == 0) {
|
if(--queries == 0) {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: false
|
searchingIndicator: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.onSearchUpdate('torrents')
|
this.onSearchUpdate('torrents')
|
||||||
}));
|
}));
|
||||||
let searchFilesParams = {
|
let searchFilesParams = {
|
||||||
limit: this.searchLimit,
|
limit: this.searchLimit,
|
||||||
safeSearch: !this.notSafeSearch,
|
safeSearch: !this.notSafeSearch,
|
||||||
orderBy: this.state.orderBy,
|
orderBy: this.state.orderBy,
|
||||||
orderDesc: this.state.orderDesc,
|
orderDesc: this.state.orderDesc,
|
||||||
};
|
};
|
||||||
if(this.state.advancedSearch && this.advanced)
|
if(this.state.advancedSearch && this.advanced)
|
||||||
searchFilesParams = Object.assign(searchFilesParams, this.advanced);
|
searchFilesParams = Object.assign(searchFilesParams, this.advanced);
|
||||||
|
|
||||||
window.torrentSocket.emit('searchFiles', oldSearch ? this.currentSearch : this.searchValue, searchFilesParams, window.customLoader((torrents) => {
|
window.torrentSocket.emit('searchFiles', oldSearch ? this.currentSearch : this.searchValue, searchFilesParams, window.customLoader((torrents) => {
|
||||||
if(torrents) {
|
if(torrents) {
|
||||||
this.searchFiles = torrents;
|
this.searchFiles = torrents;
|
||||||
let files = 0;
|
let files = 0;
|
||||||
torrents.forEach((torrent) => {
|
torrents.forEach((torrent) => {
|
||||||
if(torrent.path && torrent.path.length > 0)
|
if(torrent.path && torrent.path.length > 0)
|
||||||
files += torrent.path.length
|
files += torrent.path.length
|
||||||
});
|
});
|
||||||
if(files != this.searchLimit)
|
if(files != this.searchLimit)
|
||||||
this.moreSearchFiles = false;
|
this.moreSearchFiles = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.moreSearchFiles = false;
|
this.moreSearchFiles = false;
|
||||||
}
|
}
|
||||||
if(--queries == 0) {
|
if(--queries == 0) {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: false
|
searchingIndicator: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.onSearchUpdate('files')
|
this.onSearchUpdate('files')
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
moreTorrents() {
|
moreTorrents() {
|
||||||
this.setState({moreTorrentsIndicator: true});
|
this.setState({moreTorrentsIndicator: true});
|
||||||
this.onSearchUpdate('indicator')
|
this.onSearchUpdate('indicator')
|
||||||
|
|
||||||
window.torrentSocket.emit('searchTorrent', this.currentSearch, {
|
window.torrentSocket.emit('searchTorrent', this.currentSearch, {
|
||||||
index: this.searchTorrents.length,
|
index: this.searchTorrents.length,
|
||||||
limit: this.searchLimit,
|
limit: this.searchLimit,
|
||||||
safeSearch: !this.notSafeSearch,
|
safeSearch: !this.notSafeSearch,
|
||||||
orderBy: this.state.orderBy,
|
orderBy: this.state.orderBy,
|
||||||
orderDesc: this.state.orderDesc,
|
orderDesc: this.state.orderDesc,
|
||||||
}, window.customLoader((torrents) => {
|
}, window.customLoader((torrents) => {
|
||||||
if(torrents) {
|
if(torrents) {
|
||||||
this.searchTorrents = this.searchTorrents.concat(torrents);
|
this.searchTorrents = this.searchTorrents.concat(torrents);
|
||||||
if(torrents.length != this.searchLimit)
|
if(torrents.length != this.searchLimit)
|
||||||
this.moreSearchTorrents = false;
|
this.moreSearchTorrents = false;
|
||||||
|
|
||||||
this.setState({moreTorrentsIndicator: false});
|
this.setState({moreTorrentsIndicator: false});
|
||||||
this.onSearchUpdate('more torrents')
|
this.onSearchUpdate('more torrents')
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
calcTorrentsFiles(torrents)
|
calcTorrentsFiles(torrents)
|
||||||
{
|
{
|
||||||
let files = 0;
|
let files = 0;
|
||||||
torrents.forEach((torrent) => {
|
torrents.forEach((torrent) => {
|
||||||
if(torrent.path && torrent.path.length > 0)
|
if(torrent.path && torrent.path.length > 0)
|
||||||
files += torrent.path.length
|
files += torrent.path.length
|
||||||
});
|
});
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
moreFiles() {
|
moreFiles() {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
this.searchFiles.forEach((torrent) => {
|
this.searchFiles.forEach((torrent) => {
|
||||||
if(torrent.path && torrent.path.length > 0)
|
if(torrent.path && torrent.path.length > 0)
|
||||||
index += torrent.path.length;
|
index += torrent.path.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({moreFilesIndicator: true});
|
this.setState({moreFilesIndicator: true});
|
||||||
this.onSearchUpdate('indicator')
|
this.onSearchUpdate('indicator')
|
||||||
|
|
||||||
window.torrentSocket.emit('searchFiles', this.currentSearch, {
|
window.torrentSocket.emit('searchFiles', this.currentSearch, {
|
||||||
index: index,
|
index: index,
|
||||||
limit: this.searchLimit,
|
limit: this.searchLimit,
|
||||||
safeSearch: !this.notSafeSearch,
|
safeSearch: !this.notSafeSearch,
|
||||||
orderBy: this.state.orderBy,
|
orderBy: this.state.orderBy,
|
||||||
orderDesc: this.state.orderDesc,
|
orderDesc: this.state.orderDesc,
|
||||||
}, window.customLoader((torrents) => {
|
}, window.customLoader((torrents) => {
|
||||||
if(torrents) {
|
if(torrents) {
|
||||||
this.searchFiles = this.searchFiles.concat(torrents);
|
this.searchFiles = this.searchFiles.concat(torrents);
|
||||||
|
|
||||||
if(this.calcTorrentsFiles(torrents) != this.searchLimit)
|
if(this.calcTorrentsFiles(torrents) != this.searchLimit)
|
||||||
this.moreSearchFiles = false;
|
this.moreSearchFiles = false;
|
||||||
|
|
||||||
this.mergeFiles()
|
this.mergeFiles()
|
||||||
|
|
||||||
this.setState({moreFilesIndicator: false});
|
this.setState({moreFilesIndicator: false});
|
||||||
this.onSearchUpdate('more files')
|
this.onSearchUpdate('more files')
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
mergeFiles()
|
mergeFiles()
|
||||||
{
|
{
|
||||||
for(let i = 0; i < this.searchFiles.length; i++)
|
for(let i = 0; i < this.searchFiles.length; i++)
|
||||||
{
|
{
|
||||||
for(let j = i + 1; j < this.searchFiles.length; j++)
|
for(let j = i + 1; j < this.searchFiles.length; j++)
|
||||||
{
|
{
|
||||||
if(this.searchFiles[i].hash != this.searchFiles[j].hash)
|
if(this.searchFiles[i].hash != this.searchFiles[j].hash)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if(!this.searchFiles[i].remove)
|
if(!this.searchFiles[i].remove)
|
||||||
{
|
{
|
||||||
this.searchFiles[i].path = this.searchFiles[i].path.concat(this.searchFiles[j].path)
|
this.searchFiles[i].path = this.searchFiles[i].path.concat(this.searchFiles[j].path)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.searchFiles[j].remove = true
|
this.searchFiles[j].remove = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.searchFiles = this.searchFiles.filter(torrent => !torrent.remove)
|
this.searchFiles = this.searchFiles.filter(torrent => !torrent.remove)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.newStatisticFunc = (statistic) => {
|
this.newStatisticFunc = (statistic) => {
|
||||||
if(statistic) {
|
if(statistic) {
|
||||||
this.stats = statistic;
|
this.stats = statistic;
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.torrentSocket.emit('statistic', window.customLoader(this.newStatisticFunc));
|
window.torrentSocket.emit('statistic', window.customLoader(this.newStatisticFunc));
|
||||||
window.torrentSocket.on('newStatistic', this.newStatisticFunc);
|
window.torrentSocket.on('newStatistic', this.newStatisticFunc);
|
||||||
|
|
||||||
this.remoteSearchTorrent = (torrents) => {
|
this.remoteSearchTorrent = (torrents) => {
|
||||||
if(!torrents)
|
if(!torrents)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(torrents.length === this.searchLimit)
|
if(torrents.length === this.searchLimit)
|
||||||
this.moreSearchTorrents = true;
|
this.moreSearchTorrents = true;
|
||||||
|
|
||||||
this.searchTorrents = _.unionBy(this.searchTorrents, torrents, 'hash')
|
this.searchTorrents = _.unionBy(this.searchTorrents, torrents, 'hash')
|
||||||
this.onSearchUpdate('remote torrents')
|
this.onSearchUpdate('remote torrents')
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('remoteSearchTorrent', this.remoteSearchTorrent);
|
window.torrentSocket.on('remoteSearchTorrent', this.remoteSearchTorrent);
|
||||||
|
|
||||||
this.remoteSearchFiles = (torrents) => {
|
this.remoteSearchFiles = (torrents) => {
|
||||||
if(!torrents)
|
if(!torrents)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(torrents.length > 0 && this.calcTorrentsFiles(torrents) === this.searchLimit)
|
if(torrents.length > 0 && this.calcTorrentsFiles(torrents) === this.searchLimit)
|
||||||
this.moreSearchFiles = true;
|
this.moreSearchFiles = true;
|
||||||
|
|
||||||
this.searchFiles = _.unionBy(this.searchFiles, torrents, 'hash')
|
this.searchFiles = _.unionBy(this.searchFiles, torrents, 'hash')
|
||||||
this.mergeFiles()
|
this.mergeFiles()
|
||||||
this.onSearchUpdate('remote files')
|
this.onSearchUpdate('remote files')
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('remoteSearchFiles', this.remoteSearchFiles);
|
window.torrentSocket.on('remoteSearchFiles', this.remoteSearchFiles);
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
if(this.newStatisticFunc)
|
if(this.newStatisticFunc)
|
||||||
window.torrentSocket.off('newStatistic', this.newStatisticFunc);
|
window.torrentSocket.off('newStatistic', this.newStatisticFunc);
|
||||||
|
|
||||||
if(this.remoteSearchTorrent)
|
if(this.remoteSearchTorrent)
|
||||||
window.torrentSocket.off('remoteSearchTorrent', this.remoteSearchTorrent);
|
window.torrentSocket.off('remoteSearchTorrent', this.remoteSearchTorrent);
|
||||||
|
|
||||||
if(this.remoteSearchFiles)
|
if(this.remoteSearchFiles)
|
||||||
window.torrentSocket.off('remoteSearchFiles', this.remoteSearchFiles);
|
window.torrentSocket.off('remoteSearchFiles', this.remoteSearchFiles);
|
||||||
}
|
}
|
||||||
setSafeSearch(ch) {
|
setSafeSearch(ch) {
|
||||||
this.notSafeSearch = ch;
|
this.notSafeSearch = ch;
|
||||||
if(ch)
|
if(ch)
|
||||||
{
|
{
|
||||||
return {safeSearchText: __('safe search disabled'), safeSearchColor: '#EC407A'}
|
return {safeSearchText: __('safe search disabled'), safeSearchColor: '#EC407A'}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {safeSearchText: __('safe search enabled'), safeSearchColor: 'rgb(0, 188, 212)'}
|
return {safeSearchText: __('safe search enabled'), safeSearchColor: 'rgb(0, 188, 212)'}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const style = {
|
const style = {
|
||||||
refresh: {
|
refresh: {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="column w100p center">
|
<div className="column w100p center">
|
||||||
<div className='row inline w100p pad0-75 search-row' style={{minWidth: '35em', backgroundColor: 'white', paddingTop: 0, paddingBottom: this.searchError ? 17 : 0, margin: 5, borderRadius: 3}}>
|
<div className='row inline w100p pad0-75 search-row' style={{minWidth: '35em', backgroundColor: 'white', paddingTop: 0, paddingBottom: this.searchError ? 17 : 0, margin: 5, borderRadius: 3}}>
|
||||||
<TextField
|
<TextField
|
||||||
style={{marginTop: -12}}
|
style={{marginTop: -12}}
|
||||||
hintText={__('Search torrent or file')}
|
hintText={__('Search torrent or file')}
|
||||||
floatingLabelText={__('What to search?')}
|
floatingLabelText={__('What to search?')}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
ref='searchInput'
|
ref='searchInput'
|
||||||
defaultValue={this.searchValue}
|
defaultValue={this.searchValue}
|
||||||
errorText={this.searchError}
|
errorText={this.searchError}
|
||||||
onKeyPress={(e) => {
|
onKeyPress={(e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
this.searchValue = e.target.value
|
this.searchValue = e.target.value
|
||||||
if(this.searchValue.length < 3 && this.searchValue.length > 0)
|
if(this.searchValue.length < 3 && this.searchValue.length > 0)
|
||||||
this.searchError = __('too short string for search');
|
this.searchError = __('too short string for search');
|
||||||
else
|
else
|
||||||
this.searchError = undefined;
|
this.searchError = undefined;
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{width: 25, height: 25, margin: 2}}>
|
<div style={{width: 25, height: 25, margin: 2}}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
ref='safeSearch'
|
ref='safeSearch'
|
||||||
checked={this.notSafeSearch ? true : false}
|
checked={this.notSafeSearch ? true : false}
|
||||||
checkedIcon={<Visibility />}
|
checkedIcon={<Visibility />}
|
||||||
uncheckedIcon={<VisibilityOff />}
|
uncheckedIcon={<VisibilityOff />}
|
||||||
iconStyle={{fill: this.state.safeSearchColor}}
|
iconStyle={{fill: this.state.safeSearchColor}}
|
||||||
onCheck={(ev, ch) => {
|
onCheck={(ev, ch) => {
|
||||||
this.setState(this.setSafeSearch(ch));
|
this.setState(this.setSafeSearch(ch));
|
||||||
}}
|
}}
|
||||||
style={{paddingBottom: '0.8em'}}
|
style={{paddingBottom: '0.8em'}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{width: 25, height: 25, margin: 2}}>
|
<div style={{width: 25, height: 25, margin: 2}}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
ref='advancedSearch'
|
ref='advancedSearch'
|
||||||
checked={this.state.advancedSearch}
|
checked={this.state.advancedSearch}
|
||||||
checkedIcon={<RemoveIcon />}
|
checkedIcon={<RemoveIcon />}
|
||||||
uncheckedIcon={<AddIcon />}
|
uncheckedIcon={<AddIcon />}
|
||||||
iconStyle={{fill: 'black'}}
|
iconStyle={{fill: 'black'}}
|
||||||
onCheck={(ev, ch) => {
|
onCheck={(ev, ch) => {
|
||||||
this.setState({advancedSearch: ch});
|
this.setState({advancedSearch: ch});
|
||||||
}}
|
}}
|
||||||
style={{paddingBottom: '0.8em'}}
|
style={{paddingBottom: '0.8em'}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RaisedButton style={{marginLeft: '10px'}} label={__('Search')} primary={true} onClick={() =>{
|
<RaisedButton style={{marginLeft: '10px'}} label={__('Search')} primary={true} onClick={() =>{
|
||||||
this.search()
|
this.search()
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
this.state.advancedSearch
|
this.state.advancedSearch
|
||||||
&&
|
&&
|
||||||
<AdvancedSearch onChange={(state) => {
|
<AdvancedSearch onChange={(state) => {
|
||||||
this.advanced = state;
|
this.advanced = state;
|
||||||
}} state={this.advanced} />
|
}} state={this.advanced} />
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.stats
|
this.stats
|
||||||
&&
|
&&
|
||||||
<TorrentsStatistic stats={this.stats} />
|
<TorrentsStatistic stats={this.stats} />
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.state.searchingIndicator
|
this.state.searchingIndicator
|
||||||
?
|
?
|
||||||
<div className='pad1'>
|
<div className='pad1'>
|
||||||
<RefreshIndicator
|
<RefreshIndicator
|
||||||
size={50}
|
size={50}
|
||||||
left={0}
|
left={0}
|
||||||
top={0}
|
top={0}
|
||||||
loadingColor="#FF9800"
|
loadingColor="#FF9800"
|
||||||
status="loading"
|
status="loading"
|
||||||
style={style.refresh}
|
style={style.refresh}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default singleton(Search)
|
export default singleton(Search)
|
@ -12,171 +12,171 @@ import {Tabs, Tab} from 'material-ui/Tabs';
|
|||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
export default class TopPage extends Page {
|
export default class TopPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Rats On The Boat - Torrents top');
|
this.setTitle('Rats On The Boat - Torrents top');
|
||||||
this.topTorrents = {};
|
this.topTorrents = {};
|
||||||
this.types = ['main', 'video', 'audio', 'books', 'pictures', 'application', 'archive']
|
this.types = ['main', 'video', 'audio', 'books', 'pictures', 'application', 'archive']
|
||||||
this.descriptions = {
|
this.descriptions = {
|
||||||
main: __('All'),
|
main: __('All'),
|
||||||
video: __('Video'),
|
video: __('Video'),
|
||||||
audio: __('Audio/Music'),
|
audio: __('Audio/Music'),
|
||||||
books: __('Books'),
|
books: __('Books'),
|
||||||
pictures: __('Pictures/Images'),
|
pictures: __('Pictures/Images'),
|
||||||
application: __('Apps/Games'),
|
application: __('Apps/Games'),
|
||||||
archive: __('Archives')
|
archive: __('Archives')
|
||||||
}
|
}
|
||||||
this.times = {
|
this.times = {
|
||||||
overall: __('Overall'),
|
overall: __('Overall'),
|
||||||
hours: __('Last hour'),
|
hours: __('Last hour'),
|
||||||
week: __('Last week'),
|
week: __('Last week'),
|
||||||
month: __('Last month')
|
month: __('Last month')
|
||||||
}
|
}
|
||||||
this.state = {type: 'main', time: 'overall'}
|
this.state = {type: 'main', time: 'overall'}
|
||||||
}
|
}
|
||||||
loadMoreTorrents(type, time)
|
loadMoreTorrents(type, time)
|
||||||
{
|
{
|
||||||
time = time ? time : this.state.time
|
time = time ? time : this.state.time
|
||||||
window.torrentSocket.emit('topTorrents',
|
window.torrentSocket.emit('topTorrents',
|
||||||
type == 'main' ? null : type,
|
type == 'main' ? null : type,
|
||||||
{index: (this.topTorrents[type] && this.topTorrents[type][time] && this.topTorrents[type][time].length) || 0, time},
|
{index: (this.topTorrents[type] && this.topTorrents[type][time] && this.topTorrents[type][time].length) || 0, time},
|
||||||
window.customLoader((data) => {
|
window.customLoader((data) => {
|
||||||
if(!this.topTorrents[type])
|
if(!this.topTorrents[type])
|
||||||
this.topTorrents[type] = {}
|
this.topTorrents[type] = {}
|
||||||
if(!this.topTorrents[type][time])
|
if(!this.topTorrents[type][time])
|
||||||
this.topTorrents[type][time] = []
|
this.topTorrents[type][time] = []
|
||||||
|
|
||||||
if(data && data.length > 0)
|
if(data && data.length > 0)
|
||||||
{
|
{
|
||||||
this.topTorrents[type][time] = this.topTorrents[type][time].concat(data);
|
this.topTorrents[type][time] = this.topTorrents[type][time].concat(data);
|
||||||
this._update()
|
this._update()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_update()
|
_update()
|
||||||
{
|
{
|
||||||
if(this.timeForce)
|
if(this.timeForce)
|
||||||
return
|
return
|
||||||
this.timeForce = setTimeout(() => {
|
this.timeForce = setTimeout(() => {
|
||||||
delete this.timeForce
|
delete this.timeForce
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}, 550)
|
}, 550)
|
||||||
}
|
}
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
super.componentDidMount();
|
super.componentDidMount();
|
||||||
for(const type of this.types)
|
for(const type of this.types)
|
||||||
{
|
{
|
||||||
this.loadMoreTorrents(type)
|
this.loadMoreTorrents(type)
|
||||||
}
|
}
|
||||||
this.remoteTopTorrents = ({torrents, type, time}) => {
|
this.remoteTopTorrents = ({torrents, type, time}) => {
|
||||||
if(!torrents)
|
if(!torrents)
|
||||||
return
|
return
|
||||||
|
|
||||||
time = time ? time : 'overall'
|
time = time ? time : 'overall'
|
||||||
type = type ? type : 'main'
|
type = type ? type : 'main'
|
||||||
this.topTorrents[type][time] = _.orderBy(_.unionBy(this.topTorrents[type][time], torrents, 'hash'), ['seeders'], ['desc'])
|
this.topTorrents[type][time] = _.orderBy(_.unionBy(this.topTorrents[type][time], torrents, 'hash'), ['seeders'], ['desc'])
|
||||||
this._update();
|
this._update();
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('remoteTopTorrents', this.remoteTopTorrents);
|
window.torrentSocket.on('remoteTopTorrents', this.remoteTopTorrents);
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
if(this.remoteTopTorrents)
|
if(this.remoteTopTorrents)
|
||||||
window.torrentSocket.off('remoteTopTorrents', this.remoteTopTorrents);
|
window.torrentSocket.off('remoteTopTorrents', this.remoteTopTorrents);
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='column center w100p'>
|
<div className='column center w100p'>
|
||||||
{
|
{
|
||||||
Object.keys(this.topTorrents).length == 0
|
Object.keys(this.topTorrents).length == 0
|
||||||
&&
|
&&
|
||||||
<div className='pad0-75 w100p '>
|
<div className='pad0-75 w100p '>
|
||||||
<LinearProgress mode="indeterminate" />
|
<LinearProgress mode="indeterminate" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<Tabs
|
<Tabs
|
||||||
className='w100p'
|
className='w100p'
|
||||||
value={this.state.type}
|
value={this.state.type}
|
||||||
onChange={(type) => {
|
onChange={(type) => {
|
||||||
this.setState({type});
|
this.setState({type});
|
||||||
// lost other content
|
// lost other content
|
||||||
if(!this.topTorrents[type][this.state.time])
|
if(!this.topTorrents[type][this.state.time])
|
||||||
{
|
{
|
||||||
this.loadMoreTorrents(type, this.state.time)
|
this.loadMoreTorrents(type, this.state.time)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}}
|
tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}}
|
||||||
inkBarStyle={{display: 'none'}}
|
inkBarStyle={{display: 'none'}}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
this.types.map((type, index) => {
|
this.types.map((type, index) => {
|
||||||
if(!this.topTorrents[type])
|
if(!this.topTorrents[type])
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab buttonStyle={type === this.state.type ? {fontWeight: 'bold'} : undefined} style={{minWidth: 150}} key={index} label={this.descriptions[type]} value={type}>
|
<Tab buttonStyle={type === this.state.type ? {fontWeight: 'bold'} : undefined} style={{minWidth: 150}} key={index} label={this.descriptions[type]} value={type}>
|
||||||
<Tabs
|
<Tabs
|
||||||
className='w100p'
|
className='w100p'
|
||||||
value={this.state.time}
|
value={this.state.time}
|
||||||
onChange={(time) => {
|
onChange={(time) => {
|
||||||
this.setState({time})
|
this.setState({time})
|
||||||
// lost other content
|
// lost other content
|
||||||
if(!this.topTorrents[type][time])
|
if(!this.topTorrents[type][time])
|
||||||
{
|
{
|
||||||
this.loadMoreTorrents(type, time)
|
this.loadMoreTorrents(type, time)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}}
|
tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}}
|
||||||
inkBarStyle={{display: 'none'}}
|
inkBarStyle={{display: 'none'}}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
Object.keys(this.times).map((time, index) => {
|
Object.keys(this.times).map((time, index) => {
|
||||||
const torrents = this.topTorrents[type][time];
|
const torrents = this.topTorrents[type][time];
|
||||||
|
|
||||||
if(!torrents)
|
if(!torrents)
|
||||||
return (
|
return (
|
||||||
<Tab buttonStyle={time === this.state.time ? {fontWeight: 'bold'} : undefined} style={{minWidth: 150}} key={index} label={this.times[time]} value={time}>
|
<Tab buttonStyle={time === this.state.time ? {fontWeight: 'bold'} : undefined} style={{minWidth: 150}} key={index} label={this.times[time]} value={time}>
|
||||||
<div className='pad0-75 w100p '>
|
<div className='pad0-75 w100p '>
|
||||||
<LinearProgress mode="indeterminate" />
|
<LinearProgress mode="indeterminate" />
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</Tab>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab buttonStyle={time === this.state.time ? {fontWeight: 'bold'} : undefined} style={{minWidth: 150}} key={index} label={this.times[time]} value={time}>
|
<Tab buttonStyle={time === this.state.time ? {fontWeight: 'bold'} : undefined} style={{minWidth: 150}} key={index} label={this.times[time]} value={time}>
|
||||||
<List style={{minWidth: '20em'}}>
|
<List style={{minWidth: '20em'}}>
|
||||||
{
|
{
|
||||||
torrents.map((torrent, index) => {
|
torrents.map((torrent, index) => {
|
||||||
return <TorrentLine key={index} torrent={torrent} />
|
return <TorrentLine key={index} torrent={torrent} />
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
torrents.length > 0
|
torrents.length > 0
|
||||||
&&
|
&&
|
||||||
<div>
|
<div>
|
||||||
<ListItem innerDivStyle={{textAlign: 'center', padding: '1em'}} primaryText={<span>{__('More Torrents')}</span>} onClick={() => {
|
<ListItem innerDivStyle={{textAlign: 'center', padding: '1em'}} primaryText={<span>{__('More Torrents')}</span>} onClick={() => {
|
||||||
this.loadMoreTorrents(type)
|
this.loadMoreTorrents(type)
|
||||||
}} />
|
}} />
|
||||||
<Divider />
|
<Divider />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</List>
|
</List>
|
||||||
</Tab>)
|
</Tab>)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Tab>
|
</Tab>
|
||||||
)
|
)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,34 +53,34 @@ const treeToTorrentFiles = (tree) => {
|
|||||||
arr.push(<ListItem
|
arr.push(<ListItem
|
||||||
key={file}
|
key={file}
|
||||||
primaryText={file}
|
primaryText={file}
|
||||||
secondaryText={formatBytes(tree[file].__sizeBT)}
|
secondaryText={formatBytes(tree[file].__sizeBT)}
|
||||||
nestedItems={treeToTorrentFiles(tree[file])}
|
nestedItems={treeToTorrentFiles(tree[file])}
|
||||||
primaryTogglesNestedList={true}
|
primaryTogglesNestedList={true}
|
||||||
innerDivStyle={{wordBreak: 'break-word'}}
|
innerDivStyle={{wordBreak: 'break-word'}}
|
||||||
leftIcon={tree[file] && Object.keys(tree[file]).length > 1 ? <FileFolder /> : contentIcon(fileTypeDetect({path: file}))}
|
leftIcon={tree[file] && Object.keys(tree[file]).length > 1 ? <FileFolder /> : contentIcon(fileTypeDetect({path: file}))}
|
||||||
/>);
|
/>);
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TorrentFiles = (props) => {
|
const TorrentFiles = (props) => {
|
||||||
let filesList = props.torrent.filesList;
|
let filesList = props.torrent.filesList;
|
||||||
let tree = buildFilesTree(filesList);
|
let tree = buildFilesTree(filesList);
|
||||||
return (
|
return (
|
||||||
<List className='w100p'>
|
<List className='w100p'>
|
||||||
{
|
{
|
||||||
filesList.length > 0
|
filesList.length > 0
|
||||||
?
|
?
|
||||||
<div className='w100p'>
|
<div className='w100p'>
|
||||||
<Subheader inset={true}>{__('Content of the torrent')}:</Subheader>
|
<Subheader inset={true}>{__('Content of the torrent')}:</Subheader>
|
||||||
{treeToTorrentFiles(tree)}
|
{treeToTorrentFiles(tree)}
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div className='column center'>
|
<div className='column center'>
|
||||||
<span className='pad0-75'>{__('Processing files')}...</span>
|
<span className='pad0-75'>{__('Processing files')}...</span>
|
||||||
<LinearProgress mode="indeterminate" />
|
<LinearProgress mode="indeterminate" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -89,84 +89,84 @@ const TorrentInformation = (props) => {
|
|||||||
let torrent = props.torrent;
|
let torrent = props.torrent;
|
||||||
return (
|
return (
|
||||||
<List className='w100p'>
|
<List className='w100p'>
|
||||||
<Subheader inset={true}>{__('Information about torrent')}</Subheader>
|
<Subheader inset={true}>{__('Information about torrent')}</Subheader>
|
||||||
<ListItem
|
<ListItem
|
||||||
//leftAvatar={<Avatar icon={<ActionAssignment />} backgroundColor={blue500} />}
|
//leftAvatar={<Avatar icon={<ActionAssignment />} backgroundColor={blue500} />}
|
||||||
rightIcon={<ActionInfo />}
|
rightIcon={<ActionInfo />}
|
||||||
primaryText={__('Torrent Name')}
|
primaryText={__('Torrent Name')}
|
||||||
secondaryText={<span className='break-word' style={{whiteSpace: 'normal'}}>{torrent.name}</span>}
|
secondaryText={<span className='break-word' style={{whiteSpace: 'normal'}}>{torrent.name}</span>}
|
||||||
/>
|
/>
|
||||||
<ListItem
|
<ListItem
|
||||||
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
||||||
rightIcon={<ActionInfo />}
|
rightIcon={<ActionInfo />}
|
||||||
primaryText={__('Torrent Size')}
|
primaryText={__('Torrent Size')}
|
||||||
secondaryText={formatBytes(torrent.size)}
|
secondaryText={formatBytes(torrent.size)}
|
||||||
/>
|
/>
|
||||||
<ListItem
|
<ListItem
|
||||||
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
||||||
rightIcon={<ActionInfo />}
|
rightIcon={<ActionInfo />}
|
||||||
primaryText={__('Torrent contains files')}
|
primaryText={__('Torrent contains files')}
|
||||||
secondaryText={torrent.files}
|
secondaryText={torrent.files}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if(!props.parent)
|
if(!props.parent)
|
||||||
return
|
return
|
||||||
|
|
||||||
props.parent.setState({
|
props.parent.setState({
|
||||||
value: 'files'
|
value: 'files'
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ListItem
|
<ListItem
|
||||||
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
||||||
rightIcon={<ActionInfo />}
|
rightIcon={<ActionInfo />}
|
||||||
primaryText={__('Indexed/Added torrent date')}
|
primaryText={__('Indexed/Added torrent date')}
|
||||||
secondaryText={moment(torrent.added * 1000).format('MMMM Do YYYY, hh:mm')}
|
secondaryText={moment(torrent.added * 1000).format('MMMM Do YYYY, hh:mm')}
|
||||||
/>
|
/>
|
||||||
<ListItem
|
<ListItem
|
||||||
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
||||||
rightIcon={<ActionInfo />}
|
rightIcon={<ActionInfo />}
|
||||||
primaryText={__('Content type')}
|
primaryText={__('Content type')}
|
||||||
secondaryText={torrent.contentType || 'unknown'}
|
secondaryText={torrent.contentType || 'unknown'}
|
||||||
/>
|
/>
|
||||||
<ListItem
|
<ListItem
|
||||||
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
// leftAvatar={<Avatar icon={<EditorInsertChart />} backgroundColor={yellow600} />}
|
||||||
rightIcon={<ActionInfo />}
|
rightIcon={<ActionInfo />}
|
||||||
primaryText={__('Category')}
|
primaryText={__('Category')}
|
||||||
secondaryText={torrent.contentCategory || 'unknown'}
|
secondaryText={torrent.contentCategory || 'unknown'}
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TorrentPage extends Page {
|
export default class TorrentPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
value: 'info',
|
value: 'info',
|
||||||
searchingIndicator: false,
|
searchingIndicator: false,
|
||||||
voting: false,
|
voting: false,
|
||||||
voted: false,
|
voted: false,
|
||||||
askDownloading: false,
|
askDownloading: false,
|
||||||
downloading: false,
|
downloading: false,
|
||||||
downloadProgress: {}
|
downloadProgress: {}
|
||||||
};
|
};
|
||||||
this.setTitle('Information about torrent');
|
this.setTitle('Information about torrent');
|
||||||
}
|
}
|
||||||
|
|
||||||
changeTab(tab) {
|
changeTab(tab) {
|
||||||
if(this.state.value != tab) {
|
if(this.state.value != tab) {
|
||||||
this.setState({
|
this.setState({
|
||||||
value: tab
|
value: tab
|
||||||
});
|
});
|
||||||
console.log('change');
|
console.log('change');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onSwipeRight() {
|
onSwipeRight() {
|
||||||
this.changeTab('files');
|
this.changeTab('files');
|
||||||
}
|
}
|
||||||
onSwipeLeft() {
|
onSwipeLeft() {
|
||||||
this.changeTab('info');
|
this.changeTab('info');
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange = (value) => {
|
handleChange = (value) => {
|
||||||
if(value == 'main') {
|
if(value == 'main') {
|
||||||
@ -174,18 +174,18 @@ export default class TorrentPage extends Page {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
value: value,
|
value: value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
getTorrentInfo() {
|
getTorrentInfo() {
|
||||||
window.torrentSocket.emit('torrent', this.props.hash, {files: true, peer: this.props.peer}, window.customLoader((data) => {
|
window.torrentSocket.emit('torrent', this.props.hash, {files: true, peer: this.props.peer}, window.customLoader((data) => {
|
||||||
if(data) {
|
if(data) {
|
||||||
this.torrent = data
|
this.torrent = data
|
||||||
this.setTitle(this.torrent.name + ' - Rats On The Boat');
|
this.setTitle(this.torrent.name + ' - Rats On The Boat');
|
||||||
if(this.torrent.contentCategory == 'xxx') {
|
if(this.torrent.contentCategory == 'xxx') {
|
||||||
this.setMetaTag('robots', 'noindex');
|
this.setMetaTag('robots', 'noindex');
|
||||||
}
|
}
|
||||||
//this.forceUpdate(); // вызывается через searchingIndicator
|
//this.forceUpdate(); // вызывается через searchingIndicator
|
||||||
|
|
||||||
// Получаем более новую статистику пира
|
// Получаем более новую статистику пира
|
||||||
@ -194,195 +194,195 @@ export default class TorrentPage extends Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, () => {
|
}, () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: true
|
searchingIndicator: true
|
||||||
});
|
});
|
||||||
}, () => {
|
}, () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchingIndicator: false
|
searchingIndicator: false
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
super.componentDidMount();
|
super.componentDidMount();
|
||||||
|
|
||||||
this.filesUpdated = (hash) => {
|
this.filesUpdated = (hash) => {
|
||||||
if(this.props.hash != hash)
|
if(this.props.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.getTorrentInfo();
|
this.getTorrentInfo();
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('filesReady', this.filesUpdated);
|
window.torrentSocket.on('filesReady', this.filesUpdated);
|
||||||
|
|
||||||
this.trackerUpdate = (info) => {
|
this.trackerUpdate = (info) => {
|
||||||
if(this.props.hash != info.hash)
|
if(this.props.hash != info.hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!this.torrent)
|
if(!this.torrent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object.assign(this.torrent, info);
|
Object.assign(this.torrent, info);
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('trackerTorrentUpdate', this.trackerUpdate);
|
window.torrentSocket.on('trackerTorrentUpdate', this.trackerUpdate);
|
||||||
|
|
||||||
this.onVotes = async ({hash, good, bad, selfVote}) => {
|
this.onVotes = async ({hash, good, bad, selfVote}) => {
|
||||||
if(this.props.hash != hash)
|
if(this.props.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!this.torrent)
|
if(!this.torrent)
|
||||||
return
|
return
|
||||||
|
|
||||||
this.torrent.good = good;
|
this.torrent.good = good;
|
||||||
this.torrent.bad = bad;
|
this.torrent.bad = bad;
|
||||||
this.state.voted = selfVote;
|
this.state.voted = selfVote;
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('votes', this.onVotes);
|
window.torrentSocket.on('votes', this.onVotes);
|
||||||
|
|
||||||
this.downloading = (hash) => {
|
this.downloading = (hash) => {
|
||||||
if(this.props.hash != hash)
|
if(this.props.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({downloading: true})
|
this.setState({downloading: true})
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('downloading', this.downloading);
|
window.torrentSocket.on('downloading', this.downloading);
|
||||||
|
|
||||||
this.downloadDone = (hash, canceled) => {
|
this.downloadDone = (hash, canceled) => {
|
||||||
if(this.props.hash != hash)
|
if(this.props.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
downloading: false,
|
downloading: false,
|
||||||
askDownloading: !canceled
|
askDownloading: !canceled
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('downloadDone', this.downloadDone);
|
window.torrentSocket.on('downloadDone', this.downloadDone);
|
||||||
|
|
||||||
this.downloadProgress = (hash, progress) => {
|
this.downloadProgress = (hash, progress) => {
|
||||||
if(this.props.hash != hash)
|
if(this.props.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({downloadProgress: progress})
|
this.setState({downloadProgress: progress})
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('downloadProgress', this.downloadProgress);
|
window.torrentSocket.on('downloadProgress', this.downloadProgress);
|
||||||
|
|
||||||
this.getTorrentInfo();
|
this.getTorrentInfo();
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if(this.filesUpdated)
|
if(this.filesUpdated)
|
||||||
window.torrentSocket.off('filesReady', this.filesUpdated);
|
window.torrentSocket.off('filesReady', this.filesUpdated);
|
||||||
if(this.trackerUpdate)
|
if(this.trackerUpdate)
|
||||||
window.torrentSocket.off('trackerTorrentUpdate', this.trackerUpdate);
|
window.torrentSocket.off('trackerTorrentUpdate', this.trackerUpdate);
|
||||||
if(this.onVotes)
|
if(this.onVotes)
|
||||||
window.torrentSocket.off('votes', this.onVotes);
|
window.torrentSocket.off('votes', this.onVotes);
|
||||||
if(this.torrent && this.torrent.contentCategory == 'xxx') {
|
if(this.torrent && this.torrent.contentCategory == 'xxx') {
|
||||||
this.removeMetaTag('robots');
|
this.removeMetaTag('robots');
|
||||||
}
|
}
|
||||||
if(this.downloading)
|
if(this.downloading)
|
||||||
window.torrentSocket.off('downloading', this.downloading);
|
window.torrentSocket.off('downloading', this.downloading);
|
||||||
if(this.downloadDone)
|
if(this.downloadDone)
|
||||||
window.torrentSocket.off('downloadDone', this.downloadDone);
|
window.torrentSocket.off('downloadDone', this.downloadDone);
|
||||||
if(this.downloadProgress)
|
if(this.downloadProgress)
|
||||||
window.torrentSocket.off('downloadProgress', this.downloadProgress);
|
window.torrentSocket.off('downloadProgress', this.downloadProgress);
|
||||||
}
|
}
|
||||||
vote(good) {
|
vote(good) {
|
||||||
if(!this.torrent)
|
if(!this.torrent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
voting: true
|
voting: true
|
||||||
});
|
});
|
||||||
window.torrentSocket.emit('vote', this.torrent.hash, !!good, window.customLoader((success) => {
|
window.torrentSocket.emit('vote', this.torrent.hash, !!good, window.customLoader((success) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
voted: true,
|
voted: true,
|
||||||
voting: false
|
voting: false
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const style = {
|
const style = {
|
||||||
refresh: {
|
refresh: {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if(this.state.searchingIndicator) {
|
if(this.state.searchingIndicator) {
|
||||||
return (
|
return (
|
||||||
<div className='pad1 w100p column center'>
|
<div className='pad1 w100p column center'>
|
||||||
<RefreshIndicator
|
<RefreshIndicator
|
||||||
size={50}
|
size={50}
|
||||||
left={0}
|
left={0}
|
||||||
top={0}
|
top={0}
|
||||||
loadingColor="#FF9800"
|
loadingColor="#FF9800"
|
||||||
status="loading"
|
status="loading"
|
||||||
style={style.refresh}
|
style={style.refresh}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let torrentRating;
|
let torrentRating;
|
||||||
if(this.torrent) {
|
if(this.torrent) {
|
||||||
torrentRating = Math.round(rating(this.torrent.good, this.torrent.bad) * 100);
|
torrentRating = Math.round(rating(this.torrent.good, this.torrent.bad) * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w100p column center">
|
<div className="w100p column center">
|
||||||
{
|
{
|
||||||
this.torrent
|
this.torrent
|
||||||
?
|
?
|
||||||
<Tabs
|
<Tabs
|
||||||
className='w100p'
|
className='w100p'
|
||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
>
|
>
|
||||||
<Tab label={__('Back to main')} value="main" />
|
<Tab label={__('Back to main')} value="main" />
|
||||||
<Tab label={__('Information')} value="info" >
|
<Tab label={__('Information')} value="info" >
|
||||||
<div className='column w100p'>
|
<div className='column w100p'>
|
||||||
<div className='row w100p torrent-information-row'>
|
<div className='row w100p torrent-information-row'>
|
||||||
<div className='info-table'>
|
<div className='info-table'>
|
||||||
<TorrentInformation torrent={this.torrent} parent={this} />
|
<TorrentInformation torrent={this.torrent} parent={this} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{flexBasis: '40%'}} className='column center w100p'>
|
<div style={{flexBasis: '40%'}} className='column center w100p'>
|
||||||
<img src={NoImage} className='pad0-75' style={{height: '200px'}} />
|
<img src={NoImage} className='pad0-75' style={{height: '200px'}} />
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
href={`magnet:?xt=urn:btih:${this.torrent.hash}`}
|
href={`magnet:?xt=urn:btih:${this.torrent.hash}`}
|
||||||
target="_self"
|
target="_self"
|
||||||
label="Magnet"
|
label="Magnet"
|
||||||
secondary={true}
|
secondary={true}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
window.open(`magnet:?xt=urn:btih:${this.torrent.hash}`, '_self')
|
window.open(`magnet:?xt=urn:btih:${this.torrent.hash}`, '_self')
|
||||||
}}
|
}}
|
||||||
icon={<svg fill='white' viewBox="0 0 24 24"><path d="M17.374 20.235c2.444-2.981 6.626-8.157 6.626-8.157l-3.846-3.092s-2.857 3.523-6.571 8.097c-4.312 5.312-11.881-2.41-6.671-6.671 4.561-3.729 8.097-6.57 8.097-6.57l-3.092-3.842s-5.173 4.181-8.157 6.621c-2.662 2.175-3.76 4.749-3.76 7.24 0 5.254 4.867 10.139 10.121 10.139 2.487 0 5.064-1.095 7.253-3.765zm4.724-7.953l-1.699 2.111-1.74-1.397 1.701-2.114 1.738 1.4zm-10.386-10.385l1.4 1.738-2.113 1.701-1.397-1.74 2.11-1.699z"/></svg>}
|
icon={<svg fill='white' viewBox="0 0 24 24"><path d="M17.374 20.235c2.444-2.981 6.626-8.157 6.626-8.157l-3.846-3.092s-2.857 3.523-6.571 8.097c-4.312 5.312-11.881-2.41-6.671-6.671 4.561-3.729 8.097-6.57 8.097-6.57l-3.092-3.842s-5.173 4.181-8.157 6.621c-2.662 2.175-3.76 4.749-3.76 7.24 0 5.254 4.867 10.139 10.121 10.139 2.487 0 5.064-1.095 7.253-3.765zm4.724-7.953l-1.699 2.111-1.74-1.397 1.701-2.114 1.738 1.4zm-10.386-10.385l1.4 1.738-2.113 1.701-1.397-1.74 2.11-1.699z"/></svg>}
|
||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
!this.state.askDownloading && !this.state.downloading
|
!this.state.askDownloading && !this.state.downloading
|
||||||
&&
|
&&
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
href={`magnet:?xt=urn:btih:${this.torrent.hash}`}
|
href={`magnet:?xt=urn:btih:${this.torrent.hash}`}
|
||||||
target="_self"
|
target="_self"
|
||||||
label={__('Download')}
|
label={__('Download')}
|
||||||
backgroundColor='#00C853'
|
backgroundColor='#00C853'
|
||||||
labelColor='white'
|
labelColor='white'
|
||||||
style={{marginTop: 8}}
|
style={{marginTop: 8}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState({askDownloading: true})
|
this.setState({askDownloading: true})
|
||||||
window.torrentSocket.emit('download', this.torrent)
|
window.torrentSocket.emit('download', this.torrent)
|
||||||
}}
|
}}
|
||||||
icon={
|
icon={
|
||||||
<svg viewBox="0 0 56 56" fill='white'>
|
<svg viewBox="0 0 56 56" fill='white'>
|
||||||
<g>
|
<g>
|
||||||
<path d="M35.586,41.586L31,46.172V28c0-1.104-0.896-2-2-2s-2,0.896-2,2v18.172l-4.586-4.586c-0.781-0.781-2.047-0.781-2.828,0
|
<path d="M35.586,41.586L31,46.172V28c0-1.104-0.896-2-2-2s-2,0.896-2,2v18.172l-4.586-4.586c-0.781-0.781-2.047-0.781-2.828,0
|
||||||
s-0.781,2.047,0,2.828l7.999,7.999c0.093,0.094,0.196,0.177,0.307,0.251c0.047,0.032,0.099,0.053,0.148,0.081
|
s-0.781,2.047,0,2.828l7.999,7.999c0.093,0.094,0.196,0.177,0.307,0.251c0.047,0.032,0.099,0.053,0.148,0.081
|
||||||
c0.065,0.036,0.127,0.075,0.196,0.103c0.065,0.027,0.133,0.042,0.2,0.062c0.058,0.017,0.113,0.04,0.173,0.051
|
c0.065,0.036,0.127,0.075,0.196,0.103c0.065,0.027,0.133,0.042,0.2,0.062c0.058,0.017,0.113,0.04,0.173,0.051
|
||||||
C28.738,52.986,28.869,53,29,53s0.262-0.014,0.392-0.04c0.06-0.012,0.115-0.034,0.173-0.051c0.067-0.02,0.135-0.035,0.2-0.062
|
C28.738,52.986,28.869,53,29,53s0.262-0.014,0.392-0.04c0.06-0.012,0.115-0.034,0.173-0.051c0.067-0.02,0.135-0.035,0.2-0.062
|
||||||
c0.069-0.028,0.131-0.067,0.196-0.103c0.05-0.027,0.101-0.049,0.148-0.081c0.11-0.074,0.213-0.157,0.307-0.251l7.999-7.999
|
c0.069-0.028,0.131-0.067,0.196-0.103c0.05-0.027,0.101-0.049,0.148-0.081c0.11-0.074,0.213-0.157,0.307-0.251l7.999-7.999
|
||||||
c0.781-0.781,0.781-2.047,0-2.828S36.367,40.805,35.586,41.586z"/>
|
c0.781-0.781,0.781-2.047,0-2.828S36.367,40.805,35.586,41.586z"/>
|
||||||
<path d="M47.835,18.986c-0.137-0.019-2.457-0.335-4.684,0.002C43.1,18.996,43.049,19,42.999,19c-0.486,0-0.912-0.354-0.987-0.85
|
<path d="M47.835,18.986c-0.137-0.019-2.457-0.335-4.684,0.002C43.1,18.996,43.049,19,42.999,19c-0.486,0-0.912-0.354-0.987-0.85
|
||||||
c-0.083-0.546,0.292-1.056,0.838-1.139c1.531-0.233,3.062-0.196,4.083-0.124C46.262,9.135,39.83,3,32.085,3
|
c-0.083-0.546,0.292-1.056,0.838-1.139c1.531-0.233,3.062-0.196,4.083-0.124C46.262,9.135,39.83,3,32.085,3
|
||||||
C27.388,3,22.667,5.379,19.8,9.129C21.754,10.781,23,13.246,23,16c0,0.553-0.447,1-1,1s-1-0.447-1-1
|
C27.388,3,22.667,5.379,19.8,9.129C21.754,10.781,23,13.246,23,16c0,0.553-0.447,1-1,1s-1-0.447-1-1
|
||||||
c0-2.462-1.281-4.627-3.209-5.876c-0.227-0.147-0.462-0.277-0.702-0.396c-0.069-0.034-0.139-0.069-0.21-0.101
|
c0-2.462-1.281-4.627-3.209-5.876c-0.227-0.147-0.462-0.277-0.702-0.396c-0.069-0.034-0.139-0.069-0.21-0.101
|
||||||
@ -391,120 +391,120 @@ export default class TorrentPage extends Page {
|
|||||||
l0.012,0.21l-0.009,0.16C7.008,16.744,7,16.873,7,17v0.63l-0.567,0.271C2.705,19.688,0,24,0,28.154C0,34.135,4.865,39,10.845,39H25
|
l0.012,0.21l-0.009,0.16C7.008,16.744,7,16.873,7,17v0.63l-0.567,0.271C2.705,19.688,0,24,0,28.154C0,34.135,4.865,39,10.845,39H25
|
||||||
V28c0-2.209,1.791-4,4-4s4,1.791,4,4v11h2.353c0.059,0,0.116-0.005,0.174-0.009l0.198-0.011l0.271,0.011
|
V28c0-2.209,1.791-4,4-4s4,1.791,4,4v11h2.353c0.059,0,0.116-0.005,0.174-0.009l0.198-0.011l0.271,0.011
|
||||||
C36.053,38.995,36.11,39,36.169,39h9.803C51.501,39,56,34.501,56,28.972C56,24.161,52.49,19.872,47.835,18.986z"/>
|
C36.053,38.995,36.11,39,36.169,39h9.803C51.501,39,56,34.501,56,28.972C56,24.161,52.49,19.872,47.835,18.986z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.state.downloading
|
this.state.downloading
|
||||||
&&
|
&&
|
||||||
<div className='column center pad0-75' style={{width: '300px'}}>
|
<div className='column center pad0-75' style={{width: '300px'}}>
|
||||||
<div className='fs0-75' style={{color: 'rgb(0, 188, 212)'}}>{__('downloading')} {this.state.downloadProgress && (this.state.downloadProgress.progress * 100).toFixed(1)}%</div>
|
<div className='fs0-75' style={{color: 'rgb(0, 188, 212)'}}>{__('downloading')} {this.state.downloadProgress && (this.state.downloadProgress.progress * 100).toFixed(1)}%</div>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
style={{marginTop: 3}}
|
style={{marginTop: 3}}
|
||||||
mode="determinate"
|
mode="determinate"
|
||||||
value={this.state.downloadProgress && (this.state.downloadProgress.progress ? this.state.downloadProgress.progress : 0) * 100}
|
value={this.state.downloadProgress && (this.state.downloadProgress.progress ? this.state.downloadProgress.progress : 0) * 100}
|
||||||
/>
|
/>
|
||||||
<FlatButton
|
<FlatButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.torrentSocket.emit('downloadCancel', this.torrent.hash)
|
window.torrentSocket.emit('downloadCancel', this.torrent.hash)
|
||||||
}}
|
}}
|
||||||
label={__('Cancel download')}
|
label={__('Cancel download')}
|
||||||
secondary={true}
|
secondary={true}
|
||||||
icon={<svg fill='rgb(255, 64, 129)' viewBox="0 0 18 18"><path d="M9 1C4.58 1 1 4.58 1 9s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4 10.87L11.87 13 9 10.13 6.13 13 5 11.87 7.87 9 5 6.13 6.13 5 9 7.87 11.87 5 13 6.13 10.13 9 13 11.87z"/></svg>}
|
icon={<svg fill='rgb(255, 64, 129)' viewBox="0 0 18 18"><path d="M9 1C4.58 1 1 4.58 1 9s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4 10.87L11.87 13 9 10.13 6.13 13 5 11.87 7.87 9 5 6.13 6.13 5 9 7.87 11.87 5 13 6.13 10.13 9 13 11.87z"/></svg>}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className='fs0-75 pad0-75 center column' style={{color: 'rgba(0, 0, 0, 0.541176)'}}><div>BTIH:</div><div>{this.torrent.hash}</div></div>
|
<div className='fs0-75 pad0-75 center column' style={{color: 'rgba(0, 0, 0, 0.541176)'}}><div>BTIH:</div><div>{this.torrent.hash}</div></div>
|
||||||
{
|
{
|
||||||
this.torrent.seeders || this.torrent.leechers || this.torrent.completed
|
this.torrent.seeders || this.torrent.leechers || this.torrent.completed
|
||||||
?
|
?
|
||||||
<div className='fs0-85 pad0-75 center column'>
|
<div className='fs0-85 pad0-75 center column'>
|
||||||
<div className='pad0-25' style={{color: '#00C853'}}>{__('seeders')}: {this.torrent.seeders}</div>
|
<div className='pad0-25' style={{color: '#00C853'}}>{__('seeders')}: {this.torrent.seeders}</div>
|
||||||
<div className='pad0-25' style={{color: '#AA00FF'}}>{__('leechers')}: {this.torrent.leechers}</div>
|
<div className='pad0-25' style={{color: '#AA00FF'}}>{__('leechers')}: {this.torrent.leechers}</div>
|
||||||
<div className='pad0-25' style={{color: '#FF6D00'}}>{__('completed')}: {this.torrent.completed}</div>
|
<div className='pad0-25' style={{color: '#FF6D00'}}>{__('completed')}: {this.torrent.completed}</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
!this.state.voted && !this.state.voting
|
!this.state.voted && !this.state.voting
|
||||||
?
|
?
|
||||||
<div className='row pad0-25'>
|
<div className='row pad0-25'>
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
label={__('Good') + ` (${this.torrent.good})`}
|
label={__('Good') + ` (${this.torrent.good})`}
|
||||||
labelColor="white"
|
labelColor="white"
|
||||||
backgroundColor="#00C853"
|
backgroundColor="#00C853"
|
||||||
icon={
|
icon={
|
||||||
<svg viewBox="0 0 489.543 489.543" fill="white">
|
<svg viewBox="0 0 489.543 489.543" fill="white">
|
||||||
<g>
|
<g>
|
||||||
<path d="M270.024,0c-22.6,0-15,48.3-15,48.3s-48.3,133.2-94.5,168.7c-9.9,10.4-16.1,21.9-20,31.3l0,0l0,0
|
<path d="M270.024,0c-22.6,0-15,48.3-15,48.3s-48.3,133.2-94.5,168.7c-9.9,10.4-16.1,21.9-20,31.3l0,0l0,0
|
||||||
c-0.9,2.3-1.7,4.5-2.4,6.5c-3.1,6.3-9.7,16-23.8,24.5l46.2,200.9c0,0,71.5,9.3,143.2,7.8c28.7,2.3,59.1,2.5,83.3-2.7
|
c-0.9,2.3-1.7,4.5-2.4,6.5c-3.1,6.3-9.7,16-23.8,24.5l46.2,200.9c0,0,71.5,9.3,143.2,7.8c28.7,2.3,59.1,2.5,83.3-2.7
|
||||||
c82.2-17.5,61.6-74.8,61.6-74.8c44.3-33.3,19.1-74.9,19.1-74.9c39.4-41.1,0.7-75.6,0.7-75.6s21.3-33.2-6.2-58.3
|
c82.2-17.5,61.6-74.8,61.6-74.8c44.3-33.3,19.1-74.9,19.1-74.9c39.4-41.1,0.7-75.6,0.7-75.6s21.3-33.2-6.2-58.3
|
||||||
c-34.3-31.4-127.4-10.5-127.4-10.5l0,0c-6.5,1.1-13.4,2.5-20.8,4.3c0,0-32.2,15,0-82.7C346.324,15.1,292.624,0,270.024,0z"/>
|
c-34.3-31.4-127.4-10.5-127.4-10.5l0,0c-6.5,1.1-13.4,2.5-20.8,4.3c0,0-32.2,15,0-82.7C346.324,15.1,292.624,0,270.024,0z"/>
|
||||||
<path d="M127.324,465.7l-35-166.3c-2-9.5-11.6-17.3-21.3-17.3h-66.8l-0.1,200.8h109.1C123.024,483,129.324,475.2,127.324,465.7z"
|
<path d="M127.324,465.7l-35-166.3c-2-9.5-11.6-17.3-21.3-17.3h-66.8l-0.1,200.8h109.1C123.024,483,129.324,475.2,127.324,465.7z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
onClick={() => this.vote(true)}
|
onClick={() => this.vote(true)}
|
||||||
/>
|
/>
|
||||||
<RaisedButton
|
<RaisedButton
|
||||||
style={{marginLeft: '9px'}}
|
style={{marginLeft: '9px'}}
|
||||||
label={__('Bad') + ` (${this.torrent.bad})`}
|
label={__('Bad') + ` (${this.torrent.bad})`}
|
||||||
labelColor="white"
|
labelColor="white"
|
||||||
backgroundColor="#D50000"
|
backgroundColor="#D50000"
|
||||||
icon={
|
icon={
|
||||||
<svg viewBox="0 0 487.643 487.643" fill="white">
|
<svg viewBox="0 0 487.643 487.643" fill="white">
|
||||||
<g>
|
<g>
|
||||||
<path d="M113.869,209.443l46-200.1c0,0,71.2-9.3,142.6-7.8c28.5-2.3,58.9-2.5,83,2.7c81.9,17.4,61.4,74.5,61.4,74.5
|
<path d="M113.869,209.443l46-200.1c0,0,71.2-9.3,142.6-7.8c28.5-2.3,58.9-2.5,83,2.7c81.9,17.4,61.4,74.5,61.4,74.5
|
||||||
c44.2,33.2,19,74.6,19,74.6c39.2,41,0.7,75.3,0.7,75.3s21.2,33-6.1,58c-34.2,31.2-126.9,10.5-126.9,10.5l0,0
|
c44.2,33.2,19,74.6,19,74.6c39.2,41,0.7,75.3,0.7,75.3s21.2,33-6.1,58c-34.2,31.2-126.9,10.5-126.9,10.5l0,0
|
||||||
c-6.4-1.1-13.3-2.5-20.7-4.2c0,0-32.1-15,0,82.4s-21.4,112.3-43.9,112.3s-15-48.1-15-48.1s-48.1-132.7-94.1-168
|
c-6.4-1.1-13.3-2.5-20.7-4.2c0,0-32.1-15,0,82.4s-21.4,112.3-43.9,112.3s-15-48.1-15-48.1s-48.1-132.7-94.1-168
|
||||||
c-9.9-10.4-16.1-21.8-19.9-31.2l0,0l0,0c-0.9-2.3-1.7-4.5-2.4-6.5C134.469,227.543,127.869,217.843,113.869,209.443z
|
c-9.9-10.4-16.1-21.8-19.9-31.2l0,0l0,0c-0.9-2.3-1.7-4.5-2.4-6.5C134.469,227.543,127.869,217.843,113.869,209.443z
|
||||||
M70.869,206.643c9.7,0,19.2-7.7,21.2-17.2l34.8-165.6c2-9.5-4.3-17.2-14-17.2H4.169l0.1,200H70.869z"/>
|
M70.869,206.643c9.7,0,19.2-7.7,21.2-17.2l34.8-165.6c2-9.5-4.3-17.2-14-17.2H4.169l0.1,200H70.869z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
onClick={() => this.vote(false)}
|
onClick={() => this.vote(false)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
this.state.voting
|
this.state.voting
|
||||||
?
|
?
|
||||||
<div>voting...</div>
|
<div>voting...</div>
|
||||||
:
|
:
|
||||||
<div>Thank you for voting!</div>
|
<div>Thank you for voting!</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
this.torrent.good > 0 || this.torrent.bad > 0
|
this.torrent.good > 0 || this.torrent.bad > 0
|
||||||
?
|
?
|
||||||
<div className='w100p' style={{padding: '7px 35px', marginTop: '10px'}}>
|
<div className='w100p' style={{padding: '7px 35px', marginTop: '10px'}}>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
mode="determinate"
|
mode="determinate"
|
||||||
value={torrentRating}
|
value={torrentRating}
|
||||||
color={torrentRating >= 50 ? '#00E676' : '#FF3D00'}
|
color={torrentRating >= 50 ? '#00E676' : '#FF3D00'}
|
||||||
style={{
|
style={{
|
||||||
height: '5px',
|
height: '5px',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='row center pad0-75 fs0-85' style={{color: torrentRating >= 50 ? '#00E676' : '#FF3D00'}}>{__('Torrent rating')}: {torrentRating}%</div>
|
<div className='row center pad0-75 fs0-85' style={{color: torrentRating >= 50 ? '#00E676' : '#FF3D00'}}>{__('Torrent rating')}: {torrentRating}%</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab label={__('Files')} value="files" >
|
<Tab label={__('Files')} value="files" >
|
||||||
<TorrentFiles torrent={this.torrent} />
|
<TorrentFiles torrent={this.torrent} />
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,37 +2,37 @@ import React, { Component } from 'react';
|
|||||||
import formatBytes from './format-bytes'
|
import formatBytes from './format-bytes'
|
||||||
|
|
||||||
export default class TorrentsStatistic extends Component {
|
export default class TorrentsStatistic extends Component {
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.stats = props.stats || {}
|
this.stats = props.stats || {}
|
||||||
}
|
}
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
this.newTorrentFunc = (torrent) => {
|
this.newTorrentFunc = (torrent) => {
|
||||||
this.stats.size += torrent.size;
|
this.stats.size += torrent.size;
|
||||||
this.stats.torrents++;
|
this.stats.torrents++;
|
||||||
this.stats.files += torrent.files;
|
this.stats.files += torrent.files;
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
window.torrentSocket.on('newTorrent', this.newTorrentFunc);
|
window.torrentSocket.on('newTorrent', this.newTorrentFunc);
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
if(this.newTorrentFunc)
|
if(this.newTorrentFunc)
|
||||||
window.torrentSocket.off('newTorrent', this.newTorrentFunc);
|
window.torrentSocket.off('newTorrent', this.newTorrentFunc);
|
||||||
}
|
}
|
||||||
render()
|
render()
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<div style={{position: 'relative', width: '100%', height: 0}}>
|
<div style={{position: 'relative', width: '100%', height: 0}}>
|
||||||
<div className='column w100p counter-statistic' style={{backgroundColor: 'rgba(0,0,0,0.7)', padding: 8, borderRadius: 4, marginTop: 2}}>
|
<div className='column w100p counter-statistic' style={{backgroundColor: 'rgba(0,0,0,0.7)', padding: 8, borderRadius: 4, marginTop: 2}}>
|
||||||
<div className='row w100p' style={{backgroundColor: 'rgba(0,0,0,0.7)', padding: 8, borderRadius: 4}}>
|
<div className='row w100p' style={{backgroundColor: 'rgba(0,0,0,0.7)', padding: 8, borderRadius: 4}}>
|
||||||
<div className='row inline' style={{color: '#e5f442', fontSize: '1.15em', fill: '#e5f442'}}>
|
<div className='row inline' style={{color: '#e5f442', fontSize: '1.15em', fill: '#e5f442'}}>
|
||||||
<svg viewBox="0 0 60 60">
|
<svg viewBox="0 0 60 60">
|
||||||
<path d="M35,0C23.849,0,14.43,2.588,11.215,6.475C4.669,8.077,0.884,10.775,0.146,13.51C0.062,13.657,0,13.818,0,14v0.5V26v0.5V27
|
<path d="M35,0C23.849,0,14.43,2.588,11.215,6.475C4.669,8.077,0.884,10.775,0.146,13.51C0.062,13.657,0,13.818,0,14v0.5V26v0.5V27
|
||||||
v11v0.5V39v12c0,0.162,0.043,0.315,0.117,0.451C1.298,56.346,11.864,60,25,60c11.24,0,20.579-2.68,23.786-6.518
|
v11v0.5V39v12c0,0.162,0.043,0.315,0.117,0.451C1.298,56.346,11.864,60,25,60c11.24,0,20.579-2.68,23.786-6.518
|
||||||
c6.359-1.546,10.366-4.076,11.09-7C59.955,46.34,60,46.175,60,46V34v-0.5V22v-0.5v-12C60,4.895,51.238,0,35,0z M47.805,39.348
|
c6.359-1.546,10.366-4.076,11.09-7C59.955,46.34,60,46.175,60,46V34v-0.5V22v-0.5v-12C60,4.895,51.238,0,35,0z M47.805,39.348
|
||||||
c-0.04,0.099-0.089,0.198-0.143,0.297c-0.067,0.123-0.142,0.246-0.231,0.369c-0.066,0.093-0.141,0.185-0.219,0.277
|
c-0.04,0.099-0.089,0.198-0.143,0.297c-0.067,0.123-0.142,0.246-0.231,0.369c-0.066,0.093-0.141,0.185-0.219,0.277
|
||||||
@ -128,115 +128,115 @@ export default class TorrentsStatistic extends Component {
|
|||||||
c-0.317,1.941-3.314,3.891-7.972,5.255C49.999,51.063,50,51.031,50,51v-9.828c0.043-0.012,0.083-0.025,0.126-0.037
|
c-0.317,1.941-3.314,3.891-7.972,5.255C49.999,51.063,50,51.031,50,51v-9.828c0.043-0.012,0.083-0.025,0.126-0.037
|
||||||
c0.4-0.112,0.79-0.227,1.168-0.346c0.004-0.001,0.009-0.003,0.013-0.004c2.961-0.936,5.22-2.099,6.693-3.427v8.346
|
c0.4-0.112,0.79-0.227,1.168-0.346c0.004-0.001,0.009-0.003,0.013-0.004c2.961-0.936,5.22-2.099,6.693-3.427v8.346
|
||||||
C57.986,45.747,57.976,45.792,57.968,45.838z"/>
|
C57.986,45.747,57.976,45.792,57.968,45.838z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{ formatBytes(this.stats.size, 1) } {__('data')}</div>
|
<div style={{marginLeft: '5px'}}>{ formatBytes(this.stats.size, 1) } {__('data')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row inline' style={{color: '#f48641', fontSize: '1.15em', fill: '#f48641', marginLeft: '20px'}}>
|
<div className='row inline' style={{color: '#f48641', fontSize: '1.15em', fill: '#f48641', marginLeft: '20px'}}>
|
||||||
<svg viewBox="0 0 60 60">
|
<svg viewBox="0 0 60 60">
|
||||||
<g>
|
<g>
|
||||||
<path d="M60,8.311c0-0.199-0.052-0.382-0.131-0.551c-0.027-0.209-0.112-0.412-0.254-0.579L53.46,0H6.54L0.384,7.182
|
<path d="M60,8.311c0-0.199-0.052-0.382-0.131-0.551c-0.027-0.209-0.112-0.412-0.254-0.579L53.46,0H6.54L0.384,7.182
|
||||||
C0.242,7.348,0.157,7.55,0.131,7.76C0.052,7.929,0,8.112,0,8.311V19h3v41h54V19h3V8.311z M7.46,2h45.08l4.286,5H3.174L7.46,2z
|
C0.242,7.348,0.157,7.55,0.131,7.76C0.052,7.929,0,8.112,0,8.311V19h3v41h54V19h3V8.311z M7.46,2h45.08l4.286,5H3.174L7.46,2z
|
||||||
M55,58H5V19h50V58z M58,17h-1H3H2V9h56V17z"/>
|
M55,58H5V19h50V58z M58,17h-1H3H2V9h56V17z"/>
|
||||||
<path d="M42,23H18v10h24V23z M40,31H20v-6h20V31z"/>
|
<path d="M42,23H18v10h24V23z M40,31H20v-6h20V31z"/>
|
||||||
<path d="M45,38H15v14h30V38z M43,50H17V40h26V50z"/>
|
<path d="M45,38H15v14h30V38z M43,50H17V40h26V50z"/>
|
||||||
<path d="M22,48h5c0.552,0,1-0.447,1-1s-0.448-1-1-1h-5c-0.552,0-1,0.447-1,1S21.448,48,22,48z"/>
|
<path d="M22,48h5c0.552,0,1-0.447,1-1s-0.448-1-1-1h-5c-0.552,0-1,0.447-1,1S21.448,48,22,48z"/>
|
||||||
<path d="M27,44h11c0.552,0,1-0.447,1-1s-0.448-1-1-1H27c-0.552,0-1,0.447-1,1S26.448,44,27,44z"/>
|
<path d="M27,44h11c0.552,0,1-0.447,1-1s-0.448-1-1-1H27c-0.552,0-1,0.447-1,1S26.448,44,27,44z"/>
|
||||||
<path d="M22,44c0.26,0,0.52-0.11,0.71-0.29C22.89,43.52,23,43.26,23,43c0-0.261-0.11-0.521-0.29-0.71c-0.38-0.37-1.04-0.37-1.42,0
|
<path d="M22,44c0.26,0,0.52-0.11,0.71-0.29C22.89,43.52,23,43.26,23,43c0-0.261-0.11-0.521-0.29-0.71c-0.38-0.37-1.04-0.37-1.42,0
|
||||||
C21.11,42.479,21,42.739,21,43c0,0.27,0.11,0.52,0.29,0.71C21.48,43.89,21.73,44,22,44z"/>
|
C21.11,42.479,21,42.739,21,43c0,0.27,0.11,0.52,0.29,0.71C21.48,43.89,21.73,44,22,44z"/>
|
||||||
<path d="M31.29,46.29C31.11,46.479,31,46.739,31,47c0,0.26,0.11,0.52,0.29,0.71C31.48,47.89,31.74,48,32,48
|
<path d="M31.29,46.29C31.11,46.479,31,46.739,31,47c0,0.26,0.11,0.52,0.29,0.71C31.48,47.89,31.74,48,32,48
|
||||||
c0.26,0,0.52-0.11,0.71-0.29C32.89,47.52,33,47.26,33,47c0-0.261-0.11-0.521-0.29-0.71C32.34,45.92,31.66,45.92,31.29,46.29z"/>
|
c0.26,0,0.52-0.11,0.71-0.29C32.89,47.52,33,47.26,33,47c0-0.261-0.11-0.521-0.29-0.71C32.34,45.92,31.66,45.92,31.29,46.29z"/>
|
||||||
<path d="M38,46h-1c-0.552,0-1,0.447-1,1s0.448,1,1,1h1c0.552,0,1-0.447,1-1S38.552,46,38,46z"/>
|
<path d="M38,46h-1c-0.552,0-1,0.447-1,1s0.448,1,1,1h1c0.552,0,1-0.447,1-1S38.552,46,38,46z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{this.stats.torrents} {__('torrents')}</div>
|
<div style={{marginLeft: '5px'}}>{this.stats.torrents} {__('torrents')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row inline' style={{color: '#f441e2', fontSize: '1.15em', fill: '#f441e2', marginLeft: '20px'}}>
|
<div className='row inline' style={{color: '#f441e2', fontSize: '1.15em', fill: '#f441e2', marginLeft: '20px'}}>
|
||||||
<svg viewBox="0 0 60 60">
|
<svg viewBox="0 0 60 60">
|
||||||
<g>
|
<g>
|
||||||
<path d="M42.5,22h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,22,42.5,22z"/>
|
<path d="M42.5,22h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,22,42.5,22z"/>
|
||||||
<path d="M17.5,16h10c0.552,0,1-0.447,1-1s-0.448-1-1-1h-10c-0.552,0-1,0.447-1,1S16.948,16,17.5,16z"/>
|
<path d="M17.5,16h10c0.552,0,1-0.447,1-1s-0.448-1-1-1h-10c-0.552,0-1,0.447-1,1S16.948,16,17.5,16z"/>
|
||||||
<path d="M42.5,30h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,30,42.5,30z"/>
|
<path d="M42.5,30h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,30,42.5,30z"/>
|
||||||
<path d="M42.5,38h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,38,42.5,38z"/>
|
<path d="M42.5,38h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,38,42.5,38z"/>
|
||||||
<path d="M42.5,46h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,46,42.5,46z"/>
|
<path d="M42.5,46h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S43.052,46,42.5,46z"/>
|
||||||
<path d="M38.914,0H6.5v60h47V14.586L38.914,0z M39.5,3.414L50.086,14H39.5V3.414z M8.5,58V2h29v14h14v42H8.5z"/>
|
<path d="M38.914,0H6.5v60h47V14.586L38.914,0z M39.5,3.414L50.086,14H39.5V3.414z M8.5,58V2h29v14h14v42H8.5z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{this.stats.files} {__('files')}</div>
|
<div style={{marginLeft: '5px'}}>{this.stats.files} {__('files')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row w100p' style={{backgroundColor: 'rgba(0,0,0,0.7)', padding: 8, borderRadius: 4, marginTop: 5}}>
|
<div className='row w100p' style={{backgroundColor: 'rgba(0,0,0,0.7)', padding: 8, borderRadius: 4, marginTop: 5}}>
|
||||||
<div className='row inline' style={{color: window.peers > 0 ? '#19c632' : 'white', fontSize: '1.15em', fill: window.peers > 0 ? '#19c632' : 'white'}}>
|
<div className='row inline' style={{color: window.peers > 0 ? '#19c632' : 'white', fontSize: '1.15em', fill: window.peers > 0 ? '#19c632' : 'white'}}>
|
||||||
<svg viewBox="0 0 47 47">
|
<svg viewBox="0 0 47 47">
|
||||||
<g>
|
<g>
|
||||||
<path d="M17.567,15.938l-2.859-2.702c0.333-0.605,0.539-1.29,0.539-2.029c0-2.342-1.897-4.239-4.24-4.239
|
<path d="M17.567,15.938l-2.859-2.702c0.333-0.605,0.539-1.29,0.539-2.029c0-2.342-1.897-4.239-4.24-4.239
|
||||||
c-2.343,0-4.243,1.896-4.243,4.239c0,2.343,1.9,4.241,4.243,4.241c0.826,0,1.59-0.246,2.242-0.654l2.855,2.699
|
c-2.343,0-4.243,1.896-4.243,4.239c0,2.343,1.9,4.241,4.243,4.241c0.826,0,1.59-0.246,2.242-0.654l2.855,2.699
|
||||||
C16.536,16.922,17.023,16.399,17.567,15.938z"/>
|
C16.536,16.922,17.023,16.399,17.567,15.938z"/>
|
||||||
<path d="M29.66,15.6l3.799-6.393c0.374,0.107,0.762,0.184,1.169,0.184c2.347,0,4.244-1.898,4.244-4.241
|
<path d="M29.66,15.6l3.799-6.393c0.374,0.107,0.762,0.184,1.169,0.184c2.347,0,4.244-1.898,4.244-4.241
|
||||||
c0-2.342-1.897-4.239-4.244-4.239c-2.343,0-4.239,1.896-4.239,4.239c0,1.163,0.469,2.214,1.227,2.981l-3.787,6.375
|
c0-2.342-1.897-4.239-4.244-4.239c-2.343,0-4.239,1.896-4.239,4.239c0,1.163,0.469,2.214,1.227,2.981l-3.787,6.375
|
||||||
C28.48,14.801,29.094,15.169,29.66,15.6z"/>
|
C28.48,14.801,29.094,15.169,29.66,15.6z"/>
|
||||||
<path d="M42.762,20.952c-1.824,0-3.369,1.159-3.968,2.775l-5.278-0.521c0,0.04,0.006,0.078,0.006,0.117
|
<path d="M42.762,20.952c-1.824,0-3.369,1.159-3.968,2.775l-5.278-0.521c0,0.04,0.006,0.078,0.006,0.117
|
||||||
c0,0.688-0.076,1.36-0.213,2.009l5.276,0.521c0.319,2.024,2.062,3.576,4.177,3.576c2.342,0,4.238-1.896,4.238-4.238
|
c0,0.688-0.076,1.36-0.213,2.009l5.276,0.521c0.319,2.024,2.062,3.576,4.177,3.576c2.342,0,4.238-1.896,4.238-4.238
|
||||||
C47,22.85,45.104,20.952,42.762,20.952z"/>
|
C47,22.85,45.104,20.952,42.762,20.952z"/>
|
||||||
<path d="M28.197,37.624l-1.18-5.156c-0.666,0.232-1.359,0.398-2.082,0.481l1.182,5.157c-1.355,0.709-2.29,2.11-2.29,3.746
|
<path d="M28.197,37.624l-1.18-5.156c-0.666,0.232-1.359,0.398-2.082,0.481l1.182,5.157c-1.355,0.709-2.29,2.11-2.29,3.746
|
||||||
c0,2.342,1.896,4.237,4.243,4.237c2.342,0,4.238-1.896,4.238-4.237C32.311,39.553,30.479,37.692,28.197,37.624z"/>
|
c0,2.342,1.896,4.237,4.243,4.237c2.342,0,4.238-1.896,4.238-4.237C32.311,39.553,30.479,37.692,28.197,37.624z"/>
|
||||||
<path d="M14.357,25.37l-6.57,2.201c-0.758-1.158-2.063-1.926-3.548-1.926C1.896,25.645,0,27.542,0,29.884
|
<path d="M14.357,25.37l-6.57,2.201c-0.758-1.158-2.063-1.926-3.548-1.926C1.896,25.645,0,27.542,0,29.884
|
||||||
c0,2.345,1.896,4.242,4.239,4.242c2.341,0,4.242-1.897,4.242-4.242c0-0.098-0.021-0.188-0.029-0.284l6.591-2.207
|
c0,2.345,1.896,4.242,4.239,4.242c2.341,0,4.242-1.897,4.242-4.242c0-0.098-0.021-0.188-0.029-0.284l6.591-2.207
|
||||||
C14.746,26.752,14.51,26.077,14.357,25.37z"/>
|
C14.746,26.752,14.51,26.077,14.357,25.37z"/>
|
||||||
<circle cx="23.83" cy="23.323" r="7.271"/>
|
<circle cx="23.83" cy="23.323" r="7.271"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{window.peers} {__('peers')}</div>
|
<div style={{marginLeft: '5px'}}>{window.peers} {__('peers')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row inline' style={{color: window.peersTorrents > 0 ? '#19c687' : 'white', fontSize: '1.15em', fill: window.peersTorrents > 0 ? '#19c687' : 'white', marginLeft: '20px'}}>
|
<div className='row inline' style={{color: window.peersTorrents > 0 ? '#19c687' : 'white', fontSize: '1.15em', fill: window.peersTorrents > 0 ? '#19c687' : 'white', marginLeft: '20px'}}>
|
||||||
<svg viewBox="0 0 481.6 481.6">
|
<svg viewBox="0 0 481.6 481.6">
|
||||||
<g>
|
<g>
|
||||||
<path d="M381.6,309.4c-27.7,0-52.4,13.2-68.2,33.6l-132.3-73.9c3.1-8.9,4.8-18.5,4.8-28.4c0-10-1.7-19.5-4.9-28.5l132.2-73.8
|
<path d="M381.6,309.4c-27.7,0-52.4,13.2-68.2,33.6l-132.3-73.9c3.1-8.9,4.8-18.5,4.8-28.4c0-10-1.7-19.5-4.9-28.5l132.2-73.8
|
||||||
c15.7,20.5,40.5,33.8,68.3,33.8c47.4,0,86.1-38.6,86.1-86.1S429,0,381.5,0s-86.1,38.6-86.1,86.1c0,10,1.7,19.6,4.9,28.5
|
c15.7,20.5,40.5,33.8,68.3,33.8c47.4,0,86.1-38.6,86.1-86.1S429,0,381.5,0s-86.1,38.6-86.1,86.1c0,10,1.7,19.6,4.9,28.5
|
||||||
l-132.1,73.8c-15.7-20.6-40.5-33.8-68.3-33.8c-47.4,0-86.1,38.6-86.1,86.1s38.7,86.1,86.2,86.1c27.8,0,52.6-13.3,68.4-33.9
|
l-132.1,73.8c-15.7-20.6-40.5-33.8-68.3-33.8c-47.4,0-86.1,38.6-86.1,86.1s38.7,86.1,86.2,86.1c27.8,0,52.6-13.3,68.4-33.9
|
||||||
l132.2,73.9c-3.2,9-5,18.7-5,28.7c0,47.4,38.6,86.1,86.1,86.1s86.1-38.6,86.1-86.1S429.1,309.4,381.6,309.4z M381.6,27.1
|
l132.2,73.9c-3.2,9-5,18.7-5,28.7c0,47.4,38.6,86.1,86.1,86.1s86.1-38.6,86.1-86.1S429.1,309.4,381.6,309.4z M381.6,27.1
|
||||||
c32.6,0,59.1,26.5,59.1,59.1s-26.5,59.1-59.1,59.1s-59.1-26.5-59.1-59.1S349.1,27.1,381.6,27.1z M100,299.8
|
c32.6,0,59.1,26.5,59.1,59.1s-26.5,59.1-59.1,59.1s-59.1-26.5-59.1-59.1S349.1,27.1,381.6,27.1z M100,299.8
|
||||||
c-32.6,0-59.1-26.5-59.1-59.1s26.5-59.1,59.1-59.1s59.1,26.5,59.1,59.1S132.5,299.8,100,299.8z M381.6,454.5
|
c-32.6,0-59.1-26.5-59.1-59.1s26.5-59.1,59.1-59.1s59.1,26.5,59.1,59.1S132.5,299.8,100,299.8z M381.6,454.5
|
||||||
c-32.6,0-59.1-26.5-59.1-59.1c0-32.6,26.5-59.1,59.1-59.1s59.1,26.5,59.1,59.1C440.7,428,414.2,454.5,381.6,454.5z"/>
|
c-32.6,0-59.1-26.5-59.1-59.1c0-32.6,26.5-59.1,59.1-59.1s59.1,26.5,59.1,59.1C440.7,428,414.2,454.5,381.6,454.5z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{window.peersTorrents} {__('remote torrents')}</div>
|
<div style={{marginLeft: '5px'}}>{window.peersTorrents} {__('remote torrents')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='row inline' style={{color: window.p2pStatus == 2 ? '#78c619' : (window.p2pStatus == 1 ? '#c68319' : '#c6194a'), fontSize: '1.15em', fill: window.p2pStatus == 2 ? '#78c619' : (window.p2pStatus == 1 ? '#c68319' : '#c6194a'), marginLeft: '20px'}}>
|
<div className='row inline' style={{color: window.p2pStatus == 2 ? '#78c619' : (window.p2pStatus == 1 ? '#c68319' : '#c6194a'), fontSize: '1.15em', fill: window.p2pStatus == 2 ? '#78c619' : (window.p2pStatus == 1 ? '#c68319' : '#c6194a'), marginLeft: '20px'}}>
|
||||||
{
|
{
|
||||||
window.p2pStatus == 0
|
window.p2pStatus == 0
|
||||||
&&
|
&&
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<svg viewBox="0 0 54.908 54.908">
|
<svg viewBox="0 0 54.908 54.908">
|
||||||
<g>
|
<g>
|
||||||
<path d="M54.615,19.123c-7.243-7.244-16.89-11.233-27.161-11.233S7.537,11.878,0.293,19.123c-0.391,0.391-0.391,1.023,0,1.414
|
<path d="M54.615,19.123c-7.243-7.244-16.89-11.233-27.161-11.233S7.537,11.878,0.293,19.123c-0.391,0.391-0.391,1.023,0,1.414
|
||||||
s1.023,0.391,1.414,0C8.573,13.67,17.717,9.889,27.454,9.889s18.881,3.781,25.747,10.647c0.195,0.195,0.451,0.293,0.707,0.293
|
s1.023,0.391,1.414,0C8.573,13.67,17.717,9.889,27.454,9.889s18.881,3.781,25.747,10.647c0.195,0.195,0.451,0.293,0.707,0.293
|
||||||
s0.512-0.098,0.707-0.293C55.006,20.146,55.006,19.513,54.615,19.123z"/>
|
s0.512-0.098,0.707-0.293C55.006,20.146,55.006,19.513,54.615,19.123z"/>
|
||||||
<path d="M6.171,25c-0.391,0.391-0.391,1.023,0,1.414c0.195,0.195,0.451,0.293,0.707,0.293s0.512-0.098,0.707-0.293
|
<path d="M6.171,25c-0.391,0.391-0.391,1.023,0,1.414c0.195,0.195,0.451,0.293,0.707,0.293s0.512-0.098,0.707-0.293
|
||||||
c10.955-10.956,28.781-10.956,39.737,0c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414C37.002,13.266,17.907,13.264,6.171,25
|
c10.955-10.956,28.781-10.956,39.737,0c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414C37.002,13.266,17.907,13.264,6.171,25
|
||||||
z"/>
|
z"/>
|
||||||
<path d="M27.454,24.508c-5.825,0-11.295,2.263-15.404,6.371c-0.391,0.391-0.391,1.023,0,1.414s1.023,0.391,1.414,0
|
<path d="M27.454,24.508c-5.825,0-11.295,2.263-15.404,6.371c-0.391,0.391-0.391,1.023,0,1.414s1.023,0.391,1.414,0
|
||||||
c3.731-3.73,8.699-5.785,13.99-5.785c5.291,0,10.259,2.055,13.99,5.785c0.195,0.195,0.451,0.293,0.707,0.293
|
c3.731-3.73,8.699-5.785,13.99-5.785c5.291,0,10.259,2.055,13.99,5.785c0.195,0.195,0.451,0.293,0.707,0.293
|
||||||
s0.512-0.098,0.707-0.293c0.391-0.391,0.391-1.023,0-1.414C38.75,26.771,33.279,24.508,27.454,24.508z"/>
|
s0.512-0.098,0.707-0.293c0.391-0.391,0.391-1.023,0-1.414C38.75,26.771,33.279,24.508,27.454,24.508z"/>
|
||||||
<path d="M27.454,33.916c-3.612,0-6.551,2.939-6.551,6.552s2.939,6.552,6.551,6.552c3.613,0,6.552-2.939,6.552-6.552
|
<path d="M27.454,33.916c-3.612,0-6.551,2.939-6.551,6.552s2.939,6.552,6.551,6.552c3.613,0,6.552-2.939,6.552-6.552
|
||||||
S31.067,33.916,27.454,33.916z M27.454,45.019c-2.51,0-4.551-2.042-4.551-4.552s2.042-4.552,4.551-4.552s4.552,2.042,4.552,4.552
|
S31.067,33.916,27.454,33.916z M27.454,45.019c-2.51,0-4.551-2.042-4.551-4.552s2.042-4.552,4.551-4.552s4.552,2.042,4.552,4.552
|
||||||
S29.964,45.019,27.454,45.019z"/>
|
S29.964,45.019,27.454,45.019z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{__('not available')}</div>
|
<div style={{marginLeft: '5px'}}>{__('not available')}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
window.p2pStatus == 1
|
window.p2pStatus == 1
|
||||||
&&
|
&&
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<svg viewBox="0 0 611.989 611.988">
|
<svg viewBox="0 0 611.989 611.988">
|
||||||
<g>
|
<g>
|
||||||
<path d="M305.994,417.769c-30.85,0-55.887,25.037-55.887,55.887s25.038,55.887,55.887,55.887s55.887-25.037,55.887-55.887
|
<path d="M305.994,417.769c-30.85,0-55.887,25.037-55.887,55.887s25.038,55.887,55.887,55.887s55.887-25.037,55.887-55.887
|
||||||
S336.843,417.769,305.994,417.769z M605.436,222.369C530.697,133.434,421.549,82.446,305.994,82.446
|
S336.843,417.769,305.994,417.769z M605.436,222.369C530.697,133.434,421.549,82.446,305.994,82.446
|
||||||
S81.309,133.434,6.551,222.369c-9.93,11.811-8.402,29.434,3.428,39.363c5.234,4.396,11.587,6.558,17.939,6.558
|
S81.309,133.434,6.551,222.369c-9.93,11.811-8.402,29.434,3.428,39.363c5.234,4.396,11.587,6.558,17.939,6.558
|
||||||
c7.973,0,15.891-3.391,21.423-9.967c64.084-76.248,157.639-119.989,256.652-119.989c99.013,0,192.568,43.741,256.651,119.971
|
c7.973,0,15.891-3.391,21.423-9.967c64.084-76.248,157.639-119.989,256.652-119.989c99.013,0,192.568,43.741,256.651,119.971
|
||||||
@ -249,18 +249,18 @@ export default class TorrentsStatistic extends Component {
|
|||||||
c7.973,0,15.891-3.39,21.405-9.966c21.368-25.429,52.552-40.016,85.544-40.016s64.177,14.587,85.544,40.016
|
c7.973,0,15.891-3.39,21.405-9.966c21.368-25.429,52.552-40.016,85.544-40.016s64.177,14.587,85.544,40.016
|
||||||
c5.533,6.595,13.45,9.966,21.405,9.966c6.353,0,12.724-2.142,17.958-6.557c11.83-9.93,13.357-27.553,3.428-39.363
|
c5.533,6.595,13.45,9.966,21.405,9.966c6.353,0,12.724-2.142,17.958-6.557c11.83-9.93,13.357-27.553,3.428-39.363
|
||||||
C402.324,327.846,355.546,305.994,305.994,305.994z"/>
|
C402.324,327.846,355.546,305.994,305.994,305.994z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{__('redirect')}</div>
|
<div style={{marginLeft: '5px'}}>{__('redirect')}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
window.p2pStatus == 2
|
window.p2pStatus == 2
|
||||||
&&
|
&&
|
||||||
<div className='row inline w100p'>
|
<div className='row inline w100p'>
|
||||||
<svg viewBox="0 0 611.989 611.988">
|
<svg viewBox="0 0 611.989 611.988">
|
||||||
<g>
|
<g>
|
||||||
<path d="M305.994,417.769c-30.85,0-55.887,25.037-55.887,55.887s25.038,55.887,55.887,55.887s55.887-25.037,55.887-55.887
|
<path d="M305.994,417.769c-30.85,0-55.887,25.037-55.887,55.887s25.038,55.887,55.887,55.887s55.887-25.037,55.887-55.887
|
||||||
S336.843,417.769,305.994,417.769z M605.436,222.369C530.697,133.434,421.549,82.446,305.994,82.446
|
S336.843,417.769,305.994,417.769z M605.436,222.369C530.697,133.434,421.549,82.446,305.994,82.446
|
||||||
S81.309,133.434,6.551,222.369c-9.93,11.811-8.402,29.434,3.428,39.363c5.234,4.396,11.587,6.558,17.939,6.558
|
S81.309,133.434,6.551,222.369c-9.93,11.811-8.402,29.434,3.428,39.363c5.234,4.396,11.587,6.558,17.939,6.558
|
||||||
c7.973,0,15.891-3.391,21.423-9.967c64.084-76.248,157.639-119.989,256.652-119.989c99.013,0,192.568,43.741,256.651,119.971
|
c7.973,0,15.891-3.391,21.423-9.967c64.084-76.248,157.639-119.989,256.652-119.989c99.013,0,192.568,43.741,256.651,119.971
|
||||||
@ -273,16 +273,16 @@ export default class TorrentsStatistic extends Component {
|
|||||||
c7.973,0,15.891-3.39,21.405-9.966c21.368-25.429,52.552-40.016,85.544-40.016s64.177,14.587,85.544,40.016
|
c7.973,0,15.891-3.39,21.405-9.966c21.368-25.429,52.552-40.016,85.544-40.016s64.177,14.587,85.544,40.016
|
||||||
c5.533,6.595,13.45,9.966,21.405,9.966c6.353,0,12.724-2.142,17.958-6.557c11.83-9.93,13.357-27.553,3.428-39.363
|
c5.533,6.595,13.45,9.966,21.405,9.966c6.353,0,12.724-2.142,17.958-6.557c11.83-9.93,13.357-27.553,3.428-39.363
|
||||||
C402.324,327.846,355.546,305.994,305.994,305.994z"/>
|
C402.324,327.846,355.546,305.994,305.994,305.994z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<div style={{marginLeft: '5px'}}>{__('direct')}</div>
|
<div style={{marginLeft: '5px'}}>{__('direct')}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,12 +11,12 @@ import LinearProgress from 'material-ui/LinearProgress';
|
|||||||
let rating = require('./rating');
|
let rating = require('./rating');
|
||||||
|
|
||||||
const contentIcon = (type, category, fill = 'grey') => {
|
const contentIcon = (type, category, fill = 'grey') => {
|
||||||
if(category == 'xxx')
|
if(category == 'xxx')
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 18.282 18.282" fill={fill}>
|
<svg viewBox="0 0 18.282 18.282" fill={fill}>
|
||||||
<g>
|
<g>
|
||||||
<path d="M16.435,3.832H1.847C0.827,3.832,0,4.659,0,5.678v6.925c0,1.021,0.827,1.848,1.847,1.848h14.588
|
<path d="M16.435,3.832H1.847C0.827,3.832,0,4.659,0,5.678v6.925c0,1.021,0.827,1.848,1.847,1.848h14.588
|
||||||
c1.021,0,1.847-0.827,1.847-1.848V5.678C18.282,4.659,17.455,3.832,16.435,3.832z M3.194,7.123H2.583v4.042h0.611v0.54H1.876V6.583
|
c1.021,0,1.847-0.827,1.847-1.848V5.678C18.282,4.659,17.455,3.832,16.435,3.832z M3.194,7.123H2.583v4.042h0.611v0.54H1.876V6.583
|
||||||
h1.318V7.123z M6.197,10.986l-0.392-0.784C5.644,9.9,5.541,9.676,5.419,9.425H5.406c-0.09,0.251-0.199,0.476-0.334,0.777
|
h1.318V7.123z M6.197,10.986l-0.392-0.784C5.644,9.9,5.541,9.676,5.419,9.425H5.406c-0.09,0.251-0.199,0.476-0.334,0.777
|
||||||
l-0.36,0.784H3.593l1.254-2.191L3.638,6.654h1.125l0.379,0.791C5.27,7.709,5.367,7.921,5.47,8.165h0.013
|
l-0.36,0.784H3.593l1.254-2.191L3.638,6.654h1.125l0.379,0.791C5.27,7.709,5.367,7.921,5.47,8.165h0.013
|
||||||
@ -27,87 +27,87 @@ const contentIcon = (type, category, fill = 'grey') => {
|
|||||||
c-0.16-0.302-0.263-0.526-0.386-0.777h-0.012c-0.091,0.251-0.2,0.476-0.335,0.777l-0.36,0.784h-1.117l1.253-2.191l-1.209-2.141
|
c-0.16-0.302-0.263-0.526-0.386-0.777h-0.012c-0.091,0.251-0.2,0.476-0.335,0.777l-0.36,0.784h-1.117l1.253-2.191l-1.209-2.141
|
||||||
h1.125l0.379,0.791c0.129,0.264,0.226,0.476,0.328,0.72h0.013c0.104-0.276,0.187-0.47,0.296-0.72l0.366-0.791h1.118l-1.221,2.114
|
h1.125l0.379,0.791c0.129,0.264,0.226,0.476,0.328,0.72h0.013c0.104-0.276,0.187-0.47,0.296-0.72l0.366-0.791h1.118l-1.221,2.114
|
||||||
l1.286,2.218C15.071,10.986,13.94,10.986,13.94,10.986z M16.756,11.705h-1.311v-0.54h0.611V7.116h-0.611v-0.54h1.311V11.705z"/>
|
l1.286,2.218C15.071,10.986,13.94,10.986,13.94,10.986z M16.756,11.705h-1.311v-0.54h0.611V7.116h-0.611v-0.54h1.311V11.705z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case 'video':
|
case 'video':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 491.858 491.858" fill={fill}>
|
<svg viewBox="0 0 491.858 491.858" fill={fill}>
|
||||||
<path d="M357.714,423.331c0,9.328-10.676,16.891-23.847,16.891H23.847C10.676,440.222,0,432.659,0,423.331V203.735
|
<path d="M357.714,423.331c0,9.328-10.676,16.891-23.847,16.891H23.847C10.676,440.222,0,432.659,0,423.331V203.735
|
||||||
c0-9.33,10.676-16.892,23.847-16.892h310.02c13.171,0,23.847,7.564,23.847,16.892V423.331L357.714,423.331z"/>
|
c0-9.33,10.676-16.892,23.847-16.892h310.02c13.171,0,23.847,7.564,23.847,16.892V423.331L357.714,423.331z"/>
|
||||||
<circle cx="89.428" cy="118.706" r="59.619"/>
|
<circle cx="89.428" cy="118.706" r="59.619"/>
|
||||||
<circle cx="253.381" cy="103.801" r="74.524"/>
|
<circle cx="253.381" cy="103.801" r="74.524"/>
|
||||||
<path d="M491.858,447.677c0,0-1.986,14.904-15.899,14.904c-13.912,0-103.34-83.42-103.34-94.397V258.882
|
<path d="M491.858,447.677c0,0-1.986,14.904-15.899,14.904c-13.912,0-103.34-83.42-103.34-94.397V258.882
|
||||||
c0-10.976,87.443-94.398,103.34-94.398c15.899,0,15.899,14.905,15.899,14.905V447.677z"/>
|
c0-10.976,87.443-94.398,103.34-94.398c15.899,0,15.899,14.905,15.899,14.905V447.677z"/>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
case 'audio':
|
case 'audio':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 46 46" fill={fill}>
|
<svg viewBox="0 0 46 46" fill={fill}>
|
||||||
<path d="M28.38,0c-0.551,0-1.097,0.153-1.579,0.444c-0.046,0.027-0.09,0.059-0.13,0.093L13.121,12H2.487c-0.553,0-1,0.447-1,1v19
|
<path d="M28.38,0c-0.551,0-1.097,0.153-1.579,0.444c-0.046,0.027-0.09,0.059-0.13,0.093L13.121,12H2.487c-0.553,0-1,0.447-1,1v19
|
||||||
c0,0.553,0.447,1,1,1h10.61L26.64,45.436c0.05,0.046,0.104,0.086,0.161,0.12C27.284,45.847,27.83,46,28.38,46
|
c0,0.553,0.447,1,1,1h10.61L26.64,45.436c0.05,0.046,0.104,0.086,0.161,0.12C27.284,45.847,27.83,46,28.38,46
|
||||||
c1.713,0,3.106-1.416,3.106-3.156V3.156C31.487,1.416,30.093,0,28.38,0z M14.487,31c0,0.553-0.447,1-1,1s-1-0.447-1-1v-4
|
c1.713,0,3.106-1.416,3.106-3.156V3.156C31.487,1.416,30.093,0,28.38,0z M14.487,31c0,0.553-0.447,1-1,1s-1-0.447-1-1v-4
|
||||||
c0-0.553,0.447-1,1-1s1,0.447,1,1V31z M14.487,18c0,0.553-0.447,1-1,1s-1-0.447-1-1v-4c0-0.553,0.447-1,1-1s1,0.447,1,1V18z"/>
|
c0-0.553,0.447-1,1-1s1,0.447,1,1V31z M14.487,18c0,0.553-0.447,1-1,1s-1-0.447-1-1v-4c0-0.553,0.447-1,1-1s1,0.447,1,1V18z"/>
|
||||||
<path d="M44.513,22.5c0-5.972-4.009-11.302-9.749-12.962c-0.533-0.151-1.084,0.152-1.238,0.684
|
<path d="M44.513,22.5c0-5.972-4.009-11.302-9.749-12.962c-0.533-0.151-1.084,0.152-1.238,0.684
|
||||||
c-0.153,0.53,0.152,1.085,0.684,1.238c4.889,1.413,8.304,5.953,8.304,11.04s-3.415,9.627-8.304,11.04
|
c-0.153,0.53,0.152,1.085,0.684,1.238c4.889,1.413,8.304,5.953,8.304,11.04s-3.415,9.627-8.304,11.04
|
||||||
c-0.531,0.153-0.837,0.708-0.684,1.238c0.127,0.438,0.526,0.723,0.961,0.723c0.092,0,0.185-0.013,0.277-0.039
|
c-0.531,0.153-0.837,0.708-0.684,1.238c0.127,0.438,0.526,0.723,0.961,0.723c0.092,0,0.185-0.013,0.277-0.039
|
||||||
C40.504,33.802,44.513,28.472,44.513,22.5z"/>
|
C40.504,33.802,44.513,28.472,44.513,22.5z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
)
|
)
|
||||||
case 'pictures':
|
case 'pictures':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 58 58" fill={fill}>
|
<svg viewBox="0 0 58 58" fill={fill}>
|
||||||
<path d="M57,6H1C0.448,6,0,6.447,0,7v44c0,0.553,0.448,1,1,1h56c0.552,0,1-0.447,1-1V7C58,6.447,57.552,6,57,6z M16,17
|
<path d="M57,6H1C0.448,6,0,6.447,0,7v44c0,0.553,0.448,1,1,1h56c0.552,0,1-0.447,1-1V7C58,6.447,57.552,6,57,6z M16,17
|
||||||
c3.071,0,5.569,2.498,5.569,5.569c0,3.07-2.498,5.568-5.569,5.568s-5.569-2.498-5.569-5.568C10.431,19.498,12.929,17,16,17z
|
c3.071,0,5.569,2.498,5.569,5.569c0,3.07-2.498,5.568-5.569,5.568s-5.569-2.498-5.569-5.568C10.431,19.498,12.929,17,16,17z
|
||||||
M52.737,35.676c-0.373,0.406-1.006,0.435-1.413,0.062L40.063,25.414l-9.181,10.054l4.807,4.807c0.391,0.391,0.391,1.023,0,1.414
|
M52.737,35.676c-0.373,0.406-1.006,0.435-1.413,0.062L40.063,25.414l-9.181,10.054l4.807,4.807c0.391,0.391,0.391,1.023,0,1.414
|
||||||
s-1.023,0.391-1.414,0L23.974,31.389L7.661,45.751C7.471,45.918,7.235,46,7,46c-0.277,0-0.553-0.114-0.751-0.339
|
s-1.023,0.391-1.414,0L23.974,31.389L7.661,45.751C7.471,45.918,7.235,46,7,46c-0.277,0-0.553-0.114-0.751-0.339
|
||||||
c-0.365-0.415-0.325-1.047,0.09-1.412l17.017-14.982c0.396-0.348,0.994-0.329,1.368,0.044l4.743,4.743l9.794-10.727
|
c-0.365-0.415-0.325-1.047,0.09-1.412l17.017-14.982c0.396-0.348,0.994-0.329,1.368,0.044l4.743,4.743l9.794-10.727
|
||||||
c0.179-0.196,0.429-0.313,0.694-0.325c0.264-0.006,0.524,0.083,0.72,0.262l12,11C53.083,34.636,53.11,35.269,52.737,35.676z"/>
|
c0.179-0.196,0.429-0.313,0.694-0.325c0.264-0.006,0.524,0.083,0.72,0.262l12,11C53.083,34.636,53.11,35.269,52.737,35.676z"/>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
case 'application':
|
case 'application':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 483.85 483.85" fill={fill}>
|
<svg viewBox="0 0 483.85 483.85" fill={fill}>
|
||||||
<path d="M471.325,211.856l-56.9-56.9c-23.4-23.4-9.1-48.1,16.4-49.6c42-2.6,65.6-47.4,31.3-84.7c-37.3-34.2-81.9-10.7-84.5,31.2
|
<path d="M471.325,211.856l-56.9-56.9c-23.4-23.4-9.1-48.1,16.4-49.6c42-2.6,65.6-47.4,31.3-84.7c-37.3-34.2-81.9-10.7-84.5,31.2
|
||||||
c-1.6,25.5-26.5,39.9-49.8,16.6l-55.7-55.7c-16.7-16.7-43.8-16.7-60.5,0l-56.4,56.4c-23.4,23.4-48.2,8.9-49.8-16.6
|
c-1.6,25.5-26.5,39.9-49.8,16.6l-55.7-55.7c-16.7-16.7-43.8-16.7-60.5,0l-56.4,56.4c-23.4,23.4-48.2,8.9-49.8-16.6
|
||||||
c-2.6-42-47.6-65.9-84.9-31.6c-34.4,37.4-10.5,82.4,31.5,85c25.5,1.6,40,26.5,16.7,49.9l-56.2,56.1c-16.7,16.7-16.7,43.8,0,60.5
|
c-2.6-42-47.6-65.9-84.9-31.6c-34.4,37.4-10.5,82.4,31.5,85c25.5,1.6,40,26.5,16.7,49.9l-56.2,56.1c-16.7,16.7-16.7,43.8,0,60.5
|
||||||
l55.7,55.7c23.4,23.3,9.5,47.6-16,49.2c-42,2.6-65.5,47.3-31.2,84.6c37.3,34.3,81.8,10.9,84.4-31.1c1.6-25.5,26-39.5,49.4-16.2
|
l55.7,55.7c23.4,23.3,9.5,47.6-16,49.2c-42,2.6-65.5,47.3-31.2,84.6c37.3,34.3,81.8,10.9,84.4-31.1c1.6-25.5,26-39.5,49.4-16.2
|
||||||
l56.2,56.2c17,17,44.8,17,61.8,0.1l39.4-39.4l16.9-16.9c22.1-23.1,7.8-47.4-17.4-49c-42-2.6-65.8-47.6-31.5-84.9
|
l56.2,56.2c17,17,44.8,17,61.8,0.1l39.4-39.4l16.9-16.9c22.1-23.1,7.8-47.4-17.4-49c-42-2.6-65.8-47.6-31.5-84.9
|
||||||
c37.3-34.3,82.3-10.4,84.9,31.6c1.6,25.2,25.8,39.4,48.9,17.3l15.3-15.3l41.2-41.2c0.1-0.1,0.1-0.1,0.2-0.2l0.6-0.6
|
c37.3-34.3,82.3-10.4,84.9,31.6c1.6,25.2,25.8,39.4,48.9,17.3l15.3-15.3l41.2-41.2c0.1-0.1,0.1-0.1,0.2-0.2l0.6-0.6
|
||||||
C488.025,255.656,488.025,228.556,471.325,211.856z"/>
|
C488.025,255.656,488.025,228.556,471.325,211.856z"/>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
case 'books':
|
case 'books':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 296.999 296.999" fill={fill}>
|
<svg viewBox="0 0 296.999 296.999" fill={fill}>
|
||||||
<g>
|
<g>
|
||||||
<path d="M45.432,35.049c-0.008,0-0.017,0-0.025,0c-2.809,0-5.451,1.095-7.446,3.085c-2.017,2.012-3.128,4.691-3.128,7.543
|
<path d="M45.432,35.049c-0.008,0-0.017,0-0.025,0c-2.809,0-5.451,1.095-7.446,3.085c-2.017,2.012-3.128,4.691-3.128,7.543
|
||||||
v159.365c0,5.844,4.773,10.61,10.641,10.625c24.738,0.059,66.184,5.215,94.776,35.136V84.023c0-1.981-0.506-3.842-1.461-5.382
|
v159.365c0,5.844,4.773,10.61,10.641,10.625c24.738,0.059,66.184,5.215,94.776,35.136V84.023c0-1.981-0.506-3.842-1.461-5.382
|
||||||
C115.322,40.849,70.226,35.107,45.432,35.049z"/>
|
C115.322,40.849,70.226,35.107,45.432,35.049z"/>
|
||||||
<path d="M262.167,205.042V45.676c0-2.852-1.111-5.531-3.128-7.543c-1.995-1.99-4.639-3.085-7.445-3.085c-0.009,0-0.018,0-0.026,0
|
<path d="M262.167,205.042V45.676c0-2.852-1.111-5.531-3.128-7.543c-1.995-1.99-4.639-3.085-7.445-3.085c-0.009,0-0.018,0-0.026,0
|
||||||
c-24.793,0.059-69.889,5.801-93.357,43.593c-0.955,1.54-1.46,3.401-1.46,5.382v166.779
|
c-24.793,0.059-69.889,5.801-93.357,43.593c-0.955,1.54-1.46,3.401-1.46,5.382v166.779
|
||||||
c28.592-29.921,70.038-35.077,94.776-35.136C257.394,215.651,262.167,210.885,262.167,205.042z"/>
|
c28.592-29.921,70.038-35.077,94.776-35.136C257.394,215.651,262.167,210.885,262.167,205.042z"/>
|
||||||
<path d="M286.373,71.801h-7.706v133.241c0,14.921-12.157,27.088-27.101,27.125c-20.983,0.05-55.581,4.153-80.084,27.344
|
<path d="M286.373,71.801h-7.706v133.241c0,14.921-12.157,27.088-27.101,27.125c-20.983,0.05-55.581,4.153-80.084,27.344
|
||||||
c42.378-10.376,87.052-3.631,112.512,2.171c3.179,0.724,6.464-0.024,9.011-2.054c2.538-2.025,3.994-5.052,3.994-8.301V82.427
|
c42.378-10.376,87.052-3.631,112.512,2.171c3.179,0.724,6.464-0.024,9.011-2.054c2.538-2.025,3.994-5.052,3.994-8.301V82.427
|
||||||
C297,76.568,292.232,71.801,286.373,71.801z"/>
|
C297,76.568,292.232,71.801,286.373,71.801z"/>
|
||||||
<path d="M18.332,205.042V71.801h-7.706C4.768,71.801,0,76.568,0,82.427v168.897c0,3.25,1.456,6.276,3.994,8.301
|
<path d="M18.332,205.042V71.801h-7.706C4.768,71.801,0,76.568,0,82.427v168.897c0,3.25,1.456,6.276,3.994,8.301
|
||||||
c2.545,2.029,5.827,2.78,9.011,2.054c25.46-5.803,70.135-12.547,112.511-2.171c-24.502-23.19-59.1-27.292-80.083-27.342
|
c2.545,2.029,5.827,2.78,9.011,2.054c25.46-5.803,70.135-12.547,112.511-2.171c-24.502-23.19-59.1-27.292-80.083-27.342
|
||||||
C30.49,232.13,18.332,219.963,18.332,205.042z"/>
|
C30.49,232.13,18.332,219.963,18.332,205.042z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
case 'archive':
|
case 'archive':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 390 390" fill={fill}>
|
<svg viewBox="0 0 390 390" fill={fill}>
|
||||||
<g>
|
<g>
|
||||||
<path d="M182.681,205.334c0,5.21,4.227,9.436,9.436,9.436h5.765c5.21,0,9.436-4.226,9.436-9.436c0-5.211-4.226-9.438-9.436-9.438
|
<path d="M182.681,205.334c0,5.21,4.227,9.436,9.436,9.436h5.765c5.21,0,9.436-4.226,9.436-9.436c0-5.211-4.226-9.438-9.436-9.438
|
||||||
h-5.765C186.908,195.897,182.681,200.123,182.681,205.334z"/>
|
h-5.765C186.908,195.897,182.681,200.123,182.681,205.334z"/>
|
||||||
<path d="M383.889,126.058c-4.478-5.191-10.868-8.314-17.674-8.686V64.899c0-25.562-20.797-46.359-46.361-46.359h-75.278
|
<path d="M383.889,126.058c-4.478-5.191-10.868-8.314-17.674-8.686V64.899c0-25.562-20.797-46.359-46.361-46.359h-75.278
|
||||||
c-25.052,0-38.351,10.578-48.062,18.303c-7.807,6.208-12.518,9.955-22.626,9.955H65.099c-22.78,0-41.313,18.062-41.313,40.264
|
c-25.052,0-38.351,10.578-48.062,18.303c-7.807,6.208-12.518,9.955-22.626,9.955H65.099c-22.78,0-41.313,18.062-41.313,40.264
|
||||||
v30.311c-6.806,0.371-13.196,3.494-17.674,8.686c-4.78,5.541-6.912,12.888-5.839,20.125l30.194,203.803
|
v30.311c-6.806,0.371-13.196,3.494-17.674,8.686c-4.78,5.541-6.912,12.888-5.839,20.125l30.194,203.803
|
||||||
c1.828,12.338,12.417,21.475,24.89,21.475h279.286c12.473,0,23.063-9.137,24.891-21.475l30.195-203.802
|
c1.828,12.338,12.417,21.475,24.89,21.475h279.286c12.473,0,23.063-9.137,24.891-21.475l30.195-203.802
|
||||||
@ -123,115 +123,115 @@ const contentIcon = (type, category, fill = 'grey') => {
|
|||||||
h-32.443c-2.399,0-4.345-1.944-4.345-4.345V279.28c0-2.4,1.946-4.346,4.345-4.346h32.443c2.399,0,4.345,1.945,4.345,4.346V289.708z
|
h-32.443c-2.399,0-4.345-1.944-4.345-4.345V279.28c0-2.4,1.946-4.346,4.345-4.346h32.443c2.399,0,4.345,1.945,4.345,4.346V289.708z
|
||||||
M335.919,117.333H54.081V87.062c0-6.239,5.602-9.968,11.019-9.968h108.788c20.687,0,32.219-9.173,41.484-16.542
|
M335.919,117.333H54.081V87.062c0-6.239,5.602-9.968,11.019-9.968h108.788c20.687,0,32.219-9.173,41.484-16.542
|
||||||
c8.552-6.803,14.732-11.717,29.204-11.717h75.278c8.858,0,16.066,7.206,16.066,16.064V117.333z"/>
|
c8.552-6.803,14.732-11.717,29.204-11.717h75.278c8.858,0,16.066,7.206,16.066,16.064V117.333z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
case 'disc':
|
case 'disc':
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 49.652 49.652" fill={fill}>
|
<svg viewBox="0 0 49.652 49.652" fill={fill}>
|
||||||
<g>
|
<g>
|
||||||
<circle cx="24.826" cy="24.825" r="3.529"/>
|
<circle cx="24.826" cy="24.825" r="3.529"/>
|
||||||
<path d="M42.381,7.271C37.693,2.582,31.458,0,24.826,0C18.195,0,11.96,2.583,7.271,7.271c-9.68,9.68-9.68,25.43,0,35.11
|
<path d="M42.381,7.271C37.693,2.582,31.458,0,24.826,0C18.195,0,11.96,2.583,7.271,7.271c-9.68,9.68-9.68,25.43,0,35.11
|
||||||
c4.689,4.688,10.923,7.271,17.555,7.271c6.632,0,12.867-2.582,17.555-7.271C52.061,32.701,52.061,16.951,42.381,7.271z
|
c4.689,4.688,10.923,7.271,17.555,7.271c6.632,0,12.867-2.582,17.555-7.271C52.061,32.701,52.061,16.951,42.381,7.271z
|
||||||
M24.86,45.002l0.039-12.587c-1.967,0.019-3.941-0.719-5.442-2.22c-2.965-2.965-2.964-7.772,0-10.737
|
M24.86,45.002l0.039-12.587c-1.967,0.019-3.941-0.719-5.442-2.22c-2.965-2.965-2.964-7.772,0-10.737
|
||||||
c0.022-0.022,0.047-0.04,0.069-0.062l-8.935-8.936c4.059-4.072,9.234-6.027,14.363-5.91l-0.039,12.689
|
c0.022-0.022,0.047-0.04,0.069-0.062l-8.935-8.936c4.059-4.072,9.234-6.027,14.363-5.91l-0.039,12.689
|
||||||
c1.915,0.022,3.82,0.759,5.28,2.219c2.942,2.942,2.96,7.699,0.063,10.668l8.967,8.968C35.166,43.164,29.99,45.119,24.86,45.002z"
|
c1.915,0.022,3.82,0.759,5.28,2.219c2.942,2.942,2.96,7.699,0.063,10.668l8.967,8.968C35.166,43.164,29.99,45.119,24.86,45.002z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 123.769 123.769" fill={fill}>
|
<svg viewBox="0 0 123.769 123.769" fill={fill}>
|
||||||
<g>
|
<g>
|
||||||
<path d="M76.05,1.568l-10.101,9.3c-2.3,2.1-5.8,2.1-8.1,0l-10.2-9.2c-3.1-2.8-8-1.7-9.6,2.1l-8.3,20h64.2l-8.3-20.1
|
<path d="M76.05,1.568l-10.101,9.3c-2.3,2.1-5.8,2.1-8.1,0l-10.2-9.2c-3.1-2.8-8-1.7-9.6,2.1l-8.3,20h64.2l-8.3-20.1
|
||||||
C84.05-0.131,79.149-1.231,76.05,1.568z"/>
|
C84.05-0.131,79.149-1.231,76.05,1.568z"/>
|
||||||
<path d="M10.749,42.068c-2.9,1.4-1.8,5.7,1.3,5.7h49.8h49.701c3.199,0,4.199-4.3,1.399-5.7l-12.2-6.3h-77.8L10.749,42.068z"/>
|
<path d="M10.749,42.068c-2.9,1.4-1.8,5.7,1.3,5.7h49.8h49.701c3.199,0,4.199-4.3,1.399-5.7l-12.2-6.3h-77.8L10.749,42.068z"/>
|
||||||
<path d="M0.549,90.168l5.3,28.801c0.5,2.899,3,4.8,5.9,4.8h50.1h50.201c2.899,0,5.399-2,5.899-4.8l5.3-28.801
|
<path d="M0.549,90.168l5.3,28.801c0.5,2.899,3,4.8,5.9,4.8h50.1h50.201c2.899,0,5.399-2,5.899-4.8l5.3-28.801
|
||||||
c0.5-2.8-1-5.6-3.699-6.699c-12.801-5-26.2-7.7-36.801-9.301c-2.699-0.399-5.3,1.101-6.3,3.5l-10.1,22.9c-1.8,4-7.5,4-9.201-0.1
|
c0.5-2.8-1-5.6-3.699-6.699c-12.801-5-26.2-7.7-36.801-9.301c-2.699-0.399-5.3,1.101-6.3,3.5l-10.1,22.9c-1.8,4-7.5,4-9.201-0.1
|
||||||
l-9.8-22.7c-1.1-2.5-3.7-4-6.4-3.601c-10.6,1.5-24,4.301-36.7,9.301C1.549,84.469-0.051,87.269,0.549,90.168z"/>
|
l-9.8-22.7c-1.1-2.5-3.7-4-6.4-3.601c-10.6,1.5-24,4.301-36.7,9.301C1.549,84.469-0.051,87.269,0.549,90.168z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export {contentIcon}
|
export {contentIcon}
|
||||||
|
|
||||||
export default class Torrent extends Component {
|
export default class Torrent extends Component {
|
||||||
state = {
|
state = {
|
||||||
downloading: false,
|
downloading: false,
|
||||||
askDownloading: false,
|
askDownloading: false,
|
||||||
downloadProgress: {}
|
downloadProgress: {}
|
||||||
}
|
}
|
||||||
constructor(props)
|
constructor(props)
|
||||||
{
|
{
|
||||||
super(props)
|
super(props)
|
||||||
if(props.download)
|
if(props.download)
|
||||||
{
|
{
|
||||||
const { progress, downloaded, speed } = props.download
|
const { progress, downloaded, speed } = props.download
|
||||||
this.state.downloadProgress = {
|
this.state.downloadProgress = {
|
||||||
progress, downloaded, speed
|
progress, downloaded, speed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
this.downloading = (hash) => {
|
this.downloading = (hash) => {
|
||||||
if(this.props.torrent.hash != hash)
|
if(this.props.torrent.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({downloading: true})
|
this.setState({downloading: true})
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('downloading', this.downloading);
|
window.torrentSocket.on('downloading', this.downloading);
|
||||||
|
|
||||||
this.downloadDone = (hash, canceled) => {
|
this.downloadDone = (hash, canceled) => {
|
||||||
if(this.props.torrent.hash != hash)
|
if(this.props.torrent.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
downloading: false,
|
downloading: false,
|
||||||
askDownloading: !canceled
|
askDownloading: !canceled
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('downloadDone', this.downloadDone);
|
window.torrentSocket.on('downloadDone', this.downloadDone);
|
||||||
|
|
||||||
this.downloadProgress = (hash, progress) => {
|
this.downloadProgress = (hash, progress) => {
|
||||||
if(this.props.torrent.hash != hash)
|
if(this.props.torrent.hash != hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
downloading: true,
|
downloading: true,
|
||||||
askDownloading: true,
|
askDownloading: true,
|
||||||
downloadProgress: progress
|
downloadProgress: progress
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.torrentSocket.on('downloadProgress', this.downloadProgress);
|
window.torrentSocket.on('downloadProgress', this.downloadProgress);
|
||||||
}
|
}
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
{
|
{
|
||||||
if(this.downloading)
|
if(this.downloading)
|
||||||
window.torrentSocket.off('downloading', this.downloading);
|
window.torrentSocket.off('downloading', this.downloading);
|
||||||
if(this.downloadDone)
|
if(this.downloadDone)
|
||||||
window.torrentSocket.off('downloadDone', this.downloadDone);
|
window.torrentSocket.off('downloadDone', this.downloadDone);
|
||||||
if(this.downloadProgress)
|
if(this.downloadProgress)
|
||||||
window.torrentSocket.off('downloadProgress', this.downloadProgress);
|
window.torrentSocket.off('downloadProgress', this.downloadProgress);
|
||||||
}
|
}
|
||||||
render()
|
render()
|
||||||
{
|
{
|
||||||
const torrent = this.props.torrent;
|
const torrent = this.props.torrent;
|
||||||
let torrentRating = -1
|
let torrentRating = -1
|
||||||
if(torrent.good > 0 || torrent.bad > 0)
|
if(torrent.good > 0 || torrent.bad > 0)
|
||||||
torrentRating = Math.round(rating(torrent.good, torrent.bad) * 100);
|
torrentRating = Math.round(rating(torrent.good, torrent.bad) * 100);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ListItem
|
<ListItem
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
const link = '/torrent/' + torrent.hash;
|
const link = '/torrent/' + torrent.hash;
|
||||||
if(e.button === 1)
|
if(e.button === 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(e.ctrlKey && e.button === 0) {
|
if(e.ctrlKey && e.button === 0) {
|
||||||
let win = window.open(link, '_blank');
|
let win = window.open(link, '_blank');
|
||||||
//win.focus();
|
//win.focus();
|
||||||
@ -239,105 +239,105 @@ export default class Torrent extends Component {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PagesPie.instance().open(TorrentPage, {replace: 'all', hash: torrent.hash, peer: torrent.peer})
|
PagesPie.instance().open(TorrentPage, {replace: 'all', hash: torrent.hash, peer: torrent.peer})
|
||||||
}}
|
}}
|
||||||
primaryText={
|
primaryText={
|
||||||
<a href={'/torrent/' + torrent.hash} ref={(node) => {
|
<a href={'/torrent/' + torrent.hash} ref={(node) => {
|
||||||
if(node)
|
if(node)
|
||||||
node.onclick = () => { return false }
|
node.onclick = () => { return false }
|
||||||
}}>
|
}}>
|
||||||
<span className='break-word' style={{
|
<span className='break-word' style={{
|
||||||
color: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
color: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
||||||
}}>
|
}}>
|
||||||
{torrent.name}
|
{torrent.name}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
secondaryText={
|
secondaryText={
|
||||||
<a href={'/torrent/' + torrent.hash} ref={(node) => {
|
<a href={'/torrent/' + torrent.hash} ref={(node) => {
|
||||||
if(node)
|
if(node)
|
||||||
node.onclick = () => { return false }
|
node.onclick = () => { return false }
|
||||||
}}>
|
}}>
|
||||||
<div className='column' style={{height: 'auto', whiteSpace: 'normal', paddingTop: '0.30em'}}>
|
<div className='column' style={{height: 'auto', whiteSpace: 'normal', paddingTop: '0.30em'}}>
|
||||||
<div className='row w100p inline'>
|
<div className='row w100p inline'>
|
||||||
<div style={{color: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5252d1' : 'black') : (torrent.peer ? '#9083e2' : 'grey')}}>
|
<div style={{color: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5252d1' : 'black') : (torrent.peer ? '#9083e2' : 'grey')}}>
|
||||||
{
|
{
|
||||||
formatBytes(torrent.size, 1) + ' (' + torrent.files + ' files)'
|
formatBytes(torrent.size, 1) + ' (' + torrent.files + ' files)'
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
this.state.downloading
|
this.state.downloading
|
||||||
&&
|
&&
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
style={{width: '44%', marginLeft: 20}}
|
style={{width: '44%', marginLeft: 20}}
|
||||||
mode="determinate"
|
mode="determinate"
|
||||||
value={this.state.downloadProgress && (this.state.downloadProgress.progress ? this.state.downloadProgress.progress : 0) * 100}
|
value={this.state.downloadProgress && (this.state.downloadProgress.progress ? this.state.downloadProgress.progress : 0) * 100}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
torrent.path && torrent.path.length > 0
|
torrent.path && torrent.path.length > 0
|
||||||
?
|
?
|
||||||
torrent.path.map((path, index) => {
|
torrent.path.map((path, index) => {
|
||||||
return <div key={index} className='break-word fs0-75' style={{paddingTop: '0.3em', marginLeft: '0.6em'}}>{path}</div>
|
return <div key={index} className='break-word fs0-75' style={{paddingTop: '0.3em', marginLeft: '0.6em'}}>{path}</div>
|
||||||
})
|
})
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
torrent.seeders || torrent.leechers || torrent.completed
|
torrent.seeders || torrent.leechers || torrent.completed
|
||||||
?
|
?
|
||||||
<div className='break-word fs0-85' style={{paddingTop: '0.35em'}}>
|
<div className='break-word fs0-85' style={{paddingTop: '0.35em'}}>
|
||||||
<span style={{color: (torrent.seeders > 0 ? '#00C853' : 'grey')}}>{torrent.seeders} {__('seeders')}</span>
|
<span style={{color: (torrent.seeders > 0 ? '#00C853' : 'grey')}}>{torrent.seeders} {__('seeders')}</span>
|
||||||
<span style={{color: (torrent.leechers > 0 ? '#AA00FF' : 'grey'), marginLeft: '12px'}}>{torrent.leechers} {__('leechers')}</span>
|
<span style={{color: (torrent.leechers > 0 ? '#AA00FF' : 'grey'), marginLeft: '12px'}}>{torrent.leechers} {__('leechers')}</span>
|
||||||
<span style={{color: (torrent.completed > 0 ? '#FF6D00' : 'grey'), marginLeft: '12px'}}>{torrent.completed} {__('completed')}</span>
|
<span style={{color: (torrent.completed > 0 ? '#FF6D00' : 'grey'), marginLeft: '12px'}}>{torrent.completed} {__('completed')}</span>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
(torrent.good > 0 || torrent.bad > 0)
|
(torrent.good > 0 || torrent.bad > 0)
|
||||||
&&
|
&&
|
||||||
<div className='row w100p inline' style={{maxWidth: 600}}>
|
<div className='row w100p inline' style={{maxWidth: 600}}>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
mode="determinate"
|
mode="determinate"
|
||||||
value={torrentRating}
|
value={torrentRating}
|
||||||
color={torrentRating >= 50 ? '#00E676' : '#FF3D00'}
|
color={torrentRating >= 50 ? '#00E676' : '#FF3D00'}
|
||||||
style={{
|
style={{
|
||||||
height: '5px',
|
height: '5px',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='row center pad0-5 fs0-85 text-nowrap' style={{color: torrentRating >= 50 ? '#00E676' : '#FF3D00', width: '190px'}}>{__('Torrent rating')}: {torrentRating}%</div>
|
<div className='row center pad0-5 fs0-85 text-nowrap' style={{color: torrentRating >= 50 ? '#00E676' : '#FF3D00', width: '190px'}}>{__('Torrent rating')}: {torrentRating}%</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
leftIcon={contentIcon(torrent.contentType, torrent.contentCategory, torrent.contentCategory != 'xxx' ? (torrent.peer ? '#6f5ee0' : 'grey') : (torrent.peer ? '#9083e2' : '#d3d3d3'))}
|
leftIcon={contentIcon(torrent.contentType, torrent.contentCategory, torrent.contentCategory != 'xxx' ? (torrent.peer ? '#6f5ee0' : 'grey') : (torrent.peer ? '#9083e2' : '#d3d3d3'))}
|
||||||
rightIcon={
|
rightIcon={
|
||||||
<div className='row inline' style={{width: 63}}>
|
<div className='row inline' style={{width: 63}}>
|
||||||
{
|
{
|
||||||
!this.state.askDownloading && !this.state.downloading
|
!this.state.askDownloading && !this.state.downloading
|
||||||
?
|
?
|
||||||
<a href={`magnet:?xt=urn:btih:${torrent.hash}`}>
|
<a href={`magnet:?xt=urn:btih:${torrent.hash}`}>
|
||||||
<svg style={{
|
<svg style={{
|
||||||
height: '24px',
|
height: '24px',
|
||||||
marginRight: 12,
|
marginRight: 12,
|
||||||
fill: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
fill: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
||||||
}} onClick={(e) => {
|
}} onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.setState({askDownloading: true})
|
this.setState({askDownloading: true})
|
||||||
window.torrentSocket.emit('download', torrent)
|
window.torrentSocket.emit('download', torrent)
|
||||||
}} viewBox="0 0 56 56">
|
}} viewBox="0 0 56 56">
|
||||||
<g>
|
<g>
|
||||||
<path d="M35.586,41.586L31,46.172V28c0-1.104-0.896-2-2-2s-2,0.896-2,2v18.172l-4.586-4.586c-0.781-0.781-2.047-0.781-2.828,0
|
<path d="M35.586,41.586L31,46.172V28c0-1.104-0.896-2-2-2s-2,0.896-2,2v18.172l-4.586-4.586c-0.781-0.781-2.047-0.781-2.828,0
|
||||||
s-0.781,2.047,0,2.828l7.999,7.999c0.093,0.094,0.196,0.177,0.307,0.251c0.047,0.032,0.099,0.053,0.148,0.081
|
s-0.781,2.047,0,2.828l7.999,7.999c0.093,0.094,0.196,0.177,0.307,0.251c0.047,0.032,0.099,0.053,0.148,0.081
|
||||||
c0.065,0.036,0.127,0.075,0.196,0.103c0.065,0.027,0.133,0.042,0.2,0.062c0.058,0.017,0.113,0.04,0.173,0.051
|
c0.065,0.036,0.127,0.075,0.196,0.103c0.065,0.027,0.133,0.042,0.2,0.062c0.058,0.017,0.113,0.04,0.173,0.051
|
||||||
C28.738,52.986,28.869,53,29,53s0.262-0.014,0.392-0.04c0.06-0.012,0.115-0.034,0.173-0.051c0.067-0.02,0.135-0.035,0.2-0.062
|
C28.738,52.986,28.869,53,29,53s0.262-0.014,0.392-0.04c0.06-0.012,0.115-0.034,0.173-0.051c0.067-0.02,0.135-0.035,0.2-0.062
|
||||||
c0.069-0.028,0.131-0.067,0.196-0.103c0.05-0.027,0.101-0.049,0.148-0.081c0.11-0.074,0.213-0.157,0.307-0.251l7.999-7.999
|
c0.069-0.028,0.131-0.067,0.196-0.103c0.05-0.027,0.101-0.049,0.148-0.081c0.11-0.074,0.213-0.157,0.307-0.251l7.999-7.999
|
||||||
c0.781-0.781,0.781-2.047,0-2.828S36.367,40.805,35.586,41.586z"/>
|
c0.781-0.781,0.781-2.047,0-2.828S36.367,40.805,35.586,41.586z"/>
|
||||||
<path d="M47.835,18.986c-0.137-0.019-2.457-0.335-4.684,0.002C43.1,18.996,43.049,19,42.999,19c-0.486,0-0.912-0.354-0.987-0.85
|
<path d="M47.835,18.986c-0.137-0.019-2.457-0.335-4.684,0.002C43.1,18.996,43.049,19,42.999,19c-0.486,0-0.912-0.354-0.987-0.85
|
||||||
c-0.083-0.546,0.292-1.056,0.838-1.139c1.531-0.233,3.062-0.196,4.083-0.124C46.262,9.135,39.83,3,32.085,3
|
c-0.083-0.546,0.292-1.056,0.838-1.139c1.531-0.233,3.062-0.196,4.083-0.124C46.262,9.135,39.83,3,32.085,3
|
||||||
C27.388,3,22.667,5.379,19.8,9.129C21.754,10.781,23,13.246,23,16c0,0.553-0.447,1-1,1s-1-0.447-1-1
|
C27.388,3,22.667,5.379,19.8,9.129C21.754,10.781,23,13.246,23,16c0,0.553-0.447,1-1,1s-1-0.447-1-1
|
||||||
c0-2.462-1.281-4.627-3.209-5.876c-0.227-0.147-0.462-0.277-0.702-0.396c-0.069-0.034-0.139-0.069-0.21-0.101
|
c0-2.462-1.281-4.627-3.209-5.876c-0.227-0.147-0.462-0.277-0.702-0.396c-0.069-0.034-0.139-0.069-0.21-0.101
|
||||||
@ -346,39 +346,39 @@ export default class Torrent extends Component {
|
|||||||
l0.012,0.21l-0.009,0.16C7.008,16.744,7,16.873,7,17v0.63l-0.567,0.271C2.705,19.688,0,24,0,28.154C0,34.135,4.865,39,10.845,39H25
|
l0.012,0.21l-0.009,0.16C7.008,16.744,7,16.873,7,17v0.63l-0.567,0.271C2.705,19.688,0,24,0,28.154C0,34.135,4.865,39,10.845,39H25
|
||||||
V28c0-2.209,1.791-4,4-4s4,1.791,4,4v11h2.353c0.059,0,0.116-0.005,0.174-0.009l0.198-0.011l0.271,0.011
|
V28c0-2.209,1.791-4,4-4s4,1.791,4,4v11h2.353c0.059,0,0.116-0.005,0.174-0.009l0.198-0.011l0.271,0.011
|
||||||
C36.053,38.995,36.11,39,36.169,39h9.803C51.501,39,56,34.501,56,28.972C56,24.161,52.49,19.872,47.835,18.986z"/>
|
C36.053,38.995,36.11,39,36.169,39h9.803C51.501,39,56,34.501,56,28.972C56,24.161,52.49,19.872,47.835,18.986z"/>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
:
|
:
|
||||||
this.state.askDownloading && !this.state.downloading
|
this.state.askDownloading && !this.state.downloading
|
||||||
?
|
?
|
||||||
<img src={Spinner24} />
|
<img src={Spinner24} />
|
||||||
:
|
:
|
||||||
this.state.askDownloading && this.state.downloading
|
this.state.askDownloading && this.state.downloading
|
||||||
&&
|
&&
|
||||||
<a href={`magnet:?xt=urn:btih:${torrent.hash}`}>
|
<a href={`magnet:?xt=urn:btih:${torrent.hash}`}>
|
||||||
<svg style={{
|
<svg style={{
|
||||||
height: '24px',
|
height: '24px',
|
||||||
fill: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
fill: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
||||||
}} onClick={(e) => {
|
}} onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
window.torrentSocket.emit('downloadCancel', torrent.hash)
|
window.torrentSocket.emit('downloadCancel', torrent.hash)
|
||||||
}} viewBox="0 0 18 18"><path d="M9 1C4.58 1 1 4.58 1 9s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4 10.87L11.87 13 9 10.13 6.13 13 5 11.87 7.87 9 5 6.13 6.13 5 9 7.87 11.87 5 13 6.13 10.13 9 13 11.87z"/></svg>
|
}} viewBox="0 0 18 18"><path d="M9 1C4.58 1 1 4.58 1 9s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4 10.87L11.87 13 9 10.13 6.13 13 5 11.87 7.87 9 5 6.13 6.13 5 9 7.87 11.87 5 13 6.13 10.13 9 13 11.87z"/></svg>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
<a style={{float: 'right'}} href={`magnet:?xt=urn:btih:${torrent.hash}`}>
|
<a style={{float: 'right'}} href={`magnet:?xt=urn:btih:${torrent.hash}`}>
|
||||||
<svg style={{
|
<svg style={{
|
||||||
height: '24px',
|
height: '24px',
|
||||||
fill: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
fill: torrent.contentCategory != 'xxx' ? (torrent.peer ? '#5643db' : 'black') : (torrent.peer ? '#9083e2' : 'grey')
|
||||||
}} onClick={(e) => {
|
}} onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
var win = window.open(`magnet:?xt=urn:btih:${torrent.hash}`, '_self');
|
var win = window.open(`magnet:?xt=urn:btih:${torrent.hash}`, '_self');
|
||||||
}} viewBox="0 0 24 24">
|
}} viewBox="0 0 24 24">
|
||||||
<path d="M15.82 10.736l-5.451 6.717c-.561.691-1.214 1.042-1.94 1.042-1.144
|
<path d="M15.82 10.736l-5.451 6.717c-.561.691-1.214 1.042-1.94 1.042-1.144
|
||||||
0-2.327-.899-2.753-2.091-.214-.6-.386-1.76.865-2.784 3.417-2.794 6.716-5.446
|
0-2.327-.899-2.753-2.091-.214-.6-.386-1.76.865-2.784 3.417-2.794 6.716-5.446
|
||||||
6.716-5.446l-3.363-4.174s-4.532 3.657-6.771 5.487c-2.581 2.108-3.123 4.468-3.123
|
6.716-5.446l-3.363-4.174s-4.532 3.657-6.771 5.487c-2.581 2.108-3.123 4.468-3.123
|
||||||
6.075 0 4.416 4.014 8.438 8.42 8.438 1.604 0 3.963-.543 6.084-3.128 1.835-2.237
|
6.075 0 4.416 4.014 8.438 8.42 8.438 1.604 0 3.963-.543 6.084-3.128 1.835-2.237
|
||||||
@ -390,12 +390,12 @@ export default class Torrent extends Component {
|
|||||||
4.151zm6.152-7.934l4.318-2.88-1.575-.638 1.889-2.414-4.421 2.788 1.716.695-1.927
|
4.151zm6.152-7.934l4.318-2.88-1.575-.638 1.889-2.414-4.421 2.788 1.716.695-1.927
|
||||||
2.449zm-7.292-7.186l4.916-1.667-1.356-1.022 2.448-2.006-4.991 1.712
|
2.449zm-7.292-7.186l4.916-1.667-1.356-1.022 2.448-2.006-4.991 1.712
|
||||||
1.478 1.114-2.495 1.869z"/></svg>
|
1.478 1.114-2.495 1.869z"/></svg>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
144
src/app/touch.js
144
src/app/touch.js
@ -2,94 +2,94 @@ import ReactDOM from 'react-dom';
|
|||||||
|
|
||||||
let listenSwipe = (component, handlers) =>
|
let listenSwipe = (component, handlers) =>
|
||||||
{
|
{
|
||||||
let element = ReactDOM.findDOMNode(component),
|
let element = ReactDOM.findDOMNode(component),
|
||||||
startX,
|
startX,
|
||||||
startY,
|
startY,
|
||||||
distanceX,
|
distanceX,
|
||||||
distanceY,
|
distanceY,
|
||||||
threshold = 110,
|
threshold = 110,
|
||||||
allowedTime = 280,
|
allowedTime = 280,
|
||||||
thresholdAlternativeAxis = 145,
|
thresholdAlternativeAxis = 145,
|
||||||
elapsedTime,
|
elapsedTime,
|
||||||
startTime;
|
startTime;
|
||||||
|
|
||||||
let touchFunctions = {
|
let touchFunctions = {
|
||||||
touchstart : (e) => {
|
touchstart : (e) => {
|
||||||
let touchObject = e.changedTouches[0]
|
let touchObject = e.changedTouches[0]
|
||||||
|
|
||||||
distanceX = 0;
|
distanceX = 0;
|
||||||
distanceY = 0;
|
distanceY = 0;
|
||||||
|
|
||||||
startX = touchObject.pageX
|
startX = touchObject.pageX
|
||||||
startY = touchObject.pageY
|
startY = touchObject.pageY
|
||||||
|
|
||||||
startTime = new Date().getTime()
|
startTime = new Date().getTime()
|
||||||
|
|
||||||
if(handlers && handlers.preventDefault)
|
if(handlers && handlers.preventDefault)
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if(handlers && handlers.initSwipe)
|
if(handlers && handlers.initSwipe)
|
||||||
handlers.initSwipe.call(component);
|
handlers.initSwipe.call(component);
|
||||||
},
|
},
|
||||||
touchmove : (e) => {
|
touchmove : (e) => {
|
||||||
if(handlers && handlers.preventDefault)
|
if(handlers && handlers.preventDefault)
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
touchend : (e) => {
|
touchend : (e) => {
|
||||||
let touchObject = e.changedTouches[0];
|
let touchObject = e.changedTouches[0];
|
||||||
|
|
||||||
distanceX = touchObject.pageX - startX;
|
distanceX = touchObject.pageX - startX;
|
||||||
distanceY = touchObject.pageY - startY;
|
distanceY = touchObject.pageY - startY;
|
||||||
|
|
||||||
elapsedTime = new Date().getTime() - startTime; // get time elapsed
|
elapsedTime = new Date().getTime() - startTime; // get time elapsed
|
||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
startX,
|
startX,
|
||||||
startY,
|
startY,
|
||||||
endX: touchObject.pageX,
|
endX: touchObject.pageX,
|
||||||
endY: touchObject.pageY,
|
endY: touchObject.pageY,
|
||||||
distanceX,
|
distanceX,
|
||||||
distanceY
|
distanceY
|
||||||
};
|
};
|
||||||
|
|
||||||
if (elapsedTime <= allowedTime)
|
if (elapsedTime <= allowedTime)
|
||||||
{
|
{
|
||||||
if(distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis)
|
if(distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis)
|
||||||
{
|
{
|
||||||
if(handlers && handlers.left)
|
if(handlers && handlers.left)
|
||||||
handlers.left.call(component, params);
|
handlers.left.call(component, params);
|
||||||
} else
|
} else
|
||||||
if(-distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis) {
|
if(-distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis) {
|
||||||
if(handlers && handlers.right)
|
if(handlers && handlers.right)
|
||||||
handlers.right.call(component, params);
|
handlers.right.call(component, params);
|
||||||
} else
|
} else
|
||||||
if(distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) {
|
if(distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) {
|
||||||
if(handlers && handlers.top)
|
if(handlers && handlers.top)
|
||||||
handlers.top.call(component, params);
|
handlers.top.call(component, params);
|
||||||
} else
|
} else
|
||||||
if(-distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) {
|
if(-distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) {
|
||||||
if(handlers && handlers.bottom)
|
if(handlers && handlers.bottom)
|
||||||
handlers.bottom.call(component, params);
|
handlers.bottom.call(component, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handlers && handlers.preventDefault)
|
if(handlers && handlers.preventDefault)
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
element.addEventListener('touchstart', touchFunctions.touchstart, false);
|
element.addEventListener('touchstart', touchFunctions.touchstart, false);
|
||||||
element.addEventListener('touchmove', touchFunctions.touchmove, false);
|
element.addEventListener('touchmove', touchFunctions.touchmove, false);
|
||||||
element.addEventListener('touchend', touchFunctions.touchend, false);
|
element.addEventListener('touchend', touchFunctions.touchend, false);
|
||||||
|
|
||||||
return touchFunctions;
|
return touchFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
let removeSwipeListener = (component, touchFunctions) => {
|
let removeSwipeListener = (component, touchFunctions) => {
|
||||||
let element = ReactDOM.findDOMNode(component);
|
let element = ReactDOM.findDOMNode(component);
|
||||||
element.removeEventListener('touchstart', touchFunctions.touchstart);
|
element.removeEventListener('touchstart', touchFunctions.touchstart);
|
||||||
element.removeEventListener('touchmove', touchFunctions.touchmove);
|
element.removeEventListener('touchmove', touchFunctions.touchmove);
|
||||||
element.removeEventListener('touchend', touchFunctions.touchend);
|
element.removeEventListener('touchend', touchFunctions.touchend);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { listenSwipe, removeSwipeListener }
|
export { listenSwipe, removeSwipeListener }
|
@ -35,17 +35,17 @@ module.exports = async ({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
sphinx.query('SELECT * FROM `torrents` ORDER BY added DESC LIMIT 0,10', function (error, rows, fields) {
|
sphinx.query('SELECT * FROM `torrents` ORDER BY added DESC LIMIT 0,10', function (error, rows, fields) {
|
||||||
if(!rows) {
|
if(!rows) {
|
||||||
callback(undefined)
|
callback(undefined)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let torrents = [];
|
let torrents = [];
|
||||||
rows.forEach((row) => {
|
rows.forEach((row) => {
|
||||||
torrents.push(baseRowData(row));
|
torrents.push(baseRowData(row));
|
||||||
});
|
});
|
||||||
|
|
||||||
callback(torrents)
|
callback(torrents)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -55,25 +55,25 @@ module.exports = async ({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
sphinx.query('SELECT count(*) AS torrents, sum(size) AS sz FROM `torrents`', function (error, rows, fields) {
|
sphinx.query('SELECT count(*) AS torrents, sum(size) AS sz FROM `torrents`', function (error, rows, fields) {
|
||||||
if(!rows) {
|
if(!rows) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
callback(undefined)
|
callback(undefined)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
let result = {torrents: rows[0].torrents || 0, size: rows[0].sz || 0}
|
|
||||||
|
|
||||||
sphinx.query('SELECT count(*) AS files FROM `files`', function (error, rows, fields) {
|
|
||||||
if(!rows) {
|
|
||||||
console.error(error)
|
|
||||||
callback(undefined)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.files = rows[0].files || 0
|
let result = {torrents: rows[0].torrents || 0, size: rows[0].sz || 0}
|
||||||
|
|
||||||
callback(result)
|
sphinx.query('SELECT count(*) AS files FROM `files`', function (error, rows, fields) {
|
||||||
})
|
if(!rows) {
|
||||||
|
console.error(error)
|
||||||
|
callback(undefined)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.files = rows[0].files || 0
|
||||||
|
|
||||||
|
callback(result)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,43 +112,43 @@ module.exports = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
sphinx.query('SELECT * FROM `torrents` WHERE `hash` = ?', hash, async function (error, rows, fields) {
|
sphinx.query('SELECT * FROM `torrents` WHERE `hash` = ?', hash, async function (error, rows, fields) {
|
||||||
if(!rows || rows.length == 0) {
|
if(!rows || rows.length == 0) {
|
||||||
callback(undefined)
|
callback(undefined)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
let torrent = rows[0];
|
|
||||||
|
|
||||||
if(options.files)
|
|
||||||
{
|
|
||||||
torrent.filesList = await sphinx.query('SELECT * FROM `files` WHERE `hash` = ? LIMIT 50000', hash);
|
|
||||||
callback(baseRowData(torrent))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
callback(baseRowData(torrent))
|
|
||||||
}
|
|
||||||
|
|
||||||
if(torrentClientHashMap[hash])
|
|
||||||
{
|
|
||||||
const torrent = torrentClient.get(torrentClientHashMap[hash])
|
|
||||||
if(torrent)
|
|
||||||
{
|
|
||||||
send('downloading', torrent.infoHash)
|
|
||||||
}
|
}
|
||||||
}
|
let torrent = rows[0];
|
||||||
|
|
||||||
// get votes
|
if(options.files)
|
||||||
const {good, bad, selfVote} = await getVotes(hash)
|
{
|
||||||
send('votes', {
|
torrent.filesList = await sphinx.query('SELECT * FROM `files` WHERE `hash` = ? LIMIT 50000', hash);
|
||||||
hash, good, bad, selfVote
|
callback(baseRowData(torrent))
|
||||||
});
|
}
|
||||||
if(torrent.good != good || torrent.bad != bad)
|
else
|
||||||
{
|
{
|
||||||
console.log('finded new rating on', torrent.name, 'update votes to it')
|
callback(baseRowData(torrent))
|
||||||
torrent.good = good
|
}
|
||||||
torrent.bad = bad
|
|
||||||
updateTorrentToDB(torrent)
|
if(torrentClientHashMap[hash])
|
||||||
}
|
{
|
||||||
|
const torrent = torrentClient.get(torrentClientHashMap[hash])
|
||||||
|
if(torrent)
|
||||||
|
{
|
||||||
|
send('downloading', torrent.infoHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get votes
|
||||||
|
const {good, bad, selfVote} = await getVotes(hash)
|
||||||
|
send('votes', {
|
||||||
|
hash, good, bad, selfVote
|
||||||
|
});
|
||||||
|
if(torrent.good != good || torrent.bad != bad)
|
||||||
|
{
|
||||||
|
console.log('finded new rating on', torrent.name, 'update votes to it')
|
||||||
|
torrent.good = good
|
||||||
|
torrent.bad = bad
|
||||||
|
updateTorrentToDB(torrent)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,13 +277,13 @@ module.exports = async ({
|
|||||||
sphinx.query('SELECT * FROM `torrents` WHERE MATCH(?) ' + where + ' ' + order + ' LIMIT ?,?', args, function (error, rows, fields) {
|
sphinx.query('SELECT * FROM `torrents` WHERE MATCH(?) ' + where + ' ' + order + ' LIMIT ?,?', args, function (error, rows, fields) {
|
||||||
if(!rows) {
|
if(!rows) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
callback(undefined)
|
callback(undefined)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rows.forEach((row) => {
|
rows.forEach((row) => {
|
||||||
searchList.push(baseRowData(row));
|
searchList.push(baseRowData(row));
|
||||||
});
|
});
|
||||||
callback(searchList);
|
callback(searchList);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,37 +328,37 @@ module.exports = async ({
|
|||||||
let where = '';
|
let where = '';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(orderBy && orderBy.length > 0)
|
if(orderBy && orderBy.length > 0)
|
||||||
{
|
{
|
||||||
const orderDesc = navigation.orderDesc ? 'DESC' : 'ASC';
|
const orderDesc = navigation.orderDesc ? 'DESC' : 'ASC';
|
||||||
args.splice(1, 0, orderBy);
|
args.splice(1, 0, orderBy);
|
||||||
order = 'ORDER BY ?? ' + orderDesc;
|
order = 'ORDER BY ?? ' + orderDesc;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
if(safeSearch)
|
if(safeSearch)
|
||||||
{
|
{
|
||||||
where += " and contentCategory != 'xxx' ";
|
where += " and contentCategory != 'xxx' ";
|
||||||
}
|
}
|
||||||
if(navigation.type && navigation.type.length > 0)
|
if(navigation.type && navigation.type.length > 0)
|
||||||
{
|
{
|
||||||
where += ' and contentType = ' + sphinx.escape(navigation.type) + ' ';
|
where += ' and contentType = ' + sphinx.escape(navigation.type) + ' ';
|
||||||
}
|
}
|
||||||
if(navigation.size)
|
if(navigation.size)
|
||||||
{
|
{
|
||||||
if(navigation.size.max > 0)
|
if(navigation.size.max > 0)
|
||||||
where += ' and torrentSize < ' + sphinx.escape(navigation.size.max) + ' ';
|
where += ' and torrentSize < ' + sphinx.escape(navigation.size.max) + ' ';
|
||||||
if(navigation.size.min > 0)
|
if(navigation.size.min > 0)
|
||||||
where += ' and torrentSize > ' + sphinx.escape(navigation.size.min) + ' ';
|
where += ' and torrentSize > ' + sphinx.escape(navigation.size.min) + ' ';
|
||||||
}
|
}
|
||||||
if(navigation.files)
|
if(navigation.files)
|
||||||
{
|
{
|
||||||
if(navigation.files.max > 0)
|
if(navigation.files.max > 0)
|
||||||
where += ' and files < ' + sphinx.escape(navigation.files.max) + ' ';
|
where += ' and files < ' + sphinx.escape(navigation.files.max) + ' ';
|
||||||
if(navigation.files.min > 0)
|
if(navigation.files.min > 0)
|
||||||
where += ' and files > ' + sphinx.escape(navigation.files.min) + ' ';
|
where += ' and files > ' + sphinx.escape(navigation.files.min) + ' ';
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let search = {};
|
let search = {};
|
||||||
//args.splice(orderBy && orderBy.length > 0 ? 1 : 0, 1);
|
//args.splice(orderBy && orderBy.length > 0 ? 1 : 0, 1);
|
||||||
@ -366,8 +366,8 @@ module.exports = async ({
|
|||||||
sphinx.query('SELECT * FROM `files` WHERE MATCH(?) ' + where + ' ' + order + ' LIMIT ?,?', args, function (error, files, fields) {
|
sphinx.query('SELECT * FROM `files` WHERE MATCH(?) ' + where + ' ' + order + ' LIMIT ?,?', args, function (error, files, fields) {
|
||||||
if(!files) {
|
if(!files) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
callback(undefined)
|
callback(undefined)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(files.length === 0)
|
if(files.length === 0)
|
||||||
{
|
{
|
||||||
@ -481,7 +481,7 @@ module.exports = async ({
|
|||||||
|
|
||||||
rows = rows.map((row) => baseRowData(row));
|
rows = rows.map((row) => baseRowData(row));
|
||||||
topCache[query] = rows;
|
topCache[query] = rows;
|
||||||
callback(rows);
|
callback(rows);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,17 +28,17 @@ require('electron-context-menu')({})
|
|||||||
// Thanks to this you can use production and development versions of the app
|
// Thanks to this you can use production and development versions of the app
|
||||||
// on same machine like those are two separate apps.
|
// on same machine like those are two separate apps.
|
||||||
if (env.name !== "production") {
|
if (env.name !== "production") {
|
||||||
const userDataPath = app.getPath("userData");
|
const userDataPath = app.getPath("userData");
|
||||||
app.setPath("userData", `${userDataPath} (${env.name})`);
|
app.setPath("userData", `${userDataPath} (${env.name})`);
|
||||||
}
|
}
|
||||||
// portative version
|
// portative version
|
||||||
let portative = false
|
let portative = false
|
||||||
if(env.name === "production") {
|
if(env.name === "production") {
|
||||||
if(fs.existsSync(path.dirname(process.execPath) + `/data`))
|
if(fs.existsSync(path.dirname(process.execPath) + `/data`))
|
||||||
{
|
{
|
||||||
portative = true;
|
portative = true;
|
||||||
app.setPath("userData", path.dirname(process.execPath) + `/data`);
|
app.setPath("userData", path.dirname(process.execPath) + `/data`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourcesPath = env.name === "production" ? process.resourcesPath : 'resources'
|
const resourcesPath = env.name === "production" ? process.resourcesPath : 'resources'
|
||||||
@ -54,33 +54,33 @@ let sphinx = undefined
|
|||||||
let spider = undefined
|
let spider = undefined
|
||||||
|
|
||||||
const setApplicationMenu = () => {
|
const setApplicationMenu = () => {
|
||||||
const settingsMenuTemplate = settingsMenuTemplateFunc(appConfig, (lang) => {
|
const settingsMenuTemplate = settingsMenuTemplateFunc(appConfig, (lang) => {
|
||||||
// update menu translation
|
// update menu translation
|
||||||
changeLanguage(lang, () => setApplicationMenu())
|
changeLanguage(lang, () => setApplicationMenu())
|
||||||
})
|
})
|
||||||
const menus = [editMenuTemplateFunc(), manageMenuTemplateFunc(), settingsMenuTemplate, aboutMenuTemplateFunc()];
|
const menus = [editMenuTemplateFunc(), manageMenuTemplateFunc(), settingsMenuTemplate, aboutMenuTemplateFunc()];
|
||||||
|
|
||||||
if (env.name !== "production") {
|
if (env.name !== "production") {
|
||||||
menus.push(devMenuTemplate);
|
menus.push(devMenuTemplate);
|
||||||
}
|
}
|
||||||
// append version as disabled menu item
|
// append version as disabled menu item
|
||||||
menus.push({
|
menus.push({
|
||||||
label: app.getVersion()
|
label: app.getVersion()
|
||||||
})
|
})
|
||||||
Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
|
Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
|
||||||
};
|
};
|
||||||
|
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
if (!fs.existsSync(app.getPath("userData"))){
|
if (!fs.existsSync(app.getPath("userData"))){
|
||||||
fs.mkdirSync(app.getPath("userData"));
|
fs.mkdirSync(app.getPath("userData"));
|
||||||
}
|
}
|
||||||
const logFile = fs.createWriteStream(app.getPath("userData") + '/rats.log', {flags : 'w'});
|
const logFile = fs.createWriteStream(app.getPath("userData") + '/rats.log', {flags : 'w'});
|
||||||
const logStdout = process.stdout;
|
const logStdout = process.stdout;
|
||||||
|
|
||||||
console.log = (...d) => {
|
console.log = (...d) => {
|
||||||
const date = (new Date).toLocaleTimeString()
|
const date = (new Date).toLocaleTimeString()
|
||||||
logFile.write(`[${date}] ` + util.format(...d) + '\n');
|
logFile.write(`[${date}] ` + util.format(...d) + '\n');
|
||||||
logStdout.write(util.format(...d) + '\n');
|
logStdout.write(util.format(...d) + '\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
// print os info
|
// print os info
|
||||||
@ -94,21 +94,21 @@ console.log('Total memory:', (os.totalmem() / (1024 * 1024)).toFixed(2), 'MB')
|
|||||||
console.log('Free memory:', (os.freemem() / (1024 * 1024)).toFixed(2), 'MB')
|
console.log('Free memory:', (os.freemem() / (1024 * 1024)).toFixed(2), 'MB')
|
||||||
|
|
||||||
if(portative)
|
if(portative)
|
||||||
console.log('portative compability')
|
console.log('portative compability')
|
||||||
|
|
||||||
const shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) {
|
const shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) {
|
||||||
// Someone tried to run a second instance, we should focus our window.
|
// Someone tried to run a second instance, we should focus our window.
|
||||||
console.log('openned second application, just focus this one')
|
console.log('openned second application, just focus this one')
|
||||||
if (mainWindow) {
|
if (mainWindow) {
|
||||||
if (mainWindow.isMinimized())
|
if (mainWindow.isMinimized())
|
||||||
mainWindow.restore();
|
mainWindow.restore();
|
||||||
mainWindow.focus();
|
mainWindow.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shouldQuit) {
|
if (shouldQuit) {
|
||||||
console.log('closed because of second application')
|
console.log('closed because of second application')
|
||||||
app.exit(0);
|
app.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// log autoupdate
|
// log autoupdate
|
||||||
@ -116,162 +116,162 @@ const log = require('electron-log')
|
|||||||
log.transports.file.level = false;
|
log.transports.file.level = false;
|
||||||
log.transports.console.level = false;
|
log.transports.console.level = false;
|
||||||
log.transports.console = function(msg) {
|
log.transports.console = function(msg) {
|
||||||
const text = util.format.apply(util, msg.data);
|
const text = util.format.apply(util, msg.data);
|
||||||
console.log(text);
|
console.log(text);
|
||||||
};
|
};
|
||||||
autoUpdater.logger = log;
|
autoUpdater.logger = log;
|
||||||
|
|
||||||
autoUpdater.on('update-downloaded', () => {
|
autoUpdater.on('update-downloaded', () => {
|
||||||
console.log('update-downloaded lats quitAndInstall');
|
console.log('update-downloaded lats quitAndInstall');
|
||||||
if (env.name === "production") {
|
if (env.name === "production") {
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
title: 'Found Updates',
|
title: 'Found Updates',
|
||||||
message: 'Found updates, do you want update now?',
|
message: 'Found updates, do you want update now?',
|
||||||
buttons: ['Sure', 'No']
|
buttons: ['Sure', 'No']
|
||||||
}, (buttonIndex) => {
|
}, (buttonIndex) => {
|
||||||
if (buttonIndex === 0) {
|
if (buttonIndex === 0) {
|
||||||
const isSilent = true;
|
const isSilent = true;
|
||||||
const isForceRunAfter = true;
|
const isForceRunAfter = true;
|
||||||
autoUpdater.quitAndInstall(isSilent, isForceRunAfter);
|
autoUpdater.quitAndInstall(isSilent, isForceRunAfter);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let tray = undefined
|
let tray = undefined
|
||||||
|
|
||||||
app.on("ready", () => {
|
app.on("ready", () => {
|
||||||
sphinx = startSphinx(() => {
|
sphinx = startSphinx(() => {
|
||||||
|
|
||||||
mainWindow = createWindow("main", {
|
mainWindow = createWindow("main", {
|
||||||
width: 1000,
|
width: 1000,
|
||||||
height: 600
|
height: 600
|
||||||
});
|
});
|
||||||
|
|
||||||
dbPatcher(() => {
|
dbPatcher(() => {
|
||||||
changeLanguage(appConfig.language, () => setApplicationMenu())
|
changeLanguage(appConfig.language, () => setApplicationMenu())
|
||||||
|
|
||||||
mainWindow.loadURL(
|
mainWindow.loadURL(
|
||||||
url.format({
|
url.format({
|
||||||
pathname: path.join(__dirname, "app.html"),
|
pathname: path.join(__dirname, "app.html"),
|
||||||
protocol: "file:",
|
protocol: "file:",
|
||||||
slashes: true
|
slashes: true
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (env.name === "development") {
|
if (env.name === "development") {
|
||||||
mainWindow.openDevTools();
|
mainWindow.openDevTools();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(process.platform === 'darwin')
|
if(process.platform === 'darwin')
|
||||||
tray = new Tray(`${resourcesPath}/icons/19x19.png`)
|
tray = new Tray(`${resourcesPath}/icons/19x19.png`)
|
||||||
else
|
|
||||||
tray = new Tray(`${resourcesPath}/icons/512x512.png`)
|
|
||||||
|
|
||||||
tray.on('click', () => {
|
|
||||||
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
|
|
||||||
})
|
|
||||||
mainWindow.on('show', () => {
|
|
||||||
tray.setHighlightMode('always')
|
|
||||||
})
|
|
||||||
mainWindow.on('hide', () => {
|
|
||||||
tray.setHighlightMode('never')
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.on('close', (event) => {
|
|
||||||
if (!app.isQuiting && appConfig.trayOnClose && process.platform !== 'linux') {
|
|
||||||
event.preventDefault()
|
|
||||||
mainWindow.hide()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
mainWindow.on('closed', () => {
|
|
||||||
mainWindow = undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.on('minimize', (event) => {
|
|
||||||
if(appConfig.trayOnMinimize)
|
|
||||||
{
|
|
||||||
event.preventDefault();
|
|
||||||
mainWindow.hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var contextMenu = Menu.buildFromTemplate([
|
|
||||||
{ label: 'Show', click: function(){
|
|
||||||
mainWindow.show();
|
|
||||||
} },
|
|
||||||
{ label: 'Quit', click: function(){
|
|
||||||
app.isQuiting = true;
|
|
||||||
if (sphinx)
|
|
||||||
stop()
|
|
||||||
else
|
else
|
||||||
app.quit()
|
tray = new Tray(`${resourcesPath}/icons/512x512.png`)
|
||||||
} }
|
|
||||||
]);
|
|
||||||
|
|
||||||
tray.setContextMenu(contextMenu)
|
tray.on('click', () => {
|
||||||
tray.setToolTip('Rats on The Boat search')
|
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
|
||||||
|
})
|
||||||
|
mainWindow.on('show', () => {
|
||||||
|
tray.setHighlightMode('always')
|
||||||
|
})
|
||||||
|
mainWindow.on('hide', () => {
|
||||||
|
tray.setHighlightMode('never')
|
||||||
|
})
|
||||||
|
|
||||||
mainWindow.webContents.on('will-navigate', e => { e.preventDefault() })
|
mainWindow.on('close', (event) => {
|
||||||
mainWindow.webContents.on('new-window', (event, url, frameName) => {
|
if (!app.isQuiting && appConfig.trayOnClose && process.platform !== 'linux') {
|
||||||
if(frameName == '_self')
|
event.preventDefault()
|
||||||
{
|
mainWindow.hide()
|
||||||
event.preventDefault()
|
return
|
||||||
mainWindow.loadURL(url)
|
}
|
||||||
}
|
})
|
||||||
})
|
mainWindow.on('closed', () => {
|
||||||
|
mainWindow = undefined
|
||||||
|
})
|
||||||
|
|
||||||
if (env.name === "production" && !portative) { autoUpdater.checkForUpdates() }
|
mainWindow.on('minimize', (event) => {
|
||||||
|
if(appConfig.trayOnMinimize)
|
||||||
|
{
|
||||||
|
event.preventDefault();
|
||||||
|
mainWindow.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
spider = new spiderCall((...data) => {
|
var contextMenu = Menu.buildFromTemplate([
|
||||||
if(mainWindow)
|
{ label: 'Show', click: function(){
|
||||||
mainWindow.webContents.send(...data)
|
mainWindow.show();
|
||||||
}, (message, callback) => {
|
} },
|
||||||
ipcMain.on(message, (event, arg) => {
|
{ label: 'Quit', click: function(){
|
||||||
if(Array.isArray(arg) && typeof arg[arg.length - 1] === 'object' && arg[arg.length - 1].callback)
|
app.isQuiting = true;
|
||||||
{
|
if (sphinx)
|
||||||
const id = arg[arg.length - 1].callback
|
stop()
|
||||||
arg[arg.length - 1] = (responce) => {
|
else
|
||||||
mainWindow.webContents.send('callback', id, responce)
|
app.quit()
|
||||||
}
|
} }
|
||||||
}
|
]);
|
||||||
callback.apply(null, arg)
|
|
||||||
})
|
tray.setContextMenu(contextMenu)
|
||||||
}, app.getPath("userData"), app.getVersion(), env.name)
|
tray.setToolTip('Rats on The Boat search')
|
||||||
}, mainWindow, sphinx)
|
|
||||||
}, app.getPath("userData"), () => app.quit())
|
mainWindow.webContents.on('will-navigate', e => { e.preventDefault() })
|
||||||
|
mainWindow.webContents.on('new-window', (event, url, frameName) => {
|
||||||
|
if(frameName == '_self')
|
||||||
|
{
|
||||||
|
event.preventDefault()
|
||||||
|
mainWindow.loadURL(url)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (env.name === "production" && !portative) { autoUpdater.checkForUpdates() }
|
||||||
|
|
||||||
|
spider = new spiderCall((...data) => {
|
||||||
|
if(mainWindow)
|
||||||
|
mainWindow.webContents.send(...data)
|
||||||
|
}, (message, callback) => {
|
||||||
|
ipcMain.on(message, (event, arg) => {
|
||||||
|
if(Array.isArray(arg) && typeof arg[arg.length - 1] === 'object' && arg[arg.length - 1].callback)
|
||||||
|
{
|
||||||
|
const id = arg[arg.length - 1].callback
|
||||||
|
arg[arg.length - 1] = (responce) => {
|
||||||
|
mainWindow.webContents.send('callback', id, responce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback.apply(null, arg)
|
||||||
|
})
|
||||||
|
}, app.getPath("userData"), app.getVersion(), env.name)
|
||||||
|
}, mainWindow, sphinx)
|
||||||
|
}, app.getPath("userData"), () => app.quit())
|
||||||
});
|
});
|
||||||
|
|
||||||
let stopProtect = false
|
let stopProtect = false
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
if(stopProtect)
|
if(stopProtect)
|
||||||
return
|
return
|
||||||
stopProtect = true
|
stopProtect = true
|
||||||
|
|
||||||
if(tray)
|
if(tray)
|
||||||
tray.destroy()
|
tray.destroy()
|
||||||
|
|
||||||
if(spider)
|
if(spider)
|
||||||
{
|
{
|
||||||
spider.stop(() => sphinx.stop())
|
spider.stop(() => sphinx.stop())
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sphinx.stop()
|
sphinx.stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.on("window-all-closed", () => {
|
app.on("window-all-closed", () => {
|
||||||
if (sphinx)
|
if (sphinx)
|
||||||
stop()
|
stop()
|
||||||
else
|
else
|
||||||
app.quit()
|
app.quit()
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('before-quit', () => {
|
app.on('before-quit', () => {
|
||||||
app.isQuiting = true
|
app.isQuiting = true
|
||||||
if (sphinx)
|
if (sphinx)
|
||||||
stop()
|
stop()
|
||||||
})
|
})
|
@ -11,88 +11,88 @@ const config = require('../config')
|
|||||||
|
|
||||||
class Client extends Emiter
|
class Client extends Emiter
|
||||||
{
|
{
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
this.timeout = config.downloader.timeout;
|
this.timeout = config.downloader.timeout;
|
||||||
this.maxConnections = config.downloader.maxConnections;
|
this.maxConnections = config.downloader.maxConnections;
|
||||||
debug('timeout', this.timeout)
|
debug('timeout', this.timeout)
|
||||||
debug('maxConnections', this.maxConnections)
|
debug('maxConnections', this.maxConnections)
|
||||||
this.activeConnections = 0;
|
this.activeConnections = 0;
|
||||||
this.peers = new PeerQueue(this.maxConnections);
|
this.peers = new PeerQueue(this.maxConnections);
|
||||||
this.on('download', this._download);
|
this.on('download', this._download);
|
||||||
|
|
||||||
// if (typeof options.ignore === 'function') {
|
// if (typeof options.ignore === 'function') {
|
||||||
// this.ignore = options.ignore;
|
// this.ignore = options.ignore;
|
||||||
//}
|
//}
|
||||||
//else {
|
//else {
|
||||||
this.ignore = function (infohash, rinfo, ignore) {
|
this.ignore = function (infohash, rinfo, ignore) {
|
||||||
ignore(false);
|
ignore(false);
|
||||||
};
|
};
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
_next(infohash, successful) {
|
_next(infohash, successful) {
|
||||||
var req = this.peers.shift(infohash, successful);
|
var req = this.peers.shift(infohash, successful);
|
||||||
if (req) {
|
if (req) {
|
||||||
this.ignore(req.infohash.toString('hex'), req.rinfo, (drop) => {
|
this.ignore(req.infohash.toString('hex'), req.rinfo, (drop) => {
|
||||||
if (!drop) {
|
if (!drop) {
|
||||||
this.emit('download', req.rinfo, req.infohash);
|
this.emit('download', req.rinfo, req.infohash);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_download(rinfo, infohash)
|
_download(rinfo, infohash)
|
||||||
{
|
{
|
||||||
debug('start download', infohash.toString('hex'), 'connections', this.activeConnections);
|
debug('start download', infohash.toString('hex'), 'connections', this.activeConnections);
|
||||||
this.activeConnections++;
|
this.activeConnections++;
|
||||||
|
|
||||||
var successful = false;
|
var successful = false;
|
||||||
var socket = new net.Socket();
|
var socket = new net.Socket();
|
||||||
|
|
||||||
socket.setTimeout(this.timeout || 5000);
|
socket.setTimeout(this.timeout || 5000);
|
||||||
socket.connect(rinfo.port, rinfo.address, () => {
|
socket.connect(rinfo.port, rinfo.address, () => {
|
||||||
var wire = new Wire(infohash);
|
var wire = new Wire(infohash);
|
||||||
socket.pipe(wire).pipe(socket);
|
socket.pipe(wire).pipe(socket);
|
||||||
|
|
||||||
wire.on('metadata', (metadata, infoHash) => {
|
wire.on('metadata', (metadata, infoHash) => {
|
||||||
successful = true;
|
successful = true;
|
||||||
debug('successfuly downloader', infoHash, rinfo);
|
debug('successfuly downloader', infoHash, rinfo);
|
||||||
this.emit('complete', metadata, infoHash, rinfo);
|
this.emit('complete', metadata, infoHash, rinfo);
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
wire.on('fail', () => {
|
wire.on('fail', () => {
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
wire.sendHandshake();
|
wire.sendHandshake();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('error', (err) => {
|
socket.on('error', (err) => {
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('timeout', (err) => {
|
socket.on('timeout', (err) => {
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.once('close', () => {
|
socket.once('close', () => {
|
||||||
this.activeConnections--;
|
this.activeConnections--;
|
||||||
this._next(infohash, successful);
|
this._next(infohash, successful);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
add(rinfo, infohash) {
|
add(rinfo, infohash) {
|
||||||
this.peers.push({infohash: infohash, rinfo: rinfo});
|
this.peers.push({infohash: infohash, rinfo: rinfo});
|
||||||
if (this.activeConnections < this.maxConnections && this.peers.length() > 0) {
|
if (this.activeConnections < this.maxConnections && this.peers.length() > 0) {
|
||||||
this._next();
|
this._next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isIdle() {
|
isIdle() {
|
||||||
return this.peers.length() === 0;
|
return this.peers.length() === 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Client;
|
module.exports = Client;
|
@ -8,28 +8,28 @@ let sw = false
|
|||||||
const cpuTimer = setInterval(() => {
|
const cpuTimer = setInterval(() => {
|
||||||
if(!sw) {
|
if(!sw) {
|
||||||
keepTime = process.hrtime();
|
keepTime = process.hrtime();
|
||||||
keepUsage = process.cpuUsage();
|
keepUsage = process.cpuUsage();
|
||||||
sw = true;
|
sw = true;
|
||||||
} else {
|
} else {
|
||||||
startTime = keepTime;
|
startTime = keepTime;
|
||||||
startUsage = keepUsage;
|
startUsage = keepUsage;
|
||||||
sw = false;
|
sw = false;
|
||||||
}
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|
||||||
cpuTimer.unref()
|
cpuTimer.unref()
|
||||||
|
|
||||||
module.exports = () => {
|
module.exports = () => {
|
||||||
function secNSec2ms (secNSec) {
|
function secNSec2ms (secNSec) {
|
||||||
return secNSec[0] * 1000 + secNSec[1] / 1000000
|
return secNSec[0] * 1000 + secNSec[1] / 1000000
|
||||||
}
|
}
|
||||||
|
|
||||||
var elapTime = process.hrtime(startTime)
|
var elapTime = process.hrtime(startTime)
|
||||||
var elapUsage = process.cpuUsage(startUsage)
|
var elapUsage = process.cpuUsage(startUsage)
|
||||||
|
|
||||||
var elapTimeMS = secNSec2ms(elapTime)
|
var elapTimeMS = secNSec2ms(elapTime)
|
||||||
var elapUserMS = elapUsage.user
|
var elapUserMS = elapUsage.user
|
||||||
var elapSystMS = elapUsage.system
|
var elapSystMS = elapUsage.system
|
||||||
|
|
||||||
return Math.round(100 * ((elapUserMS + elapSystMS) / 1000) / elapTimeMS)
|
return Math.round(100 * ((elapUserMS + elapSystMS) / 1000) / elapTimeMS)
|
||||||
}
|
}
|
@ -1,55 +1,55 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var PeerQueue = function (maxSize, perLimit) {
|
var PeerQueue = function (maxSize, perLimit) {
|
||||||
this.maxSize = maxSize || 200;
|
this.maxSize = maxSize || 200;
|
||||||
this.perLimit = perLimit || 10;
|
this.perLimit = perLimit || 10;
|
||||||
this.peers = {};
|
this.peers = {};
|
||||||
this.reqs = [];
|
this.reqs = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
PeerQueue.prototype._shift = function () {
|
PeerQueue.prototype._shift = function () {
|
||||||
if (this.length() > 0) {
|
if (this.length() > 0) {
|
||||||
var req = this.reqs.shift();
|
var req = this.reqs.shift();
|
||||||
this.peers[req.infohash.toString('hex')] = [];
|
this.peers[req.infohash.toString('hex')] = [];
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PeerQueue.prototype.push = function (peer) {
|
PeerQueue.prototype.push = function (peer) {
|
||||||
var infohashHex = peer.infohash.toString('hex');
|
var infohashHex = peer.infohash.toString('hex');
|
||||||
var peers = this.peers[infohashHex];
|
var peers = this.peers[infohashHex];
|
||||||
|
|
||||||
if (peers && peers.length < this.perLimit) {
|
if (peers && peers.length < this.perLimit) {
|
||||||
peers.push(peer);
|
peers.push(peer);
|
||||||
}
|
}
|
||||||
else if (this.length() < this.maxSize) {
|
else if (this.length() < this.maxSize) {
|
||||||
this.reqs.push(peer);
|
this.reqs.push(peer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PeerQueue.prototype.shift = function (infohash, successful) {
|
PeerQueue.prototype.shift = function (infohash, successful) {
|
||||||
if (infohash) {
|
if (infohash) {
|
||||||
var infohashHex = infohash.toString('hex');
|
var infohashHex = infohash.toString('hex');
|
||||||
if (successful === true) {
|
if (successful === true) {
|
||||||
delete this.peers[infohashHex];
|
delete this.peers[infohashHex];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var peers = this.peers[infohashHex];
|
var peers = this.peers[infohashHex];
|
||||||
if (peers) {
|
if (peers) {
|
||||||
if (peers.length > 0) {
|
if (peers.length > 0) {
|
||||||
return peers.shift();
|
return peers.shift();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete this.peers[infohashHex];
|
delete this.peers[infohashHex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this._shift();
|
return this._shift();
|
||||||
};
|
};
|
||||||
|
|
||||||
PeerQueue.prototype.length = function () {
|
PeerQueue.prototype.length = function () {
|
||||||
return this.reqs.length;
|
return this.reqs.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = PeerQueue;
|
module.exports = PeerQueue;
|
@ -9,312 +9,312 @@ const config = require('../config')
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
const bootstraps = [{
|
const bootstraps = [{
|
||||||
address: 'router.bittorrent.com',
|
address: 'router.bittorrent.com',
|
||||||
port: 6881
|
port: 6881
|
||||||
}, {
|
}, {
|
||||||
address: 'router.utorrent.com',
|
address: 'router.utorrent.com',
|
||||||
port: 6881
|
port: 6881
|
||||||
}, {
|
}, {
|
||||||
address: 'dht.transmissionbt.com',
|
address: 'dht.transmissionbt.com',
|
||||||
port: 6881
|
port: 6881
|
||||||
}, {
|
}, {
|
||||||
address: 'dht.aelitis.com',
|
address: 'dht.aelitis.com',
|
||||||
port: 6881
|
port: 6881
|
||||||
}]
|
}]
|
||||||
|
|
||||||
function isValidPort(port) {
|
function isValidPort(port) {
|
||||||
return port > 0 && port < (1 << 16)
|
return port > 0 && port < (1 << 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateTid() {
|
function generateTid() {
|
||||||
return parseInt(Math.random() * 99).toString()
|
return parseInt(Math.random() * 99).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Spider extends Emiter {
|
class Spider extends Emiter {
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
super()
|
super()
|
||||||
const options = arguments.length? arguments[0]: {}
|
const options = arguments.length? arguments[0]: {}
|
||||||
this.table = new Table(options.tableCaption || 1000)
|
this.table = new Table(options.tableCaption || 1000)
|
||||||
this.bootstraps = options.bootstraps || bootstraps
|
this.bootstraps = options.bootstraps || bootstraps
|
||||||
this.token = new Token()
|
this.token = new Token()
|
||||||
this.client = client
|
this.client = client
|
||||||
this.ignore = false; // ignore all requests
|
this.ignore = false; // ignore all requests
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
|
|
||||||
this.walkInterval = config.spider.walkInterval;
|
this.walkInterval = config.spider.walkInterval;
|
||||||
this.foundSpeed = 0;
|
this.foundSpeed = 0;
|
||||||
this.foundCounter = 0;
|
this.foundCounter = 0;
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
this.foundSpeed = this.foundCounter;
|
this.foundSpeed = this.foundCounter;
|
||||||
this.foundCounter = 0;
|
this.foundCounter = 0;
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
this.announceHashes = []
|
this.announceHashes = []
|
||||||
}
|
}
|
||||||
|
|
||||||
send(message, address) {
|
send(message, address) {
|
||||||
const data = bencode.encode(message)
|
const data = bencode.encode(message)
|
||||||
this.udp.send(data, 0, data.length, address.port, address.address)
|
this.udp.send(data, 0, data.length, address.port, address.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
findNode(id, address) {
|
findNode(id, address) {
|
||||||
const message = {
|
const message = {
|
||||||
t: generateTid(),
|
t: generateTid(),
|
||||||
y: 'q',
|
y: 'q',
|
||||||
q: 'find_node',
|
q: 'find_node',
|
||||||
a: {
|
a: {
|
||||||
id: id,
|
id: id,
|
||||||
target: Node.generateID()
|
target: Node.generateID()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.send(message, address)
|
this.send(message, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
getPeersRequest(infoHash, address) {
|
getPeersRequest(infoHash, address) {
|
||||||
const message = {
|
const message = {
|
||||||
t: generateTid(),
|
t: generateTid(),
|
||||||
y: 'q',
|
y: 'q',
|
||||||
q: 'get_peers',
|
q: 'get_peers',
|
||||||
a: {
|
a: {
|
||||||
id: this.table.id,
|
id: this.table.id,
|
||||||
info_hash: infoHash
|
info_hash: infoHash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.send(message, address)
|
this.send(message, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
announcePeer(infoHash, token, address, port)
|
announcePeer(infoHash, token, address, port)
|
||||||
{
|
{
|
||||||
const message = {
|
const message = {
|
||||||
t: generateTid(),
|
t: generateTid(),
|
||||||
y: 'q',
|
y: 'q',
|
||||||
q: 'announce_peer',
|
q: 'announce_peer',
|
||||||
a: {
|
a: {
|
||||||
id: this.table.id,
|
id: this.table.id,
|
||||||
token: token,
|
token: token,
|
||||||
info_hash: infoHash,
|
info_hash: infoHash,
|
||||||
port: port,
|
port: port,
|
||||||
implied_port: port ? 0 : 1
|
implied_port: port ? 0 : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.send(message, address)
|
this.send(message, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
join() {
|
join() {
|
||||||
this.bootstraps.forEach((bootstrap) => {
|
this.bootstraps.forEach((bootstrap) => {
|
||||||
this.findNode(this.table.id, bootstrap)
|
this.findNode(this.table.id, bootstrap)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
walk() {
|
walk() {
|
||||||
if(this.closing)
|
if(this.closing)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!this.client || this.client.isIdle()) {
|
if(!this.client || this.client.isIdle()) {
|
||||||
if(!this.ignore)
|
if(!this.ignore)
|
||||||
{
|
{
|
||||||
const node = this.table.shift()
|
const node = this.table.shift()
|
||||||
if (node && (config.spider.nodesUsage === 0 || parseInt(Math.random() * this.table.nodes.length / config.spider.nodesUsage) === 0)) {
|
if (node && (config.spider.nodesUsage === 0 || parseInt(Math.random() * this.table.nodes.length / config.spider.nodesUsage) === 0)) {
|
||||||
this.findNode(Node.neighbor(node.id, this.table.id), {address: node.address, port: node.port})
|
this.findNode(Node.neighbor(node.id, this.table.id), {address: node.address, port: node.port})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTimeout(()=>this.walk(), this.walkInterval)
|
setTimeout(()=>this.walk(), this.walkInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
onFoundNodes(data, token, address) {
|
onFoundNodes(data, token, address) {
|
||||||
const nodes = Node.decodeNodes(data)
|
const nodes = Node.decodeNodes(data)
|
||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
if (node.id != this.table.id && isValidPort(node.port)) {
|
if (node.id != this.table.id && isValidPort(node.port)) {
|
||||||
this.table.add(node)
|
this.table.add(node)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.emit('nodes', nodes)
|
this.emit('nodes', nodes)
|
||||||
|
|
||||||
// announce torrents
|
// announce torrents
|
||||||
if(token)
|
if(token)
|
||||||
{
|
{
|
||||||
for(const hash of this.announceHashes)
|
for(const hash of this.announceHashes)
|
||||||
{
|
{
|
||||||
this.announcePeer(hash, token, address)
|
this.announcePeer(hash, token, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onFoundPeers(peers, token, address) {
|
onFoundPeers(peers, token, address) {
|
||||||
if(token)
|
if(token)
|
||||||
{
|
{
|
||||||
for(const hash of this.announceHashes)
|
for(const hash of this.announceHashes)
|
||||||
{
|
{
|
||||||
this.announcePeer(hash, token, address)
|
this.announcePeer(hash, token, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!peers || peers.length == 0)
|
if(!peers || peers.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ips = Node.decodeCompactIP(peers)
|
const ips = Node.decodeCompactIP(peers)
|
||||||
this.emit('peer', ips)
|
this.emit('peer', ips)
|
||||||
}
|
}
|
||||||
|
|
||||||
onFindNodeRequest(message, address) {
|
onFindNodeRequest(message, address) {
|
||||||
if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
|
if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const {t: tid, a: {id: nid, target: infohash}} = message
|
const {t: tid, a: {id: nid, target: infohash}} = message
|
||||||
|
|
||||||
if (tid === undefined || target.length != 20 || nid.length != 20) {
|
if (tid === undefined || target.length != 20 || nid.length != 20) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send({
|
this.send({
|
||||||
t: tid,
|
t: tid,
|
||||||
y: 'r',
|
y: 'r',
|
||||||
r: {
|
r: {
|
||||||
id: Node.neighbor(nid, this.table.id),
|
id: Node.neighbor(nid, this.table.id),
|
||||||
nodes: Node.encodeNodes(this.table.first())
|
nodes: Node.encodeNodes(this.table.first())
|
||||||
}
|
}
|
||||||
}, address)
|
}, address)
|
||||||
|
|
||||||
// also check hashes of alive ones
|
// also check hashes of alive ones
|
||||||
for(const hash of this.announceHashes)
|
for(const hash of this.announceHashes)
|
||||||
{
|
{
|
||||||
this.getPeersRequest(hash, address)
|
this.getPeersRequest(hash, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onGetPeersRequest(message, address) {
|
onGetPeersRequest(message, address) {
|
||||||
if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
|
if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const {t: tid, a: {id: nid, info_hash: infohash}} = message
|
const {t: tid, a: {id: nid, info_hash: infohash}} = message
|
||||||
|
|
||||||
if (tid === undefined || infohash.length != 20 || nid.length != 20) {
|
if (tid === undefined || infohash.length != 20 || nid.length != 20) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send({
|
this.send({
|
||||||
t: tid,
|
t: tid,
|
||||||
y: 'r',
|
y: 'r',
|
||||||
r: {
|
r: {
|
||||||
id: Node.neighbor(nid, this.table.id),
|
id: Node.neighbor(nid, this.table.id),
|
||||||
nodes: Node.encodeNodes(this.table.first()),
|
nodes: Node.encodeNodes(this.table.first()),
|
||||||
token: this.token.token
|
token: this.token.token
|
||||||
}
|
}
|
||||||
}, address)
|
}, address)
|
||||||
|
|
||||||
this.emit('unensureHash', infohash.toString('hex').toUpperCase())
|
this.emit('unensureHash', infohash.toString('hex').toUpperCase())
|
||||||
|
|
||||||
// also check hashes of alive ones
|
// also check hashes of alive ones
|
||||||
for(const hash of this.announceHashes)
|
for(const hash of this.announceHashes)
|
||||||
{
|
{
|
||||||
this.getPeersRequest(hash, address)
|
this.getPeersRequest(hash, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onAnnouncePeerRequest(message, address) {
|
onAnnouncePeerRequest(message, address) {
|
||||||
let {t: tid, a: {info_hash: infohash, token: token, id: id, implied_port: implied, port: port}} = message
|
let {t: tid, a: {info_hash: infohash, token: token, id: id, implied_port: implied, port: port}} = message
|
||||||
if (!tid) return
|
if (!tid) return
|
||||||
|
|
||||||
if (!this.token.isValid(token)) return
|
if (!this.token.isValid(token)) return
|
||||||
|
|
||||||
port = (implied != undefined && implied != 0) ? address.port : (port || 0)
|
port = (implied != undefined && implied != 0) ? address.port : (port || 0)
|
||||||
if (!isValidPort(port)) return
|
if (!isValidPort(port)) return
|
||||||
|
|
||||||
this.send({ t: tid, y: 'r', r: { id: Node.neighbor(id, this.table.id) } }, address)
|
this.send({ t: tid, y: 'r', r: { id: Node.neighbor(id, this.table.id) } }, address)
|
||||||
|
|
||||||
let addressPair = {
|
let addressPair = {
|
||||||
address: address.address,
|
address: address.address,
|
||||||
port: port
|
port: port
|
||||||
};
|
};
|
||||||
this.emit('ensureHash', infohash.toString('hex').toUpperCase(), addressPair)
|
this.emit('ensureHash', infohash.toString('hex').toUpperCase(), addressPair)
|
||||||
if(this.client && !this.ignore) {
|
if(this.client && !this.ignore) {
|
||||||
this.client.add(addressPair, infohash);
|
this.client.add(addressPair, infohash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPingRequest(message, address) {
|
onPingRequest(message, address) {
|
||||||
if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
|
if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send({ t: message.t, y: 'r', r: { id: Node.neighbor(message.a.id, this.table.id) } }, address)
|
this.send({ t: message.t, y: 'r', r: { id: Node.neighbor(message.a.id, this.table.id) } }, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
parse(data, address) {
|
parse(data, address) {
|
||||||
try {
|
try {
|
||||||
const message = bencode.decode(data)
|
const message = bencode.decode(data)
|
||||||
if (message.y.toString() == 'r') {
|
if (message.y.toString() == 'r') {
|
||||||
if(message.r.nodes) {
|
if(message.r.nodes) {
|
||||||
this.foundCounter++;
|
this.foundCounter++;
|
||||||
this.onFoundNodes(message.r.nodes, message.r.token, address)
|
this.onFoundNodes(message.r.nodes, message.r.token, address)
|
||||||
} else if(message.r.values) {
|
} else if(message.r.values) {
|
||||||
this.onFoundPeers(message.r.values, message.r.token, address)
|
this.onFoundPeers(message.r.values, message.r.token, address)
|
||||||
}
|
}
|
||||||
} else if (message.y.toString() == 'q') {
|
} else if (message.y.toString() == 'q') {
|
||||||
this.foundCounter++;
|
this.foundCounter++;
|
||||||
switch(message.q.toString()) {
|
switch(message.q.toString()) {
|
||||||
case 'get_peers':
|
case 'get_peers':
|
||||||
this.onGetPeersRequest(message, address)
|
this.onGetPeersRequest(message, address)
|
||||||
break
|
break
|
||||||
case 'announce_peer':
|
case 'announce_peer':
|
||||||
this.onAnnouncePeerRequest(message, address)
|
this.onAnnouncePeerRequest(message, address)
|
||||||
break
|
break
|
||||||
case 'find_node':
|
case 'find_node':
|
||||||
this.onFindNodeRequest(message, address)
|
this.onFindNodeRequest(message, address)
|
||||||
break
|
break
|
||||||
case 'ping':
|
case 'ping':
|
||||||
this.onPingRequest(message, address)
|
this.onPingRequest(message, address)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(port) {
|
listen(port) {
|
||||||
if(this.initialized)
|
if(this.initialized)
|
||||||
return
|
return
|
||||||
this.initialized = true
|
this.initialized = true
|
||||||
|
|
||||||
this.closing = false
|
this.closing = false
|
||||||
this.udp = dgram.createSocket('udp4')
|
this.udp = dgram.createSocket('udp4')
|
||||||
this.udp.bind(port)
|
this.udp.bind(port)
|
||||||
this.udp.on('listening', () => {
|
this.udp.on('listening', () => {
|
||||||
console.log(`Listen DHT protocol on ${this.udp.address().address}:${this.udp.address().port}`)
|
console.log(`Listen DHT protocol on ${this.udp.address().address}:${this.udp.address().port}`)
|
||||||
})
|
})
|
||||||
this.udp.on('message', (data, addr) => {
|
this.udp.on('message', (data, addr) => {
|
||||||
this.parse(data, addr)
|
this.parse(data, addr)
|
||||||
})
|
})
|
||||||
this.udp.on('error', (err) => {})
|
this.udp.on('error', (err) => {})
|
||||||
this.joinInterval = setInterval(() => {
|
this.joinInterval = setInterval(() => {
|
||||||
if(!this.client || this.client.isIdle()) {
|
if(!this.client || this.client.isIdle()) {
|
||||||
this.join()
|
this.join()
|
||||||
}
|
}
|
||||||
}, 3000)
|
}, 3000)
|
||||||
this.join()
|
this.join()
|
||||||
this.walk()
|
this.walk()
|
||||||
}
|
}
|
||||||
|
|
||||||
close(callback)
|
close(callback)
|
||||||
{
|
{
|
||||||
if(!this.initialized) {
|
if(!this.initialized) {
|
||||||
if(callback)
|
if(callback)
|
||||||
callback()
|
callback()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
clearInterval(this.joinInterval)
|
clearInterval(this.joinInterval)
|
||||||
this.closing = true
|
this.closing = true
|
||||||
this.udp.close(() => {
|
this.udp.close(() => {
|
||||||
this.initialized = false
|
this.initialized = false
|
||||||
if(callback)
|
if(callback)
|
||||||
callback()
|
callback()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Spider
|
module.exports = Spider
|
@ -13,119 +13,119 @@ const connectionIdLow = 0x27101980
|
|||||||
const requests = {};
|
const requests = {};
|
||||||
|
|
||||||
let message = function (buf, host, port) {
|
let message = function (buf, host, port) {
|
||||||
server.send(buf, 0, buf.length, port, host, function(err, bytes) {
|
server.send(buf, 0, buf.length, port, host, function(err, bytes) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err.message);
|
console.log(err.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let connectTracker = function(connection) {
|
let connectTracker = function(connection) {
|
||||||
debug('start screape connection');
|
debug('start screape connection');
|
||||||
let buffer = new Buffer(16);
|
let buffer = new Buffer(16);
|
||||||
|
|
||||||
const transactionId = Math.floor((Math.random()*100000)+1);
|
const transactionId = Math.floor((Math.random()*100000)+1);
|
||||||
|
|
||||||
buffer.fill(0);
|
buffer.fill(0);
|
||||||
|
|
||||||
buffer.writeUInt32BE(connectionIdHigh, 0);
|
buffer.writeUInt32BE(connectionIdHigh, 0);
|
||||||
buffer.writeUInt32BE(connectionIdLow, 4);
|
buffer.writeUInt32BE(connectionIdLow, 4);
|
||||||
buffer.writeUInt32BE(ACTION_CONNECT, 8);
|
buffer.writeUInt32BE(ACTION_CONNECT, 8);
|
||||||
buffer.writeUInt32BE(transactionId, 12);
|
buffer.writeUInt32BE(transactionId, 12);
|
||||||
|
|
||||||
// очистка старых соединений
|
// очистка старых соединений
|
||||||
for(const transaction in requests) {
|
for(const transaction in requests) {
|
||||||
if((new Date).getTime() - requests[transaction].date.getTime() > config.udpTrackersTimeout) {
|
if((new Date).getTime() - requests[transaction].date.getTime() > config.udpTrackersTimeout) {
|
||||||
delete requests[transaction];
|
delete requests[transaction];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
requests[transactionId] = connection;
|
requests[transactionId] = connection;
|
||||||
message(buffer, connection.host, connection.port);
|
message(buffer, connection.host, connection.port);
|
||||||
};
|
};
|
||||||
|
|
||||||
let scrapeTorrent = function (connectionIdHigh, connectionIdLow, transactionId) {
|
let scrapeTorrent = function (connectionIdHigh, connectionIdLow, transactionId) {
|
||||||
let connection = requests[transactionId];
|
let connection = requests[transactionId];
|
||||||
if(!connection)
|
if(!connection)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!connection.hash || connection.hash.length != 40)
|
if(!connection.hash || connection.hash.length != 40)
|
||||||
return
|
return
|
||||||
|
|
||||||
debug('start scrape');
|
debug('start scrape');
|
||||||
let buffer = new Buffer(56)
|
let buffer = new Buffer(56)
|
||||||
|
|
||||||
buffer.fill(0);
|
buffer.fill(0);
|
||||||
|
|
||||||
buffer.writeUInt32BE(connectionIdHigh, 0);
|
buffer.writeUInt32BE(connectionIdHigh, 0);
|
||||||
buffer.writeUInt32BE(connectionIdLow, 4);
|
buffer.writeUInt32BE(connectionIdLow, 4);
|
||||||
buffer.writeUInt32BE(ACTION_SCRAPE, 8);
|
buffer.writeUInt32BE(ACTION_SCRAPE, 8);
|
||||||
buffer.writeUInt32BE(transactionId, 12);
|
buffer.writeUInt32BE(transactionId, 12);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
buffer.write(connection.hash, 16, buffer.length, 'hex');
|
buffer.write(connection.hash, 16, buffer.length, 'hex');
|
||||||
// do scrape
|
// do scrape
|
||||||
message(buffer, connection.host, connection.port);
|
message(buffer, connection.host, connection.port);
|
||||||
} catch(error)
|
} catch(error)
|
||||||
{
|
{
|
||||||
console.log('ERROR on scrape', error)
|
console.log('ERROR on scrape', error)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
server.on("message", function (msg, rinfo) {
|
server.on("message", function (msg, rinfo) {
|
||||||
let buffer = new Buffer(msg)
|
let buffer = new Buffer(msg)
|
||||||
|
|
||||||
const action = buffer.readUInt32BE(0, 4);
|
const action = buffer.readUInt32BE(0, 4);
|
||||||
const transactionId = buffer.readUInt32BE(4, 4);
|
const transactionId = buffer.readUInt32BE(4, 4);
|
||||||
|
|
||||||
if(!(transactionId in requests))
|
if(!(transactionId in requests))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
debug("returned action: " + action);
|
debug("returned action: " + action);
|
||||||
debug("returned transactionId: " + transactionId);
|
debug("returned transactionId: " + transactionId);
|
||||||
|
|
||||||
if (action === ACTION_CONNECT) {
|
if (action === ACTION_CONNECT) {
|
||||||
debug("connect response");
|
debug("connect response");
|
||||||
|
|
||||||
let connectionIdHigh = buffer.readUInt32BE(8, 4);
|
let connectionIdHigh = buffer.readUInt32BE(8, 4);
|
||||||
let connectionIdLow = buffer.readUInt32BE(12, 4);
|
let connectionIdLow = buffer.readUInt32BE(12, 4);
|
||||||
|
|
||||||
scrapeTorrent(connectionIdHigh, connectionIdLow, transactionId);
|
scrapeTorrent(connectionIdHigh, connectionIdLow, transactionId);
|
||||||
|
|
||||||
} else if (action === ACTION_SCRAPE) {
|
} else if (action === ACTION_SCRAPE) {
|
||||||
debug("scrape response");
|
debug("scrape response");
|
||||||
|
|
||||||
let seeders = buffer.readUInt32BE(8, 4);
|
let seeders = buffer.readUInt32BE(8, 4);
|
||||||
let completed = buffer.readUInt32BE(12, 4);
|
let completed = buffer.readUInt32BE(12, 4);
|
||||||
let leechers = buffer.readUInt32BE(16, 4);
|
let leechers = buffer.readUInt32BE(16, 4);
|
||||||
|
|
||||||
let connection = requests[transactionId];
|
let connection = requests[transactionId];
|
||||||
connection.callback({
|
connection.callback({
|
||||||
host: connection.host,
|
host: connection.host,
|
||||||
port: connection.port,
|
port: connection.port,
|
||||||
hash: connection.hash,
|
hash: connection.hash,
|
||||||
seeders,
|
seeders,
|
||||||
completed,
|
completed,
|
||||||
leechers
|
leechers
|
||||||
})
|
})
|
||||||
delete requests[transactionId];
|
delete requests[transactionId];
|
||||||
} else if (action === ACTION_ERROR) {
|
} else if (action === ACTION_ERROR) {
|
||||||
delete requests[transactionId];
|
delete requests[transactionId];
|
||||||
console.log("error in scrape response");
|
console.log("error in scrape response");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let getPeersStatistic = (host, port, hash, callback) => {
|
let getPeersStatistic = (host, port, hash, callback) => {
|
||||||
let connection = {
|
let connection = {
|
||||||
host, port, hash, callback, date: new Date()
|
host, port, hash, callback, date: new Date()
|
||||||
}
|
}
|
||||||
connectTracker(connection);
|
connectTracker(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
server.on("listening", function () {
|
server.on("listening", function () {
|
||||||
var address = server.address();
|
var address = server.address();
|
||||||
console.log("listening udp tracker respose on " + address.address + ":" + address.port);
|
console.log("listening udp tracker respose on " + address.address + ":" + address.port);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.bind(config.udpTrackersPort);
|
server.bind(config.udpTrackersPort);
|
||||||
|
@ -18,230 +18,230 @@ var EXT_HANDSHAKE_ID = 0;
|
|||||||
var BT_MSG_ID = 20;
|
var BT_MSG_ID = 20;
|
||||||
|
|
||||||
var Wire = function(infohash) {
|
var Wire = function(infohash) {
|
||||||
stream.Duplex.call(this);
|
stream.Duplex.call(this);
|
||||||
|
|
||||||
this._bitfield = new BitField(0, { grow: BITFIELD_GROW });
|
this._bitfield = new BitField(0, { grow: BITFIELD_GROW });
|
||||||
this._infohash = infohash;
|
this._infohash = infohash;
|
||||||
|
|
||||||
this._buffer = [];
|
this._buffer = [];
|
||||||
this._bufferSize = 0;
|
this._bufferSize = 0;
|
||||||
|
|
||||||
this._next = null;
|
this._next = null;
|
||||||
this._nextSize = 0;
|
this._nextSize = 0;
|
||||||
|
|
||||||
this._metadata = null;
|
this._metadata = null;
|
||||||
this._metadataSize = null;
|
this._metadataSize = null;
|
||||||
this._numPieces = 0;
|
this._numPieces = 0;
|
||||||
this._ut_metadata = null;
|
this._ut_metadata = null;
|
||||||
|
|
||||||
this._onHandshake();
|
this._onHandshake();
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(Wire, stream.Duplex);
|
util.inherits(Wire, stream.Duplex);
|
||||||
|
|
||||||
Wire.prototype._onMessageLength = function (buffer) {
|
Wire.prototype._onMessageLength = function (buffer) {
|
||||||
if (buffer.length >= 4) {
|
if (buffer.length >= 4) {
|
||||||
var length = buffer.readUInt32BE(0);
|
var length = buffer.readUInt32BE(0);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
this._register(length, this._onMessage)
|
this._register(length, this._onMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._onMessage = function (buffer) {
|
Wire.prototype._onMessage = function (buffer) {
|
||||||
this._register(4, this._onMessageLength)
|
this._register(4, this._onMessageLength)
|
||||||
if (buffer[0] == BT_MSG_ID) {
|
if (buffer[0] == BT_MSG_ID) {
|
||||||
this._onExtended(buffer.readUInt8(1), buffer.slice(2));
|
this._onExtended(buffer.readUInt8(1), buffer.slice(2));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._onExtended = function(ext, buf) {
|
Wire.prototype._onExtended = function(ext, buf) {
|
||||||
if (ext === 0) {
|
if (ext === 0) {
|
||||||
try {
|
try {
|
||||||
this._onExtHandshake(bencode.decode(buf));
|
this._onExtHandshake(bencode.decode(buf));
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this._fail();
|
this._fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._onPiece(buf);
|
this._onPiece(buf);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._register = function (size, next) {
|
Wire.prototype._register = function (size, next) {
|
||||||
this._nextSize = size;
|
this._nextSize = size;
|
||||||
this._next = next;
|
this._next = next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype.end = function() {
|
Wire.prototype.end = function() {
|
||||||
stream.Duplex.prototype.end.apply(this, arguments);
|
stream.Duplex.prototype.end.apply(this, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._onHandshake = function() {
|
Wire.prototype._onHandshake = function() {
|
||||||
this._register(1, function(buffer) {
|
this._register(1, function(buffer) {
|
||||||
if (buffer.length == 0) {
|
if (buffer.length == 0) {
|
||||||
this.end();
|
this.end();
|
||||||
return this._fail();
|
return this._fail();
|
||||||
}
|
}
|
||||||
var pstrlen = buffer.readUInt8(0);
|
var pstrlen = buffer.readUInt8(0);
|
||||||
this._register(pstrlen + 48, function(handshake) {
|
this._register(pstrlen + 48, function(handshake) {
|
||||||
var protocol = handshake.slice(0, pstrlen);
|
var protocol = handshake.slice(0, pstrlen);
|
||||||
if (protocol.toString() !== BT_PROTOCOL.toString()) {
|
if (protocol.toString() !== BT_PROTOCOL.toString()) {
|
||||||
this.end();
|
this.end();
|
||||||
this._fail();
|
this._fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handshake = handshake.slice(pstrlen);
|
handshake = handshake.slice(pstrlen);
|
||||||
if ( !!(handshake[5] & 0x10) ) {
|
if ( !!(handshake[5] & 0x10) ) {
|
||||||
this._register(4, this._onMessageLength);
|
this._register(4, this._onMessageLength);
|
||||||
this._sendExtHandshake();
|
this._sendExtHandshake();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._fail();
|
this._fail();
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._onExtHandshake = function(extHandshake) {
|
Wire.prototype._onExtHandshake = function(extHandshake) {
|
||||||
if (!extHandshake.metadata_size || !extHandshake.m.ut_metadata
|
if (!extHandshake.metadata_size || !extHandshake.m.ut_metadata
|
||||||
|| extHandshake.metadata_size > MAX_METADATA_SIZE) {
|
|| extHandshake.metadata_size > MAX_METADATA_SIZE) {
|
||||||
this._fail();
|
this._fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._metadataSize = extHandshake.metadata_size;
|
this._metadataSize = extHandshake.metadata_size;
|
||||||
this._numPieces = Math.ceil(this._metadataSize / PIECE_LENGTH);
|
this._numPieces = Math.ceil(this._metadataSize / PIECE_LENGTH);
|
||||||
this._ut_metadata = extHandshake.m.ut_metadata;
|
this._ut_metadata = extHandshake.m.ut_metadata;
|
||||||
|
|
||||||
this._requestPieces();
|
this._requestPieces();
|
||||||
}
|
}
|
||||||
|
|
||||||
Wire.prototype._requestPieces = function() {
|
Wire.prototype._requestPieces = function() {
|
||||||
this._metadata = new Buffer(this._metadataSize);
|
this._metadata = new Buffer(this._metadataSize);
|
||||||
for (var piece = 0; piece < this._numPieces; piece++) {
|
for (var piece = 0; piece < this._numPieces; piece++) {
|
||||||
this._requestPiece(piece);
|
this._requestPiece(piece);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._requestPiece = function(piece) {
|
Wire.prototype._requestPiece = function(piece) {
|
||||||
var msg = Buffer.concat([
|
var msg = Buffer.concat([
|
||||||
new Buffer([BT_MSG_ID]),
|
new Buffer([BT_MSG_ID]),
|
||||||
new Buffer([this._ut_metadata]),
|
new Buffer([this._ut_metadata]),
|
||||||
bencode.encode({msg_type: 0, piece: piece})
|
bencode.encode({msg_type: 0, piece: piece})
|
||||||
]);
|
]);
|
||||||
this._sendMessage(msg);
|
this._sendMessage(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._sendPacket = function(packet) {
|
Wire.prototype._sendPacket = function(packet) {
|
||||||
this.push(packet);
|
this.push(packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._sendMessage = function(msg) {
|
Wire.prototype._sendMessage = function(msg) {
|
||||||
var buf = new Buffer(4);
|
var buf = new Buffer(4);
|
||||||
buf.writeUInt32BE(msg.length, 0);
|
buf.writeUInt32BE(msg.length, 0);
|
||||||
this._sendPacket(Buffer.concat([buf, msg]));
|
this._sendPacket(Buffer.concat([buf, msg]));
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype.sendHandshake = function() {
|
Wire.prototype.sendHandshake = function() {
|
||||||
var peerID = Node.generateID();
|
var peerID = Node.generateID();
|
||||||
var packet = Buffer.concat([
|
var packet = Buffer.concat([
|
||||||
new Buffer([BT_PROTOCOL.length]),
|
new Buffer([BT_PROTOCOL.length]),
|
||||||
BT_PROTOCOL, BT_RESERVED, this._infohash, peerID
|
BT_PROTOCOL, BT_RESERVED, this._infohash, peerID
|
||||||
]);
|
]);
|
||||||
this._sendPacket(packet);
|
this._sendPacket(packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._sendExtHandshake = function() {
|
Wire.prototype._sendExtHandshake = function() {
|
||||||
var msg = Buffer.concat([
|
var msg = Buffer.concat([
|
||||||
new Buffer([BT_MSG_ID]),
|
new Buffer([BT_MSG_ID]),
|
||||||
new Buffer([EXT_HANDSHAKE_ID]),
|
new Buffer([EXT_HANDSHAKE_ID]),
|
||||||
bencode.encode({m: {ut_metadata: 1}})
|
bencode.encode({m: {ut_metadata: 1}})
|
||||||
]);
|
]);
|
||||||
this._sendMessage(msg);
|
this._sendMessage(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._onPiece = function(piece) {
|
Wire.prototype._onPiece = function(piece) {
|
||||||
var dict, trailer;
|
var dict, trailer;
|
||||||
try {
|
try {
|
||||||
var str = piece.toString();
|
var str = piece.toString();
|
||||||
var trailerIndex = str.indexOf('ee') + 2;
|
var trailerIndex = str.indexOf('ee') + 2;
|
||||||
dict = bencode.decode(str.substring(0, trailerIndex));
|
dict = bencode.decode(str.substring(0, trailerIndex));
|
||||||
trailer = piece.slice(trailerIndex);
|
trailer = piece.slice(trailerIndex);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this._fail();
|
this._fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dict.msg_type != 1) {
|
if (dict.msg_type != 1) {
|
||||||
this._fail();
|
this._fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (trailer.length > PIECE_LENGTH) {
|
if (trailer.length > PIECE_LENGTH) {
|
||||||
this._fail();
|
this._fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trailer.copy(this._metadata, dict.piece * PIECE_LENGTH);
|
trailer.copy(this._metadata, dict.piece * PIECE_LENGTH);
|
||||||
this._bitfield.set(dict.piece);
|
this._bitfield.set(dict.piece);
|
||||||
this._checkDone();
|
this._checkDone();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._checkDone = function () {
|
Wire.prototype._checkDone = function () {
|
||||||
var done = true;
|
var done = true;
|
||||||
for (var piece = 0; piece < this._numPieces; piece++) {
|
for (var piece = 0; piece < this._numPieces; piece++) {
|
||||||
if (!this._bitfield.get(piece)) {
|
if (!this._bitfield.get(piece)) {
|
||||||
done = false;
|
done = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!done) {
|
if (!done) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this._onDone(this._metadata);
|
this._onDone(this._metadata);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._onDone = function(metadata) {
|
Wire.prototype._onDone = function(metadata) {
|
||||||
try {
|
try {
|
||||||
var info = bencode.decode(metadata).info;
|
var info = bencode.decode(metadata).info;
|
||||||
if (info) {
|
if (info) {
|
||||||
metadata = bencode.encode(info);
|
metadata = bencode.encode(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
this._fail();
|
this._fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var infohash = crypto.createHash('sha1').update(metadata).digest('hex');
|
var infohash = crypto.createHash('sha1').update(metadata).digest('hex');
|
||||||
if (this._infohash.toString('hex') != infohash ) {
|
if (this._infohash.toString('hex') != infohash ) {
|
||||||
this._fail();
|
this._fail();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.emit('metadata', {info: bencode.decode(metadata, 'utf8')}, this._infohash);
|
this.emit('metadata', {info: bencode.decode(metadata, 'utf8')}, this._infohash);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._fail = function() {
|
Wire.prototype._fail = function() {
|
||||||
this.emit('fail');
|
this.emit('fail');
|
||||||
};
|
};
|
||||||
|
|
||||||
Wire.prototype._write = function (buf, encoding, next) {
|
Wire.prototype._write = function (buf, encoding, next) {
|
||||||
this._bufferSize += buf.length;
|
this._bufferSize += buf.length;
|
||||||
this._buffer.push(buf);
|
this._buffer.push(buf);
|
||||||
|
|
||||||
while (this._bufferSize >= this._nextSize) {
|
while (this._bufferSize >= this._nextSize) {
|
||||||
var buffer = Buffer.concat(this._buffer);
|
var buffer = Buffer.concat(this._buffer);
|
||||||
this._bufferSize -= this._nextSize;
|
this._bufferSize -= this._nextSize;
|
||||||
this._buffer = this._bufferSize
|
this._buffer = this._bufferSize
|
||||||
? [buffer.slice(this._nextSize)]
|
? [buffer.slice(this._nextSize)]
|
||||||
: [];
|
: [];
|
||||||
this._next(buffer.slice(0, this._nextSize));
|
this._next(buffer.slice(0, this._nextSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
next(null);
|
next(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wire.prototype._read = function() {
|
Wire.prototype._read = function() {
|
||||||
// do nothing
|
// do nothing
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Wire;
|
module.exports = Wire;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// https://stackoverflow.com/questions/15270902/check-for-internet-connectivity-in-nodejs
|
// https://stackoverflow.com/questions/15270902/check-for-internet-connectivity-in-nodejs
|
||||||
module.exports = function checkInternet(cb) {
|
module.exports = function checkInternet(cb) {
|
||||||
require('dns').lookup('google.com',function(err) {
|
require('dns').lookup('google.com',function(err) {
|
||||||
if (err && err.code == "ENOTFOUND") {
|
if (err && err.code == "ENOTFOUND") {
|
||||||
cb(false);
|
cb(false);
|
||||||
} else {
|
} else {
|
||||||
cb(true);
|
cb(true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -25,9 +25,9 @@ let config = {
|
|||||||
sitemapMaxSize: 25000,
|
sitemapMaxSize: 25000,
|
||||||
|
|
||||||
sphinx: {
|
sphinx: {
|
||||||
host : '127.0.0.1',
|
host : '127.0.0.1',
|
||||||
port : 9306,
|
port : 9306,
|
||||||
connectionLimit: 30
|
connectionLimit: 30
|
||||||
},
|
},
|
||||||
|
|
||||||
spider: {
|
spider: {
|
||||||
@ -80,7 +80,7 @@ const configProxy = new Proxy(config, {
|
|||||||
|
|
||||||
target[prop] = value
|
target[prop] = value
|
||||||
|
|
||||||
if(!fs.existsSync(configPath))
|
if(!fs.existsSync(configPath))
|
||||||
fs.writeFileSync(configPath, '{}')
|
fs.writeFileSync(configPath, '{}')
|
||||||
|
|
||||||
const data = fs.readFileSync(configPath)
|
const data = fs.readFileSync(configPath)
|
||||||
|
@ -13,31 +13,31 @@ const currentVersion = 4
|
|||||||
|
|
||||||
|
|
||||||
module.exports = async (callback, mainWindow, sphinxApp) => {
|
module.exports = async (callback, mainWindow, sphinxApp) => {
|
||||||
const sphinx = await single().waitConnection()
|
const sphinx = await single().waitConnection()
|
||||||
|
|
||||||
const setVersion = async (version) => {
|
const setVersion = async (version) => {
|
||||||
await sphinx.query(`delete from version where id = 1`)
|
await sphinx.query(`delete from version where id = 1`)
|
||||||
await sphinx.query(`insert into version(id, version) values(1, ${version})`)
|
await sphinx.query(`insert into version(id, version) values(1, ${version})`)
|
||||||
if(sphinxApp)
|
if(sphinxApp)
|
||||||
fs.writeFileSync(`${sphinxApp.directoryPath}/version.vrs`, version)
|
fs.writeFileSync(`${sphinxApp.directoryPath}/version.vrs`, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
let patchWindow;
|
let patchWindow;
|
||||||
const openPatchWindow = () => {
|
const openPatchWindow = () => {
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!BrowserWindow)
|
if(!BrowserWindow)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(mainWindow)
|
if(mainWindow)
|
||||||
mainWindow.hide()
|
mainWindow.hide()
|
||||||
|
|
||||||
patchWindow = new BrowserWindow({width: 800, height: 400, closable: false})
|
patchWindow = new BrowserWindow({width: 800, height: 400, closable: false})
|
||||||
|
|
||||||
patchWindow.setMenu(null)
|
patchWindow.setMenu(null)
|
||||||
|
|
||||||
patchWindow.loadURL("data:text/html;charset=utf-8," + encodeURI(`
|
patchWindow.loadURL("data:text/html;charset=utf-8," + encodeURI(`
|
||||||
<html>
|
<html>
|
||||||
<head><title>Database patching...</title></head>
|
<head><title>Database patching...</title></head>
|
||||||
<style>
|
<style>
|
||||||
@ -97,146 +97,146 @@ module.exports = async (callback, mainWindow, sphinxApp) => {
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
|
|
||||||
const patch = async (version) => {
|
const patch = async (version) => {
|
||||||
console.log('db version', version)
|
console.log('db version', version)
|
||||||
switch(version)
|
switch(version)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
console.log('patch db to version 2')
|
console.log('patch db to version 2')
|
||||||
openPatchWindow()
|
openPatchWindow()
|
||||||
let i = 1
|
let i = 1
|
||||||
|
|
||||||
const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c
|
const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c
|
||||||
const files = (await sphinx.query("SELECT COUNT(*) AS c FROM files"))[0].c
|
const files = (await sphinx.query("SELECT COUNT(*) AS c FROM files"))[0].c
|
||||||
|
|
||||||
await forBigTable(sphinx, 'torrents', async (torrent) => {
|
await forBigTable(sphinx, 'torrents', async (torrent) => {
|
||||||
console.log('update index', torrent.id, torrent.name, '[', i, 'of', torrents, ']')
|
console.log('update index', torrent.id, torrent.name, '[', i, 'of', torrents, ']')
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true})
|
patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true})
|
||||||
|
|
||||||
torrent.nameIndex = torrent.name
|
torrent.nameIndex = torrent.name
|
||||||
await sphinx.query(`DELETE FROM torrents WHERE id = ${torrent.id}`)
|
await sphinx.query(`DELETE FROM torrents WHERE id = ${torrent.id}`)
|
||||||
await sphinx.insertValues('torrents', torrent)
|
await sphinx.insertValues('torrents', torrent)
|
||||||
})
|
})
|
||||||
i = 1
|
i = 1
|
||||||
await forBigTable(sphinx, 'files', async (file) => {
|
await forBigTable(sphinx, 'files', async (file) => {
|
||||||
console.log('update index', file.id, file.path, '[', i, 'of', files, ']')
|
console.log('update index', file.id, file.path, '[', i, 'of', files, ']')
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
patchWindow.webContents.send('reindex', {field: file.path, index: i++, all: files})
|
patchWindow.webContents.send('reindex', {field: file.path, index: i++, all: files})
|
||||||
|
|
||||||
file.pathIndex = file.path
|
file.pathIndex = file.path
|
||||||
await sphinx.query(`DELETE FROM files WHERE id = ${file.id}`)
|
await sphinx.query(`DELETE FROM files WHERE id = ${file.id}`)
|
||||||
await sphinx.insertValues('files', file)
|
await sphinx.insertValues('files', file)
|
||||||
})
|
})
|
||||||
|
|
||||||
await setVersion(2)
|
await setVersion(2)
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
openPatchWindow()
|
openPatchWindow()
|
||||||
|
|
||||||
console.log('optimizing torrents')
|
console.log('optimizing torrents')
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
patchWindow.webContents.send('optimize', {field: 'torrents'})
|
patchWindow.webContents.send('optimize', {field: 'torrents'})
|
||||||
sphinx.query(`OPTIMIZE INDEX torrents`)
|
sphinx.query(`OPTIMIZE INDEX torrents`)
|
||||||
await sphinxApp.waitOptimized('torrents')
|
await sphinxApp.waitOptimized('torrents')
|
||||||
|
|
||||||
console.log('optimizing files')
|
console.log('optimizing files')
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
patchWindow.webContents.send('optimize', {field: 'files'})
|
patchWindow.webContents.send('optimize', {field: 'files'})
|
||||||
sphinx.query(`OPTIMIZE INDEX files`)
|
sphinx.query(`OPTIMIZE INDEX files`)
|
||||||
await sphinxApp.waitOptimized('files')
|
await sphinxApp.waitOptimized('files')
|
||||||
|
|
||||||
await setVersion(3)
|
await setVersion(3)
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
openPatchWindow()
|
openPatchWindow()
|
||||||
|
|
||||||
// block xxx
|
// block xxx
|
||||||
let bad = 0
|
let bad = 0
|
||||||
|
|
||||||
let i = 1
|
let i = 1
|
||||||
const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c
|
const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c
|
||||||
await forBigTable(sphinx, 'torrents', async (torrent) => {
|
await forBigTable(sphinx, 'torrents', async (torrent) => {
|
||||||
console.log('update index', torrent.id, torrent.name, '[', i, 'of', torrents, '] - delete:', bad)
|
console.log('update index', torrent.id, torrent.name, '[', i, 'of', torrents, '] - delete:', bad)
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true})
|
patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true})
|
||||||
|
|
||||||
if(torrent.contentcategory == 'xxx')
|
if(torrent.contentcategory == 'xxx')
|
||||||
{
|
{
|
||||||
delete torrent.contentcategory
|
delete torrent.contentcategory
|
||||||
delete torrent.contenttype
|
delete torrent.contenttype
|
||||||
torrent = await getTorrent(sphinx, null, torrent) // get files
|
torrent = await getTorrent(sphinx, null, torrent) // get files
|
||||||
torrentTypeDetect(torrent, torrent.filesList)
|
torrentTypeDetect(torrent, torrent.filesList)
|
||||||
if(torrent.contentType == 'bad')
|
if(torrent.contentType == 'bad')
|
||||||
{
|
{
|
||||||
console.log('remove bad torrent', torrent.name)
|
console.log('remove bad torrent', torrent.name)
|
||||||
bad++
|
bad++
|
||||||
await sphinx.query(`DELETE FROM torrents WHERE hash = '${torrent.hash}'`)
|
await sphinx.query(`DELETE FROM torrents WHERE hash = '${torrent.hash}'`)
|
||||||
await sphinx.query(`DELETE FROM files WHERE hash = '${torrent.hash}'`)
|
await sphinx.query(`DELETE FROM files WHERE hash = '${torrent.hash}'`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('removed', bad, 'torrents')
|
console.log('removed', bad, 'torrents')
|
||||||
|
|
||||||
await setVersion(4)
|
await setVersion(4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('db patch done')
|
console.log('db patch done')
|
||||||
sphinx.destroy()
|
sphinx.destroy()
|
||||||
if(patchWindow)
|
if(patchWindow)
|
||||||
{
|
{
|
||||||
patchWindow.destroy()
|
patchWindow.destroy()
|
||||||
if(mainWindow)
|
if(mainWindow)
|
||||||
mainWindow.show()
|
mainWindow.show()
|
||||||
}
|
}
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
// init of db, we can set version to last
|
// init of db, we can set version to last
|
||||||
if(sphinxApp && sphinxApp.isInitDb)
|
if(sphinxApp && sphinxApp.isInitDb)
|
||||||
{
|
{
|
||||||
console.log('new db, set version to last version', currentVersion)
|
console.log('new db, set version to last version', currentVersion)
|
||||||
await setVersion(currentVersion)
|
await setVersion(currentVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
sphinx.query('select * from version', async (err, version) => {
|
sphinx.query('select * from version', async (err, version) => {
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
console.log('error on version get on db patch')
|
console.log('error on version get on db patch')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!version || !version[0] || !version[0].version)
|
if(!version || !version[0] || !version[0].version)
|
||||||
{
|
{
|
||||||
if(sphinxApp && fs.existsSync(`${sphinxApp.directoryPath}/version.vrs`))
|
if(sphinxApp && fs.existsSync(`${sphinxApp.directoryPath}/version.vrs`))
|
||||||
{
|
{
|
||||||
const ver = parseInt(fs.readFileSync(`${sphinxApp.directoryPath}/version.vrs`))
|
const ver = parseInt(fs.readFileSync(`${sphinxApp.directoryPath}/version.vrs`))
|
||||||
if(ver > 0)
|
if(ver > 0)
|
||||||
{
|
{
|
||||||
console.log('readed version from version.vrs', ver)
|
console.log('readed version from version.vrs', ver)
|
||||||
patch(ver)
|
patch(ver)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console.log('error: bad version in version.vrs')
|
console.log('error: bad version in version.vrs')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console.log('version not founded, set db version to 1')
|
console.log('version not founded, set db version to 1')
|
||||||
await setVersion(1)
|
await setVersion(1)
|
||||||
patch(1)
|
patch(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
patch(version[0].version)
|
patch(version[0].version)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -2,67 +2,67 @@ const path = require('path')
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
if (fs.existsSync(`./${app}`)) {
|
if (fs.existsSync(`./${app}`)) {
|
||||||
return `./${app}`
|
return `./${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/^win/.test(process.platform) && fs.existsSync(`./${app}.exe`)) {
|
if (/^win/.test(process.platform) && fs.existsSync(`./${app}.exe`)) {
|
||||||
return `./${app}.exe`
|
return `./${app}.exe`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/^win/.test(process.platform) && fs.existsSync(`./${process.arch}/${app}.exe`)) {
|
if (/^win/.test(process.platform) && fs.existsSync(`./${process.arch}/${app}.exe`)) {
|
||||||
return `./${process.arch}/${app}.exe`
|
return `./${process.arch}/${app}.exe`
|
||||||
}
|
}
|
||||||
|
|
||||||
if(/^win/.test(process.platform) && fs.existsSync(path.dirname(process.execPath) + `/${app}.exe`)) {
|
if(/^win/.test(process.platform) && fs.existsSync(path.dirname(process.execPath) + `/${app}.exe`)) {
|
||||||
return path.dirname(process.execPath) + `/${app}.exe`
|
return path.dirname(process.execPath) + `/${app}.exe`
|
||||||
}
|
}
|
||||||
|
|
||||||
if(/^win/.test(process.platform) && fs.existsSync(path.dirname(process.execPath) + `/${process.arch}/${app}.exe`)) {
|
if(/^win/.test(process.platform) && fs.existsSync(path.dirname(process.execPath) + `/${process.arch}/${app}.exe`)) {
|
||||||
return path.dirname(process.execPath) + `/${process.arch}/${app}.exe`
|
return path.dirname(process.execPath) + `/${process.arch}/${app}.exe`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs.existsSync(fs.realpathSync(__dirname) + `/${app}`)) {
|
if (fs.existsSync(fs.realpathSync(__dirname) + `/${app}`)) {
|
||||||
return fs.realpathSync(__dirname) + `/${app}`
|
return fs.realpathSync(__dirname) + `/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs.existsSync(fs.realpathSync(__dirname) + `/${process.arch}/${app}`)) {
|
if (fs.existsSync(fs.realpathSync(__dirname) + `/${process.arch}/${app}`)) {
|
||||||
return fs.realpathSync(__dirname) + `/${process.arch}/${app}`
|
return fs.realpathSync(__dirname) + `/${process.arch}/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs.existsSync(fs.realpathSync(path.join(__dirname, '/../../..')) + `/${app}`)) {
|
if (fs.existsSync(fs.realpathSync(path.join(__dirname, '/../../..')) + `/${app}`)) {
|
||||||
return fs.realpathSync(path.join(__dirname, '/../../..')) + `/${app}`
|
return fs.realpathSync(path.join(__dirname, '/../../..')) + `/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs.existsSync(fs.realpathSync(path.join(__dirname, '/../../..')) + `/${process.arch}/${app}`)) {
|
if (fs.existsSync(fs.realpathSync(path.join(__dirname, '/../../..')) + `/${process.arch}/${app}`)) {
|
||||||
return fs.realpathSync(path.join(__dirname, '/../../..')) + `/${process.arch}/${app}`
|
return fs.realpathSync(path.join(__dirname, '/../../..')) + `/${process.arch}/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (process.platform === 'darwin' && fs.existsSync(fs.realpathSync(path.join(__dirname, '/../../../MacOS')) + `/${app}`)) {
|
if (process.platform === 'darwin' && fs.existsSync(fs.realpathSync(path.join(__dirname, '/../../../MacOS')) + `/${app}`)) {
|
||||||
return fs.realpathSync(path.join(__dirname, '/../../../MacOS')) + `/${app}`
|
return fs.realpathSync(path.join(__dirname, '/../../../MacOS')) + `/${app}`
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
if (/^win/.test(process.platform) && fs.existsSync(`imports/win/${app}.exe`)) {
|
if (/^win/.test(process.platform) && fs.existsSync(`imports/win/${app}.exe`)) {
|
||||||
return `imports/win/${app}.exe`
|
return `imports/win/${app}.exe`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/^win/.test(process.platform) && fs.existsSync(`imports/win/${process.arch}/${app}.exe`)) {
|
if (/^win/.test(process.platform) && fs.existsSync(`imports/win/${process.arch}/${app}.exe`)) {
|
||||||
return `imports/win/${process.arch}/${app}.exe`
|
return `imports/win/${process.arch}/${app}.exe`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'linux' && fs.existsSync(`imports/linux/${app}`)) {
|
if (process.platform === 'linux' && fs.existsSync(`imports/linux/${app}`)) {
|
||||||
return `imports/linux/${app}`
|
return `imports/linux/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'linux' && fs.existsSync(`imports/linux/${process.arch}/${app}`)) {
|
if (process.platform === 'linux' && fs.existsSync(`imports/linux/${process.arch}/${app}`)) {
|
||||||
return `imports/linux/${process.arch}/${app}`
|
return `imports/linux/${process.arch}/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'darwin' && fs.existsSync(`imports/darwin/${app}`)) {
|
if (process.platform === 'darwin' && fs.existsSync(`imports/darwin/${app}`)) {
|
||||||
return `imports/darwin/${app}`
|
return `imports/darwin/${app}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${app}`
|
return `${app}`
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
module.exports = class Feed {
|
module.exports = class Feed {
|
||||||
constructor({sphinx})
|
constructor({sphinx})
|
||||||
{
|
{
|
||||||
this.feed = []
|
this.feed = []
|
||||||
this.sphinx = sphinx
|
this.sphinx = sphinx
|
||||||
this.loaded = false
|
this.loaded = false
|
||||||
this.max = 1000
|
this.max = 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
size()
|
size()
|
||||||
{
|
{
|
||||||
return this.feed.length
|
return this.feed.length
|
||||||
}
|
}
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
if(!this.loaded)
|
if(!this.loaded)
|
||||||
return // feed not loaded on begining, ignore saving
|
return // feed not loaded on begining, ignore saving
|
||||||
|
|
||||||
console.log('saving feed')
|
console.log('saving feed')
|
||||||
await this.sphinx.query('delete from feed where id > 0')
|
await this.sphinx.query('delete from feed where id > 0')
|
||||||
let id = 0
|
let id = 0
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
@ -24,77 +24,77 @@ module.exports = class Feed {
|
|||||||
async record => await this.sphinx.query('insert into feed(id, data) values(?, ?)', [++id, JSON.stringify(record)])
|
async record => await this.sphinx.query('insert into feed(id, data) values(?, ?)', [++id, JSON.stringify(record)])
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
this.feed = await this.sphinx.query('select * from feed limit 1000')
|
this.feed = await this.sphinx.query('select * from feed limit 1000')
|
||||||
if(this.feed && this.feed.length > 0)
|
if(this.feed && this.feed.length > 0)
|
||||||
this.feed = this.feed.map(f => JSON.parse(f.data))
|
this.feed = this.feed.map(f => JSON.parse(f.data))
|
||||||
else
|
else
|
||||||
this.feed = []
|
this.feed = []
|
||||||
|
|
||||||
this._order()
|
this._order()
|
||||||
this.loaded = true
|
this.loaded = true
|
||||||
console.log('lodead feed')
|
console.log('lodead feed')
|
||||||
}
|
}
|
||||||
|
|
||||||
clear()
|
clear()
|
||||||
{
|
{
|
||||||
console.log('clearing feed')
|
console.log('clearing feed')
|
||||||
this.feed = []
|
this.feed = []
|
||||||
}
|
}
|
||||||
|
|
||||||
add(data) {
|
add(data) {
|
||||||
let index = -1
|
let index = -1
|
||||||
if(data.hash)
|
if(data.hash)
|
||||||
index = this.feed.findIndex(element => element.hash === data.hash)
|
index = this.feed.findIndex(element => element.hash === data.hash)
|
||||||
|
|
||||||
if(index >= 0)
|
if(index >= 0)
|
||||||
this.feed[index] = Object.assign(this.feed[index], data) // just push up element
|
this.feed[index] = Object.assign(this.feed[index], data) // just push up element
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(typeof data == 'object')
|
if(typeof data == 'object')
|
||||||
{
|
{
|
||||||
data.feedDate = Math.floor(Date.now() / 1000)
|
data.feedDate = Math.floor(Date.now() / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.feed.length >= this.max)
|
if(this.feed.length >= this.max)
|
||||||
{
|
{
|
||||||
//cleanup
|
//cleanup
|
||||||
for(let i = this.feed.length - 1; i <= 0; i--)
|
for(let i = this.feed.length - 1; i <= 0; i--)
|
||||||
if(this._compare(this.feed[i]) <= 0)
|
if(this._compare(this.feed[i]) <= 0)
|
||||||
this.feed.pop()
|
this.feed.pop()
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
|
|
||||||
if(this.feed.length >= this.max)
|
if(this.feed.length >= this.max)
|
||||||
this.feed[this.feed.length - 1] = data // replace last one
|
this.feed[this.feed.length - 1] = data // replace last one
|
||||||
else
|
else
|
||||||
this.feed.push(data) // insert
|
this.feed.push(data) // insert
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.feed.push(data) // insert
|
this.feed.push(data) // insert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._order()
|
this._order()
|
||||||
}
|
}
|
||||||
|
|
||||||
_order() {
|
_order() {
|
||||||
this.feed.sort((a, b) => this._compare(b) - this._compare(a))
|
this.feed.sort((a, b) => this._compare(b) - this._compare(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
_compare(x)
|
_compare(x)
|
||||||
{
|
{
|
||||||
const rating = (x && x.good) || 0
|
const rating = (x && x.good) || 0
|
||||||
const comments = 0
|
const comments = 0
|
||||||
const time = Math.floor(Date.now() / 1000) - x.feedDate
|
const time = Math.floor(Date.now() / 1000) - x.feedDate
|
||||||
|
|
||||||
const maxTime = 600000
|
const maxTime = 600000
|
||||||
if(time > maxTime)
|
if(time > maxTime)
|
||||||
time = maxTime
|
time = maxTime
|
||||||
const relativeTime = (maxTime - time) / maxTime
|
const relativeTime = (maxTime - time) / maxTime
|
||||||
return relativeTime * relativeTime + rating * 1.5 * relativeTime + comments * 4 * relativeTime
|
return relativeTime * relativeTime + rating * 1.5 * relativeTime + comments * 4 * relativeTime
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,24 +1,24 @@
|
|||||||
module.exports = (sphinx, table, callback, doneCallback, max = 1000, where = '') => new Promise((done) => {
|
module.exports = (sphinx, table, callback, doneCallback, max = 1000, where = '') => new Promise((done) => {
|
||||||
const checker = (index = 0) => {
|
const checker = (index = 0) => {
|
||||||
sphinx.query(`SELECT * FROM ${table} WHERE id > ${index} ${where} LIMIT ${max}`, (err, torrents) => {
|
sphinx.query(`SELECT * FROM ${table} WHERE id > ${index} ${where} LIMIT ${max}`, (err, torrents) => {
|
||||||
const finish = () => {
|
const finish = () => {
|
||||||
if(err)
|
if(err)
|
||||||
console.log('big table parse error', err)
|
console.log('big table parse error', err)
|
||||||
if(doneCallback)
|
if(doneCallback)
|
||||||
doneCallback(true)
|
doneCallback(true)
|
||||||
done(true)
|
done(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!err && torrents.length > 0)
|
if(!err && torrents.length > 0)
|
||||||
Promise.all(torrents.map(callback)).then(() => {
|
Promise.all(torrents.map(callback)).then(() => {
|
||||||
if(torrents.length === max)
|
if(torrents.length === max)
|
||||||
checker(torrents[torrents.length - 1].id)
|
checker(torrents[torrents.length - 1].id)
|
||||||
else
|
else
|
||||||
finish()
|
finish()
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
finish()
|
finish()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
checker()
|
checker()
|
||||||
})
|
})
|
@ -7,78 +7,78 @@ import { app, BrowserWindow, screen } from "electron";
|
|||||||
import jetpack from "fs-jetpack";
|
import jetpack from "fs-jetpack";
|
||||||
|
|
||||||
export default (name, options) => {
|
export default (name, options) => {
|
||||||
const userDataDir = jetpack.cwd(app.getPath("userData"));
|
const userDataDir = jetpack.cwd(app.getPath("userData"));
|
||||||
const stateStoreFile = `window-state-${name}.json`;
|
const stateStoreFile = `window-state-${name}.json`;
|
||||||
const defaultSize = {
|
const defaultSize = {
|
||||||
width: options.width,
|
width: options.width,
|
||||||
height: options.height
|
height: options.height
|
||||||
};
|
};
|
||||||
let state = {};
|
let state = {};
|
||||||
let win;
|
let win;
|
||||||
|
|
||||||
const restore = () => {
|
const restore = () => {
|
||||||
let restoredState = {};
|
let restoredState = {};
|
||||||
try {
|
try {
|
||||||
restoredState = userDataDir.read(stateStoreFile, "json");
|
restoredState = userDataDir.read(stateStoreFile, "json");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// For some reason json can't be read (might be corrupted).
|
// For some reason json can't be read (might be corrupted).
|
||||||
// No worries, we have defaults.
|
// No worries, we have defaults.
|
||||||
}
|
}
|
||||||
return Object.assign({}, defaultSize, restoredState);
|
return Object.assign({}, defaultSize, restoredState);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCurrentPosition = () => {
|
const getCurrentPosition = () => {
|
||||||
const position = win.getPosition();
|
const position = win.getPosition();
|
||||||
const size = win.getSize();
|
const size = win.getSize();
|
||||||
return {
|
return {
|
||||||
x: position[0],
|
x: position[0],
|
||||||
y: position[1],
|
y: position[1],
|
||||||
width: size[0],
|
width: size[0],
|
||||||
height: size[1]
|
height: size[1]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const windowWithinBounds = (windowState, bounds) => {
|
const windowWithinBounds = (windowState, bounds) => {
|
||||||
return (
|
return (
|
||||||
windowState.x >= bounds.x &&
|
windowState.x >= bounds.x &&
|
||||||
windowState.y >= bounds.y &&
|
windowState.y >= bounds.y &&
|
||||||
windowState.x + windowState.width <= bounds.x + bounds.width &&
|
windowState.x + windowState.width <= bounds.x + bounds.width &&
|
||||||
windowState.y + windowState.height <= bounds.y + bounds.height
|
windowState.y + windowState.height <= bounds.y + bounds.height
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetToDefaults = () => {
|
const resetToDefaults = () => {
|
||||||
const bounds = screen.getPrimaryDisplay().bounds;
|
const bounds = screen.getPrimaryDisplay().bounds;
|
||||||
return Object.assign({}, defaultSize, {
|
return Object.assign({}, defaultSize, {
|
||||||
x: (bounds.width - defaultSize.width) / 2,
|
x: (bounds.width - defaultSize.width) / 2,
|
||||||
y: (bounds.height - defaultSize.height) / 2
|
y: (bounds.height - defaultSize.height) / 2
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const ensureVisibleOnSomeDisplay = windowState => {
|
const ensureVisibleOnSomeDisplay = windowState => {
|
||||||
const visible = screen.getAllDisplays().some(display => {
|
const visible = screen.getAllDisplays().some(display => {
|
||||||
return windowWithinBounds(windowState, display.bounds);
|
return windowWithinBounds(windowState, display.bounds);
|
||||||
});
|
});
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
// Window is partially or fully not visible now.
|
// Window is partially or fully not visible now.
|
||||||
// Reset it to safe defaults.
|
// Reset it to safe defaults.
|
||||||
return resetToDefaults();
|
return resetToDefaults();
|
||||||
}
|
}
|
||||||
return windowState;
|
return windowState;
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveState = () => {
|
const saveState = () => {
|
||||||
if (!win.isMinimized() && !win.isMaximized()) {
|
if (!win.isMinimized() && !win.isMaximized()) {
|
||||||
Object.assign(state, getCurrentPosition());
|
Object.assign(state, getCurrentPosition());
|
||||||
}
|
}
|
||||||
userDataDir.write(stateStoreFile, state, { atomic: true });
|
userDataDir.write(stateStoreFile, state, { atomic: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
state = ensureVisibleOnSomeDisplay(restore());
|
state = ensureVisibleOnSomeDisplay(restore());
|
||||||
|
|
||||||
win = new BrowserWindow(Object.assign({}, options, state));
|
win = new BrowserWindow(Object.assign({}, options, state));
|
||||||
|
|
||||||
win.on("close", saveState);
|
win.on("close", saveState);
|
||||||
|
|
||||||
return win;
|
return win;
|
||||||
};
|
};
|
||||||
|
@ -4,94 +4,94 @@ import url from "url";
|
|||||||
import __ from '../../app/translation'
|
import __ from '../../app/translation'
|
||||||
|
|
||||||
export const aboutMenuTemplateFunc = () => ({
|
export const aboutMenuTemplateFunc = () => ({
|
||||||
label: __("About"),
|
label: __("About"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: __("Changelog"),
|
label: __("Changelog"),
|
||||||
accelerator: "CmdOrCtrl+]",
|
accelerator: "CmdOrCtrl+]",
|
||||||
click: () => {
|
click: () => {
|
||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
parent: BrowserWindow.getFocusedWindow(),
|
parent: BrowserWindow.getFocusedWindow(),
|
||||||
modal: true
|
modal: true
|
||||||
})
|
})
|
||||||
win.setMenu(null)
|
win.setMenu(null)
|
||||||
win.loadURL(url.format({
|
win.loadURL(url.format({
|
||||||
pathname: path.join(__dirname, "app.html"),
|
pathname: path.join(__dirname, "app.html"),
|
||||||
protocol: "file:",
|
protocol: "file:",
|
||||||
slashes: true
|
slashes: true
|
||||||
}))
|
}))
|
||||||
win.webContents.on('did-finish-load', () => {
|
win.webContents.on('did-finish-load', () => {
|
||||||
setTimeout(() => win.send('url', '/changelog'), 0)
|
setTimeout(() => win.send('url', '/changelog'), 0)
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleRedirect = (e, url) => {
|
const handleRedirect = (e, url) => {
|
||||||
if(url != win.webContents.getURL()) {
|
if(url != win.webContents.getURL()) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
shell.openExternal(url)
|
shell.openExternal(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
win.webContents.on('will-navigate', handleRedirect)
|
win.webContents.on('will-navigate', handleRedirect)
|
||||||
win.webContents.on('new-window', handleRedirect)
|
win.webContents.on('new-window', handleRedirect)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Bug Report"),
|
label: __("Bug Report"),
|
||||||
accelerator: "CmdOrCtrl+[",
|
accelerator: "CmdOrCtrl+[",
|
||||||
click: () => {
|
click: () => {
|
||||||
shell.openExternal('https://github.com/DEgITx/rats-search/issues')
|
shell.openExternal('https://github.com/DEgITx/rats-search/issues')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Donate"),
|
label: __("Donate"),
|
||||||
accelerator: "CmdOrCtrl+*",
|
accelerator: "CmdOrCtrl+*",
|
||||||
click: () => {
|
click: () => {
|
||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
parent: BrowserWindow.getFocusedWindow(),
|
parent: BrowserWindow.getFocusedWindow(),
|
||||||
modal: true,
|
modal: true,
|
||||||
width: 1000
|
width: 1000
|
||||||
})
|
})
|
||||||
win.setMenu(null)
|
win.setMenu(null)
|
||||||
win.loadURL(url.format({
|
win.loadURL(url.format({
|
||||||
pathname: path.join(__dirname, "donate.html"),
|
pathname: path.join(__dirname, "donate.html"),
|
||||||
protocol: "file:",
|
protocol: "file:",
|
||||||
slashes: true
|
slashes: true
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const handleRedirect = (e, url) => {
|
const handleRedirect = (e, url) => {
|
||||||
if(url != win.webContents.getURL()) {
|
if(url != win.webContents.getURL()) {
|
||||||
if(!url.includes('patreon'))
|
if(!url.includes('patreon'))
|
||||||
return
|
return
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
shell.openExternal(url)
|
shell.openExternal(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
win.webContents.on('will-navigate', handleRedirect)
|
win.webContents.on('will-navigate', handleRedirect)
|
||||||
win.webContents.on('new-window', handleRedirect)
|
win.webContents.on('new-window', handleRedirect)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Help (Documentation)"),
|
label: __("Help (Documentation)"),
|
||||||
accelerator: "CmdOrCtrl+?",
|
accelerator: "CmdOrCtrl+?",
|
||||||
click: () => {
|
click: () => {
|
||||||
shell.openExternal('https://github.com/DEgITx/rats-search/blob/master/docs/MANUAL.md')
|
shell.openExternal('https://github.com/DEgITx/rats-search/blob/master/docs/MANUAL.md')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Support (Discussion)"),
|
label: __("Support (Discussion)"),
|
||||||
accelerator: "CmdOrCtrl+>",
|
accelerator: "CmdOrCtrl+>",
|
||||||
click: () => {
|
click: () => {
|
||||||
shell.openExternal('https://discord.gg/t9GQtxA')
|
shell.openExternal('https://discord.gg/t9GQtxA')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("About (GitHub)"),
|
label: __("About (GitHub)"),
|
||||||
accelerator: "CmdOrCtrl+<",
|
accelerator: "CmdOrCtrl+<",
|
||||||
click: () => {
|
click: () => {
|
||||||
shell.openExternal('https://github.com/DEgITx/rats-search')
|
shell.openExternal('https://github.com/DEgITx/rats-search')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -4,45 +4,45 @@ import path from 'path'
|
|||||||
import __, { translationsDir } from '../../app/translation'
|
import __, { translationsDir } from '../../app/translation'
|
||||||
|
|
||||||
export const settingsMenuTemplateFunc = (config, onLanguageChange) => ({
|
export const settingsMenuTemplateFunc = (config, onLanguageChange) => ({
|
||||||
label: __("Settings"),
|
label: __("Settings"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: __("Main Settings"),
|
label: __("Main Settings"),
|
||||||
accelerator: "CmdOrCtrl+O",
|
accelerator: "CmdOrCtrl+O",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.send('url', '/config')
|
BrowserWindow.getFocusedWindow().webContents.send('url', '/config')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Torrents Filters"),
|
label: __("Torrents Filters"),
|
||||||
accelerator: "CmdOrCtrl+\\",
|
accelerator: "CmdOrCtrl+\\",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.send('url', '/filters')
|
BrowserWindow.getFocusedWindow().webContents.send('url', '/filters')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Language"),
|
label: __("Language"),
|
||||||
submenu: (() => {
|
submenu: (() => {
|
||||||
const translations = []
|
const translations = []
|
||||||
const translationsDirectory = translationsDir()
|
const translationsDirectory = translationsDir()
|
||||||
fs.readdirSync(translationsDirectory).forEach(translation => {
|
fs.readdirSync(translationsDirectory).forEach(translation => {
|
||||||
const translationJson = JSON.parse(fs.readFileSync(`${translationsDirectory}/${translation}`, 'utf8'))
|
const translationJson = JSON.parse(fs.readFileSync(`${translationsDirectory}/${translation}`, 'utf8'))
|
||||||
const lang = path.basename(translation, '.json')
|
const lang = path.basename(translation, '.json')
|
||||||
translations.push({
|
translations.push({
|
||||||
label: translationJson.nameOriginal,
|
label: translationJson.nameOriginal,
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
checked: config.language === lang,
|
checked: config.language === lang,
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.send('changeLanguage', lang)
|
BrowserWindow.getFocusedWindow().webContents.send('changeLanguage', lang)
|
||||||
config.language = lang
|
config.language = lang
|
||||||
if(onLanguageChange)
|
if(onLanguageChange)
|
||||||
onLanguageChange(lang)
|
onLanguageChange(lang)
|
||||||
console.log('changed translation to:', lang)
|
console.log('changed translation to:', lang)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return translations
|
return translations
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
import { app, BrowserWindow } from "electron";
|
import { app, BrowserWindow } from "electron";
|
||||||
|
|
||||||
export const devMenuTemplate = {
|
export const devMenuTemplate = {
|
||||||
label: "Development",
|
label: "Development",
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: "Reload",
|
label: "Reload",
|
||||||
accelerator: "CmdOrCtrl+R",
|
accelerator: "CmdOrCtrl+R",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.reloadIgnoringCache();
|
BrowserWindow.getFocusedWindow().webContents.reloadIgnoringCache();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Toggle DevTools",
|
label: "Toggle DevTools",
|
||||||
accelerator: "Alt+CmdOrCtrl+I",
|
accelerator: "Alt+CmdOrCtrl+I",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().toggleDevTools();
|
BrowserWindow.getFocusedWindow().toggleDevTools();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Quit",
|
label: "Quit",
|
||||||
accelerator: "CmdOrCtrl+Q",
|
accelerator: "CmdOrCtrl+Q",
|
||||||
click: () => {
|
click: () => {
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import __ from '../../app/translation'
|
import __ from '../../app/translation'
|
||||||
|
|
||||||
export const editMenuTemplateFunc = () => ({
|
export const editMenuTemplateFunc = () => ({
|
||||||
label: __("Edit"),
|
label: __("Edit"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{ label: __("Undo"), accelerator: "CmdOrCtrl+Z", selector: "undo:" },
|
{ label: __("Undo"), accelerator: "CmdOrCtrl+Z", selector: "undo:" },
|
||||||
{ label: __("Redo"), accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
|
{ label: __("Redo"), accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
|
||||||
{ type: "separator" },
|
{ type: "separator" },
|
||||||
{ label: __("Cut"), accelerator: "CmdOrCtrl+X", selector: "cut:" },
|
{ label: __("Cut"), accelerator: "CmdOrCtrl+X", selector: "cut:" },
|
||||||
{ label: __("Copy"), accelerator: "CmdOrCtrl+C", selector: "copy:" },
|
{ label: __("Copy"), accelerator: "CmdOrCtrl+C", selector: "copy:" },
|
||||||
{ label: __("Paste"), accelerator: "CmdOrCtrl+V", selector: "paste:" },
|
{ label: __("Paste"), accelerator: "CmdOrCtrl+V", selector: "paste:" },
|
||||||
{ label: __("Select All"), accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
|
{ label: __("Select All"), accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -4,28 +4,28 @@ import url from "url";
|
|||||||
import __ from '../../app/translation'
|
import __ from '../../app/translation'
|
||||||
|
|
||||||
export const manageMenuTemplateFunc = () => ({
|
export const manageMenuTemplateFunc = () => ({
|
||||||
label: __("Manage"),
|
label: __("Manage"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: __("Downloads"),
|
label: __("Downloads"),
|
||||||
accelerator: "CmdOrCtrl+d",
|
accelerator: "CmdOrCtrl+d",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.send('url', '/downloads')
|
BrowserWindow.getFocusedWindow().webContents.send('url', '/downloads')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Search"),
|
label: __("Search"),
|
||||||
accelerator: "CmdOrCtrl+n",
|
accelerator: "CmdOrCtrl+n",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.send('url', '/')
|
BrowserWindow.getFocusedWindow().webContents.send('url', '/')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Top"),
|
label: __("Top"),
|
||||||
accelerator: "CmdOrCtrl+t",
|
accelerator: "CmdOrCtrl+t",
|
||||||
click: () => {
|
click: () => {
|
||||||
BrowserWindow.getFocusedWindow().webContents.send('url', '/top')
|
BrowserWindow.getFocusedWindow().webContents.send('url', '/top')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -2,36 +2,36 @@ const mysql = require('mysql');
|
|||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
|
||||||
const expand = (sphinx) => {
|
const expand = (sphinx) => {
|
||||||
const queryCall = sphinx.query.bind(sphinx)
|
const queryCall = sphinx.query.bind(sphinx)
|
||||||
|
|
||||||
sphinx.query = (sql, args, callback) => new Promise((resolve, reject) => {
|
sphinx.query = (sql, args, callback) => new Promise((resolve, reject) => {
|
||||||
if(typeof args === 'function' || typeof args === 'undefined')
|
if(typeof args === 'function' || typeof args === 'undefined')
|
||||||
{
|
{
|
||||||
queryCall(sql, (err, res) => {
|
queryCall(sql, (err, res) => {
|
||||||
if(err)
|
if(err)
|
||||||
reject(err)
|
reject(err)
|
||||||
else
|
else
|
||||||
resolve(res)
|
resolve(res)
|
||||||
|
|
||||||
if(args)
|
if(args)
|
||||||
args(err, res)
|
args(err, res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
queryCall(sql, args, (err, res) => {
|
queryCall(sql, args, (err, res) => {
|
||||||
if(err)
|
if(err)
|
||||||
reject(err)
|
reject(err)
|
||||||
else
|
else
|
||||||
resolve(res)
|
resolve(res)
|
||||||
|
|
||||||
if(callback)
|
if(callback)
|
||||||
callback(err, res)
|
callback(err, res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
sphinx.insertValues = (table, values, callback) => new Promise((resolve) => {
|
sphinx.insertValues = (table, values, callback) => new Promise((resolve) => {
|
||||||
let names = '';
|
let names = '';
|
||||||
let data = '';
|
let data = '';
|
||||||
for(const val in values)
|
for(const val in values)
|
||||||
@ -46,101 +46,101 @@ const expand = (sphinx) => {
|
|||||||
data = data.slice(0, -1)
|
data = data.slice(0, -1)
|
||||||
let query = `INSERT INTO ${table}(${names}) VALUES(${data})`;
|
let query = `INSERT INTO ${table}(${names}) VALUES(${data})`;
|
||||||
queryCall(query, (...responce) => {
|
queryCall(query, (...responce) => {
|
||||||
if(callback)
|
if(callback)
|
||||||
callback(...responce)
|
callback(...responce)
|
||||||
resolve(...responce)
|
resolve(...responce)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
sphinx.updateValues = (table, values, whereObject, callback) => new Promise((resolve) => {
|
sphinx.updateValues = (table, values, whereObject, callback) => new Promise((resolve) => {
|
||||||
let set = ''
|
let set = ''
|
||||||
for(const val in values)
|
for(const val in values)
|
||||||
{
|
{
|
||||||
if(values[val] === null)
|
if(values[val] === null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(typeof values[val] == 'object')
|
if(typeof values[val] == 'object')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// skip text indexes (manticore bug https://github.com/manticoresoftware/manticoresearch/issues/84)
|
// skip text indexes (manticore bug https://github.com/manticoresoftware/manticoresearch/issues/84)
|
||||||
if(typeof values[val] == 'string')
|
if(typeof values[val] == 'string')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
set += '`' + val + '` = ' + sphinx.escape(values[val]) + ',';
|
set += '`' + val + '` = ' + sphinx.escape(values[val]) + ',';
|
||||||
}
|
}
|
||||||
if(set.length == 0)
|
if(set.length == 0)
|
||||||
return
|
return
|
||||||
set = set.slice(0, -1)
|
set = set.slice(0, -1)
|
||||||
|
|
||||||
let where = ''
|
let where = ''
|
||||||
for(const w in whereObject)
|
for(const w in whereObject)
|
||||||
{
|
{
|
||||||
if(whereObject[w] === null)
|
if(whereObject[w] === null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
where += '`' + w + '` = ' + sphinx.escape(whereObject[w]) + ' and';
|
where += '`' + w + '` = ' + sphinx.escape(whereObject[w]) + ' and';
|
||||||
}
|
}
|
||||||
if(where.length == 0)
|
if(where.length == 0)
|
||||||
return
|
return
|
||||||
where = where.slice(0, -3)
|
where = where.slice(0, -3)
|
||||||
|
|
||||||
const query = `UPDATE ${table} SET ${set} WHERE ${where}`;
|
const query = `UPDATE ${table} SET ${set} WHERE ${where}`;
|
||||||
queryCall(query, (...responce) => {
|
queryCall(query, (...responce) => {
|
||||||
if(callback)
|
if(callback)
|
||||||
callback(...responce)
|
callback(...responce)
|
||||||
resolve(...responce)
|
resolve(...responce)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return sphinx
|
return sphinx
|
||||||
}
|
}
|
||||||
|
|
||||||
const pool = () => {
|
const pool = () => {
|
||||||
let sphinx = mysql.createPool({
|
let sphinx = mysql.createPool({
|
||||||
connectionLimit: config.sphinx.connectionLimit,
|
connectionLimit: config.sphinx.connectionLimit,
|
||||||
host : config.sphinx.host,
|
host : config.sphinx.host,
|
||||||
port : config.sphinx.port
|
port : config.sphinx.port
|
||||||
});
|
});
|
||||||
return expand(sphinx)
|
return expand(sphinx)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mysqlSingle;
|
let mysqlSingle;
|
||||||
const single = (callback) => {
|
const single = (callback) => {
|
||||||
mysqlSingle = mysql.createConnection({
|
mysqlSingle = mysql.createConnection({
|
||||||
host : config.sphinx.host,
|
host : config.sphinx.host,
|
||||||
port : config.sphinx.port
|
port : config.sphinx.port
|
||||||
});
|
});
|
||||||
|
|
||||||
let promiseResolve;
|
let promiseResolve;
|
||||||
const connectionPromise = new Promise((resolve) => {
|
const connectionPromise = new Promise((resolve) => {
|
||||||
promiseResolve = resolve
|
promiseResolve = resolve
|
||||||
})
|
})
|
||||||
mysqlSingle.waitConnection = () => connectionPromise;
|
mysqlSingle.waitConnection = () => connectionPromise;
|
||||||
|
|
||||||
mysqlSingle.connect((mysqlError) => {
|
mysqlSingle.connect((mysqlError) => {
|
||||||
if (mysqlError) {
|
if (mysqlError) {
|
||||||
console.error('error connecting: ' + mysqlError.stack);
|
console.error('error connecting: ' + mysqlError.stack);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(callback)
|
if(callback)
|
||||||
callback(mysqlSingle)
|
callback(mysqlSingle)
|
||||||
|
|
||||||
promiseResolve(mysqlSingle)
|
promiseResolve(mysqlSingle)
|
||||||
});
|
});
|
||||||
|
|
||||||
mysqlSingle.on('error', (err) => {
|
mysqlSingle.on('error', (err) => {
|
||||||
console.log('db error', err);
|
console.log('db error', err);
|
||||||
if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
|
if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
|
||||||
mysqlSingle = undefined
|
mysqlSingle = undefined
|
||||||
single(); // lost due to either server restart, or a
|
single(); // lost due to either server restart, or a
|
||||||
} else { // connnection idle timeout (the wait_timeout
|
} else { // connnection idle timeout (the wait_timeout
|
||||||
throw err; // server variable configures this)
|
throw err; // server variable configures this)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mysqlSingle = expand(mysqlSingle)
|
mysqlSingle = expand(mysqlSingle)
|
||||||
return mysqlSingle
|
return mysqlSingle
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {pool, single}
|
module.exports = {pool, single}
|
@ -22,16 +22,16 @@ const socketMessages = {}
|
|||||||
|
|
||||||
io.on('connection', (socket) =>
|
io.on('connection', (socket) =>
|
||||||
{
|
{
|
||||||
for(const message in socketMessages)
|
for(const message in socketMessages)
|
||||||
{
|
{
|
||||||
socket.on(message, socketMessages[message])
|
socket.on(message, socketMessages[message])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
sphinx = startSphinx(() => {
|
sphinx = startSphinx(() => {
|
||||||
dbPatcher(() => {
|
dbPatcher(() => {
|
||||||
spider = spiderCall((...data) => io.sockets.emit(...data), (message, callback) => {
|
spider = spiderCall((...data) => io.sockets.emit(...data), (message, callback) => {
|
||||||
socketMessages[message] = callback
|
socketMessages[message] = callback
|
||||||
}, path.resolve(packageJson.serverDataDirectory), packageJson.version, 'production')
|
}, path.resolve(packageJson.serverDataDirectory), packageJson.version, 'production')
|
||||||
}, null, sphinx)
|
}, null, sphinx)
|
||||||
}, path.resolve(packageJson.serverDataDirectory), () => {})
|
}, path.resolve(packageJson.serverDataDirectory), () => {})
|
@ -3,12 +3,12 @@
|
|||||||
* @param {Array} a items An array containing the items.
|
* @param {Array} a items An array containing the items.
|
||||||
*/
|
*/
|
||||||
module.exports = function shuffle(a) {
|
module.exports = function shuffle(a) {
|
||||||
let j, x, i;
|
let j, x, i;
|
||||||
for (i = a.length - 1; i > 0; i--) {
|
for (i = a.length - 1; i > 0; i--) {
|
||||||
j = Math.floor(Math.random() * (i + 1));
|
j = Math.floor(Math.random() * (i + 1));
|
||||||
x = a[i];
|
x = a[i];
|
||||||
a[i] = a[j];
|
a[i] = a[j];
|
||||||
a[j] = x;
|
a[j] = x;
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
let env
|
let env
|
||||||
try{
|
try{
|
||||||
env = require("env");
|
env = require("env");
|
||||||
} catch(e){}
|
} catch(e){}
|
||||||
const appPath = require('./electronAppPath')
|
const appPath = require('./electronAppPath')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
@ -10,7 +10,7 @@ const { spawn, exec } = require('child_process')
|
|||||||
const appConfig = require('./config')
|
const appConfig = require('./config')
|
||||||
|
|
||||||
const writeSphinxConfig = (path, dbPath) => {
|
const writeSphinxConfig = (path, dbPath) => {
|
||||||
let config = `
|
let config = `
|
||||||
index torrents
|
index torrents
|
||||||
{
|
{
|
||||||
type = rt
|
type = rt
|
||||||
@ -92,115 +92,115 @@ const writeSphinxConfig = (path, dbPath) => {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// clear dir in test env
|
// clear dir in test env
|
||||||
if(env && env.name === 'test')
|
if(env && env.name === 'test')
|
||||||
{
|
{
|
||||||
if (fs.existsSync(`${dbPath}/database`)) {
|
if (fs.existsSync(`${dbPath}/database`)) {
|
||||||
fs.readdirSync(`${dbPath}/database`).forEach(function(file, index){
|
fs.readdirSync(`${dbPath}/database`).forEach(function(file, index){
|
||||||
const curPath = `${dbPath}/database` + "/" + file;
|
const curPath = `${dbPath}/database` + "/" + file;
|
||||||
if (!fs.lstatSync(curPath).isDirectory()) {
|
if (!fs.lstatSync(curPath).isDirectory()) {
|
||||||
fs.unlinkSync(curPath);
|
fs.unlinkSync(curPath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.readdirSync(path).forEach(function(file, index){
|
fs.readdirSync(path).forEach(function(file, index){
|
||||||
if(!file.startsWith('binlog'))
|
if(!file.startsWith('binlog'))
|
||||||
return;
|
return;
|
||||||
const curPath = path + "/" + file;
|
const curPath = path + "/" + file;
|
||||||
if (!fs.lstatSync(curPath).isDirectory()) {
|
if (!fs.lstatSync(curPath).isDirectory()) {
|
||||||
fs.unlinkSync(curPath);
|
fs.unlinkSync(curPath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean query.log because it too large and don't consist any good info
|
// clean query.log because it too large and don't consist any good info
|
||||||
if(fs.existsSync(`${path}/query.log`))
|
if(fs.existsSync(`${path}/query.log`))
|
||||||
{
|
{
|
||||||
fs.unlinkSync(`${path}/query.log`)
|
fs.unlinkSync(`${path}/query.log`)
|
||||||
}
|
}
|
||||||
|
|
||||||
let isInitDb = false
|
let isInitDb = false
|
||||||
|
|
||||||
if (!fs.existsSync(`${dbPath}/database`)){
|
if (!fs.existsSync(`${dbPath}/database`)){
|
||||||
fs.mkdirSync(`${dbPath}/database`);
|
fs.mkdirSync(`${dbPath}/database`);
|
||||||
isInitDb = true
|
isInitDb = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if(/^win/.test(process.platform))
|
if(/^win/.test(process.platform))
|
||||||
config = iconv.encode(config, 'win1251')
|
config = iconv.encode(config, 'win1251')
|
||||||
|
|
||||||
fs.writeFileSync(`${path}/sphinx.conf`, config)
|
fs.writeFileSync(`${path}/sphinx.conf`, config)
|
||||||
console.log(`writed sphinx config to ${path}`)
|
console.log(`writed sphinx config to ${path}`)
|
||||||
console.log('db path:', dbPath)
|
console.log('db path:', dbPath)
|
||||||
|
|
||||||
return {isInitDb}
|
return {isInitDb}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (callback, dataDirectory, onClose) => {
|
module.exports = (callback, dataDirectory, onClose) => {
|
||||||
const sphinxPath = path.resolve(appPath('searchd'))
|
const sphinxPath = path.resolve(appPath('searchd'))
|
||||||
console.log('Sphinx Path:', sphinxPath)
|
console.log('Sphinx Path:', sphinxPath)
|
||||||
|
|
||||||
const sphinxConfigDirectory = dataDirectory
|
const sphinxConfigDirectory = dataDirectory
|
||||||
appConfig['dbPath'] = appConfig.dbPath && appConfig.dbPath.length > 0 ? appConfig.dbPath : sphinxConfigDirectory;
|
appConfig['dbPath'] = appConfig.dbPath && appConfig.dbPath.length > 0 ? appConfig.dbPath : sphinxConfigDirectory;
|
||||||
// on portable dir can move database directory
|
// on portable dir can move database directory
|
||||||
if(!fs.existsSync(appConfig.dbPath) && fs.existsSync(sphinxConfigDirectory))
|
if(!fs.existsSync(appConfig.dbPath) && fs.existsSync(sphinxConfigDirectory))
|
||||||
{
|
{
|
||||||
appConfig['dbPath'] = sphinxConfigDirectory
|
appConfig['dbPath'] = sphinxConfigDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isInitDb } = writeSphinxConfig(sphinxConfigDirectory, appConfig.dbPath)
|
const { isInitDb } = writeSphinxConfig(sphinxConfigDirectory, appConfig.dbPath)
|
||||||
|
|
||||||
const config = `${sphinxConfigDirectory}/sphinx.conf`
|
const config = `${sphinxConfigDirectory}/sphinx.conf`
|
||||||
const options = ['--config', config]
|
const options = ['--config', config]
|
||||||
if(!(/^win/.test(process.platform)))
|
if(!(/^win/.test(process.platform)))
|
||||||
{
|
{
|
||||||
options.push('--nodetach')
|
options.push('--nodetach')
|
||||||
}
|
}
|
||||||
const sphinx = spawn(sphinxPath, options)
|
const sphinx = spawn(sphinxPath, options)
|
||||||
// remeber initizalizing of db
|
// remeber initizalizing of db
|
||||||
sphinx.isInitDb = isInitDb
|
sphinx.isInitDb = isInitDb
|
||||||
sphinx.directoryPath = appConfig.dbPath
|
sphinx.directoryPath = appConfig.dbPath
|
||||||
sphinx.directoryPathDb = appConfig.dbPath + '/database'
|
sphinx.directoryPathDb = appConfig.dbPath + '/database'
|
||||||
|
|
||||||
const optimizeResolvers = {}
|
const optimizeResolvers = {}
|
||||||
|
|
||||||
sphinx.stdout.on('data', (data) => {
|
sphinx.stdout.on('data', (data) => {
|
||||||
console.log(`sphinx: ${data}`)
|
console.log(`sphinx: ${data}`)
|
||||||
if (data.includes('accepting connections')) {
|
if (data.includes('accepting connections')) {
|
||||||
console.log('catched sphinx start')
|
console.log('catched sphinx start')
|
||||||
if(callback)
|
if(callback)
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkOptimized = String(data).match(/index ([\w]+): optimized/)
|
const checkOptimized = String(data).match(/index ([\w]+): optimized/)
|
||||||
if(checkOptimized)
|
if(checkOptimized)
|
||||||
{
|
{
|
||||||
if(optimizeResolvers[checkOptimized[1]])
|
if(optimizeResolvers[checkOptimized[1]])
|
||||||
{
|
{
|
||||||
console.log('resolve optimizer', checkOptimized[1])
|
console.log('resolve optimizer', checkOptimized[1])
|
||||||
optimizeResolvers[checkOptimized[1]]()
|
optimizeResolvers[checkOptimized[1]]()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
sphinx.on('close', (code, signal) => {
|
sphinx.on('close', (code, signal) => {
|
||||||
console.log(`sphinx closed with code ${code} and signal ${signal}`)
|
console.log(`sphinx closed with code ${code} and signal ${signal}`)
|
||||||
if(onClose)
|
if(onClose)
|
||||||
onClose()
|
onClose()
|
||||||
})
|
})
|
||||||
|
|
||||||
sphinx.stop = () => {
|
sphinx.stop = () => {
|
||||||
console.log('sphinx closing...')
|
console.log('sphinx closing...')
|
||||||
exec(`"${sphinxPath}" --config "${config}" --stopwait`)
|
exec(`"${sphinxPath}" --config "${config}" --stopwait`)
|
||||||
}
|
}
|
||||||
|
|
||||||
sphinx.waitOptimized = (table) => new Promise((resolve) => {
|
sphinx.waitOptimized = (table) => new Promise((resolve) => {
|
||||||
optimizeResolvers[table] = () => {
|
optimizeResolvers[table] = () => {
|
||||||
delete optimizeResolvers[table];
|
delete optimizeResolvers[table];
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return sphinx
|
return sphinx
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -3,184 +3,184 @@ const EventEmitter = require('events');
|
|||||||
const forBigTable = require('./forBigTable')
|
const forBigTable = require('./forBigTable')
|
||||||
|
|
||||||
module.exports = class P2PStore extends EventEmitter {
|
module.exports = class P2PStore extends EventEmitter {
|
||||||
constructor(p2p, sphinx)
|
constructor(p2p, sphinx)
|
||||||
{
|
{
|
||||||
super()
|
super()
|
||||||
this.id = 0
|
this.id = 0
|
||||||
this.synchronized = false
|
this.synchronized = false
|
||||||
|
|
||||||
console.log('connect p2p store...')
|
console.log('connect p2p store...')
|
||||||
this.p2p = p2p
|
this.p2p = p2p
|
||||||
this.sphinx = sphinx
|
this.sphinx = sphinx
|
||||||
|
|
||||||
this.sphinx.query("SELECT MAX(`id`) as mx from store", (err, rows) => {
|
this.sphinx.query("SELECT MAX(`id`) as mx from store", (err, rows) => {
|
||||||
if(err)
|
if(err)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(rows[0] && rows[0].mx >= 1)
|
if(rows[0] && rows[0].mx >= 1)
|
||||||
this.id = rows[0].mx;
|
this.id = rows[0].mx;
|
||||||
|
|
||||||
console.log('store db index', this.id)
|
console.log('store db index', this.id)
|
||||||
|
|
||||||
let lock = false
|
let lock = false
|
||||||
this.p2p.events.on('peer', () => {
|
this.p2p.events.on('peer', () => {
|
||||||
if(lock)
|
if(lock)
|
||||||
return
|
return
|
||||||
lock = true
|
lock = true
|
||||||
setTimeout(() => this.sync(), 1000)
|
setTimeout(() => this.sync(), 1000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.p2p.on('dbStore', (record) => {
|
this.p2p.on('dbStore', (record) => {
|
||||||
if(!record || record.id - 1 !== this.id)
|
if(!record || record.id - 1 !== this.id)
|
||||||
{
|
{
|
||||||
console.log('out of range peerdb store', record.id)
|
console.log('out of range peerdb store', record.id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this._syncRecord(record, () => {
|
this._syncRecord(record, () => {
|
||||||
// redirect other peers that record are stored
|
// redirect other peers that record are stored
|
||||||
this.p2p.emit('dbStore', record)
|
this.p2p.emit('dbStore', record)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.p2p.on('dbSync', ({id} = {}, callback) => {
|
this.p2p.on('dbSync', ({id} = {}, callback) => {
|
||||||
console.log('ask to sync db from', id, 'version')
|
console.log('ask to sync db from', id, 'version')
|
||||||
if(typeof id === 'undefined' || id >= this.id)
|
if(typeof id === 'undefined' || id >= this.id)
|
||||||
{
|
{
|
||||||
callback(false)
|
callback(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// back
|
// back
|
||||||
this.sphinx.query(`select * from store where id > ${id}`, (err, records) => {
|
this.sphinx.query(`select * from store where id > ${id}`, (err, records) => {
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
console.log(err)
|
console.log(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(records.length > 0)
|
if(records.length > 0)
|
||||||
callback({
|
callback({
|
||||||
records,
|
records,
|
||||||
index: this.id
|
index: this.id
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sync()
|
sync()
|
||||||
{
|
{
|
||||||
console.log('sync db on version', this.id)
|
console.log('sync db on version', this.id)
|
||||||
const processSync = (data, nil, peer) => {
|
const processSync = (data, nil, peer) => {
|
||||||
if(!data || !data.records)
|
if(!data || !data.records)
|
||||||
return
|
return
|
||||||
|
|
||||||
const oldIndex = this.id
|
const oldIndex = this.id
|
||||||
data.records.forEach(record => this._syncRecord(record))
|
data.records.forEach(record => this._syncRecord(record))
|
||||||
|
|
||||||
// peer also can contain another part of store records, try to sync them all
|
// peer also can contain another part of store records, try to sync them all
|
||||||
if(data.index >= 0
|
if(data.index >= 0
|
||||||
&& oldIndex < this.id // last sync update of store must be successful, otherwise no point to try sync db from this peer
|
&& oldIndex < this.id // last sync update of store must be successful, otherwise no point to try sync db from this peer
|
||||||
&& this.id < data.index)
|
&& this.id < data.index)
|
||||||
{
|
{
|
||||||
console.log('continue sync store from', this.id, 'index', 'peer', peer.peerId)
|
console.log('continue sync store from', this.id, 'index', 'peer', peer.peerId)
|
||||||
peer.emit('dbSync', {id: this.id}, processSync)
|
peer.emit('dbSync', {id: this.id}, processSync)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.p2p.emit('dbSync', {id: this.id}, processSync)
|
this.p2p.emit('dbSync', {id: this.id}, processSync)
|
||||||
this.synchronized = true
|
this.synchronized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
_syncRecord(record, callback)
|
_syncRecord(record, callback)
|
||||||
{
|
{
|
||||||
if(!record)
|
if(!record)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!record.id)
|
if(!record.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(record.id <= this.id)
|
if(record.id <= this.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(typeof record.data !== 'object')
|
if(typeof record.data !== 'object')
|
||||||
record.data = JSON.parse(record.data)
|
record.data = JSON.parse(record.data)
|
||||||
|
|
||||||
// check hash
|
// check hash
|
||||||
if(objectHash(record.data) !== record.hash)
|
if(objectHash(record.data) !== record.hash)
|
||||||
{
|
{
|
||||||
console.log('wrong hash for sync peerdb')
|
console.log('wrong hash for sync peerdb')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// set myself to false
|
// set myself to false
|
||||||
record.myself = false
|
record.myself = false
|
||||||
|
|
||||||
// push to db
|
// push to db
|
||||||
console.log('sync peerdb record', record.id)
|
console.log('sync peerdb record', record.id)
|
||||||
this._pushToDb(record)
|
this._pushToDb(record)
|
||||||
this.id = record.id
|
this.id = record.id
|
||||||
|
|
||||||
// redirect to next
|
// redirect to next
|
||||||
if(callback)
|
if(callback)
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
_pushToDb(value, callback)
|
_pushToDb(value, callback)
|
||||||
{
|
{
|
||||||
const data = this.sphinx.escape(JSON.stringify(value.data))
|
const data = this.sphinx.escape(JSON.stringify(value.data))
|
||||||
this.sphinx.query(
|
this.sphinx.query(
|
||||||
`insert into store(id, hash, peerId, data` + (value.index || value.data._index ? ', storeIndex' : '') + `)
|
`insert into store(id, hash, peerId, data` + (value.index || value.data._index ? ', storeIndex' : '') + `)
|
||||||
values('${value.id}', '${value.hash}', '${value.peerId || value.peerid}', ${data}` + (value.index || value.data._index ? ',' + this.sphinx.escape(value.index || value.data._index) : '') + ')',
|
values('${value.id}', '${value.hash}', '${value.peerId || value.peerid}', ${data}` + (value.index || value.data._index ? ',' + this.sphinx.escape(value.index || value.data._index) : '') + ')',
|
||||||
(err) => {
|
(err) => {
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
console.log(err)
|
console.log(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(callback)
|
if(callback)
|
||||||
callback()
|
callback()
|
||||||
})
|
})
|
||||||
this.emit('store', value)
|
this.emit('store', value)
|
||||||
}
|
}
|
||||||
|
|
||||||
store(obj)
|
store(obj)
|
||||||
{
|
{
|
||||||
if(!this.synchronized)
|
if(!this.synchronized)
|
||||||
{
|
{
|
||||||
console.log('cant store item on unsync db')
|
console.log('cant store item on unsync db')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean temp from object
|
// clean temp from object
|
||||||
const temp = obj._temp
|
const temp = obj._temp
|
||||||
delete obj._temp
|
delete obj._temp
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
id: ++this.id,
|
id: ++this.id,
|
||||||
hash: objectHash(obj),
|
hash: objectHash(obj),
|
||||||
data: obj,
|
data: obj,
|
||||||
index: obj._index,
|
index: obj._index,
|
||||||
peerId: this.p2p.peerId,
|
peerId: this.p2p.peerId,
|
||||||
myself: true,
|
myself: true,
|
||||||
temp
|
temp
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('store object', value.id)
|
console.log('store object', value.id)
|
||||||
|
|
||||||
this._pushToDb(value, () => {
|
this._pushToDb(value, () => {
|
||||||
// store record
|
// store record
|
||||||
this.p2p.emit('dbStore', value)
|
this.p2p.emit('dbStore', value)
|
||||||
})
|
})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async find(index)
|
async find(index)
|
||||||
{
|
{
|
||||||
const records = []
|
const records = []
|
||||||
await forBigTable(this.sphinx, 'store', (record) => records.push(record), null, 1000, `and match(${this.sphinx.escape(index)})`)
|
await forBigTable(this.sphinx, 'store', (record) => records.push(record), null, 1000, `and match(${this.sphinx.escape(index)})`)
|
||||||
return records.map( ({data, peerid}) => Object.assign(JSON.parse(data), { _peerId: peerid }) )
|
return records.map( ({data, peerid}) => Object.assign(JSON.parse(data), { _peerId: peerid }) )
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,85 +5,85 @@ const glob = require('glob')
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
//mode: 'production',
|
//mode: 'production',
|
||||||
entry: path.resolve("src/app/index.js"),
|
entry: path.resolve("src/app/index.js"),
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve('web'),
|
path: path.resolve('web'),
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: ["babel-loader"]
|
use: ["babel-loader"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: ["style-loader", "css-loader"]
|
use: ["style-loader", "css-loader"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
|
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
|
||||||
use: ['url-loader']
|
use: ['url-loader']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
inject: true,
|
inject: true,
|
||||||
template: 'app/app.html',
|
template: 'app/app.html',
|
||||||
minify: {
|
minify: {
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
removeRedundantAttributes: true,
|
removeRedundantAttributes: true,
|
||||||
useShortDoctype: true,
|
useShortDoctype: true,
|
||||||
removeEmptyAttributes: true,
|
removeEmptyAttributes: true,
|
||||||
removeStyleLinkTypeAttributes: true,
|
removeStyleLinkTypeAttributes: true,
|
||||||
keepClosingSlash: true,
|
keepClosingSlash: true,
|
||||||
minifyJS: true,
|
minifyJS: true,
|
||||||
minifyCSS: true,
|
minifyCSS: true,
|
||||||
minifyURLs: true,
|
minifyURLs: true,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({WEB: true}),
|
new webpack.DefinePlugin({WEB: true}),
|
||||||
// Generate a service worker script that will precache, and keep up to date,
|
// Generate a service worker script that will precache, and keep up to date,
|
||||||
// the HTML & assets that are part of the Webpack build.
|
// the HTML & assets that are part of the Webpack build.
|
||||||
new SWPrecacheWebpackPlugin({
|
new SWPrecacheWebpackPlugin({
|
||||||
// By default, a cache-busting query parameter is appended to requests
|
// By default, a cache-busting query parameter is appended to requests
|
||||||
// used to populate the caches, to ensure the responses are fresh.
|
// used to populate the caches, to ensure the responses are fresh.
|
||||||
// If a URL is already hashed by Webpack, then there is no concern
|
// If a URL is already hashed by Webpack, then there is no concern
|
||||||
// about it being stale, and the cache-busting can be skipped.
|
// about it being stale, and the cache-busting can be skipped.
|
||||||
dontCacheBustUrlsMatching: /\.\w{8}\./,
|
dontCacheBustUrlsMatching: /\.\w{8}\./,
|
||||||
filename: 'service-worker.js',
|
filename: 'service-worker.js',
|
||||||
logger(message) {
|
logger(message) {
|
||||||
if (message.indexOf('Total precache size is') === 0) {
|
if (message.indexOf('Total precache size is') === 0) {
|
||||||
// This message occurs for every build and is a bit too noisy.
|
// This message occurs for every build and is a bit too noisy.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (message.indexOf('Skipping static resource') === 0) {
|
if (message.indexOf('Skipping static resource') === 0) {
|
||||||
// This message obscures real errors so we ignore it.
|
// This message obscures real errors so we ignore it.
|
||||||
// https://github.com/facebookincubator/create-react-app/issues/2612
|
// https://github.com/facebookincubator/create-react-app/issues/2612
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(message);
|
console.log(message);
|
||||||
},
|
},
|
||||||
minify: true,
|
minify: true,
|
||||||
// For unknown URLs, fallback to the index page
|
// For unknown URLs, fallback to the index page
|
||||||
navigateFallback: 'index.html',
|
navigateFallback: 'index.html',
|
||||||
// Ignores URLs starting from /__ (useful for Firebase):
|
// Ignores URLs starting from /__ (useful for Firebase):
|
||||||
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
|
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
|
||||||
navigateFallbackWhitelist: [/^(?!\/__).*/],
|
navigateFallbackWhitelist: [/^(?!\/__).*/],
|
||||||
// Don't precache sourcemaps (they're large) and build asset manifest:
|
// Don't precache sourcemaps (they're large) and build asset manifest:
|
||||||
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
|
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
|
||||||
mergeStaticsConfig: true,
|
mergeStaticsConfig: true,
|
||||||
staticFileGlobs: glob.sync('public/images/**/*.*').concat(glob.sync('public/sounds/**/*.*')),
|
staticFileGlobs: glob.sync('public/images/**/*.*').concat(glob.sync('public/sounds/**/*.*')),
|
||||||
stripPrefix: 'public/',
|
stripPrefix: 'public/',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
node: {
|
node: {
|
||||||
dgram: 'empty',
|
dgram: 'empty',
|
||||||
fs: 'empty',
|
fs: 'empty',
|
||||||
net: 'empty',
|
net: 'empty',
|
||||||
tls: 'empty',
|
tls: 'empty',
|
||||||
},
|
},
|
||||||
};
|
};
|
@ -3,12 +3,12 @@ const webpack = require('webpack');
|
|||||||
|
|
||||||
let compiler = webpack(config);
|
let compiler = webpack(config);
|
||||||
compiler.run((err, stats) => {
|
compiler.run((err, stats) => {
|
||||||
if(err)
|
if(err)
|
||||||
throw new Error(err)
|
throw new Error(err)
|
||||||
|
|
||||||
|
|
||||||
if(stats.compilation.errors && stats.compilation.errors.length > 0)
|
if(stats.compilation.errors && stats.compilation.errors.length > 0)
|
||||||
console.error('compilation errors', stats.compilation.errors)
|
console.error('compilation errors', stats.compilation.errors)
|
||||||
else
|
else
|
||||||
console.log('succesfully builded web version')
|
console.log('succesfully builded web version')
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user