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

app/menu: no scrolling menu while in edit mode

darkfi 1 неделя назад
Родитель
Сommit
a05f6e816f

+ 4 - 1
bin/app/Makefile

@@ -98,8 +98,11 @@ assets/forest_720x1280.mp4:
 
 # Developer targets
 
-dev: $(SRC) fonts assets/forest_1920x1080.ivf
+compile-dev: $(SRC) fonts assets/forest_1920x1080.ivf
 	$(CARGO) lbuild --no-default-features $(DEV_FEATURES)
+
+dev:
+	$(MAKE) compile-dev
 	-mv target/debug/darkfi-app .
 	./darkfi-app
 

+ 3 - 2
bin/app/src/app/schema/menu/channel.rs

@@ -1326,8 +1326,9 @@ pub async fn make(
         prop.push_str(atom, Role::App, &channel_name).unwrap();
     }
 
-    let menu_node =
-        node.setup(|me| Menu::new(me, window_scale.clone(), app.renderer.clone())).await;
+    let menu_node = node
+        .setup(|me| Menu::new(me, window_scale.clone(), app.renderer.clone(), app.ex.clone()))
+        .await;
     content_area.link(menu_node.clone());
 
     // Setup add_channel button handler now that menu_node exists

+ 3 - 2
bin/app/src/app/schema/menu/contact.rs

@@ -1346,8 +1346,9 @@ pub async fn make(
         prop.push_str(atom, Role::App, &contact_name).unwrap();
     }
 
-    let menu_node =
-        node.setup(|me| Menu::new(me, window_scale.clone(), app.renderer.clone())).await;
+    let menu_node = node
+        .setup(|me| Menu::new(me, window_scale.clone(), app.renderer.clone(), app.ex.clone()))
+        .await;
     content_area.link(menu_node.clone());
 
     // Connect cancel/done buttons and edit_active signal

+ 3 - 2
bin/app/src/app/schema/menu/mod.rs

@@ -464,8 +464,9 @@ pub async fn make(
     });
     app.tasks.lock().unwrap().push(listen_click);
 
-    let menu_node =
-        node.setup(|me| Menu::new(me, window_scale.clone(), app.renderer.clone())).await;
+    let menu_node = node
+        .setup(|me| Menu::new(me, window_scale.clone(), app.renderer.clone(), app.ex.clone()))
+        .await;
     layer_node.link(menu_node.clone());
 
     // Subscribe to edit_done signal to persist the joined list and unlink removed layers

+ 23 - 24
bin/app/src/ui/menu/mod.rs

@@ -67,7 +67,7 @@ struct TouchInfo {
     start_instant: std::time::Instant,
     samples: VecDeque<(std::time::Instant, f32)>,
     last_instant: std::time::Instant,
-    last_y: f32,
+    last_pos: Point,
 }
 
 #[derive(Clone)]
@@ -90,7 +90,7 @@ impl TouchInfo {
             start_instant: std::time::Instant::now(),
             samples: VecDeque::from([(std::time::Instant::now(), pos.y)]),
             last_instant: std::time::Instant::now(),
-            last_y: pos.y,
+            last_pos: pos,
         }
     }
 
@@ -114,6 +114,9 @@ pub type MenuPtr = Arc<Menu>;
 
 pub struct Menu {
     node: SceneNodeWeak,
+    /// Weak self-reference so handlers can spawn detached tasks.
+    me: Weak<Self>,
+    ex: ExecutorPtr,
     renderer: Renderer,
     tasks: SyncMutex<Vec<smol::Task<()>>>,
     root_dc_key: u64,
@@ -145,8 +148,6 @@ pub struct Menu {
     mouse_click_info: SyncMutex<Option<MouseClickInfo>>,
     drag_info: SyncMutex<Option<DragInfo>>,
     long_press_task: SyncMutex<Option<smol::Task<()>>>,
-    weak_self: SyncMutex<Option<Weak<Self>>>,
-    ex: SyncMutex<Option<ExecutorPtr>>,
     scroll_start_accel: PropertyFloat32,
     scroll_resist: PropertyFloat32,
     motion_cv: Arc<CondVar>,
@@ -162,6 +163,7 @@ impl Menu {
         node: SceneNodeWeak,
         window_scale: PropertyFloat32,
         renderer: Renderer,
+        ex: ExecutorPtr,
     ) -> Pimpl {
         let node_ref = &node.upgrade().unwrap();
         let is_visible = PropertyBool::wrap(node_ref, Role::Internal, "is_visible", 0).unwrap();
@@ -192,8 +194,10 @@ impl Menu {
 
         let motion_cv = Arc::new(CondVar::new());
 
-        let self_ = Arc::new(Self {
+        let self_ = Arc::new_cyclic(|me| Self {
             node: node.clone(),
+            me: me.clone(),
+            ex,
             renderer: renderer.clone(),
             tasks: SyncMutex::new(vec![]),
             root_dc_key: OsRng.gen(),
@@ -222,8 +226,6 @@ impl Menu {
             mouse_click_info: SyncMutex::new(None),
             drag_info: SyncMutex::new(None),
             long_press_task: SyncMutex::new(None),
-            weak_self: SyncMutex::new(None),
-            ex: SyncMutex::new(None),
             scroll_start_accel,
             scroll_resist,
             motion_cv,
@@ -284,12 +286,14 @@ impl Menu {
         let is_long_press = is_long_press_tap && elapsed_ms >= 500;
 
         if is_long_press {
-            self.save_items_layout();
-            self.is_edit_mode.store(true, Ordering::Release);
-            let node = self.node.upgrade().unwrap();
-            node.trigger("edit_active", vec![]).await.unwrap();
-            let atom = &mut self.renderer.make_guard(gfxtag!("Menu::long_press"));
-            self.redraw(atom);
+            if !self.is_edit_mode.load(Ordering::Relaxed) {
+                self.save_items_layout();
+                self.is_edit_mode.store(true, Ordering::Release);
+                let node = self.node.upgrade().unwrap();
+                node.trigger("edit_active", vec![]).await.unwrap();
+                let atom = &mut self.renderer.make_guard(gfxtag!("Menu::long_press"));
+                self.redraw(atom);
+            }
         } else if is_tap {
             let is_edit_mode = self.is_edit_mode.load(Ordering::Relaxed);
 
@@ -518,10 +522,7 @@ impl Menu {
 
         let rect = self.rect.get();
         let max_scroll = (content_height - rect.h).max(0.);
-
-        // Allow 50% overscroll past the end of the content
-        let overscroll = rect.h * 0.5;
-        let scroll = scroll.clamp(0., max_scroll + overscroll);
+        let scroll = scroll.clamp(0., max_scroll);
         self.scroll.store(scroll, Ordering::Relaxed);
     }
 
@@ -638,9 +639,7 @@ impl UIObject for Menu {
     }
 
     async fn start(self: Arc<Self>, ex: ExecutorPtr) {
-        *self.weak_self.lock() = Some(Arc::downgrade(&self));
-        *self.ex.lock() = Some(ex.clone());
-        let me = Arc::downgrade(&self);
+        let me = self.me.clone();
         let node_ref = &self.node.upgrade().unwrap();
 
         let me2 = me.clone();
@@ -736,14 +735,14 @@ impl UIObject for Menu {
             Some(MouseClickInfo { start_pos: mouse_pos, start_instant: std::time::Instant::now() });
 
         // Spawn a task to detect long press
-        let weak_self = self.weak_self.lock().clone().unwrap();
+        let me = self.me.clone();
         let start_pos = mouse_pos;
 
-        let ex = self.ex.lock().clone().unwrap();
+        let ex = self.ex.clone();
         let long_press_task = ex.spawn(async move {
             darkfi::system::msleep(500).await;
 
-            let Some(arc_self) = weak_self.upgrade() else { return };
+            let Some(arc_self) = me.upgrade() else { return };
             let current_mouse_pos = arc_self.mouse_pos.lock().clone();
             let click_info = arc_self.mouse_click_info.lock().clone();
 
@@ -915,7 +914,7 @@ impl UIObject for Menu {
                     let mut touch_info = self.touch_info.lock();
                     let Some(info) = &mut *touch_info else { return false };
 
-                    info.last_y = touch_pos.y;
+                    info.last_pos = touch_pos;
                     info.push_sample(touch_pos.y);
 
                     let last_elapsed = info.last_instant.elapsed().as_millis();