Explorar o código

app/edit: add actionbar on android and delete the old action popup from the schema

jkds hai 7 meses
pai
achega
0ba46c47a3
Modificáronse 2 ficheiros con 48 adicións e 406 borrados
  1. 0 400
      bin/app/src/app/schema/chat.rs
  2. 48 6
      bin/app/src/ui/edit/mod.rs

+ 0 - 400
bin/app/src/app/schema/chat.rs

@@ -91,12 +91,6 @@ mod android_ui_consts {
     pub const CMD_HELP_NICK_DESC_WIDTH: f32 = 1000.;
     pub const CMD_HELP_NICK_DESC_X: f32 = 320.;
     pub const CMD_HELP_LABEL_Y: f32 = 20.;
-
-    pub const ACTION_POPUP_Y_OFF: f32 = 200.;
-    pub const ACTION_COPY_RECT: Rectangle = Rectangle::new(0., 0., 200., 160.);
-    pub const ACTION_PASTE_RECT: Rectangle = Rectangle::new(220., 0., 240., 160.);
-    pub const ACTION_SELECT_ALL_RECT: Rectangle = Rectangle::new(480., 0., 400., 160.);
-    pub const ACTION_LABEL_POS: Point = Point::new(55., 50.);
 }
 
 #[cfg(target_os = "android")]
@@ -158,12 +152,6 @@ mod ui_consts {
     pub const CMD_HELP_NICK_DESC_WIDTH: f32 = 500.;
     pub const CMD_HELP_NICK_DESC_X: f32 = 160.;
     pub const CMD_HELP_LABEL_Y: f32 = 10.;
-
-    pub const ACTION_POPUP_Y_OFF: f32 = 100.;
-    pub const ACTION_COPY_RECT: Rectangle = Rectangle::new(0., 0., 100., 80.);
-    pub const ACTION_PASTE_RECT: Rectangle = Rectangle::new(110., 0., 120., 80.);
-    pub const ACTION_SELECT_ALL_RECT: Rectangle = Rectangle::new(240., 0., 200., 80.);
-    pub const ACTION_LABEL_POS: Point = Point::new(20., 20.);
 }
 
 use super::EMOJI_PICKER_ICON_SIZE;
@@ -215,7 +203,6 @@ pub async fn make(
     cc.add_const_f32("EMOJIBTN_BOX_1", EMOJIBTN_BOX[1]);
     cc.add_const_f32("SENDBTN_BOX_0", SENDBTN_BOX[0]);
     cc.add_const_f32("SENDBTN_BOX_1", SENDBTN_BOX[1]);
-    cc.add_const_f32("ACTION_POPUP_Y_OFF", ACTION_POPUP_Y_OFF);
     cc.add_const_f32("CMD_HELP_HEIGHT", CMD_HELP_HEIGHT);
     cc.add_const_f32("CMD_HELP_GAP", CMD_HELP_GAP);
 
@@ -1215,398 +1202,11 @@ pub async fn make(
         .await;
     cmd_layer_node.link(node);
 
-    // Create debug box
-    /*
-    let mut node = create_vector_art("debugtool");
-    let mut prop = Property::new("hoff", PropertyType::Float32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-    node.set_property_f32(atom, Role::App, "hoff", 40.).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, EMOJIBTN_BOX[0]).unwrap();
-    let code = cc.compile("h - EMOJIBTN_BOX_1").unwrap();
-    prop.set_expr(atom, Role::App, 1, code).unwrap();
-    prop.set_f32(atom, Role::App, 2, EMOJIBTN_BOX[2]).unwrap();
-    prop.set_f32(atom, Role::App, 3, EMOJIBTN_BOX[3]).unwrap();
-    let hoff_prop = node.get_property("hoff").unwrap();
-    prop.add_depend(&hoff_prop, 0, "hoff");
-    node.set_property_u32(atom, Role::App, "z_index", 6).unwrap();
-    let mut shape = VectorShape::new();
-    shape.add_outline(
-        expr::const_f32(0.),
-        expr::const_f32(0.),
-        expr::load_var("w"),
-        expr::load_var("h"),
-        2.,
-        [1., 0., 0., 1.],
-    );
-    let node =
-        node.setup(|me| VectorArt::new(me, shape, app.render_api.clone())).await;
-    layer_node.link(node);
-    */
-
-    // Overlay popup
-    let content_layer_node = layer_node.clone();
-    let layer_node = create_layer("overlay_layer");
-    let prop = layer_node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, 40.).unwrap();
-    let code = cc.compile("editz_bg_top_y - ACTION_POPUP_Y_OFF").unwrap();
-    //let code = cc.compile("h - 60 - 80").unwrap();
-    //let code = cc.compile("h - 60 - 300").unwrap();
-    prop.set_expr(atom, Role::App, 1, code).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-    prop.add_depend(&editbox_bg_rect_prop, 1, "editz_bg_top_y");
-    layer_node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
-    layer_node.set_property_u32(atom, Role::App, "z_index", 8).unwrap();
-    // Priority higher than chatview but lower than chatedit
-    layer_node.set_property_u32(atom, Role::App, "priority", 1).unwrap();
-    let layer_node = layer_node.setup(|me| Layer::new(me, app.render_api.clone())).await;
-    content_layer_node.link(layer_node.clone());
-
-    let actions_is_visible = PropertyBool::wrap(&layer_node, Role::App, "is_visible", 0).unwrap();
-
-    // Create the actionbar bg
-    let node = create_vector_art("actionbar_bg");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 1, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
-
-    let mut shape = VectorShape::new();
-
-    let color1 = [0., 0.13, 0.08, 0.75];
-    let color2 = [0., 0., 0., 1.];
-    let gradient = [color1.clone(), color1, color2.clone(), color2];
-    let hicolor = [0., 0.94, 1., 1.];
-
-    // Copy box
-    shape.add_gradient_box(
-        expr::const_f32(ACTION_COPY_RECT.x),
-        expr::const_f32(ACTION_COPY_RECT.y),
-        expr::const_f32(ACTION_COPY_RECT.rhs()),
-        expr::const_f32(ACTION_COPY_RECT.bhs()),
-        gradient.clone(),
-    );
-
-    // Copy outline
-    shape.add_outline(
-        expr::const_f32(ACTION_COPY_RECT.x),
-        expr::const_f32(ACTION_COPY_RECT.y),
-        expr::const_f32(ACTION_COPY_RECT.rhs()),
-        expr::const_f32(ACTION_COPY_RECT.bhs()),
-        1.,
-        hicolor.clone(),
-    );
-
-    // Paste box
-    shape.add_gradient_box(
-        expr::const_f32(ACTION_PASTE_RECT.x),
-        expr::const_f32(ACTION_PASTE_RECT.y),
-        expr::const_f32(ACTION_PASTE_RECT.rhs()),
-        expr::const_f32(ACTION_PASTE_RECT.bhs()),
-        gradient.clone(),
-    );
-
-    // Paste outline
-    shape.add_outline(
-        expr::const_f32(ACTION_PASTE_RECT.x),
-        expr::const_f32(ACTION_PASTE_RECT.y),
-        expr::const_f32(ACTION_PASTE_RECT.rhs()),
-        expr::const_f32(ACTION_PASTE_RECT.bhs()),
-        1.,
-        hicolor.clone(),
-    );
-
-    // Select all box
-    shape.add_gradient_box(
-        expr::const_f32(ACTION_SELECT_ALL_RECT.x),
-        expr::const_f32(ACTION_SELECT_ALL_RECT.y),
-        expr::const_f32(ACTION_SELECT_ALL_RECT.rhs()),
-        expr::const_f32(ACTION_SELECT_ALL_RECT.bhs()),
-        gradient,
-    );
-
-    // Select all outline
-    shape.add_outline(
-        expr::const_f32(ACTION_SELECT_ALL_RECT.x),
-        expr::const_f32(ACTION_SELECT_ALL_RECT.y),
-        expr::const_f32(ACTION_SELECT_ALL_RECT.rhs()),
-        expr::const_f32(ACTION_SELECT_ALL_RECT.bhs()),
-        1.,
-        hicolor,
-    );
-
-    let node = node.setup(|me| VectorArt::new(me, shape, app.render_api.clone())).await;
-    layer_node.link(node);
-
-    // Create some text
-    let node = create_text("actions_label");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, ACTION_LABEL_POS.x).unwrap();
-    prop.set_f32(atom, Role::App, 1, ACTION_LABEL_POS.y).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-    node.set_property_f32(atom, Role::App, "font_size", FONTSIZE).unwrap();
-    node.set_property_str(atom, Role::App, "text", "copy   paste   select all").unwrap();
-    //node.set_property_bool(atom, Role::App, "debug", true).unwrap();
-    //node.set_property_str(atom, Role::App, "text", "anon1").unwrap();
-    let prop = node.get_property("text_color").unwrap();
-    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 1, 0.94).unwrap();
-    prop.set_f32(atom, Role::App, 2, 1.).unwrap();
-    prop.set_f32(atom, Role::App, 3, 1.).unwrap();
-    node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
-
-    let node = node
-        .setup(|me| Text::new(me, window_scale.clone(), app.render_api.clone(), i18n_fish.clone()))
-        .await;
-    layer_node.link(node);
-
-    // Copy button
-    let node = create_button("copy_btn");
-    node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, ACTION_COPY_RECT.x).unwrap();
-    prop.set_f32(atom, Role::App, 1, ACTION_COPY_RECT.y).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_COPY_RECT.w).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_COPY_RECT.h).unwrap();
-
-    let (slot, recvr) = Slot::new("copy_clicked");
-    node.register("click", slot).unwrap();
-    let actions_is_visible2 = actions_is_visible.clone();
-    let editz_select_text2 = editz_select_text.clone();
-    let render_api = app.render_api.clone();
-    let listen_click = app.ex.spawn(async move {
-        while let Ok(_) = recvr.recv().await {
-            info!(target: "app::chat", "clicked copy");
-            let atom = &mut render_api.make_guard(gfxtag!("copy_clicked action"));
-            actions_is_visible2.set(atom, false);
-            let select_text = editz_select_text2.get_str(0).unwrap();
-            miniquad::window::clipboard_set(&select_text);
-        }
-    });
-    app.tasks.lock().unwrap().push(listen_click);
-
-    let node = node.setup(Button::new).await;
-    layer_node.link(node);
-
-    // Paste button
-    let node = create_button("paste_btn");
-    node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, ACTION_PASTE_RECT.x).unwrap();
-    prop.set_f32(atom, Role::App, 1, ACTION_PASTE_RECT.y).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_PASTE_RECT.w).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_PASTE_RECT.h).unwrap();
-
-    let (slot, recvr) = Slot::new("paste_clicked");
-    node.register("click", slot).unwrap();
-    let actions_is_visible2 = actions_is_visible.clone();
-    let chatedit_node2 = chatedit_node.clone();
-    let render_api = app.render_api.clone();
-    let listen_click = app.ex.spawn(async move {
-        while let Ok(_) = recvr.recv().await {
-            let atom = &mut render_api.make_guard(gfxtag!("paste_clicked action"));
-            if let Some(text) = miniquad::window::clipboard_get() {
-                info!(target: "app::chat", "clicked paste: {text}");
-                let mut data = vec![];
-                text.encode(&mut data).unwrap();
-                chatedit_node2.call_method("insert_text", data).await.unwrap();
-            } else {
-                info!(target: "app::chat", "clicked paste but clip is empty");
-            }
-            actions_is_visible2.set(atom, false);
-        }
-    });
-    app.tasks.lock().unwrap().push(listen_click);
-
-    let node = node.setup(Button::new).await;
-    layer_node.link(node);
-
-    // Select all button
-    let node = create_button("select_all_btn");
-    node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, ACTION_SELECT_ALL_RECT.x).unwrap();
-    prop.set_f32(atom, Role::App, 1, ACTION_SELECT_ALL_RECT.y).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.w).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-
-    let (slot, recvr) = Slot::new("select_all_clicked");
-    node.register("click", slot).unwrap();
-    let listen_click = app.ex.spawn(async move {
-        while let Ok(_) = recvr.recv().await {
-            info!(target: "app::chat", "clicked select_all");
-        }
-    });
-    app.tasks.lock().unwrap().push(listen_click);
-
-    let node = node.setup(Button::new).await;
-    layer_node.link(node);
-
-    // Paste overlay popup
-    let layer_node = create_layer("paste_layer");
-    let prop = layer_node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, 40.).unwrap();
-    let code = cc.compile("editz_bg_top_y - ACTION_POPUP_Y_OFF").unwrap();
-    //let code = cc.compile("h - 60 - 80").unwrap();
-    //let code = cc.compile("h - 60 - 300").unwrap();
-    prop.set_expr(atom, Role::App, 1, code).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-    prop.add_depend(&editbox_bg_rect_prop, 1, "editz_bg_top_y");
-    layer_node.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
-    layer_node.set_property_u32(atom, Role::App, "z_index", 8).unwrap();
-    // Priority higher than chatview but lower than chatedit
-    layer_node.set_property_u32(atom, Role::App, "priority", 1).unwrap();
-    let layer_node = layer_node.setup(|me| Layer::new(me, app.render_api.clone())).await;
-    content_layer_node.link(layer_node.clone());
-
-    let pasta_is_visible = PropertyBool::wrap(&layer_node, Role::App, "is_visible", 0).unwrap();
-
-    let (slot, recvr) = Slot::new("reqpasta");
-    chatedit_node.register("paste_request", slot).unwrap();
-    let pasta_is_visible2 = pasta_is_visible.clone();
-    let render_api = app.render_api.clone();
-    let listen_click = app.ex.spawn(async move {
-        while let Ok(_) = recvr.recv().await {
-            let atom = &mut render_api.make_guard(gfxtag!("paste_req action"));
-            pasta_is_visible2.set(atom, true);
-        }
-    });
-    app.tasks.lock().unwrap().push(listen_click);
-
-    // Create the paste bg
-    let node = create_vector_art("paste_bg");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 1, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
-
-    let mut shape = VectorShape::new();
-
-    let color1 = [0., 0.13, 0.08, 0.75];
-    let color2 = [0., 0., 0., 1.];
-    let gradient = [color1.clone(), color1, color2.clone(), color2];
-    let hicolor = [0., 0.94, 1., 1.];
-
-    // Paste box
-    shape.add_gradient_box(
-        expr::const_f32(0.),
-        expr::const_f32(0.),
-        expr::const_f32(ACTION_PASTE_RECT.w),
-        expr::const_f32(ACTION_PASTE_RECT.h),
-        gradient.clone(),
-    );
-
-    // Paste outline
-    shape.add_outline(
-        expr::const_f32(0.),
-        expr::const_f32(0.),
-        expr::const_f32(ACTION_PASTE_RECT.w),
-        expr::const_f32(ACTION_PASTE_RECT.h),
-        1.,
-        hicolor.clone(),
-    );
-
-    let node = node.setup(|me| VectorArt::new(me, shape, app.render_api.clone())).await;
-    layer_node.link(node);
-
-    // Create some text
-    let node = create_text("paste_label");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, ACTION_LABEL_POS.x).unwrap();
-    prop.set_f32(atom, Role::App, 1, ACTION_LABEL_POS.y).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_SELECT_ALL_RECT.rhs()).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_SELECT_ALL_RECT.h).unwrap();
-    node.set_property_f32(atom, Role::App, "font_size", FONTSIZE).unwrap();
-    node.set_property_str(atom, Role::App, "text", "paste").unwrap();
-    //node.set_property_bool(atom, Role::App, "debug", true).unwrap();
-    //node.set_property_str(atom, Role::App, "text", "anon1").unwrap();
-    let prop = node.get_property("text_color").unwrap();
-    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 1, 0.94).unwrap();
-    prop.set_f32(atom, Role::App, 2, 1.).unwrap();
-    prop.set_f32(atom, Role::App, 3, 1.).unwrap();
-    node.set_property_u32(atom, Role::App, "z_index", 1).unwrap();
-
-    let node = node
-        .setup(|me| Text::new(me, window_scale.clone(), app.render_api.clone(), i18n_fish.clone()))
-        .await;
-    layer_node.link(node);
-
-    // Paste button
-    let node = create_button("paste_btn");
-    node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 1, 0.).unwrap();
-    prop.set_f32(atom, Role::App, 2, ACTION_PASTE_RECT.w).unwrap();
-    prop.set_f32(atom, Role::App, 3, ACTION_PASTE_RECT.h).unwrap();
-
-    let node = node.setup(Button::new).await;
-    layer_node.link(node.clone());
-
-    let (slot, recvr) = Slot::new("paste_clicked");
-    node.register("click", slot).unwrap();
-    let chatedit_node2 = chatedit_node.clone();
-    let pasta_is_visible2 = pasta_is_visible.clone();
-    let render_api = app.render_api.clone();
-    let listen_click = app.ex.spawn(async move {
-        while let Ok(_) = recvr.recv().await {
-            let atom = &mut render_api.make_guard(gfxtag!("paste_clicked action"));
-            if let Some(text) = miniquad::window::clipboard_get() {
-                info!(target: "app::chat", "clicked paste: {text}");
-                let mut data = vec![];
-                text.encode(&mut data).unwrap();
-                chatedit_node2.call_method("insert_text", data).await.unwrap();
-            } else {
-                info!(target: "app::chat", "clicked paste but clip is empty");
-            }
-            pasta_is_visible2.set(atom, false);
-        }
-    });
-    app.tasks.lock().unwrap().push(listen_click);
-
-    #[cfg(target_os = "android")]
-    {
-        let editz_select_sub = editz_select_text.subscribe_modify();
-        let pasta_is_visible2 = pasta_is_visible.clone();
-        let render_api = app.render_api.clone();
-        let editz_select_task = app.ex.spawn(async move {
-            while let Ok(_) = editz_select_sub.receive().await {
-                let atom = &mut render_api.make_guard(gfxtag!("edit select task"));
-                if editz_select_text.is_null(0).unwrap() {
-                    info!(target: "app::chat", "selection changed: null");
-                    // Avoid triggering unecessary redraws
-                    if actions_is_visible.get() {
-                        actions_is_visible.set(atom, false);
-                        pasta_is_visible2.set(atom, false);
-                    }
-                } else {
-                    let select_text = editz_select_text.get_str(0).unwrap();
-                    info!(target: "app::chat", "selection changed: {select_text}");
-                    // Avoid triggering unecessary redraws
-                    if !actions_is_visible.get() {
-                        actions_is_visible.set(atom, true);
-                        pasta_is_visible2.set(atom, false);
-                    }
-                }
-            }
-        });
-        app.tasks.lock().unwrap().push(editz_select_task);
-    }
-
     let editz_text_sub = editz_text.prop().subscribe_modify();
     let render_api = app.render_api.clone();
     let editz_text_task = app.ex.spawn(async move {
         while let Ok(_) = editz_text_sub.receive().await {
             let atom = &mut render_api.make_guard(gfxtag!("chatedit txt changed"));
-            pasta_is_visible.set(atom, false);
 
             let text = editz_text.get();
             debug!(target: "app::chat", "text changed: {text}");

+ 48 - 6
bin/app/src/ui/edit/mod.rs

@@ -661,6 +661,36 @@ impl BaseEdit {
     fn handle_touch_start(&self, touch_pos: Point) -> bool {
         t!("handle_touch_start({touch_pos:?})");
 
+        let atom = &mut self.render_api.make_guard(gfxtag!("BaseEdit::handle_touch_start_action"));
+        if let Some(action_id) = self.action_mode.interact(touch_pos) {
+            match action_id {
+                ACTION_COPY => {
+                    if let Some(txt) = self.editor.lock().selected_text() {
+                        miniquad::window::clipboard_set(&txt);
+                    }
+                }
+                ACTION_PASTE => {
+                    if let Some(txt) = miniquad::window::clipboard_get() {
+                        self.editor.lock().insert(&txt, atom);
+                        self.behave.apply_cursor_scroll();
+                    }
+                }
+                ACTION_SELALL => {
+                    self.editor.lock().driver().select_all();
+                    if let Some(seltext) = self.editor.lock().selected_text() {
+                        self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
+                    }
+                }
+                _ => {}
+            }
+
+            self.eval_rect();
+            self.redraw(atom);
+            return true;
+        } else {
+            self.action_mode.redraw(atom.batch_id);
+        }
+
         let rect = self.rect.get();
         if !rect.contains(touch_pos) {
             t!("rect!cont rect={rect:?}, touch_pos={touch_pos:?}");
@@ -759,27 +789,39 @@ impl BaseEdit {
         match &touch_state {
             TouchStateAction::Inactive => return false,
             TouchStateAction::StartSelect => {
+                let cursor_pos = self.get_cursor_pos();
+                let mut menu = action::Menu::new(
+                    cursor_pos,
+                    self.font_size.get(),
+                    self.action_fg_color.get(),
+                    self.action_bg_color.get(),
+                    self.action_padding.get(),
+                    self.action_spacing.get(),
+                    self.window_scale.get(),
+                );
+
                 let atom = &mut self
                     .render_api
                     .make_guard(gfxtag!("BaseEdit::TouchStateAction::StartSelect"));
 
                 if self.text.get().is_empty() {
-                    self.node().trigger("paste_request", vec![]).await.unwrap();
-                    /*
-                    self.draw_pasta_overlay(atom.batch_id);
+                    menu.add("Paste", ACTION_PASTE);
 
-                    d!("touch state: StartSelect -> Pasta");
                     self.touch_info.lock().state = TouchStateAction::Inactive;
-                    */
                 } else {
-                    self.abs_to_local(&mut touch_pos);
+                    menu.add("Copy", ACTION_COPY);
+                    menu.add("Paste", ACTION_PASTE);
+                    menu.add("Select All", ACTION_SELALL);
 
+                    self.abs_to_local(&mut touch_pos);
                     self.start_touch_select(touch_pos, atom);
                     self.redraw_select(atom.batch_id);
 
                     d!("touch state: StartSelect -> Select");
                     self.touch_info.lock().state = TouchStateAction::Select;
                 }
+                self.action_mode.set(menu);
+                self.action_mode.redraw(atom.batch_id);
             }
             TouchStateAction::DragSelectHandle { side } => {
                 let rect = self.rect.get();