diff --git a/client/src/components/Home.js b/client/src/components/Home.js
index 7f46bf0..44ae940 100644
--- a/client/src/components/Home.js
+++ b/client/src/components/Home.js
@@ -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) {
@@ -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
@@ -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 (
-
{/* File Choosing */}
{
- const navigate = useNavigate()
- return (
-
-
-
-
{
- navigate('/Progress')
- }}>Receiver
-
-
+/*
+ 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 (
+
+ {/* Fist bump image is the button. Simulates the bump */}
+
+
+
+
+
FIST BUMP THE DEVICES
TO INITIATE TRANSFER!
-
-
{
- navigate('/')
- }}>CANCEL
-
- )
+
+
+ {/* If currently downloading torrent, render loading spinner; else, render nothing */}
+ { this.state.showProgress
+ ?
Loading...
+ : null}
+
+ {/* Container for the downloaded files */}
+
+
+
+ {/* Cancel button (currently does not work) */}
+
CANCEL
+
+ )}
}
+// Declaring prop types
+WaitForBumpReceiver.propTypes = {
+ showProgress: PropTypes.bool,
+ client: PropTypes.object,
+ bumpCallback: PropTypes.func
+};
+
export default WaitForBumpReceiver
\ No newline at end of file
diff --git a/client/src/components/WaitForBumpSender.js b/client/src/components/WaitForBumpSender.js
index 658946f..ec07c58 100644
--- a/client/src/components/WaitForBumpSender.js
+++ b/client/src/components/WaitForBumpSender.js
@@ -18,25 +18,26 @@ class WaitForBumpSender extends React.Component {
}
this.props.bumpCallback(sensorData);
}
+
+ cancelSend = () => {
+ useNavigate('/');
+ }
render(){ return (
-
Simulate BAM! by Sender
+
+
+
+
+
+
+ FIST BUMP THE DEVICES
+
+ TO INITIATE TRANSFER!
+
-
-
-
-
- FIST BUMP THE DEVICES
-
- TO INITIATE TRANSFER!
-
+
CANCEL
-
-
{
- useNavigate('/');
- }}>CANCEL
-
)}
}
diff --git a/client/src/styles/containers.css b/client/src/styles/containers.css
index d5f7d3a..b03804e 100644
--- a/client/src/styles/containers.css
+++ b/client/src/styles/containers.css
@@ -12,8 +12,21 @@ ul{
align-items: center;
border: 1px solid rgb(107, 107, 107);
}
+.fileList{
+ max-height: 200px;
+ margin: auto;
+ padding: auto;
+}
+.fileListContainer{
+ min-height: 200px;
+ max-height: 200px;
+ margin: auto;
+ margin-bottom: 1%;
+ padding: auto;
+}
.fileNameContainer{
margin: 0;
+ overflow-wrap: break-word;
}
.downloadListContainer{
padding: 5%;
diff --git a/client/src/styles/transferinprogress.css b/client/src/styles/transferinprogress.css
index 745f4e2..842914c 100644
--- a/client/src/styles/transferinprogress.css
+++ b/client/src/styles/transferinprogress.css
@@ -3,17 +3,98 @@
background-color: black;
color: white;
text-align: center;
- width: 500px;
+ width: 80%;
margin: 0 auto;
border-radius: 25px;
line-height: 1.5;
- padding-bottom: 250px;
margin-top: 20px;
-
}
.text-style {
font-family: 'Bangers', cursive;
font-size: 36px;
- margin-top: 50px;
+ margin-top: none;
+}
+
+
+/* credit to lukehaas for loading spinner*/
+.loader {
+ color: #3b3b3b;
+ font-size: 90px;
+ text-indent: -9999em;
+ overflow: hidden;
+ width: 1em;
+ height: 1em;
+ border-radius: 50%;
+ margin: 72px auto;
+ position: relative;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-animation: load6 1.7s infinite ease, round 1.7s infinite ease;
+ animation: load6 1.7s infinite ease, round 1.7s infinite ease;
+}
+@-webkit-keyframes load6 {
+ 0% {
+ box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
+ }
+ 5%,
+ 95% {
+ box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
+ }
+ 10%,
+ 59% {
+ box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em;
+ }
+ 20% {
+ box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em;
+ }
+ 38% {
+ box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em;
+ }
+ 100% {
+ box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
+ }
+}
+@keyframes load6 {
+ 0% {
+ box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
+ }
+ 5%,
+ 95% {
+ box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
+ }
+ 10%,
+ 59% {
+ box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em;
+ }
+ 20% {
+ box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em;
+ }
+ 38% {
+ box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em;
+ }
+ 100% {
+ box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
+ }
+}
+@-webkit-keyframes round {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes round {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
}
\ No newline at end of file
diff --git a/client/src/styles/waitforbump.css b/client/src/styles/waitforbump.css
index 5f95cd6..3209ca6 100644
--- a/client/src/styles/waitforbump.css
+++ b/client/src/styles/waitforbump.css
@@ -3,15 +3,10 @@
.text-style{
font-family: 'Bangers', cursive;
font-size: 36px;
+ margin-top: none !important;
}
.fists-bumping-container {
- /* original css
- position: absolute;
- top: 47%;
- left: 50%;
- margin-top: -150px;
- margin-left: -190px;*/
display: flex;
flex-direction: column;
align-items: center;
@@ -19,13 +14,8 @@
}
.fists-bumping-image-size{
- /* original css
- margin-top: 30px;
- max-width: 380px;
- height: auto;*/
max-width: 380px;
height: 200px;
- margin-bottom: -90px;
}
.red-button-bottom{
@@ -33,25 +23,22 @@
font-size: 26px;
position: relative;
bottom: 5%;
- /*left: 50%;*/
font-weight: 800;
border-radius: 15px;
max-width: 350px;
min-width:350px;
margin: 10px;
- /*margin-left: -175px;*/
transition: transform 0.3s ease;
background-color: rgba(255,180,176,255);
}
.test-button {
- font-family: "Roboto", sans-serif;
font-size: 23px;
+ border: none;
font-weight: 800;
- border-radius: 15px;
- max-width: 175px;
- min-width: 175px;
- margin: 10px;
+ max-width: auto;
+ min-width: auto;
+ margin-top: 8%;
transition: transform 0.3s ease;
- background-color: rgba(153,153,255,255);
+ background-color: rgba(153,153,255,0);
}