commit c60e1af3eb849e09ba7d2b7f3990eb35c917756b
parent 87cb5ed515d5c773c283aee2661cd01cade0081b
Author: William Casarin <jb55@jb55.com>
Date: Wed, 6 Aug 2025 18:53:45 -0700
chrome: add virtual keyboard ui
Diffstat:
6 files changed, 95 insertions(+), 32 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -3532,6 +3532,7 @@ dependencies = [
name = "notedeck_chrome"
version = "0.6.0"
dependencies = [
+ "bitflags 2.9.1",
"eframe",
"egui",
"egui-winit",
diff --git a/crates/notedeck/src/platform/mod.rs b/crates/notedeck/src/platform/mod.rs
@@ -1,12 +1,22 @@
#[cfg(target_os = "android")]
pub mod android;
+const VIRT_HEIGHT: i32 = 400;
+
#[cfg(target_os = "android")]
-pub fn virtual_keyboard_height() -> i32 {
- android::virtual_keyboard_height()
+pub fn virtual_keyboard_height(virt: bool) -> i32 {
+ if virt {
+ VIRT_HEIGHT
+ } else {
+ android::virtual_keyboard_height()
+ }
}
#[cfg(not(target_os = "android"))]
-pub fn virtual_keyboard_height() -> i32 {
- 0
+pub fn virtual_keyboard_height(virt: bool) -> i32 {
+ if virt {
+ VIRT_HEIGHT
+ } else {
+ 0
+ }
}
diff --git a/crates/notedeck_chrome/Cargo.toml b/crates/notedeck_chrome/Cargo.toml
@@ -9,6 +9,7 @@ license = "GPLv3"
description = "The nostr browser"
[dependencies]
+bitflags = { workspace = true }
eframe = { workspace = true }
egui_tabs = { workspace = true }
egui_extras = { workspace = true }
diff --git a/crates/notedeck_chrome/src/chrome.rs b/crates/notedeck_chrome/src/chrome.rs
@@ -2,6 +2,7 @@
//#[cfg(target_arch = "wasm32")]
//use wasm_bindgen::prelude::*;
use crate::app::NotedeckApp;
+use crate::ChromeOptions;
use eframe::CreationContext;
use egui::{vec2, Button, Color32, Label, Layout, Rect, RichText, ThemePreference, Widget};
use egui_extras::{Size, StripBuilder};
@@ -24,33 +25,13 @@ use std::collections::HashMap;
static ICON_WIDTH: f32 = 40.0;
pub static ICON_EXPANSION_MULTIPLE: f32 = 1.2;
+#[derive(Default)]
pub struct Chrome {
active: i32,
- open: bool,
tab_selected: i32,
+ options: ChromeOptions,
apps: Vec<NotedeckApp>,
pub repaint_causes: HashMap<egui::RepaintCause, u64>,
-
- #[cfg(feature = "memory")]
- show_memory_debug: bool,
- show_repaint_debug: bool,
-}
-
-impl Default for Chrome {
- fn default() -> Self {
- Self {
- active: 0,
- repaint_causes: Default::default(),
- tab_selected: 0,
- // sidemenu is not open by default on mobile/narrow uis
- open: !notedeck::ui::is_compiled_as_mobile(),
- apps: vec![],
-
- #[cfg(feature = "memory")]
- show_memory_debug: false,
- show_repaint_debug: false,
- }
- }
}
/// When you click the toolbar button, these actions
@@ -223,7 +204,7 @@ impl Chrome {
}
pub fn toggle(&mut self) {
- self.open = !self.open;
+ self.options.toggle(ChromeOptions::IsOpen);
}
pub fn add_app(&mut self, app: NotedeckApp) {
@@ -366,7 +347,9 @@ impl Chrome {
fn amount_open(&self, ui: &mut egui::Ui) -> f32 {
let open_id = egui::Id::new("chrome_open");
let side_panel_width: f32 = 74.0;
- ui.ctx().animate_bool(open_id, self.open) * side_panel_width
+ ui.ctx()
+ .animate_bool(open_id, self.options.contains(ChromeOptions::IsOpen))
+ * side_panel_width
}
fn toolbar_height() -> f32 {
@@ -477,12 +460,25 @@ impl Chrome {
fn show(&mut self, ctx: &mut AppContext, ui: &mut egui::Ui) -> Option<ChromePanelAction> {
ui.spacing_mut().item_spacing.x = 0.0;
- if notedeck::ui::is_narrow(ui.ctx()) {
+ if ctx.args.options.contains(NotedeckOptions::Debug)
+ && ui.ctx().input(|i| i.key_pressed(egui::Key::Backtick))
+ {
+ self.options.toggle(ChromeOptions::VirtualKeyboard);
+ }
+
+ let r = if notedeck::ui::is_narrow(ui.ctx()) {
self.toolbar_chrome(ctx, ui)
} else {
let amt_open = self.amount_open(ui);
self.panel(ctx, StripBuilder::new(ui), amt_open)
+ };
+
+ // virtual keyboard
+ if self.options.contains(ChromeOptions::VirtualKeyboard) {
+ virtual_keyboard_ui(ui);
}
+
+ r
}
fn topdown_sidebar(&mut self, ui: &mut egui::Ui, i18n: &mut Localization) {
@@ -497,7 +493,7 @@ impl Chrome {
if ui.add(expand_side_panel_button()).clicked() {
//self.active = (self.active + 1) % (self.apps.len() as i32);
- self.open = !self.open;
+ self.options.toggle(ChromeOptions::IsOpen);
}
ui.add_space(4.0);
@@ -1023,10 +1019,10 @@ fn bottomup_sidebar(
.on_hover_cursor(egui::CursorIcon::PointingHand);
if r.clicked() {
- chrome.show_repaint_debug = !chrome.show_repaint_debug;
+ chrome.options.toggle(ChromeOptions::RepaintDebug);
}
- if chrome.show_repaint_debug {
+ if chrome.options.contains(ChromeOptions::RepaintDebug) {
for cause in ui.ctx().repaint_causes() {
chrome
.repaint_causes
@@ -1218,3 +1214,21 @@ fn repaint_causes_window(ui: &mut egui::Ui, causes: &HashMap<egui::RepaintCause,
});
});
}
+
+fn virtual_keyboard_ui(ui: &mut egui::Ui) {
+ let height = notedeck::platform::virtual_keyboard_height(true);
+ let screen_rect = ui.ctx().screen_rect();
+
+ let min = egui::Pos2::new(0.0, screen_rect.max.y - height as f32);
+ let rect = Rect::from_min_max(min, screen_rect.max);
+ let painter = ui.painter_at(rect);
+
+ painter.rect_filled(rect, 0.0, Color32::from_black_alpha(200));
+
+ ui.put(rect, |ui: &mut egui::Ui| {
+ ui.centered_and_justified(|ui| {
+ ui.label("This is a keyboard");
+ })
+ .response
+ });
+}
diff --git a/crates/notedeck_chrome/src/lib.rs b/crates/notedeck_chrome/src/lib.rs
@@ -5,6 +5,8 @@ mod android;
mod app;
mod chrome;
+mod options;
pub use app::NotedeckApp;
pub use chrome::Chrome;
+pub use options::ChromeOptions;
diff --git a/crates/notedeck_chrome/src/options.rs b/crates/notedeck_chrome/src/options.rs
@@ -0,0 +1,35 @@
+use bitflags::bitflags;
+
+bitflags! {
+ #[repr(transparent)]
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+ pub struct ChromeOptions: u64 {
+ /// Is the chrome currently open?
+ const NoOptions = 0;
+
+ /// Is the chrome currently open?
+ const IsOpen = 1 << 0;
+
+ /// Are we simulating a virtual keyboard? This is mostly for debugging
+ /// if we are too lazy to open up a real mobile device with soft
+ /// keyboard
+ const VirtualKeyboard = 1 << 1;
+
+ /// Are we showing the memory debug window?
+ const MemoryDebug = 1 << 2;
+
+ /// Repaint debug
+ const RepaintDebug = 1 << 3;
+ }
+}
+
+impl Default for ChromeOptions {
+ fn default() -> Self {
+ let mut options = ChromeOptions::NoOptions;
+ options.set(
+ ChromeOptions::IsOpen,
+ !notedeck::ui::is_compiled_as_mobile(),
+ );
+ options
+ }
+}