@@ -4,6 +4,7 @@ use crate::{channel_buffer::ChannelBuffer, channel_chat::ChannelChat};
use anyhow::{anyhow, Result};
use client::{Client, Subscription, User, UserId, UserStore};
use collections::{hash_map, HashMap, HashSet};
+use db::RELEASE_CHANNEL;
use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt};
use gpui::{AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Task, WeakModelHandle};
use rpc::{
@@ -47,6 +48,26 @@ pub struct Channel {
pub unseen_message_id: Option<u64>,
}
+impl Channel {
+ pub fn link(&self) -> String {
+ RELEASE_CHANNEL.link_prefix().to_owned()
+ + "channel/"
+ + &self.slug()
+ + "-"
+ + &self.id.to_string()
+ }
+
+ pub fn slug(&self) -> String {
+ let slug: String = self
+ .name
+ .chars()
+ .map(|c| if c.is_alphanumeric() { c } else { '-' })
+ .collect();
+
+ slug.trim_matches(|c| c == '-').to_string()
+ }
+}
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
pub struct ChannelPath(Arc<[ChannelId]>);
@@ -34,8 +34,8 @@ use gpui::{
},
impl_actions,
platform::{CursorStyle, MouseButton, PromptLevel},
- serde_json, AnyElement, AppContext, AsyncAppContext, Element, Entity, FontCache, ModelHandle,
- Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
+ serde_json, AnyElement, AppContext, AsyncAppContext, ClipboardItem, Element, Entity, FontCache,
+ ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
};
use menu::{Confirm, SelectNext, SelectPrev};
use project::{Fs, Project};
@@ -100,6 +100,11 @@ pub struct JoinChannelChat {
pub channel_id: u64,
}
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct CopyChannelLink {
+ pub channel_id: u64,
+}
+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct StartMoveChannelFor {
channel_id: ChannelId,
@@ -157,6 +162,7 @@ impl_actions!(
OpenChannelNotes,
JoinChannelCall,
JoinChannelChat,
+ CopyChannelLink,
LinkChannel,
StartMoveChannelFor,
StartLinkChannelFor,
@@ -205,6 +211,7 @@ pub fn init(cx: &mut AppContext) {
cx.add_action(CollabPanel::expand_selected_channel);
cx.add_action(CollabPanel::open_channel_notes);
cx.add_action(CollabPanel::join_channel_chat);
+ cx.add_action(CollabPanel::copy_channel_link);
cx.add_action(
|panel: &mut CollabPanel, action: &ToggleSelectedIx, cx: &mut ViewContext<CollabPanel>| {
@@ -2571,6 +2578,13 @@ impl CollabPanel {
},
));
+ items.push(ContextMenuItem::action(
+ "Copy Channel Link",
+ CopyChannelLink {
+ channel_id: path.channel_id(),
+ },
+ ));
+
if self.channel_store.read(cx).is_user_admin(path.channel_id()) {
let parent_id = path.parent_id();
@@ -3219,6 +3233,15 @@ impl CollabPanel {
});
}
}
+
+ fn copy_channel_link(&mut self, action: &CopyChannelLink, cx: &mut ViewContext<Self>) {
+ let channel_store = self.channel_store.read(cx);
+ let Some(channel) = channel_store.channel_for_id(action.channel_id) else {
+ return;
+ };
+ let item = ClipboardItem::new(channel.link());
+ cx.write_to_clipboard(item)
+ }
}
fn render_tree_branch(