feat(downloading): ability to choose files which you wanna download

This commit is contained in:
Alexey Kasyanchuk 2018-08-28 04:20:48 +03:00
parent 3326bc2505
commit 0b329b8328
3 changed files with 155 additions and 12 deletions

View File

@ -7,6 +7,7 @@ import Subheader from 'material-ui/Subheader';
import {Tabs, Tab} from 'material-ui/Tabs'; import {Tabs, Tab} from 'material-ui/Tabs';
import ActionInfo from 'material-ui/svg-icons/action/info'; import ActionInfo from 'material-ui/svg-icons/action/info';
import RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import Toggle from 'material-ui/Toggle';
import FileFolder from 'material-ui/svg-icons/file/folder'; import FileFolder from 'material-ui/svg-icons/file/folder';
import NoImage from './images/no-image-icon.png' import NoImage from './images/no-image-icon.png'
@ -42,13 +43,23 @@ let buildFilesTree = (filesList) => {
filesList.forEach((file) => { filesList.forEach((file) => {
let pathTree = file.path.split('/'); let pathTree = file.path.split('/');
let currentItem = rootTree; let currentItem = rootTree;
pathTree.forEach((pathItem) => { pathTree.forEach((pathItem, index) => {
if(!(pathItem in currentItem)) if(!(pathItem in currentItem))
{
// крайний индекс, значит это объект файла, объединяем объекты
if(index === pathTree.length - 1)
{
file.__sizeBT = 0
file.__fileBT = true
currentItem[pathItem] = file
}
else
{ {
currentItem[pathItem] = { currentItem[pathItem] = {
__sizeBT: 0 __sizeBT: 0
} }
} }
}
currentItem = currentItem[pathItem] currentItem = currentItem[pathItem]
currentItem.__sizeBT += file.size; currentItem.__sizeBT += file.size;
}) })
@ -57,22 +68,59 @@ let buildFilesTree = (filesList) => {
return rootTree; return rootTree;
} }
const treeToTorrentFiles = (tree) => { const treeToTorrentFiles = (tree, torrent, toggles) => {
// toggles for button disable/enable torrent/directory in torrent client
if(toggles)
{
if(tree.__fileBT && typeof tree.downloadIndex !== 'undefined')
{
toggles.push({
downloadIndex: tree.downloadIndex,
selected: typeof tree.downloadSelected === 'undefined' || tree.downloadSelected
})
}
}
// this is already file, return
if(tree.__fileBT)
return
let arr = []; let arr = [];
for(let file in tree) for(let file in tree)
{ {
if(file == '__sizeBT') if(file == '__sizeBT')
continue; continue;
const newToggles = []
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], torrent, newToggles)}
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].__fileBT ? <FileFolder /> : contentIcon(fileTypeDetect({path: file}))}
rightToggle={
newToggles.length > 0
&&
<Toggle
toggled={newToggles.every( ({selected}) => selected )}
onToggle={(e, checked) => {
e.preventDefault()
e.stopPropagation()
let toggleValues = {}
newToggles.forEach(({downloadIndex}) => toggleValues[downloadIndex] = checked)
window.torrentSocket.emit('downloadSelectFiles', torrent, toggleValues)
}}
/>}
/>); />);
if(toggles)
{
for(const newToggle of newToggles)
toggles.push(newToggle)
}
} }
return arr; return arr;
} }
@ -87,7 +135,7 @@ const TorrentFiles = (props) => {
? ?
<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, {hash: props.torrent.hash})}
</div> </div>
: :
<div className='column center'> <div className='column center'>
@ -221,10 +269,19 @@ export default class TorrentPage extends Page {
componentDidMount() { componentDidMount() {
super.componentDidMount(); super.componentDidMount();
this.filesUpdated = (hash) => { this.filesUpdated = (hash, filesList) => {
if(this.props.hash != hash) if(this.props.hash != hash)
return; return;
if(filesList)
{
if(this.torrent)
{
this.torrent.filesList = filesList
this.forceUpdate()
}
}
else
this.getTorrentInfo(); this.getTorrentInfo();
} }
window.torrentSocket.on('filesReady', this.filesUpdated); window.torrentSocket.on('filesReady', this.filesUpdated);

View File

@ -57,6 +57,7 @@ module.exports = async ({
removeOnDone: download.removeOnDone, removeOnDone: download.removeOnDone,
paused: torrent.paused || torrent._paused paused: torrent.paused || torrent._paused
} }
torrent.filesList = download.files.length > 0 ? downloadFilesList(download) : torrent.filesList
} }
} }
@ -81,6 +82,14 @@ module.exports = async ({
Fn(...rest, (data) => callback(mergeTorrentsWithDownloads(data, copy))) Fn(...rest, (data) => callback(mergeTorrentsWithDownloads(data, copy)))
} }
const downloadFilesList = (torrent) => torrent.files.map((file, index) => ({
path: file.path.replace(/\\/g, '/'),
size: file.length,
downloadIndex: index,
downloadSelected: file.selected
}))
recive('recentTorrents', function(callback) recive('recentTorrents', function(callback)
{ {
if(typeof callback != 'function') if(typeof callback != 'function')
@ -692,6 +701,7 @@ module.exports = async ({
delete torrent._paused delete torrent._paused
torrent._pause() torrent._pause()
} }
send('filesReady', torrent.infoHash, downloadFilesList(torrent))
}) })
torrent.on('done', () => { torrent.on('done', () => {
@ -762,6 +772,49 @@ module.exports = async ({
return _destroy.call(torrent, ...args) return _destroy.call(torrent, ...args)
} }
torrent.selectFiles = (selection) => {
if(Array.isArray(selection))
{
if(selection.length !== torrent.files.length)
{
logTE('downloader', 'selection map not full', torrent.files.length, selection.length)
return
}
for(let i = 0; i < selection.length; i++)
{
torrent.files[i].selected = !!selection[i]
}
}
else
{
for(let fileId in selection)
{
fileId = parseInt(fileId)
if(fileId >= torrent.files.length)
{
logTE('downloader', 'selection map wrong', selection)
return
}
torrent.files[fileId].selected = !!selection[fileId]
}
}
torrent.updateFilesSelection()
}
torrent.updateFilesSelection = () => {
torrent.deselect(0, torrent.pieces.length - 1, false)
for(const file of torrent.files)
{
const {selected} = file
if(typeof selected === 'undefined' || selected)
file.select()
else
file.deselect()
}
logT('downloader', 'selection updated')
}
if(callback) if(callback)
callback(true) callback(true)
@ -834,6 +887,31 @@ module.exports = async ({
}) })
}) })
recive('downloadSelectFiles', ({hash}, files, callback) =>
{
logT('downloader', 'call update selection', hash, files.length)
const id = torrentClientHashMap[hash]
if(!id)
{
logT('downloader', 'cant find torrent for selection', hash)
if(callback)
callback(false)
return
}
const torrent = torrentClient.get(id)
if(!torrent) {
logT('downloader', 'no torrent for selection founded')
return
}
torrent.selectFiles(files)
send('filesReady', torrent.infoHash, downloadFilesList(torrent))
if(callback)
callback(true)
})
recive('downloads', (callback) => recive('downloads', (callback) =>
{ {
callback(torrentClient.torrents.map(torrent => ({ callback(torrentClient.torrents.map(torrent => ({

View File

@ -10,7 +10,8 @@ torrentClient.saveSession = (sessionFile) => {
torrent: torrent.torrentObject, torrent: torrent.torrentObject,
removeOnDone: torrent.removeOnDone, removeOnDone: torrent.removeOnDone,
paused: torrent.paused || torrent._paused paused: torrent.paused || torrent._paused,
selection: torrent.files.map(file => typeof file.selected === 'undefined' || file.selected)
})) }))
}, null, 4), 'utf8'); }, null, 4), 'utf8');
} }
@ -34,7 +35,7 @@ torrentClient.loadSession = (sessionFile) => {
return return
} }
const {torrents} = obj const {torrents} = obj
torrents.forEach(({torrent, infoHash, path, removeOnDone, paused}) => { torrents.forEach(({torrent, infoHash, path, removeOnDone, paused, selection}) => {
if(!torrent || !infoHash || !path) if(!torrent || !infoHash || !path)
{ {
logT('downloader', 'no info for starting download this torrent') logT('downloader', 'no info for starting download this torrent')
@ -51,6 +52,13 @@ torrentClient.loadSession = (sessionFile) => {
{ {
download._paused = true download._paused = true
} }
if(selection)
{
download.on('metadata', () => {
logT('downloader', 'load torrent selection from session')
download.selectFiles(selection)
})
}
} }
}) })
} }