Started working on the tabs, added selection background for filters, started expanding Storage options
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
@@ -13,7 +12,7 @@ import (
|
||||
//Message contains the JSON messages from the client, we first unmarshal to get the messagetype, then each module unmarshalls the actual message once we know the type
|
||||
type Message struct {
|
||||
MessageType string
|
||||
Payload json.RawMessage
|
||||
Payload []string
|
||||
}
|
||||
|
||||
//GenericPayload is for any request to the server that only requires the TorrentHashString for matching (which is a lot of requests)
|
||||
@@ -49,9 +48,9 @@ type TorrentFileList struct {
|
||||
|
||||
//PeerFileList returns a slice of peers
|
||||
type PeerFileList struct {
|
||||
MessageType string
|
||||
TotalPeers int
|
||||
PeerList []torrent.Peer
|
||||
MessageType string `json:"MessageType"`
|
||||
TotalPeers int `json:"TotalPeers"`
|
||||
PeerList []torrent.Peer `json:"PeerList"`
|
||||
}
|
||||
|
||||
//ClientDB struct contains the struct that is used to compose the torrentlist
|
||||
@@ -69,14 +68,15 @@ type ClientDB struct {
|
||||
TorrentHashString string `json:"TorrentHashString"`
|
||||
PercentDone string `json:"PercentDone"`
|
||||
TorrentHash metainfo.Hash
|
||||
StoragePath string `json:"StorageLocation"`
|
||||
StoragePath string `json:"StoragePath"`
|
||||
DateAdded string
|
||||
KnownSwarm []torrent.Peer
|
||||
Status string `json:"Status"`
|
||||
BytesCompleted int64
|
||||
UpdatedAt time.Time
|
||||
UploadRatio string
|
||||
AddedAt string
|
||||
ETA string `json:"ETA"`
|
||||
Label string
|
||||
SourceLocation string
|
||||
SourceType string `json:"SourceType"`
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package engine //main file for all the calculations and data gathering needed fo
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
@@ -11,7 +12,7 @@ import (
|
||||
Storage "github.com/deranjer/goTorrent/storage"
|
||||
)
|
||||
|
||||
func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted bool) { //forcing a timeout of the torrent if it doesn't load
|
||||
func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted bool) { //forcing a timeout of the torrent if it doesn't load from program restart
|
||||
timeout := make(chan bool, 1) //creating a timeout channel for our gotinfo
|
||||
go func() {
|
||||
time.Sleep(seconds * time.Second)
|
||||
@@ -19,7 +20,7 @@ func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted
|
||||
}()
|
||||
select {
|
||||
case <-clientTorrent.GotInfo(): //attempting to retrieve info for torrent
|
||||
fmt.Println("Recieved torrent info for...", clientTorrent.Name())
|
||||
//fmt.Println("Recieved torrent info for...", clientTorrent.Name())
|
||||
clientTorrent.DownloadAll()
|
||||
return false
|
||||
case <-timeout: // getting info for torrent has timed out so purging the torrent
|
||||
@@ -30,7 +31,7 @@ func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted
|
||||
|
||||
}
|
||||
|
||||
//StartTorrent creates the storage.db entry and starts the torrent and adds to the running torrent array
|
||||
//StartTorrent creates the storage.db entry and starts A NEW TORRENT and adds to the running torrent array
|
||||
func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage *Storage.TorrentLocal, torrentDbStorage *bolt.DB, dataDir string, torrentFile string, torrentFileName string) {
|
||||
|
||||
timeOutInfo(clientTorrent, 45) //seeing if adding the torrrent times out (giving 45 seconds)
|
||||
@@ -88,7 +89,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
if len(PreviousTorrentArray) > 0 { //if we actually have a previous array
|
||||
for _, previousElement := range PreviousTorrentArray {
|
||||
TempHash := singleTorrent.InfoHash()
|
||||
if previousElement.TorrentHashString == TempHash.AsString() { //matching previous to new
|
||||
if previousElement.TorrentHashString == TempHash.String() { //matching previous to new
|
||||
CalculateTorrentSpeed(singleTorrent, fullClientDB, previousElement)
|
||||
}
|
||||
}
|
||||
@@ -103,6 +104,17 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
var TempHash metainfo.Hash
|
||||
TempHash = singleTorrent.InfoHash()
|
||||
|
||||
singleTorrentStorageInfo := Storage.FetchTorrentFromStorage(db, []byte(TempHash.String())) //fetching all the info from the database
|
||||
var torrentTypeTemp string
|
||||
torrentTypeTemp = singleTorrentStorageInfo.TorrentType //either "file" or "magnet" maybe more in the future
|
||||
if torrentTypeTemp == "file" {
|
||||
fullClientDB.SourceType = "Torrent file"
|
||||
} else {
|
||||
fullClientDB.SourceType = "Magnet Link"
|
||||
}
|
||||
|
||||
fullClientDB.StoragePath = singleTorrentStorageInfo.StoragePath
|
||||
|
||||
fullClientDB.DownloadedSize = dSize
|
||||
fullClientDB.Size = tSize
|
||||
PercentDone := fmt.Sprintf("%.2f", bytesCompletedMB/totalSizeMB)
|
||||
@@ -111,12 +123,19 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
fullClientDB.DataBytesRead = fullStruct.ConnStats.DataBytesRead
|
||||
fullClientDB.DataBytesWritten = fullStruct.ConnStats.DataBytesWritten
|
||||
fullClientDB.ActivePeers = activePeersString + " / (" + totalPeersString + ")"
|
||||
fullClientDB.TorrentHashString = TempHash.AsString()
|
||||
fullClientDB.TorrentHashString = TempHash.String()
|
||||
fullClientDB.StoragePath = element.StoragePath
|
||||
fullClientDB.TorrentName = element.TorrentName
|
||||
fullClientDB.DateAdded = element.DateAdded
|
||||
fullClientDB.BytesCompleted = singleTorrent.BytesCompleted()
|
||||
CalculateTorrentETA(singleTorrent, fullClientDB) //calculating the ETA for the torrent
|
||||
|
||||
fullClientDB.UploadRatio = CalculateUploadRatio(singleTorrent, fullClientDB, db) //calculate the upload ratio
|
||||
tickUpdateStruct := Storage.TorrentLocal{} //we are shoving the tick updates into a torrentlocal struct to pass to storage
|
||||
tickUpdateStruct.UploadRatio = fullClientDB.UploadRatio
|
||||
tickUpdateStruct.UploadedBytes = fullClientDB.DataBytesWritten
|
||||
tickUpdateStruct.Hash = fullClientDB.TorrentHashString
|
||||
Storage.UpdateStorageTick(db, tickUpdateStruct)
|
||||
//fmt.Println("Download Speed: ", fullClientDB.DownloadSpeed)
|
||||
//fmt.Println("Percent Done: ", fullClientDB.PercentDone)
|
||||
//tclient.WriteStatus(os.Stdout)
|
||||
@@ -125,7 +144,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
RunningTorrentArray = append(RunningTorrentArray, *fullClientDB)
|
||||
|
||||
}
|
||||
fmt.Println("RunningTorrentArrayCreated...")
|
||||
//fmt.Println("RunningTorrentArrayCreated...")
|
||||
return RunningTorrentArray
|
||||
}
|
||||
|
||||
@@ -134,8 +153,8 @@ func CreateFileListArray(tclient *torrent.Client, selectedHash string) TorrentFi
|
||||
runningTorrents := tclient.Torrents() //don't need running torrent array since we aren't adding or deleting from storage
|
||||
TorrentFileListSelected := TorrentFileList{}
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
tempHash := singleTorrent.InfoHash()
|
||||
if tempHash.AsString() == selectedHash { // if our selection hash equals our torrent hash
|
||||
tempHash := singleTorrent.InfoHash().String()
|
||||
if tempHash == selectedHash { // if our selection hash equals our torrent hash
|
||||
TorrentFileListSelected.FileList = singleTorrent.Files()
|
||||
TorrentFileListSelected.MessageType = "torrentFileList"
|
||||
TorrentFileListSelected.TotalFiles = len(singleTorrent.Files())
|
||||
@@ -149,20 +168,18 @@ func CreateFileListArray(tclient *torrent.Client, selectedHash string) TorrentFi
|
||||
//CreatePeerListArray create a list of peers for the torrent and displays them
|
||||
func CreatePeerListArray(tclient *torrent.Client, selectedHash string) PeerFileList {
|
||||
runningTorrents := tclient.Torrents()
|
||||
|
||||
fmt.Println("Hash String", selectedHash)
|
||||
TorrentPeerList := PeerFileList{}
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
tempHash := singleTorrent.InfoHash()
|
||||
if tempHash.AsString() == selectedHash {
|
||||
tempHash := singleTorrent.InfoHash().String()
|
||||
if (strings.Compare(tempHash, selectedHash)) == 0 {
|
||||
TorrentPeerList.MessageType = "torrentPeerList"
|
||||
TorrentPeerList.TotalPeers = len(TorrentPeerList.PeerList)
|
||||
TorrentPeerList.PeerList = singleTorrent.KnownSwarm()
|
||||
TorrentPeerList.TotalPeers = len(TorrentPeerList.PeerList)
|
||||
return TorrentPeerList
|
||||
break //only looking for one result
|
||||
}
|
||||
}
|
||||
return TorrentPeerList
|
||||
|
||||
}
|
||||
|
||||
//CreateTorrentDetailJSON creates the json response for a request for more torrent information
|
||||
@@ -174,8 +191,8 @@ func CreateTorrentDetailJSON(tclient *torrent.Client, selectedHash string, torre
|
||||
|
||||
TorrentDetailStruct := ClientDB{}
|
||||
for _, singleTorrent := range runningTorrents { //ranging through the running torrents to find the one we are looking for
|
||||
tempHash := singleTorrent.InfoHash()
|
||||
if tempHash.AsString() == selectedHash {
|
||||
tempHash := singleTorrent.InfoHash().String()
|
||||
if tempHash == selectedHash {
|
||||
fmt.Println("CreateTorrentDetail", localTorrentInfo)
|
||||
return TorrentDetailStruct
|
||||
break //only looking for one result
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
func secondsToMinutes(inSeconds int64) string {
|
||||
@@ -46,7 +47,7 @@ func ConvertSizetoGB(t float32, d float32) (tDelta string, dDelta string) { //co
|
||||
}
|
||||
}
|
||||
|
||||
//CalculateTorrentSpeed is used to calculate the torrent upload and download speed over time
|
||||
//CalculateTorrentSpeed is used to calculate the torrent upload and download speed over time c is current clientdb, oc is last client db to calculate speed over time
|
||||
func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) {
|
||||
now := time.Now()
|
||||
bytes := t.BytesCompleted()
|
||||
@@ -89,6 +90,16 @@ func CalculateTorrentETA(t *torrent.Torrent, c *ClientDB) {
|
||||
}
|
||||
}
|
||||
|
||||
func CalculateUploadRatio(t *torrent.Torrent, c *ClientDB, db *bolt.DB) string {
|
||||
if c.DataBytesWritten > 0 {
|
||||
uploadRatioTemp := c.DataBytesRead / c.DataBytesWritten
|
||||
uploadRatio := fmt.Sprintf("%.2f", uploadRatioTemp)
|
||||
return uploadRatio
|
||||
}
|
||||
uploadRatio := fmt.Sprintf("%.2f", 0.00) //we haven't uploaded anything so no upload ratio
|
||||
return uploadRatio
|
||||
}
|
||||
|
||||
//CalculateTorrentStatus is used to determine what the STATUS column of the frontend will display ll2
|
||||
func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB) {
|
||||
if t.Seeding() && t.Stats().ActivePeers > 0 && t.BytesMissing() == 0 {
|
||||
|
48
main.go
48
main.go
@@ -12,12 +12,11 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
Engine "github.com/deranjer/goTorrent/engine"
|
||||
Storage "github.com/deranjer/goTorrent/storage"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -129,7 +128,7 @@ func main() {
|
||||
fmt.Println("Unable to read JSON client message", err)
|
||||
}
|
||||
|
||||
fmt.Println("MessageType", msg.MessageType)
|
||||
//fmt.Println("MessageFull", msg)
|
||||
switch msg.MessageType { //first handling data requests
|
||||
|
||||
case "torrentListRequest":
|
||||
@@ -141,6 +140,7 @@ func main() {
|
||||
torrentlistArray.MessageType = "torrentList"
|
||||
torrentlistArray.ClientDBstruct = RunningTorrentArray
|
||||
torrentlistArray.Totaltorrents = len(RunningTorrentArray)
|
||||
//fmt.Println("%+v\n", PreviousTorrentArray)
|
||||
//fmt.Printf("%+v\n", torrentlistArray)
|
||||
conn.WriteJSON(torrentlistArray)
|
||||
break
|
||||
@@ -148,23 +148,30 @@ func main() {
|
||||
|
||||
case "torrentFileListRequest": //client requested a filelist update
|
||||
fmt.Println("client Requested Filelist update")
|
||||
fileListRequest := Engine.GenericPayload{}
|
||||
json.Unmarshal(msg.Payload, &fileListRequest) //unmarshal into the generic payload
|
||||
FileListArray := Engine.CreateFileListArray(tclient, fileListRequest.TorrentHashString)
|
||||
FileListArray := Engine.CreateFileListArray(tclient, msg.Payload[0])
|
||||
conn.WriteJSON(FileListArray) //writing the JSON to the client
|
||||
break
|
||||
|
||||
case "torrentDetailedInfo": //TODO Figure out how to get single torrent info correctly
|
||||
fmt.Println("client requested detailed Torrent Info")
|
||||
torrentDetailRequest := Engine.GenericPayload{}
|
||||
json.Unmarshal(msg.Payload, &torrentDetailRequest)
|
||||
torrentDetailArray := Engine.CreateTorrentDetailJSON(tclient, torrentDetailRequest.TorrentHashString, db)
|
||||
|
||||
torrentDetailArray := Engine.CreateTorrentDetailJSON(tclient, msg.Payload[0], db)
|
||||
conn.WriteJSON(torrentDetailArray)
|
||||
break
|
||||
|
||||
case "torrentPeerListRequest":
|
||||
fmt.Println("client requested peer list")
|
||||
torrentPeerList := Engine.CreatePeerListArray(tclient, msg.Payload[0])
|
||||
//fmt.Printf("%+v\n", torrentPeerList)
|
||||
//JSONTEST, _ := json.Marshal(torrentPeerList)
|
||||
//fmt.Println(JSONTEST)
|
||||
|
||||
conn.WriteJSON(torrentPeerList)
|
||||
break
|
||||
|
||||
case "magnetLinkSubmit": //if we detect a magnet link we will be adding a magnet torrent
|
||||
magnetMessage := Engine.MagnetMessage{} //grabbing a magnetMessage struct from engine->clientstructs
|
||||
json.Unmarshal(msg.Payload, &magnetMessage) //unmarshalling the "Payload" from Message into our magnetmessage struct
|
||||
json.Unmarshal([]byte(msg.Payload[0]), &magnetMessage) //unmarshalling the "Payload" from Message into our magnetmessage struct
|
||||
clientTorrent, err := tclient.AddMagnet(magnetMessage.MagnetLink) //reading the payload into the torrent client
|
||||
if err != nil {
|
||||
fmt.Println("Magnet Error", err)
|
||||
@@ -177,11 +184,10 @@ func main() {
|
||||
|
||||
case "stopTorrents":
|
||||
TorrentListCommands := Engine.TorrentCommandMessage{}
|
||||
json.Unmarshal(msg.Payload, &TorrentListCommands)
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
|
||||
for _, singleSelection := range TorrentListCommands.TorrentHashStrings {
|
||||
if singleTorrent.InfoHash().AsString() == singleSelection {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
fmt.Println("Matched for stopping torrents")
|
||||
//singleTorrent.Drop()
|
||||
}
|
||||
@@ -190,12 +196,10 @@ func main() {
|
||||
break
|
||||
|
||||
case "deleteTorrents":
|
||||
TorrentListCommands := Engine.TorrentCommandMessage{}
|
||||
json.Unmarshal(msg.Payload, &TorrentListCommands)
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
|
||||
for _, singleSelection := range TorrentListCommands.TorrentHashStrings {
|
||||
if singleTorrent.InfoHash().AsString() == singleSelection {
|
||||
for _, singleSelection := range msg.Payload {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
fmt.Println("Matched for deleting torrents")
|
||||
singleTorrent.Drop()
|
||||
}
|
||||
@@ -204,14 +208,12 @@ func main() {
|
||||
break
|
||||
|
||||
case "startTorrents":
|
||||
fmt.Println("Starting torrents")
|
||||
TorrentListCommands := Engine.TorrentCommandMessage{}
|
||||
json.Unmarshal(msg.Payload, &TorrentListCommands)
|
||||
fmt.Println("Starting torrents", msg.Payload)
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
|
||||
for _, singleSelection := range TorrentListCommands.TorrentHashStrings {
|
||||
if singleTorrent.InfoHash().AsString() == singleSelection {
|
||||
fmt.Println("Matched for starting torrents")
|
||||
for _, singleSelection := range msg.Payload {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
fmt.Println("Matched for starting torrents", singleSelection)
|
||||
singleTorrent.DownloadAll()
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,12 +1,14 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
binary "encoding/binary"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
//TODO, this entire file need to be rewritten to encode and decode from the struct
|
||||
//TorrentLocal is local storage of the torrents for readd on server restart
|
||||
type TorrentLocal struct {
|
||||
Hash string
|
||||
@@ -17,6 +19,9 @@ type TorrentLocal struct {
|
||||
TorrentType string //magnet or .torrent file
|
||||
TorrentFileName string
|
||||
Label string //for labeling torrent files
|
||||
UploadedBytes int64
|
||||
DownloadedBytes int64 //TODO not sure if needed since we should have the file which contains the bytes
|
||||
UploadRatio string
|
||||
}
|
||||
|
||||
//ReadInTorrents is called to read in ALL local stored torrents in the boltdb database (called on server restart)
|
||||
@@ -121,6 +126,10 @@ func AddTorrentLocalStorage(torrentStorage *bolt.DB, local *TorrentLocal) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("UploadRatio"), []byte(local.UploadRatio))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -139,7 +148,26 @@ func DelTorrentLocalStorage(torrentStorage *bolt.DB, local *TorrentLocal) {
|
||||
|
||||
}
|
||||
|
||||
//FetchTorrentFromStorage grabs the localtorrent info from the bolt database for usage found my torrenthash
|
||||
//UpdateStorageTick updates the values in boltdb that should update on every tick (like uploadratio or uploadedbytes, not downloaded since we should have the actual file)
|
||||
func UpdateStorageTick(torrentStorage *bolt.DB, torrentLocal TorrentLocal) {
|
||||
UploadedBytes := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(UploadedBytes, uint64(torrentLocal.UploadedBytes)) //converting int64 into byte slice for storage
|
||||
selectedHash := []byte(torrentLocal.Hash)
|
||||
torrentStorage.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(selectedHash)
|
||||
err := b.Put([]byte("UploadRatio"), []byte(torrentLocal.UploadRatio))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("UploadedBytes"), []byte(UploadedBytes))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
//FetchTorrentFromStorage grabs the localtorrent info from the bolt database for usage found by torrenthash
|
||||
func FetchTorrentFromStorage(torrentStorage *bolt.DB, selectedHash []byte) TorrentLocal {
|
||||
singleTorrentInfo := TorrentLocal{}
|
||||
torrentStorage.View(func(tx *bolt.Tx) error {
|
||||
|
@@ -1,65 +1,94 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from '../store/actions';
|
||||
|
||||
import ReactTooltip from 'react-tooltip'
|
||||
|
||||
import BackendIcon from 'material-ui-icons/InfoOutline';
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from '../store/actions';
|
||||
import Select from 'material-ui/Select/Select';
|
||||
|
||||
|
||||
var title = document.title; //Set the number of active torrents in the title
|
||||
let torrents= [];
|
||||
|
||||
let peerList = [];
|
||||
|
||||
var torrentListRequest = {
|
||||
messageType: "torrentListRequest"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//websocket is started in kickwebsocket.js and is picked up here so "ws" is already defined 22
|
||||
ws.onmessage = function (evt) { //When we recieve a message from the websocket
|
||||
var serverMessage = JSON.parse(evt.data)
|
||||
if (serverMessage.MessageType == "torrentList"){
|
||||
console.log("Recieved Client Update...")
|
||||
//var serverMessage = JSON.parse(evt.data);
|
||||
|
||||
torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding)
|
||||
for(var i = 0; i < serverMessage.total; i++){
|
||||
torrents.push({
|
||||
TorrentHashString: serverMessage.data[i].TorrentHash,
|
||||
TorrentName: serverMessage.data[i].TorrentName,
|
||||
DownloadedSize: serverMessage.data[i].DownloadedSize,
|
||||
Size: serverMessage.data[i].Size,
|
||||
DownloadSpeed: serverMessage.data[i].DownloadSpeed,
|
||||
UploadSpeed: serverMessage.data[i].UploadSpeed,
|
||||
PercentDone: serverMessage.data[i].PercentDone,
|
||||
StoragePath: serverMessage.data[i].StoragePath,
|
||||
DateAdded: serverMessage.data[i].DateAdded,
|
||||
Status: serverMessage.data[i].Status,
|
||||
BytesCompleted: serverMessage.data[i].BytesCompleted,
|
||||
ActivePeers: serverMessage.data[i].ActivePeers,
|
||||
ETA: serverMessage.data[i].ETA,
|
||||
})
|
||||
}
|
||||
var newTitle = '(' + serverMessage.total + ')' + title; //updating the title
|
||||
document.title = newTitle;
|
||||
//console.log("message", serverMessage.MessageType)
|
||||
switch (serverMessage.MessageType) {
|
||||
|
||||
case "torrentList":
|
||||
//console.log("Recieved Client Update...", serverMessage)
|
||||
//var serverMessage = JSON.parse(evt.data);
|
||||
|
||||
} else if (serverMessage.MessageType == "fileList"){
|
||||
console.log("Recieved FileListUpdate", serverMessage.fileList)
|
||||
fileList = [];
|
||||
for (var i = 0; i < serverMessage.total; i++){
|
||||
fileList.push({
|
||||
FileList: serverMessage.fileList[i]
|
||||
torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding)
|
||||
for(var i = 0; i < serverMessage.total; i++){
|
||||
torrents.push({
|
||||
TorrentHashString: serverMessage.data[i].TorrentHashString,
|
||||
TorrentName: serverMessage.data[i].TorrentName,
|
||||
DownloadedSize: serverMessage.data[i].DownloadedSize,
|
||||
Size: serverMessage.data[i].Size,
|
||||
DownloadSpeed: serverMessage.data[i].DownloadSpeed,
|
||||
UploadSpeed: serverMessage.data[i].UploadSpeed,
|
||||
PercentDone: serverMessage.data[i].PercentDone,
|
||||
StoragePath: serverMessage.data[i].StoragePath,
|
||||
DateAdded: serverMessage.data[i].DateAdded,
|
||||
Status: serverMessage.data[i].Status,
|
||||
BytesCompleted: serverMessage.data[i].BytesCompleted,
|
||||
ActivePeers: serverMessage.data[i].ActivePeers,
|
||||
ETA: serverMessage.data[i].ETA,
|
||||
Ratio: serverMessage.data[i].Ratio,
|
||||
})
|
||||
}
|
||||
var newTitle = '(' + serverMessage.total + ')' + title; //updating the title
|
||||
document.title = newTitle;
|
||||
break;
|
||||
|
||||
case "torrentPeerList":
|
||||
console.log("Full EVENT", evt.data)
|
||||
peerList = []; //clearing out the peerlist array to make room for new (so that it does keep adding)
|
||||
|
||||
for(var i = 0; i < serverMessage.TotalPeers; i++){
|
||||
peerList.push({
|
||||
PeerID: serverMessage.PeerList[i].Id.toString(),
|
||||
IP: serverMessage.PeerList[i].IP,
|
||||
Port: serverMessage.PeerList[i].Port,
|
||||
Source: serverMessage.PeerList[i].Source,
|
||||
SupportsEncryption: serverMessage.PeerList[i].SupportsEncryption.toString(),
|
||||
})
|
||||
}
|
||||
console.log("Peerlist", peerList)
|
||||
break
|
||||
|
||||
case "torrentFileList":
|
||||
console.log("Recieved FileListUpdate", serverMessage.fileList)
|
||||
fileList = [];
|
||||
for (var i = 0; i < serverMessage.total; i++){
|
||||
fileList.push({
|
||||
fileList: serverMessage.fileList[i]
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
case "speedTab":
|
||||
console.log("Speedtab data requested")
|
||||
break;
|
||||
|
||||
case "loggerData":
|
||||
console.log("Logger data requested")
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -82,7 +111,45 @@ var buttonStyle ={
|
||||
|
||||
class BackendSocket extends React.Component {
|
||||
|
||||
|
||||
|
||||
selectionHandler = (selectionHashes, selectedTab) => {
|
||||
switch (selectedTab) {
|
||||
case 0:
|
||||
console.log("general tab information requested")
|
||||
break;
|
||||
case 1:
|
||||
let peerListHashes = {
|
||||
MessageType: "torrentPeerListRequest",
|
||||
Payload: selectionHashes,
|
||||
}
|
||||
//console.log("Peers tab information requested", peerListHashes)
|
||||
ws.send(JSON.stringify(peerListHashes))
|
||||
break;
|
||||
case 2:
|
||||
console.log("Files tab information requested")
|
||||
break;
|
||||
case 3:
|
||||
console.log("Speed tab information requested")
|
||||
break;
|
||||
case 4:
|
||||
console.log("Logger tab information requested")
|
||||
break;
|
||||
default:
|
||||
console.log("default tab")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
testSelectionLength = (selection) => {
|
||||
if (nextProps.selectionHashes.length > 1){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
this.timerID = setInterval(
|
||||
() => this.tick(),
|
||||
@@ -95,11 +162,30 @@ class BackendSocket extends React.Component {
|
||||
clearInterval(this.timerID);
|
||||
}
|
||||
|
||||
tick() {
|
||||
tick() { // this tick is the main tick that updates ALL of the components that update on tick... which is a lot
|
||||
ws.send(JSON.stringify(torrentListRequest))//talking to the server to get the torrent list
|
||||
this.props.newTorrentList(torrents)
|
||||
console.log("Torrentlist", torrents)
|
||||
this.props.newTorrentList(torrents) //sending the list of torrents to torrentlist.js
|
||||
if (this.props.selectedTab === 1 && this.props.selectionHashes.length === 1){ //if we are on the peerlist tab dispatch a new peerlist
|
||||
let peerListHashes = {
|
||||
MessageType: "torrentPeerListRequest",
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
ws.send(JSON.stringify(peerListHashes))
|
||||
this.props.newPeerList(peerList)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
console.log("Lenght", nextProps.selectionHashes.length, "value", nextProps.selectionHashes)
|
||||
if (nextProps.selectionHashes.length === 1){ //if we have a selection pass it on for the tabs to verify
|
||||
this.selectionHandler(nextProps.selectionHashes, nextProps.selectedTab)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={divStyle}>
|
||||
@@ -116,6 +202,8 @@ class BackendSocket extends React.Component {
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
selectionHashes: state.selectionHashes,
|
||||
selectedTab: state.selectedTab,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -125,6 +213,7 @@ const mapStateToProps = state => {
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
newTorrentList: (torrentList) => dispatch({type: actionTypes.TORRENT_LIST, torrentList }),
|
||||
newPeerList: (peerList) => dispatch({type: actionTypes.PEER_LIST, peerList})
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,18 +1,107 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { withStyles } from 'material-ui/styles';
|
||||
import Paper from 'material-ui/Paper';
|
||||
import Grid from 'material-ui/Grid';
|
||||
|
||||
|
||||
|
||||
function GeneralTab(props) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
Here
|
||||
</div>
|
||||
);
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from '../../store/actions';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
marginTop: 0,
|
||||
},
|
||||
paper: {
|
||||
padding: 16,
|
||||
textAlign: 'left',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
floatRight: {
|
||||
float: 'right',
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
class GeneralTab extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedTorrent: []
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps = () => {
|
||||
//console.log("recieving props in generaltab", "TYPE", this.props.selectionHashes[Object.keys(this.props.selectionHashes)[0]])
|
||||
if (this.props.selectionHashes.length === 1) { //if one torrent is selected
|
||||
let selectionHashTemp = this.props.selectionHashes[Object.keys(this.props.selectionHashes)[0]]// extract out the hash of the single selection
|
||||
let selectedTorrentTemp = []
|
||||
this.props.torrentList.forEach(function(singleTorrent){
|
||||
if (singleTorrent.TorrentHashString === selectionHashTemp){
|
||||
selectedTorrentTemp = singleTorrent
|
||||
}
|
||||
})
|
||||
//selectedTorrentTemp = this.props.torrentList.filter(torrent => torrent.TorrentHashString === this.props.selectionHashes)
|
||||
console.log("SelectedTorrentTemp", selectedTorrentTemp)
|
||||
this.setState({ selectedTorrent: selectedTorrentTemp });
|
||||
} else {
|
||||
this.setState({ selectedTorrent: [] })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Grid container spacing={8}>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Paper className={classes.paper}>Torrent Name: <span className={classes.floatRight}>{this.state.selectedTorrent["TorrentName"]} </span></Paper>
|
||||
<Paper className={classes.paper}>Torrent Size: <span className={classes.floatRight}>{this.state.selectedTorrent["Size"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Storage Path: <span className={classes.floatRight}>{this.state.selectedTorrent["StoragePath"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Date Added: <span className={classes.floatRight}> {this.state.selectedTorrent["DateAdded"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Source Type: <span className={classes.floatRight}> {this.state.selectedTorrent["SourceType"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Label: <span className={classes.floatRight}> {this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Torrent Hash: <span className={classes.floatRight}> {this.state.selectedTorrent["TorrentHashString"]} </span> </Paper>
|
||||
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Paper className={classes.paper}>Status: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Percent Done: <span className={classes.floatRight}>{this.state.selectedTorrent["PercentDone"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Torrent DL Amount: <span className={classes.floatRight}>{this.state.selectedTorrent["DownloadedSize"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Total Upload Amount: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Seeding Ratio: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>ETA: <span className={classes.floatRight}>{this.state.selectedTorrent["ETA"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Status: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Paper className={classes.paper}>Status: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Torrent DL Amount: {this.state.selectedTorrent["DownloadedSize"]} </Paper>
|
||||
|
||||
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default GeneralTab
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
selectionHashes: state.selectionHashes,
|
||||
torrentList: state.torrentList,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps)(GeneralTab))
|
||||
|
69
torrent-project/src/BottomMenu/Tabs/peerTab.js
Normal file
69
torrent-project/src/BottomMenu/Tabs/peerTab.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
|
||||
|
||||
import {
|
||||
SortingState, LocalSorting, VirtualTableLayout, SelectionState,
|
||||
} from '@devexpress/dx-react-grid';
|
||||
|
||||
import {
|
||||
Grid, TableView, TableHeaderRow, PagingPanel, VirtualTableView, TableColumnResizing,
|
||||
DragDropContext, TableColumnReordering,
|
||||
} from '@devexpress/dx-react-grid-material-ui';
|
||||
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from '../../store/actions';
|
||||
|
||||
|
||||
class PeerTab extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { //rows are stored in redux they are sent over from the server
|
||||
columns: [
|
||||
{ name: 'PeerID', title: 'Peer ID' },
|
||||
{ name: 'IP', title: 'IP Address'},
|
||||
//{ name: 'Country', title: 'Country of Origin'}, //TODO map IP to country
|
||||
{ name: 'Port', title: 'Port'},
|
||||
{ name: 'Source', title: 'Source'}, //T=Tracker, I=Incoming, Hg=DHTGetPeers, Ha=DHTAnnouncePeer, X=PEX
|
||||
{ name: 'SupportsEncryption', title: 'Supports Encryption'},
|
||||
],
|
||||
sorting: [],
|
||||
columnOrder: ['PeerID', 'IP', 'Port', 'Source', 'SupportsEncryption'],
|
||||
columnWidths: {PeerID: 250, IP: 150, Port: 100, Source: 150, SupportsEncryption: 150},
|
||||
};
|
||||
|
||||
this.changeColumnOrder = columnOrder => this.setState({columnOrder});
|
||||
this.changeColumnWidths = columnWidths => this.setState({columnWidths});
|
||||
this.changeSorting = sorting => this.setState({sorting});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Grid rows={this.props.peerList} columns={this.state.columns}>
|
||||
<SortingState sorting={this.state.sorting} onSortingChange={this.changeSorting} />
|
||||
<LocalSorting />
|
||||
<DragDropContext />
|
||||
<TableView />
|
||||
<TableColumnResizing columnWidths={this.state.columnWidths} onColumnWidthsChange={this.changeColumnWidths}/>
|
||||
<TableColumnReordering order={this.state.columnOrder} onOrderChange={this.changeColumnOrder} />
|
||||
<TableHeaderRow allowSorting allowResizing allowDragging />
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
selectionHashes: state.selectionHashes,
|
||||
peerList: state.peerList,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(PeerTab)
|
@@ -5,6 +5,12 @@ import { withStyles } from 'material-ui/styles';
|
||||
import AppBar from 'material-ui/AppBar';
|
||||
import Tabs, { Tab } from 'material-ui/Tabs';
|
||||
import GeneralTab from './Tabs/generalTab';
|
||||
import PeerTab from './Tabs/peerTab';
|
||||
|
||||
|
||||
//Redux
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from '../store/actions'
|
||||
|
||||
function TabContainer(props) {
|
||||
return <div style={{ padding: 8 * 3 }}>{props.children}</div>;
|
||||
@@ -26,23 +32,21 @@ function TabContainer(props) {
|
||||
});
|
||||
|
||||
class BasicTabs extends React.Component {
|
||||
state = {
|
||||
value: 0,
|
||||
};
|
||||
|
||||
|
||||
handleChange = (event, value) => {
|
||||
this.setState({ value });
|
||||
//this.setState({ value });
|
||||
this.props.changeTab(value)
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { value } = this.state;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<div className="DragHandle"> {/* making the appbar draggable */}
|
||||
<AppBar position="static">
|
||||
<Tabs value={value} onChange={this.handleChange}>
|
||||
<Tabs value={this.props.selectedTab} onChange={this.handleChange}>
|
||||
<Tab label="General"/>
|
||||
<Tab label="Peers"/>
|
||||
<Tab label="Files"/>
|
||||
@@ -51,11 +55,11 @@ function TabContainer(props) {
|
||||
</Tabs>
|
||||
</AppBar>
|
||||
</div>
|
||||
{value === 0 && <TabContainer><GeneralTab /></TabContainer>}
|
||||
{value === 1 && <TabContainer>Peers</TabContainer>}
|
||||
{value === 2 && <TabContainer>Files</TabContainer>}
|
||||
{value === 3 && <TabContainer>Speed</TabContainer>}
|
||||
{value === 4 && <TabContainer>Logger</TabContainer>}
|
||||
{this.props.selectedTab === 0 && <TabContainer><GeneralTab /></TabContainer>}
|
||||
{this.props.selectedTab === 1 && <TabContainer><PeerTab /></TabContainer>}
|
||||
{this.props.selectedTab === 2 && <TabContainer>Files</TabContainer>}
|
||||
{this.props.selectedTab === 3 && <TabContainer>Speed</TabContainer>}
|
||||
{this.props.selectedTab === 4 && <TabContainer>Logger</TabContainer>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -65,4 +69,17 @@ function TabContainer(props) {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(BasicTabs);
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
selectedTab: state.selectedTab,
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
changeTab: (selectedTab) => dispatch({type: actionTypes.SELECTED_TAB, selectedTab }),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(BasicTabs));
|
@@ -48,9 +48,9 @@ class BasicLayout extends React.PureComponent {
|
||||
|
||||
var layout = [
|
||||
{i: 'a', x: 0, y: 0, w: 6, h: 1},
|
||||
{i: 'b', x: 0, y: 1, w: 1, h: 5},
|
||||
{i: 'b', x: 0, y: 1, w: 1, h: 7},
|
||||
{i: 'c', x: 1, y: 1, w: 5, h: 3, minW: 5, minH: 3},
|
||||
{i: 'd', x: 1, y: 2, w: 5, h: 2, minW: 5, minH: 1}
|
||||
{i: 'd', x: 1, y: 2, w: 5, h: 4, minW: 5, minH: 1}
|
||||
];
|
||||
this.state = { layout };
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ import AllTorrentsIcon from 'material-ui-icons/AllInclusive'
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from './store/actions';
|
||||
|
||||
|
||||
//TODO, clean up the goddamn variable names you are all over the place
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
@@ -28,6 +28,9 @@ const styles = theme => ({
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
color: 'red',
|
||||
},
|
||||
active: {
|
||||
backgroundColor: '#80b3ff',
|
||||
}
|
||||
});
|
||||
|
||||
@@ -35,46 +38,110 @@ const styles = theme => ({
|
||||
class SimpleList extends React.Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
const { classes } = this.props;
|
||||
this.state = {
|
||||
allTorrentsClass: classes.active,
|
||||
downloadingClass: '',
|
||||
seedingClass: '',
|
||||
activeTorrentsClass: '',
|
||||
completedTorrentsClass: '',
|
||||
allID: "All",
|
||||
downloadingID: "Downloading",
|
||||
seedingID: "Seeding",
|
||||
activeID: "Active",
|
||||
completedID: "Completed",
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
setFilter = (filterState) => {
|
||||
|
||||
setActiveElement = (listItem) => {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
setFilter = (filterState, id) => {
|
||||
const { classes } = this.props;
|
||||
filterState = [{columnName: 'Status', value: filterState}]
|
||||
this.props.changeFilter(filterState)//dispatch to redux
|
||||
console.log("Switching filters classes", id)
|
||||
switch (id){ //TODO.. there has to be a better fucking way to do this
|
||||
case "All":
|
||||
this.state.allTorrentsClass = classes.active
|
||||
this.state.downloadingClass = ''
|
||||
this.state.seedingClass = ''
|
||||
this.state.activeTorrentsClass = ''
|
||||
this.state.completedTorrentsClass = ''
|
||||
break
|
||||
case "Downloading":
|
||||
console.log("Downloading...")
|
||||
this.state.downloadingClass = classes.active
|
||||
this.state.allTorrentsClass = ''
|
||||
this.state.seedingClass = ''
|
||||
this.state.activeTorrentsClass = ''
|
||||
this.state.completedTorrentsClass = ''
|
||||
break
|
||||
case "Seeding":
|
||||
this.state.seedingClass = classes.active
|
||||
this.state.allTorrentsClass = ''
|
||||
this.state.downloadingClass = ''
|
||||
this.state.activeTorrentsClass = ''
|
||||
this.state.completedTorrentsClass = ''
|
||||
break
|
||||
case "Active":
|
||||
this.state.activeTorrentsClass = classes.active
|
||||
this.state.allTorrentsClass = ''
|
||||
this.state.downloadingClass = ''
|
||||
this.state.seedingClass = ''
|
||||
this.state.completedTorrentsClass = ''
|
||||
break
|
||||
case "Completed":
|
||||
this.state.completedTorrentsClass = classes.active
|
||||
this.state.allTorrentsClass = ''
|
||||
this.state.downloadingClass = ''
|
||||
this.state.seedingClass = ''
|
||||
this.state.activeTorrentsClass = ''
|
||||
break
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<List>
|
||||
<ListItem button onClick={ () => this.setFilter('')}>
|
||||
<List dense>
|
||||
<ListItem dense className={this.state.allTorrentsClass} button onClick={ () => this.setFilter('', this.state.allID)}>
|
||||
<ListItemIcon className={classes.icons} >
|
||||
<AllTorrentsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="All Torrents" />
|
||||
</ListItem>
|
||||
<ListItem button={true} onClick={ () => this.setFilter('Downloading')}>
|
||||
<ListItem className={this.state.downloadingClass} button={true} onClick={ () => this.setFilter('Downloading', this.state.downloadingID)}>
|
||||
<ListItemIcon className={classes.icons}>
|
||||
<DownloadingTorrentsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Downloading Torrents" />
|
||||
</ListItem>
|
||||
<ListItem button={true} onClick={ () => this.setFilter('Seeding')}>
|
||||
<ListItem className={this.state.seedingClass} button={true} onClick={ () => this.setFilter('Seeding', this.state.seedingID)}>
|
||||
<ListItemIcon className={classes.icons}>
|
||||
<UploadingTorrentsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Uploading Torrents" />
|
||||
<ListItemText primary="Seeding Torrents" />
|
||||
</ListItem>
|
||||
<ListItem button={true} onClick={ () => this.setFilter('Active')}>
|
||||
<ListItem className={this.state.activeTorrentsClass} button={true} onClick={ () => this.setFilter('Active', this.state.activeID)}>
|
||||
<ListItemIcon className={classes.icons}>
|
||||
<ActiveTorrentsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Active Torrents" />
|
||||
</ListItem>
|
||||
<ListItem button={true} onClick={ () => this.setFilter('Completed')}>
|
||||
<ListItem className={this.state.completedTorrentsClass} button={true} onClick={ () => this.setFilter('Completed', this.state.completedID)}>
|
||||
<ListItemIcon className={classes.inactiveIcon}>
|
||||
<ActiveTorrentsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Inactive Torrents" />
|
||||
<ListItemText primary="Completed Torrents" />
|
||||
</ListItem>
|
||||
</List>
|
||||
<Divider />
|
||||
|
@@ -3,4 +3,6 @@ export const CHANGE_SELECTION = 'CHANGE_SELECTION';
|
||||
export const CHANGE_FILTER = 'CHANGE_FILTER';
|
||||
export const TORRENT_LIST = 'TORRENT_LIST';
|
||||
export const SET_BUTTON_STATE = 'BUTTON_STATE';
|
||||
|
||||
export const SELECTION_HASHES = 'SELECTION_HASHES';
|
||||
export const SELECTED_TAB = 'SELECTED_TAB';
|
||||
export const PEER_LIST = 'PEER_LIST';
|
||||
|
@@ -7,9 +7,13 @@ const initialState = {
|
||||
buttonState: [{startButton: "default", pauseButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default"}],
|
||||
sorting: [],
|
||||
selection: [],
|
||||
selectionHashes: [],
|
||||
filter: ["Status", ""],
|
||||
columnName: "Status",
|
||||
torrentList: [],
|
||||
peerList: [],
|
||||
torrentDetailInfo: [],
|
||||
selectedTab: 0,
|
||||
}
|
||||
|
||||
const reducer = (state = initialState, action) => {
|
||||
@@ -19,10 +23,19 @@ const reducer = (state = initialState, action) => {
|
||||
console.log("Change Selection", action.selection)
|
||||
return {
|
||||
...state,
|
||||
peerList: [], //changing selection will purge out all of the old data
|
||||
selectionHashes: [],
|
||||
selection: action.selection,
|
||||
};
|
||||
|
||||
case actionTypes.SORTLIST:
|
||||
case actionTypes.SELECTION_HASHES:
|
||||
console.log("Selection hashes REDUX", action.selectionHashes)
|
||||
return {
|
||||
...state,
|
||||
selectionHashes: action.selectionHashes,
|
||||
};
|
||||
|
||||
case actionTypes.SORTLIST: //TODO do I even need this in redux?
|
||||
console.log("List Sort", action.sorting)
|
||||
return state;
|
||||
|
||||
@@ -35,15 +48,26 @@ const reducer = (state = initialState, action) => {
|
||||
case actionTypes.TORRENT_LIST:
|
||||
return {
|
||||
...state,
|
||||
torrentList: action.torrentList
|
||||
torrentList: action.torrentList,
|
||||
};
|
||||
|
||||
case actionTypes.PEER_LIST:
|
||||
return {
|
||||
...state,
|
||||
peerList: action.peerList
|
||||
}
|
||||
|
||||
case actionTypes.SET_BUTTON_STATE:
|
||||
return {
|
||||
...state,
|
||||
buttonState: action.buttonState
|
||||
};
|
||||
|
||||
|
||||
case actionTypes.SELECTED_TAB:
|
||||
return {
|
||||
...state,
|
||||
selectedTab: action.selectedTab
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
|
@@ -68,15 +68,15 @@ class IconButtons extends React.Component {
|
||||
|
||||
}
|
||||
|
||||
startTorrentState = {
|
||||
messageType: "startTorrents",
|
||||
Payload: this.props.selection,
|
||||
}
|
||||
|
||||
|
||||
startTorrent = (selection) => {
|
||||
startTorrent = () => {
|
||||
console.log("Starting Torrents", selection)
|
||||
ws.send()
|
||||
let startTorrentHashes = {
|
||||
MessageType: "startTorrents",
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
//console.log("Peers tab information requested", peerListHashes)
|
||||
ws.send(JSON.stringify(startTorrentHashes))
|
||||
}
|
||||
|
||||
buttonHandler = (buttonState) => {
|
||||
@@ -138,6 +138,7 @@ const mapStateToProps = state => {
|
||||
return {
|
||||
buttonState: state.buttonState,
|
||||
selection: state.selection,
|
||||
selectionHashes: state.selectionHashes,
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -77,7 +77,17 @@ class TorrentListTable extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
determineButtonState = (selectedRows) => {
|
||||
determineSelectionHashes = (selectedRows) => {
|
||||
console.log("CurrentSelectionHashes", this.props.selectionHashes)
|
||||
let selectionHashes = [] //rebuilding our selection hashes from our currently selected rows
|
||||
selectedRows.forEach(element => {
|
||||
selectionHashes.push(element.TorrentHashString) //push the selection hash to the temp array
|
||||
})
|
||||
this.props.sendSelectionHashes(selectionHashes) //push the result to redux
|
||||
}
|
||||
|
||||
|
||||
determineButtonState = (selectedRows) => { //TODO run a filter to corrently determing button status... currently broken
|
||||
selectedRows.forEach(element => {
|
||||
if (element.Status === "Downloading" || "Awaiting Peers" || "Seeding") {
|
||||
let buttonState = [{startButton: "default", pauseButton: "primary", stopButton: "primary", deleteButton: "accent", fSeedButton: "default", fRecheckButton: "primary"}]
|
||||
@@ -92,16 +102,19 @@ class TorrentListTable extends React.Component {
|
||||
}
|
||||
|
||||
changeSelection = (selection) => {
|
||||
this.props.changeSelection(selection) //dispatch selection to redux
|
||||
this.props.changeSelection(selection) //dispatch selection to redux, also clear out anything tied to the old selection (peerlists, filelists, etc)
|
||||
|
||||
if (selection.length === 0) { //if selection is empty buttons will be default
|
||||
if (selection.length === 0) { //if selection is empty buttons will be default and selectionHashes will be blanked out and pushed to redux
|
||||
this.props.setButtonState(this.props.buttonStateDefault) //if no selection dispatch that to redux
|
||||
//let selectionHashes = []
|
||||
//this.props.sendSelectionHashes(selectionHashes) //clearning out selection hashes since we have nothing selected
|
||||
} else { // if we have selection continue on with logic to determine button state
|
||||
const selectedRows = [] //array of all the selected Rows
|
||||
selection.forEach(element => {
|
||||
selectedRows.push(this.props.torrentList[element]) //pushing the selected rows out of torrentlist
|
||||
});
|
||||
this.determineButtonState(selectedRows) //running a filter on the rows to determing buttonState
|
||||
this.determineSelectionHashes(selectedRows) //pulling the torrent hashes for the selcted rows
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,6 +163,7 @@ const mapStateToProps = state => {
|
||||
torrentList: state.torrentList,
|
||||
buttonState: state.buttonState,
|
||||
buttonStateDefault: state.buttonStateDefault, //all default
|
||||
selectionHashes: state.selectionHashes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,7 +171,8 @@ const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
changeSorting: (sorting) => dispatch({type: actionTypes.SORTLIST, sorting }),
|
||||
changeSelection: (selection) => dispatch({type: actionTypes.CHANGE_SELECTION, selection}),
|
||||
setButtonState: (buttonState) => dispatch({type: actionTypes.SET_BUTTON_STATE, buttonState})
|
||||
setButtonState: (buttonState) => dispatch({type: actionTypes.SET_BUTTON_STATE, buttonState}),
|
||||
sendSelectionHashes: (selectionHashes) => dispatch({type: actionTypes.SELECTION_HASHES, selectionHashes}),
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user