mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
webui:
- redesigned friends list - added friendly units on downloads page - added progress bar on downloads page - fixed makefile directories and updated readme git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8202 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
b999ccc34b
commit
7c1cab07e8
@ -2,4 +2,13 @@ libresapi: resource_api and new webinterface
|
|||||||
============================================
|
============================================
|
||||||
|
|
||||||
* ./api contains a C++ backend to control retroshare from webinterfaces or scripting
|
* ./api contains a C++ backend to control retroshare from webinterfaces or scripting
|
||||||
* ./webui contains HTML/CSS/JavaScript files for the webinterface
|
* ./webfiles contains compiled files for the webinterface
|
||||||
|
* ./webui contains HTML/CSS/JavaScript source files for the webinterface
|
||||||
|
|
||||||
|
Quickinfo for builders and packagers
|
||||||
|
====================================
|
||||||
|
|
||||||
|
* copy the files in ./webfiles to
|
||||||
|
* ./webui (Windows)
|
||||||
|
* /usr/share/RetroShare0.6/webui (Linux)
|
||||||
|
* other OS: see RsAccountsDetail::PathDataDirectory()
|
@ -71,6 +71,23 @@ input:hover{
|
|||||||
background-color: midnightblue;
|
background-color: midnightblue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flexbox{
|
||||||
|
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||||
|
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||||
|
display: -ms-flexbox; /* TWEENER - IE 10 */
|
||||||
|
display: -webkit-flex; /* NEW - Chrome */
|
||||||
|
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexwidemember{
|
||||||
|
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||||
|
-moz-box-flex: 1; /* OLD - Firefox 19- */
|
||||||
|
width: 20%; /* For old syntax, otherwise collapses. */
|
||||||
|
-webkit-flex: 1; /* Chrome */
|
||||||
|
-ms-flex: 1; /* IE 10 */
|
||||||
|
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||||
|
}
|
||||||
|
|
||||||
#logo_splash{
|
#logo_splash{
|
||||||
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
|
@ -188,21 +188,6 @@ var changeUrlListener = {
|
|||||||
};
|
};
|
||||||
signalSlotServer.registerClient(changeUrlListener);
|
signalSlotServer.registerClient(changeUrlListener);
|
||||||
|
|
||||||
var Peers = React.createClass({
|
|
||||||
mixins: [AutoUpdateMixin],
|
|
||||||
getPath: function(){return "peers";},
|
|
||||||
getInitialState: function(){
|
|
||||||
return {data: []};
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
var renderOne = function(f){
|
|
||||||
console.log("make one");
|
|
||||||
return <p>{f.name} <img src={api_url+f.locations[0].avatar_address} /></p>;
|
|
||||||
};
|
|
||||||
return <div>{this.state.data.map(renderOne)}</div>;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var Peers2 = React.createClass({
|
var Peers2 = React.createClass({
|
||||||
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
||||||
getPath: function(){return "peers";},
|
getPath: function(){return "peers";},
|
||||||
@ -260,6 +245,81 @@ var Peers2 = React.createClass({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Peers3 = React.createClass({
|
||||||
|
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
||||||
|
getPath: function(){return "peers";},
|
||||||
|
getInitialState: function(){
|
||||||
|
return {data: []};
|
||||||
|
},
|
||||||
|
add_friend_handler: function(){
|
||||||
|
this.emit("change_url", {url: "add_friend"});
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
var component = this;
|
||||||
|
var Peer = React.createClass({
|
||||||
|
remove_peer_handler: function(){
|
||||||
|
var yes = window.confirm("Remove "+this.props.data.name+" from friendslist?");
|
||||||
|
if(yes){
|
||||||
|
RS.request({path: component.getPath()+"/"+this.props.data.pgp_id+"/delete"});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
var locations = this.props.data.locations.map(function(loc){
|
||||||
|
var online_style = {
|
||||||
|
width: "1em",
|
||||||
|
height: "1em",
|
||||||
|
borderRadius: "0.5em",
|
||||||
|
backgroundColor: "grey",
|
||||||
|
float:"left",
|
||||||
|
};
|
||||||
|
if(loc.is_online)
|
||||||
|
online_style.backgroundColor = "lime";
|
||||||
|
return(<div key={loc.peer_id} style={{color: loc.is_online? "lime": "grey"}}>{/*<div style={online_style}></div>*/}{loc.location}</div>);
|
||||||
|
});
|
||||||
|
var avatars = this.props.data.locations.map(function(loc){
|
||||||
|
if(loc.is_online)
|
||||||
|
{
|
||||||
|
var avatar_url = api_url + component.getPath() + loc.avatar_address;
|
||||||
|
return <img style={{borderRadius: "3mm", margin: "2mm"}} src={avatar_url}/>;
|
||||||
|
}
|
||||||
|
else return <span></span>;
|
||||||
|
});
|
||||||
|
var remove_button_style = {
|
||||||
|
color: "red",
|
||||||
|
//fontSize: "1.5em",
|
||||||
|
fontSize: "10mm",
|
||||||
|
padding: "0.2em",
|
||||||
|
cursor: "pointer",
|
||||||
|
};
|
||||||
|
var remove_button = <div onClick={this.remove_peer_handler} style={remove_button_style}>X</div>;
|
||||||
|
var is_online = false;
|
||||||
|
for(var i in this.props.data.locations)
|
||||||
|
{
|
||||||
|
if(this.props.data.locations[i].is_online)
|
||||||
|
is_online = true;
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<div className="flexbox" style={{color: is_online? "lime": "grey"}}>
|
||||||
|
<div>{avatars}</div>
|
||||||
|
<div className="flexwidemember">
|
||||||
|
<h1 style={{marginBottom: "1mm"}}>{this.props.data.name}</h1>
|
||||||
|
<div>{locations}</div>
|
||||||
|
</div>
|
||||||
|
{remove_button}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* span reduces width to only the text length, div does not */}
|
||||||
|
<div onClick={this.add_friend_handler} className="btn2">+ add friend</div>
|
||||||
|
{this.state.data.map(function(peer){ return <Peer key={peer.pgp_id} data={peer}/>; })}
|
||||||
|
</div>);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
var AddPeerWidget = React.createClass({
|
var AddPeerWidget = React.createClass({
|
||||||
getInitialState: function(){
|
getInitialState: function(){
|
||||||
return {page: "start"};
|
return {page: "start"};
|
||||||
@ -309,6 +369,35 @@ var AddPeerWidget = React.createClass({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var ProgressBar = React.createClass({
|
||||||
|
render: function(){
|
||||||
|
return(
|
||||||
|
<div style={{
|
||||||
|
borderStyle: "solid",
|
||||||
|
borderColor: "lime",
|
||||||
|
borderRadius: "3mm",
|
||||||
|
padding: "2mm",
|
||||||
|
height: "10mm",
|
||||||
|
}}>
|
||||||
|
<div style={{backgroundColor: "lime", height: "100%", width: (this.props.progress*100)+"%",}}></div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function makeFriendlyUnit(bytes)
|
||||||
|
{
|
||||||
|
if(bytes < 1e3)
|
||||||
|
return bytes.toFixed(1) + "B";
|
||||||
|
if(bytes < 1e3)
|
||||||
|
return (bytes/1e3).toFixed(1) + "kB";
|
||||||
|
if(bytes < 1e9)
|
||||||
|
return (bytes/1e6).toFixed(1) + "MB";
|
||||||
|
if(bytes < 1e12)
|
||||||
|
return (bytes/1e9).toFixed(1) + "GB";
|
||||||
|
return (bytes/1e12).toFixed(1) + "TB";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var DownloadsWidget = React.createClass({
|
var DownloadsWidget = React.createClass({
|
||||||
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
||||||
getPath: function(){ return "transfers/downloads";},
|
getPath: function(){ return "transfers/downloads";},
|
||||||
@ -372,8 +461,8 @@ var DownloadsWidget = React.createClass({
|
|||||||
}
|
}
|
||||||
return(<tr>
|
return(<tr>
|
||||||
<td>{this.props.data.name}</td>
|
<td>{this.props.data.name}</td>
|
||||||
<td>{this.props.data.size}</td>
|
<td>{makeFriendlyUnit(this.props.data.size)}</td>
|
||||||
<td>{this.props.data.transfered / this.props.data.size}</td>
|
<td><ProgressBar progress={this.props.data.transfered / this.props.data.size}/></td>
|
||||||
<td>{this.props.data.download_status}</td>
|
<td>{this.props.data.download_status}</td>
|
||||||
<td>{ctrlBtn} <div className="btn" onClick={cancelFn}>cancel</div> {playBtn}</td>
|
<td>{ctrlBtn} <div className="btn" onClick={cancelFn}>cancel</div> {playBtn}</td>
|
||||||
</tr>);
|
</tr>);
|
||||||
@ -728,7 +817,7 @@ var MainWidget = React.createClass({
|
|||||||
}
|
}
|
||||||
if(this.state.page === "friends")
|
if(this.state.page === "friends")
|
||||||
{
|
{
|
||||||
mainpage = <Peers2 />;
|
mainpage = <Peers3 />;
|
||||||
}
|
}
|
||||||
if(this.state.page === "downloads")
|
if(this.state.page === "downloads")
|
||||||
{
|
{
|
||||||
@ -765,6 +854,7 @@ var MainWidget = React.createClass({
|
|||||||
<AudioPlayerWidget/>
|
<AudioPlayerWidget/>
|
||||||
{menubutton}
|
{menubutton}
|
||||||
{mainpage}
|
{mainpage}
|
||||||
|
{/*<ProgressBar progress={0.7}/>*/}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
REACT_VERSION = 0.13.1
|
REACT_VERSION = 0.13.1
|
||||||
|
|
||||||
JSEXTLIBS = dist/react.js dist/JSXTransformer.js
|
DISTDIR = ../webfiles
|
||||||
|
JSEXTLIBS = $(DISTDIR)/react.js $(DISTDIR)/JSXTransformer.js
|
||||||
JSLIBS = RsXHRConnection.js RsApi.js
|
JSLIBS = RsXHRConnection.js RsApi.js
|
||||||
HTML = index.html
|
HTML = index.html
|
||||||
JSGUI = gui.jsx
|
JSGUI = gui.jsx
|
||||||
CSS = green-black.css
|
CSS = green-black.css
|
||||||
|
|
||||||
all: dist $(JSEXTLIBS) $(addprefix dist/, $(JSLIBS)) $(addprefix dist/, $(HTML)) $(addprefix dist/, $(JSGUI)) $(addprefix dist/, $(CSS))
|
all: $(DISTDIR) $(JSEXTLIBS) $(addprefix $(DISTDIR)/, $(JSLIBS)) $(addprefix $(DISTDIR)/, $(HTML)) $(addprefix $(DISTDIR)/, $(JSGUI)) $(addprefix $(DISTDIR)/, $(CSS))
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
dist/livereload: dist $(JSEXTLIBS) $(addprefix dist/, $(JSLIBS)) $(addprefix dist/, $(HTML)) $(addprefix dist/, $(JSGUI)) $(addprefix dist/, $(CSS))
|
$(DISTDIR)/livereload: $(DISTDIR) $(JSEXTLIBS) $(addprefix $(DISTDIR)/, $(JSLIBS)) $(addprefix $(DISTDIR)/, $(HTML)) $(addprefix $(DISTDIR)/, $(JSGUI)) $(addprefix $(DISTDIR)/, $(CSS))
|
||||||
wget -qO- http://localhost:9090/api/v2/livereload/trigger
|
wget -qO- http://localhost:9090/api/v2/livereload/trigger
|
||||||
touch dist/livereload
|
touch $(DISTDIR)/livereload
|
||||||
|
|
||||||
dist/react.js:
|
$(DISTDIR)/react.js:
|
||||||
cd dist && wget --no-check-certificate --output-document react.js http://fb.me/react-$(REACT_VERSION).js
|
cd $(DISTDIR) && wget --no-check-certificate --output-document react.js http://fb.me/react-$(REACT_VERSION).js
|
||||||
|
|
||||||
dist/JSXTransformer.js:
|
$(DISTDIR)/JSXTransformer.js:
|
||||||
cd dist && wget --no-check-certificate --output-document JSXTransformer.js http://fb.me/JSXTransformer-$(REACT_VERSION).js
|
cd $(DISTDIR) && wget --no-check-certificate --output-document JSXTransformer.js http://fb.me/JSXTransformer-$(REACT_VERSION).js
|
||||||
|
|
||||||
$(addprefix dist/, $(JSLIBS)): dist/%: %
|
$(addprefix $(DISTDIR)/, $(JSLIBS)): $(DISTDIR)/%: %
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
$(addprefix dist/, $(HTML)): dist/%: %
|
$(addprefix $(DISTDIR)/, $(HTML)): $(DISTDIR)/%: %
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
$(addprefix dist/, $(JSGUI)): dist/%: %
|
$(addprefix $(DISTDIR)/, $(JSGUI)): $(DISTDIR)/%: %
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
$(addprefix dist/, $(CSS)): dist/%: %
|
$(addprefix $(DISTDIR)/, $(CSS)): $(DISTDIR)/%: %
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
dist:
|
$(DISTDIR):
|
||||||
mkdir dist
|
mkdir $(DISTDIR)
|
||||||
|
@ -12,9 +12,11 @@ BUILD / INSTALLATION
|
|||||||
|
|
||||||
- run (requires wget, use MinGW shell on Windows)
|
- run (requires wget, use MinGW shell on Windows)
|
||||||
make
|
make
|
||||||
- all output files are now in the "dist" folder
|
- all output files are now in libresapi/src/webfiles
|
||||||
- use the --webinterface 9090 command line parameter to enable webui in retroshare-nogui
|
- use the --webinterface 9090 command line parameter to enable webui in retroshare-nogui
|
||||||
- set the --docroot parameter of retroshare-nogui to point to the "dist" directory
|
- set the --docroot parameter of retroshare-nogui to point to the "libresapi/src/webfiles" directory
|
||||||
|
(or symlink from /usr/share/RetroShare0.6/webui on Linux, ./webui on Windows)
|
||||||
|
- retroshare-gui does not have a --docroot parameter. Use symlinks then.
|
||||||
|
|
||||||
DEVELOPMENT
|
DEVELOPMENT
|
||||||
-----------
|
-----------
|
||||||
@ -26,8 +28,8 @@ DEVELOPMENT
|
|||||||
npm install
|
npm install
|
||||||
- run Retroshare with webinterface on port 9090
|
- run Retroshare with webinterface on port 9090
|
||||||
- during development, run this command (use MinGW shell on Windows)
|
- during development, run this command (use MinGW shell on Windows)
|
||||||
while true; do make dist/livereload --silent; sleep 1; done
|
while true; do make ../webfiles/livereload --silent; sleep 1; done
|
||||||
- the command will copy the source files to the "dist" directory if they change
|
- the command will copy the source files to libresapi/src/webfiles if they change
|
||||||
- it will trigger livereload at http://localhost:9090/api/v2/livereload/trigger
|
- it will trigger livereload at http://localhost:9090/api/v2/livereload/trigger
|
||||||
|
|
||||||
API DOCUMENTATION
|
API DOCUMENTATION
|
||||||
|
@ -71,6 +71,23 @@ input:hover{
|
|||||||
background-color: midnightblue;
|
background-color: midnightblue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flexbox{
|
||||||
|
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||||
|
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||||
|
display: -ms-flexbox; /* TWEENER - IE 10 */
|
||||||
|
display: -webkit-flex; /* NEW - Chrome */
|
||||||
|
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexwidemember{
|
||||||
|
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||||
|
-moz-box-flex: 1; /* OLD - Firefox 19- */
|
||||||
|
width: 20%; /* For old syntax, otherwise collapses. */
|
||||||
|
-webkit-flex: 1; /* Chrome */
|
||||||
|
-ms-flex: 1; /* IE 10 */
|
||||||
|
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||||
|
}
|
||||||
|
|
||||||
#logo_splash{
|
#logo_splash{
|
||||||
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
|
@ -188,21 +188,6 @@ var changeUrlListener = {
|
|||||||
};
|
};
|
||||||
signalSlotServer.registerClient(changeUrlListener);
|
signalSlotServer.registerClient(changeUrlListener);
|
||||||
|
|
||||||
var Peers = React.createClass({
|
|
||||||
mixins: [AutoUpdateMixin],
|
|
||||||
getPath: function(){return "peers";},
|
|
||||||
getInitialState: function(){
|
|
||||||
return {data: []};
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
var renderOne = function(f){
|
|
||||||
console.log("make one");
|
|
||||||
return <p>{f.name} <img src={api_url+f.locations[0].avatar_address} /></p>;
|
|
||||||
};
|
|
||||||
return <div>{this.state.data.map(renderOne)}</div>;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var Peers2 = React.createClass({
|
var Peers2 = React.createClass({
|
||||||
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
||||||
getPath: function(){return "peers";},
|
getPath: function(){return "peers";},
|
||||||
@ -260,6 +245,81 @@ var Peers2 = React.createClass({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Peers3 = React.createClass({
|
||||||
|
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
||||||
|
getPath: function(){return "peers";},
|
||||||
|
getInitialState: function(){
|
||||||
|
return {data: []};
|
||||||
|
},
|
||||||
|
add_friend_handler: function(){
|
||||||
|
this.emit("change_url", {url: "add_friend"});
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
var component = this;
|
||||||
|
var Peer = React.createClass({
|
||||||
|
remove_peer_handler: function(){
|
||||||
|
var yes = window.confirm("Remove "+this.props.data.name+" from friendslist?");
|
||||||
|
if(yes){
|
||||||
|
RS.request({path: component.getPath()+"/"+this.props.data.pgp_id+"/delete"});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
var locations = this.props.data.locations.map(function(loc){
|
||||||
|
var online_style = {
|
||||||
|
width: "1em",
|
||||||
|
height: "1em",
|
||||||
|
borderRadius: "0.5em",
|
||||||
|
backgroundColor: "grey",
|
||||||
|
float:"left",
|
||||||
|
};
|
||||||
|
if(loc.is_online)
|
||||||
|
online_style.backgroundColor = "lime";
|
||||||
|
return(<div key={loc.peer_id} style={{color: loc.is_online? "lime": "grey"}}>{/*<div style={online_style}></div>*/}{loc.location}</div>);
|
||||||
|
});
|
||||||
|
var avatars = this.props.data.locations.map(function(loc){
|
||||||
|
if(loc.is_online)
|
||||||
|
{
|
||||||
|
var avatar_url = api_url + component.getPath() + loc.avatar_address;
|
||||||
|
return <img style={{borderRadius: "3mm", margin: "2mm"}} src={avatar_url}/>;
|
||||||
|
}
|
||||||
|
else return <span></span>;
|
||||||
|
});
|
||||||
|
var remove_button_style = {
|
||||||
|
color: "red",
|
||||||
|
//fontSize: "1.5em",
|
||||||
|
fontSize: "10mm",
|
||||||
|
padding: "0.2em",
|
||||||
|
cursor: "pointer",
|
||||||
|
};
|
||||||
|
var remove_button = <div onClick={this.remove_peer_handler} style={remove_button_style}>X</div>;
|
||||||
|
var is_online = false;
|
||||||
|
for(var i in this.props.data.locations)
|
||||||
|
{
|
||||||
|
if(this.props.data.locations[i].is_online)
|
||||||
|
is_online = true;
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<div className="flexbox" style={{color: is_online? "lime": "grey"}}>
|
||||||
|
<div>{avatars}</div>
|
||||||
|
<div className="flexwidemember">
|
||||||
|
<h1 style={{marginBottom: "1mm"}}>{this.props.data.name}</h1>
|
||||||
|
<div>{locations}</div>
|
||||||
|
</div>
|
||||||
|
{remove_button}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* span reduces width to only the text length, div does not */}
|
||||||
|
<div onClick={this.add_friend_handler} className="btn2">+ add friend</div>
|
||||||
|
{this.state.data.map(function(peer){ return <Peer key={peer.pgp_id} data={peer}/>; })}
|
||||||
|
</div>);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
var AddPeerWidget = React.createClass({
|
var AddPeerWidget = React.createClass({
|
||||||
getInitialState: function(){
|
getInitialState: function(){
|
||||||
return {page: "start"};
|
return {page: "start"};
|
||||||
@ -309,6 +369,35 @@ var AddPeerWidget = React.createClass({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var ProgressBar = React.createClass({
|
||||||
|
render: function(){
|
||||||
|
return(
|
||||||
|
<div style={{
|
||||||
|
borderStyle: "solid",
|
||||||
|
borderColor: "lime",
|
||||||
|
borderRadius: "3mm",
|
||||||
|
padding: "2mm",
|
||||||
|
height: "10mm",
|
||||||
|
}}>
|
||||||
|
<div style={{backgroundColor: "lime", height: "100%", width: (this.props.progress*100)+"%",}}></div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function makeFriendlyUnit(bytes)
|
||||||
|
{
|
||||||
|
if(bytes < 1e3)
|
||||||
|
return bytes.toFixed(1) + "B";
|
||||||
|
if(bytes < 1e3)
|
||||||
|
return (bytes/1e3).toFixed(1) + "kB";
|
||||||
|
if(bytes < 1e9)
|
||||||
|
return (bytes/1e6).toFixed(1) + "MB";
|
||||||
|
if(bytes < 1e12)
|
||||||
|
return (bytes/1e9).toFixed(1) + "GB";
|
||||||
|
return (bytes/1e12).toFixed(1) + "TB";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var DownloadsWidget = React.createClass({
|
var DownloadsWidget = React.createClass({
|
||||||
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
mixins: [AutoUpdateMixin, SignalSlotMixin],
|
||||||
getPath: function(){ return "transfers/downloads";},
|
getPath: function(){ return "transfers/downloads";},
|
||||||
@ -372,8 +461,8 @@ var DownloadsWidget = React.createClass({
|
|||||||
}
|
}
|
||||||
return(<tr>
|
return(<tr>
|
||||||
<td>{this.props.data.name}</td>
|
<td>{this.props.data.name}</td>
|
||||||
<td>{this.props.data.size}</td>
|
<td>{makeFriendlyUnit(this.props.data.size)}</td>
|
||||||
<td>{this.props.data.transfered / this.props.data.size}</td>
|
<td><ProgressBar progress={this.props.data.transfered / this.props.data.size}/></td>
|
||||||
<td>{this.props.data.download_status}</td>
|
<td>{this.props.data.download_status}</td>
|
||||||
<td>{ctrlBtn} <div className="btn" onClick={cancelFn}>cancel</div> {playBtn}</td>
|
<td>{ctrlBtn} <div className="btn" onClick={cancelFn}>cancel</div> {playBtn}</td>
|
||||||
</tr>);
|
</tr>);
|
||||||
@ -728,7 +817,7 @@ var MainWidget = React.createClass({
|
|||||||
}
|
}
|
||||||
if(this.state.page === "friends")
|
if(this.state.page === "friends")
|
||||||
{
|
{
|
||||||
mainpage = <Peers2 />;
|
mainpage = <Peers3 />;
|
||||||
}
|
}
|
||||||
if(this.state.page === "downloads")
|
if(this.state.page === "downloads")
|
||||||
{
|
{
|
||||||
@ -765,6 +854,7 @@ var MainWidget = React.createClass({
|
|||||||
<AudioPlayerWidget/>
|
<AudioPlayerWidget/>
|
||||||
{menubutton}
|
{menubutton}
|
||||||
{mainpage}
|
{mainpage}
|
||||||
|
{/*<ProgressBar progress={0.7}/>*/}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user