Implemented status bar with some status information: sync process, connected nodes and blockchain height.
This commit is contained in:
@@ -14,6 +14,7 @@ pub struct Blockchain {
|
|||||||
pub version: u32,
|
pub version: u32,
|
||||||
pub blocks: Vec<Block>,
|
pub blocks: Vec<Block>,
|
||||||
last_block: Option<Block>,
|
last_block: Option<Block>,
|
||||||
|
max_height: u64,
|
||||||
db: Connection,
|
db: Connection,
|
||||||
zones: RefCell<HashSet<String>>
|
zones: RefCell<HashSet<String>>
|
||||||
}
|
}
|
||||||
@@ -24,7 +25,7 @@ impl Blockchain {
|
|||||||
let version = settings.version;
|
let version = settings.version;
|
||||||
|
|
||||||
let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB");
|
let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB");
|
||||||
let mut blockchain = Blockchain{ origin, version, blocks: Vec::new(), last_block: None, db, zones: RefCell::new(HashSet::new()) };
|
let mut blockchain = Blockchain{ origin, version, blocks: Vec::new(), last_block: None, max_height: 0, db, zones: RefCell::new(HashSet::new()) };
|
||||||
blockchain.init_db();
|
blockchain.init_db();
|
||||||
blockchain
|
blockchain
|
||||||
}
|
}
|
||||||
@@ -243,6 +244,16 @@ impl Blockchain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn max_height(&self) -> u64 {
|
||||||
|
self.max_height
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_max_height(&mut self, height: u64) {
|
||||||
|
if height > self.max_height {
|
||||||
|
self.max_height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*pub fn check(&self) -> bool {
|
/*pub fn check(&self) -> bool {
|
||||||
let mut prev_block = None;
|
let mut prev_block = None;
|
||||||
for block in self.blocks.iter() {
|
for block in self.blocks.iter() {
|
||||||
|
|||||||
+6
-3
@@ -4,10 +4,13 @@ pub enum Event {
|
|||||||
MinerStopped,
|
MinerStopped,
|
||||||
KeyGeneratorStarted,
|
KeyGeneratorStarted,
|
||||||
KeyGeneratorStopped,
|
KeyGeneratorStopped,
|
||||||
KeyCreated {path: String, public: String},
|
KeyCreated { path: String, public: String },
|
||||||
KeyLoaded {path: String, public: String},
|
KeyLoaded { path: String, public: String },
|
||||||
KeySaved {path: String, public: String},
|
KeySaved { path: String, public: String },
|
||||||
NewBlockReceived,
|
NewBlockReceived,
|
||||||
BlockchainChanged,
|
BlockchainChanged,
|
||||||
ActionStopMining,
|
ActionStopMining,
|
||||||
|
StatsCount { nodes: usize, blocks: u64 },
|
||||||
|
SyncStarted { have: u64, height: u64 },
|
||||||
|
ActionIdle,
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-30
@@ -56,11 +56,11 @@ fn main() {
|
|||||||
let program = args[0].clone();
|
let program = args[0].clone();
|
||||||
|
|
||||||
let mut opts = Options::new();
|
let mut opts = Options::new();
|
||||||
opts.optflag("h","help", "Print this help menu");
|
opts.optflag("h", "help", "Print this help menu");
|
||||||
opts.optflag("n","nogui","Run without graphic user interface");
|
opts.optflag("n", "nogui", "Run without graphic user interface");
|
||||||
opts.optflag("v","verbose","Show more debug messages");
|
opts.optflag("v", "verbose", "Show more debug messages");
|
||||||
opts.optflag("d","debug","Show trace messages, more than debug");
|
opts.optflag("d", "debug", "Show trace messages, more than debug");
|
||||||
opts.optopt("c","config","Path to config file", "");
|
opts.optopt("c", "config", "Path to config file", "");
|
||||||
|
|
||||||
let opt_matches = match opts.parse(&args[1..]) {
|
let opt_matches = match opts.parse(&args[1..]) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
@@ -161,8 +161,8 @@ fn create_genesis_if_needed(context: &Arc<Mutex<Context>>, miner: &Arc<Mutex<Min
|
|||||||
|
|
||||||
fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
||||||
let file_content = include_str!("webview/index.html");
|
let file_content = include_str!("webview/index.html");
|
||||||
let mut styles= inline_style(include_str!("webview/bulma.css"));
|
let mut styles = inline_style(include_str!("webview/bulma.css"));
|
||||||
styles.push_str(&inline_style(include_str!("webview/miner.css")));
|
styles.push_str(&inline_style(include_str!("webview/busy_indicator.css")));
|
||||||
let scripts = inline_script(include_str!("webview/scripts.js"));
|
let scripts = inline_script(include_str!("webview/scripts.js"));
|
||||||
|
|
||||||
let html = Content::Html(file_content.to_owned().replace("{styles}", &styles).replace("{scripts}", &scripts));
|
let html = Content::Html(file_content.to_owned().replace("{styles}", &styles).replace("{scripts}", &scripts));
|
||||||
@@ -189,10 +189,19 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
|||||||
Event::KeyCreated { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) }
|
Event::KeyCreated { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) }
|
||||||
Event::KeyLoaded { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) }
|
Event::KeyLoaded { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) }
|
||||||
Event::KeySaved { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) }
|
Event::KeySaved { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) }
|
||||||
Event::MinerStarted => { format!("showMiningIndicator({});", true) }
|
Event::MinerStarted => { format!("showMiningIndicator({}, false);", true) }
|
||||||
Event::KeyGeneratorStarted => { format!("showMiningIndicator({});", true) }
|
Event::KeyGeneratorStarted => { format!("showMiningIndicator({}, false);", true) }
|
||||||
Event::MinerStopped => { format!("showMiningIndicator({});", false) }
|
Event::MinerStopped => { format!("showMiningIndicator({}, false);", false) }
|
||||||
Event::KeyGeneratorStopped => { format!("showMiningIndicator({});", false) }
|
Event::KeyGeneratorStopped => { format!("showMiningIndicator({}, false);", false) }
|
||||||
|
Event::SyncStarted { have, height } => {
|
||||||
|
format!("setLeftStatusBarText('Synchronizing {}/{}'); showMiningIndicator(true, true);", have, height)
|
||||||
|
}
|
||||||
|
Event::ActionIdle => {
|
||||||
|
format!("setLeftStatusBarText('Idle'); showMiningIndicator(false, true);")
|
||||||
|
}
|
||||||
|
Event::StatsCount { nodes, blocks } => {
|
||||||
|
format!("setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks)
|
||||||
|
}
|
||||||
_ => { String::new() }
|
_ => { String::new() }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,17 +225,17 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
|||||||
match Keystore::from_file(&file_name, "") {
|
match Keystore::from_file(&file_name, "") {
|
||||||
None => {
|
None => {
|
||||||
error!("Error loading keystore '{}'!", &file_name);
|
error!("Error loading keystore '{}'!", &file_name);
|
||||||
},
|
}
|
||||||
Some(keystore) => {
|
Some(keystore) => {
|
||||||
info!("Loaded keystore with key: {:?}", &keystore.get_public());
|
info!("Loaded keystore with key: {:?}", &keystore.get_public());
|
||||||
let mut c = context.lock().unwrap();
|
let mut c = context.lock().unwrap();
|
||||||
c.bus.post(Event::KeyLoaded {path: keystore.get_path().to_owned(), public: keystore.get_public().to_string()});
|
c.bus.post(Event::KeyLoaded { path: keystore.get_path().to_owned(), public: keystore.get_public().to_string() });
|
||||||
c.set_keystore(keystore);
|
c.set_keystore(keystore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
CreateKey {} => {
|
CreateKey {} => {
|
||||||
create_key(context.clone());
|
create_key(context.clone());
|
||||||
}
|
}
|
||||||
@@ -240,11 +249,11 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
|||||||
let public = c.keystore.get_public().to_string();
|
let public = c.keystore.get_public().to_string();
|
||||||
c.keystore.save(&new_path, "");
|
c.keystore.save(&new_path, "");
|
||||||
info!("Key file saved to {}", &path);
|
info!("Key file saved to {}", &path);
|
||||||
c.bus.post(Event::KeySaved {path, public });
|
c.bus.post(Event::KeySaved { path, public });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CheckDomain { name} => {
|
CheckDomain { name } => {
|
||||||
let name = name.to_lowercase();
|
let name = name.to_lowercase();
|
||||||
let c = context.lock().unwrap();
|
let c = context.lock().unwrap();
|
||||||
let available = c.get_blockchain().is_domain_available(&name, &c.get_keystore());
|
let available = c.get_blockchain().is_domain_available(&name, &c.get_keystore());
|
||||||
@@ -282,7 +291,7 @@ fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
|
|||||||
ChangeDomain { .. } => {}
|
ChangeDomain { .. } => {}
|
||||||
RenewDomain { .. } => {}
|
RenewDomain { .. } => {}
|
||||||
TransferDomain { .. } => {}
|
TransferDomain { .. } => {}
|
||||||
CheckZone { name} => {
|
CheckZone { name } => {
|
||||||
let name = name.to_lowercase();
|
let name = name.to_lowercase();
|
||||||
if !check_domain(&name, false) {
|
if !check_domain(&name, false) {
|
||||||
web_view.eval("zoneAvailable(false)").expect("Error evaluating!");
|
web_view.eval("zoneAvailable(false)").expect("Error evaluating!");
|
||||||
@@ -398,8 +407,8 @@ fn create_key(context: Arc<Mutex<Context>>) {
|
|||||||
Some(keystore) => {
|
Some(keystore) => {
|
||||||
info!("Key mined successfully: {:?}", &keystore.get_public());
|
info!("Key mined successfully: {:?}", &keystore.get_public());
|
||||||
let mut c = context.lock().unwrap();
|
let mut c = context.lock().unwrap();
|
||||||
mining.store(false,Ordering::Relaxed);
|
mining.store(false, Ordering::Relaxed);
|
||||||
c.bus.post(Event::KeyCreated {path: keystore.get_path().to_owned(), public: keystore.get_public().to_string()});
|
c.bus.post(Event::KeyCreated { path: keystore.get_path().to_owned(), public: keystore.get_public().to_string() });
|
||||||
c.set_keystore(keystore);
|
c.set_keystore(keystore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,7 +449,7 @@ fn create_server_context(context: Arc<Mutex<Context>>, settings: &Settings) -> A
|
|||||||
server_context.dns_port = settings.dns.port;
|
server_context.dns_port = settings.dns.port;
|
||||||
server_context.resolve_strategy = match settings.dns.forwarders.is_empty() {
|
server_context.resolve_strategy = match settings.dns.forwarders.is_empty() {
|
||||||
true => { ResolveStrategy::Recursive }
|
true => { ResolveStrategy::Recursive }
|
||||||
false => { ResolveStrategy::Forward { upstreams: settings.dns.forwarders.clone() }}
|
false => { ResolveStrategy::Forward { upstreams: settings.dns.forwarders.clone() } }
|
||||||
};
|
};
|
||||||
server_context.filters.push(Box::new(BlockchainFilter::new(context)));
|
server_context.filters.push(Box::new(BlockchainFilter::new(context)));
|
||||||
match server_context.initialize() {
|
match server_context.initialize() {
|
||||||
@@ -455,16 +464,16 @@ fn create_server_context(context: Arc<Mutex<Context>>, settings: &Settings) -> A
|
|||||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||||
pub enum Cmd {
|
pub enum Cmd {
|
||||||
Loaded,
|
Loaded,
|
||||||
LoadKey{},
|
LoadKey {},
|
||||||
CreateKey{},
|
CreateKey {},
|
||||||
SaveKey{},
|
SaveKey {},
|
||||||
CheckZone{name: String},
|
CheckZone { name: String },
|
||||||
CreateZone{name: String, data: String},
|
CreateZone { name: String, data: String },
|
||||||
CheckDomain{name: String},
|
CheckDomain { name: String },
|
||||||
CreateDomain{name: String, records: String, tags: String},
|
CreateDomain { name: String, records: String, tags: String },
|
||||||
ChangeDomain{name: String, records: String, tags: String},
|
ChangeDomain { name: String, records: String, tags: String },
|
||||||
RenewDomain{name: String, days: u16},
|
RenewDomain { name: String, days: u16 },
|
||||||
TransferDomain{name: String, owner: String},
|
TransferDomain { name: String, owner: String },
|
||||||
StopMining,
|
StopMining,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-6
@@ -91,6 +91,9 @@ impl Network {
|
|||||||
token => {
|
token => {
|
||||||
if !handle_connection_event(context.clone(), &mut peers, &poll.registry(), &event) {
|
if !handle_connection_event(context.clone(), &mut peers, &poll.registry(), &event) {
|
||||||
let _ = peers.close_peer(poll.registry(), &token);
|
let _ = peers.close_peer(poll.registry(), &token);
|
||||||
|
let mut context = context.lock().unwrap();
|
||||||
|
let blocks_count = context.blockchain.height();
|
||||||
|
context.bus.post(crate::event::Event::StatsCount { nodes: peers.get_peers_active_count(), blocks: blocks_count });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,9 +126,10 @@ fn handle_connection_event(context: Arc<Mutex<Context>>, peers: &mut Peers, regi
|
|||||||
let data = data.unwrap();
|
let data = data.unwrap();
|
||||||
match Message::from_bytes(data) {
|
match Message::from_bytes(data) {
|
||||||
Ok(message) => {
|
Ok(message) => {
|
||||||
debug!("Got message from socket {}: {:?}", &event.token().0, &message);
|
let m = format!("{:?}", &message);
|
||||||
let new_state = handle_message(context.clone(), message, peers, &event.token());
|
let new_state = handle_message(context.clone(), message, peers, &event.token());
|
||||||
let peer = peers.get_mut_peer(&event.token()).unwrap();
|
let peer = peers.get_mut_peer(&event.token()).unwrap();
|
||||||
|
debug!("Got message from {}: {:?}", &peer.get_addr(), &m);
|
||||||
let stream = peer.get_stream();
|
let stream = peer.get_stream();
|
||||||
match new_state {
|
match new_state {
|
||||||
State::Message { data } => {
|
State::Message { data } => {
|
||||||
@@ -163,17 +167,17 @@ fn handle_connection_event(context: Arc<Mutex<Context>>, peers: &mut Peers, regi
|
|||||||
Some(peer) => {
|
Some(peer) => {
|
||||||
match peer.get_state().clone() {
|
match peer.get_state().clone() {
|
||||||
State::Connecting => {
|
State::Connecting => {
|
||||||
debug!("Sending hello to socket {}", event.token().0);
|
debug!("Sending hello to {}", &peer.get_addr());
|
||||||
let data: String = {
|
let data: String = {
|
||||||
let c = context.lock().unwrap();
|
let c = context.lock().unwrap();
|
||||||
let message = Message::hand(&c.settings.origin, c.settings.version, c.settings.public);
|
let message = Message::hand(&c.settings.origin, c.settings.version, c.settings.public);
|
||||||
serde_json::to_string(&message).unwrap()
|
serde_json::to_string(&message).unwrap()
|
||||||
};
|
};
|
||||||
send_message(peer.get_stream(), &data.into_bytes());
|
send_message(peer.get_stream(), &data.into_bytes());
|
||||||
debug!("Sent hello through socket {}", event.token().0);
|
debug!("Sent hello to {}", &peer.get_addr());
|
||||||
}
|
}
|
||||||
State::Message { data } => {
|
State::Message { data } => {
|
||||||
debug!("Sending data to socket {}: {}", event.token().0, &String::from_utf8(data.clone()).unwrap());
|
debug!("Sending data to {}: {}", &peer.get_addr(), &String::from_utf8(data.clone()).unwrap());
|
||||||
send_message(peer.get_stream(), &data);
|
send_message(peer.get_stream(), &data);
|
||||||
}
|
}
|
||||||
State::Connected => {}
|
State::Connected => {}
|
||||||
@@ -273,9 +277,16 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
return State::Error;
|
return State::Error;
|
||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
|
let active_count = peers.get_peers_active_count();
|
||||||
let peer = peers.get_mut_peer(token).unwrap();
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
peer.set_height(height);
|
peer.set_height(height);
|
||||||
|
peer.set_active(true);
|
||||||
|
let mut context = context.lock().unwrap();
|
||||||
|
let blocks_count = context.blockchain.height();
|
||||||
|
context.bus.post(crate::event::Event::StatsCount { nodes: active_count, blocks: blocks_count });
|
||||||
if peer.is_higher(my_height) {
|
if peer.is_higher(my_height) {
|
||||||
|
context.blockchain.update_max_height(height);
|
||||||
|
context.bus.post(crate::event::Event::SyncStarted { have: my_height, height});
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
State::message(Message::GetPeers)
|
State::message(Message::GetPeers)
|
||||||
@@ -288,6 +299,7 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
Message::Ping { height } => {
|
Message::Ping { height } => {
|
||||||
let peer = peers.get_mut_peer(token).unwrap();
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
peer.set_height(height);
|
peer.set_height(height);
|
||||||
|
peer.set_active(true);
|
||||||
if peer.is_higher(my_height) {
|
if peer.is_higher(my_height) {
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
@@ -297,9 +309,14 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
Message::Pong { height } => {
|
Message::Pong { height } => {
|
||||||
let peer = peers.get_mut_peer(token).unwrap();
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
peer.set_height(height);
|
peer.set_height(height);
|
||||||
|
peer.set_active(true);
|
||||||
if peer.is_higher(my_height) {
|
if peer.is_higher(my_height) {
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
|
let mut context = context.lock().unwrap();
|
||||||
|
let blocks_count = context.blockchain.height();
|
||||||
|
context.bus.post(crate::event::Event::ActionIdle);
|
||||||
|
context.bus.post(crate::event::Event::StatsCount { nodes: peers.get_peers_active_count(), blocks: blocks_count });
|
||||||
State::idle()
|
State::idle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,12 +341,22 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
Ok(block) => block,
|
Ok(block) => block,
|
||||||
Err(_) => return State::Error
|
Err(_) => return State::Error
|
||||||
};
|
};
|
||||||
// TODO check if the block is good
|
// TODO check here if the block is good before trying to add
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut context = context.lock().unwrap();
|
let mut context = context.lock().unwrap();
|
||||||
|
let max_height = context.blockchain.max_height();
|
||||||
match context.blockchain.add_block(block) {
|
match context.blockchain.add_block(block) {
|
||||||
Ok(_) => { context.bus.post(crate::event::Event::BlockchainChanged); }
|
Ok(_) => {
|
||||||
|
let my_height = context.blockchain.height();
|
||||||
|
context.bus.post(crate::event::Event::BlockchainChanged);
|
||||||
|
// If it was the last block to sync
|
||||||
|
if my_height == max_height {
|
||||||
|
context.bus.post(crate::event::Event::ActionIdle);
|
||||||
|
} else {
|
||||||
|
context.bus.post(crate::event::Event::SyncStarted { have: my_height, height: max_height});
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(_) => { warn!("Discarded received block"); }
|
Err(_) => { warn!("Discarded received block"); }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+7
-2
@@ -10,11 +10,12 @@ pub struct Peer {
|
|||||||
height: u64,
|
height: u64,
|
||||||
inbound: bool,
|
inbound: bool,
|
||||||
public: bool,
|
public: bool,
|
||||||
|
active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Peer {
|
impl Peer {
|
||||||
pub fn new(addr: SocketAddr, stream: TcpStream, state: State, inbound: bool) -> Self {
|
pub fn new(addr: SocketAddr, stream: TcpStream, state: State, inbound: bool) -> Self {
|
||||||
Peer { addr, stream, state, height: 0, inbound, public: false }
|
Peer { addr, stream, state, height: 0, inbound, public: false, active: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_addr(&self) -> SocketAddr {
|
pub fn get_addr(&self) -> SocketAddr {
|
||||||
@@ -53,8 +54,12 @@ impl Peer {
|
|||||||
self.public = public;
|
self.public = public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_active(&mut self, active: bool) {
|
||||||
|
self.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn active(&self) -> bool {
|
pub fn active(&self) -> bool {
|
||||||
self.state.active()
|
self.active
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disabled(&self) -> bool {
|
pub fn disabled(&self) -> bool {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ impl Peers {
|
|||||||
|
|
||||||
if !peer.disabled() && !peer.is_inbound() {
|
if !peer.disabled() && !peer.is_inbound() {
|
||||||
peer.set_state(State::offline());
|
peer.set_state(State::offline());
|
||||||
|
peer.set_active(false);
|
||||||
} else {
|
} else {
|
||||||
self.peers.remove(token);
|
self.peers.remove(token);
|
||||||
}
|
}
|
||||||
@@ -112,6 +113,16 @@ impl Peers {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_peers_active_count(&self) -> usize {
|
||||||
|
let mut count = 0;
|
||||||
|
for (_, peer) in self.peers.iter() {
|
||||||
|
if peer.active() {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
pub fn skip_peer_connection(&self, addr: &SocketAddr) -> bool {
|
pub fn skip_peer_connection(&self, addr: &SocketAddr) -> bool {
|
||||||
for (_, peer) in self.peers.iter() {
|
for (_, peer) in self.peers.iter() {
|
||||||
if peer.equals(addr) && (!peer.is_public() || peer.active() || peer.disabled()) {
|
if peer.equals(addr) && (!peer.is_public() || peer.active() || peer.disabled()) {
|
||||||
|
|||||||
@@ -26,16 +26,6 @@ impl State {
|
|||||||
State::Message {data: Vec::from(response.as_bytes()) }
|
State::Message {data: Vec::from(response.as_bytes()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
State::Connecting => { true }
|
|
||||||
State::Connected => { true }
|
|
||||||
State::Idle { .. } => { true }
|
|
||||||
State::Message { .. } => { true }
|
|
||||||
_ => { false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_idle(&self) -> bool {
|
pub fn is_idle(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
State::Idle { .. } => { true }
|
State::Idle { .. } => { true }
|
||||||
|
|||||||
Vendored
+9
@@ -10846,4 +10846,13 @@ html {
|
|||||||
width: 50%;
|
width: 50%;
|
||||||
top: 10pt;
|
top: 10pt;
|
||||||
right: 10pt;
|
right: 10pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
padding: 0.2rem 0.5rem 0.2rem 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
z-index: 9;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
.busy_indicator {
|
||||||
|
width:24px;
|
||||||
|
height:24px;
|
||||||
|
display:inline-block;
|
||||||
|
padding:0px;
|
||||||
|
text-align:left;
|
||||||
|
float:left;
|
||||||
|
margin-left: -5px;
|
||||||
|
}
|
||||||
|
.busy_indicator span {
|
||||||
|
position:absolute;
|
||||||
|
display:inline-block;
|
||||||
|
width:24px;
|
||||||
|
height:24px;
|
||||||
|
border-radius:100%;
|
||||||
|
background:#ee3333;
|
||||||
|
-webkit-animation:busy_indicator 1.6s linear infinite;
|
||||||
|
animation:busy_indicator 1.6s linear infinite;
|
||||||
|
}
|
||||||
|
.busy_indicator span:last-child {
|
||||||
|
animation-delay:-0.8s;
|
||||||
|
-webkit-animation-delay:-0.8s;
|
||||||
|
}
|
||||||
|
@keyframes busy_indicator {
|
||||||
|
0% {transform: scale(0, 0);opacity:0.9;}
|
||||||
|
100% {transform: scale(1, 1);opacity:0;}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes busy_indicator {
|
||||||
|
0% {-webkit-transform: scale(0, 0);opacity:0.9;}
|
||||||
|
100% {-webkit-transform: scale(1, 1);opacity:0;}
|
||||||
|
}
|
||||||
|
.busy_blue span {
|
||||||
|
background:#3273dc;
|
||||||
|
}
|
||||||
+20
-5
@@ -9,10 +9,6 @@
|
|||||||
{scripts}
|
{scripts}
|
||||||
</head>
|
</head>
|
||||||
<body onload="onLoad();">
|
<body onload="onLoad();">
|
||||||
<div class="mining_indicator" id="mining_indicator" onclick="miningIndicatorClick(this)">
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="modal_dialog" class="modal">
|
<div id="modal_dialog" class="modal">
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
@@ -328,6 +324,25 @@
|
|||||||
</div> <!-- columns -->
|
</div> <!-- columns -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer is-hidden">Some footer text is here</div>
|
<div class="footer is-family-code">
|
||||||
|
<div class="level">
|
||||||
|
<div class="level-left">
|
||||||
|
<div class="level-item" id="indicator_parent">
|
||||||
|
<div class="busy_indicator busy_blue" id="busy_indicator" onclick="miningIndicatorClick(this)">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-item">
|
||||||
|
<div id="status_bar_left">Connecting and syncing...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="level-right">
|
||||||
|
<div class="level-item" id="status_bar_right">No data</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
.mining_indicator {
|
|
||||||
position:absolute;
|
|
||||||
left:0px;
|
|
||||||
bottom:0px;
|
|
||||||
width:30px;
|
|
||||||
height:30px;
|
|
||||||
display:inline-block;
|
|
||||||
padding:0px;
|
|
||||||
text-align:left;
|
|
||||||
float:left;
|
|
||||||
z-index:10;
|
|
||||||
}
|
|
||||||
.mining_indicator span {
|
|
||||||
position:absolute;
|
|
||||||
display:inline-block;
|
|
||||||
width:30px;
|
|
||||||
height:30px;
|
|
||||||
border-radius:100%;
|
|
||||||
background:#ee3333;
|
|
||||||
-webkit-animation:mining_indicator 1.6s linear infinite;
|
|
||||||
animation:mining_indicator 1.6s linear infinite;
|
|
||||||
}
|
|
||||||
.mining_indicator span:last-child {
|
|
||||||
animation-delay:-0.8s;
|
|
||||||
-webkit-animation-delay:-0.8s;
|
|
||||||
}
|
|
||||||
@keyframes mining_indicator {
|
|
||||||
0% {transform: scale(0, 0);opacity:0.5;}
|
|
||||||
100% {transform: scale(1, 1);opacity:0;}
|
|
||||||
}
|
|
||||||
@-webkit-keyframes mining_indicator {
|
|
||||||
0% {-webkit-transform: scale(0, 0);opacity:0.5;}
|
|
||||||
100% {-webkit-transform: scale(1, 1);opacity:0;}
|
|
||||||
}
|
|
||||||
+21
-4
@@ -249,12 +249,19 @@ function showWarning(text) {
|
|||||||
setTimeout(button.onclick, 5000);
|
setTimeout(button.onclick, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMiningIndicator(visible) {
|
function showMiningIndicator(visible, blue) {
|
||||||
indicator = document.getElementById("mining_indicator");
|
var indicator = document.getElementById("busy_indicator");
|
||||||
|
var parent = document.getElementById("indicator_parent");
|
||||||
|
var add = "";
|
||||||
|
if (blue) {
|
||||||
|
add = " busy_blue";
|
||||||
|
}
|
||||||
if (visible) {
|
if (visible) {
|
||||||
indicator.style.visibility = 'visible';
|
indicator.className = 'busy_indicator' + add;
|
||||||
|
parent.style.display = 'flex';
|
||||||
} else {
|
} else {
|
||||||
indicator.style.visibility = 'hidden';
|
indicator.className = 'busy_indicator is-hidden';
|
||||||
|
parent.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,6 +271,16 @@ function miningIndicatorClick(element) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setLeftStatusBarText(text) {
|
||||||
|
var bar = document.getElementById("status_bar_left");
|
||||||
|
bar.innerHTML = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRightStatusBarText(text) {
|
||||||
|
var bar = document.getElementById("status_bar_right");
|
||||||
|
bar.innerHTML = text;
|
||||||
|
}
|
||||||
|
|
||||||
function keystoreChanged(path, pub_key) {
|
function keystoreChanged(path, pub_key) {
|
||||||
if (path == '') {
|
if (path == '') {
|
||||||
path = "In memory";
|
path = "In memory";
|
||||||
|
|||||||
Reference in New Issue
Block a user