wip
This commit is contained in:
@@ -19,7 +19,7 @@ use gtk::{
|
||||
};
|
||||
|
||||
|
||||
pub fn menu_credentials(window: &ApplicationWindow, parent: >k::Box, context: &Arc<Mutex<Context>>) {
|
||||
pub fn menu(window: &ApplicationWindow, parent: >k::Box, context: &Arc<Mutex<Context>>) {
|
||||
let key_data = Rc::new(RefCell::from(KeyData{hash: String::new(), path: String::new(), public: String::new()}));
|
||||
let keys = Box::new(Orientation::Horizontal, 8);
|
||||
keys.set_hexpand(true);
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
use std::{
|
||||
sync::{Arc, MutexGuard},
|
||||
rc::Rc, cell::RefCell
|
||||
};
|
||||
|
||||
use alfis::{
|
||||
blockchain::{
|
||||
types::MineResult,
|
||||
transaction::DomainData
|
||||
},
|
||||
crypto::CryptoBox,
|
||||
Keystore,
|
||||
Block,
|
||||
Bytes,
|
||||
Transaction,
|
||||
from_hex,
|
||||
is_yggdrasil_record,
|
||||
CLASS_DOMAIN,
|
||||
DOMAIN_LIFETIME,
|
||||
DOMAIN_DIFFICULTY,
|
||||
MAX_RECORDS
|
||||
};
|
||||
|
||||
use crate::{Mutex, Context, Miner, ui::KeyData};
|
||||
use log::{debug, error, info, warn};
|
||||
use chrono::Utc;
|
||||
|
||||
use gtk::{
|
||||
prelude::*,
|
||||
AlertDialog,
|
||||
ApplicationWindow,
|
||||
Box,
|
||||
Button,
|
||||
Entry,
|
||||
FileDialog,
|
||||
Label,
|
||||
Orientation,
|
||||
Overlay,
|
||||
Popover
|
||||
};
|
||||
|
||||
|
||||
struct Domain<'a> {
|
||||
domain: &'a str,
|
||||
timestamp: u32,
|
||||
d: &'a str,
|
||||
}
|
||||
|
||||
|
||||
pub fn menu(app: &adw::Application, window: &ApplicationWindow, parent: >k::Box, context: &Arc<Mutex<Context>>, miner: &Arc<Mutex<Miner>>) {
|
||||
// let new_domain_btn = Button::with_label("New domain");
|
||||
let new_domain_btn = Button::from_icon_name("list-add");
|
||||
new_domain_btn.add_css_class("suggested-action");
|
||||
new_domain_btn.set_halign(gtk::Align::End);
|
||||
new_domain_btn.set_hexpand(false);
|
||||
parent.append(&new_domain_btn);
|
||||
|
||||
// let new_domain_child = Box::new(Orientation::Vertical, 16);
|
||||
|
||||
// let new_domain_desc = Box::new(Orientation::Horizontal, 8);
|
||||
// new_domain_child.append(&new_domain_desc);
|
||||
|
||||
// let domain_entry = Entry::builder()
|
||||
// .placeholder_text("example")
|
||||
// .hexpand(true)
|
||||
// .build();
|
||||
// new_domain_desc.append(&domain_entry);
|
||||
|
||||
// let new_domain_pop = Popover::builder()
|
||||
// .autohide(true)
|
||||
// .child(&new_domain_child)
|
||||
// .build();
|
||||
// parent.append(&new_domain_pop);
|
||||
|
||||
// let _ = new_domain_btn.connect_clicked(move |_| { new_domain_pop.popup(); });
|
||||
|
||||
// let win = ApplicationWindow::builder()
|
||||
// .application(app)
|
||||
// .title("Мое модальное окно")
|
||||
// .default_width(400)
|
||||
// .default_height(300)
|
||||
// .modal(true) // Это делает окно модальным
|
||||
// .build();
|
||||
|
||||
// win.set_child(Some(&Label::new(Some("Meow"))));
|
||||
|
||||
// // Устанавливаем родительское окно (допустим, `parent_window` - это ссылка на главное окно)
|
||||
// parent.append(&win);
|
||||
// // let tmp_modal = AlertDialog::builder()
|
||||
// // .message("This is the test message")
|
||||
// // .modal(true)
|
||||
// // .build();
|
||||
// let tmp_layout = Overlay::builder()
|
||||
// .child(&Label::new(Some("This is the test message")))
|
||||
// .build();
|
||||
// parent.append(&tmp_layout);
|
||||
// // tmp_modal.show(Some(window));
|
||||
}
|
||||
|
||||
fn load_domains(context: &mut MutexGuard<Context>) {
|
||||
// let _ = handle.dispatch(move |web_view|{
|
||||
// web_view.eval("clearMyDomains();")
|
||||
// });
|
||||
let domains = context.chain.get_my_domains(context.get_keystore());
|
||||
let mut domains = domains.iter().map(|(_, d)| d).collect::<Vec<_>>();
|
||||
domains.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
for (domain, timestamp, data) in domains {
|
||||
let d = serde_json::to_string(&data).unwrap();
|
||||
let d = d.replace("'", "\\'").replace("\\n", "\\\\n").replace("\"", "\\\"");
|
||||
let command = format!("addMyDomain('{}', {}, {}, '{}');", &domain, timestamp, timestamp + DOMAIN_LIFETIME, &d);
|
||||
// let _ = handle.dispatch(move |web_view|{
|
||||
// web_view.eval(&command)
|
||||
// });
|
||||
}
|
||||
// let _ = handle.dispatch(move |web_view|{
|
||||
// web_view.eval("refreshMyDomains();")
|
||||
// });
|
||||
}
|
||||
|
||||
fn action_create_domain(
|
||||
context: Arc<Mutex<Context>>,
|
||||
miner: Arc<Mutex<Miner>>,
|
||||
name: String,
|
||||
data: String,
|
||||
signing: String,
|
||||
encryption: String,
|
||||
renewal: bool
|
||||
) {
|
||||
debug!("Creating domain with data: {}", &data);
|
||||
let c = Arc::clone(&context);
|
||||
let context = context.lock().unwrap();
|
||||
if !context.has_keys() {
|
||||
// show_warning(web_view, "You don't have keys loaded!<br>Load or mine the keys and try again.");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
return;
|
||||
}
|
||||
if context.chain.is_waiting_signers() {
|
||||
// show_warning(web_view, "Waiting for last full block to be signed. Try again later.");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
info!("Waiting for last full block to be signed. Try again later.");
|
||||
return;
|
||||
}
|
||||
let keystore = context.get_keystore().unwrap().clone();
|
||||
let pub_key = keystore.get_public();
|
||||
let data = match serde_json::from_str::<DomainData>(&data) {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
// show_warning(web_view, "Something wrong with domain data. I cannot mine it.");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
warn!("Error parsing data: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
info!("Parsed domain data:\n{:#?}", &data);
|
||||
if data.records.len() > MAX_RECORDS {
|
||||
// show_warning(web_view, "Too many records. Mining more than 30 records not allowed.");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
return;
|
||||
}
|
||||
// Check if yggdrasil only quality of zone is not violated
|
||||
let zones = context.chain.get_zones();
|
||||
for z in zones {
|
||||
if z.name == data.zone && z.yggdrasil {
|
||||
for record in &data.records {
|
||||
if !is_yggdrasil_record(record) {
|
||||
// show_warning(web_view, &format!("Zone {} is Yggdrasil only, you cannot use IPs from clearnet!", &data.zone));
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let (signing, encryption) = if signing.is_empty() || encryption.is_empty() {
|
||||
(keystore.get_public(), keystore.get_encryption_public())
|
||||
} else {
|
||||
(Bytes::new(from_hex(&signing).unwrap()), Bytes::new(from_hex(&encryption).unwrap()))
|
||||
};
|
||||
match context.chain.can_mine_domain(context.chain.get_height(), &name, &pub_key) {
|
||||
MineResult::Fine => {
|
||||
drop(context);
|
||||
create_domain(c, miner, CLASS_DOMAIN, &name, data, DOMAIN_DIFFICULTY, &keystore, signing, encryption, renewal);
|
||||
// let _ = web_view.eval("domainMiningStarted();");
|
||||
// event_info(web_view, &format!("Mining of domain \\'{}\\' has started", &name));
|
||||
}
|
||||
MineResult::WrongName => {
|
||||
// show_warning(web_view, "You can't mine this domain!");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
}
|
||||
MineResult::WrongData => {
|
||||
// show_warning(web_view, "You have an error in records!");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
}
|
||||
MineResult::WrongKey => {
|
||||
// show_warning(web_view, "You can't mine with current key!");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
}
|
||||
MineResult::WrongZone => {
|
||||
// show_warning(web_view, "You can't mine domain in this zone!");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
}
|
||||
MineResult::NotOwned => {
|
||||
// show_warning(web_view, "This domain is already taken, and it is not yours!");
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
}
|
||||
MineResult::Cooldown { time } => {
|
||||
// event_info(web_view, &format!("You have cooldown {}!", format_cooldown(time)));
|
||||
// show_warning(web_view, &format!("You have cooldown {}!", format_cooldown(time)));
|
||||
// let _ = web_view.eval("domainMiningUnavailable();");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_domain(
|
||||
context: Arc<Mutex<Context>>,
|
||||
miner: Arc<Mutex<Miner>>,
|
||||
class: &str,
|
||||
name: &str,
|
||||
mut data: DomainData,
|
||||
difficulty: u32,
|
||||
keystore: &Keystore,
|
||||
signing: Bytes,
|
||||
encryption: Bytes,
|
||||
renewal: bool
|
||||
) {
|
||||
let name = name.to_owned();
|
||||
let encrypted = CryptoBox::encrypt(encryption.as_slice(), name.as_bytes()).expect("Error encrypting domain name!");
|
||||
data.encrypted = Bytes::from_bytes(&encrypted);
|
||||
|
||||
let data = serde_json::to_string(&data).unwrap();
|
||||
let (signing, encryption) = if signing.is_empty() || encryption.is_empty() {
|
||||
(keystore.get_public(), keystore.get_encryption_public())
|
||||
} else {
|
||||
(signing, encryption)
|
||||
};
|
||||
let transaction = Transaction::from_str(name, class.to_owned(), data, signing, encryption);
|
||||
// If this domain is already in blockchain we approve slightly smaller difficulty
|
||||
let height = context.lock().unwrap().chain.get_height();
|
||||
let discount = context.lock().unwrap().chain.get_identity_discount(&transaction.identity, renewal, height, Utc::now().timestamp());
|
||||
let block = Block::new(Some(transaction), keystore.get_public(), Bytes::default(), difficulty - discount);
|
||||
miner.lock().unwrap().add_block(block, keystore.clone());
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,5 +1,6 @@
|
||||
#[warn(unused_imports)]
|
||||
mod credentails;
|
||||
mod domains;
|
||||
|
||||
use alfis::{
|
||||
blockchain::{
|
||||
@@ -52,6 +53,7 @@ pub fn run_ui(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) -> glib::E
|
||||
.build();
|
||||
|
||||
let context = context.clone();
|
||||
let miner = miner.clone();
|
||||
application.connect_activate(move |app| {
|
||||
let window = ApplicationWindow::builder()
|
||||
.application(app)
|
||||
@@ -66,11 +68,14 @@ pub fn run_ui(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) -> glib::E
|
||||
let nb = Notebook::new();
|
||||
window.set_child(Some(&nb));
|
||||
|
||||
let main = Box::new(Orientation::Vertical, 5);
|
||||
credentails::menu_credentials(&window, &main, &context);
|
||||
let credentails = Box::new(Orientation::Vertical, 4);
|
||||
credentails::menu(&window, &credentails, &context);
|
||||
|
||||
let domains = Box::new(Orientation::Vertical, 4);
|
||||
domains::menu(app, &window, &domains, &context, &miner);
|
||||
|
||||
nb.append_page(&main, Some(&Label::new(Some("Credentials"))));
|
||||
nb.append_page(&credentails, Some(&Label::new(Some("Credentials"))));
|
||||
nb.append_page(&domains, Some(&Label::new(Some("Domains"))));
|
||||
|
||||
window.present();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user