Add read-only channel notes support
Fix some bugs where ChannelNotes and ChannelChat had old cached channel instances
This commit is contained in:
parent
3853009d92
commit
0eff7c6ca9
12 changed files with 186 additions and 219 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1569,6 +1569,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"settings",
|
"settings",
|
||||||
|
"smallvec",
|
||||||
"theme",
|
"theme",
|
||||||
"theme_selector",
|
"theme_selector",
|
||||||
"time",
|
"time",
|
||||||
|
|
|
@ -370,42 +370,15 @@
|
||||||
{
|
{
|
||||||
"context": "Pane",
|
"context": "Pane",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"ctrl-1": [
|
"ctrl-1": ["pane::ActivateItem", 0],
|
||||||
"pane::ActivateItem",
|
"ctrl-2": ["pane::ActivateItem", 1],
|
||||||
0
|
"ctrl-3": ["pane::ActivateItem", 2],
|
||||||
],
|
"ctrl-4": ["pane::ActivateItem", 3],
|
||||||
"ctrl-2": [
|
"ctrl-5": ["pane::ActivateItem", 4],
|
||||||
"pane::ActivateItem",
|
"ctrl-6": ["pane::ActivateItem", 5],
|
||||||
1
|
"ctrl-7": ["pane::ActivateItem", 6],
|
||||||
],
|
"ctrl-8": ["pane::ActivateItem", 7],
|
||||||
"ctrl-3": [
|
"ctrl-9": ["pane::ActivateItem", 8],
|
||||||
"pane::ActivateItem",
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"ctrl-4": [
|
|
||||||
"pane::ActivateItem",
|
|
||||||
3
|
|
||||||
],
|
|
||||||
"ctrl-5": [
|
|
||||||
"pane::ActivateItem",
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"ctrl-6": [
|
|
||||||
"pane::ActivateItem",
|
|
||||||
5
|
|
||||||
],
|
|
||||||
"ctrl-7": [
|
|
||||||
"pane::ActivateItem",
|
|
||||||
6
|
|
||||||
],
|
|
||||||
"ctrl-8": [
|
|
||||||
"pane::ActivateItem",
|
|
||||||
7
|
|
||||||
],
|
|
||||||
"ctrl-9": [
|
|
||||||
"pane::ActivateItem",
|
|
||||||
8
|
|
||||||
],
|
|
||||||
"ctrl-0": "pane::ActivateLastItem",
|
"ctrl-0": "pane::ActivateLastItem",
|
||||||
"ctrl--": "pane::GoBack",
|
"ctrl--": "pane::GoBack",
|
||||||
"ctrl-_": "pane::GoForward",
|
"ctrl-_": "pane::GoForward",
|
||||||
|
@ -416,42 +389,15 @@
|
||||||
{
|
{
|
||||||
"context": "Workspace",
|
"context": "Workspace",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"cmd-1": [
|
"cmd-1": ["workspace::ActivatePane", 0],
|
||||||
"workspace::ActivatePane",
|
"cmd-2": ["workspace::ActivatePane", 1],
|
||||||
0
|
"cmd-3": ["workspace::ActivatePane", 2],
|
||||||
],
|
"cmd-4": ["workspace::ActivatePane", 3],
|
||||||
"cmd-2": [
|
"cmd-5": ["workspace::ActivatePane", 4],
|
||||||
"workspace::ActivatePane",
|
"cmd-6": ["workspace::ActivatePane", 5],
|
||||||
1
|
"cmd-7": ["workspace::ActivatePane", 6],
|
||||||
],
|
"cmd-8": ["workspace::ActivatePane", 7],
|
||||||
"cmd-3": [
|
"cmd-9": ["workspace::ActivatePane", 8],
|
||||||
"workspace::ActivatePane",
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"cmd-4": [
|
|
||||||
"workspace::ActivatePane",
|
|
||||||
3
|
|
||||||
],
|
|
||||||
"cmd-5": [
|
|
||||||
"workspace::ActivatePane",
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"cmd-6": [
|
|
||||||
"workspace::ActivatePane",
|
|
||||||
5
|
|
||||||
],
|
|
||||||
"cmd-7": [
|
|
||||||
"workspace::ActivatePane",
|
|
||||||
6
|
|
||||||
],
|
|
||||||
"cmd-8": [
|
|
||||||
"workspace::ActivatePane",
|
|
||||||
7
|
|
||||||
],
|
|
||||||
"cmd-9": [
|
|
||||||
"workspace::ActivatePane",
|
|
||||||
8
|
|
||||||
],
|
|
||||||
"cmd-b": "workspace::ToggleLeftDock",
|
"cmd-b": "workspace::ToggleLeftDock",
|
||||||
"cmd-r": "workspace::ToggleRightDock",
|
"cmd-r": "workspace::ToggleRightDock",
|
||||||
"cmd-j": "workspace::ToggleBottomDock",
|
"cmd-j": "workspace::ToggleBottomDock",
|
||||||
|
@ -494,38 +440,14 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"cmd-k cmd-left": [
|
"cmd-k cmd-left": ["workspace::ActivatePaneInDirection", "Left"],
|
||||||
"workspace::ActivatePaneInDirection",
|
"cmd-k cmd-right": ["workspace::ActivatePaneInDirection", "Right"],
|
||||||
"Left"
|
"cmd-k cmd-up": ["workspace::ActivatePaneInDirection", "Up"],
|
||||||
],
|
"cmd-k cmd-down": ["workspace::ActivatePaneInDirection", "Down"],
|
||||||
"cmd-k cmd-right": [
|
"cmd-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
||||||
"workspace::ActivatePaneInDirection",
|
"cmd-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
||||||
"Right"
|
"cmd-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
||||||
],
|
"cmd-k shift-down": ["workspace::SwapPaneInDirection", "Down"]
|
||||||
"cmd-k cmd-up": [
|
|
||||||
"workspace::ActivatePaneInDirection",
|
|
||||||
"Up"
|
|
||||||
],
|
|
||||||
"cmd-k cmd-down": [
|
|
||||||
"workspace::ActivatePaneInDirection",
|
|
||||||
"Down"
|
|
||||||
],
|
|
||||||
"cmd-k shift-left": [
|
|
||||||
"workspace::SwapPaneInDirection",
|
|
||||||
"Left"
|
|
||||||
],
|
|
||||||
"cmd-k shift-right": [
|
|
||||||
"workspace::SwapPaneInDirection",
|
|
||||||
"Right"
|
|
||||||
],
|
|
||||||
"cmd-k shift-up": [
|
|
||||||
"workspace::SwapPaneInDirection",
|
|
||||||
"Up"
|
|
||||||
],
|
|
||||||
"cmd-k shift-down": [
|
|
||||||
"workspace::SwapPaneInDirection",
|
|
||||||
"Down"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Bindings from Atom
|
// Bindings from Atom
|
||||||
|
@ -627,14 +549,6 @@
|
||||||
"space": "collab_panel::InsertSpace"
|
"space": "collab_panel::InsertSpace"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"context": "(CollabPanel && not_editing) > Editor",
|
|
||||||
"bindings": {
|
|
||||||
"cmd-c": "collab_panel::StartLinkChannel",
|
|
||||||
"cmd-x": "collab_panel::StartMoveChannel",
|
|
||||||
"cmd-v": "collab_panel::MoveOrLinkToSelected"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"context": "ChannelModal",
|
"context": "ChannelModal",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
|
@ -655,57 +569,21 @@
|
||||||
"cmd-v": "terminal::Paste",
|
"cmd-v": "terminal::Paste",
|
||||||
"cmd-k": "terminal::Clear",
|
"cmd-k": "terminal::Clear",
|
||||||
// Some nice conveniences
|
// Some nice conveniences
|
||||||
"cmd-backspace": [
|
"cmd-backspace": ["terminal::SendText", "\u0015"],
|
||||||
"terminal::SendText",
|
"cmd-right": ["terminal::SendText", "\u0005"],
|
||||||
"\u0015"
|
"cmd-left": ["terminal::SendText", "\u0001"],
|
||||||
],
|
|
||||||
"cmd-right": [
|
|
||||||
"terminal::SendText",
|
|
||||||
"\u0005"
|
|
||||||
],
|
|
||||||
"cmd-left": [
|
|
||||||
"terminal::SendText",
|
|
||||||
"\u0001"
|
|
||||||
],
|
|
||||||
// Terminal.app compatibility
|
// Terminal.app compatibility
|
||||||
"alt-left": [
|
"alt-left": ["terminal::SendText", "\u001bb"],
|
||||||
"terminal::SendText",
|
"alt-right": ["terminal::SendText", "\u001bf"],
|
||||||
"\u001bb"
|
|
||||||
],
|
|
||||||
"alt-right": [
|
|
||||||
"terminal::SendText",
|
|
||||||
"\u001bf"
|
|
||||||
],
|
|
||||||
// There are conflicting bindings for these keys in the global context.
|
// There are conflicting bindings for these keys in the global context.
|
||||||
// these bindings override them, remove at your own risk:
|
// these bindings override them, remove at your own risk:
|
||||||
"up": [
|
"up": ["terminal::SendKeystroke", "up"],
|
||||||
"terminal::SendKeystroke",
|
"pageup": ["terminal::SendKeystroke", "pageup"],
|
||||||
"up"
|
"down": ["terminal::SendKeystroke", "down"],
|
||||||
],
|
"pagedown": ["terminal::SendKeystroke", "pagedown"],
|
||||||
"pageup": [
|
"escape": ["terminal::SendKeystroke", "escape"],
|
||||||
"terminal::SendKeystroke",
|
"enter": ["terminal::SendKeystroke", "enter"],
|
||||||
"pageup"
|
"ctrl-c": ["terminal::SendKeystroke", "ctrl-c"]
|
||||||
],
|
|
||||||
"down": [
|
|
||||||
"terminal::SendKeystroke",
|
|
||||||
"down"
|
|
||||||
],
|
|
||||||
"pagedown": [
|
|
||||||
"terminal::SendKeystroke",
|
|
||||||
"pagedown"
|
|
||||||
],
|
|
||||||
"escape": [
|
|
||||||
"terminal::SendKeystroke",
|
|
||||||
"escape"
|
|
||||||
],
|
|
||||||
"enter": [
|
|
||||||
"terminal::SendKeystroke",
|
|
||||||
"enter"
|
|
||||||
],
|
|
||||||
"ctrl-c": [
|
|
||||||
"terminal::SendKeystroke",
|
|
||||||
"ctrl-c"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub enum Event {
|
||||||
|
|
||||||
pub struct Room {
|
pub struct Room {
|
||||||
id: u64,
|
id: u64,
|
||||||
channel_id: Option<u64>,
|
pub channel_id: Option<u64>,
|
||||||
live_kit: Option<LiveKitRoom>,
|
live_kit: Option<LiveKitRoom>,
|
||||||
status: RoomStatus,
|
status: RoomStatus,
|
||||||
shared_projects: HashSet<WeakModelHandle<Project>>,
|
shared_projects: HashSet<WeakModelHandle<Project>>,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::Channel;
|
use crate::{Channel, ChannelId, ChannelStore};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use client::{Client, Collaborator, UserStore};
|
use client::{Client, Collaborator, UserStore};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
@ -19,10 +19,11 @@ pub(crate) fn init(client: &Arc<Client>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ChannelBuffer {
|
pub struct ChannelBuffer {
|
||||||
pub(crate) channel: Arc<Channel>,
|
pub channel_id: ChannelId,
|
||||||
connected: bool,
|
connected: bool,
|
||||||
collaborators: HashMap<PeerId, Collaborator>,
|
collaborators: HashMap<PeerId, Collaborator>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
|
channel_store: ModelHandle<ChannelStore>,
|
||||||
buffer: ModelHandle<language::Buffer>,
|
buffer: ModelHandle<language::Buffer>,
|
||||||
buffer_epoch: u64,
|
buffer_epoch: u64,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
|
@ -34,6 +35,7 @@ pub enum ChannelBufferEvent {
|
||||||
CollaboratorsChanged,
|
CollaboratorsChanged,
|
||||||
Disconnected,
|
Disconnected,
|
||||||
BufferEdited,
|
BufferEdited,
|
||||||
|
ChannelChanged,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for ChannelBuffer {
|
impl Entity for ChannelBuffer {
|
||||||
|
@ -46,7 +48,7 @@ impl Entity for ChannelBuffer {
|
||||||
}
|
}
|
||||||
self.client
|
self.client
|
||||||
.send(proto::LeaveChannelBuffer {
|
.send(proto::LeaveChannelBuffer {
|
||||||
channel_id: self.channel.id,
|
channel_id: self.channel_id,
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
|
@ -58,6 +60,7 @@ impl ChannelBuffer {
|
||||||
channel: Arc<Channel>,
|
channel: Arc<Channel>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
|
channel_store: ModelHandle<ChannelStore>,
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<ModelHandle<Self>> {
|
) -> Result<ModelHandle<Self>> {
|
||||||
let response = client
|
let response = client
|
||||||
|
@ -90,9 +93,10 @@ impl ChannelBuffer {
|
||||||
connected: true,
|
connected: true,
|
||||||
collaborators: Default::default(),
|
collaborators: Default::default(),
|
||||||
acknowledge_task: None,
|
acknowledge_task: None,
|
||||||
channel,
|
channel_id: channel.id,
|
||||||
subscription: Some(subscription.set_model(&cx.handle(), &mut cx.to_async())),
|
subscription: Some(subscription.set_model(&cx.handle(), &mut cx.to_async())),
|
||||||
user_store,
|
user_store,
|
||||||
|
channel_store,
|
||||||
};
|
};
|
||||||
this.replace_collaborators(response.collaborators, cx);
|
this.replace_collaborators(response.collaborators, cx);
|
||||||
this
|
this
|
||||||
|
@ -179,7 +183,7 @@ impl ChannelBuffer {
|
||||||
let operation = language::proto::serialize_operation(operation);
|
let operation = language::proto::serialize_operation(operation);
|
||||||
self.client
|
self.client
|
||||||
.send(proto::UpdateChannelBuffer {
|
.send(proto::UpdateChannelBuffer {
|
||||||
channel_id: self.channel.id,
|
channel_id: self.channel_id,
|
||||||
operations: vec![operation],
|
operations: vec![operation],
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
|
@ -223,12 +227,15 @@ impl ChannelBuffer {
|
||||||
&self.collaborators
|
&self.collaborators
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn channel(&self) -> Arc<Channel> {
|
pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
||||||
self.channel.clone()
|
self.channel_store
|
||||||
|
.read(cx)
|
||||||
|
.channel_for_id(self.channel_id)
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn disconnect(&mut self, cx: &mut ModelContext<Self>) {
|
pub(crate) fn disconnect(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
log::info!("channel buffer {} disconnected", self.channel.id);
|
log::info!("channel buffer {} disconnected", self.channel_id);
|
||||||
if self.connected {
|
if self.connected {
|
||||||
self.connected = false;
|
self.connected = false;
|
||||||
self.subscription.take();
|
self.subscription.take();
|
||||||
|
@ -237,6 +244,11 @@ impl ChannelBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn channel_changed(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
|
cx.emit(ChannelBufferEvent::ChannelChanged);
|
||||||
|
cx.notify()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_connected(&self) -> bool {
|
pub fn is_connected(&self) -> bool {
|
||||||
self.connected
|
self.connected
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use time::OffsetDateTime;
|
||||||
use util::{post_inc, ResultExt as _, TryFutureExt};
|
use util::{post_inc, ResultExt as _, TryFutureExt};
|
||||||
|
|
||||||
pub struct ChannelChat {
|
pub struct ChannelChat {
|
||||||
channel: Arc<Channel>,
|
pub channel_id: ChannelId,
|
||||||
messages: SumTree<ChannelMessage>,
|
messages: SumTree<ChannelMessage>,
|
||||||
channel_store: ModelHandle<ChannelStore>,
|
channel_store: ModelHandle<ChannelStore>,
|
||||||
loaded_all_messages: bool,
|
loaded_all_messages: bool,
|
||||||
|
@ -74,7 +74,7 @@ impl Entity for ChannelChat {
|
||||||
fn release(&mut self, _: &mut AppContext) {
|
fn release(&mut self, _: &mut AppContext) {
|
||||||
self.rpc
|
self.rpc
|
||||||
.send(proto::LeaveChannelChat {
|
.send(proto::LeaveChannelChat {
|
||||||
channel_id: self.channel.id,
|
channel_id: self.channel_id,
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ impl ChannelChat {
|
||||||
|
|
||||||
Ok(cx.add_model(|cx| {
|
Ok(cx.add_model(|cx| {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
channel,
|
channel_id: channel.id,
|
||||||
user_store,
|
user_store,
|
||||||
channel_store,
|
channel_store,
|
||||||
rpc: client,
|
rpc: client,
|
||||||
|
@ -116,8 +116,11 @@ impl ChannelChat {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn channel(&self) -> &Arc<Channel> {
|
pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
||||||
&self.channel
|
self.channel_store
|
||||||
|
.read(cx)
|
||||||
|
.channel_for_id(self.channel_id)
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_message(
|
pub fn send_message(
|
||||||
|
@ -135,7 +138,7 @@ impl ChannelChat {
|
||||||
.current_user()
|
.current_user()
|
||||||
.ok_or_else(|| anyhow!("current_user is not present"))?;
|
.ok_or_else(|| anyhow!("current_user is not present"))?;
|
||||||
|
|
||||||
let channel_id = self.channel.id;
|
let channel_id = self.channel_id;
|
||||||
let pending_id = ChannelMessageId::Pending(post_inc(&mut self.next_pending_message_id));
|
let pending_id = ChannelMessageId::Pending(post_inc(&mut self.next_pending_message_id));
|
||||||
let nonce = self.rng.gen();
|
let nonce = self.rng.gen();
|
||||||
self.insert_messages(
|
self.insert_messages(
|
||||||
|
@ -178,7 +181,7 @@ impl ChannelChat {
|
||||||
|
|
||||||
pub fn remove_message(&mut self, id: u64, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
pub fn remove_message(&mut self, id: u64, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
||||||
let response = self.rpc.request(proto::RemoveChannelMessage {
|
let response = self.rpc.request(proto::RemoveChannelMessage {
|
||||||
channel_id: self.channel.id,
|
channel_id: self.channel_id,
|
||||||
message_id: id,
|
message_id: id,
|
||||||
});
|
});
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
@ -195,7 +198,7 @@ impl ChannelChat {
|
||||||
if !self.loaded_all_messages {
|
if !self.loaded_all_messages {
|
||||||
let rpc = self.rpc.clone();
|
let rpc = self.rpc.clone();
|
||||||
let user_store = self.user_store.clone();
|
let user_store = self.user_store.clone();
|
||||||
let channel_id = self.channel.id;
|
let channel_id = self.channel_id;
|
||||||
if let Some(before_message_id) =
|
if let Some(before_message_id) =
|
||||||
self.messages.first().and_then(|message| match message.id {
|
self.messages.first().and_then(|message| match message.id {
|
||||||
ChannelMessageId::Saved(id) => Some(id),
|
ChannelMessageId::Saved(id) => Some(id),
|
||||||
|
@ -236,13 +239,13 @@ impl ChannelChat {
|
||||||
{
|
{
|
||||||
self.rpc
|
self.rpc
|
||||||
.send(proto::AckChannelMessage {
|
.send(proto::AckChannelMessage {
|
||||||
channel_id: self.channel.id,
|
channel_id: self.channel_id,
|
||||||
message_id: latest_message_id,
|
message_id: latest_message_id,
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
self.last_acknowledged_id = Some(latest_message_id);
|
self.last_acknowledged_id = Some(latest_message_id);
|
||||||
self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
store.acknowledge_message_id(self.channel.id, latest_message_id, cx);
|
store.acknowledge_message_id(self.channel_id, latest_message_id, cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +254,7 @@ impl ChannelChat {
|
||||||
pub fn rejoin(&mut self, cx: &mut ModelContext<Self>) {
|
pub fn rejoin(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
let user_store = self.user_store.clone();
|
let user_store = self.user_store.clone();
|
||||||
let rpc = self.rpc.clone();
|
let rpc = self.rpc.clone();
|
||||||
let channel_id = self.channel.id;
|
let channel_id = self.channel_id;
|
||||||
cx.spawn(|this, mut cx| {
|
cx.spawn(|this, mut cx| {
|
||||||
async move {
|
async move {
|
||||||
let response = rpc.request(proto::JoinChannelChat { channel_id }).await?;
|
let response = rpc.request(proto::JoinChannelChat { channel_id }).await?;
|
||||||
|
@ -348,7 +351,7 @@ impl ChannelChat {
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.insert_messages(SumTree::from_item(message, &()), cx);
|
this.insert_messages(SumTree::from_item(message, &()), cx);
|
||||||
cx.emit(ChannelChatEvent::NewMessage {
|
cx.emit(ChannelChatEvent::NewMessage {
|
||||||
channel_id: this.channel.id,
|
channel_id: this.channel_id,
|
||||||
message_id,
|
message_id,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -72,6 +72,10 @@ impl Channel {
|
||||||
|
|
||||||
slug.trim_matches(|c| c == '-').to_string()
|
slug.trim_matches(|c| c == '-').to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn can_edit_notes(&self) -> bool {
|
||||||
|
self.role == proto::ChannelRole::Member || self.role == proto::ChannelRole::Admin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
|
||||||
|
@ -265,10 +269,11 @@ impl ChannelStore {
|
||||||
) -> Task<Result<ModelHandle<ChannelBuffer>>> {
|
) -> Task<Result<ModelHandle<ChannelBuffer>>> {
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
let user_store = self.user_store.clone();
|
let user_store = self.user_store.clone();
|
||||||
|
let channel_store = cx.handle();
|
||||||
self.open_channel_resource(
|
self.open_channel_resource(
|
||||||
channel_id,
|
channel_id,
|
||||||
|this| &mut this.opened_buffers,
|
|this| &mut this.opened_buffers,
|
||||||
|channel, cx| ChannelBuffer::new(channel, client, user_store, cx),
|
|channel, cx| ChannelBuffer::new(channel, client, user_store, channel_store, cx),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -778,7 +783,7 @@ impl ChannelStore {
|
||||||
let channel_buffer = buffer.read(cx);
|
let channel_buffer = buffer.read(cx);
|
||||||
let buffer = channel_buffer.buffer().read(cx);
|
let buffer = channel_buffer.buffer().read(cx);
|
||||||
buffer_versions.push(proto::ChannelBufferVersion {
|
buffer_versions.push(proto::ChannelBufferVersion {
|
||||||
channel_id: channel_buffer.channel().id,
|
channel_id: channel_buffer.channel_id,
|
||||||
epoch: channel_buffer.epoch(),
|
epoch: channel_buffer.epoch(),
|
||||||
version: language::proto::serialize_version(&buffer.version()),
|
version: language::proto::serialize_version(&buffer.version()),
|
||||||
});
|
});
|
||||||
|
@ -805,13 +810,13 @@ impl ChannelStore {
|
||||||
};
|
};
|
||||||
|
|
||||||
channel_buffer.update(cx, |channel_buffer, cx| {
|
channel_buffer.update(cx, |channel_buffer, cx| {
|
||||||
let channel_id = channel_buffer.channel().id;
|
let channel_id = channel_buffer.channel_id;
|
||||||
if let Some(remote_buffer) = response
|
if let Some(remote_buffer) = response
|
||||||
.buffers
|
.buffers
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|buffer| buffer.channel_id == channel_id)
|
.find(|buffer| buffer.channel_id == channel_id)
|
||||||
{
|
{
|
||||||
let channel_id = channel_buffer.channel().id;
|
let channel_id = channel_buffer.channel_id;
|
||||||
let remote_version =
|
let remote_version =
|
||||||
language::proto::deserialize_version(&remote_buffer.version);
|
language::proto::deserialize_version(&remote_buffer.version);
|
||||||
|
|
||||||
|
@ -934,11 +939,27 @@ impl ChannelStore {
|
||||||
|
|
||||||
if channels_changed {
|
if channels_changed {
|
||||||
if !payload.delete_channels.is_empty() {
|
if !payload.delete_channels.is_empty() {
|
||||||
self.channel_index.delete_channels(&payload.delete_channels);
|
let mut channels_to_delete: Vec<u64> = Vec::new();
|
||||||
self.channel_participants
|
let mut channels_to_rehome: Vec<u64> = Vec::new();
|
||||||
.retain(|channel_id, _| !payload.delete_channels.contains(channel_id));
|
for channel_id in payload.delete_channels {
|
||||||
|
if payload
|
||||||
|
.channels
|
||||||
|
.iter()
|
||||||
|
.any(|channel| channel.id == channel_id)
|
||||||
|
{
|
||||||
|
channels_to_rehome.push(channel_id)
|
||||||
|
} else {
|
||||||
|
channels_to_delete.push(channel_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for channel_id in &payload.delete_channels {
|
self.channel_index.delete_channels(&channels_to_delete);
|
||||||
|
self.channel_index
|
||||||
|
.delete_paths_through_channels(&channels_to_rehome);
|
||||||
|
self.channel_participants
|
||||||
|
.retain(|channel_id, _| !channels_to_delete.contains(channel_id));
|
||||||
|
|
||||||
|
for channel_id in &channels_to_delete {
|
||||||
let channel_id = *channel_id;
|
let channel_id = *channel_id;
|
||||||
if payload
|
if payload
|
||||||
.channels
|
.channels
|
||||||
|
@ -959,7 +980,16 @@ impl ChannelStore {
|
||||||
|
|
||||||
let mut index = self.channel_index.bulk_insert();
|
let mut index = self.channel_index.bulk_insert();
|
||||||
for channel in payload.channels {
|
for channel in payload.channels {
|
||||||
index.insert(channel)
|
let id = channel.id;
|
||||||
|
let channel_changed = index.insert(channel);
|
||||||
|
|
||||||
|
if channel_changed {
|
||||||
|
if let Some(OpenedModelHandle::Open(buffer)) = self.opened_buffers.get(&id) {
|
||||||
|
if let Some(buffer) = buffer.upgrade(cx) {
|
||||||
|
buffer.update(cx, ChannelBuffer::channel_changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for unseen_buffer_change in payload.unseen_channel_buffer_changes {
|
for unseen_buffer_change in payload.unseen_channel_buffer_changes {
|
||||||
|
|
|
@ -24,12 +24,16 @@ impl ChannelIndex {
|
||||||
|
|
||||||
/// Delete the given channels from this index.
|
/// Delete the given channels from this index.
|
||||||
pub fn delete_channels(&mut self, channels: &[ChannelId]) {
|
pub fn delete_channels(&mut self, channels: &[ChannelId]) {
|
||||||
|
dbg!("delete_channels", &channels);
|
||||||
self.channels_by_id
|
self.channels_by_id
|
||||||
.retain(|channel_id, _| !channels.contains(channel_id));
|
.retain(|channel_id, _| !channels.contains(channel_id));
|
||||||
self.paths.retain(|path| {
|
self.delete_paths_through_channels(channels)
|
||||||
path.iter()
|
}
|
||||||
.all(|channel_id| self.channels_by_id.contains_key(channel_id))
|
|
||||||
});
|
pub fn delete_paths_through_channels(&mut self, channels: &[ChannelId]) {
|
||||||
|
dbg!("rehome_channels", &channels);
|
||||||
|
self.paths
|
||||||
|
.retain(|path| !path.iter().any(|channel_id| channels.contains(channel_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bulk_insert(&mut self) -> ChannelPathsInsertGuard {
|
pub fn bulk_insert(&mut self) -> ChannelPathsInsertGuard {
|
||||||
|
@ -121,9 +125,15 @@ impl<'a> ChannelPathsInsertGuard<'a> {
|
||||||
insert_new_message(&mut self.channels_by_id, channel_id, message_id)
|
insert_new_message(&mut self.channels_by_id, channel_id, message_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, channel_proto: proto::Channel) {
|
pub fn insert(&mut self, channel_proto: proto::Channel) -> bool {
|
||||||
|
let mut ret = false;
|
||||||
if let Some(existing_channel) = self.channels_by_id.get_mut(&channel_proto.id) {
|
if let Some(existing_channel) = self.channels_by_id.get_mut(&channel_proto.id) {
|
||||||
let existing_channel = Arc::make_mut(existing_channel);
|
let existing_channel = Arc::make_mut(existing_channel);
|
||||||
|
|
||||||
|
ret = existing_channel.visibility != channel_proto.visibility()
|
||||||
|
|| existing_channel.role != channel_proto.role()
|
||||||
|
|| existing_channel.name != channel_proto.name;
|
||||||
|
|
||||||
existing_channel.visibility = channel_proto.visibility();
|
existing_channel.visibility = channel_proto.visibility();
|
||||||
existing_channel.role = channel_proto.role();
|
existing_channel.role = channel_proto.role();
|
||||||
existing_channel.name = channel_proto.name;
|
existing_channel.name = channel_proto.name;
|
||||||
|
@ -141,6 +151,7 @@ impl<'a> ChannelPathsInsertGuard<'a> {
|
||||||
);
|
);
|
||||||
self.insert_root(channel_proto.id);
|
self.insert_root(channel_proto.id);
|
||||||
}
|
}
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_edge(&mut self, channel_id: ChannelId, parent_id: ChannelId) {
|
pub fn insert_edge(&mut self, channel_id: ChannelId, parent_id: ChannelId) {
|
||||||
|
|
|
@ -412,7 +412,7 @@ async fn test_channel_buffer_disconnect(
|
||||||
|
|
||||||
channel_buffer_a.update(cx_a, |buffer, _| {
|
channel_buffer_a.update(cx_a, |buffer, _| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer.channel().as_ref(),
|
buffer.channel(cx).unwrap().as_ref(),
|
||||||
&channel(channel_id, "the-channel", proto::ChannelRole::Admin)
|
&channel(channel_id, "the-channel", proto::ChannelRole::Admin)
|
||||||
);
|
);
|
||||||
assert!(!buffer.is_connected());
|
assert!(!buffer.is_connected());
|
||||||
|
@ -437,7 +437,7 @@ async fn test_channel_buffer_disconnect(
|
||||||
// Channel buffer observed the deletion
|
// Channel buffer observed the deletion
|
||||||
channel_buffer_b.update(cx_b, |buffer, _| {
|
channel_buffer_b.update(cx_b, |buffer, _| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer.channel().as_ref(),
|
buffer.channel(cx).unwrap().as_ref(),
|
||||||
&channel(channel_id, "the-channel", proto::ChannelRole::Member)
|
&channel(channel_id, "the-channel", proto::ChannelRole::Member)
|
||||||
);
|
);
|
||||||
assert!(!buffer.is_connected());
|
assert!(!buffer.is_connected());
|
||||||
|
|
|
@ -98,7 +98,8 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||||
|
|
||||||
30..=40 => {
|
30..=40 => {
|
||||||
if let Some(buffer) = channel_buffers.iter().choose(rng) {
|
if let Some(buffer) = channel_buffers.iter().choose(rng) {
|
||||||
let channel_name = buffer.read_with(cx, |b, _| b.channel().name.clone());
|
let channel_name =
|
||||||
|
buffer.read_with(cx, |b, _| b.channel(cx).unwrap().name.clone());
|
||||||
break ChannelBufferOperation::LeaveChannelNotes { channel_name };
|
break ChannelBufferOperation::LeaveChannelNotes { channel_name };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +107,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(buffer) = channel_buffers.iter().choose(rng) {
|
if let Some(buffer) = channel_buffers.iter().choose(rng) {
|
||||||
break buffer.read_with(cx, |b, _| {
|
break buffer.read_with(cx, |b, _| {
|
||||||
let channel_name = b.channel().name.clone();
|
let channel_name = b.channel(cx).unwrap().name.clone();
|
||||||
let edits = b
|
let edits = b
|
||||||
.buffer()
|
.buffer()
|
||||||
.read_with(cx, |buffer, _| buffer.get_random_edits(rng, 3));
|
.read_with(cx, |buffer, _| buffer.get_random_edits(rng, 3));
|
||||||
|
@ -153,7 +154,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||||
let buffer = cx.update(|cx| {
|
let buffer = cx.update(|cx| {
|
||||||
let mut left_buffer = Err(TestError::Inapplicable);
|
let mut left_buffer = Err(TestError::Inapplicable);
|
||||||
client.channel_buffers().retain(|buffer| {
|
client.channel_buffers().retain(|buffer| {
|
||||||
if buffer.read(cx).channel().name == channel_name {
|
if buffer.read(cx).channel(cx).unwrap().name == channel_name {
|
||||||
left_buffer = Ok(buffer.clone());
|
left_buffer = Ok(buffer.clone());
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
@ -179,7 +180,9 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||||
client
|
client
|
||||||
.channel_buffers()
|
.channel_buffers()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|buffer| buffer.read(cx).channel().name == channel_name)
|
.find(|buffer| {
|
||||||
|
buffer.read(cx).channel(cx).unwrap().name == channel_name
|
||||||
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
})
|
})
|
||||||
.ok_or_else(|| TestError::Inapplicable)?;
|
.ok_or_else(|| TestError::Inapplicable)?;
|
||||||
|
@ -250,7 +253,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||||
if let Some(channel_buffer) = client
|
if let Some(channel_buffer) = client
|
||||||
.channel_buffers()
|
.channel_buffers()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|b| b.read(cx).channel().id == channel_id.to_proto())
|
.find(|b| b.read(cx).channel_id == channel_id.to_proto())
|
||||||
{
|
{
|
||||||
let channel_buffer = channel_buffer.read(cx);
|
let channel_buffer = channel_buffer.read(cx);
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ postage.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_derive.workspace = true
|
serde_derive.workspace = true
|
||||||
time.workspace = true
|
time.workspace = true
|
||||||
|
smallvec.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
call = { path = "../call", features = ["test-support"] }
|
call = { path = "../call", features = ["test-support"] }
|
||||||
|
|
|
@ -15,13 +15,14 @@ use gpui::{
|
||||||
ViewContext, ViewHandle,
|
ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{FollowableItem, Item, ItemHandle},
|
item::{FollowableItem, Item, ItemEvent, ItemHandle},
|
||||||
register_followable_item,
|
register_followable_item,
|
||||||
searchable::SearchableItemHandle,
|
searchable::SearchableItemHandle,
|
||||||
ItemNavHistory, Pane, SaveIntent, ViewId, Workspace, WorkspaceId,
|
ItemNavHistory, Pane, SaveIntent, ViewId, Workspace, WorkspaceId,
|
||||||
|
@ -140,6 +141,12 @@ impl ChannelView {
|
||||||
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
||||||
channel_buffer.clone(),
|
channel_buffer.clone(),
|
||||||
)));
|
)));
|
||||||
|
editor.set_read_only(
|
||||||
|
!channel_buffer
|
||||||
|
.read(cx)
|
||||||
|
.channel(cx)
|
||||||
|
.is_some_and(|c| c.can_edit_notes()),
|
||||||
|
);
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone()));
|
let _editor_event_subscription = cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone()));
|
||||||
|
@ -157,8 +164,8 @@ impl ChannelView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn channel(&self, cx: &AppContext) -> Arc<Channel> {
|
pub fn channel(&self, cx: &AppContext) -> Option<Arc<Channel>> {
|
||||||
self.channel_buffer.read(cx).channel()
|
self.channel_buffer.read(cx).channel(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_channel_buffer_event(
|
fn handle_channel_buffer_event(
|
||||||
|
@ -172,6 +179,13 @@ impl ChannelView {
|
||||||
editor.set_read_only(true);
|
editor.set_read_only(true);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}),
|
}),
|
||||||
|
ChannelBufferEvent::ChannelChanged => {
|
||||||
|
self.editor.update(cx, |editor, cx| {
|
||||||
|
editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
|
||||||
|
cx.emit(editor::Event::TitleChanged);
|
||||||
|
cx.notify()
|
||||||
|
});
|
||||||
|
}
|
||||||
ChannelBufferEvent::BufferEdited => {
|
ChannelBufferEvent::BufferEdited => {
|
||||||
if cx.is_self_focused() || self.editor.is_focused(cx) {
|
if cx.is_self_focused() || self.editor.is_focused(cx) {
|
||||||
self.acknowledge_buffer_version(cx);
|
self.acknowledge_buffer_version(cx);
|
||||||
|
@ -179,7 +193,7 @@ impl ChannelView {
|
||||||
self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
let channel_buffer = self.channel_buffer.read(cx);
|
let channel_buffer = self.channel_buffer.read(cx);
|
||||||
store.notes_changed(
|
store.notes_changed(
|
||||||
channel_buffer.channel().id,
|
channel_buffer.channel_id,
|
||||||
channel_buffer.epoch(),
|
channel_buffer.epoch(),
|
||||||
&channel_buffer.buffer().read(cx).version(),
|
&channel_buffer.buffer().read(cx).version(),
|
||||||
cx,
|
cx,
|
||||||
|
@ -187,7 +201,7 @@ impl ChannelView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
ChannelBufferEvent::CollaboratorsChanged => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +209,7 @@ impl ChannelView {
|
||||||
self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
let channel_buffer = self.channel_buffer.read(cx);
|
let channel_buffer = self.channel_buffer.read(cx);
|
||||||
store.acknowledge_notes_version(
|
store.acknowledge_notes_version(
|
||||||
channel_buffer.channel().id,
|
channel_buffer.channel_id,
|
||||||
channel_buffer.epoch(),
|
channel_buffer.epoch(),
|
||||||
&channel_buffer.buffer().read(cx).version(),
|
&channel_buffer.buffer().read(cx).version(),
|
||||||
cx,
|
cx,
|
||||||
|
@ -250,11 +264,17 @@ impl Item for ChannelView {
|
||||||
style: &theme::Tab,
|
style: &theme::Tab,
|
||||||
cx: &gpui::AppContext,
|
cx: &gpui::AppContext,
|
||||||
) -> AnyElement<V> {
|
) -> AnyElement<V> {
|
||||||
let channel_name = &self.channel_buffer.read(cx).channel().name;
|
let label = if let Some(channel) = self.channel(cx) {
|
||||||
let label = if self.channel_buffer.read(cx).is_connected() {
|
match (
|
||||||
format!("#{}", channel_name)
|
channel.can_edit_notes(),
|
||||||
|
self.channel_buffer.read(cx).is_connected(),
|
||||||
|
) {
|
||||||
|
(true, true) => format!("#{}", channel.name),
|
||||||
|
(false, true) => format!("#{} (read-only)", channel.name),
|
||||||
|
(_, false) => format!("#{} (disconnected)", channel.name),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
format!("#{} (disconnected)", channel_name)
|
format!("channel notes (disconnected)")
|
||||||
};
|
};
|
||||||
Label::new(label, style.label.to_owned()).into_any()
|
Label::new(label, style.label.to_owned()).into_any()
|
||||||
}
|
}
|
||||||
|
@ -298,6 +318,10 @@ impl Item for ChannelView {
|
||||||
fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Vector2F> {
|
fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Vector2F> {
|
||||||
self.editor.read(cx).pixel_position_of_cursor(cx)
|
self.editor.read(cx).pixel_position_of_cursor(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_item_events(event: &Self::Event) -> SmallVec<[ItemEvent; 2]> {
|
||||||
|
editor::Editor::to_item_events(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FollowableItem for ChannelView {
|
impl FollowableItem for ChannelView {
|
||||||
|
@ -313,7 +337,7 @@ impl FollowableItem for ChannelView {
|
||||||
|
|
||||||
Some(proto::view::Variant::ChannelView(
|
Some(proto::view::Variant::ChannelView(
|
||||||
proto::view::ChannelView {
|
proto::view::ChannelView {
|
||||||
channel_id: channel_buffer.channel().id,
|
channel_id: channel_buffer.channel_id,
|
||||||
editor: if let Some(proto::view::Variant::Editor(proto)) =
|
editor: if let Some(proto::view::Variant::Editor(proto)) =
|
||||||
self.editor.read(cx).to_state_proto(cx)
|
self.editor.read(cx).to_state_proto(cx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -267,11 +267,15 @@ impl ChatPanel {
|
||||||
|
|
||||||
fn set_active_chat(&mut self, chat: ModelHandle<ChannelChat>, cx: &mut ViewContext<Self>) {
|
fn set_active_chat(&mut self, chat: ModelHandle<ChannelChat>, cx: &mut ViewContext<Self>) {
|
||||||
if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) {
|
if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) {
|
||||||
let id = chat.read(cx).channel().id;
|
let id = chat.read(cx).channel_id;
|
||||||
{
|
{
|
||||||
let chat = chat.read(cx);
|
let chat = chat.read(cx);
|
||||||
self.message_list.reset(chat.message_count());
|
self.message_list.reset(chat.message_count());
|
||||||
let placeholder = format!("Message #{}", chat.channel().name);
|
let placeholder = if let Some(channel) = chat.channel(cx) {
|
||||||
|
format!("Message #{}", channel.name)
|
||||||
|
} else {
|
||||||
|
"Message Channel".to_string()
|
||||||
|
};
|
||||||
self.input_editor.update(cx, move |editor, cx| {
|
self.input_editor.update(cx, move |editor, cx| {
|
||||||
editor.set_placeholder_text(placeholder, cx);
|
editor.set_placeholder_text(placeholder, cx);
|
||||||
});
|
});
|
||||||
|
@ -360,7 +364,7 @@ impl ChatPanel {
|
||||||
let is_admin = self
|
let is_admin = self
|
||||||
.channel_store
|
.channel_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.is_channel_admin(active_chat.channel().id);
|
.is_channel_admin(active_chat.channel_id);
|
||||||
let last_message = active_chat.message(ix.saturating_sub(1));
|
let last_message = active_chat.message(ix.saturating_sub(1));
|
||||||
let this_message = active_chat.message(ix);
|
let this_message = active_chat.message(ix);
|
||||||
let is_continuation = last_message.id != this_message.id
|
let is_continuation = last_message.id != this_message.id
|
||||||
|
@ -645,7 +649,7 @@ impl ChatPanel {
|
||||||
cx: &mut ViewContext<ChatPanel>,
|
cx: &mut ViewContext<ChatPanel>,
|
||||||
) -> Task<Result<()>> {
|
) -> Task<Result<()>> {
|
||||||
if let Some((chat, _)) = &self.active_chat {
|
if let Some((chat, _)) = &self.active_chat {
|
||||||
if chat.read(cx).channel().id == selected_channel_id {
|
if chat.read(cx).channel_id == selected_channel_id {
|
||||||
return Task::ready(Ok(()));
|
return Task::ready(Ok(()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -664,7 +668,7 @@ impl ChatPanel {
|
||||||
|
|
||||||
fn open_notes(&mut self, _: &OpenChannelNotes, cx: &mut ViewContext<Self>) {
|
fn open_notes(&mut self, _: &OpenChannelNotes, cx: &mut ViewContext<Self>) {
|
||||||
if let Some((chat, _)) = &self.active_chat {
|
if let Some((chat, _)) = &self.active_chat {
|
||||||
let channel_id = chat.read(cx).channel().id;
|
let channel_id = chat.read(cx).channel_id;
|
||||||
if let Some(workspace) = self.workspace.upgrade(cx) {
|
if let Some(workspace) = self.workspace.upgrade(cx) {
|
||||||
ChannelView::open(channel_id, workspace, cx).detach();
|
ChannelView::open(channel_id, workspace, cx).detach();
|
||||||
}
|
}
|
||||||
|
@ -673,7 +677,7 @@ impl ChatPanel {
|
||||||
|
|
||||||
fn join_call(&mut self, _: &JoinCall, cx: &mut ViewContext<Self>) {
|
fn join_call(&mut self, _: &JoinCall, cx: &mut ViewContext<Self>) {
|
||||||
if let Some((chat, _)) = &self.active_chat {
|
if let Some((chat, _)) = &self.active_chat {
|
||||||
let channel_id = chat.read(cx).channel().id;
|
let channel_id = chat.read(cx).channel_id;
|
||||||
ActiveCall::global(cx)
|
ActiveCall::global(cx)
|
||||||
.update(cx, |call, cx| call.join_channel(channel_id, cx))
|
.update(cx, |call, cx| call.join_channel(channel_id, cx))
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue