mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 19:49:24 +00:00
testing customer to vendor product ux
This commit is contained in:
parent
a2f8041f59
commit
bbc817d263
8 changed files with 147 additions and 63 deletions
|
@ -175,14 +175,16 @@ pub async fn request_invoice(contact: String) -> Result<reqres::Invoice, Box<dyn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send the request to contact to add them
|
/// Send the request to contact to add them. Set the prune arg to 1
|
||||||
pub async fn add_contact_request(contact: String) -> Result<Contact, Box<dyn Error>> {
|
///
|
||||||
|
/// for gpg key removal.
|
||||||
|
pub async fn add_contact_request(contact: String, prune: u32) -> Result<Contact, Box<dyn Error>> {
|
||||||
// TODO(c2m): Error handling for http 402 status
|
// TODO(c2m): Error handling for http 402 status
|
||||||
let host = utils::get_i2p_http_proxy();
|
let host = utils::get_i2p_http_proxy();
|
||||||
let proxy = reqwest::Proxy::http(&host)?;
|
let proxy = reqwest::Proxy::http(&host)?;
|
||||||
let client = reqwest::Client::builder().proxy(proxy).build();
|
let client = reqwest::Client::builder().proxy(proxy).build();
|
||||||
match client?
|
match client?
|
||||||
.get(format!("http://{}/share", contact))
|
.get(format!("http://{}/share/{}", contact, prune))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,6 +82,7 @@ pub fn find_all() -> Vec<Product> {
|
||||||
|
|
||||||
/// Modify product
|
/// Modify product
|
||||||
pub fn modify(p: Json<Product>) -> Product {
|
pub fn modify(p: Json<Product>) -> Product {
|
||||||
|
// TODO(c2m): don't allow modification to products with un-delivered orders
|
||||||
info!("modify product: {}", &p.pid);
|
info!("modify product: {}", &p.pid);
|
||||||
let f_prod: Product = find(&p.pid);
|
let f_prod: Product = find(&p.pid);
|
||||||
if f_prod.pid == utils::empty_string() {
|
if f_prod.pid == utils::empty_string() {
|
||||||
|
@ -143,7 +144,7 @@ pub async fn get_vendor_product(
|
||||||
let proxy = reqwest::Proxy::http(&host)?;
|
let proxy = reqwest::Proxy::http(&host)?;
|
||||||
let client = reqwest::Client::builder().proxy(proxy).build();
|
let client = reqwest::Client::builder().proxy(proxy).build();
|
||||||
match client?
|
match client?
|
||||||
.get(format!("http://{}/market/product/{}", contact, pid))
|
.get(format!("http://{}/market/{}", contact, pid))
|
||||||
.header("proof", jwp)
|
.header("proof", jwp)
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -29,6 +29,8 @@ pub struct ContactStatus {
|
||||||
pub h_exp: String,
|
pub h_exp: String,
|
||||||
/// i2p address of current status check
|
/// i2p address of current status check
|
||||||
pub i2p: String,
|
pub i2p: String,
|
||||||
|
/// update vendor status of contact
|
||||||
|
pub is_vendor: bool,
|
||||||
/// JSON Web Proof of current status check
|
/// JSON Web Proof of current status check
|
||||||
pub jwp: String,
|
pub jwp: String,
|
||||||
/// Alias for contact
|
/// Alias for contact
|
||||||
|
@ -45,6 +47,7 @@ impl Default for ContactStatus {
|
||||||
exp: utils::empty_string(),
|
exp: utils::empty_string(),
|
||||||
h_exp: utils::empty_string(),
|
h_exp: utils::empty_string(),
|
||||||
i2p: utils::empty_string(),
|
i2p: utils::empty_string(),
|
||||||
|
is_vendor: false,
|
||||||
jwp: utils::empty_string(),
|
jwp: utils::empty_string(),
|
||||||
nick: String::from("anon"),
|
nick: String::from("anon"),
|
||||||
signed_key: false,
|
signed_key: false,
|
||||||
|
|
|
@ -446,7 +446,7 @@ impl eframe::App for AddressBookApp {
|
||||||
if ui.button("Add").clicked() {
|
if ui.button("Add").clicked() {
|
||||||
// Get the contacts information from the /share API
|
// Get the contacts information from the /share API
|
||||||
let contact = self.contact.clone();
|
let contact = self.contact.clone();
|
||||||
send_contact_info_req(self.contact_info_tx.clone(), ctx.clone(), contact);
|
send_contact_info_req(self.contact_info_tx.clone(), ctx.clone(), contact, 0);
|
||||||
add_contact_timeout(self.contact_timeout_tx.clone(), ctx.clone());
|
add_contact_timeout(self.contact_timeout_tx.clone(), ctx.clone());
|
||||||
self.is_adding = true;
|
self.is_adding = true;
|
||||||
}
|
}
|
||||||
|
@ -548,6 +548,7 @@ impl eframe::App for AddressBookApp {
|
||||||
self.contact_info_tx.clone(),
|
self.contact_info_tx.clone(),
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
self.status.i2p.clone(),
|
self.status.i2p.clone(),
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
self.showing_status = true;
|
self.showing_status = true;
|
||||||
self.is_pinging = true;
|
self.is_pinging = true;
|
||||||
|
@ -579,10 +580,15 @@ impl eframe::App for AddressBookApp {
|
||||||
|
|
||||||
// Send asyc requests to neveko-core
|
// Send asyc requests to neveko-core
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
fn send_contact_info_req(tx: Sender<models::Contact>, ctx: egui::Context, contact: String) {
|
fn send_contact_info_req(
|
||||||
|
tx: Sender<models::Contact>,
|
||||||
|
ctx: egui::Context,
|
||||||
|
contact: String,
|
||||||
|
prune: u32,
|
||||||
|
) {
|
||||||
log::debug!("async send_contact_info_req");
|
log::debug!("async send_contact_info_req");
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
match contact::add_contact_request(contact).await {
|
match contact::add_contact_request(contact, prune).await {
|
||||||
Ok(contact) => {
|
Ok(contact) => {
|
||||||
let _ = tx.send(contact);
|
let _ = tx.send(contact);
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
|
|
|
@ -7,11 +7,14 @@ use std::sync::mpsc::{
|
||||||
pub struct MarketApp {
|
pub struct MarketApp {
|
||||||
contact_info_tx: Sender<models::Contact>,
|
contact_info_tx: Sender<models::Contact>,
|
||||||
contact_info_rx: Receiver<models::Contact>,
|
contact_info_rx: Receiver<models::Contact>,
|
||||||
|
contact_timeout_tx: Sender<bool>,
|
||||||
|
contact_timeout_rx: Receiver<bool>,
|
||||||
find_vendor: String,
|
find_vendor: String,
|
||||||
get_vendor_products_tx: Sender<Vec<models::Product>>,
|
get_vendor_products_tx: Sender<Vec<models::Product>>,
|
||||||
get_vendor_products_rx: Receiver<Vec<models::Product>>,
|
get_vendor_products_rx: Receiver<Vec<models::Product>>,
|
||||||
get_vendor_product_tx: Sender<models::Product>,
|
get_vendor_product_tx: Sender<models::Product>,
|
||||||
get_vendor_product_rx: Receiver<models::Product>,
|
get_vendor_product_rx: Receiver<models::Product>,
|
||||||
|
is_loading: bool,
|
||||||
is_ordering: bool,
|
is_ordering: bool,
|
||||||
is_pinging: bool,
|
is_pinging: bool,
|
||||||
is_product_image_set: bool,
|
is_product_image_set: bool,
|
||||||
|
@ -21,6 +24,7 @@ pub struct MarketApp {
|
||||||
is_showing_orders: bool,
|
is_showing_orders: bool,
|
||||||
is_showing_vendor_status: bool,
|
is_showing_vendor_status: bool,
|
||||||
is_showing_vendors: bool,
|
is_showing_vendors: bool,
|
||||||
|
is_timeout: bool,
|
||||||
is_vendor_enabled: bool,
|
is_vendor_enabled: bool,
|
||||||
is_window_shopping: bool,
|
is_window_shopping: bool,
|
||||||
orders: Vec<models::Order>,
|
orders: Vec<models::Order>,
|
||||||
|
@ -36,13 +40,13 @@ pub struct MarketApp {
|
||||||
_refresh_on_delete_product_tx: Sender<bool>,
|
_refresh_on_delete_product_tx: Sender<bool>,
|
||||||
_refresh_on_delete_product_rx: Receiver<bool>,
|
_refresh_on_delete_product_rx: Receiver<bool>,
|
||||||
s_contact: models::Contact,
|
s_contact: models::Contact,
|
||||||
showing_vendor_status: bool,
|
|
||||||
vendor_status: utils::ContactStatus,
|
vendor_status: utils::ContactStatus,
|
||||||
vendors: Vec<models::Contact>,
|
vendors: Vec<models::Contact>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MarketApp {
|
impl Default for MarketApp {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
let (contact_timeout_tx, contact_timeout_rx) = std::sync::mpsc::channel();
|
||||||
let (_refresh_on_delete_product_tx, _refresh_on_delete_product_rx) =
|
let (_refresh_on_delete_product_tx, _refresh_on_delete_product_rx) =
|
||||||
std::sync::mpsc::channel();
|
std::sync::mpsc::channel();
|
||||||
let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
|
let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
|
||||||
|
@ -55,11 +59,14 @@ impl Default for MarketApp {
|
||||||
MarketApp {
|
MarketApp {
|
||||||
contact_info_rx,
|
contact_info_rx,
|
||||||
contact_info_tx,
|
contact_info_tx,
|
||||||
|
contact_timeout_rx,
|
||||||
|
contact_timeout_tx,
|
||||||
find_vendor: utils::empty_string(),
|
find_vendor: utils::empty_string(),
|
||||||
get_vendor_products_rx,
|
get_vendor_products_rx,
|
||||||
get_vendor_products_tx,
|
get_vendor_products_tx,
|
||||||
get_vendor_product_rx,
|
get_vendor_product_rx,
|
||||||
get_vendor_product_tx,
|
get_vendor_product_tx,
|
||||||
|
is_loading: false,
|
||||||
is_ordering: false,
|
is_ordering: false,
|
||||||
is_pinging: false,
|
is_pinging: false,
|
||||||
is_product_image_set: false,
|
is_product_image_set: false,
|
||||||
|
@ -69,6 +76,7 @@ impl Default for MarketApp {
|
||||||
is_showing_product_update: false,
|
is_showing_product_update: false,
|
||||||
is_showing_vendor_status: false,
|
is_showing_vendor_status: false,
|
||||||
is_showing_vendors: false,
|
is_showing_vendors: false,
|
||||||
|
is_timeout: false,
|
||||||
is_vendor_enabled,
|
is_vendor_enabled,
|
||||||
is_window_shopping: false,
|
is_window_shopping: false,
|
||||||
orders: Vec::new(),
|
orders: Vec::new(),
|
||||||
|
@ -88,7 +96,6 @@ impl Default for MarketApp {
|
||||||
_refresh_on_delete_product_tx,
|
_refresh_on_delete_product_tx,
|
||||||
_refresh_on_delete_product_rx,
|
_refresh_on_delete_product_rx,
|
||||||
s_contact: Default::default(),
|
s_contact: Default::default(),
|
||||||
showing_vendor_status: false,
|
|
||||||
vendor_status: Default::default(),
|
vendor_status: Default::default(),
|
||||||
vendors: Vec::new(),
|
vendors: Vec::new(),
|
||||||
}
|
}
|
||||||
|
@ -99,17 +106,54 @@ impl eframe::App for MarketApp {
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
// Hook into async channel threads
|
// Hook into async channel threads
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
if let Ok(contact_info) = self.contact_info_rx.try_recv() {
|
if let Ok(contact_info) = self.contact_info_rx.try_recv() {
|
||||||
self.s_contact = contact_info;
|
self.s_contact = contact_info;
|
||||||
if self.s_contact.xmr_address != utils::empty_string() {
|
if self.s_contact.xmr_address != utils::empty_string() {
|
||||||
self.is_pinging = false;
|
self.is_pinging = false;
|
||||||
|
self.vendor_status.is_vendor = self.s_contact.is_vendor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(vendor_products) = self.get_vendor_products_rx.try_recv() {
|
if let Ok(vendor_products) = self.get_vendor_products_rx.try_recv() {
|
||||||
|
self.is_loading = false;
|
||||||
self.products = vendor_products;
|
self.products = vendor_products;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(vendor_product) = self.get_vendor_product_rx.try_recv() {
|
if let Ok(vendor_product) = self.get_vendor_product_rx.try_recv() {
|
||||||
|
self.is_loading = false;
|
||||||
|
if !vendor_product.image.is_empty() {
|
||||||
|
// only pull image from vendor when we want to view
|
||||||
|
let file_path = format!(
|
||||||
|
"/home/{}/.neveko/{}.jpeg",
|
||||||
|
std::env::var("USER").unwrap_or(String::from("user")),
|
||||||
|
vendor_product.pid
|
||||||
|
);
|
||||||
|
if self.is_window_shopping {
|
||||||
|
self.is_loading = true;
|
||||||
|
let contents = std::fs::read(&file_path).unwrap_or(Vec::new());
|
||||||
|
// this image should uwrap if vendor image bytes are
|
||||||
|
// bad
|
||||||
|
let default_img = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
|
||||||
|
let default_r_img =
|
||||||
|
egui_extras::RetainedImage::from_image_bytes("qr.png", &default_img)
|
||||||
|
.unwrap();
|
||||||
|
self.product_image =
|
||||||
|
egui_extras::RetainedImage::from_image_bytes(file_path, &contents)
|
||||||
|
.unwrap_or(default_r_img);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.product_from_vendor = vendor_product;
|
self.product_from_vendor = vendor_product;
|
||||||
|
self.is_product_image_set = true;
|
||||||
|
self.is_showing_product_image = true;
|
||||||
|
self.is_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(timeout) = self.contact_timeout_rx.try_recv() {
|
||||||
|
self.is_timeout = true;
|
||||||
|
if timeout {
|
||||||
|
self.is_pinging = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(c2m): create order form
|
// TODO(c2m): create order form
|
||||||
|
@ -163,7 +207,7 @@ impl eframe::App for MarketApp {
|
||||||
})
|
})
|
||||||
.body(|mut body| {
|
.body(|mut body| {
|
||||||
for v in &self.vendors {
|
for v in &self.vendors {
|
||||||
if v.i2p_address.contains(&self.find_vendor) && v.is_vendor {
|
if v.i2p_address.contains(&self.find_vendor) {
|
||||||
let row_height = 20.0;
|
let row_height = 20.0;
|
||||||
body.row(row_height, |mut row| {
|
body.row(row_height, |mut row| {
|
||||||
row.col(|ui| {
|
row.col(|ui| {
|
||||||
|
@ -195,6 +239,7 @@ impl eframe::App for MarketApp {
|
||||||
String::from("gui-jwp"),
|
String::from("gui-jwp"),
|
||||||
String::from(&v.i2p_address),
|
String::from(&v.i2p_address),
|
||||||
);
|
);
|
||||||
|
log::debug!("jwp: {}", self.vendor_status.jwp);
|
||||||
let r_exp = utils::search_gui_db(
|
let r_exp = utils::search_gui_db(
|
||||||
String::from("gui-exp"),
|
String::from("gui-exp"),
|
||||||
String::from(&v.i2p_address),
|
String::from(&v.i2p_address),
|
||||||
|
@ -220,7 +265,11 @@ impl eframe::App for MarketApp {
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
self.vendor_status.i2p.clone(),
|
self.vendor_status.i2p.clone(),
|
||||||
);
|
);
|
||||||
self.showing_vendor_status = true;
|
vendor_status_timeout(
|
||||||
|
self.contact_timeout_tx.clone(),
|
||||||
|
ctx.clone(),
|
||||||
|
);
|
||||||
|
self.is_showing_vendor_status = true;
|
||||||
self.is_pinging = true;
|
self.is_pinging = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -234,8 +283,10 @@ impl eframe::App for MarketApp {
|
||||||
&& self.vendor_status.signed_key
|
&& self.vendor_status.signed_key
|
||||||
&& self.vendor_status.jwp != utils::empty_string()
|
&& self.vendor_status.jwp != utils::empty_string()
|
||||||
&& v.i2p_address == self.vendor_status.i2p
|
&& v.i2p_address == self.vendor_status.i2p
|
||||||
|
&& self.vendor_status.is_vendor
|
||||||
{
|
{
|
||||||
if ui.button("View Products").clicked() {
|
if ui.button("View Products").clicked() {
|
||||||
|
self.is_loading = true;
|
||||||
send_products_from_vendor_req(
|
send_products_from_vendor_req(
|
||||||
self.get_vendor_products_tx.clone(),
|
self.get_vendor_products_tx.clone(),
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
|
@ -244,6 +295,7 @@ impl eframe::App for MarketApp {
|
||||||
);
|
);
|
||||||
self.is_window_shopping = true;
|
self.is_window_shopping = true;
|
||||||
self.is_showing_products = true;
|
self.is_showing_products = true;
|
||||||
|
self.is_showing_vendors = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -274,7 +326,13 @@ impl eframe::App for MarketApp {
|
||||||
} else {
|
} else {
|
||||||
"offline"
|
"offline"
|
||||||
};
|
};
|
||||||
|
let mode = if self.vendor_status.is_vendor {
|
||||||
|
"enabled "
|
||||||
|
} else {
|
||||||
|
"disabled"
|
||||||
|
};
|
||||||
ui.label(format!("status: {}", status));
|
ui.label(format!("status: {}", status));
|
||||||
|
ui.label(format!("vendor mode: {}", mode));
|
||||||
ui.label(format!("nick: {}", self.vendor_status.nick));
|
ui.label(format!("nick: {}", self.vendor_status.nick));
|
||||||
ui.label(format!("tx proof: {}", self.vendor_status.txp));
|
ui.label(format!("tx proof: {}", self.vendor_status.txp));
|
||||||
ui.label(format!("jwp: {}", self.vendor_status.jwp));
|
ui.label(format!("jwp: {}", self.vendor_status.jwp));
|
||||||
|
@ -314,7 +372,10 @@ impl eframe::App for MarketApp {
|
||||||
Column,
|
Column,
|
||||||
TableBuilder,
|
TableBuilder,
|
||||||
};
|
};
|
||||||
|
if self.is_loading {
|
||||||
|
ui.add(egui::Spinner::new());
|
||||||
|
ui.label("loading...");
|
||||||
|
}
|
||||||
let table = TableBuilder::new(ui)
|
let table = TableBuilder::new(ui)
|
||||||
.striped(true)
|
.striped(true)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
|
@ -367,7 +428,6 @@ impl eframe::App for MarketApp {
|
||||||
row.col(|ui| {
|
row.col(|ui| {
|
||||||
if ui.button("View").clicked() {
|
if ui.button("View").clicked() {
|
||||||
if !self.is_product_image_set {
|
if !self.is_product_image_set {
|
||||||
self.is_showing_product_image = true;
|
|
||||||
let file_path = format!(
|
let file_path = format!(
|
||||||
"/home/{}/.neveko/{}.jpeg",
|
"/home/{}/.neveko/{}.jpeg",
|
||||||
std::env::var("USER")
|
std::env::var("USER")
|
||||||
|
@ -376,9 +436,8 @@ impl eframe::App for MarketApp {
|
||||||
);
|
);
|
||||||
// For the sake of brevity product list doesn't have
|
// For the sake of brevity product list doesn't have
|
||||||
// image bytes, get them
|
// image bytes, get them
|
||||||
let mut i_product = product::find(&p.pid);
|
|
||||||
// only pull image from vendor when we want to view
|
|
||||||
if self.is_window_shopping {
|
if self.is_window_shopping {
|
||||||
|
self.is_loading = true;
|
||||||
send_product_from_vendor_req(
|
send_product_from_vendor_req(
|
||||||
self.get_vendor_product_tx.clone(),
|
self.get_vendor_product_tx.clone(),
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
|
@ -386,52 +445,38 @@ impl eframe::App for MarketApp {
|
||||||
self.vendor_status.jwp.clone(),
|
self.vendor_status.jwp.clone(),
|
||||||
String::from(&p.pid),
|
String::from(&p.pid),
|
||||||
);
|
);
|
||||||
let e_product: models::Product = models::Product {
|
} else {
|
||||||
pid: self.product_from_vendor.pid.clone(),
|
let i_product = product::find(&p.pid);
|
||||||
description: self
|
match std::fs::write(&file_path, &i_product.image) {
|
||||||
.product_from_vendor
|
Ok(w) => w,
|
||||||
.description
|
Err(_) => {
|
||||||
.clone(),
|
log::error!("failed to write product image")
|
||||||
image: self
|
}
|
||||||
.product_from_vendor
|
|
||||||
.image
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect(),
|
|
||||||
in_stock: self.product_from_vendor.in_stock,
|
|
||||||
name: self.product_from_vendor.name.clone(),
|
|
||||||
price: self.product_from_vendor.price,
|
|
||||||
qty: self.product_from_vendor.qty,
|
|
||||||
};
|
};
|
||||||
i_product = e_product;
|
let contents =
|
||||||
}
|
|
||||||
match std::fs::write(&file_path, &i_product.image) {
|
|
||||||
Ok(w) => w,
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("failed to write product image")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.is_product_image_set = true;
|
|
||||||
let contents =
|
|
||||||
std::fs::read(&file_path).unwrap_or(Vec::new());
|
std::fs::read(&file_path).unwrap_or(Vec::new());
|
||||||
if !i_product.image.is_empty() {
|
if !i_product.image.is_empty() {
|
||||||
// this image should uwrap if vendor image bytes are
|
// this image should uwrap if vendor image bytes are
|
||||||
// bad
|
// bad
|
||||||
let default_img = std::fs::read("./assets/qr.png")
|
let default_img = std::fs::read("./assets/qr.png")
|
||||||
.unwrap_or(Vec::new());
|
.unwrap_or(Vec::new());
|
||||||
let default_r_img =
|
let default_r_img =
|
||||||
egui_extras::RetainedImage::from_image_bytes(
|
egui_extras::RetainedImage::from_image_bytes(
|
||||||
"qr.png",
|
"qr.png",
|
||||||
&default_img,
|
&default_img,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.product_image =
|
self.product_image =
|
||||||
egui_extras::RetainedImage::from_image_bytes(
|
egui_extras::RetainedImage::from_image_bytes(
|
||||||
file_path, &contents,
|
file_path, &contents,
|
||||||
)
|
)
|
||||||
.unwrap_or(default_r_img);
|
.unwrap_or(default_r_img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !self.is_window_shopping {
|
||||||
|
self.is_product_image_set = true;
|
||||||
|
self.is_showing_product_image = true;
|
||||||
}
|
}
|
||||||
self.is_product_image_set = true;
|
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,6 +678,8 @@ impl eframe::App for MarketApp {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if ui.button("View Vendors").clicked() {
|
if ui.button("View Vendors").clicked() {
|
||||||
|
// assume all contacts are vendors until updated status check
|
||||||
|
self.vendors = contact::find_all();
|
||||||
self.is_showing_vendors = true;
|
self.is_showing_vendors = true;
|
||||||
}
|
}
|
||||||
ui.label("\n");
|
ui.label("\n");
|
||||||
|
@ -704,6 +751,7 @@ impl eframe::App for MarketApp {
|
||||||
if ui.button("View Products").clicked() {
|
if ui.button("View Products").clicked() {
|
||||||
self.products = product::find_all();
|
self.products = product::find_all();
|
||||||
self.is_showing_products = true;
|
self.is_showing_products = true;
|
||||||
|
self.is_showing_vendors = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -723,7 +771,7 @@ fn _refresh_on_delete_product_req(_tx: Sender<bool>, _ctx: egui::Context) {
|
||||||
fn send_contact_info_req(tx: Sender<models::Contact>, ctx: egui::Context, contact: String) {
|
fn send_contact_info_req(tx: Sender<models::Contact>, ctx: egui::Context, contact: String) {
|
||||||
log::debug!("async send_contact_info_req");
|
log::debug!("async send_contact_info_req");
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
match contact::add_contact_request(contact).await {
|
match contact::add_contact_request(contact, 1).await {
|
||||||
Ok(contact) => {
|
Ok(contact) => {
|
||||||
let _ = tx.send(contact);
|
let _ = tx.send(contact);
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
|
@ -774,3 +822,15 @@ fn send_product_from_vendor_req(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vendor_status_timeout(tx: Sender<bool>, ctx: egui::Context) {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(
|
||||||
|
crate::ADD_CONTACT_TIMEOUT_SECS,
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
log::error!("vendor status timeout");
|
||||||
|
let _ = tx.send(true);
|
||||||
|
ctx.request_repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ impl eframe::App for WrapApp {
|
||||||
let is_bg = std::env::var(crate::NEVEKO_DEV_BACKGROUND).unwrap_or(String::from("0"));
|
let is_bg = std::env::var(crate::NEVEKO_DEV_BACKGROUND).unwrap_or(String::from("0"));
|
||||||
if is_bg != String::from("1") {
|
if is_bg != String::from("1") {
|
||||||
utils::kill_child_processes(false);
|
utils::kill_child_processes(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,23 @@ pub async fn get_i2p_status() -> Custom<Json<i2p::HttpProxyStatus>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Share your contact information
|
/// Share your contact information.
|
||||||
|
///
|
||||||
|
/// 0 - returns full info with gpg key
|
||||||
|
///
|
||||||
|
/// 1 - return pruned info without gpg key
|
||||||
///
|
///
|
||||||
/// Protected: false
|
/// Protected: false
|
||||||
#[get("/")]
|
#[get("/<pruned>")]
|
||||||
pub async fn share_contact_info() -> Custom<Json<models::Contact>> {
|
pub async fn share_contact_info(pruned: u32) -> Custom<Json<models::Contact>> {
|
||||||
let info: models::Contact = contact::share().await;
|
let info: models::Contact = contact::share().await;
|
||||||
|
if pruned == 1 {
|
||||||
|
let p_info: models::Contact = models::Contact {
|
||||||
|
gpg_key: Vec::new(),
|
||||||
|
..info
|
||||||
|
};
|
||||||
|
return Custom(Status::Ok, Json(p_info));
|
||||||
|
}
|
||||||
Custom(Status::Ok, Json(info))
|
Custom(Status::Ok, Json(info))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ async fn rocket() -> _ {
|
||||||
routes![
|
routes![
|
||||||
controller::create_order,
|
controller::create_order,
|
||||||
controller::create_dispute,
|
controller::create_dispute,
|
||||||
|
controller::get_product,
|
||||||
controller::get_products,
|
controller::get_products,
|
||||||
controller::finalize_order,
|
controller::finalize_order,
|
||||||
controller::request_shipment,
|
controller::request_shipment,
|
||||||
|
|
Loading…
Reference in a new issue