chat: add copy text entry to message menu (#8271)

Bennet Bo Fenner created

As we don't have selection inside the chat right now (which might be
complicated to implement, e.g. cross element selection and markdown
blocks), I think its viable to support copying the whole text of a
message using the message menu:

![image](https://github.com/zed-industries/zed/assets/53836821/6092dfed-0297-457e-9455-ba1e6190e288)

Release Notes:

- Added option to copy the text of a message within the chat

Change summary

crates/collab_ui/src/chat_panel.rs | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)

Detailed changes

crates/collab_ui/src/chat_panel.rs 🔗

@@ -7,9 +7,9 @@ use collections::HashMap;
 use db::kvp::KEY_VALUE_STORE;
 use editor::Editor;
 use gpui::{
-    actions, div, list, prelude::*, px, Action, AppContext, AsyncWindowContext, CursorStyle,
-    DismissEvent, ElementId, EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight,
-    HighlightStyle, ListOffset, ListScrollEvent, ListState, Model, Render, StyledText,
+    actions, div, list, prelude::*, px, Action, AppContext, AsyncWindowContext, ClipboardItem,
+    CursorStyle, DismissEvent, ElementId, EventEmitter, FocusHandle, FocusableView, FontStyle,
+    FontWeight, HighlightStyle, ListOffset, ListScrollEvent, ListState, Model, Render, StyledText,
     Subscription, Task, View, ViewContext, VisualContext, WeakView,
 };
 use language::LanguageRegistry;
@@ -629,6 +629,20 @@ impl ChatPanel {
                         })
                     }),
                 )
+                .entry(
+                    "Copy message text",
+                    None,
+                    cx.handler_for(&this, move |this, cx| {
+                        this.active_chat().map(|active_chat| {
+                            if let Some(message) =
+                                active_chat.read(cx).find_loaded_message(message_id)
+                            {
+                                let text = message.body.clone();
+                                cx.write_to_clipboard(ClipboardItem::new(text))
+                            }
+                        });
+                    }),
+                )
                 .when(can_delete_message, move |menu| {
                     menu.entry(
                         "Delete message",