mirror of
https://github.com/librekeys/picoforge.git
synced 2026-07-28 08:01:19 -07:00
feat(ui): Show success/error states in dialogs
This commit is contained in:
+602
-114
File diff suppressed because it is too large
Load Diff
@@ -176,6 +176,7 @@ impl<V: 'static> AppSidebar<V> {
|
||||
.w_full()
|
||||
.bg(rgb(0x111113))
|
||||
// .border_r_1()
|
||||
.mt_1()
|
||||
.border_t_1()
|
||||
.border_color(border_color)
|
||||
.p_2()
|
||||
|
||||
+19
-4
@@ -1,6 +1,6 @@
|
||||
use crate::device::io;
|
||||
use crate::device::types::{AppConfigInput, FullDeviceStatus};
|
||||
use crate::ui::components::{card::Card, dialog, page_view::PageView};
|
||||
use crate::ui::components::{card::Card, dialog, dialog::PinPromptContent, page_view::PageView};
|
||||
use crate::ui::types::{LedDriverType, UsbIdentityPreset};
|
||||
use gpui::*;
|
||||
use gpui_component::button::{ButtonCustomVariant, ButtonVariants};
|
||||
@@ -211,6 +211,7 @@ impl ConfigView {
|
||||
changes: AppConfigInput,
|
||||
method: crate::device::types::DeviceMethod,
|
||||
pin: Option<String>,
|
||||
dialog_handle: Option<WeakEntity<PinPromptContent>>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.loading = true;
|
||||
@@ -255,11 +256,24 @@ impl ConfigView {
|
||||
this.enable_secp256k1 = config.enable_secp256k1;
|
||||
|
||||
this.device_status = Some(new_status);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
if let Some(ref dh) = dialog_handle {
|
||||
let _ = dh.update(cx, |d, cx| {
|
||||
d.set_success(
|
||||
"Configuration applied successfully.".to_string(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error saving config: {}", e);
|
||||
if let Some(ref dh) = dialog_handle {
|
||||
let _ = dh.update(cx, |d, cx| {
|
||||
d.set_error(format!("Failed to apply: {}", e), cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,12 +296,13 @@ impl ConfigView {
|
||||
"Confirm",
|
||||
window,
|
||||
cx,
|
||||
move |pin, _, cx| {
|
||||
move |pin, dialog_handle, cx| {
|
||||
let _ = view_handle.update(cx, |this, cx| {
|
||||
this.write_config_to_device(
|
||||
changes.clone(),
|
||||
crate::device::types::DeviceMethod::Fido,
|
||||
Some(pin),
|
||||
Some(dialog_handle),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
@@ -396,7 +411,7 @@ impl ConfigView {
|
||||
if method == crate::device::types::DeviceMethod::Fido {
|
||||
self.open_pin_dialog(changes, window, cx);
|
||||
} else {
|
||||
self.write_config_to_device(changes, method, None, cx);
|
||||
self.write_config_to_device(changes, method, None, None, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ impl Render for LogsView {
|
||||
|
||||
let copy_logs_listener = cx.listener(|this, _, _, cx| {
|
||||
let all_logs = this.logs.join("\n");
|
||||
log::info!("Copying {} bytes of logs", all_logs.len());
|
||||
log::debug!("Copying {} bytes of logs", all_logs.len());
|
||||
cx.write_to_clipboard(ClipboardItem::new_string(all_logs));
|
||||
});
|
||||
|
||||
@@ -128,10 +128,7 @@ impl Render for LogsView {
|
||||
theme.foreground.to_rgb()
|
||||
};
|
||||
|
||||
div()
|
||||
.text_color(color)
|
||||
.child(log.clone())
|
||||
.cursor_text()
|
||||
div().text_color(color).child(log.clone())
|
||||
}),
|
||||
)),
|
||||
)
|
||||
|
||||
+63
-35
@@ -4,6 +4,7 @@ use crate::ui::components::{
|
||||
button::{PFButton, PFIconButton},
|
||||
card::Card,
|
||||
dialog,
|
||||
dialog::{ChangePinContent, ConfirmContent, PinPromptContent},
|
||||
page_view::PageView,
|
||||
};
|
||||
use gpui::*;
|
||||
@@ -78,13 +79,19 @@ impl PasskeysView {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn unlock_storage(&mut self, pin: String, cx: &mut Context<Self>) {
|
||||
fn unlock_storage(
|
||||
&mut self,
|
||||
pin: String,
|
||||
dialog_handle: WeakEntity<PinPromptContent>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.loading {
|
||||
return;
|
||||
}
|
||||
self.loading = true;
|
||||
cx.notify();
|
||||
|
||||
log::info!("Unlocking FIDO storage...");
|
||||
let entity = cx.entity().downgrade();
|
||||
|
||||
self._task = Some(cx.spawn(async move |_, cx| {
|
||||
@@ -98,14 +105,19 @@ impl PasskeysView {
|
||||
this.loading = false;
|
||||
match result {
|
||||
Ok(creds) => {
|
||||
log::info!("Storage unlocked. {} credentials found.", creds.len());
|
||||
this.unlocked = true;
|
||||
this.cached_pin = Some(pin);
|
||||
this.credentials = creds;
|
||||
cx.emit(PasskeysEvent::CloseDialog);
|
||||
let _ = dialog_handle.update(cx, |d, cx| {
|
||||
d.set_success("Storage unlocked successfully.".to_string(), cx);
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
let msg = format!("Failed to unlock: {}", e);
|
||||
cx.emit(PasskeysEvent::Notification(msg));
|
||||
log::error!("Failed to unlock storage: {}", e);
|
||||
let _ = dialog_handle.update(cx, |d, cx| {
|
||||
d.set_error(format!("Failed to unlock: {}", e), cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -120,13 +132,20 @@ impl PasskeysView {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn execute_delete(&mut self, credential_id: String, pin: String, cx: &mut Context<Self>) {
|
||||
fn execute_delete(
|
||||
&mut self,
|
||||
credential_id: String,
|
||||
pin: String,
|
||||
dialog_handle: WeakEntity<ConfirmContent>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.loading {
|
||||
return;
|
||||
}
|
||||
self.loading = true;
|
||||
cx.notify();
|
||||
|
||||
log::info!("Deleting credential...");
|
||||
let entity = cx.entity().downgrade();
|
||||
|
||||
self._task = Some(cx.spawn(async move |_, cx| {
|
||||
@@ -138,16 +157,18 @@ impl PasskeysView {
|
||||
|
||||
let _ = entity.update(cx, |this, cx| match result {
|
||||
Ok(_) => {
|
||||
log::info!("Credential deleted successfully.");
|
||||
this.refresh_credentials(pin, cx);
|
||||
cx.emit(PasskeysEvent::CloseDialog);
|
||||
cx.emit(PasskeysEvent::Notification(
|
||||
"Credential deleted".to_string(),
|
||||
));
|
||||
let _ = dialog_handle.update(cx, |d, cx| {
|
||||
d.set_success("Credential deleted successfully.".to_string(), cx);
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error deleting credential: {}", e);
|
||||
this.loading = false;
|
||||
let msg = format!("Error deleting: {}", e);
|
||||
cx.emit(PasskeysEvent::Notification(msg));
|
||||
let _ = dialog_handle.update(cx, |d, cx| {
|
||||
d.set_error(format!("Error deleting: {}", e), cx);
|
||||
});
|
||||
cx.notify();
|
||||
}
|
||||
});
|
||||
@@ -181,9 +202,9 @@ impl PasskeysView {
|
||||
"Unlock",
|
||||
window,
|
||||
cx,
|
||||
move |pin, _, cx| {
|
||||
move |pin, dialog_handle, cx| {
|
||||
let _ = view_handle.update(cx, |this, cx| {
|
||||
this.unlock_storage(pin, cx);
|
||||
this.unlock_storage(pin, dialog_handle, cx);
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -208,9 +229,9 @@ impl PasskeysView {
|
||||
ButtonVariant::Danger,
|
||||
window,
|
||||
cx,
|
||||
move |_, cx| {
|
||||
move |dialog_handle, cx| {
|
||||
let _ = view_handle.update(cx, |this, cx| {
|
||||
this.execute_delete(cred_id.clone(), pin_str.clone(), cx);
|
||||
this.execute_delete(cred_id.clone(), pin_str.clone(), dialog_handle, cx);
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -218,22 +239,12 @@ impl PasskeysView {
|
||||
|
||||
fn open_change_pin_dialog(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let view_handle = cx.entity().downgrade();
|
||||
let view_for_error = cx.entity().downgrade();
|
||||
|
||||
dialog::open_change_pin(
|
||||
window,
|
||||
cx,
|
||||
move |msg, cx| {
|
||||
let _ = view_for_error.update(cx, |_, cx| {
|
||||
cx.emit(PasskeysEvent::Notification(msg.to_string()));
|
||||
});
|
||||
},
|
||||
move |current, new, cx| {
|
||||
let _ = view_handle.update(cx, |this, cx| {
|
||||
this.change_pin(current, new, cx);
|
||||
});
|
||||
},
|
||||
);
|
||||
dialog::open_change_pin(window, cx, move |current, new, dialog_handle, cx| {
|
||||
let _ = view_handle.update(cx, |this, cx| {
|
||||
this.change_pin(current, new, dialog_handle, cx);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn open_min_pin_length_dialog(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
@@ -354,12 +365,20 @@ impl PasskeysView {
|
||||
});
|
||||
}
|
||||
|
||||
fn change_pin(&mut self, current: String, new: String, cx: &mut Context<Self>) {
|
||||
fn change_pin(
|
||||
&mut self,
|
||||
current: String,
|
||||
new: String,
|
||||
dialog_handle: WeakEntity<ChangePinContent>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.loading {
|
||||
return;
|
||||
}
|
||||
self.loading = true;
|
||||
cx.notify();
|
||||
|
||||
log::info!("Changing FIDO PIN...");
|
||||
let entity = cx.entity().downgrade();
|
||||
|
||||
self._task = Some(cx.spawn(async move |_, cx| {
|
||||
@@ -372,15 +391,19 @@ impl PasskeysView {
|
||||
this.loading = false;
|
||||
match result {
|
||||
Ok(msg) => {
|
||||
cx.emit(PasskeysEvent::CloseDialog);
|
||||
cx.emit(PasskeysEvent::Notification(msg));
|
||||
// Refresh device info
|
||||
log::info!("PIN changed: {}", msg);
|
||||
if let Ok(info) = io::get_fido_info() {
|
||||
this.fido_info = Some(info);
|
||||
}
|
||||
let _ = dialog_handle.update(cx, |d, cx| {
|
||||
d.set_success("PIN changed successfully.".to_string(), cx);
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
cx.emit(PasskeysEvent::Notification(format!("Error: {}", e)));
|
||||
log::error!("PIN change failed: {}", e);
|
||||
let _ = dialog_handle.update(cx, |d, cx| {
|
||||
d.set_error(format!("Error: {}", e), cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -400,6 +423,7 @@ impl PasskeysView {
|
||||
}
|
||||
self.loading = true;
|
||||
cx.notify();
|
||||
log::info!("Updating minimum PIN length to {}...", min_len);
|
||||
let entity = cx.entity().downgrade();
|
||||
|
||||
self._task = Some(cx.spawn(async move |_, cx| {
|
||||
@@ -411,6 +435,7 @@ impl PasskeysView {
|
||||
.await;
|
||||
|
||||
if let Err(e) = res_len {
|
||||
log::error!("Failed to set minimum PIN length: {}", e);
|
||||
let _ = entity.update(cx, |this, cx| {
|
||||
this.loading = false;
|
||||
cx.emit(PasskeysEvent::Notification(format!(
|
||||
@@ -431,6 +456,7 @@ impl PasskeysView {
|
||||
this.loading = false;
|
||||
match res_pin {
|
||||
Ok(_) => {
|
||||
log::info!("Minimum length and PIN updated successfully.");
|
||||
cx.emit(PasskeysEvent::CloseDialog);
|
||||
cx.emit(PasskeysEvent::Notification(
|
||||
"Minimum length and PIN updated".to_string(),
|
||||
@@ -440,6 +466,7 @@ impl PasskeysView {
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Length set, but PIN change failed: {}", e);
|
||||
cx.emit(PasskeysEvent::Notification(format!(
|
||||
"Length set, but PIN change failed: {}",
|
||||
e
|
||||
@@ -451,6 +478,7 @@ impl PasskeysView {
|
||||
} else {
|
||||
let _ = entity.update(cx, |this, cx| {
|
||||
this.loading = false;
|
||||
log::info!("Minimum PIN length updated to {}.", min_len);
|
||||
cx.emit(PasskeysEvent::CloseDialog);
|
||||
cx.emit(PasskeysEvent::Notification(format!(
|
||||
"Minimum length updated to {}",
|
||||
|
||||
Reference in New Issue
Block a user