Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 53 additions & 10 deletions client/src/components/Home.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import Header from "./Header"
import SuperheroName from "./SuperheroName"
import SendFiles from "./SendFiles"
import Receive from './Receive';
import "../styles/button.css";
import "../styles/containers.css";
import WaitForBumpSender from './WaitForBumpSender'
import WaitForBumpReceiver from './WaitForBumpReceiver'
import React from 'react'
import { APIsend } from './ApiFetch'
import { APIrecv, APIsend } from './ApiFetch'

class Home extends React.Component {
constructor(props) {
Expand All @@ -19,6 +21,12 @@ class Home extends React.Component {
}
}

onReceiveButtonClick = () => {
this.setState({
appState: "WaitingToReceive",
});
}

/**
* Called by SendFiles when the user has pressed the "Send" button.
* @param link: Magnet link send by SendFiles
Expand Down Expand Up @@ -48,23 +56,58 @@ class Home extends React.Component {

APIsend(clientData);
}

/**
* Called by WaitForBumpReceiver when a BAM/Bump has been detected
* @param sensorData: Coordinates and Date received by WaitForBumpReceiver from db
*/
receiverBumpCallback = (sensorData) => {
console.log("Sender BAM!", sensorData);

// Build the API request body
const clientData = {
name: "Placeholder",
magnetLink: this.state.magnetLink,
coordinates: sensorData.coordinates,
date: sensorData.date,
}

APIrecv(clientData);
}

render() {
return (
<div className="App">
{this.state.appState == "Choosing" && <Header />}
{(this.state.appState == "Choosing" || this.state.appState == "WaitingToReceive") && <Header />}
{this.state.appState == "Choosing" && <SuperheroName />}

<SendFiles
client={this.state.client}
pressedSendButtonCallback={this.pressedSendButtonCallback}
/>

{(this.state.appState == "Choosing" || this.state.appState == "ReadyToSend") &&
<SendFiles
client={this.state.client}
pressedSendButtonCallback={this.pressedSendButtonCallback}
/>}

{this.state.appState == "ReadyToSend" && (
<WaitForBumpSender bumpCallback={this.senderBumpCallback} />
)}

{this.state.appState == "Choosing" && <Receive />}

{this.state.appState == "Choosing" && (
<button
type="button receive"
className="button receiveFilesButton"
onClick={this.onReceiveButtonClick}
>
RECEIVE FILES
</button>
)}

{this.state.appState == "WaitingToReceive" && (

<WaitForBumpReceiver
client={this.state.client}
bumpCallback={this.receiverBumpCallback} />
)}

</div>
);
}
Expand Down
5 changes: 5 additions & 0 deletions client/src/components/Receive.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const Receive = ({ torrent }) => {
let torrentId = response.magnetLink;
// https://webtorrent.io/docs
client.add(torrentId, function (torrent) {
while (torrent.progress != 1) {
console.log('Progress: ' + (torrent.progress * 100).toFixed(1) + '%')
setProgress((torrent.progress * 100).toFixed(1));
setInterval()
}
torrent.files.forEach(function (file) {
zip.file(file.path, Blob, { base64: true });
// temporary code. will be replaced with updating Parent Component torr state
Expand Down
18 changes: 12 additions & 6 deletions client/src/components/SendFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ class SendFiles extends React.Component {

// Populates pre component with file names
handleFile = (e) => {
// Creating html components
e.preventDefault()
const fileListContainer = document.getElementById('fileListContainer')
const fileList = document.getElementById('filelist')
const userFiles = document.getElementById('files').files
e.preventDefault()

// Loop through userFiles and set html data to each file name
fileList.innerHTML = ''
for (let i = 0; i < userFiles.length; i++) {
fileList.innerHTML += userFiles[i].name + '\n\n'
}

// If the list is empty, display nothing
// Else, display the html components
if (fileList.innerHTML === '' || fileList.innerHTML === null) {
fileList.style.display = 'none'
fileListContainer.style.display = 'none'
Expand All @@ -36,6 +41,7 @@ class SendFiles extends React.Component {
fileListContainer.style.display = 'flex'
}

// Set the current files state to userFiles
this.setState({
files: userFiles
});
Expand All @@ -45,9 +51,10 @@ class SendFiles extends React.Component {
* When the "Send Files" button is clicked, this function is called
*/
sendButtonClicked = () => {
// FILES TO SEND
// Files to send
console.log(this.state.files);
// CREATE TORRENT SEED
// Create torrent seed
console.log(this.state.client)
let returnMagnetLink = this.props.pressedSendButtonCallback;
this.state.client.seed(this.state.files, function (torrent) {
// console.log("Client is seeding:\n" + torrent.magnetURI);
Expand All @@ -67,7 +74,6 @@ class SendFiles extends React.Component {
{/* Makes it so that when you click "Send", it un-renders the "Choose Files" and "Send" Button */}
{this.state.isChoosingFiles && (
<div>

{/* File Choosing */}
<input
type="file"
Expand All @@ -94,7 +100,7 @@ class SendFiles extends React.Component {
}
}

// DECLARING PROP TYPES
// Declaring prop types
SendFiles.propTypes = {
client: PropTypes.object,
pressedSendButtonCallback: PropTypes.func,
Expand Down
201 changes: 182 additions & 19 deletions client/src/components/WaitForBumpReceiver.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,198 @@
import React from 'react'
import Header from './Header'
import SuperheroName from './SuperheroName'
import '../styles/button.css'
import "../styles/containers.css"
import '../styles/waitforbump.css'
import '../styles/transferinprogress.css'
import 'bootstrap/dist/css/bootstrap.min.css'
import { APIrecv } from "./ApiFetch";
import { useNavigate } from 'react-router-dom'
import FistsBumping from '../assets/FistsBumping.png'
import JSZip from "../../node_modules/jszip/dist/jszip";
import downloadIcon from "../assets/download.png";
import PropTypes from 'prop-types';

const WaitForBumpReceiver = () => {
const navigate = useNavigate()
return (
<div className="App">
<Header />
<SuperheroName />
<button className = "test-button" onClick={() => {
navigate('/Progress')
}}>Receiver</button>
<div className='fists-bumping-container'>
<img src = {FistsBumping} className="fists-bumping-image-size" alt="Fist Bump Waiting Pic"/>
/*
Waiting for Bump Receiver page

Receiver renders this component after clicking Receive button on Home
Currently, this component simulates the BAM action and starts receiving files
Later, application should render TransferInProgress while downloading
Then, render ReceiveFiles once done downloading
But for now, this component contains all that functionality

*/
class WaitForBumpReceiver extends React.Component {
constructor(props) {
super(props);
this.state = {
client: this.props.client,
showProgress: false
}
}

// (will be) Called when detected BAM action
bamEvent = () => {
let addedFiles = 0;
var zip = new JSZip();
const clientData = {
name: "Superman",
// magnetLink: "",
coordinates: [115, 115],
date: Date.now(),
};

// Check if the client has been created and created one if false
if(this.state.client == null){
const { WebTorrent } = window
this.setState({
client: new WebTorrent()
});
}

// Display loading spinner (and progress)
this.setState({
showProgress: true
})

// API fetch call to grab magnet link from matching sender
APIrecv(clientData).then((response) => {

// Log response
console.log("Torrent ID: ", response.magnetLink);
let torrentId = response.magnetLink;

// https://webtorrent.io/docs
// Start downloading torrent
this.state.client.add(torrentId, function (torrent) {

// Loop through each file in the torrent
torrent.files.forEach(function (file) {

// Set the parameters for the zip file
zip.file(file.path, Blob, { base64: true });

// Start zip into blob object for href download
file.getBlob(function (err, blob) {
if (err) throw err;
addedFiles += 1;

// Add file path to zip
zip.file(file.path, blob);

// Start the download when all files have been added
if (addedFiles === torrent.files.length) {

// Name the the file in the zip and start generating each file component
if (torrent.files.length > 1) { zip = zip.folder(torrent.name);}
zip.generateAsync({ type: "blob" }).then(function (blob) {
// Start creating and editing html components
let downloadList = document.getElementById("downloadList");
let fileRow = document.createElement("div");
fileRow.className = "downloadAllContainer";
const url = URL.createObjectURL(blob);

// Create Download All Files button html component
const a = document.createElement("a");
a.download = "downloaded_files";
a.href = url;
a.textContent = "Download All Files";
a.className = "downloadAllButton";

// Add components to html body
fileRow.appendChild(a);
downloadList.appendChild(fileRow);
setTimeout(function () {
URL.revokeObjectURL(url);
}, 30 * 1000);
});
}
});

// Start turning each individual file into blob object
file.getBlobURL(function callback(err, url) {
if (err) throw err;

// Start creating and editing html components
let downloadList = document.getElementById("downloadList");
let fileRow = document.createElement("div");
fileRow.className = "row fileRow";
downloadList.appendChild(fileRow);

// Create html component for file names
var p = document.createElement("p");
p.innerHTML = file.name;
p.className = "col-10 fileNameContainer";

// Create html component for individual download button
var a = document.createElement("a");
a.download = file.name;
a.href = url;
a.className = "col-4 downloadButton";

// Insert download image into button
var img = document.createElement("img");
img.className = "downloadIcon";
img.src = downloadIcon;
a.appendChild(img);

// Add components to html body
fileRow.appendChild(p);
fileRow.appendChild(a);
});
});
});

// Once torrent is done downloading, stop showing loading spinner/progress
}).then(() => {
setTimeout(function () {}, 30 * 1000);
this.setState({
showProgress: false
})
})
}

cancelReceive = () => {
useNavigate('/');
}

render(){ return (
<div className="App">
{/* Fist bump image is the button. Simulates the bump */}
<button className = "test-button" onClick={this.bamEvent}>
<img src = {FistsBumping} className="fists-bumping-image-size" alt="Fist Bump Waiting Pic"/>
</button>

<div className='fists-bumping-container'>
<h1 className="text-style">
<br/>
FIST BUMP THE DEVICES
<br/>
TO INITIATE TRANSFER!
</h1>
</div>
<button className = "red-button-bottom" onClick={() => {
navigate('/')
}}>CANCEL</button>
</div>
)
</div>

{/* If currently downloading torrent, render loading spinner; else, render nothing */}
{ this.state.showProgress
? <div className="loader">Loading...</div>
: null}

{/* Container for the downloaded files */}
<div
id="downloadList"
className="downloadListContainer container-fluid">
</div>

{/* Cancel button (currently does not work) */}
<button className = "red-button-bottom" onClick={this.cancelReceive}>CANCEL</button>
</div>
)}
}

// Declaring prop types
WaitForBumpReceiver.propTypes = {
showProgress: PropTypes.bool,
client: PropTypes.object,
bumpCallback: PropTypes.func
};

export default WaitForBumpReceiver
Loading