Просмотр исходного кода

app: various minor fixes to settings editor: fix font sizes, make net transport a drop down not text input, add edit_switch for focus stealing, and add Role::Root for netdebug backend to override perms

darkfi 6 дней назад
Родитель
Сommit
319d27b411

+ 1 - 1
bin/app/src/app/schema/menu/mod.rs

@@ -119,7 +119,7 @@ mod ui_consts {
 pub mod channel;
 pub mod contact;
 mod edit_buttons;
-mod edit_switch;
+pub mod edit_switch;
 
 pub async fn make(
     app: &App,

+ 30 - 5
bin/app/src/app/schema/settings.rs

@@ -22,6 +22,7 @@ use crate::{
             create_button, create_dropdown, create_layer, create_singleline_edit, create_slider,
             create_text, create_vector_art,
         },
+        schema::menu::edit_switch::edit_switch,
         App,
     },
     expr::{self, Compiler},
@@ -52,6 +53,8 @@ mod android_ui_consts {
     pub const SETTING_LABEL_X: f32 = 40.;
     pub const SETTING_LABEL_LINESPACE: f32 = 140.;
     pub const SEARCH_BAR_Y: f32 = SETTING_LABEL_LINESPACE;
+    pub const SEARCH_INPUT_FONTSIZE: f32 = 32.;
+    pub const SEARCH_INPUT_BASELINE: f32 = 32.;
     pub const SETTING_LABEL_Y: f32 = (SETTING_LABEL_LINESPACE - 1.2 * SETTING_LABEL_FONTSIZE) / 2.;
     pub const SLIDER_PAD: f32 = 20.;
     pub const RESET_BTN_W: f32 = 70.;
@@ -97,6 +100,8 @@ mod ui_consts {
     pub const SETTING_LABEL_X: f32 = 20.;
     pub const SETTING_LABEL_LINESPACE: f32 = 60.;
     pub const SEARCH_BAR_Y: f32 = SETTING_LABEL_LINESPACE;
+    pub const SEARCH_INPUT_FONTSIZE: f32 = 16.;
+    pub const SEARCH_INPUT_BASELINE: f32 = 16.;
     pub const SETTING_LABEL_Y: f32 = (SETTING_LABEL_LINESPACE - 1.2 * SETTING_LABEL_FONTSIZE) / 2.;
     pub const SLIDER_PAD: f32 = 10.;
     pub const RESET_BTN_W: f32 = 35.;
@@ -352,6 +357,7 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
     layer_node.link(node);
 
     // Search Bar Input
+    let mut edit_nodes: Vec<SceneNodePtr> = vec![];
     let editbox_node = create_singleline_edit("search_input");
     editbox_node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
     editbox_node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
@@ -381,8 +387,16 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
     editbox_node.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
     editbox_node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
     editbox_node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
-    editbox_node.get_property("font_size").unwrap().set_f32(atom, Role::App, 0, 16.).unwrap();
-    editbox_node.get_property("baseline").unwrap().set_default_f32(0, 16.).unwrap();
+    editbox_node
+        .get_property("font_size")
+        .unwrap()
+        .set_default_f32(0, SEARCH_INPUT_FONTSIZE)
+        .unwrap();
+    editbox_node
+        .get_property("baseline")
+        .unwrap()
+        .set_default_f32(0, SEARCH_INPUT_BASELINE)
+        .unwrap();
 
     // Search icon
     let node = create_vector_art("search_icon");
@@ -529,7 +543,8 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
             )
         })
         .await;
-    layer_node.link(node);
+    layer_node.link(node.clone());
+    edit_nodes.push(node);
 
     // Search background
     let node = create_vector_art("search_bg");
@@ -663,7 +678,7 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
         let setting_clone = setting.clone();
         let setting_name = setting_clone.name.clone();
         let is_bool = matches!(setting_clone.get_value(), PropertyValue::Bool(_));
-        let is_enum = matches!(setting_clone.get_value(), PropertyValue::Enum(_));
+        let is_enum = setting_clone.prop.typ == PropertyType::Enum;
 
         setting_y += SETTING_LABEL_LINESPACE;
 
@@ -958,6 +973,7 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
         setting_layer_node.link(label_value_node);
 
         let editz_text: Option<PropertyStr>;
+        let mut row_edit_node: Option<SceneNodePtr> = None;
         if !is_enum {
             // Text edit
             let editbox_node = create_singleline_edit("value_editbox");
@@ -1056,7 +1072,9 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
                     )
                 })
                 .await;
-            setting_layer_node.link(node);
+            setting_layer_node.link(node.clone());
+            edit_nodes.push(node.clone());
+            row_edit_node = Some(node);
         } else {
             editz_text = None;
             let value_prop = setting_clone.prop.clone();
@@ -1536,9 +1554,13 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
                 let (slot, recvr) = Slot::new("select_clicked");
                 node.register("click", slot).unwrap();
                 let select2 = select.clone();
+                let row_edit_node2 = if is_bool { None } else { row_edit_node.clone() };
                 let listen_click = app.ex.spawn(async move {
                     while let Ok(_) = recvr.recv().await {
                         select2();
+                        if let Some(edit_node) = &row_edit_node2 {
+                            edit_node.call_method("focus", vec![]).await.unwrap();
+                        }
                     }
                 });
                 app.tasks.lock().push(listen_click);
@@ -1711,6 +1733,8 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
         }
     }
 
+    edit_switch(&mut app.tasks.lock(), &edit_nodes, app.ex.clone());
+
     // Sync with current settings
     {
         let sg_root2 = app.sg_root.clone();
@@ -1869,6 +1893,7 @@ async fn update_setting(
         node.set_property_bool(atom, Role::App, "is_active", false).unwrap();
         node.set_property_bool(atom, Role::App, "is_focused", false).unwrap();
         node.set_property_str(atom, Role::App, "text", "").unwrap();
+        node.call_method("unfocus", vec![]).await.unwrap();
     }
 
     let Some(editz_text) = editz_text else { return };

+ 9 - 9
bin/app/src/net.rs

@@ -343,31 +343,31 @@ impl ZeroMQAdapter {
 
                 match prop_type {
                     PropertyType::Null => {
-                        prop.set_null(atom, Role::User, prop_i)?;
+                        prop.set_null(atom, Role::Root, prop_i)?;
                     }
                     PropertyType::Bool => {
                         let val = bool::decode(&mut cur).unwrap();
-                        prop.set_bool(atom, Role::User, prop_i, val)?;
+                        prop.set_bool(atom, Role::Root, prop_i, val)?;
                     }
                     PropertyType::Uint32 => {
                         let val = u32::decode(&mut cur).unwrap();
-                        prop.set_u32(atom, Role::User, prop_i, val)?;
+                        prop.set_u32(atom, Role::Root, prop_i, val)?;
                     }
                     PropertyType::Float32 => {
                         let val = f32::decode(&mut cur).unwrap();
-                        prop.set_f32(atom, Role::User, prop_i, val)?;
+                        prop.set_f32(atom, Role::Root, prop_i, val)?;
                     }
                     PropertyType::Str => {
                         let val = String::decode(&mut cur).unwrap();
-                        prop.set_str(atom, Role::User, prop_i, val)?;
+                        prop.set_str(atom, Role::Root, prop_i, val)?;
                     }
                     PropertyType::Enum => {
                         let val = String::decode(&mut cur).unwrap();
-                        prop.set_enum(atom, Role::User, prop_i, val)?;
+                        prop.set_enum(atom, Role::Root, prop_i, val)?;
                     }
                     PropertyType::SceneNodeId => {
                         let val = SceneNodeId::decode(&mut cur).unwrap();
-                        prop.set_node_id(atom, Role::User, prop_i, val)?;
+                        prop.set_node_id(atom, Role::Root, prop_i, val)?;
                     }
                     PropertyType::SExpr => {
                         // Exprs are sent as source strings and compiled here.
@@ -389,7 +389,7 @@ impl ZeroMQAdapter {
                                 .map(|s| s.to_string()),
                         );
                         check_expr(&code, &names)?;
-                        prop.set_expr(atom, Role::User, prop_i, code)?;
+                        prop.set_expr(atom, Role::Root, prop_i, code)?;
                     }
                     PropertyType::VectorShape => {
                         // Vertices carry coordinate exprs as source strings,
@@ -428,7 +428,7 @@ impl ZeroMQAdapter {
                             indices.push(index);
                         }
                         let shape = VectorShape { verts, indices };
-                        prop.set_shape(atom, Role::User, prop_i, shape)?;
+                        prop.set_shape(atom, Role::Root, prop_i, shape)?;
                     }
                 }
             }

+ 30 - 5
bin/app/src/prop/mod.rs

@@ -102,11 +102,14 @@ impl Role {
     pub const Ignored: Role = Role(1 << 3);
     /// Theme engine writes (stamped by `ThemeCtx` setters)
     pub const Theme: Role = Role(1 << 4);
+    /// Debug backend (netdbg/pydrk) override: bypasses all permission
+    /// masks. Never part of a mask, never used by app code.
+    pub const Root: Role = Role(1 << 5);
 
     /// The empty mask
     pub const NONE: Role = Role(0);
     /// All roles
-    pub const ALL: Role = Role(0b1_1111);
+    pub const ALL: Role = Role(0b11_1111);
 
     /// True when every bit of `other` is also set in `self`.
     pub fn contains(self, other: Role) -> bool {
@@ -379,16 +382,18 @@ impl Property {
         *self.node.lock().unwrap() = Some(node);
     }
 
-    /// Read-mask check for the acting role.
+    /// Read-mask check for the acting role. `Role::Root` overrides
+    /// every mask.
     #[inline]
     pub fn can_read(&self, role: Role) -> bool {
-        self.permission.read.contains(role)
+        role == Role::Root || self.permission.read.contains(role)
     }
 
-    /// Write-mask check for the acting role.
+    /// Write-mask check for the acting role. `Role::Root` overrides
+    /// every mask.
     #[inline]
     pub fn can_write(&self, role: Role) -> bool {
-        self.permission.write.contains(role)
+        role == Role::Root || self.permission.write.contains(role)
     }
 
     /// Central write enforcement: called at the top of every mutating
@@ -2258,6 +2263,26 @@ mod tests {
         assert_eq!(prop.get_f32(0).unwrap(), 0.5);
     }
 
+    #[test]
+    fn test_permission_root_override() {
+        // Role::Root (netdbg backend) bypasses every mask, even masks
+        // that exclude all other roles.
+        let mut temp = Property::new(
+            "alpha",
+            PropertyType::Float32,
+            PropertySubType::Null,
+            PropertyPermission { read: Role::ALL, write: Role::Internal | Role::App },
+        );
+        temp.set_defaults_f32(vec![0.]).unwrap();
+        let prop = Arc::new(temp);
+        let atom = &mut PropertyAtomicGuard::none();
+
+        assert!(prop.can_write(Role::Root));
+        assert!(prop.can_read(Role::Root));
+        prop.set_f32(atom, Role::Root, 0, 7.).unwrap();
+        assert_eq!(prop.get_f32(0).unwrap(), 7.);
+    }
+
     #[test]
     fn test_role_bitflags() {
         let mask = Role::App | Role::Theme;

+ 1 - 1
bin/app/src/setting.rs

@@ -69,7 +69,7 @@ pub fn create_setting(name: &str) -> SceneNode {
         PropertyPermission::default(),
     );
     prop.set_enum_items(vec!["tcp", "tor"]).unwrap();
-    prop.set_defaults_str(vec!["tcp".to_string()]).unwrap();
+    prop.set_default_enum(0, "tcp").unwrap();
     node.add_property(prop).unwrap();
 
     let mut prop = Property::new(