From f210180de67cfe1412004e88a3d40e886eed03c7 Mon Sep 17 00:00:00 2001 From: 2ro <17595647+2ro@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:31:54 -0400 Subject: [PATCH] Build 39: match Grim's focus handling on text fields (.focus(false)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grim never lets a field default to constant focus. Its TextEdit defaults to focus = true, which means an unfocused field calls request_focus() EVERY frame. Grim's own usage always overrides this — every field is .focus(false) (focus only on tap), and at most one gets .focus(first_draw) to grab focus once when a screen opens (see grim wallets/modals/add.rs). Goblin's converted fields skipped this, so all ~16 fields requested focus each frame and fought each other on multi-field screens (wallet setup, import, rotate). Set every field to .focus(false) to match Grim exactly: fields now focus on tap and bring up the native keyboard, with no thrash. The native IME path itself is already identical to Grim (verified: edit.rs differs only by additive display builders; MainActivity onTextInput JNI plumbing is byte-for-byte Grim; android/winit/eframe/egui/jni deps match). --- src/gui/views/goblin/mod.rs | 9 +++++++++ src/gui/views/goblin/onboarding.rs | 5 +++++ src/gui/views/goblin/send.rs | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/gui/views/goblin/mod.rs b/src/gui/views/goblin/mod.rs index 4b70e7a4..025e7c0b 100644 --- a/src/gui/views/goblin/mod.rs +++ b/src/gui/views/goblin/mod.rs @@ -1731,12 +1731,14 @@ impl GoblinWalletView { ui.add_space(16.0); settings_group(ui, "Add external node", |ui| { TextEdit::new(egui::Id::from("set_node_url")) + .focus(false) .hint_text("https://node.example.com:3413") .text_color(t.surface_text) .body() .ui(ui, &mut self.node_url_input, cb); ui.add_space(8.0); TextEdit::new(egui::Id::from("set_node_secret")) + .focus(false) .hint_text("API secret (optional)") .text_color(t.surface_text) .body() @@ -1818,6 +1820,7 @@ impl GoblinWalletView { ui.add_space(16.0); settings_group(ui, "Add relay", |ui| { TextEdit::new(egui::Id::from("set_relay")) + .focus(false) .hint_text("wss://relay.example.com") .text_color(t.surface_text) .body() @@ -2044,6 +2047,7 @@ impl GoblinWalletView { ui.add_space(10.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("rotate_reset")) + .focus(false) .hint_text("Type RESET") .text_color(t.surface_text) .body() @@ -2052,6 +2056,7 @@ impl GoblinWalletView { ui.add_space(8.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("rotate_pass")) + .focus(false) .hint_text("Wallet password") .password() .text_color(t.surface_text) @@ -2213,6 +2218,7 @@ impl GoblinWalletView { ui.add_space(10.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("import_nsec")) + .focus(false) .hint_text("nsec1… or identity backup JSON") .password() .text_color(t.surface_text) @@ -2222,6 +2228,7 @@ impl GoblinWalletView { ui.add_space(8.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("import_pass")) + .focus(false) .hint_text("Wallet password") .password() .text_color(t.surface_text) @@ -2231,6 +2238,7 @@ impl GoblinWalletView { ui.add_space(8.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("import_backup_pass")) + .focus(false) .hint_text("Backup password (only if exported elsewhere)") .password() .text_color(t.surface_text) @@ -2516,6 +2524,7 @@ impl GoblinWalletView { ); let before = claim.input.clone(); TextEdit::new(egui::Id::from("settings_claim")) + .focus(false) .hint_text("yourname") .text_color(t.surface_text) .body() diff --git a/src/gui/views/goblin/onboarding.rs b/src/gui/views/goblin/onboarding.rs index 018474fd..6d917af1 100644 --- a/src/gui/views/goblin/onboarding.rs +++ b/src/gui/views/goblin/onboarding.rs @@ -321,6 +321,7 @@ impl OnboardingContent { ui.add_space(10.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("onb_ext_url")) + .focus(false) .hint_text("https://node.example.com") .text_color(t.surface_text) .body() @@ -380,6 +381,7 @@ impl OnboardingContent { w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("onb_name")) + .focus(false) .hint_text("Wallet name") .text_color(t.surface_text) .body() @@ -388,6 +390,7 @@ impl OnboardingContent { ui.add_space(8.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("onb_pass")) + .focus(false) .hint_text("Password") .password() .text_color(t.surface_text) @@ -397,6 +400,7 @@ impl OnboardingContent { ui.add_space(8.0); w::field_well(ui, |ui| { TextEdit::new(egui::Id::from("onb_pass2")) + .focus(false) .hint_text("Repeat password") .password() .text_color(t.surface_text) @@ -792,6 +796,7 @@ impl OnboardingContent { ); let before = self.claim.input.clone(); TextEdit::new(egui::Id::from("onb_claim")) + .focus(false) .hint_text("yourname") .text_color(t.surface_text) .body() diff --git a/src/gui/views/goblin/send.rs b/src/gui/views/goblin/send.rs index 858abf4a..20038b26 100644 --- a/src/gui/views/goblin/send.rs +++ b/src/gui/views/goblin/send.rs @@ -285,6 +285,7 @@ impl SendFlow { ); ui.add_space(8.0); let mut te = TextEdit::new(egui::Id::from("send_search")) + .focus(false) .hint_text("@handle, npub, or name") .text_color(t.surface_text) .body() @@ -789,6 +790,7 @@ impl SendFlow { ui.add_space(8.0); let note_id = egui::Id::from("send_note"); TextEdit::new(note_id) + .focus(false) .hint_text("Add a note…") .text_color(t.surface_text) .body()