From 3422eb65e81394329385a44223638fed5ea23f2a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 7 Sep 2023 11:16:51 -0700 Subject: [PATCH 01/38] Restore channel chat model and panel view --- Cargo.lock | 1 + crates/channel/src/channel.rs | 9 +- crates/channel/src/channel_buffer.rs | 14 +- crates/channel/src/channel_chat.rs | 459 ++++++++++++++++++++++ crates/channel/src/channel_store.rs | 88 +++-- crates/channel/src/channel_store_tests.rs | 220 ++++++++++- crates/collab/src/tests/test_server.rs | 2 +- crates/collab_ui/Cargo.toml | 1 + crates/collab_ui/src/channel_view.rs | 11 +- crates/collab_ui/src/chat_panel.rs | 391 ++++++++++++++++++ crates/collab_ui/src/collab_ui.rs | 1 + crates/rpc/proto/zed.proto | 57 ++- crates/rpc/src/proto.rs | 12 + crates/theme/src/theme.rs | 12 + 14 files changed, 1227 insertions(+), 51 deletions(-) create mode 100644 crates/channel/src/channel_chat.rs create mode 100644 crates/collab_ui/src/chat_panel.rs diff --git a/Cargo.lock b/Cargo.lock index 121e9a28dd..6b25b47b75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1553,6 +1553,7 @@ dependencies = [ "settings", "theme", "theme_selector", + "time 0.3.27", "util", "vcs_menu", "workspace", diff --git a/crates/channel/src/channel.rs b/crates/channel/src/channel.rs index 15631b7dd3..b4acc0c25f 100644 --- a/crates/channel/src/channel.rs +++ b/crates/channel/src/channel.rs @@ -1,10 +1,13 @@ +mod channel_buffer; +mod channel_chat; mod channel_store; -pub mod channel_buffer; -use std::sync::Arc; +pub use channel_buffer::{ChannelBuffer, ChannelBufferEvent}; +pub use channel_chat::{ChannelChat, ChannelChatEvent, ChannelMessage, ChannelMessageId}; +pub use channel_store::{Channel, ChannelEvent, ChannelId, ChannelMembership, ChannelStore}; -pub use channel_store::*; use client::Client; +use std::sync::Arc; #[cfg(test)] mod channel_store_tests; diff --git a/crates/channel/src/channel_buffer.rs b/crates/channel/src/channel_buffer.rs index e11282cf79..06f9093fb5 100644 --- a/crates/channel/src/channel_buffer.rs +++ b/crates/channel/src/channel_buffer.rs @@ -23,13 +23,13 @@ pub struct ChannelBuffer { subscription: Option, } -pub enum Event { +pub enum ChannelBufferEvent { CollaboratorsChanged, Disconnected, } impl Entity for ChannelBuffer { - type Event = Event; + type Event = ChannelBufferEvent; fn release(&mut self, _: &mut AppContext) { if self.connected { @@ -101,7 +101,7 @@ impl ChannelBuffer { } } self.collaborators = collaborators; - cx.emit(Event::CollaboratorsChanged); + cx.emit(ChannelBufferEvent::CollaboratorsChanged); cx.notify(); } @@ -141,7 +141,7 @@ impl ChannelBuffer { this.update(&mut cx, |this, cx| { this.collaborators.push(collaborator); - cx.emit(Event::CollaboratorsChanged); + cx.emit(ChannelBufferEvent::CollaboratorsChanged); cx.notify(); }); @@ -165,7 +165,7 @@ impl ChannelBuffer { true } }); - cx.emit(Event::CollaboratorsChanged); + cx.emit(ChannelBufferEvent::CollaboratorsChanged); cx.notify(); }); @@ -185,7 +185,7 @@ impl ChannelBuffer { break; } } - cx.emit(Event::CollaboratorsChanged); + cx.emit(ChannelBufferEvent::CollaboratorsChanged); cx.notify(); }); @@ -230,7 +230,7 @@ impl ChannelBuffer { if self.connected { self.connected = false; self.subscription.take(); - cx.emit(Event::Disconnected); + cx.emit(ChannelBufferEvent::Disconnected); cx.notify() } } diff --git a/crates/channel/src/channel_chat.rs b/crates/channel/src/channel_chat.rs new file mode 100644 index 0000000000..ebe491e5b8 --- /dev/null +++ b/crates/channel/src/channel_chat.rs @@ -0,0 +1,459 @@ +use crate::Channel; +use anyhow::{anyhow, Result}; +use client::{ + proto, + user::{User, UserStore}, + Client, Subscription, TypedEnvelope, +}; +use futures::lock::Mutex; +use gpui::{AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Task}; +use rand::prelude::*; +use std::{collections::HashSet, mem, ops::Range, sync::Arc}; +use sum_tree::{Bias, SumTree}; +use time::OffsetDateTime; +use util::{post_inc, ResultExt as _, TryFutureExt}; + +pub struct ChannelChat { + channel: Arc, + messages: SumTree, + loaded_all_messages: bool, + next_pending_message_id: usize, + user_store: ModelHandle, + rpc: Arc, + outgoing_messages_lock: Arc>, + rng: StdRng, + _subscription: Subscription, +} + +#[derive(Clone, Debug)] +pub struct ChannelMessage { + pub id: ChannelMessageId, + pub body: String, + pub timestamp: OffsetDateTime, + pub sender: Arc, + pub nonce: u128, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum ChannelMessageId { + Saved(u64), + Pending(usize), +} + +#[derive(Clone, Debug, Default)] +pub struct ChannelMessageSummary { + max_id: ChannelMessageId, + count: usize, +} + +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] +struct Count(usize); + +#[derive(Clone, Debug, PartialEq)] +pub enum ChannelChatEvent { + MessagesUpdated { + old_range: Range, + new_count: usize, + }, +} + +impl Entity for ChannelChat { + type Event = ChannelChatEvent; + + fn release(&mut self, _: &mut AppContext) { + self.rpc + .send(proto::LeaveChannelChat { + channel_id: self.channel.id, + }) + .log_err(); + } +} + +impl ChannelChat { + pub fn init(rpc: &Arc) { + rpc.add_model_message_handler(Self::handle_message_sent); + } + + pub async fn new( + channel: Arc, + user_store: ModelHandle, + client: Arc, + mut cx: AsyncAppContext, + ) -> Result> { + let channel_id = channel.id; + let subscription = client.subscribe_to_entity(channel_id).unwrap(); + + let response = client + .request(proto::JoinChannelChat { channel_id }) + .await?; + let messages = messages_from_proto(response.messages, &user_store, &mut cx).await?; + let loaded_all_messages = response.done; + + Ok(cx.add_model(|cx| { + let mut this = Self { + channel, + user_store, + rpc: client, + outgoing_messages_lock: Default::default(), + messages: Default::default(), + loaded_all_messages, + next_pending_message_id: 0, + rng: StdRng::from_entropy(), + _subscription: subscription.set_model(&cx.handle(), &mut cx.to_async()), + }; + this.insert_messages(messages, cx); + this + })) + } + + pub fn name(&self) -> &str { + &self.channel.name + } + + pub fn send_message( + &mut self, + body: String, + cx: &mut ModelContext, + ) -> Result>> { + if body.is_empty() { + Err(anyhow!("message body can't be empty"))?; + } + + let current_user = self + .user_store + .read(cx) + .current_user() + .ok_or_else(|| anyhow!("current_user is not present"))?; + + let channel_id = self.channel.id; + let pending_id = ChannelMessageId::Pending(post_inc(&mut self.next_pending_message_id)); + let nonce = self.rng.gen(); + self.insert_messages( + SumTree::from_item( + ChannelMessage { + id: pending_id, + body: body.clone(), + sender: current_user, + timestamp: OffsetDateTime::now_utc(), + nonce, + }, + &(), + ), + cx, + ); + let user_store = self.user_store.clone(); + let rpc = self.rpc.clone(); + let outgoing_messages_lock = self.outgoing_messages_lock.clone(); + Ok(cx.spawn(|this, mut cx| async move { + let outgoing_message_guard = outgoing_messages_lock.lock().await; + let request = rpc.request(proto::SendChannelMessage { + channel_id, + body, + nonce: Some(nonce.into()), + }); + let response = request.await?; + drop(outgoing_message_guard); + let message = ChannelMessage::from_proto( + response.message.ok_or_else(|| anyhow!("invalid message"))?, + &user_store, + &mut cx, + ) + .await?; + this.update(&mut cx, |this, cx| { + this.insert_messages(SumTree::from_item(message, &()), cx); + Ok(()) + }) + })) + } + + pub fn load_more_messages(&mut self, cx: &mut ModelContext) -> bool { + if !self.loaded_all_messages { + let rpc = self.rpc.clone(); + let user_store = self.user_store.clone(); + let channel_id = self.channel.id; + if let Some(before_message_id) = + self.messages.first().and_then(|message| match message.id { + ChannelMessageId::Saved(id) => Some(id), + ChannelMessageId::Pending(_) => None, + }) + { + cx.spawn(|this, mut cx| { + async move { + let response = rpc + .request(proto::GetChannelMessages { + channel_id, + before_message_id, + }) + .await?; + let loaded_all_messages = response.done; + let messages = + messages_from_proto(response.messages, &user_store, &mut cx).await?; + this.update(&mut cx, |this, cx| { + this.loaded_all_messages = loaded_all_messages; + this.insert_messages(messages, cx); + }); + anyhow::Ok(()) + } + .log_err() + }) + .detach(); + return true; + } + } + false + } + + pub fn rejoin(&mut self, cx: &mut ModelContext) { + let user_store = self.user_store.clone(); + let rpc = self.rpc.clone(); + let channel_id = self.channel.id; + cx.spawn(|this, mut cx| { + async move { + let response = rpc.request(proto::JoinChannelChat { channel_id }).await?; + let messages = messages_from_proto(response.messages, &user_store, &mut cx).await?; + let loaded_all_messages = response.done; + + let pending_messages = this.update(&mut cx, |this, cx| { + if let Some((first_new_message, last_old_message)) = + messages.first().zip(this.messages.last()) + { + if first_new_message.id > last_old_message.id { + let old_messages = mem::take(&mut this.messages); + cx.emit(ChannelChatEvent::MessagesUpdated { + old_range: 0..old_messages.summary().count, + new_count: 0, + }); + this.loaded_all_messages = loaded_all_messages; + } + } + + this.insert_messages(messages, cx); + if loaded_all_messages { + this.loaded_all_messages = loaded_all_messages; + } + + this.pending_messages().cloned().collect::>() + }); + + for pending_message in pending_messages { + let request = rpc.request(proto::SendChannelMessage { + channel_id, + body: pending_message.body, + nonce: Some(pending_message.nonce.into()), + }); + let response = request.await?; + let message = ChannelMessage::from_proto( + response.message.ok_or_else(|| anyhow!("invalid message"))?, + &user_store, + &mut cx, + ) + .await?; + this.update(&mut cx, |this, cx| { + this.insert_messages(SumTree::from_item(message, &()), cx); + }); + } + + anyhow::Ok(()) + } + .log_err() + }) + .detach(); + } + + pub fn message_count(&self) -> usize { + self.messages.summary().count + } + + pub fn messages(&self) -> &SumTree { + &self.messages + } + + pub fn message(&self, ix: usize) -> &ChannelMessage { + let mut cursor = self.messages.cursor::(); + cursor.seek(&Count(ix), Bias::Right, &()); + cursor.item().unwrap() + } + + pub fn messages_in_range(&self, range: Range) -> impl Iterator { + let mut cursor = self.messages.cursor::(); + cursor.seek(&Count(range.start), Bias::Right, &()); + cursor.take(range.len()) + } + + pub fn pending_messages(&self) -> impl Iterator { + let mut cursor = self.messages.cursor::(); + cursor.seek(&ChannelMessageId::Pending(0), Bias::Left, &()); + cursor + } + + async fn handle_message_sent( + this: ModelHandle, + message: TypedEnvelope, + _: Arc, + mut cx: AsyncAppContext, + ) -> Result<()> { + let user_store = this.read_with(&cx, |this, _| this.user_store.clone()); + let message = message + .payload + .message + .ok_or_else(|| anyhow!("empty message"))?; + + let message = ChannelMessage::from_proto(message, &user_store, &mut cx).await?; + this.update(&mut cx, |this, cx| { + this.insert_messages(SumTree::from_item(message, &()), cx) + }); + + Ok(()) + } + + fn insert_messages(&mut self, messages: SumTree, cx: &mut ModelContext) { + if let Some((first_message, last_message)) = messages.first().zip(messages.last()) { + let nonces = messages + .cursor::<()>() + .map(|m| m.nonce) + .collect::>(); + + let mut old_cursor = self.messages.cursor::<(ChannelMessageId, Count)>(); + let mut new_messages = old_cursor.slice(&first_message.id, Bias::Left, &()); + let start_ix = old_cursor.start().1 .0; + let removed_messages = old_cursor.slice(&last_message.id, Bias::Right, &()); + let removed_count = removed_messages.summary().count; + let new_count = messages.summary().count; + let end_ix = start_ix + removed_count; + + new_messages.append(messages, &()); + + let mut ranges = Vec::>::new(); + if new_messages.last().unwrap().is_pending() { + new_messages.append(old_cursor.suffix(&()), &()); + } else { + new_messages.append( + old_cursor.slice(&ChannelMessageId::Pending(0), Bias::Left, &()), + &(), + ); + + while let Some(message) = old_cursor.item() { + let message_ix = old_cursor.start().1 .0; + if nonces.contains(&message.nonce) { + if ranges.last().map_or(false, |r| r.end == message_ix) { + ranges.last_mut().unwrap().end += 1; + } else { + ranges.push(message_ix..message_ix + 1); + } + } else { + new_messages.push(message.clone(), &()); + } + old_cursor.next(&()); + } + } + + drop(old_cursor); + self.messages = new_messages; + + for range in ranges.into_iter().rev() { + cx.emit(ChannelChatEvent::MessagesUpdated { + old_range: range, + new_count: 0, + }); + } + cx.emit(ChannelChatEvent::MessagesUpdated { + old_range: start_ix..end_ix, + new_count, + }); + cx.notify(); + } + } +} + +async fn messages_from_proto( + proto_messages: Vec, + user_store: &ModelHandle, + cx: &mut AsyncAppContext, +) -> Result> { + let unique_user_ids = proto_messages + .iter() + .map(|m| m.sender_id) + .collect::>() + .into_iter() + .collect(); + user_store + .update(cx, |user_store, cx| { + user_store.get_users(unique_user_ids, cx) + }) + .await?; + + let mut messages = Vec::with_capacity(proto_messages.len()); + for message in proto_messages { + messages.push(ChannelMessage::from_proto(message, user_store, cx).await?); + } + let mut result = SumTree::new(); + result.extend(messages, &()); + Ok(result) +} + +impl ChannelMessage { + pub async fn from_proto( + message: proto::ChannelMessage, + user_store: &ModelHandle, + cx: &mut AsyncAppContext, + ) -> Result { + let sender = user_store + .update(cx, |user_store, cx| { + user_store.get_user(message.sender_id, cx) + }) + .await?; + Ok(ChannelMessage { + id: ChannelMessageId::Saved(message.id), + body: message.body, + timestamp: OffsetDateTime::from_unix_timestamp(message.timestamp as i64)?, + sender, + nonce: message + .nonce + .ok_or_else(|| anyhow!("nonce is required"))? + .into(), + }) + } + + pub fn is_pending(&self) -> bool { + matches!(self.id, ChannelMessageId::Pending(_)) + } +} + +impl sum_tree::Item for ChannelMessage { + type Summary = ChannelMessageSummary; + + fn summary(&self) -> Self::Summary { + ChannelMessageSummary { + max_id: self.id, + count: 1, + } + } +} + +impl Default for ChannelMessageId { + fn default() -> Self { + Self::Saved(0) + } +} + +impl sum_tree::Summary for ChannelMessageSummary { + type Context = (); + + fn add_summary(&mut self, summary: &Self, _: &()) { + self.max_id = summary.max_id; + self.count += summary.count; + } +} + +impl<'a> sum_tree::Dimension<'a, ChannelMessageSummary> for ChannelMessageId { + fn add_summary(&mut self, summary: &'a ChannelMessageSummary, _: &()) { + debug_assert!(summary.max_id > *self); + *self = summary.max_id; + } +} + +impl<'a> sum_tree::Dimension<'a, ChannelMessageSummary> for Count { + fn add_summary(&mut self, summary: &'a ChannelMessageSummary, _: &()) { + self.0 += summary.count; + } +} diff --git a/crates/channel/src/channel_store.rs b/crates/channel/src/channel_store.rs index a4c8da6df4..6096692ccb 100644 --- a/crates/channel/src/channel_store.rs +++ b/crates/channel/src/channel_store.rs @@ -1,4 +1,4 @@ -use crate::channel_buffer::ChannelBuffer; +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}; @@ -20,7 +20,8 @@ pub struct ChannelStore { channels_with_admin_privileges: HashSet, outgoing_invites: HashSet<(ChannelId, UserId)>, update_channels_tx: mpsc::UnboundedSender, - opened_buffers: HashMap, + opened_buffers: HashMap>, + opened_chats: HashMap>, client: Arc, user_store: ModelHandle, _rpc_subscription: Subscription, @@ -50,15 +51,9 @@ impl Entity for ChannelStore { type Event = ChannelEvent; } -pub enum ChannelMemberStatus { - Invited, - Member, - NotMember, -} - -enum OpenedChannelBuffer { - Open(WeakModelHandle), - Loading(Shared, Arc>>>), +enum OpenedModelHandle { + Open(WeakModelHandle), + Loading(Shared, Arc>>>), } impl ChannelStore { @@ -94,6 +89,7 @@ impl ChannelStore { channels_with_admin_privileges: Default::default(), outgoing_invites: Default::default(), opened_buffers: Default::default(), + opened_chats: Default::default(), update_channels_tx, client, user_store, @@ -154,7 +150,7 @@ impl ChannelStore { pub fn has_open_channel_buffer(&self, channel_id: ChannelId, cx: &AppContext) -> bool { if let Some(buffer) = self.opened_buffers.get(&channel_id) { - if let OpenedChannelBuffer::Open(buffer) = buffer { + if let OpenedModelHandle::Open(buffer) = buffer { return buffer.upgrade(cx).is_some(); } } @@ -166,24 +162,58 @@ impl ChannelStore { channel_id: ChannelId, cx: &mut ModelContext, ) -> Task>> { - // Make sure that a given channel buffer is only opened once per + let client = self.client.clone(); + self.open_channel_resource( + channel_id, + |this| &mut this.opened_buffers, + |channel, cx| ChannelBuffer::new(channel, client, cx), + cx, + ) + } + + pub fn open_channel_chat( + &mut self, + channel_id: ChannelId, + cx: &mut ModelContext, + ) -> Task>> { + let client = self.client.clone(); + let user_store = self.user_store.clone(); + self.open_channel_resource( + channel_id, + |this| &mut this.opened_chats, + |channel, cx| ChannelChat::new(channel, user_store, client, cx), + cx, + ) + } + + fn open_channel_resource( + &mut self, + channel_id: ChannelId, + map: fn(&mut Self) -> &mut HashMap>, + load: F, + cx: &mut ModelContext, + ) -> Task>> + where + F: 'static + FnOnce(Arc, AsyncAppContext) -> Fut, + Fut: Future>>, + { + // Make sure that a given channel resource is only opened once per // app instance, even if this method is called multiple times // with the same channel id while the first task is still running. let task = loop { - match self.opened_buffers.entry(channel_id) { + match map(self).entry(channel_id) { hash_map::Entry::Occupied(e) => match e.get() { - OpenedChannelBuffer::Open(buffer) => { + OpenedModelHandle::Open(buffer) => { if let Some(buffer) = buffer.upgrade(cx) { break Task::ready(Ok(buffer)).shared(); } else { - self.opened_buffers.remove(&channel_id); + map(self).remove(&channel_id); continue; } } - OpenedChannelBuffer::Loading(task) => break task.clone(), + OpenedModelHandle::Loading(task) => break task.clone(), }, hash_map::Entry::Vacant(e) => { - let client = self.client.clone(); let task = cx .spawn(|this, cx| async move { let channel = this.read_with(&cx, |this, _| { @@ -192,12 +222,10 @@ impl ChannelStore { }) })?; - ChannelBuffer::new(channel, client, cx) - .await - .map_err(Arc::new) + load(channel, cx).await.map_err(Arc::new) }) .shared(); - e.insert(OpenedChannelBuffer::Loading(task.clone())); + e.insert(OpenedModelHandle::Loading(task.clone())); cx.spawn({ let task = task.clone(); |this, mut cx| async move { @@ -208,14 +236,14 @@ impl ChannelStore { this.opened_buffers.remove(&channel_id); }) .detach(); - this.opened_buffers.insert( + map(this).insert( channel_id, - OpenedChannelBuffer::Open(buffer.downgrade()), + OpenedModelHandle::Open(buffer.downgrade()), ); } Err(error) => { log::error!("failed to open channel buffer {error:?}"); - this.opened_buffers.remove(&channel_id); + map(this).remove(&channel_id); } }); } @@ -496,7 +524,7 @@ impl ChannelStore { let mut buffer_versions = Vec::new(); for buffer in self.opened_buffers.values() { - if let OpenedChannelBuffer::Open(buffer) = buffer { + if let OpenedModelHandle::Open(buffer) = buffer { if let Some(buffer) = buffer.upgrade(cx) { let channel_buffer = buffer.read(cx); let buffer = channel_buffer.buffer().read(cx); @@ -522,7 +550,7 @@ impl ChannelStore { this.update(&mut cx, |this, cx| { this.opened_buffers.retain(|_, buffer| match buffer { - OpenedChannelBuffer::Open(channel_buffer) => { + OpenedModelHandle::Open(channel_buffer) => { let Some(channel_buffer) = channel_buffer.upgrade(cx) else { return false; }; @@ -583,7 +611,7 @@ impl ChannelStore { false }) } - OpenedChannelBuffer::Loading(_) => true, + OpenedModelHandle::Loading(_) => true, }); }); anyhow::Ok(()) @@ -605,7 +633,7 @@ impl ChannelStore { if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| { for (_, buffer) in this.opened_buffers.drain() { - if let OpenedChannelBuffer::Open(buffer) = buffer { + if let OpenedModelHandle::Open(buffer) = buffer { if let Some(buffer) = buffer.upgrade(cx) { buffer.update(cx, |buffer, cx| buffer.disconnect(cx)); } @@ -654,7 +682,7 @@ impl ChannelStore { for channel_id in &payload.remove_channels { let channel_id = *channel_id; - if let Some(OpenedChannelBuffer::Open(buffer)) = + if let Some(OpenedModelHandle::Open(buffer)) = self.opened_buffers.remove(&channel_id) { if let Some(buffer) = buffer.upgrade(cx) { diff --git a/crates/channel/src/channel_store_tests.rs b/crates/channel/src/channel_store_tests.rs index 18894b1f47..3ae899ecde 100644 --- a/crates/channel/src/channel_store_tests.rs +++ b/crates/channel/src/channel_store_tests.rs @@ -1,6 +1,8 @@ +use crate::channel_chat::ChannelChatEvent; + use super::*; -use client::{Client, UserStore}; -use gpui::{AppContext, ModelHandle}; +use client::{test::FakeServer, Client, UserStore}; +use gpui::{AppContext, ModelHandle, TestAppContext}; use rpc::proto; use util::http::FakeHttpClient; @@ -137,6 +139,220 @@ fn test_dangling_channel_paths(cx: &mut AppContext) { assert_channels(&channel_store, &[(0, "a".to_string(), true)], cx); } +#[gpui::test] +async fn test_channel_messages(cx: &mut TestAppContext) { + cx.foreground().forbid_parking(); + + let user_id = 5; + let http_client = FakeHttpClient::with_404_response(); + let client = cx.update(|cx| Client::new(http_client.clone(), cx)); + let server = FakeServer::for_client(user_id, &client, cx).await; + let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx)); + crate::init(&client); + + let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx)); + + let channel_id = 5; + + // Get the available channels. + server.send(proto::UpdateChannels { + channels: vec![proto::Channel { + id: channel_id, + name: "the-channel".to_string(), + parent_id: None, + }], + ..Default::default() + }); + channel_store.next_notification(cx).await; + cx.read(|cx| { + assert_channels(&channel_store, &[(0, "the-channel".to_string(), false)], cx); + }); + + let get_users = server.receive::().await.unwrap(); + assert_eq!(get_users.payload.user_ids, vec![5]); + server + .respond( + get_users.receipt(), + proto::UsersResponse { + users: vec![proto::User { + id: 5, + github_login: "nathansobo".into(), + avatar_url: "http://avatar.com/nathansobo".into(), + }], + }, + ) + .await; + + // Join a channel and populate its existing messages. + let channel = channel_store + .update(cx, |store, cx| { + let channel_id = store.channels().next().unwrap().1.id; + store.open_channel_chat(channel_id, cx) + }) + .await + .unwrap(); + channel.read_with(cx, |channel, _| assert!(channel.messages().is_empty())); + let join_channel = server.receive::().await.unwrap(); + server + .respond( + join_channel.receipt(), + proto::JoinChannelChatResponse { + messages: vec![ + proto::ChannelMessage { + id: 10, + body: "a".into(), + timestamp: 1000, + sender_id: 5, + nonce: Some(1.into()), + }, + proto::ChannelMessage { + id: 11, + body: "b".into(), + timestamp: 1001, + sender_id: 6, + nonce: Some(2.into()), + }, + ], + done: false, + }, + ) + .await; + + // Client requests all users for the received messages + let mut get_users = server.receive::().await.unwrap(); + get_users.payload.user_ids.sort(); + assert_eq!(get_users.payload.user_ids, vec![6]); + server + .respond( + get_users.receipt(), + proto::UsersResponse { + users: vec![proto::User { + id: 6, + github_login: "maxbrunsfeld".into(), + avatar_url: "http://avatar.com/maxbrunsfeld".into(), + }], + }, + ) + .await; + + assert_eq!( + channel.next_event(cx).await, + ChannelChatEvent::MessagesUpdated { + old_range: 0..0, + new_count: 2, + } + ); + channel.read_with(cx, |channel, _| { + assert_eq!( + channel + .messages_in_range(0..2) + .map(|message| (message.sender.github_login.clone(), message.body.clone())) + .collect::>(), + &[ + ("nathansobo".into(), "a".into()), + ("maxbrunsfeld".into(), "b".into()) + ] + ); + }); + + // Receive a new message. + server.send(proto::ChannelMessageSent { + channel_id, + message: Some(proto::ChannelMessage { + id: 12, + body: "c".into(), + timestamp: 1002, + sender_id: 7, + nonce: Some(3.into()), + }), + }); + + // Client requests user for message since they haven't seen them yet + let get_users = server.receive::().await.unwrap(); + assert_eq!(get_users.payload.user_ids, vec![7]); + server + .respond( + get_users.receipt(), + proto::UsersResponse { + users: vec![proto::User { + id: 7, + github_login: "as-cii".into(), + avatar_url: "http://avatar.com/as-cii".into(), + }], + }, + ) + .await; + + assert_eq!( + channel.next_event(cx).await, + ChannelChatEvent::MessagesUpdated { + old_range: 2..2, + new_count: 1, + } + ); + channel.read_with(cx, |channel, _| { + assert_eq!( + channel + .messages_in_range(2..3) + .map(|message| (message.sender.github_login.clone(), message.body.clone())) + .collect::>(), + &[("as-cii".into(), "c".into())] + ) + }); + + // Scroll up to view older messages. + channel.update(cx, |channel, cx| { + assert!(channel.load_more_messages(cx)); + }); + let get_messages = server.receive::().await.unwrap(); + assert_eq!(get_messages.payload.channel_id, 5); + assert_eq!(get_messages.payload.before_message_id, 10); + server + .respond( + get_messages.receipt(), + proto::GetChannelMessagesResponse { + done: true, + messages: vec![ + proto::ChannelMessage { + id: 8, + body: "y".into(), + timestamp: 998, + sender_id: 5, + nonce: Some(4.into()), + }, + proto::ChannelMessage { + id: 9, + body: "z".into(), + timestamp: 999, + sender_id: 6, + nonce: Some(5.into()), + }, + ], + }, + ) + .await; + + assert_eq!( + channel.next_event(cx).await, + ChannelChatEvent::MessagesUpdated { + old_range: 0..0, + new_count: 2, + } + ); + channel.read_with(cx, |channel, _| { + assert_eq!( + channel + .messages_in_range(0..2) + .map(|message| (message.sender.github_login.clone(), message.body.clone())) + .collect::>(), + &[ + ("nathansobo".into(), "y".into()), + ("maxbrunsfeld".into(), "z".into()) + ] + ); + }); +} + fn update_channels( channel_store: &ModelHandle, message: proto::UpdateChannels, diff --git a/crates/collab/src/tests/test_server.rs b/crates/collab/src/tests/test_server.rs index eef1dde967..a7dbd97239 100644 --- a/crates/collab/src/tests/test_server.rs +++ b/crates/collab/src/tests/test_server.rs @@ -6,7 +6,7 @@ use crate::{ }; use anyhow::anyhow; use call::ActiveCall; -use channel::{channel_buffer::ChannelBuffer, ChannelStore}; +use channel::{ChannelBuffer, ChannelStore}; use client::{ self, proto::PeerId, Client, Connection, Credentials, EstablishConnectionError, UserStore, }; diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index da32308558..0a52b9a19f 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -55,6 +55,7 @@ schemars.workspace = true postage.workspace = true serde.workspace = true serde_derive.workspace = true +time.workspace = true [dev-dependencies] call = { path = "../call", features = ["test-support"] } diff --git a/crates/collab_ui/src/channel_view.rs b/crates/collab_ui/src/channel_view.rs index 5086cc8b37..76b79eaf39 100644 --- a/crates/collab_ui/src/channel_view.rs +++ b/crates/collab_ui/src/channel_view.rs @@ -1,8 +1,5 @@ use anyhow::{anyhow, Result}; -use channel::{ - channel_buffer::{self, ChannelBuffer}, - ChannelId, -}; +use channel::{ChannelBuffer, ChannelBufferEvent, ChannelId}; use client::proto; use clock::ReplicaId; use collections::HashMap; @@ -118,14 +115,14 @@ impl ChannelView { fn handle_channel_buffer_event( &mut self, _: ModelHandle, - event: &channel_buffer::Event, + event: &ChannelBufferEvent, cx: &mut ViewContext, ) { match event { - channel_buffer::Event::CollaboratorsChanged => { + ChannelBufferEvent::CollaboratorsChanged => { self.refresh_replica_id_map(cx); } - channel_buffer::Event::Disconnected => self.editor.update(cx, |editor, cx| { + ChannelBufferEvent::Disconnected => self.editor.update(cx, |editor, cx| { editor.set_read_only(true); cx.notify(); }), diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs new file mode 100644 index 0000000000..0105a9d27b --- /dev/null +++ b/crates/collab_ui/src/chat_panel.rs @@ -0,0 +1,391 @@ +use channel::{ChannelChat, ChannelChatEvent, ChannelMessage, ChannelStore}; +use client::Client; +use editor::Editor; +use gpui::{ + actions, + elements::*, + platform::{CursorStyle, MouseButton}, + views::{ItemType, Select, SelectStyle}, + AnyViewHandle, AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle, +}; +use language::language_settings::SoftWrap; +use menu::Confirm; +use std::sync::Arc; +use theme::Theme; +use time::{OffsetDateTime, UtcOffset}; +use util::{ResultExt, TryFutureExt}; + +const MESSAGE_LOADING_THRESHOLD: usize = 50; + +pub struct ChatPanel { + client: Arc, + channel_store: ModelHandle, + active_channel: Option<(ModelHandle, Subscription)>, + message_list: ListState, + input_editor: ViewHandle, + channel_select: ViewHandle { + let channel = &channel_store.read(cx).channel_at_index(ix).unwrap().1; + let theme = match (item_type, is_hovered) { + (ItemType::Header, _) => &theme.header, + (ItemType::Selected, false) => &theme.active_item, + (ItemType::Selected, true) => &theme.hovered_active_item, + (ItemType::Unselected, false) => &theme.item, + (ItemType::Unselected, true) => &theme.hovered_item, + }; + Flex::row() + .with_child( + Label::new("#".to_string(), theme.hash.text.clone()) + .contained() + .with_style(theme.hash.container), + ) + .with_child(Label::new(channel.name.clone(), theme.name.clone())) + .contained() + .with_style(theme.container) + .into_any() + } + + fn render_sign_in_prompt( + &self, + theme: &Arc, + cx: &mut ViewContext, + ) -> AnyElement { + enum SignInPromptLabel {} + + MouseEventHandler::new::(0, cx, |mouse_state, _| { + Label::new( + "Sign in to use chat".to_string(), + theme + .chat_panel + .sign_in_prompt + .style_for(mouse_state) + .clone(), + ) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, this, cx| { + let client = this.client.clone(); + cx.spawn(|this, mut cx| async move { + if client + .authenticate_and_connect(true, &cx) + .log_err() + .await + .is_some() + { + this.update(&mut cx, |this, cx| { + if cx.handle().is_focused(cx) { + cx.focus(&this.input_editor); + } + }) + .ok(); + } + }) + .detach(); + }) + .aligned() + .into_any() + } + + fn send(&mut self, _: &Confirm, cx: &mut ViewContext) { + if let Some((channel, _)) = self.active_channel.as_ref() { + let body = self.input_editor.update(cx, |editor, cx| { + let body = editor.text(cx); + editor.clear(cx); + body + }); + + if let Some(task) = channel + .update(cx, |channel, cx| channel.send_message(body, cx)) + .log_err() + { + task.detach(); + } + } + } + + fn load_more_messages(&mut self, _: &LoadMoreMessages, cx: &mut ViewContext) { + if let Some((channel, _)) = self.active_channel.as_ref() { + channel.update(cx, |channel, cx| { + channel.load_more_messages(cx); + }) + } + } +} + +impl Entity for ChatPanel { + type Event = Event; +} + +impl View for ChatPanel { + fn ui_name() -> &'static str { + "ChatPanel" + } + + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { + let theme = theme::current(cx); + let element = if self.client.user_id().is_some() { + self.render_channel(cx) + } else { + self.render_sign_in_prompt(&theme, cx) + }; + element + .contained() + .with_style(theme.chat_panel.container) + .constrained() + .with_min_width(150.) + .into_any() + } + + fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + if matches!( + *self.client.status().borrow(), + client::Status::Connected { .. } + ) { + cx.focus(&self.input_editor); + } + } +} + +fn format_timestamp( + mut timestamp: OffsetDateTime, + mut now: OffsetDateTime, + local_timezone: UtcOffset, +) -> String { + timestamp = timestamp.to_offset(local_timezone); + now = now.to_offset(local_timezone); + + let today = now.date(); + let date = timestamp.date(); + let mut hour = timestamp.hour(); + let mut part = "am"; + if hour > 12 { + hour -= 12; + part = "pm"; + } + if date == today { + format!("{:02}:{:02}{}", hour, timestamp.minute(), part) + } else if date.next_day() == Some(today) { + format!("yesterday at {:02}:{:02}{}", hour, timestamp.minute(), part) + } else { + format!("{:02}/{}/{}", date.month() as u32, date.day(), date.year()) + } +} diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs index ee34f600fa..b40ecc6992 100644 --- a/crates/collab_ui/src/collab_ui.rs +++ b/crates/collab_ui/src/collab_ui.rs @@ -1,4 +1,5 @@ pub mod channel_view; +pub mod chat_panel; pub mod collab_panel; mod collab_titlebar_item; mod contact_notification; diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 2e96d79f5e..eb26e81b99 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -155,7 +155,16 @@ message Envelope { RemoveChannelBufferCollaborator remove_channel_buffer_collaborator = 136; UpdateChannelBufferCollaborator update_channel_buffer_collaborator = 139; RejoinChannelBuffers rejoin_channel_buffers = 140; - RejoinChannelBuffersResponse rejoin_channel_buffers_response = 141; // Current max + RejoinChannelBuffersResponse rejoin_channel_buffers_response = 141; + + JoinChannelChat join_channel_chat = 142; + JoinChannelChatResponse join_channel_chat_response = 143; + LeaveChannelChat leave_channel_chat = 144; + SendChannelMessage send_channel_message = 145; + SendChannelMessageResponse send_channel_message_response = 146; + ChannelMessageSent channel_message_sent = 147; + GetChannelMessages get_channel_messages = 148; + GetChannelMessagesResponse get_channel_messages_response = 149; // Current max } } @@ -1021,10 +1030,56 @@ message RenameChannel { string name = 2; } +message JoinChannelChat { + uint64 channel_id = 1; +} + +message JoinChannelChatResponse { + repeated ChannelMessage messages = 1; + bool done = 2; +} + +message LeaveChannelChat { + uint64 channel_id = 1; +} + +message SendChannelMessage { + uint64 channel_id = 1; + string body = 2; + Nonce nonce = 3; +} + +message SendChannelMessageResponse { + ChannelMessage message = 1; +} + +message ChannelMessageSent { + uint64 channel_id = 1; + ChannelMessage message = 2; +} + +message GetChannelMessages { + uint64 channel_id = 1; + uint64 before_message_id = 2; +} + +message GetChannelMessagesResponse { + repeated ChannelMessage messages = 1; + bool done = 2; +} + message JoinChannelBuffer { uint64 channel_id = 1; } +message ChannelMessage { + uint64 id = 1; + string body = 2; + uint64 timestamp = 3; + uint64 sender_id = 4; + Nonce nonce = 5; +} + message RejoinChannelBuffers { repeated ChannelBufferVersion buffers = 1; } diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index f643a8c168..7b98f50e75 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -147,6 +147,7 @@ messages!( (CreateBufferForPeer, Foreground), (CreateChannel, Foreground), (ChannelResponse, Foreground), + (ChannelMessageSent, Foreground), (CreateProjectEntry, Foreground), (CreateRoom, Foreground), (CreateRoomResponse, Foreground), @@ -163,6 +164,10 @@ messages!( (GetCodeActionsResponse, Background), (GetHover, Background), (GetHoverResponse, Background), + (GetChannelMessages, Background), + (GetChannelMessagesResponse, Background), + (SendChannelMessage, Background), + (SendChannelMessageResponse, Background), (GetCompletions, Background), (GetCompletionsResponse, Background), (GetDefinition, Background), @@ -184,6 +189,9 @@ messages!( (JoinProjectResponse, Foreground), (JoinRoom, Foreground), (JoinRoomResponse, Foreground), + (JoinChannelChat, Foreground), + (JoinChannelChatResponse, Foreground), + (LeaveChannelChat, Foreground), (LeaveProject, Foreground), (LeaveRoom, Foreground), (OpenBufferById, Background), @@ -293,6 +301,7 @@ request_messages!( (InviteChannelMember, Ack), (JoinProject, JoinProjectResponse), (JoinRoom, JoinRoomResponse), + (JoinChannelChat, JoinChannelChatResponse), (LeaveRoom, Ack), (RejoinRoom, RejoinRoomResponse), (IncomingCall, Ack), @@ -313,6 +322,8 @@ request_messages!( (RespondToContactRequest, Ack), (RespondToChannelInvite, Ack), (SetChannelMemberAdmin, Ack), + (SendChannelMessage, SendChannelMessageResponse), + (GetChannelMessages, GetChannelMessagesResponse), (GetChannelMembers, GetChannelMembersResponse), (JoinChannel, JoinRoomResponse), (RemoveChannel, Ack), @@ -388,6 +399,7 @@ entity_messages!( entity_messages!( channel_id, + ChannelMessageSent, UpdateChannelBuffer, RemoveChannelBufferCollaborator, AddChannelBufferCollaborator, diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index a542249788..15d7e1a71f 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -49,6 +49,7 @@ pub struct Theme { pub copilot: Copilot, pub collab_panel: CollabPanel, pub project_panel: ProjectPanel, + pub chat_panel: ChatPanel, pub command_palette: CommandPalette, pub picker: Picker, pub editor: Editor, @@ -611,6 +612,17 @@ pub struct IconButton { pub button_width: f32, } +#[derive(Deserialize, Default, JsonSchema)] +pub struct ChatPanel { + #[serde(flatten)] + pub container: ContainerStyle, + pub channel_select: ChannelSelect, + pub input_editor: FieldEditor, + pub message: ChatMessage, + pub pending_message: ChatMessage, + pub sign_in_prompt: Interactive, +} + #[derive(Deserialize, Default, JsonSchema)] pub struct ChatMessage { #[serde(flatten)] From da5a77badf9f39ac7e2614b2c33fd65fc1857629 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 7 Sep 2023 12:24:25 -0700 Subject: [PATCH 02/38] Start work on restoring server-side code for chat messages --- crates/channel/src/channel.rs | 1 + crates/channel/src/channel_chat.rs | 8 +- .../20221109000000_test_schema.sql | 20 +++ .../20230907114200_add_channel_messages.sql | 19 +++ crates/collab/src/db/ids.rs | 2 + crates/collab/src/db/queries.rs | 1 + crates/collab/src/db/queries/messages.rs | 152 ++++++++++++++++++ crates/collab/src/db/tables.rs | 2 + crates/collab/src/db/tables/channel.rs | 8 + .../src/db/tables/channel_chat_participant.rs | 41 +++++ .../collab/src/db/tables/channel_message.rs | 45 ++++++ crates/collab/src/db/tests.rs | 1 + crates/collab/src/db/tests/message_tests.rs | 53 ++++++ crates/collab/src/rpc.rs | 119 +++++++++++++- crates/collab/src/tests.rs | 1 + .../collab/src/tests/channel_message_tests.rs | 56 +++++++ 16 files changed, 524 insertions(+), 5 deletions(-) create mode 100644 crates/collab/migrations/20230907114200_add_channel_messages.sql create mode 100644 crates/collab/src/db/queries/messages.rs create mode 100644 crates/collab/src/db/tables/channel_chat_participant.rs create mode 100644 crates/collab/src/db/tables/channel_message.rs create mode 100644 crates/collab/src/db/tests/message_tests.rs create mode 100644 crates/collab/src/tests/channel_message_tests.rs diff --git a/crates/channel/src/channel.rs b/crates/channel/src/channel.rs index b4acc0c25f..37f1c0ce44 100644 --- a/crates/channel/src/channel.rs +++ b/crates/channel/src/channel.rs @@ -14,4 +14,5 @@ mod channel_store_tests; pub fn init(client: &Arc) { channel_buffer::init(client); + channel_chat::init(client); } diff --git a/crates/channel/src/channel_chat.rs b/crates/channel/src/channel_chat.rs index ebe491e5b8..3916189363 100644 --- a/crates/channel/src/channel_chat.rs +++ b/crates/channel/src/channel_chat.rs @@ -57,6 +57,10 @@ pub enum ChannelChatEvent { }, } +pub fn init(client: &Arc) { + client.add_model_message_handler(ChannelChat::handle_message_sent); +} + impl Entity for ChannelChat { type Event = ChannelChatEvent; @@ -70,10 +74,6 @@ impl Entity for ChannelChat { } impl ChannelChat { - pub fn init(rpc: &Arc) { - rpc.add_model_message_handler(Self::handle_message_sent); - } - pub async fn new( channel: Arc, user_store: ModelHandle, diff --git a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql index 80477dcb3c..ab12039b10 100644 --- a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql +++ b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql @@ -192,6 +192,26 @@ CREATE TABLE "channels" ( "created_at" TIMESTAMP NOT NULL DEFAULT now ); +CREATE TABLE IF NOT EXISTS "channel_chat_participants" ( + "id" INTEGER PRIMARY KEY AUTOINCREMENT, + "user_id" INTEGER NOT NULL REFERENCES users (id), + "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE, + "connection_id" INTEGER NOT NULL, + "connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE +); +CREATE INDEX "index_channel_chat_participants_on_channel_id" ON "channel_chat_participants" ("channel_id"); + +CREATE TABLE IF NOT EXISTS "channel_messages" ( + "id" INTEGER PRIMARY KEY AUTOINCREMENT, + "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE, + "sender_id" INTEGER NOT NULL REFERENCES users (id), + "body" TEXT NOT NULL, + "sent_at" TIMESTAMP, + "nonce" BLOB NOT NULL +); +CREATE INDEX "index_channel_messages_on_channel_id" ON "channel_messages" ("channel_id"); +CREATE UNIQUE INDEX "index_channel_messages_on_nonce" ON "channel_messages" ("nonce"); + CREATE TABLE "channel_paths" ( "id_path" TEXT NOT NULL PRIMARY KEY, "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE diff --git a/crates/collab/migrations/20230907114200_add_channel_messages.sql b/crates/collab/migrations/20230907114200_add_channel_messages.sql new file mode 100644 index 0000000000..abe7753ca6 --- /dev/null +++ b/crates/collab/migrations/20230907114200_add_channel_messages.sql @@ -0,0 +1,19 @@ +CREATE TABLE IF NOT EXISTS "channel_messages" ( + "id" SERIAL PRIMARY KEY, + "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE, + "sender_id" INTEGER NOT NULL REFERENCES users (id), + "body" TEXT NOT NULL, + "sent_at" TIMESTAMP, + "nonce" UUID NOT NULL +); +CREATE INDEX "index_channel_messages_on_channel_id" ON "channel_messages" ("channel_id"); +CREATE UNIQUE INDEX "index_channel_messages_on_nonce" ON "channel_messages" ("nonce"); + +CREATE TABLE IF NOT EXISTS "channel_chat_participants" ( + "id" SERIAL PRIMARY KEY, + "user_id" INTEGER NOT NULL REFERENCES users (id), + "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE, + "connection_id" INTEGER NOT NULL, + "connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE +); +CREATE INDEX "index_channel_chat_participants_on_channel_id" ON "channel_chat_participants" ("channel_id"); diff --git a/crates/collab/src/db/ids.rs b/crates/collab/src/db/ids.rs index b33ea57183..865a39fd71 100644 --- a/crates/collab/src/db/ids.rs +++ b/crates/collab/src/db/ids.rs @@ -112,8 +112,10 @@ fn value_to_integer(v: Value) -> Result { id_type!(BufferId); id_type!(AccessTokenId); +id_type!(ChannelChatParticipantId); id_type!(ChannelId); id_type!(ChannelMemberId); +id_type!(MessageId); id_type!(ContactId); id_type!(FollowerId); id_type!(RoomId); diff --git a/crates/collab/src/db/queries.rs b/crates/collab/src/db/queries.rs index 09a8f073b4..54db0663d2 100644 --- a/crates/collab/src/db/queries.rs +++ b/crates/collab/src/db/queries.rs @@ -4,6 +4,7 @@ pub mod access_tokens; pub mod buffers; pub mod channels; pub mod contacts; +pub mod messages; pub mod projects; pub mod rooms; pub mod servers; diff --git a/crates/collab/src/db/queries/messages.rs b/crates/collab/src/db/queries/messages.rs new file mode 100644 index 0000000000..e8b9ec7416 --- /dev/null +++ b/crates/collab/src/db/queries/messages.rs @@ -0,0 +1,152 @@ +use super::*; +use time::OffsetDateTime; + +impl Database { + pub async fn join_channel_chat( + &self, + channel_id: ChannelId, + connection_id: ConnectionId, + user_id: UserId, + ) -> Result<()> { + self.transaction(|tx| async move { + self.check_user_is_channel_member(channel_id, user_id, &*tx) + .await?; + channel_chat_participant::ActiveModel { + id: ActiveValue::NotSet, + channel_id: ActiveValue::Set(channel_id), + user_id: ActiveValue::Set(user_id), + connection_id: ActiveValue::Set(connection_id.id as i32), + connection_server_id: ActiveValue::Set(ServerId(connection_id.owner_id as i32)), + } + .insert(&*tx) + .await?; + Ok(()) + }) + .await + } + + pub async fn leave_channel_chat( + &self, + channel_id: ChannelId, + connection_id: ConnectionId, + _user_id: UserId, + ) -> Result<()> { + self.transaction(|tx| async move { + channel_chat_participant::Entity::delete_many() + .filter( + Condition::all() + .add( + channel_chat_participant::Column::ConnectionServerId + .eq(connection_id.owner_id), + ) + .add(channel_chat_participant::Column::ConnectionId.eq(connection_id.id)) + .add(channel_chat_participant::Column::ChannelId.eq(channel_id)), + ) + .exec(&*tx) + .await?; + + Ok(()) + }) + .await + } + + pub async fn get_channel_messages( + &self, + channel_id: ChannelId, + user_id: UserId, + count: usize, + before_message_id: Option, + ) -> Result> { + self.transaction(|tx| async move { + self.check_user_is_channel_member(channel_id, user_id, &*tx) + .await?; + + let mut condition = + Condition::all().add(channel_message::Column::ChannelId.eq(channel_id)); + + if let Some(before_message_id) = before_message_id { + condition = condition.add(channel_message::Column::Id.lt(before_message_id)); + } + + let mut rows = channel_message::Entity::find() + .filter(condition) + .limit(count as u64) + .stream(&*tx) + .await?; + + let mut messages = Vec::new(); + while let Some(row) = rows.next().await { + let row = row?; + let nonce = row.nonce.as_u64_pair(); + messages.push(proto::ChannelMessage { + id: row.id.to_proto(), + sender_id: row.sender_id.to_proto(), + body: row.body, + timestamp: row.sent_at.unix_timestamp() as u64, + nonce: Some(proto::Nonce { + upper_half: nonce.0, + lower_half: nonce.1, + }), + }); + } + + Ok(messages) + }) + .await + } + + pub async fn create_channel_message( + &self, + channel_id: ChannelId, + user_id: UserId, + body: &str, + timestamp: OffsetDateTime, + nonce: u128, + ) -> Result<(MessageId, Vec)> { + self.transaction(|tx| async move { + let mut rows = channel_chat_participant::Entity::find() + .filter(channel_chat_participant::Column::ChannelId.eq(channel_id)) + .stream(&*tx) + .await?; + + let mut is_participant = false; + let mut participant_connection_ids = Vec::new(); + while let Some(row) = rows.next().await { + let row = row?; + if row.user_id == user_id { + is_participant = true; + } + participant_connection_ids.push(row.connection()); + } + drop(rows); + + if !is_participant { + Err(anyhow!("not a chat participant"))?; + } + + let message = channel_message::Entity::insert(channel_message::ActiveModel { + channel_id: ActiveValue::Set(channel_id), + sender_id: ActiveValue::Set(user_id), + body: ActiveValue::Set(body.to_string()), + sent_at: ActiveValue::Set(timestamp), + nonce: ActiveValue::Set(Uuid::from_u128(nonce)), + id: ActiveValue::NotSet, + }) + .on_conflict( + OnConflict::column(channel_message::Column::Nonce) + .update_column(channel_message::Column::Nonce) + .to_owned(), + ) + .exec(&*tx) + .await?; + + #[derive(Debug, Clone, Copy, EnumIter, DeriveColumn)] + enum QueryConnectionId { + ConnectionId, + } + + Ok((message.last_insert_id, participant_connection_ids)) + }) + .await + } +} diff --git a/crates/collab/src/db/tables.rs b/crates/collab/src/db/tables.rs index 1765cee065..81200df3e7 100644 --- a/crates/collab/src/db/tables.rs +++ b/crates/collab/src/db/tables.rs @@ -4,7 +4,9 @@ pub mod buffer_operation; pub mod buffer_snapshot; pub mod channel; pub mod channel_buffer_collaborator; +pub mod channel_chat_participant; pub mod channel_member; +pub mod channel_message; pub mod channel_path; pub mod contact; pub mod feature_flag; diff --git a/crates/collab/src/db/tables/channel.rs b/crates/collab/src/db/tables/channel.rs index 05895ede4c..54f12defc1 100644 --- a/crates/collab/src/db/tables/channel.rs +++ b/crates/collab/src/db/tables/channel.rs @@ -21,6 +21,8 @@ pub enum Relation { Member, #[sea_orm(has_many = "super::channel_buffer_collaborator::Entity")] BufferCollaborators, + #[sea_orm(has_many = "super::channel_chat_participant::Entity")] + ChatParticipants, } impl Related for Entity { @@ -46,3 +48,9 @@ impl Related for Entity { Relation::BufferCollaborators.def() } } + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ChatParticipants.def() + } +} diff --git a/crates/collab/src/db/tables/channel_chat_participant.rs b/crates/collab/src/db/tables/channel_chat_participant.rs new file mode 100644 index 0000000000..f3ef36c289 --- /dev/null +++ b/crates/collab/src/db/tables/channel_chat_participant.rs @@ -0,0 +1,41 @@ +use crate::db::{ChannelChatParticipantId, ChannelId, ServerId, UserId}; +use rpc::ConnectionId; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] +#[sea_orm(table_name = "channel_chat_participants")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: ChannelChatParticipantId, + pub channel_id: ChannelId, + pub user_id: UserId, + pub connection_id: i32, + pub connection_server_id: ServerId, +} + +impl Model { + pub fn connection(&self) -> ConnectionId { + ConnectionId { + owner_id: self.connection_server_id.0 as u32, + id: self.connection_id as u32, + } + } +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::channel::Entity", + from = "Column::ChannelId", + to = "super::channel::Column::Id" + )] + Channel, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/collab/src/db/tables/channel_message.rs b/crates/collab/src/db/tables/channel_message.rs new file mode 100644 index 0000000000..d043d5b668 --- /dev/null +++ b/crates/collab/src/db/tables/channel_message.rs @@ -0,0 +1,45 @@ +use crate::db::{ChannelId, MessageId, UserId}; +use sea_orm::entity::prelude::*; +use time::OffsetDateTime; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] +#[sea_orm(table_name = "channel_messages")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: MessageId, + pub channel_id: ChannelId, + pub sender_id: UserId, + pub body: String, + pub sent_at: OffsetDateTime, + pub nonce: Uuid, +} + +impl ActiveModelBehavior for ActiveModel {} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::channel::Entity", + from = "Column::ChannelId", + to = "super::channel::Column::Id" + )] + Channel, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::SenderId", + to = "super::user::Column::Id" + )] + Sender, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Sender.def() + } +} diff --git a/crates/collab/src/db/tests.rs b/crates/collab/src/db/tests.rs index ee961006cb..1d6c550865 100644 --- a/crates/collab/src/db/tests.rs +++ b/crates/collab/src/db/tests.rs @@ -1,6 +1,7 @@ mod buffer_tests; mod db_tests; mod feature_flag_tests; +mod message_tests; use super::*; use gpui::executor::Background; diff --git a/crates/collab/src/db/tests/message_tests.rs b/crates/collab/src/db/tests/message_tests.rs new file mode 100644 index 0000000000..1dd686a1d2 --- /dev/null +++ b/crates/collab/src/db/tests/message_tests.rs @@ -0,0 +1,53 @@ +use crate::{ + db::{Database, NewUserParams}, + test_both_dbs, +}; +use std::sync::Arc; +use time::OffsetDateTime; + +test_both_dbs!( + test_channel_message_nonces, + test_channel_message_nonces_postgres, + test_channel_message_nonces_sqlite +); + +async fn test_channel_message_nonces(db: &Arc) { + let user = db + .create_user( + "user@example.com", + false, + NewUserParams { + github_login: "user".into(), + github_user_id: 1, + invite_count: 0, + }, + ) + .await + .unwrap() + .user_id; + let channel = db + .create_channel("channel", None, "room", user) + .await + .unwrap(); + + let msg1_id = db + .create_channel_message(channel, user, "1", OffsetDateTime::now_utc(), 1) + .await + .unwrap(); + let msg2_id = db + .create_channel_message(channel, user, "2", OffsetDateTime::now_utc(), 2) + .await + .unwrap(); + let msg3_id = db + .create_channel_message(channel, user, "3", OffsetDateTime::now_utc(), 1) + .await + .unwrap(); + let msg4_id = db + .create_channel_message(channel, user, "4", OffsetDateTime::now_utc(), 2) + .await + .unwrap(); + + assert_ne!(msg1_id, msg2_id); + assert_eq!(msg1_id, msg3_id); + assert_eq!(msg2_id, msg4_id); +} diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index e454fcbb9e..b508c45dc5 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -2,7 +2,10 @@ mod connection_pool; use crate::{ auth, - db::{self, ChannelId, ChannelsForUser, Database, ProjectId, RoomId, ServerId, User, UserId}, + db::{ + self, ChannelId, ChannelsForUser, Database, MessageId, ProjectId, RoomId, ServerId, User, + UserId, + }, executor::Executor, AppState, Result, }; @@ -56,6 +59,7 @@ use std::{ }, time::{Duration, Instant}, }; +use time::OffsetDateTime; use tokio::sync::{watch, Semaphore}; use tower::ServiceBuilder; use tracing::{info_span, instrument, Instrument}; @@ -63,6 +67,9 @@ use tracing::{info_span, instrument, Instrument}; pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30); pub const CLEANUP_TIMEOUT: Duration = Duration::from_secs(10); +const MESSAGE_COUNT_PER_PAGE: usize = 100; +const MAX_MESSAGE_LEN: usize = 1024; + lazy_static! { static ref METRIC_CONNECTIONS: IntGauge = register_int_gauge!("connections", "number of connections").unwrap(); @@ -255,6 +262,10 @@ impl Server { .add_request_handler(get_channel_members) .add_request_handler(respond_to_channel_invite) .add_request_handler(join_channel) + .add_request_handler(join_channel_chat) + .add_message_handler(leave_channel_chat) + .add_request_handler(send_channel_message) + .add_request_handler(get_channel_messages) .add_request_handler(follow) .add_message_handler(unfollow) .add_message_handler(update_followers) @@ -2641,6 +2652,112 @@ fn channel_buffer_updated( }); } +async fn send_channel_message( + request: proto::SendChannelMessage, + response: Response, + session: Session, +) -> Result<()> { + // Validate the message body. + let body = request.body.trim().to_string(); + if body.len() > MAX_MESSAGE_LEN { + return Err(anyhow!("message is too long"))?; + } + if body.is_empty() { + return Err(anyhow!("message can't be blank"))?; + } + + let timestamp = OffsetDateTime::now_utc(); + let nonce = request + .nonce + .ok_or_else(|| anyhow!("nonce can't be blank"))?; + + let channel_id = ChannelId::from_proto(request.channel_id); + let (message_id, connection_ids) = session + .db() + .await + .create_channel_message( + channel_id, + session.user_id, + &body, + timestamp, + nonce.clone().into(), + ) + .await?; + let message = proto::ChannelMessage { + sender_id: session.user_id.to_proto(), + id: message_id.to_proto(), + body, + timestamp: timestamp.unix_timestamp() as u64, + nonce: Some(nonce), + }; + broadcast(Some(session.connection_id), connection_ids, |connection| { + session.peer.send( + connection, + proto::ChannelMessageSent { + channel_id: channel_id.to_proto(), + message: Some(message.clone()), + }, + ) + }); + response.send(proto::SendChannelMessageResponse { + message: Some(message), + })?; + Ok(()) +} + +async fn join_channel_chat( + request: proto::JoinChannelChat, + response: Response, + session: Session, +) -> Result<()> { + let channel_id = ChannelId::from_proto(request.channel_id); + + let db = session.db().await; + db.join_channel_chat(channel_id, session.connection_id, session.user_id) + .await?; + let messages = db + .get_channel_messages(channel_id, session.user_id, MESSAGE_COUNT_PER_PAGE, None) + .await?; + response.send(proto::JoinChannelChatResponse { + done: messages.len() < MESSAGE_COUNT_PER_PAGE, + messages, + })?; + Ok(()) +} + +async fn leave_channel_chat(request: proto::LeaveChannelChat, session: Session) -> Result<()> { + let channel_id = ChannelId::from_proto(request.channel_id); + session + .db() + .await + .leave_channel_chat(channel_id, session.connection_id, session.user_id) + .await?; + Ok(()) +} + +async fn get_channel_messages( + request: proto::GetChannelMessages, + response: Response, + session: Session, +) -> Result<()> { + let channel_id = ChannelId::from_proto(request.channel_id); + let messages = session + .db() + .await + .get_channel_messages( + channel_id, + session.user_id, + MESSAGE_COUNT_PER_PAGE, + Some(MessageId::from_proto(request.before_message_id)), + ) + .await?; + response.send(proto::GetChannelMessagesResponse { + done: messages.len() < MESSAGE_COUNT_PER_PAGE, + messages, + })?; + Ok(()) +} + async fn update_diff_base(request: proto::UpdateDiffBase, session: Session) -> Result<()> { let project_id = ProjectId::from_proto(request.project_id); let project_connection_ids = session diff --git a/crates/collab/src/tests.rs b/crates/collab/src/tests.rs index 3000f0d8c3..b0f5b96fde 100644 --- a/crates/collab/src/tests.rs +++ b/crates/collab/src/tests.rs @@ -2,6 +2,7 @@ use call::Room; use gpui::{ModelHandle, TestAppContext}; mod channel_buffer_tests; +mod channel_message_tests; mod channel_tests; mod integration_tests; mod random_channel_buffer_tests; diff --git a/crates/collab/src/tests/channel_message_tests.rs b/crates/collab/src/tests/channel_message_tests.rs new file mode 100644 index 0000000000..e7afd136f3 --- /dev/null +++ b/crates/collab/src/tests/channel_message_tests.rs @@ -0,0 +1,56 @@ +use crate::tests::TestServer; +use gpui::{executor::Deterministic, TestAppContext}; +use std::sync::Arc; + +#[gpui::test] +async fn test_basic_channel_messages( + deterministic: Arc, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + + let channel_id = server + .make_channel("the-channel", (&client_a, cx_a), &mut [(&client_b, cx_b)]) + .await; + + let channel_chat_a = client_a + .channel_store() + .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + let channel_chat_b = client_b + .channel_store() + .update(cx_b, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + + channel_chat_a + .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap()) + .await + .unwrap(); + channel_chat_a + .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap()) + .await + .unwrap(); + + deterministic.run_until_parked(); + channel_chat_b + .update(cx_b, |c, cx| c.send_message("three".into(), cx).unwrap()) + .await + .unwrap(); + + deterministic.run_until_parked(); + channel_chat_a.update(cx_a, |c, _| { + assert_eq!( + c.messages() + .iter() + .map(|m| m.body.as_str()) + .collect::>(), + vec!["one", "two", "three"] + ); + }) +} From ddda5a559b79ff11b9afa29e20a9a3f32799ec85 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 7 Sep 2023 18:06:05 -0700 Subject: [PATCH 03/38] Restore chat functionality with a very rough UI --- crates/channel/Cargo.toml | 1 + crates/channel/src/channel_store.rs | 4 + crates/channel/src/channel_store_tests.rs | 221 ++++++++--------- crates/client/src/test.rs | 9 +- crates/collab/src/db/queries/messages.rs | 5 +- .../collab/src/db/tables/channel_message.rs | 4 +- crates/collab/src/db/tests/message_tests.rs | 6 + crates/collab_ui/src/chat_panel.rs | 229 ++++++++++++++---- crates/collab_ui/src/collab_panel.rs | 15 +- crates/collab_ui/src/collab_ui.rs | 3 +- crates/zed/src/zed.rs | 15 +- styles/src/style_tree/app.ts | 2 + styles/src/style_tree/chat_panel.ts | 111 +++++++++ 13 files changed, 440 insertions(+), 185 deletions(-) create mode 100644 styles/src/style_tree/chat_panel.ts diff --git a/crates/channel/Cargo.toml b/crates/channel/Cargo.toml index c2191fdfa3..00e9135bc1 100644 --- a/crates/channel/Cargo.toml +++ b/crates/channel/Cargo.toml @@ -47,5 +47,6 @@ tempfile = "3" collections = { path = "../collections", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } +client = { path = "../client", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } diff --git a/crates/channel/src/channel_store.rs b/crates/channel/src/channel_store.rs index 6096692ccb..48228041ec 100644 --- a/crates/channel/src/channel_store.rs +++ b/crates/channel/src/channel_store.rs @@ -111,6 +111,10 @@ impl ChannelStore { } } + pub fn client(&self) -> Arc { + self.client.clone() + } + pub fn has_children(&self, channel_id: ChannelId) -> bool { self.channel_paths.iter().any(|path| { if let Some(ix) = path.iter().position(|id| *id == channel_id) { diff --git a/crates/channel/src/channel_store_tests.rs b/crates/channel/src/channel_store_tests.rs index 3ae899ecde..22174f161b 100644 --- a/crates/channel/src/channel_store_tests.rs +++ b/crates/channel/src/channel_store_tests.rs @@ -4,15 +4,12 @@ use super::*; use client::{test::FakeServer, Client, UserStore}; use gpui::{AppContext, ModelHandle, TestAppContext}; use rpc::proto; +use settings::SettingsStore; use util::http::FakeHttpClient; #[gpui::test] fn test_update_channels(cx: &mut AppContext) { - let http = FakeHttpClient::with_404_response(); - let client = Client::new(http.clone(), cx); - let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx)); - - let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx)); + let channel_store = init_test(cx); update_channels( &channel_store, @@ -80,11 +77,7 @@ fn test_update_channels(cx: &mut AppContext) { #[gpui::test] fn test_dangling_channel_paths(cx: &mut AppContext) { - let http = FakeHttpClient::with_404_response(); - let client = Client::new(http.clone(), cx); - let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx)); - - let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx)); + let channel_store = init_test(cx); update_channels( &channel_store, @@ -141,18 +134,11 @@ fn test_dangling_channel_paths(cx: &mut AppContext) { #[gpui::test] async fn test_channel_messages(cx: &mut TestAppContext) { - cx.foreground().forbid_parking(); - let user_id = 5; - let http_client = FakeHttpClient::with_404_response(); - let client = cx.update(|cx| Client::new(http_client.clone(), cx)); - let server = FakeServer::for_client(user_id, &client, cx).await; - let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx)); - crate::init(&client); - - let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx)); - let channel_id = 5; + let channel_store = cx.update(init_test); + let client = channel_store.read_with(cx, |s, _| s.client()); + let server = FakeServer::for_client(user_id, &client, cx).await; // Get the available channels. server.send(proto::UpdateChannels { @@ -163,85 +149,71 @@ async fn test_channel_messages(cx: &mut TestAppContext) { }], ..Default::default() }); - channel_store.next_notification(cx).await; + cx.foreground().run_until_parked(); cx.read(|cx| { assert_channels(&channel_store, &[(0, "the-channel".to_string(), false)], cx); }); let get_users = server.receive::().await.unwrap(); assert_eq!(get_users.payload.user_ids, vec![5]); - server - .respond( - get_users.receipt(), - proto::UsersResponse { - users: vec![proto::User { - id: 5, - github_login: "nathansobo".into(), - avatar_url: "http://avatar.com/nathansobo".into(), - }], - }, - ) - .await; + server.respond( + get_users.receipt(), + proto::UsersResponse { + users: vec![proto::User { + id: 5, + github_login: "nathansobo".into(), + avatar_url: "http://avatar.com/nathansobo".into(), + }], + }, + ); // Join a channel and populate its existing messages. - let channel = channel_store - .update(cx, |store, cx| { - let channel_id = store.channels().next().unwrap().1.id; - store.open_channel_chat(channel_id, cx) - }) - .await - .unwrap(); - channel.read_with(cx, |channel, _| assert!(channel.messages().is_empty())); + let channel = channel_store.update(cx, |store, cx| { + let channel_id = store.channels().next().unwrap().1.id; + store.open_channel_chat(channel_id, cx) + }); let join_channel = server.receive::().await.unwrap(); - server - .respond( - join_channel.receipt(), - proto::JoinChannelChatResponse { - messages: vec![ - proto::ChannelMessage { - id: 10, - body: "a".into(), - timestamp: 1000, - sender_id: 5, - nonce: Some(1.into()), - }, - proto::ChannelMessage { - id: 11, - body: "b".into(), - timestamp: 1001, - sender_id: 6, - nonce: Some(2.into()), - }, - ], - done: false, - }, - ) - .await; + server.respond( + join_channel.receipt(), + proto::JoinChannelChatResponse { + messages: vec![ + proto::ChannelMessage { + id: 10, + body: "a".into(), + timestamp: 1000, + sender_id: 5, + nonce: Some(1.into()), + }, + proto::ChannelMessage { + id: 11, + body: "b".into(), + timestamp: 1001, + sender_id: 6, + nonce: Some(2.into()), + }, + ], + done: false, + }, + ); + + cx.foreground().start_waiting(); // Client requests all users for the received messages let mut get_users = server.receive::().await.unwrap(); get_users.payload.user_ids.sort(); assert_eq!(get_users.payload.user_ids, vec![6]); - server - .respond( - get_users.receipt(), - proto::UsersResponse { - users: vec![proto::User { - id: 6, - github_login: "maxbrunsfeld".into(), - avatar_url: "http://avatar.com/maxbrunsfeld".into(), - }], - }, - ) - .await; - - assert_eq!( - channel.next_event(cx).await, - ChannelChatEvent::MessagesUpdated { - old_range: 0..0, - new_count: 2, - } + server.respond( + get_users.receipt(), + proto::UsersResponse { + users: vec![proto::User { + id: 6, + github_login: "maxbrunsfeld".into(), + avatar_url: "http://avatar.com/maxbrunsfeld".into(), + }], + }, ); + + let channel = channel.await.unwrap(); channel.read_with(cx, |channel, _| { assert_eq!( channel @@ -270,18 +242,16 @@ async fn test_channel_messages(cx: &mut TestAppContext) { // Client requests user for message since they haven't seen them yet let get_users = server.receive::().await.unwrap(); assert_eq!(get_users.payload.user_ids, vec![7]); - server - .respond( - get_users.receipt(), - proto::UsersResponse { - users: vec![proto::User { - id: 7, - github_login: "as-cii".into(), - avatar_url: "http://avatar.com/as-cii".into(), - }], - }, - ) - .await; + server.respond( + get_users.receipt(), + proto::UsersResponse { + users: vec![proto::User { + id: 7, + github_login: "as-cii".into(), + avatar_url: "http://avatar.com/as-cii".into(), + }], + }, + ); assert_eq!( channel.next_event(cx).await, @@ -307,30 +277,28 @@ async fn test_channel_messages(cx: &mut TestAppContext) { let get_messages = server.receive::().await.unwrap(); assert_eq!(get_messages.payload.channel_id, 5); assert_eq!(get_messages.payload.before_message_id, 10); - server - .respond( - get_messages.receipt(), - proto::GetChannelMessagesResponse { - done: true, - messages: vec![ - proto::ChannelMessage { - id: 8, - body: "y".into(), - timestamp: 998, - sender_id: 5, - nonce: Some(4.into()), - }, - proto::ChannelMessage { - id: 9, - body: "z".into(), - timestamp: 999, - sender_id: 6, - nonce: Some(5.into()), - }, - ], - }, - ) - .await; + server.respond( + get_messages.receipt(), + proto::GetChannelMessagesResponse { + done: true, + messages: vec![ + proto::ChannelMessage { + id: 8, + body: "y".into(), + timestamp: 998, + sender_id: 5, + nonce: Some(4.into()), + }, + proto::ChannelMessage { + id: 9, + body: "z".into(), + timestamp: 999, + sender_id: 6, + nonce: Some(5.into()), + }, + ], + }, + ); assert_eq!( channel.next_event(cx).await, @@ -353,6 +321,19 @@ async fn test_channel_messages(cx: &mut TestAppContext) { }); } +fn init_test(cx: &mut AppContext) -> ModelHandle { + let http = FakeHttpClient::with_404_response(); + let client = Client::new(http.clone(), cx); + let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx)); + + cx.foreground().forbid_parking(); + cx.set_global(SettingsStore::test(cx)); + crate::init(&client); + client::init(&client, cx); + + cx.add_model(|cx| ChannelStore::new(client, user_store, cx)) +} + fn update_channels( channel_store: &ModelHandle, message: proto::UpdateChannels, diff --git a/crates/client/src/test.rs b/crates/client/src/test.rs index 00e7cd1508..38cd12f21c 100644 --- a/crates/client/src/test.rs +++ b/crates/client/src/test.rs @@ -170,8 +170,7 @@ impl FakeServer { staff: false, flags: Default::default(), }, - ) - .await; + ); continue; } @@ -182,11 +181,7 @@ impl FakeServer { } } - pub async fn respond( - &self, - receipt: Receipt, - response: T::Response, - ) { + pub fn respond(&self, receipt: Receipt, response: T::Response) { self.peer.respond(receipt, response).unwrap() } diff --git a/crates/collab/src/db/queries/messages.rs b/crates/collab/src/db/queries/messages.rs index e8b9ec7416..4593d8f2f3 100644 --- a/crates/collab/src/db/queries/messages.rs +++ b/crates/collab/src/db/queries/messages.rs @@ -82,7 +82,7 @@ impl Database { id: row.id.to_proto(), sender_id: row.sender_id.to_proto(), body: row.body, - timestamp: row.sent_at.unix_timestamp() as u64, + timestamp: row.sent_at.assume_utc().unix_timestamp() as u64, nonce: Some(proto::Nonce { upper_half: nonce.0, lower_half: nonce.1, @@ -124,6 +124,9 @@ impl Database { Err(anyhow!("not a chat participant"))?; } + let timestamp = timestamp.to_offset(time::UtcOffset::UTC); + let timestamp = time::PrimitiveDateTime::new(timestamp.date(), timestamp.time()); + let message = channel_message::Entity::insert(channel_message::ActiveModel { channel_id: ActiveValue::Set(channel_id), sender_id: ActiveValue::Set(user_id), diff --git a/crates/collab/src/db/tables/channel_message.rs b/crates/collab/src/db/tables/channel_message.rs index d043d5b668..ff49c63ba7 100644 --- a/crates/collab/src/db/tables/channel_message.rs +++ b/crates/collab/src/db/tables/channel_message.rs @@ -1,6 +1,6 @@ use crate::db::{ChannelId, MessageId, UserId}; use sea_orm::entity::prelude::*; -use time::OffsetDateTime; +use time::PrimitiveDateTime; #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(table_name = "channel_messages")] @@ -10,7 +10,7 @@ pub struct Model { pub channel_id: ChannelId, pub sender_id: UserId, pub body: String, - pub sent_at: OffsetDateTime, + pub sent_at: PrimitiveDateTime, pub nonce: Uuid, } diff --git a/crates/collab/src/db/tests/message_tests.rs b/crates/collab/src/db/tests/message_tests.rs index 1dd686a1d2..c40e53d355 100644 --- a/crates/collab/src/db/tests/message_tests.rs +++ b/crates/collab/src/db/tests/message_tests.rs @@ -30,6 +30,12 @@ async fn test_channel_message_nonces(db: &Arc) { .await .unwrap(); + let owner_id = db.create_server("test").await.unwrap().0 as u32; + + db.join_channel_chat(channel, rpc::ConnectionId { owner_id, id: 0 }, user) + .await + .unwrap(); + let msg1_id = db .create_channel_message(channel, user, "1", OffsetDateTime::now_utc(), 1) .await diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index 0105a9d27b..1cbd8574eb 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -1,21 +1,33 @@ +use crate::collab_panel::{CollaborationPanelDockPosition, CollaborationPanelSettings}; +use anyhow::Result; use channel::{ChannelChat, ChannelChatEvent, ChannelMessage, ChannelStore}; use client::Client; +use db::kvp::KEY_VALUE_STORE; use editor::Editor; use gpui::{ actions, elements::*, platform::{CursorStyle, MouseButton}, + serde_json, views::{ItemType, Select, SelectStyle}, - AnyViewHandle, AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle, + AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelHandle, Subscription, Task, View, + ViewContext, ViewHandle, WeakViewHandle, }; use language::language_settings::SoftWrap; use menu::Confirm; +use project::Fs; +use serde::{Deserialize, Serialize}; use std::sync::Arc; use theme::Theme; use time::{OffsetDateTime, UtcOffset}; use util::{ResultExt, TryFutureExt}; +use workspace::{ + dock::{DockPosition, Panel}, + Workspace, +}; const MESSAGE_LOADING_THRESHOLD: usize = 50; +const CHAT_PANEL_KEY: &'static str = "ChatPanel"; pub struct ChatPanel { client: Arc, @@ -25,11 +37,25 @@ pub struct ChatPanel { input_editor: ViewHandle, channel_select: ViewHandle, @@ -105,7 +105,7 @@ impl ChatPanel { let mut message_list = ListState::::new(0, Orientation::Bottom, 1000., move |this, ix, cx| { - let message = this.active_channel.as_ref().unwrap().0.read(cx).message(ix); + let message = this.active_chat.as_ref().unwrap().0.read(cx).message(ix); this.render_message(message, cx) }); message_list.set_scroll_handler(|visible_range, this, cx| { @@ -119,7 +119,7 @@ impl ChatPanel { fs, client, channel_store, - active_channel: Default::default(), + active_chat: Default::default(), pending_serialization: Task::ready(None), message_list, input_editor, @@ -151,6 +151,7 @@ impl ChatPanel { cx.observe(&this.channel_select, |this, channel_select, cx| { let selected_ix = channel_select.read(cx).selected_index(); + let selected_channel_id = this .channel_store .read(cx) @@ -216,14 +217,14 @@ impl ChatPanel { fn init_active_channel(&mut self, cx: &mut ViewContext) { let channel_count = self.channel_store.read(cx).channel_count(); self.message_list.reset(0); - self.active_channel = None; + self.active_chat = None; self.channel_select.update(cx, |select, cx| { select.set_item_count(channel_count, cx); }); } - fn set_active_channel(&mut self, chat: ModelHandle, cx: &mut ViewContext) { - if self.active_channel.as_ref().map(|e| &e.0) != Some(&chat) { + fn set_active_chat(&mut self, chat: ModelHandle, cx: &mut ViewContext) { + if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) { let id = chat.read(cx).channel().id; { let chat = chat.read(cx); @@ -234,7 +235,7 @@ impl ChatPanel { }); } let subscription = cx.subscribe(&chat, Self::channel_did_change); - self.active_channel = Some((chat, subscription)); + self.active_chat = Some((chat, subscription)); self.channel_select.update(cx, |select, cx| { if let Some(ix) = self.channel_store.read(cx).index_of_channel(id) { select.set_selected_index(ix, cx); @@ -275,7 +276,7 @@ impl ChatPanel { } fn render_active_channel_messages(&self) -> AnyElement { - let messages = if self.active_channel.is_some() { + let messages = if self.active_chat.is_some() { List::new(self.message_list.clone()).into_any() } else { Empty::new().into_any() @@ -396,15 +397,15 @@ impl ChatPanel { } fn send(&mut self, _: &Confirm, cx: &mut ViewContext) { - if let Some((channel, _)) = self.active_channel.as_ref() { + if let Some((chat, _)) = self.active_chat.as_ref() { let body = self.input_editor.update(cx, |editor, cx| { let body = editor.text(cx); editor.clear(cx); body }); - if let Some(task) = channel - .update(cx, |channel, cx| channel.send_message(body, cx)) + if let Some(task) = chat + .update(cx, |chat, cx| chat.send_message(body, cx)) .log_err() { task.detach(); @@ -413,8 +414,8 @@ impl ChatPanel { } fn load_more_messages(&mut self, _: &LoadMoreMessages, cx: &mut ViewContext) { - if let Some((channel, _)) = self.active_channel.as_ref() { - channel.update(cx, |channel, cx| { + if let Some((chat, _)) = self.active_chat.as_ref() { + chat.update(cx, |channel, cx| { channel.load_more_messages(cx); }) } @@ -425,13 +426,19 @@ impl ChatPanel { selected_channel_id: u64, cx: &mut ViewContext, ) -> Task> { + if let Some((chat, _)) = &self.active_chat { + if chat.read(cx).channel().id == selected_channel_id { + return Task::ready(Ok(())); + } + } + let open_chat = self.channel_store.update(cx, |store, cx| { store.open_channel_chat(selected_channel_id, cx) }); cx.spawn(|this, mut cx| async move { let chat = open_chat.await?; this.update(&mut cx, |this, cx| { - this.set_active_channel(chat, cx); + this.set_active_chat(chat, cx); }) }) } diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 396ff6df91..ad1c2a0037 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -80,7 +80,7 @@ struct RenameChannel { } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -struct OpenChannelBuffer { +struct OpenChannelNotes { channel_id: u64, } @@ -104,7 +104,7 @@ impl_actions!( ManageMembers, RenameChannel, ToggleCollapse, - OpenChannelBuffer + OpenChannelNotes ] ); @@ -130,7 +130,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(CollabPanel::toggle_channel_collapsed); cx.add_action(CollabPanel::collapse_selected_channel); cx.add_action(CollabPanel::expand_selected_channel); - cx.add_action(CollabPanel::open_channel_buffer); + cx.add_action(CollabPanel::open_channel_notes); } #[derive(Debug)] @@ -226,10 +226,6 @@ enum ListEntry { channel: Arc, depth: usize, }, - ChannelCall { - channel: Arc, - depth: usize, - }, ChannelNotes { channel_id: ChannelId, }, @@ -369,13 +365,6 @@ impl CollabPanel { return channel_row; } } - ListEntry::ChannelCall { channel, depth } => this.render_channel_call( - &*channel, - *depth, - &theme.collab_panel, - is_selected, - cx, - ), ListEntry::ChannelNotes { channel_id } => this.render_channel_notes( *channel_id, &theme.collab_panel, @@ -751,12 +740,6 @@ impl CollabPanel { channel: channel.clone(), depth, }); - if !channel_store.channel_participants(channel.id).is_empty() { - self.entries.push(ListEntry::ChannelCall { - channel: channel.clone(), - depth, - }); - } } } } @@ -1566,10 +1549,23 @@ impl CollabPanel { let disclosed = has_children.then(|| !self.collapsed_channels.binary_search(&channel_id).is_ok()); + let is_active = iife!({ + let call_channel = ActiveCall::global(cx) + .read(cx) + .room()? + .read(cx) + .channel_id()?; + Some(call_channel == channel_id) + }) + .unwrap_or(false); + + const FACEPILE_LIMIT: usize = 3; + enum ChannelCall {} - enum ChannelNotes {} MouseEventHandler::new::(channel.id as usize, cx, |state, cx| { + let row_hovered = state.hovered(); + Flex::::row() .with_child( Svg::new("icons/hash.svg") @@ -1588,29 +1584,49 @@ impl CollabPanel { .flex(1., true), ) .with_child( - MouseEventHandler::new::(channel_id as usize, cx, |_, _| { - Svg::new("icons/radix/speaker-loud.svg") - .with_color(theme.channel_hash.color) - .constrained() - .with_width(theme.channel_hash.width) - .aligned() - .right() - }) + MouseEventHandler::new::( + channel.id as usize, + cx, + move |_, cx| { + let participants = + self.channel_store.read(cx).channel_participants(channel_id); + if !participants.is_empty() { + let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT); + + FacePile::new(theme.face_overlap) + .with_children( + participants + .iter() + .filter_map(|user| { + Some( + Image::from_data(user.avatar.clone()?) + .with_style(theme.channel_avatar), + ) + }) + .take(FACEPILE_LIMIT), + ) + .with_children((extra_count > 0).then(|| { + Label::new( + format!("+{}", extra_count), + theme.extra_participant_label.text.clone(), + ) + .contained() + .with_style(theme.extra_participant_label.container) + })) + .into_any() + } else if row_hovered { + Svg::new("icons/radix/speaker-loud.svg") + .with_color(theme.channel_hash.color) + .constrained() + .with_width(theme.channel_hash.width) + .into_any() + } else { + Empty::new().into_any() + } + }, + ) .on_click(MouseButton::Left, move |_, this, cx| { - this.join_channel_call(channel_id, cx) - }), - ) - .with_child( - MouseEventHandler::new::(channel_id as usize, cx, |_, _| { - Svg::new("icons/radix/file.svg") - .with_color(theme.channel_hash.color) - .constrained() - .with_width(theme.channel_hash.width) - .aligned() - .right() - }) - .on_click(MouseButton::Left, move |_, this, cx| { - this.open_channel_buffer(&OpenChannelBuffer { channel_id }, cx); + this.join_channel_call(channel_id, cx); }), ) .align_children_center() @@ -1622,7 +1638,7 @@ impl CollabPanel { .constrained() .with_height(theme.row_height) .contained() - .with_style(*theme.channel_row.style_for(is_selected, state)) + .with_style(*theme.channel_row.style_for(is_selected || is_active, state)) .with_padding_left( theme.channel_row.default_style().padding.left + theme.channel_indent * depth as f32, @@ -1638,94 +1654,6 @@ impl CollabPanel { .into_any() } - fn render_channel_call( - &self, - channel: &Channel, - depth: usize, - theme: &theme::CollabPanel, - is_selected: bool, - cx: &mut ViewContext, - ) -> AnyElement { - let channel_id = channel.id; - - let is_active = iife!({ - let call_channel = ActiveCall::global(cx) - .read(cx) - .room()? - .read(cx) - .channel_id()?; - Some(call_channel == channel_id) - }) - .unwrap_or(false); - - const FACEPILE_LIMIT: usize = 5; - - enum ChannelCall {} - - let host_avatar_width = theme - .contact_avatar - .width - .or(theme.contact_avatar.height) - .unwrap_or(0.); - - MouseEventHandler::new::(channel.id as usize, cx, |state, cx| { - let participants = self.channel_store.read(cx).channel_participants(channel_id); - let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT); - let tree_branch = *theme.tree_branch.in_state(is_selected).style_for(state); - let row = theme.project_row.in_state(is_selected).style_for(state); - - Flex::::row() - .with_child(render_tree_branch( - tree_branch, - &row.name.text, - true, - vec2f(host_avatar_width, theme.row_height), - cx.font_cache(), - )) - .with_child( - FacePile::new(theme.face_overlap) - .with_children( - participants - .iter() - .filter_map(|user| { - Some( - Image::from_data(user.avatar.clone()?) - .with_style(theme.channel_avatar), - ) - }) - .take(FACEPILE_LIMIT), - ) - .with_children((extra_count > 0).then(|| { - Label::new( - format!("+{}", extra_count), - theme.extra_participant_label.text.clone(), - ) - .contained() - .with_style(theme.extra_participant_label.container) - })), - ) - .align_children_center() - .constrained() - .with_height(theme.row_height) - .aligned() - .left() - .contained() - .with_style(*theme.channel_row.style_for(is_selected || is_active, state)) - .with_padding_left( - theme.channel_row.default_style().padding.left - + theme.channel_indent * (depth + 1) as f32, - ) - }) - .on_click(MouseButton::Left, move |_, this, cx| { - this.join_channel_call(channel_id, cx); - }) - .on_click(MouseButton::Right, move |e, this, cx| { - this.deploy_channel_context_menu(Some(e.position), channel_id, cx); - }) - .with_cursor_style(CursorStyle::PointingHand) - .into_any() - } - fn render_channel_notes( &self, channel_id: ChannelId, @@ -1775,7 +1703,7 @@ impl CollabPanel { .with_padding_left(theme.channel_row.default_style().padding.left) }) .on_click(MouseButton::Left, move |_, this, cx| { - this.open_channel_buffer(&OpenChannelBuffer { channel_id }, cx); + this.open_channel_notes(&OpenChannelNotes { channel_id }, cx); }) .with_cursor_style(CursorStyle::PointingHand) .into_any() @@ -1987,7 +1915,7 @@ impl CollabPanel { let mut items = vec![ ContextMenuItem::action(expand_action_name, ToggleCollapse { channel_id }), - ContextMenuItem::action("Open Notes", OpenChannelBuffer { channel_id }), + ContextMenuItem::action("Open Notes", OpenChannelNotes { channel_id }), ]; if self.channel_store.read(cx).is_user_admin(channel_id) { @@ -2114,9 +2042,6 @@ impl CollabPanel { ListEntry::Channel { channel, .. } => { self.join_channel_chat(channel.id, cx); } - ListEntry::ChannelCall { channel, .. } => { - self.join_channel_call(channel.id, cx); - } ListEntry::ContactPlaceholder => self.toggle_contact_finder(cx), _ => {} } @@ -2325,7 +2250,7 @@ impl CollabPanel { } } - fn open_channel_buffer(&mut self, action: &OpenChannelBuffer, cx: &mut ViewContext) { + fn open_channel_notes(&mut self, action: &OpenChannelNotes, cx: &mut ViewContext) { if let Some(workspace) = self.workspace.upgrade(cx) { let pane = workspace.read(cx).active_pane().clone(); let channel_id = action.channel_id; @@ -2510,7 +2435,9 @@ impl CollabPanel { .detach_and_log_err(cx); } - fn join_channel_chat(&self, channel_id: u64, cx: &mut ViewContext) { + fn join_channel_chat(&mut self, channel_id: u64, cx: &mut ViewContext) { + self.open_channel_notes(&OpenChannelNotes { channel_id }, cx); + if let Some(workspace) = self.workspace.upgrade(cx) { cx.app_context().defer(move |cx| { workspace.update(cx, |workspace, cx| { @@ -2757,18 +2684,6 @@ impl PartialEq for ListEntry { return channel_1.id == channel_2.id && depth_1 == depth_2; } } - ListEntry::ChannelCall { - channel: channel_1, - depth: depth_1, - } => { - if let ListEntry::ChannelCall { - channel: channel_2, - depth: depth_2, - } = other - { - return channel_1.id == channel_2.id && depth_1 == depth_2; - } - } ListEntry::ChannelNotes { channel_id } => { if let ListEntry::ChannelNotes { channel_id: other_id, From f2112b9aad44fab5092d9f640d3617955b470419 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Sep 2023 17:11:33 -0700 Subject: [PATCH 09/38] Rejoin channel chats upon reconnecting --- crates/channel/src/channel_store.rs | 10 +++ .../collab/src/tests/channel_message_tests.rs | 85 ++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/crates/channel/src/channel_store.rs b/crates/channel/src/channel_store.rs index b90a3fdaeb..e61e520b47 100644 --- a/crates/channel/src/channel_store.rs +++ b/crates/channel/src/channel_store.rs @@ -532,6 +532,16 @@ impl ChannelStore { fn handle_connect(&mut self, cx: &mut ModelContext) -> Task> { self.disconnect_channel_buffers_task.take(); + for chat in self.opened_chats.values() { + if let OpenedModelHandle::Open(chat) = chat { + if let Some(chat) = chat.upgrade(cx) { + chat.update(cx, |chat, cx| { + chat.rejoin(cx); + }); + } + } + } + let mut buffer_versions = Vec::new(); for buffer in self.opened_buffers.values() { if let OpenedModelHandle::Open(buffer) = buffer { diff --git a/crates/collab/src/tests/channel_message_tests.rs b/crates/collab/src/tests/channel_message_tests.rs index e7afd136f3..f74416fa7d 100644 --- a/crates/collab/src/tests/channel_message_tests.rs +++ b/crates/collab/src/tests/channel_message_tests.rs @@ -1,5 +1,6 @@ -use crate::tests::TestServer; -use gpui::{executor::Deterministic, TestAppContext}; +use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer}; +use channel::ChannelChat; +use gpui::{executor::Deterministic, ModelHandle, TestAppContext}; use std::sync::Arc; #[gpui::test] @@ -54,3 +55,83 @@ async fn test_basic_channel_messages( ); }) } + +#[gpui::test] +async fn test_rejoin_channel_chat( + deterministic: Arc, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + + let channel_id = server + .make_channel("the-channel", (&client_a, cx_a), &mut [(&client_b, cx_b)]) + .await; + + let channel_chat_a = client_a + .channel_store() + .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + let channel_chat_b = client_b + .channel_store() + .update(cx_b, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + + channel_chat_a + .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap()) + .await + .unwrap(); + channel_chat_b + .update(cx_b, |c, cx| c.send_message("two".into(), cx).unwrap()) + .await + .unwrap(); + + server.forbid_connections(); + server.disconnect_client(client_a.peer_id().unwrap()); + + // While client A is disconnected, clients A and B both send new messages. + channel_chat_a + .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap()) + .await + .unwrap_err(); + channel_chat_a + .update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap()) + .await + .unwrap_err(); + channel_chat_b + .update(cx_b, |c, cx| c.send_message("five".into(), cx).unwrap()) + .await + .unwrap(); + channel_chat_b + .update(cx_b, |c, cx| c.send_message("six".into(), cx).unwrap()) + .await + .unwrap(); + + // Client A reconnects. + server.allow_connections(); + deterministic.advance_clock(RECONNECT_TIMEOUT); + + // Client A fetches the messages that were sent while they were disconnected + // and resends their own messages which failed to send. + let expected_messages = &["one", "two", "five", "six", "three", "four"]; + assert_messages(&channel_chat_a, expected_messages, cx_a); + assert_messages(&channel_chat_b, expected_messages, cx_b); +} + +#[track_caller] +fn assert_messages(chat: &ModelHandle, messages: &[&str], cx: &mut TestAppContext) { + chat.update(cx, |chat, _| { + assert_eq!( + chat.messages() + .iter() + .map(|m| m.body.as_str()) + .collect::>(), + messages + ); + }) +} From 1c50587cad882e7fe751720fd4d7aee1b3dc4740 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Sep 2023 17:37:05 -0700 Subject: [PATCH 10/38] Remove channel chat participant when connection is lost --- crates/collab/src/db/queries/buffers.rs | 23 ++++++++ crates/collab/src/db/queries/messages.rs | 19 ++++++ crates/collab/src/db/queries/rooms.rs | 73 ++++++++++-------------- crates/collab/src/rpc.rs | 3 +- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/crates/collab/src/db/queries/buffers.rs b/crates/collab/src/db/queries/buffers.rs index 00de201403..62ead11932 100644 --- a/crates/collab/src/db/queries/buffers.rs +++ b/crates/collab/src/db/queries/buffers.rs @@ -249,6 +249,29 @@ impl Database { .await } + pub async fn channel_buffer_connection_lost( + &self, + connection: ConnectionId, + tx: &DatabaseTransaction, + ) -> Result<()> { + channel_buffer_collaborator::Entity::update_many() + .filter( + Condition::all() + .add(channel_buffer_collaborator::Column::ConnectionId.eq(connection.id as i32)) + .add( + channel_buffer_collaborator::Column::ConnectionServerId + .eq(connection.owner_id as i32), + ), + ) + .set(channel_buffer_collaborator::ActiveModel { + connection_lost: ActiveValue::set(true), + ..Default::default() + }) + .exec(&*tx) + .await?; + Ok(()) + } + pub async fn leave_channel_buffers( &self, connection: ConnectionId, diff --git a/crates/collab/src/db/queries/messages.rs b/crates/collab/src/db/queries/messages.rs index 4593d8f2f3..60bb245207 100644 --- a/crates/collab/src/db/queries/messages.rs +++ b/crates/collab/src/db/queries/messages.rs @@ -25,6 +25,25 @@ impl Database { .await } + pub async fn channel_chat_connection_lost( + &self, + connection_id: ConnectionId, + tx: &DatabaseTransaction, + ) -> Result<()> { + channel_chat_participant::Entity::delete_many() + .filter( + Condition::all() + .add( + channel_chat_participant::Column::ConnectionServerId + .eq(connection_id.owner_id), + ) + .add(channel_chat_participant::Column::ConnectionId.eq(connection_id.id)), + ) + .exec(tx) + .await?; + Ok(()) + } + pub async fn leave_channel_chat( &self, channel_id: ChannelId, diff --git a/crates/collab/src/db/queries/rooms.rs b/crates/collab/src/db/queries/rooms.rs index e348b50bee..fb81fef176 100644 --- a/crates/collab/src/db/queries/rooms.rs +++ b/crates/collab/src/db/queries/rooms.rs @@ -890,54 +890,43 @@ impl Database { pub async fn connection_lost(&self, connection: ConnectionId) -> Result<()> { self.transaction(|tx| async move { - let participant = room_participant::Entity::find() - .filter( - Condition::all() - .add( - room_participant::Column::AnsweringConnectionId - .eq(connection.id as i32), - ) - .add( - room_participant::Column::AnsweringConnectionServerId - .eq(connection.owner_id as i32), - ), - ) - .one(&*tx) + self.room_connection_lost(connection, &*tx).await?; + self.channel_buffer_connection_lost(connection, &*tx) .await?; - - if let Some(participant) = participant { - room_participant::Entity::update(room_participant::ActiveModel { - answering_connection_lost: ActiveValue::set(true), - ..participant.into_active_model() - }) - .exec(&*tx) - .await?; - } - - channel_buffer_collaborator::Entity::update_many() - .filter( - Condition::all() - .add( - channel_buffer_collaborator::Column::ConnectionId - .eq(connection.id as i32), - ) - .add( - channel_buffer_collaborator::Column::ConnectionServerId - .eq(connection.owner_id as i32), - ), - ) - .set(channel_buffer_collaborator::ActiveModel { - connection_lost: ActiveValue::set(true), - ..Default::default() - }) - .exec(&*tx) - .await?; - + self.channel_chat_connection_lost(connection, &*tx).await?; Ok(()) }) .await } + pub async fn room_connection_lost( + &self, + connection: ConnectionId, + tx: &DatabaseTransaction, + ) -> Result<()> { + let participant = room_participant::Entity::find() + .filter( + Condition::all() + .add(room_participant::Column::AnsweringConnectionId.eq(connection.id as i32)) + .add( + room_participant::Column::AnsweringConnectionServerId + .eq(connection.owner_id as i32), + ), + ) + .one(&*tx) + .await?; + + if let Some(participant) = participant { + room_participant::Entity::update(room_participant::ActiveModel { + answering_connection_lost: ActiveValue::set(true), + ..participant.into_active_model() + }) + .exec(&*tx) + .await?; + } + Ok(()) + } + fn build_incoming_call( room: &proto::Room, called_user_id: UserId, diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index b508c45dc5..5ecd05ae1b 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -904,9 +904,8 @@ async fn connection_lost( room_updated(&room, &session.peer); } } + update_user_contacts(session.user_id, &session).await?; - - } _ = teardown.changed().fuse() => {} } From 06555a423bc91aeecd4efdd801d70db7a8c2ab19 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 14 Sep 2023 13:49:02 -0600 Subject: [PATCH 11/38] vim: g s/S for outline/project symbols --- assets/keymaps/vim.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 1a7b81ee8f..4dffb07dfc 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -125,6 +125,8 @@ "g shift-t": "pane::ActivatePrevItem", "g d": "editor::GoToDefinition", "g shift-d": "editor::GoToTypeDefinition", + "g s": "outline::Toggle", + "g shift-s": "project_symbols::Toggle", "g .": "editor::ToggleCodeActions", // zed specific "g shift-a": "editor::FindAllReferences", // zed specific "g *": [ From 4667110d0f0f921d4127101516414d5aab56d66f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 14 Sep 2023 14:05:02 -0600 Subject: [PATCH 12/38] Fix multi-key shortcuts with modifiers To make this work we need to move the handling of multiple possible key events into the keyboard shortcut system. This was broken in #2957. --- crates/gpui/src/keymap_matcher.rs | 71 ++++++++++++++++----- crates/gpui/src/keymap_matcher/keymap.rs | 12 ++-- crates/gpui/src/keymap_matcher/keystroke.rs | 48 +++++++++++++- crates/gpui/src/platform/mac/event.rs | 1 + crates/gpui/src/platform/mac/window.rs | 40 ++---------- crates/terminal/src/mappings/keys.rs | 1 + crates/vim/src/state.rs | 1 - 7 files changed, 117 insertions(+), 57 deletions(-) diff --git a/crates/gpui/src/keymap_matcher.rs b/crates/gpui/src/keymap_matcher.rs index 8cb7d30dfe..89dd7bfc7d 100644 --- a/crates/gpui/src/keymap_matcher.rs +++ b/crates/gpui/src/keymap_matcher.rs @@ -75,7 +75,6 @@ impl KeymapMatcher { keystroke: Keystroke, mut dispatch_path: Vec<(usize, KeymapContext)>, ) -> MatchResult { - let mut any_pending = false; // Collect matched bindings into an ordered list using the position in the matching binding first, // and then the order the binding matched in the view tree second. // The key is the reverse position of the binding in the bindings list so that later bindings @@ -84,7 +83,8 @@ impl KeymapMatcher { let no_action_id = (NoAction {}).id(); let first_keystroke = self.pending_keystrokes.is_empty(); - self.pending_keystrokes.push(keystroke.clone()); + let mut pending_key = None; + let mut previous_keystrokes = self.pending_keystrokes.clone(); self.contexts.clear(); self.contexts @@ -106,24 +106,32 @@ impl KeymapMatcher { } for binding in self.keymap.bindings().iter().rev() { - match binding.match_keys_and_context(&self.pending_keystrokes, &self.contexts[i..]) - { - BindingMatchResult::Complete(action) => { - if action.id() != no_action_id { - matched_bindings.push((*view_id, action)); + for possibility in keystroke.match_possibilities() { + previous_keystrokes.push(possibility.clone()); + match binding.match_keys_and_context(&previous_keystrokes, &self.contexts[i..]) + { + BindingMatchResult::Complete(action) => { + if action.id() != no_action_id { + matched_bindings.push((*view_id, action)); + } } + BindingMatchResult::Partial => { + if pending_key == None || pending_key == Some(possibility.clone()) { + self.pending_views + .insert(*view_id, self.contexts[i].clone()); + pending_key = Some(possibility) + } + } + _ => {} } - BindingMatchResult::Partial => { - self.pending_views - .insert(*view_id, self.contexts[i].clone()); - any_pending = true; - } - _ => {} + previous_keystrokes.pop(); } } } - if !any_pending { + if pending_key.is_some() { + self.pending_keystrokes.push(pending_key.unwrap()); + } else { self.clear_pending(); } @@ -131,7 +139,7 @@ impl KeymapMatcher { // Collect the sorted matched bindings into the final vec for ease of use // Matched bindings are in order by precedence MatchResult::Matches(matched_bindings) - } else if any_pending { + } else if !self.pending_keystrokes.is_empty() { MatchResult::Pending } else { MatchResult::None @@ -340,6 +348,7 @@ mod tests { shift: false, cmd: false, function: false, + ime_key: None, } ); @@ -352,6 +361,7 @@ mod tests { shift: true, cmd: false, function: false, + ime_key: None, } ); @@ -364,6 +374,7 @@ mod tests { shift: true, cmd: true, function: false, + ime_key: None, } ); @@ -466,7 +477,7 @@ mod tests { #[derive(Clone, Deserialize, PartialEq, Eq, Debug)] pub struct A(pub String); impl_actions!(test, [A]); - actions!(test, [B, Ab]); + actions!(test, [B, Ab, Dollar, Quote, Ess, Backtick]); #[derive(Clone, Debug, Eq, PartialEq)] struct ActionArg { @@ -477,6 +488,10 @@ mod tests { Binding::new("a", A("x".to_string()), Some("a")), Binding::new("b", B, Some("a")), Binding::new("a b", Ab, Some("a || b")), + Binding::new("$", Dollar, Some("a")), + Binding::new("\"", Quote, Some("a")), + Binding::new("alt-s", Ess, Some("a")), + Binding::new("ctrl-`", Backtick, Some("a")), ]); let mut context_a = KeymapContext::default(); @@ -543,6 +558,30 @@ mod tests { MatchResult::Matches(vec![(1, Box::new(Ab))]) ); + // handle Czech $ (option + 4 key) + assert_eq!( + matcher.push_keystroke(Keystroke::parse("alt-ç->$")?, vec![(1, context_a.clone())]), + MatchResult::Matches(vec![(1, Box::new(Dollar))]) + ); + + // handle Brazillian quote (quote key then space key) + assert_eq!( + matcher.push_keystroke(Keystroke::parse("space->\"")?, vec![(1, context_a.clone())]), + MatchResult::Matches(vec![(1, Box::new(Quote))]) + ); + + // handle ctrl+` on a brazillian keyboard + assert_eq!( + matcher.push_keystroke(Keystroke::parse("ctrl-->`")?, vec![(1, context_a.clone())]), + MatchResult::Matches(vec![(1, Box::new(Backtick))]) + ); + + // handle alt-s on a US keyboard + assert_eq!( + matcher.push_keystroke(Keystroke::parse("alt-s->ß")?, vec![(1, context_a.clone())]), + MatchResult::Matches(vec![(1, Box::new(Ess))]) + ); + Ok(()) } } diff --git a/crates/gpui/src/keymap_matcher/keymap.rs b/crates/gpui/src/keymap_matcher/keymap.rs index 7cb95cab3a..6abbf1016f 100644 --- a/crates/gpui/src/keymap_matcher/keymap.rs +++ b/crates/gpui/src/keymap_matcher/keymap.rs @@ -162,7 +162,8 @@ mod tests { shift: false, cmd: false, function: false, - key: "q".to_string() + key: "q".to_string(), + ime_key: None, }], "{keystroke_duplicate_to_1:?} should have the expected keystroke in the keymap" ); @@ -179,7 +180,8 @@ mod tests { shift: false, cmd: false, function: false, - key: "w".to_string() + key: "w".to_string(), + ime_key: None, }, &Keystroke { ctrl: true, @@ -187,7 +189,8 @@ mod tests { shift: false, cmd: false, function: false, - key: "w".to_string() + key: "w".to_string(), + ime_key: None, } ], "{full_duplicate_to_2:?} should have a duplicated keystroke in the keymap" @@ -339,7 +342,8 @@ mod tests { shift: false, cmd: false, function: false, - key: expected_key.to_string() + key: expected_key.to_string(), + ime_key: None, }], "{expected:?} should have the expected keystroke with key '{expected_key}' in the keymap for element {i}" ); diff --git a/crates/gpui/src/keymap_matcher/keystroke.rs b/crates/gpui/src/keymap_matcher/keystroke.rs index 164dea8aba..bc0caddac9 100644 --- a/crates/gpui/src/keymap_matcher/keystroke.rs +++ b/crates/gpui/src/keymap_matcher/keystroke.rs @@ -2,6 +2,7 @@ use std::fmt::Write; use anyhow::anyhow; use serde::Deserialize; +use smallvec::SmallVec; #[derive(Clone, Debug, Eq, PartialEq, Default, Deserialize, Hash)] pub struct Keystroke { @@ -10,10 +11,47 @@ pub struct Keystroke { pub shift: bool, pub cmd: bool, pub function: bool, + /// key is the character printed on the key that was pressed + /// e.g. for option-s, key is "s" pub key: String, + /// ime_key is the character inserted by the IME engine when that key was pressed. + /// e.g. for option-s, ime_key is "ß" + pub ime_key: Option, } impl Keystroke { + // When matching a key we cannot know whether the user intended to type + // the ime_key or the key. On some non-US keyboards keys we use in our + // bindings are behind option (for example `$` is typed `alt-ç` on a Czech keyboard), + // and on some keyboards the IME handler converts a sequence of keys into a + // specific character (for example `"` is typed as `" space` on a brazillian keyboard). + pub fn match_possibilities(&self) -> SmallVec<[Keystroke; 2]> { + let mut possibilities = SmallVec::new(); + match self.ime_key.as_ref() { + None => possibilities.push(self.clone()), + Some(ime_key) => { + possibilities.push(Keystroke { + ctrl: self.ctrl, + alt: false, + shift: false, + cmd: false, + function: false, + key: ime_key.to_string(), + ime_key: None, + }); + possibilities.push(Keystroke { + ime_key: None, + ..self.clone() + }); + } + } + possibilities + } + + /// key syntax is: + /// [ctrl-][alt-][shift-][cmd-][fn-]key[->ime_key] + /// ime_key is only used for generating test events, + /// when matching a key with an ime_key set will be matched without it. pub fn parse(source: &str) -> anyhow::Result { let mut ctrl = false; let mut alt = false; @@ -21,6 +59,7 @@ impl Keystroke { let mut cmd = false; let mut function = false; let mut key = None; + let mut ime_key = None; let mut components = source.split('-').peekable(); while let Some(component) = components.next() { @@ -31,10 +70,14 @@ impl Keystroke { "cmd" => cmd = true, "fn" => function = true, _ => { - if let Some(component) = components.peek() { - if component.is_empty() && source.ends_with('-') { + if let Some(next) = components.peek() { + if next.is_empty() && source.ends_with('-') { key = Some(String::from("-")); break; + } else if next.len() > 1 && next.starts_with('>') { + key = Some(String::from(component)); + ime_key = Some(String::from(&next[1..])); + components.next(); } else { return Err(anyhow!("Invalid keystroke `{}`", source)); } @@ -54,6 +97,7 @@ impl Keystroke { cmd, function, key, + ime_key, }) } diff --git a/crates/gpui/src/platform/mac/event.rs b/crates/gpui/src/platform/mac/event.rs index 7710834f53..c19d7abe4f 100644 --- a/crates/gpui/src/platform/mac/event.rs +++ b/crates/gpui/src/platform/mac/event.rs @@ -327,6 +327,7 @@ unsafe fn parse_keystroke(native_event: id) -> Keystroke { cmd, function, key, + ime_key: None, } } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index ba8c7a6963..ad8275f0ac 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -285,6 +285,7 @@ enum ImeState { None, } +#[derive(Debug)] struct InsertText { replacement_range: Option>, text: String, @@ -1006,40 +1007,7 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: .flatten() .is_some(); if !is_composing { - // if the IME has changed the key, we'll first emit an event with the character - // generated by the IME system; then fallback to the keystroke if that is not - // handled. - // cases that we have working: - // - " on a brazillian layout by typing - // - ctrl-` on a brazillian layout by typing - // - $ on a czech QWERTY layout by typing - // - 4 on a czech QWERTY layout by typing - // - ctrl-4 on a czech QWERTY layout by typing (or ) - if ime_text.is_some() && ime_text.as_ref() != Some(&event.keystroke.key) { - let event_with_ime_text = KeyDownEvent { - is_held: false, - keystroke: Keystroke { - // we match ctrl because some use-cases need it. - // we don't match alt because it's often used to generate the optional character - // we don't match shift because we're not here with letters (usually) - // we don't match cmd/fn because they don't seem to use IME - ctrl: event.keystroke.ctrl, - alt: false, - shift: false, - cmd: false, - function: false, - key: ime_text.clone().unwrap(), - }, - }; - handled = callback(Event::KeyDown(event_with_ime_text)); - } - if !handled { - // empty key happens when you type a deadkey in input composition. - // (e.g. on a brazillian keyboard typing quote is a deadkey) - if !event.keystroke.key.is_empty() { - handled = callback(Event::KeyDown(event)); - } - } + handled = callback(Event::KeyDown(event)); } if !handled { @@ -1197,6 +1165,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) { shift: false, function: false, key: ".".into(), + ime_key: None, }; let event = Event::KeyDown(KeyDownEvent { keystroke: keystroke.clone(), @@ -1479,6 +1448,9 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS replacement_range, text: text.to_string(), }); + if text.to_string().to_ascii_lowercase() != pending_key_down.0.keystroke.key { + pending_key_down.0.keystroke.ime_key = Some(text.to_string()); + } window_state.borrow_mut().pending_key_down = Some(pending_key_down); } } diff --git a/crates/terminal/src/mappings/keys.rs b/crates/terminal/src/mappings/keys.rs index 9d19625971..b933fd48e9 100644 --- a/crates/terminal/src/mappings/keys.rs +++ b/crates/terminal/src/mappings/keys.rs @@ -333,6 +333,7 @@ mod test { cmd: false, function: false, key: "🖖🏻".to_string(), //2 char string + ime_key: None, }; assert_eq!(to_esc_str(&ks, &TermMode::NONE, false), None); } diff --git a/crates/vim/src/state.rs b/crates/vim/src/state.rs index 2cb5e058e8..8fd4049767 100644 --- a/crates/vim/src/state.rs +++ b/crates/vim/src/state.rs @@ -186,7 +186,6 @@ impl EditorState { if self.active_operator().is_none() && self.pre_count.is_some() || self.active_operator().is_some() && self.post_count.is_some() { - dbg!("VimCount"); context.add_identifier("VimCount"); } From 89327eb84e42bcf9749413a59f8be21c2b0e88b5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Sep 2023 15:16:08 -0700 Subject: [PATCH 13/38] Start styling the chat panel --- styles/src/style_tree/chat_panel.ts | 90 +++++++++++------------------ 1 file changed, 34 insertions(+), 56 deletions(-) diff --git a/styles/src/style_tree/chat_panel.ts b/styles/src/style_tree/chat_panel.ts index 735c3b54dd..53559911e7 100644 --- a/styles/src/style_tree/chat_panel.ts +++ b/styles/src/style_tree/chat_panel.ts @@ -1,53 +1,21 @@ import { background, border, - border_color, - foreground, text, } from "./components" -import { interactive, toggleable } from "../element" import { useTheme } from "../theme" -import collab_modals from "./collab_modals" -import { icon_button, toggleable_icon_button } from "../component/icon_button" -import { indicator } from "../component/indicator" -export default function contacts_panel(): any { +export default function chat_panel(): any { const theme = useTheme() - - const CHANNEL_SPACING = 4 as const - const NAME_MARGIN = 6 as const - const SPACING = 12 as const - const INDENT_SIZE = 8 as const - const ITEM_HEIGHT = 28 as const - const layer = theme.middle - const input_editor = { - background: background(layer, "on"), - corner_radius: 6, - text: text(layer, "sans", "base"), - placeholder_text: text(layer, "sans", "base", "disabled", { - size: "xs", - }), - selection: theme.players[0], - border: border(layer, "on"), - padding: { - bottom: 4, - left: 8, - right: 8, - top: 4, - }, - margin: { - left: SPACING, - right: SPACING, - }, - } + const SPACING = 12 as const const channel_name = { padding: { - top: 4, + // top: 4, bottom: 4, - left: 4, + // left: 4, right: 4, }, hash: { @@ -58,8 +26,14 @@ export default function contacts_panel(): any { return { background: background(layer), + padding: { + top: SPACING, + bottom: SPACING, + left: SPACING, + right: SPACING, + }, channel_select: { - header: channel_name, + header: { ...channel_name }, item: channel_name, active_item: channel_name, hovered_item: channel_name, @@ -71,24 +45,38 @@ export default function contacts_panel(): any { } } }, - input_editor, + input_editor: { + background: background(layer, "on"), + corner_radius: 6, + text: text(layer, "sans", "base"), + placeholder_text: text(layer, "sans", "base", "disabled", { + size: "xs", + }), + selection: theme.players[0], + border: border(layer, "on"), + padding: { + bottom: 4, + left: 8, + right: 8, + top: 4, + }, + }, message: { body: text(layer, "sans", "base"), sender: { - padding: { - left: 4, - right: 4, + margin: { + right: 8, }, - ...text(layer, "sans", "base", "disabled"), + ...text(layer, "sans", "base", { weight: "bold" }), }, - timestamp: text(layer, "sans", "base"), + timestamp: text(layer, "sans", "base", "disabled"), + margin: { bottom: SPACING } }, pending_message: { body: text(layer, "sans", "base"), sender: { - padding: { - left: 4, - right: 4, + margin: { + right: 8, }, ...text(layer, "sans", "base", "disabled"), }, @@ -96,16 +84,6 @@ export default function contacts_panel(): any { }, sign_in_prompt: { default: text(layer, "sans", "base"), - }, - timestamp: { - body: text(layer, "sans", "base"), - sender: { - padding: { - left: 4, - right: 4, - }, - ...text(layer, "sans", "base", "disabled"), - } } } } From 59269d422b246ecf20fa7f8d6417bc371f117250 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Sep 2023 16:22:21 -0700 Subject: [PATCH 14/38] Allow deleting chat messages --- crates/channel/src/channel_chat.rs | 46 +++++++++ crates/collab/src/db/queries/messages.rs | 40 ++++++++ crates/collab/src/rpc.rs | 20 ++++ .../collab/src/tests/channel_message_tests.rs | 97 +++++++++++++++++-- crates/collab_ui/src/chat_panel.rs | 76 ++++++++++++--- crates/rpc/proto/zed.proto | 8 +- crates/rpc/src/proto.rs | 3 + 7 files changed, 266 insertions(+), 24 deletions(-) diff --git a/crates/channel/src/channel_chat.rs b/crates/channel/src/channel_chat.rs index f821e2ed8e..8e03a3b6fd 100644 --- a/crates/channel/src/channel_chat.rs +++ b/crates/channel/src/channel_chat.rs @@ -59,6 +59,7 @@ pub enum ChannelChatEvent { pub fn init(client: &Arc) { client.add_model_message_handler(ChannelChat::handle_message_sent); + client.add_model_message_handler(ChannelChat::handle_message_removed); } impl Entity for ChannelChat { @@ -166,6 +167,21 @@ impl ChannelChat { })) } + pub fn remove_message(&mut self, id: u64, cx: &mut ModelContext) -> Task> { + let response = self.rpc.request(proto::RemoveChannelMessage { + channel_id: self.channel.id, + message_id: id, + }); + cx.spawn(|this, mut cx| async move { + response.await?; + + this.update(&mut cx, |this, cx| { + this.message_removed(id, cx); + Ok(()) + }) + }) + } + pub fn load_more_messages(&mut self, cx: &mut ModelContext) -> bool { if !self.loaded_all_messages { let rpc = self.rpc.clone(); @@ -306,6 +322,18 @@ impl ChannelChat { Ok(()) } + async fn handle_message_removed( + this: ModelHandle, + message: TypedEnvelope, + _: Arc, + mut cx: AsyncAppContext, + ) -> Result<()> { + this.update(&mut cx, |this, cx| { + this.message_removed(message.payload.message_id, cx) + }); + Ok(()) + } + fn insert_messages(&mut self, messages: SumTree, cx: &mut ModelContext) { if let Some((first_message, last_message)) = messages.first().zip(messages.last()) { let nonces = messages @@ -363,6 +391,24 @@ impl ChannelChat { cx.notify(); } } + + fn message_removed(&mut self, id: u64, cx: &mut ModelContext) { + let mut cursor = self.messages.cursor::(); + let mut messages = cursor.slice(&ChannelMessageId::Saved(id), Bias::Left, &()); + if let Some(item) = cursor.item() { + if item.id == ChannelMessageId::Saved(id) { + let ix = messages.summary().count; + cursor.next(&()); + messages.append(cursor.suffix(&()), &()); + drop(cursor); + self.messages = messages; + cx.emit(ChannelChatEvent::MessagesUpdated { + old_range: ix..ix + 1, + new_count: 0, + }); + } + } + } } async fn messages_from_proto( diff --git a/crates/collab/src/db/queries/messages.rs b/crates/collab/src/db/queries/messages.rs index 60bb245207..0b88df6716 100644 --- a/crates/collab/src/db/queries/messages.rs +++ b/crates/collab/src/db/queries/messages.rs @@ -171,4 +171,44 @@ impl Database { }) .await } + + pub async fn remove_channel_message( + &self, + channel_id: ChannelId, + message_id: MessageId, + user_id: UserId, + ) -> Result> { + self.transaction(|tx| async move { + let mut rows = channel_chat_participant::Entity::find() + .filter(channel_chat_participant::Column::ChannelId.eq(channel_id)) + .stream(&*tx) + .await?; + + let mut is_participant = false; + let mut participant_connection_ids = Vec::new(); + while let Some(row) = rows.next().await { + let row = row?; + if row.user_id == user_id { + is_participant = true; + } + participant_connection_ids.push(row.connection()); + } + drop(rows); + + if !is_participant { + Err(anyhow!("not a chat participant"))?; + } + + let result = channel_message::Entity::delete_by_id(message_id) + .filter(channel_message::Column::SenderId.eq(user_id)) + .exec(&*tx) + .await?; + if result.rows_affected == 0 { + Err(anyhow!("no such message"))?; + } + + Ok(participant_connection_ids) + }) + .await + } } diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 549b98376f..3289daf6ca 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -265,6 +265,7 @@ impl Server { .add_request_handler(join_channel_chat) .add_message_handler(leave_channel_chat) .add_request_handler(send_channel_message) + .add_request_handler(remove_channel_message) .add_request_handler(get_channel_messages) .add_request_handler(follow) .add_message_handler(unfollow) @@ -2696,6 +2697,25 @@ async fn send_channel_message( Ok(()) } +async fn remove_channel_message( + request: proto::RemoveChannelMessage, + response: Response, + session: Session, +) -> Result<()> { + let channel_id = ChannelId::from_proto(request.channel_id); + let message_id = MessageId::from_proto(request.message_id); + let connection_ids = session + .db() + .await + .remove_channel_message(channel_id, message_id, session.user_id) + .await?; + broadcast(Some(session.connection_id), connection_ids, |connection| { + session.peer.send(connection, request.clone()) + }); + response.send(proto::Ack {})?; + Ok(()) +} + async fn join_channel_chat( request: proto::JoinChannelChat, response: Response, diff --git a/crates/collab/src/tests/channel_message_tests.rs b/crates/collab/src/tests/channel_message_tests.rs index f74416fa7d..1a9460c6cf 100644 --- a/crates/collab/src/tests/channel_message_tests.rs +++ b/crates/collab/src/tests/channel_message_tests.rs @@ -1,5 +1,5 @@ use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer}; -use channel::ChannelChat; +use channel::{ChannelChat, ChannelMessageId}; use gpui::{executor::Deterministic, ModelHandle, TestAppContext}; use std::sync::Arc; @@ -123,15 +123,92 @@ async fn test_rejoin_channel_chat( assert_messages(&channel_chat_b, expected_messages, cx_b); } +#[gpui::test] +async fn test_remove_channel_message( + deterministic: Arc, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, + cx_c: &mut TestAppContext, +) { + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + let client_c = server.create_client(cx_c, "user_c").await; + + let channel_id = server + .make_channel( + "the-channel", + (&client_a, cx_a), + &mut [(&client_b, cx_b), (&client_c, cx_c)], + ) + .await; + + let channel_chat_a = client_a + .channel_store() + .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + let channel_chat_b = client_b + .channel_store() + .update(cx_b, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + + // Client A sends some messages. + channel_chat_a + .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap()) + .await + .unwrap(); + channel_chat_a + .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap()) + .await + .unwrap(); + channel_chat_a + .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap()) + .await + .unwrap(); + + // Clients A and B see all of the messages. + deterministic.run_until_parked(); + let expected_messages = &["one", "two", "three"]; + assert_messages(&channel_chat_a, expected_messages, cx_a); + assert_messages(&channel_chat_b, expected_messages, cx_b); + + // Client A deletes one of their messages. + channel_chat_a + .update(cx_a, |c, cx| { + let ChannelMessageId::Saved(id) = c.message(1).id else { + panic!("message not saved") + }; + c.remove_message(id, cx) + }) + .await + .unwrap(); + + // Client B sees that the message is gone. + deterministic.run_until_parked(); + let expected_messages = &["one", "three"]; + assert_messages(&channel_chat_a, expected_messages, cx_a); + assert_messages(&channel_chat_b, expected_messages, cx_b); + + // Client C joins the channel chat, and does not see the deleted message. + let channel_chat_c = client_c + .channel_store() + .update(cx_c, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); + assert_messages(&channel_chat_c, expected_messages, cx_c); +} + #[track_caller] fn assert_messages(chat: &ModelHandle, messages: &[&str], cx: &mut TestAppContext) { - chat.update(cx, |chat, _| { - assert_eq!( - chat.messages() - .iter() - .map(|m| m.body.as_str()) - .collect::>(), - messages - ); - }) + assert_eq!( + chat.read_with(cx, |chat, _| chat + .messages() + .iter() + .map(|m| m.body.clone()) + .collect::>(),), + messages + ); } diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index ba0d196e8d..bbd6094d03 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -1,6 +1,6 @@ use crate::ChatPanelSettings; use anyhow::Result; -use channel::{ChannelChat, ChannelChatEvent, ChannelMessage, ChannelStore}; +use channel::{ChannelChat, ChannelChatEvent, ChannelMessageId, ChannelStore}; use client::Client; use db::kvp::KEY_VALUE_STORE; use editor::Editor; @@ -19,7 +19,7 @@ use project::Fs; use serde::{Deserialize, Serialize}; use settings::SettingsStore; use std::sync::Arc; -use theme::Theme; +use theme::{IconButton, Theme}; use time::{OffsetDateTime, UtcOffset}; use util::{ResultExt, TryFutureExt}; use workspace::{ @@ -105,8 +105,7 @@ impl ChatPanel { let mut message_list = ListState::::new(0, Orientation::Bottom, 1000., move |this, ix, cx| { - let message = this.active_chat.as_ref().unwrap().0.read(cx).message(ix); - this.render_message(message, cx) + this.render_message(ix, cx) }); message_list.set_scroll_handler(|visible_range, this, cx| { if visible_range.start < MESSAGE_LOADING_THRESHOLD { @@ -285,38 +284,70 @@ impl ChatPanel { messages.flex(1., true).into_any() } - fn render_message(&self, message: &ChannelMessage, cx: &AppContext) -> AnyElement { + fn render_message(&self, ix: usize, cx: &mut ViewContext) -> AnyElement { + let message = self.active_chat.as_ref().unwrap().0.read(cx).message(ix); + let now = OffsetDateTime::now_utc(); let theme = theme::current(cx); - let theme = if message.is_pending() { + let style = if message.is_pending() { &theme.chat_panel.pending_message } else { &theme.chat_panel.message }; + let belongs_to_user = Some(message.sender.id) == self.client.user_id(); + let message_id_to_remove = + if let (ChannelMessageId::Saved(id), true) = (message.id, belongs_to_user) { + Some(id) + } else { + None + }; + + enum DeleteMessage {} + + let body = message.body.clone(); Flex::column() .with_child( Flex::row() .with_child( Label::new( message.sender.github_login.clone(), - theme.sender.text.clone(), + style.sender.text.clone(), ) .contained() - .with_style(theme.sender.container), + .with_style(style.sender.container), ) .with_child( Label::new( format_timestamp(message.timestamp, now, self.local_timezone), - theme.timestamp.text.clone(), + style.timestamp.text.clone(), ) .contained() - .with_style(theme.timestamp.container), - ), + .with_style(style.timestamp.container), + ) + .with_children(message_id_to_remove.map(|id| { + MouseEventHandler::new::( + id as usize, + cx, + |mouse_state, _| { + let button_style = + theme.collab_panel.contact_button.style_for(mouse_state); + render_icon_button(button_style, "icons/x.svg") + .aligned() + .into_any() + }, + ) + .with_padding(Padding::uniform(2.)) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, this, cx| { + this.remove_message(id, cx); + }) + .flex_float() + })), ) - .with_child(Text::new(message.body.clone(), theme.body.clone())) + .with_child(Text::new(body, style.body.clone())) .contained() - .with_style(theme.container) + .with_style(style.container) .into_any() } @@ -413,6 +444,12 @@ impl ChatPanel { } } + fn remove_message(&mut self, id: u64, cx: &mut ViewContext) { + if let Some((chat, _)) = self.active_chat.as_ref() { + chat.update(cx, |chat, cx| chat.remove_message(id, cx).detach()) + } + } + fn load_more_messages(&mut self, _: &LoadMoreMessages, cx: &mut ViewContext) { if let Some((chat, _)) = self.active_chat.as_ref() { chat.update(cx, |channel, cx| { @@ -551,3 +588,16 @@ fn format_timestamp( format!("{:02}/{}/{}", date.month() as u32, date.day(), date.year()) } } + +fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element { + Svg::new(svg_path) + .with_color(style.color) + .constrained() + .with_width(style.icon_width) + .aligned() + .constrained() + .with_width(style.button_width) + .with_height(style.button_width) + .contained() + .with_style(style.container) +} diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index eb26e81b99..855588a2d8 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -164,7 +164,8 @@ message Envelope { SendChannelMessageResponse send_channel_message_response = 146; ChannelMessageSent channel_message_sent = 147; GetChannelMessages get_channel_messages = 148; - GetChannelMessagesResponse get_channel_messages_response = 149; // Current max + GetChannelMessagesResponse get_channel_messages_response = 149; + RemoveChannelMessage remove_channel_message = 150; // Current max } } @@ -1049,6 +1050,11 @@ message SendChannelMessage { Nonce nonce = 3; } +message RemoveChannelMessage { + uint64 channel_id = 1; + uint64 message_id = 2; +} + message SendChannelMessageResponse { ChannelMessage message = 1; } diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 7b98f50e75..240daed1b2 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -217,6 +217,7 @@ messages!( (RejoinRoomResponse, Foreground), (RemoveContact, Foreground), (RemoveChannelMember, Foreground), + (RemoveChannelMessage, Foreground), (ReloadBuffers, Foreground), (ReloadBuffersResponse, Foreground), (RemoveProjectCollaborator, Foreground), @@ -327,6 +328,7 @@ request_messages!( (GetChannelMembers, GetChannelMembersResponse), (JoinChannel, JoinRoomResponse), (RemoveChannel, Ack), + (RemoveChannelMessage, Ack), (RenameProjectEntry, ProjectEntryResponse), (RenameChannel, ChannelResponse), (SaveBuffer, BufferSaved), @@ -402,6 +404,7 @@ entity_messages!( ChannelMessageSent, UpdateChannelBuffer, RemoveChannelBufferCollaborator, + RemoveChannelMessage, AddChannelBufferCollaborator, UpdateChannelBufferCollaborator ); From dd7c68704111e7d09ecaeac87df4a082b0293c58 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Sep 2023 17:19:08 -0700 Subject: [PATCH 15/38] Style the chat panel further --- crates/collab_ui/src/chat_panel.rs | 13 +++++--- crates/gpui/src/views/select.rs | 6 +++- crates/theme/src/theme.rs | 1 + styles/src/style_tree/chat_panel.ts | 47 +++++++++++++++++++---------- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index bbd6094d03..afd293422f 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -97,7 +97,7 @@ impl ChatPanel { .with_style(move |cx| { let style = &theme::current(cx).chat_panel.channel_select; SelectStyle { - header: style.header.container, + header: Default::default(), menu: style.menu, } }) @@ -269,14 +269,17 @@ impl ChatPanel { .contained() .with_style(theme.chat_panel.channel_select.container), ) - .with_child(self.render_active_channel_messages()) + .with_child(self.render_active_channel_messages(&theme)) .with_child(self.render_input_box(&theme, cx)) .into_any() } - fn render_active_channel_messages(&self) -> AnyElement { + fn render_active_channel_messages(&self, theme: &Arc) -> AnyElement { let messages = if self.active_chat.is_some() { - List::new(self.message_list.clone()).into_any() + List::new(self.message_list.clone()) + .contained() + .with_style(theme.chat_panel.list) + .into_any() } else { Empty::new().into_any() }; @@ -381,6 +384,8 @@ impl ChatPanel { .with_style(theme.hash.container), ) .with_child(Label::new(channel.name.clone(), theme.name.clone())) + .aligned() + .left() .contained() .with_style(theme.container) .into_any() diff --git a/crates/gpui/src/views/select.rs b/crates/gpui/src/views/select.rs index 0de535f837..0d57630c24 100644 --- a/crates/gpui/src/views/select.rs +++ b/crates/gpui/src/views/select.rs @@ -1,5 +1,7 @@ use crate::{ - elements::*, platform::MouseButton, AppContext, Entity, View, ViewContext, WeakViewHandle, + elements::*, + platform::{CursorStyle, MouseButton}, + AppContext, Entity, View, ViewContext, WeakViewHandle, }; pub struct Select { @@ -102,6 +104,7 @@ impl View for Select { .contained() .with_style(style.header) }) + .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, this, cx| { this.toggle(cx); }), @@ -128,6 +131,7 @@ impl View for Select { cx, ) }) + .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, this, cx| { this.set_selected_index(ix, cx); }) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index a845db3ba4..613c88d5cc 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -629,6 +629,7 @@ pub struct IconButton { pub struct ChatPanel { #[serde(flatten)] pub container: ContainerStyle, + pub list: ContainerStyle, pub channel_select: ChannelSelect, pub input_editor: FieldEditor, pub message: ChatMessage, diff --git a/styles/src/style_tree/chat_panel.ts b/styles/src/style_tree/chat_panel.ts index 53559911e7..d0e5d3c249 100644 --- a/styles/src/style_tree/chat_panel.ts +++ b/styles/src/style_tree/chat_panel.ts @@ -13,10 +13,10 @@ export default function chat_panel(): any { const channel_name = { padding: { - // top: 4, + left: SPACING, + right: SPACING, + top: 4, bottom: 4, - // left: 4, - right: 4, }, hash: { ...text(layer, "sans", "base"), @@ -26,23 +26,33 @@ export default function chat_panel(): any { return { background: background(layer), - padding: { - top: SPACING, - bottom: SPACING, - left: SPACING, - right: SPACING, + list: { + margin: { + left: SPACING, + right: SPACING, + } }, channel_select: { - header: { ...channel_name }, + header: { + ...channel_name, + border: border(layer, { bottom: true }) + }, item: channel_name, - active_item: channel_name, - hovered_item: channel_name, - hovered_active_item: channel_name, + active_item: { + ...channel_name, + background: background(layer, "on", "active"), + }, + hovered_item: { + ...channel_name, + background: background(layer, "on", "hovered"), + }, + hovered_active_item: { + ...channel_name, + background: background(layer, "on", "active"), + }, menu: { - padding: { - top: 10, - bottom: 10, - } + background: background(layer, "on"), + border: border(layer, { bottom: true }) } }, input_editor: { @@ -54,6 +64,11 @@ export default function chat_panel(): any { }), selection: theme.players[0], border: border(layer, "on"), + margin: { + left: SPACING, + right: SPACING, + bottom: SPACING, + }, padding: { bottom: 4, left: 8, From b75971196fc481daed108111e2be4227c54e457a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Sep 2023 18:05:44 -0700 Subject: [PATCH 16/38] Add buttons for opening channel notes and joining call, in chat panel header --- crates/collab_ui/src/channel_view.rs | 25 +++++++++ crates/collab_ui/src/chat_panel.rs | 82 +++++++++++++++++++++------- crates/collab_ui/src/collab_panel.rs | 26 +-------- crates/gpui/src/views/select.rs | 6 +- crates/theme/src/theme.rs | 2 +- styles/src/style_tree/chat_panel.ts | 10 ++-- 6 files changed, 100 insertions(+), 51 deletions(-) diff --git a/crates/collab_ui/src/channel_view.rs b/crates/collab_ui/src/channel_view.rs index 8bcfad68b3..c6f32cecd2 100644 --- a/crates/collab_ui/src/channel_view.rs +++ b/crates/collab_ui/src/channel_view.rs @@ -1,4 +1,5 @@ use anyhow::{anyhow, Result}; +use call::ActiveCall; use channel::{ChannelBuffer, ChannelBufferEvent, ChannelId}; use client::proto; use clock::ReplicaId; @@ -35,6 +36,30 @@ pub struct ChannelView { } impl ChannelView { + pub fn deploy(channel_id: ChannelId, workspace: ViewHandle, cx: &mut AppContext) { + let pane = workspace.read(cx).active_pane().clone(); + let channel_view = Self::open(channel_id, pane.clone(), workspace.clone(), cx); + cx.spawn(|mut cx| async move { + let channel_view = channel_view.await?; + pane.update(&mut cx, |pane, cx| { + let room_id = ActiveCall::global(cx) + .read(cx) + .room() + .map(|room| room.read(cx).id()); + ActiveCall::report_call_event_for_room( + "open channel notes", + room_id, + Some(channel_id), + &workspace.read(cx).app_state().client, + cx, + ); + pane.add_item(Box::new(channel_view), true, true, None, cx); + }); + anyhow::Ok(()) + }) + .detach(); + } + pub fn open( channel_id: ChannelId, pane: ViewHandle, diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index afd293422f..8e4148bd9b 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -1,5 +1,6 @@ -use crate::ChatPanelSettings; +use crate::{channel_view::ChannelView, ChatPanelSettings}; use anyhow::Result; +use call::ActiveCall; use channel::{ChannelChat, ChannelChatEvent, ChannelMessageId, ChannelStore}; use client::Client; use db::kvp::KEY_VALUE_STORE; @@ -80,8 +81,11 @@ impl ChatPanel { editor }); + let workspace_handle = workspace.weak_handle(); + let channel_select = cx.add_view(|cx| { let channel_store = channel_store.clone(); + let workspace = workspace_handle.clone(); Select::new(0, cx, { move |ix, item_type, is_hovered, cx| { Self::render_channel_name( @@ -89,7 +93,8 @@ impl ChatPanel { ix, item_type, is_hovered, - &theme::current(cx).chat_panel.channel_select, + &theme::current(cx).chat_panel, + workspace, cx, ) } @@ -334,7 +339,7 @@ impl ChatPanel { cx, |mouse_state, _| { let button_style = - theme.collab_panel.contact_button.style_for(mouse_state); + theme.chat_panel.icon_button.style_for(mouse_state); render_icon_button(button_style, "icons/x.svg") .aligned() .into_any() @@ -366,28 +371,62 @@ impl ChatPanel { ix: usize, item_type: ItemType, is_hovered: bool, - theme: &theme::ChannelSelect, - cx: &AppContext, + theme: &theme::ChatPanel, + workspace: WeakViewHandle, + cx: &mut ViewContext { + enum ChannelNotes {} + enum JoinCall {} + let channel = &channel_store.read(cx).channel_at_index(ix).unwrap().1; - let theme = match (item_type, is_hovered) { - (ItemType::Header, _) => &theme.header, - (ItemType::Selected, false) => &theme.active_item, - (ItemType::Selected, true) => &theme.hovered_active_item, - (ItemType::Unselected, false) => &theme.item, - (ItemType::Unselected, true) => &theme.hovered_item, + let channel_id = channel.id; + let style = &theme.channel_select; + let style = match (&item_type, is_hovered) { + (ItemType::Header, _) => &style.header, + (ItemType::Selected, _) => &style.active_item, + (ItemType::Unselected, false) => &style.item, + (ItemType::Unselected, true) => &style.hovered_item, }; - Flex::row() + let mut row = Flex::row() .with_child( - Label::new("#".to_string(), theme.hash.text.clone()) + Label::new("#".to_string(), style.hash.text.clone()) .contained() - .with_style(theme.hash.container), + .with_style(style.hash.container), ) - .with_child(Label::new(channel.name.clone(), theme.name.clone())) - .aligned() - .left() + .with_child(Label::new(channel.name.clone(), style.name.clone())); + + if matches!(item_type, ItemType::Header) { + row.add_children([ + MouseEventHandler::new::(0, cx, |mouse_state, _| { + render_icon_button( + theme.icon_button.style_for(mouse_state), + "icons/radix/file.svg", + ) + }) + .on_click(MouseButton::Left, move |_, _, cx| { + if let Some(workspace) = workspace.upgrade(cx) { + ChannelView::deploy(channel_id, workspace, cx); + } + }) + .flex_float(), + MouseEventHandler::new::(0, cx, |mouse_state, _| { + render_icon_button( + theme.icon_button.style_for(mouse_state), + "icons/radix/speaker-loud.svg", + ) + }) + .on_click(MouseButton::Left, move |_, _, cx| { + ActiveCall::global(cx) + .update(cx, |call, cx| call.join_channel(channel_id, cx)) + .detach_and_log_err(cx); + }) + .flex_float(), + ]); + } + + row.align_children_center() .contained() - .with_style(theme.container) + .with_style(style.container) .into_any() } @@ -511,6 +550,7 @@ impl View for ChatPanel { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + self.has_focus = true; if matches!( *self.client.status().borrow(), client::Status::Connected { .. } @@ -518,6 +558,10 @@ impl View for ChatPanel { cx.focus(&self.input_editor); } } + + fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext) { + self.has_focus = false; + } } impl Panel for ChatPanel { @@ -594,7 +638,7 @@ fn format_timestamp( } } -fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element { +fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element { Svg::new(svg_path) .with_color(style.color) .constrained() diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index ad1c2a0037..437eaad3fe 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -2252,29 +2252,7 @@ impl CollabPanel { fn open_channel_notes(&mut self, action: &OpenChannelNotes, cx: &mut ViewContext) { if let Some(workspace) = self.workspace.upgrade(cx) { - let pane = workspace.read(cx).active_pane().clone(); - let channel_id = action.channel_id; - let channel_view = ChannelView::open(channel_id, pane.clone(), workspace, cx); - cx.spawn(|_, mut cx| async move { - let channel_view = channel_view.await?; - pane.update(&mut cx, |pane, cx| { - pane.add_item(Box::new(channel_view), true, true, None, cx) - }); - anyhow::Ok(()) - }) - .detach(); - let room_id = ActiveCall::global(cx) - .read(cx) - .room() - .map(|room| room.read(cx).id()); - - ActiveCall::report_call_event_for_room( - "open channel notes", - room_id, - Some(channel_id), - &self.client, - cx, - ); + ChannelView::deploy(action.channel_id, workspace, cx); } } @@ -2436,8 +2414,6 @@ impl CollabPanel { } fn join_channel_chat(&mut self, channel_id: u64, cx: &mut ViewContext) { - self.open_channel_notes(&OpenChannelNotes { channel_id }, cx); - if let Some(workspace) = self.workspace.upgrade(cx) { cx.app_context().defer(move |cx| { workspace.update(cx, |workspace, cx| { diff --git a/crates/gpui/src/views/select.rs b/crates/gpui/src/views/select.rs index 0d57630c24..bad65ccfc8 100644 --- a/crates/gpui/src/views/select.rs +++ b/crates/gpui/src/views/select.rs @@ -6,7 +6,7 @@ use crate::{ pub struct Select { handle: WeakViewHandle, - render_item: Box AnyElement>, + render_item: Box) -> AnyElement>, selected_item_ix: usize, item_count: usize, is_open: bool, @@ -29,7 +29,9 @@ pub enum ItemType { pub enum Event {} impl Select { - pub fn new AnyElement>( + pub fn new< + F: 'static + Fn(usize, ItemType, bool, &mut ViewContext) -> AnyElement, + >( item_count: usize, cx: &mut ViewContext, render_item: F, diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 613c88d5cc..5ea5ce8778 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -635,6 +635,7 @@ pub struct ChatPanel { pub message: ChatMessage, pub pending_message: ChatMessage, pub sign_in_prompt: Interactive, + pub icon_button: Interactive, } #[derive(Deserialize, Default, JsonSchema)] @@ -654,7 +655,6 @@ pub struct ChannelSelect { pub item: ChannelName, pub active_item: ChannelName, pub hovered_item: ChannelName, - pub hovered_active_item: ChannelName, pub menu: ContainerStyle, } diff --git a/styles/src/style_tree/chat_panel.ts b/styles/src/style_tree/chat_panel.ts index d0e5d3c249..9efa084456 100644 --- a/styles/src/style_tree/chat_panel.ts +++ b/styles/src/style_tree/chat_panel.ts @@ -3,6 +3,7 @@ import { border, text, } from "./components" +import { icon_button } from "../component/icon_button" import { useTheme } from "../theme" export default function chat_panel(): any { @@ -46,15 +47,16 @@ export default function chat_panel(): any { ...channel_name, background: background(layer, "on", "hovered"), }, - hovered_active_item: { - ...channel_name, - background: background(layer, "on", "active"), - }, menu: { background: background(layer, "on"), border: border(layer, { bottom: true }) } }, + icon_button: icon_button({ + variant: "ghost", + color: "variant", + size: "sm", + }), input_editor: { background: background(layer, "on"), corner_radius: 6, From 6ce672fb325dd56eb19b487eb10fd42e075b7523 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Sep 2023 18:38:37 -0700 Subject: [PATCH 17/38] Add tooltips and actions for opening notes+call from chat No keyboard shortcut yet. --- crates/collab_ui/src/chat_panel.rs | 66 ++++++++++++++++++++++------ crates/collab_ui/src/collab_panel.rs | 12 +++-- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index 8e4148bd9b..be2dbf811c 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -43,6 +43,7 @@ pub struct ChatPanel { width: Option, pending_serialization: Task>, subscriptions: Vec, + workspace: WeakViewHandle, has_focus: bool, } @@ -58,11 +59,16 @@ pub enum Event { Dismissed, } -actions!(chat_panel, [LoadMoreMessages, ToggleFocus]); +actions!( + chat_panel, + [LoadMoreMessages, ToggleFocus, OpenChannelNotes, JoinCall] +); pub fn init(cx: &mut AppContext) { cx.add_action(ChatPanel::send); cx.add_action(ChatPanel::load_more_messages); + cx.add_action(ChatPanel::open_notes); + cx.add_action(ChatPanel::join_call); } impl ChatPanel { @@ -93,7 +99,6 @@ impl ChatPanel { ix, item_type, is_hovered, - &theme::current(cx).chat_panel, workspace, cx, ) @@ -131,6 +136,7 @@ impl ChatPanel { local_timezone: cx.platform().local_timezone(), has_focus: false, subscriptions: Vec::new(), + workspace: workspace_handle, width: None, }; @@ -371,22 +377,22 @@ impl ChatPanel { ix: usize, item_type: ItemType, is_hovered: bool, - theme: &theme::ChatPanel, workspace: WeakViewHandle, cx: &mut ViewContext { - enum ChannelNotes {} - enum JoinCall {} + let theme = theme::current(cx); + let tooltip_style = &theme.tooltip; + let theme = &theme.chat_panel; + let style = match (&item_type, is_hovered) { + (ItemType::Header, _) => &theme.channel_select.header, + (ItemType::Selected, _) => &theme.channel_select.active_item, + (ItemType::Unselected, false) => &theme.channel_select.item, + (ItemType::Unselected, true) => &theme.channel_select.hovered_item, + }; let channel = &channel_store.read(cx).channel_at_index(ix).unwrap().1; let channel_id = channel.id; - let style = &theme.channel_select; - let style = match (&item_type, is_hovered) { - (ItemType::Header, _) => &style.header, - (ItemType::Selected, _) => &style.active_item, - (ItemType::Unselected, false) => &style.item, - (ItemType::Unselected, true) => &style.hovered_item, - }; + let mut row = Flex::row() .with_child( Label::new("#".to_string(), style.hash.text.clone()) @@ -397,7 +403,7 @@ impl ChatPanel { if matches!(item_type, ItemType::Header) { row.add_children([ - MouseEventHandler::new::(0, cx, |mouse_state, _| { + MouseEventHandler::new::(0, cx, |mouse_state, _| { render_icon_button( theme.icon_button.style_for(mouse_state), "icons/radix/file.svg", @@ -408,8 +414,15 @@ impl ChatPanel { ChannelView::deploy(channel_id, workspace, cx); } }) + .with_tooltip::( + channel_id as usize, + "Open Notes", + Some(Box::new(OpenChannelNotes)), + tooltip_style.clone(), + cx, + ) .flex_float(), - MouseEventHandler::new::(0, cx, |mouse_state, _| { + MouseEventHandler::new::(0, cx, |mouse_state, _| { render_icon_button( theme.icon_button.style_for(mouse_state), "icons/radix/speaker-loud.svg", @@ -420,6 +433,13 @@ impl ChatPanel { .update(cx, |call, cx| call.join_channel(channel_id, cx)) .detach_and_log_err(cx); }) + .with_tooltip::( + channel_id as usize, + "Join Call", + Some(Box::new(JoinCall)), + tooltip_style.clone(), + cx, + ) .flex_float(), ]); } @@ -523,6 +543,24 @@ impl ChatPanel { }) }) } + + fn open_notes(&mut self, _: &OpenChannelNotes, cx: &mut ViewContext) { + if let Some((chat, _)) = &self.active_chat { + let channel_id = chat.read(cx).channel().id; + if let Some(workspace) = self.workspace.upgrade(cx) { + ChannelView::deploy(channel_id, workspace, cx); + } + } + } + + fn join_call(&mut self, _: &JoinCall, cx: &mut ViewContext) { + if let Some((chat, _)) = &self.active_chat { + let channel_id = chat.read(cx).channel().id; + ActiveCall::global(cx) + .update(cx, |call, cx| call.join_channel(channel_id, cx)) + .detach_and_log_err(cx); + } + } } impl Entity for ChatPanel { diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 437eaad3fe..d5189b5e4d 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -80,8 +80,13 @@ struct RenameChannel { } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -struct OpenChannelNotes { - channel_id: u64, +pub struct OpenChannelNotes { + pub channel_id: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct JoinChannelCall { + pub channel_id: u64, } actions!( @@ -104,7 +109,8 @@ impl_actions!( ManageMembers, RenameChannel, ToggleCollapse, - OpenChannelNotes + OpenChannelNotes, + JoinChannelCall, ] ); From 492e961e820d090cdb99b012cd071598aafe8e78 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Sep 2023 18:39:31 -0700 Subject: [PATCH 18/38] Bump protocol version --- crates/rpc/src/rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index d64cbae929..a1393f56e9 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -6,4 +6,4 @@ pub use conn::Connection; pub use peer::*; mod macros; -pub const PROTOCOL_VERSION: u32 = 62; +pub const PROTOCOL_VERSION: u32 = 63; From f4e40b3411e8a01b97c03d169a80f1b00f809ee6 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 15 Sep 2023 11:17:02 -0400 Subject: [PATCH 19/38] Ignore .idea directory I'm testing RustRover --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 15a0a9f5f2..2d8807a4b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea **/target **/cargo-target /zed.xcworkspace From 3e01d78a8078eb30eeb3dc6cc63b4e5b0c369043 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 15 Sep 2023 10:24:12 -0600 Subject: [PATCH 20/38] Make cargo test -p gpui work --- crates/gpui/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 705feb351d..95b7ccb559 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -67,6 +67,7 @@ dhat = "0.3" env_logger.workspace = true png = "0.16" simplelog = "0.9" +util = { path = "../util", features = ["test-support"] } [target.'cfg(target_os = "macos")'.dependencies] media = { path = "../media" } From 9ef7004383265c1564795878c29d2718520880ad Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 15 Sep 2023 10:26:43 -0600 Subject: [PATCH 21/38] Add shift-d and shift-x as aliases for d and x in visual mode --- assets/keymaps/vim.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 4dffb07dfc..44dbf2533f 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -452,6 +452,8 @@ "shift-o": "vim::OtherEnd", "d": "vim::VisualDelete", "x": "vim::VisualDelete", + "shift-d": "vim::VisualDelete", + "shift-x": "vim::VisualDelete", "y": "vim::VisualYank", "p": "vim::Paste", "shift-p": [ From 24974ee2faa3272cca1dc350362d12e82984806b Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Sep 2023 12:50:49 -0400 Subject: [PATCH 22/38] Unify icons using multiple variants, remove all unused icons --- assets/icons/Icons/exit.svg | 3 - assets/icons/arrow_down_12.svg | 10 --- assets/icons/arrow_down_16.svg | 3 - assets/icons/arrow_down_8.svg | 10 --- assets/icons/arrow_left_12.svg | 10 --- assets/icons/arrow_left_16.svg | 3 - assets/icons/arrow_left_8.svg | 10 --- assets/icons/arrow_right_12.svg | 10 --- assets/icons/arrow_right_16.svg | 3 - assets/icons/arrow_right_8.svg | 10 --- assets/icons/arrow_up_12.svg | 10 --- assets/icons/arrow_up_16.svg | 3 - assets/icons/arrow_up_8.svg | 10 --- ...rrow_up_right_8.svg => arrow_up_right.svg} | 0 assets/icons/assist_15.svg | 1 - assets/icons/backspace _12.svg | 3 - assets/icons/backspace _16.svg | 3 - assets/icons/backspace _8.svg | 3 - assets/icons/{bolt_8.svg => bolt.svg} | 0 assets/icons/bolt_12.svg | 3 - assets/icons/bolt_16.svg | 3 - assets/icons/bolt_slash_12.svg | 10 --- assets/icons/bolt_slash_16.svg | 3 - assets/icons/bolt_slash_8.svg | 10 --- .../{radix/caret-down.svg => caret_down.svg} | 0 assets/icons/caret_down_12.svg | 3 - assets/icons/caret_down_16.svg | 3 - assets/icons/caret_down_8.svg | 10 --- assets/icons/caret_left_12.svg | 3 - assets/icons/caret_left_16.svg | 3 - assets/icons/caret_left_8.svg | 10 --- assets/icons/caret_right_12.svg | 3 - assets/icons/caret_right_16.svg | 3 - assets/icons/caret_right_8.svg | 10 --- .../{radix/caret-up.svg => caret_up.svg} | 0 assets/icons/caret_up_12.svg | 3 - assets/icons/caret_up_16.svg | 3 - assets/icons/caret_up_8.svg | 10 --- ...nsensitive_12.svg => case_insensitive.svg} | 0 assets/icons/channel_hash.svg | 6 -- assets/icons/check_12.svg | 3 - assets/icons/check_16.svg | 3 - assets/icons/check_8.svg | 3 - assets/icons/chevron_down_12.svg | 3 - assets/icons/chevron_down_16.svg | 3 - assets/icons/chevron_down_8.svg | 3 - assets/icons/chevron_left_12.svg | 3 - assets/icons/chevron_left_16.svg | 3 - assets/icons/chevron_left_8.svg | 3 - assets/icons/chevron_right_12.svg | 3 - assets/icons/chevron_right_16.svg | 3 - assets/icons/chevron_right_8.svg | 3 - assets/icons/chevron_up_12.svg | 3 - assets/icons/chevron_up_16.svg | 3 - assets/icons/chevron_up_8.svg | 3 - .../{circle_check_16.svg => circle_check.svg} | 0 assets/icons/circle_check_12.svg | 10 --- assets/icons/circle_check_8.svg | 10 --- assets/icons/circle_info_12.svg | 10 --- assets/icons/circle_info_16.svg | 3 - assets/icons/circle_info_8.svg | 10 --- assets/icons/circle_up_12.svg | 10 --- assets/icons/circle_up_16.svg | 3 - assets/icons/circle_up_8.svg | 10 --- assets/icons/circle_x_mark_12.svg | 10 --- assets/icons/circle_x_mark_16.svg | 3 - assets/icons/circle_x_mark_8.svg | 10 --- assets/icons/cloud_12.svg | 3 - assets/icons/cloud_8.svg | 3 - assets/icons/cloud_slash_8.svg | 10 --- assets/icons/copilot_16.svg | 12 --- ...t_disabled_16.svg => copilot_disabled.svg} | 0 ...copilot_error_16.svg => copilot_error.svg} | 0 .../{copilot_init_16.svg => copilot_init.svg} | 0 assets/icons/copy.svg | 5 -- assets/icons/delete_12.svg | 3 - assets/icons/delete_16.svg | 3 - assets/icons/delete_8.svg | 3 - assets/icons/{radix => }/desktop.svg | 0 assets/icons/disable_screen_sharing_12.svg | 3 - .../{cloud_slash_12.svg => disconnected.svg} | 0 assets/icons/dock_bottom_12.svg | 11 --- assets/icons/dock_bottom_8.svg | 11 --- assets/icons/dock_modal_12.svg | 11 --- assets/icons/dock_modal_8.svg | 11 --- assets/icons/dock_right_12.svg | 11 --- assets/icons/dock_right_8.svg | 11 --- .../icons/{download_12.svg => download.svg} | 0 assets/icons/download_8.svg | 10 --- assets/icons/ellipsis_14.svg | 3 - assets/icons/enable_screen_sharing_12.svg | 3 - assets/icons/exit.svg | 10 ++- .../{link_out_12.svg => external_link.svg} | 0 assets/icons/feedback_16.svg | 3 - assets/icons/{radix => }/file.svg | 0 assets/icons/file_12.svg | 4 - assets/icons/file_16.svg | 4 - assets/icons/file_8.svg | 4 - assets/icons/filter_12.svg | 3 - assets/icons/filter_14.svg | 6 -- assets/icons/folder_tree_12.svg | 10 --- assets/icons/folder_tree_16.svg | 3 - assets/icons/folder_tree_8.svg | 10 --- assets/icons/git_diff_12.svg | 10 --- assets/icons/git_diff_8.svg | 10 --- assets/icons/github-copilot-dummy.svg | 1 - assets/icons/html.svg | 5 -- assets/icons/kebab.svg | 5 -- assets/icons/leave_12.svg | 3 - assets/icons/lock.svg | 6 -- assets/icons/lock_8.svg | 3 - assets/icons/logo_96.svg | 3 - assets/icons/{radix => }/magic-wand.svg | 0 assets/icons/magnifying_glass_12.svg | 10 --- assets/icons/magnifying_glass_16.svg | 3 - assets/icons/magnifying_glass_8.svg | 10 --- assets/icons/match_case.svg | 5 -- assets/icons/match_word.svg | 5 -- assets/icons/maximize.svg | 6 +- assets/icons/maximize_8.svg | 10 --- assets/icons/{hamburger_15.svg => menu.svg} | 0 assets/icons/{radix => }/mic-mute.svg | 0 assets/icons/{radix => }/mic.svg | 0 assets/icons/microphone.svg | 5 -- assets/icons/minimize.svg | 6 +- assets/icons/minimize_8.svg | 10 --- assets/icons/plus.svg | 9 ++- assets/icons/plus_12.svg | 10 --- assets/icons/plus_16.svg | 10 --- assets/icons/plus_8.svg | 10 --- assets/icons/{radix => }/quote.svg | 0 assets/icons/quote_15.svg | 1 - assets/icons/radix/accessibility.svg | 8 -- assets/icons/radix/activity-log.svg | 8 -- assets/icons/radix/align-baseline.svg | 8 -- assets/icons/radix/align-bottom.svg | 8 -- .../icons/radix/align-center-horizontally.svg | 8 -- .../icons/radix/align-center-vertically.svg | 8 -- assets/icons/radix/align-center.svg | 8 -- assets/icons/radix/align-end.svg | 8 -- .../icons/radix/align-horizontal-centers.svg | 8 -- assets/icons/radix/align-left.svg | 8 -- assets/icons/radix/align-right.svg | 8 -- assets/icons/radix/align-start.svg | 8 -- assets/icons/radix/align-stretch.svg | 8 -- assets/icons/radix/align-top.svg | 8 -- assets/icons/radix/align-vertical-centers.svg | 8 -- assets/icons/radix/all-sides.svg | 8 -- assets/icons/radix/angle.svg | 8 -- assets/icons/radix/archive.svg | 8 -- assets/icons/radix/arrow-bottom-left.svg | 8 -- assets/icons/radix/arrow-bottom-right.svg | 8 -- assets/icons/radix/arrow-down.svg | 8 -- assets/icons/radix/arrow-left.svg | 8 -- assets/icons/radix/arrow-right.svg | 8 -- assets/icons/radix/arrow-top-left.svg | 8 -- assets/icons/radix/arrow-top-right.svg | 8 -- assets/icons/radix/arrow-up.svg | 8 -- assets/icons/radix/aspect-ratio.svg | 8 -- assets/icons/radix/avatar.svg | 8 -- assets/icons/radix/backpack.svg | 8 -- assets/icons/radix/badge.svg | 8 -- assets/icons/radix/bar-chart.svg | 8 -- assets/icons/radix/bell.svg | 8 -- assets/icons/radix/blending-mode.svg | 8 -- assets/icons/radix/bookmark-filled.svg | 8 -- assets/icons/radix/bookmark.svg | 8 -- assets/icons/radix/border-all.svg | 17 ---- assets/icons/radix/border-bottom.svg | 29 ------- assets/icons/radix/border-dashed.svg | 8 -- assets/icons/radix/border-dotted.svg | 8 -- assets/icons/radix/border-left.svg | 29 ------- assets/icons/radix/border-none.svg | 35 --------- assets/icons/radix/border-right.svg | 29 ------- assets/icons/radix/border-solid.svg | 8 -- assets/icons/radix/border-split.svg | 21 ----- assets/icons/radix/border-style.svg | 8 -- assets/icons/radix/border-top.svg | 29 ------- assets/icons/radix/border-width.svg | 8 -- assets/icons/radix/box-model.svg | 8 -- assets/icons/radix/box.svg | 8 -- assets/icons/radix/button.svg | 8 -- assets/icons/radix/calendar.svg | 8 -- assets/icons/radix/camera.svg | 8 -- assets/icons/radix/card-stack-minus.svg | 8 -- assets/icons/radix/card-stack-plus.svg | 8 -- assets/icons/radix/card-stack.svg | 8 -- assets/icons/radix/caret-left.svg | 8 -- assets/icons/radix/caret-right.svg | 8 -- assets/icons/radix/caret-sort.svg | 8 -- assets/icons/radix/chat-bubble.svg | 8 -- assets/icons/radix/check-circled.svg | 8 -- assets/icons/radix/check.svg | 8 -- assets/icons/radix/checkbox.svg | 8 -- assets/icons/radix/chevron-down.svg | 8 -- assets/icons/radix/chevron-left.svg | 8 -- assets/icons/radix/chevron-right.svg | 8 -- assets/icons/radix/chevron-up.svg | 8 -- assets/icons/radix/circle-backslash.svg | 8 -- assets/icons/radix/circle.svg | 8 -- assets/icons/radix/clipboard-copy.svg | 8 -- assets/icons/radix/clipboard.svg | 8 -- assets/icons/radix/clock.svg | 8 -- assets/icons/radix/code.svg | 8 -- assets/icons/radix/codesandbox-logo.svg | 8 -- assets/icons/radix/color-wheel.svg | 8 -- assets/icons/radix/column-spacing.svg | 8 -- assets/icons/radix/columns.svg | 8 -- assets/icons/radix/commit.svg | 8 -- assets/icons/radix/component-1.svg | 8 -- assets/icons/radix/component-2.svg | 8 -- assets/icons/radix/component-boolean.svg | 8 -- assets/icons/radix/component-instance.svg | 8 -- assets/icons/radix/component-none.svg | 8 -- assets/icons/radix/component-placeholder.svg | 12 --- assets/icons/radix/container.svg | 8 -- assets/icons/radix/cookie.svg | 8 -- assets/icons/radix/copy.svg | 8 -- assets/icons/radix/corner-bottom-left.svg | 8 -- assets/icons/radix/corner-bottom-right.svg | 8 -- assets/icons/radix/corner-top-left.svg | 8 -- assets/icons/radix/corner-top-right.svg | 8 -- assets/icons/radix/corners.svg | 8 -- assets/icons/radix/countdown-timer.svg | 8 -- .../icons/radix/counter-clockwise-clock.svg | 8 -- assets/icons/radix/crop.svg | 8 -- assets/icons/radix/cross-1.svg | 8 -- assets/icons/radix/cross-2.svg | 8 -- assets/icons/radix/cross-circled.svg | 8 -- assets/icons/radix/crosshair-1.svg | 8 -- assets/icons/radix/crosshair-2.svg | 8 -- assets/icons/radix/crumpled-paper.svg | 8 -- assets/icons/radix/cube.svg | 8 -- assets/icons/radix/cursor-arrow.svg | 8 -- assets/icons/radix/cursor-text.svg | 8 -- assets/icons/radix/dash.svg | 8 -- assets/icons/radix/dashboard.svg | 8 -- assets/icons/radix/desktop-mute.svg | 4 - assets/icons/radix/dimensions.svg | 8 -- assets/icons/radix/disc.svg | 8 -- assets/icons/radix/discord-logo.svg | 13 ---- assets/icons/radix/divider-horizontal.svg | 8 -- assets/icons/radix/divider-vertical.svg | 8 -- assets/icons/radix/dot-filled.svg | 6 -- assets/icons/radix/dot-solid.svg | 6 -- assets/icons/radix/dot.svg | 8 -- assets/icons/radix/dots-horizontal.svg | 8 -- assets/icons/radix/dots-vertical.svg | 8 -- assets/icons/radix/double-arrow-down.svg | 8 -- assets/icons/radix/double-arrow-left.svg | 8 -- assets/icons/radix/double-arrow-right.svg | 8 -- assets/icons/radix/double-arrow-up.svg | 8 -- assets/icons/radix/download.svg | 8 -- assets/icons/radix/drag-handle-dots-1.svg | 26 ------- assets/icons/radix/drag-handle-dots-2.svg | 8 -- assets/icons/radix/drag-handle-horizontal.svg | 8 -- assets/icons/radix/drag-handle-vertical.svg | 8 -- assets/icons/radix/drawing-pin-filled.svg | 14 ---- assets/icons/radix/drawing-pin-solid.svg | 14 ---- assets/icons/radix/drawing-pin.svg | 8 -- assets/icons/radix/dropdown-menu.svg | 8 -- assets/icons/radix/enter-full-screen.svg | 8 -- assets/icons/radix/enter.svg | 8 -- assets/icons/radix/envelope-closed.svg | 8 -- assets/icons/radix/envelope-open.svg | 8 -- assets/icons/radix/eraser.svg | 8 -- assets/icons/radix/exclamation-triangle.svg | 8 -- assets/icons/radix/exit-full-screen.svg | 8 -- assets/icons/radix/exit.svg | 8 -- assets/icons/radix/external-link.svg | 8 -- assets/icons/radix/eye-closed.svg | 8 -- assets/icons/radix/eye-none.svg | 8 -- assets/icons/radix/eye-open.svg | 8 -- assets/icons/radix/face.svg | 8 -- assets/icons/radix/figma-logo.svg | 8 -- assets/icons/radix/file-minus.svg | 8 -- assets/icons/radix/file-plus.svg | 8 -- assets/icons/radix/file-text.svg | 8 -- assets/icons/radix/font-bold.svg | 6 -- assets/icons/radix/font-family.svg | 6 -- assets/icons/radix/font-italic.svg | 8 -- assets/icons/radix/font-roman.svg | 8 -- assets/icons/radix/font-size.svg | 8 -- assets/icons/radix/font-style.svg | 8 -- assets/icons/radix/frame.svg | 8 -- assets/icons/radix/framer-logo.svg | 8 -- assets/icons/radix/gear.svg | 8 -- assets/icons/radix/github-logo.svg | 8 -- assets/icons/radix/globe.svg | 26 ------- assets/icons/radix/grid.svg | 8 -- assets/icons/radix/group.svg | 8 -- assets/icons/radix/half-1.svg | 8 -- assets/icons/radix/half-2.svg | 8 -- assets/icons/radix/hamburger-menu.svg | 8 -- assets/icons/radix/hand.svg | 8 -- assets/icons/radix/heading.svg | 8 -- assets/icons/radix/heart-filled.svg | 8 -- assets/icons/radix/heart.svg | 8 -- assets/icons/radix/height.svg | 8 -- assets/icons/radix/hobby-knife.svg | 8 -- assets/icons/radix/home.svg | 8 -- assets/icons/radix/iconjar-logo.svg | 8 -- assets/icons/radix/id-card.svg | 8 -- assets/icons/radix/image.svg | 8 -- assets/icons/radix/info-circled.svg | 8 -- assets/icons/radix/inner-shadow.svg | 78 ------------------- assets/icons/radix/input.svg | 8 -- assets/icons/radix/instagram-logo.svg | 8 -- assets/icons/radix/justify-center.svg | 8 -- assets/icons/radix/justify-end.svg | 8 -- assets/icons/radix/justify-start.svg | 8 -- assets/icons/radix/justify-stretch.svg | 8 -- assets/icons/radix/keyboard.svg | 7 -- assets/icons/radix/lap-timer.svg | 8 -- assets/icons/radix/laptop.svg | 8 -- assets/icons/radix/layers.svg | 8 -- assets/icons/radix/layout.svg | 8 -- assets/icons/radix/letter-case-capitalize.svg | 8 -- assets/icons/radix/letter-case-lowercase.svg | 8 -- assets/icons/radix/letter-case-toggle.svg | 8 -- assets/icons/radix/letter-case-uppercase.svg | 8 -- assets/icons/radix/letter-spacing.svg | 8 -- assets/icons/radix/lightning-bolt.svg | 8 -- assets/icons/radix/line-height.svg | 8 -- assets/icons/radix/link-1.svg | 8 -- assets/icons/radix/link-2.svg | 8 -- assets/icons/radix/link-break-1.svg | 8 -- assets/icons/radix/link-break-2.svg | 8 -- assets/icons/radix/link-none-1.svg | 8 -- assets/icons/radix/link-none-2.svg | 8 -- assets/icons/radix/linkedin-logo.svg | 8 -- assets/icons/radix/list-bullet.svg | 8 -- assets/icons/radix/lock-closed.svg | 8 -- assets/icons/radix/lock-open-1.svg | 8 -- assets/icons/radix/lock-open-2.svg | 8 -- assets/icons/radix/loop.svg | 8 -- assets/icons/radix/magnifying-glass.svg | 8 -- assets/icons/radix/margin.svg | 8 -- assets/icons/radix/mask-off.svg | 8 -- assets/icons/radix/mask-on.svg | 8 -- assets/icons/radix/maximize.svg | 4 - assets/icons/radix/minimize.svg | 4 - assets/icons/radix/minus-circled.svg | 8 -- assets/icons/radix/minus.svg | 8 -- assets/icons/radix/mix.svg | 8 -- assets/icons/radix/mixer-horizontal.svg | 8 -- assets/icons/radix/mixer-vertical.svg | 8 -- assets/icons/radix/mobile.svg | 8 -- assets/icons/radix/modulz-logo.svg | 8 -- assets/icons/radix/moon.svg | 8 -- assets/icons/radix/move.svg | 8 -- assets/icons/radix/notion-logo.svg | 6 -- assets/icons/radix/opacity.svg | 8 -- assets/icons/radix/open-in-new-window.svg | 10 --- assets/icons/radix/outer-shadow.svg | 43 ---------- assets/icons/radix/overline.svg | 8 -- assets/icons/radix/padding.svg | 8 -- assets/icons/radix/paper-plane.svg | 8 -- assets/icons/radix/pause.svg | 8 -- assets/icons/radix/pencil-1.svg | 8 -- assets/icons/radix/pencil-2.svg | 8 -- assets/icons/radix/person.svg | 8 -- assets/icons/radix/pie-chart.svg | 8 -- assets/icons/radix/pilcrow.svg | 8 -- assets/icons/radix/pin-bottom.svg | 8 -- assets/icons/radix/pin-left.svg | 8 -- assets/icons/radix/pin-right.svg | 8 -- assets/icons/radix/pin-top.svg | 8 -- assets/icons/radix/play.svg | 8 -- assets/icons/radix/plus-circled.svg | 8 -- assets/icons/radix/plus.svg | 8 -- assets/icons/radix/question-mark-circled.svg | 8 -- assets/icons/radix/question-mark.svg | 8 -- assets/icons/radix/radiobutton.svg | 8 -- assets/icons/radix/reader.svg | 8 -- assets/icons/radix/reload.svg | 8 -- assets/icons/radix/reset.svg | 8 -- assets/icons/radix/resume.svg | 8 -- assets/icons/radix/rocket.svg | 8 -- .../icons/radix/rotate-counter-clockwise.svg | 8 -- assets/icons/radix/row-spacing.svg | 8 -- assets/icons/radix/rows.svg | 8 -- assets/icons/radix/ruler-horizontal.svg | 8 -- assets/icons/radix/ruler-square.svg | 8 -- assets/icons/radix/scissors.svg | 8 -- assets/icons/radix/section.svg | 8 -- assets/icons/radix/sewing-pin-filled.svg | 8 -- assets/icons/radix/sewing-pin-solid.svg | 8 -- assets/icons/radix/sewing-pin.svg | 8 -- assets/icons/radix/shadow-inner.svg | 78 ------------------- assets/icons/radix/shadow-none.svg | 78 ------------------- assets/icons/radix/shadow-outer.svg | 43 ---------- assets/icons/radix/shadow.svg | 78 ------------------- assets/icons/radix/share-1.svg | 8 -- assets/icons/radix/share-2.svg | 8 -- assets/icons/radix/shuffle.svg | 8 -- assets/icons/radix/size.svg | 8 -- assets/icons/radix/sketch-logo.svg | 8 -- assets/icons/radix/slash.svg | 8 -- assets/icons/radix/slider.svg | 8 -- .../radix/space-between-horizontally.svg | 8 -- .../icons/radix/space-between-vertically.svg | 8 -- .../icons/radix/space-evenly-horizontally.svg | 8 -- .../icons/radix/space-evenly-vertically.svg | 8 -- assets/icons/radix/speaker-moderate.svg | 8 -- assets/icons/radix/speaker-quiet.svg | 8 -- assets/icons/radix/square.svg | 8 -- assets/icons/radix/stack.svg | 8 -- assets/icons/radix/star-filled.svg | 6 -- assets/icons/radix/star.svg | 8 -- assets/icons/radix/stitches-logo.svg | 8 -- assets/icons/radix/stop.svg | 8 -- assets/icons/radix/stopwatch.svg | 8 -- assets/icons/radix/stretch-horizontally.svg | 8 -- assets/icons/radix/stretch-vertically.svg | 8 -- assets/icons/radix/strikethrough.svg | 8 -- assets/icons/radix/sun.svg | 8 -- assets/icons/radix/switch.svg | 8 -- assets/icons/radix/symbol.svg | 8 -- assets/icons/radix/table.svg | 8 -- assets/icons/radix/target.svg | 8 -- assets/icons/radix/text-align-bottom.svg | 8 -- assets/icons/radix/text-align-center.svg | 8 -- assets/icons/radix/text-align-justify.svg | 8 -- assets/icons/radix/text-align-left.svg | 8 -- assets/icons/radix/text-align-middle.svg | 8 -- assets/icons/radix/text-align-right.svg | 8 -- assets/icons/radix/text-align-top.svg | 8 -- assets/icons/radix/text-none.svg | 8 -- assets/icons/radix/text.svg | 8 -- assets/icons/radix/thick-arrow-down.svg | 8 -- assets/icons/radix/thick-arrow-left.svg | 8 -- assets/icons/radix/thick-arrow-right.svg | 8 -- assets/icons/radix/thick-arrow-up.svg | 8 -- assets/icons/radix/timer.svg | 8 -- assets/icons/radix/tokens.svg | 8 -- assets/icons/radix/track-next.svg | 8 -- assets/icons/radix/track-previous.svg | 8 -- assets/icons/radix/transform.svg | 8 -- assets/icons/radix/transparency-grid.svg | 9 --- assets/icons/radix/trash.svg | 8 -- assets/icons/radix/triangle-down.svg | 3 - assets/icons/radix/triangle-left.svg | 3 - assets/icons/radix/triangle-right.svg | 3 - assets/icons/radix/triangle-up.svg | 3 - assets/icons/radix/twitter-logo.svg | 8 -- assets/icons/radix/underline.svg | 8 -- assets/icons/radix/update.svg | 8 -- assets/icons/radix/upload.svg | 8 -- assets/icons/radix/value-none.svg | 8 -- assets/icons/radix/value.svg | 8 -- assets/icons/radix/vercel-logo.svg | 8 -- assets/icons/radix/video.svg | 8 -- assets/icons/radix/view-grid.svg | 8 -- assets/icons/radix/view-horizontal.svg | 8 -- assets/icons/radix/view-none.svg | 8 -- assets/icons/radix/view-vertical.svg | 8 -- assets/icons/radix/width.svg | 8 -- assets/icons/radix/zoom-in.svg | 8 -- assets/icons/radix/zoom-out.svg | 8 -- assets/icons/robot_14.svg | 4 - assets/icons/screen.svg | 4 - assets/icons/{radix => }/speaker-loud.svg | 0 assets/icons/{radix => }/speaker-off.svg | 0 assets/icons/speech_bubble_12.svg | 3 - assets/icons/split_12.svg | 12 --- ...split_message_15.svg => split_message.svg} | 0 assets/icons/stop_sharing.svg | 5 -- assets/icons/success.svg | 4 - assets/icons/terminal_12.svg | 10 --- assets/icons/terminal_16.svg | 3 - assets/icons/terminal_8.svg | 10 --- assets/icons/triangle_exclamation_12.svg | 10 --- assets/icons/triangle_exclamation_16.svg | 3 - assets/icons/triangle_exclamation_8.svg | 10 --- assets/icons/unlock_8.svg | 10 --- assets/icons/user_circle_12.svg | 10 --- assets/icons/user_circle_8.svg | 10 --- assets/icons/user_group_12.svg | 3 - assets/icons/user_group_16.svg | 3 - assets/icons/user_group_8.svg | 10 --- assets/icons/user_plus_12.svg | 5 -- assets/icons/user_plus_16.svg | 5 -- assets/icons/user_plus_8.svg | 10 --- assets/icons/version_control_branch_12.svg | 3 - .../{word_search_14.svg => word_search.svg} | 0 assets/icons/word_search_12.svg | 8 -- assets/icons/x_mark_12.svg | 10 --- assets/icons/x_mark_16.svg | 10 --- assets/icons/x_mark_8.svg | 10 --- ..._plus_copilot_32.svg => zed_x_copilot.svg} | 0 .../src/activity_indicator.rs | 4 +- crates/ai/src/assistant.rs | 4 +- crates/auto_update/src/update_notification.rs | 2 +- crates/collab_ui/src/collab_panel.rs | 4 +- .../src/collab_panel/contact_finder.rs | 2 +- crates/collab_ui/src/collab_titlebar_item.rs | 18 ++--- crates/collab_ui/src/notifications.rs | 2 +- crates/copilot_button/src/copilot_button.rs | 8 +- crates/diagnostics/src/diagnostics.rs | 10 +-- crates/editor/src/editor.rs | 2 +- crates/editor/src/element.rs | 2 +- crates/feedback/src/feedback_editor.rs | 2 +- .../quick_action_bar/src/quick_action_bar.rs | 2 +- crates/search/src/project_search.rs | 8 +- crates/search/src/search.rs | 4 +- crates/storybook/src/collab_panel.rs | 4 +- crates/storybook/src/workspace.rs | 6 +- crates/terminal_view/src/terminal_panel.rs | 6 +- crates/workspace/src/notifications.rs | 2 +- crates/workspace/src/pane.rs | 14 ++-- styles/src/style_tree/assistant.ts | 14 ++-- styles/src/style_tree/copilot.ts | 10 +-- styles/src/style_tree/editor.ts | 4 +- 514 files changed, 86 insertions(+), 4033 deletions(-) delete mode 100644 assets/icons/Icons/exit.svg delete mode 100644 assets/icons/arrow_down_12.svg delete mode 100644 assets/icons/arrow_down_16.svg delete mode 100644 assets/icons/arrow_down_8.svg delete mode 100644 assets/icons/arrow_left_12.svg delete mode 100644 assets/icons/arrow_left_16.svg delete mode 100644 assets/icons/arrow_left_8.svg delete mode 100644 assets/icons/arrow_right_12.svg delete mode 100644 assets/icons/arrow_right_16.svg delete mode 100644 assets/icons/arrow_right_8.svg delete mode 100644 assets/icons/arrow_up_12.svg delete mode 100644 assets/icons/arrow_up_16.svg delete mode 100644 assets/icons/arrow_up_8.svg rename assets/icons/{arrow_up_right_8.svg => arrow_up_right.svg} (100%) delete mode 100644 assets/icons/assist_15.svg delete mode 100644 assets/icons/backspace _12.svg delete mode 100644 assets/icons/backspace _16.svg delete mode 100644 assets/icons/backspace _8.svg rename assets/icons/{bolt_8.svg => bolt.svg} (100%) delete mode 100644 assets/icons/bolt_12.svg delete mode 100644 assets/icons/bolt_16.svg delete mode 100644 assets/icons/bolt_slash_12.svg delete mode 100644 assets/icons/bolt_slash_16.svg delete mode 100644 assets/icons/bolt_slash_8.svg rename assets/icons/{radix/caret-down.svg => caret_down.svg} (100%) delete mode 100644 assets/icons/caret_down_12.svg delete mode 100644 assets/icons/caret_down_16.svg delete mode 100644 assets/icons/caret_down_8.svg delete mode 100644 assets/icons/caret_left_12.svg delete mode 100644 assets/icons/caret_left_16.svg delete mode 100644 assets/icons/caret_left_8.svg delete mode 100644 assets/icons/caret_right_12.svg delete mode 100644 assets/icons/caret_right_16.svg delete mode 100644 assets/icons/caret_right_8.svg rename assets/icons/{radix/caret-up.svg => caret_up.svg} (100%) delete mode 100644 assets/icons/caret_up_12.svg delete mode 100644 assets/icons/caret_up_16.svg delete mode 100644 assets/icons/caret_up_8.svg rename assets/icons/{case_insensitive_12.svg => case_insensitive.svg} (100%) delete mode 100644 assets/icons/channel_hash.svg delete mode 100644 assets/icons/check_12.svg delete mode 100644 assets/icons/check_16.svg delete mode 100644 assets/icons/check_8.svg delete mode 100644 assets/icons/chevron_down_12.svg delete mode 100644 assets/icons/chevron_down_16.svg delete mode 100644 assets/icons/chevron_down_8.svg delete mode 100644 assets/icons/chevron_left_12.svg delete mode 100644 assets/icons/chevron_left_16.svg delete mode 100644 assets/icons/chevron_left_8.svg delete mode 100644 assets/icons/chevron_right_12.svg delete mode 100644 assets/icons/chevron_right_16.svg delete mode 100644 assets/icons/chevron_right_8.svg delete mode 100644 assets/icons/chevron_up_12.svg delete mode 100644 assets/icons/chevron_up_16.svg delete mode 100644 assets/icons/chevron_up_8.svg rename assets/icons/{circle_check_16.svg => circle_check.svg} (100%) delete mode 100644 assets/icons/circle_check_12.svg delete mode 100644 assets/icons/circle_check_8.svg delete mode 100644 assets/icons/circle_info_12.svg delete mode 100644 assets/icons/circle_info_16.svg delete mode 100644 assets/icons/circle_info_8.svg delete mode 100644 assets/icons/circle_up_12.svg delete mode 100644 assets/icons/circle_up_16.svg delete mode 100644 assets/icons/circle_up_8.svg delete mode 100644 assets/icons/circle_x_mark_12.svg delete mode 100644 assets/icons/circle_x_mark_16.svg delete mode 100644 assets/icons/circle_x_mark_8.svg delete mode 100644 assets/icons/cloud_12.svg delete mode 100644 assets/icons/cloud_8.svg delete mode 100644 assets/icons/cloud_slash_8.svg delete mode 100644 assets/icons/copilot_16.svg rename assets/icons/{copilot_disabled_16.svg => copilot_disabled.svg} (100%) rename assets/icons/{copilot_error_16.svg => copilot_error.svg} (100%) rename assets/icons/{copilot_init_16.svg => copilot_init.svg} (100%) delete mode 100644 assets/icons/copy.svg delete mode 100644 assets/icons/delete_12.svg delete mode 100644 assets/icons/delete_16.svg delete mode 100644 assets/icons/delete_8.svg rename assets/icons/{radix => }/desktop.svg (100%) delete mode 100644 assets/icons/disable_screen_sharing_12.svg rename assets/icons/{cloud_slash_12.svg => disconnected.svg} (100%) delete mode 100644 assets/icons/dock_bottom_12.svg delete mode 100644 assets/icons/dock_bottom_8.svg delete mode 100644 assets/icons/dock_modal_12.svg delete mode 100644 assets/icons/dock_modal_8.svg delete mode 100644 assets/icons/dock_right_12.svg delete mode 100644 assets/icons/dock_right_8.svg rename assets/icons/{download_12.svg => download.svg} (100%) delete mode 100644 assets/icons/download_8.svg delete mode 100644 assets/icons/ellipsis_14.svg delete mode 100644 assets/icons/enable_screen_sharing_12.svg rename assets/icons/{link_out_12.svg => external_link.svg} (100%) delete mode 100644 assets/icons/feedback_16.svg rename assets/icons/{radix => }/file.svg (100%) delete mode 100644 assets/icons/file_12.svg delete mode 100644 assets/icons/file_16.svg delete mode 100644 assets/icons/file_8.svg delete mode 100644 assets/icons/filter_12.svg delete mode 100644 assets/icons/filter_14.svg delete mode 100644 assets/icons/folder_tree_12.svg delete mode 100644 assets/icons/folder_tree_16.svg delete mode 100644 assets/icons/folder_tree_8.svg delete mode 100644 assets/icons/git_diff_12.svg delete mode 100644 assets/icons/git_diff_8.svg delete mode 100644 assets/icons/github-copilot-dummy.svg delete mode 100644 assets/icons/html.svg delete mode 100644 assets/icons/kebab.svg delete mode 100644 assets/icons/leave_12.svg delete mode 100644 assets/icons/lock.svg delete mode 100644 assets/icons/lock_8.svg delete mode 100644 assets/icons/logo_96.svg rename assets/icons/{radix => }/magic-wand.svg (100%) delete mode 100644 assets/icons/magnifying_glass_12.svg delete mode 100644 assets/icons/magnifying_glass_16.svg delete mode 100644 assets/icons/magnifying_glass_8.svg delete mode 100644 assets/icons/match_case.svg delete mode 100644 assets/icons/match_word.svg delete mode 100644 assets/icons/maximize_8.svg rename assets/icons/{hamburger_15.svg => menu.svg} (100%) rename assets/icons/{radix => }/mic-mute.svg (100%) rename assets/icons/{radix => }/mic.svg (100%) delete mode 100644 assets/icons/microphone.svg delete mode 100644 assets/icons/minimize_8.svg delete mode 100644 assets/icons/plus_12.svg delete mode 100644 assets/icons/plus_16.svg delete mode 100644 assets/icons/plus_8.svg rename assets/icons/{radix => }/quote.svg (100%) delete mode 100644 assets/icons/quote_15.svg delete mode 100644 assets/icons/radix/accessibility.svg delete mode 100644 assets/icons/radix/activity-log.svg delete mode 100644 assets/icons/radix/align-baseline.svg delete mode 100644 assets/icons/radix/align-bottom.svg delete mode 100644 assets/icons/radix/align-center-horizontally.svg delete mode 100644 assets/icons/radix/align-center-vertically.svg delete mode 100644 assets/icons/radix/align-center.svg delete mode 100644 assets/icons/radix/align-end.svg delete mode 100644 assets/icons/radix/align-horizontal-centers.svg delete mode 100644 assets/icons/radix/align-left.svg delete mode 100644 assets/icons/radix/align-right.svg delete mode 100644 assets/icons/radix/align-start.svg delete mode 100644 assets/icons/radix/align-stretch.svg delete mode 100644 assets/icons/radix/align-top.svg delete mode 100644 assets/icons/radix/align-vertical-centers.svg delete mode 100644 assets/icons/radix/all-sides.svg delete mode 100644 assets/icons/radix/angle.svg delete mode 100644 assets/icons/radix/archive.svg delete mode 100644 assets/icons/radix/arrow-bottom-left.svg delete mode 100644 assets/icons/radix/arrow-bottom-right.svg delete mode 100644 assets/icons/radix/arrow-down.svg delete mode 100644 assets/icons/radix/arrow-left.svg delete mode 100644 assets/icons/radix/arrow-right.svg delete mode 100644 assets/icons/radix/arrow-top-left.svg delete mode 100644 assets/icons/radix/arrow-top-right.svg delete mode 100644 assets/icons/radix/arrow-up.svg delete mode 100644 assets/icons/radix/aspect-ratio.svg delete mode 100644 assets/icons/radix/avatar.svg delete mode 100644 assets/icons/radix/backpack.svg delete mode 100644 assets/icons/radix/badge.svg delete mode 100644 assets/icons/radix/bar-chart.svg delete mode 100644 assets/icons/radix/bell.svg delete mode 100644 assets/icons/radix/blending-mode.svg delete mode 100644 assets/icons/radix/bookmark-filled.svg delete mode 100644 assets/icons/radix/bookmark.svg delete mode 100644 assets/icons/radix/border-all.svg delete mode 100644 assets/icons/radix/border-bottom.svg delete mode 100644 assets/icons/radix/border-dashed.svg delete mode 100644 assets/icons/radix/border-dotted.svg delete mode 100644 assets/icons/radix/border-left.svg delete mode 100644 assets/icons/radix/border-none.svg delete mode 100644 assets/icons/radix/border-right.svg delete mode 100644 assets/icons/radix/border-solid.svg delete mode 100644 assets/icons/radix/border-split.svg delete mode 100644 assets/icons/radix/border-style.svg delete mode 100644 assets/icons/radix/border-top.svg delete mode 100644 assets/icons/radix/border-width.svg delete mode 100644 assets/icons/radix/box-model.svg delete mode 100644 assets/icons/radix/box.svg delete mode 100644 assets/icons/radix/button.svg delete mode 100644 assets/icons/radix/calendar.svg delete mode 100644 assets/icons/radix/camera.svg delete mode 100644 assets/icons/radix/card-stack-minus.svg delete mode 100644 assets/icons/radix/card-stack-plus.svg delete mode 100644 assets/icons/radix/card-stack.svg delete mode 100644 assets/icons/radix/caret-left.svg delete mode 100644 assets/icons/radix/caret-right.svg delete mode 100644 assets/icons/radix/caret-sort.svg delete mode 100644 assets/icons/radix/chat-bubble.svg delete mode 100644 assets/icons/radix/check-circled.svg delete mode 100644 assets/icons/radix/check.svg delete mode 100644 assets/icons/radix/checkbox.svg delete mode 100644 assets/icons/radix/chevron-down.svg delete mode 100644 assets/icons/radix/chevron-left.svg delete mode 100644 assets/icons/radix/chevron-right.svg delete mode 100644 assets/icons/radix/chevron-up.svg delete mode 100644 assets/icons/radix/circle-backslash.svg delete mode 100644 assets/icons/radix/circle.svg delete mode 100644 assets/icons/radix/clipboard-copy.svg delete mode 100644 assets/icons/radix/clipboard.svg delete mode 100644 assets/icons/radix/clock.svg delete mode 100644 assets/icons/radix/code.svg delete mode 100644 assets/icons/radix/codesandbox-logo.svg delete mode 100644 assets/icons/radix/color-wheel.svg delete mode 100644 assets/icons/radix/column-spacing.svg delete mode 100644 assets/icons/radix/columns.svg delete mode 100644 assets/icons/radix/commit.svg delete mode 100644 assets/icons/radix/component-1.svg delete mode 100644 assets/icons/radix/component-2.svg delete mode 100644 assets/icons/radix/component-boolean.svg delete mode 100644 assets/icons/radix/component-instance.svg delete mode 100644 assets/icons/radix/component-none.svg delete mode 100644 assets/icons/radix/component-placeholder.svg delete mode 100644 assets/icons/radix/container.svg delete mode 100644 assets/icons/radix/cookie.svg delete mode 100644 assets/icons/radix/copy.svg delete mode 100644 assets/icons/radix/corner-bottom-left.svg delete mode 100644 assets/icons/radix/corner-bottom-right.svg delete mode 100644 assets/icons/radix/corner-top-left.svg delete mode 100644 assets/icons/radix/corner-top-right.svg delete mode 100644 assets/icons/radix/corners.svg delete mode 100644 assets/icons/radix/countdown-timer.svg delete mode 100644 assets/icons/radix/counter-clockwise-clock.svg delete mode 100644 assets/icons/radix/crop.svg delete mode 100644 assets/icons/radix/cross-1.svg delete mode 100644 assets/icons/radix/cross-2.svg delete mode 100644 assets/icons/radix/cross-circled.svg delete mode 100644 assets/icons/radix/crosshair-1.svg delete mode 100644 assets/icons/radix/crosshair-2.svg delete mode 100644 assets/icons/radix/crumpled-paper.svg delete mode 100644 assets/icons/radix/cube.svg delete mode 100644 assets/icons/radix/cursor-arrow.svg delete mode 100644 assets/icons/radix/cursor-text.svg delete mode 100644 assets/icons/radix/dash.svg delete mode 100644 assets/icons/radix/dashboard.svg delete mode 100644 assets/icons/radix/desktop-mute.svg delete mode 100644 assets/icons/radix/dimensions.svg delete mode 100644 assets/icons/radix/disc.svg delete mode 100644 assets/icons/radix/discord-logo.svg delete mode 100644 assets/icons/radix/divider-horizontal.svg delete mode 100644 assets/icons/radix/divider-vertical.svg delete mode 100644 assets/icons/radix/dot-filled.svg delete mode 100644 assets/icons/radix/dot-solid.svg delete mode 100644 assets/icons/radix/dot.svg delete mode 100644 assets/icons/radix/dots-horizontal.svg delete mode 100644 assets/icons/radix/dots-vertical.svg delete mode 100644 assets/icons/radix/double-arrow-down.svg delete mode 100644 assets/icons/radix/double-arrow-left.svg delete mode 100644 assets/icons/radix/double-arrow-right.svg delete mode 100644 assets/icons/radix/double-arrow-up.svg delete mode 100644 assets/icons/radix/download.svg delete mode 100644 assets/icons/radix/drag-handle-dots-1.svg delete mode 100644 assets/icons/radix/drag-handle-dots-2.svg delete mode 100644 assets/icons/radix/drag-handle-horizontal.svg delete mode 100644 assets/icons/radix/drag-handle-vertical.svg delete mode 100644 assets/icons/radix/drawing-pin-filled.svg delete mode 100644 assets/icons/radix/drawing-pin-solid.svg delete mode 100644 assets/icons/radix/drawing-pin.svg delete mode 100644 assets/icons/radix/dropdown-menu.svg delete mode 100644 assets/icons/radix/enter-full-screen.svg delete mode 100644 assets/icons/radix/enter.svg delete mode 100644 assets/icons/radix/envelope-closed.svg delete mode 100644 assets/icons/radix/envelope-open.svg delete mode 100644 assets/icons/radix/eraser.svg delete mode 100644 assets/icons/radix/exclamation-triangle.svg delete mode 100644 assets/icons/radix/exit-full-screen.svg delete mode 100644 assets/icons/radix/exit.svg delete mode 100644 assets/icons/radix/external-link.svg delete mode 100644 assets/icons/radix/eye-closed.svg delete mode 100644 assets/icons/radix/eye-none.svg delete mode 100644 assets/icons/radix/eye-open.svg delete mode 100644 assets/icons/radix/face.svg delete mode 100644 assets/icons/radix/figma-logo.svg delete mode 100644 assets/icons/radix/file-minus.svg delete mode 100644 assets/icons/radix/file-plus.svg delete mode 100644 assets/icons/radix/file-text.svg delete mode 100644 assets/icons/radix/font-bold.svg delete mode 100644 assets/icons/radix/font-family.svg delete mode 100644 assets/icons/radix/font-italic.svg delete mode 100644 assets/icons/radix/font-roman.svg delete mode 100644 assets/icons/radix/font-size.svg delete mode 100644 assets/icons/radix/font-style.svg delete mode 100644 assets/icons/radix/frame.svg delete mode 100644 assets/icons/radix/framer-logo.svg delete mode 100644 assets/icons/radix/gear.svg delete mode 100644 assets/icons/radix/github-logo.svg delete mode 100644 assets/icons/radix/globe.svg delete mode 100644 assets/icons/radix/grid.svg delete mode 100644 assets/icons/radix/group.svg delete mode 100644 assets/icons/radix/half-1.svg delete mode 100644 assets/icons/radix/half-2.svg delete mode 100644 assets/icons/radix/hamburger-menu.svg delete mode 100644 assets/icons/radix/hand.svg delete mode 100644 assets/icons/radix/heading.svg delete mode 100644 assets/icons/radix/heart-filled.svg delete mode 100644 assets/icons/radix/heart.svg delete mode 100644 assets/icons/radix/height.svg delete mode 100644 assets/icons/radix/hobby-knife.svg delete mode 100644 assets/icons/radix/home.svg delete mode 100644 assets/icons/radix/iconjar-logo.svg delete mode 100644 assets/icons/radix/id-card.svg delete mode 100644 assets/icons/radix/image.svg delete mode 100644 assets/icons/radix/info-circled.svg delete mode 100644 assets/icons/radix/inner-shadow.svg delete mode 100644 assets/icons/radix/input.svg delete mode 100644 assets/icons/radix/instagram-logo.svg delete mode 100644 assets/icons/radix/justify-center.svg delete mode 100644 assets/icons/radix/justify-end.svg delete mode 100644 assets/icons/radix/justify-start.svg delete mode 100644 assets/icons/radix/justify-stretch.svg delete mode 100644 assets/icons/radix/keyboard.svg delete mode 100644 assets/icons/radix/lap-timer.svg delete mode 100644 assets/icons/radix/laptop.svg delete mode 100644 assets/icons/radix/layers.svg delete mode 100644 assets/icons/radix/layout.svg delete mode 100644 assets/icons/radix/letter-case-capitalize.svg delete mode 100644 assets/icons/radix/letter-case-lowercase.svg delete mode 100644 assets/icons/radix/letter-case-toggle.svg delete mode 100644 assets/icons/radix/letter-case-uppercase.svg delete mode 100644 assets/icons/radix/letter-spacing.svg delete mode 100644 assets/icons/radix/lightning-bolt.svg delete mode 100644 assets/icons/radix/line-height.svg delete mode 100644 assets/icons/radix/link-1.svg delete mode 100644 assets/icons/radix/link-2.svg delete mode 100644 assets/icons/radix/link-break-1.svg delete mode 100644 assets/icons/radix/link-break-2.svg delete mode 100644 assets/icons/radix/link-none-1.svg delete mode 100644 assets/icons/radix/link-none-2.svg delete mode 100644 assets/icons/radix/linkedin-logo.svg delete mode 100644 assets/icons/radix/list-bullet.svg delete mode 100644 assets/icons/radix/lock-closed.svg delete mode 100644 assets/icons/radix/lock-open-1.svg delete mode 100644 assets/icons/radix/lock-open-2.svg delete mode 100644 assets/icons/radix/loop.svg delete mode 100644 assets/icons/radix/magnifying-glass.svg delete mode 100644 assets/icons/radix/margin.svg delete mode 100644 assets/icons/radix/mask-off.svg delete mode 100644 assets/icons/radix/mask-on.svg delete mode 100644 assets/icons/radix/maximize.svg delete mode 100644 assets/icons/radix/minimize.svg delete mode 100644 assets/icons/radix/minus-circled.svg delete mode 100644 assets/icons/radix/minus.svg delete mode 100644 assets/icons/radix/mix.svg delete mode 100644 assets/icons/radix/mixer-horizontal.svg delete mode 100644 assets/icons/radix/mixer-vertical.svg delete mode 100644 assets/icons/radix/mobile.svg delete mode 100644 assets/icons/radix/modulz-logo.svg delete mode 100644 assets/icons/radix/moon.svg delete mode 100644 assets/icons/radix/move.svg delete mode 100644 assets/icons/radix/notion-logo.svg delete mode 100644 assets/icons/radix/opacity.svg delete mode 100644 assets/icons/radix/open-in-new-window.svg delete mode 100644 assets/icons/radix/outer-shadow.svg delete mode 100644 assets/icons/radix/overline.svg delete mode 100644 assets/icons/radix/padding.svg delete mode 100644 assets/icons/radix/paper-plane.svg delete mode 100644 assets/icons/radix/pause.svg delete mode 100644 assets/icons/radix/pencil-1.svg delete mode 100644 assets/icons/radix/pencil-2.svg delete mode 100644 assets/icons/radix/person.svg delete mode 100644 assets/icons/radix/pie-chart.svg delete mode 100644 assets/icons/radix/pilcrow.svg delete mode 100644 assets/icons/radix/pin-bottom.svg delete mode 100644 assets/icons/radix/pin-left.svg delete mode 100644 assets/icons/radix/pin-right.svg delete mode 100644 assets/icons/radix/pin-top.svg delete mode 100644 assets/icons/radix/play.svg delete mode 100644 assets/icons/radix/plus-circled.svg delete mode 100644 assets/icons/radix/plus.svg delete mode 100644 assets/icons/radix/question-mark-circled.svg delete mode 100644 assets/icons/radix/question-mark.svg delete mode 100644 assets/icons/radix/radiobutton.svg delete mode 100644 assets/icons/radix/reader.svg delete mode 100644 assets/icons/radix/reload.svg delete mode 100644 assets/icons/radix/reset.svg delete mode 100644 assets/icons/radix/resume.svg delete mode 100644 assets/icons/radix/rocket.svg delete mode 100644 assets/icons/radix/rotate-counter-clockwise.svg delete mode 100644 assets/icons/radix/row-spacing.svg delete mode 100644 assets/icons/radix/rows.svg delete mode 100644 assets/icons/radix/ruler-horizontal.svg delete mode 100644 assets/icons/radix/ruler-square.svg delete mode 100644 assets/icons/radix/scissors.svg delete mode 100644 assets/icons/radix/section.svg delete mode 100644 assets/icons/radix/sewing-pin-filled.svg delete mode 100644 assets/icons/radix/sewing-pin-solid.svg delete mode 100644 assets/icons/radix/sewing-pin.svg delete mode 100644 assets/icons/radix/shadow-inner.svg delete mode 100644 assets/icons/radix/shadow-none.svg delete mode 100644 assets/icons/radix/shadow-outer.svg delete mode 100644 assets/icons/radix/shadow.svg delete mode 100644 assets/icons/radix/share-1.svg delete mode 100644 assets/icons/radix/share-2.svg delete mode 100644 assets/icons/radix/shuffle.svg delete mode 100644 assets/icons/radix/size.svg delete mode 100644 assets/icons/radix/sketch-logo.svg delete mode 100644 assets/icons/radix/slash.svg delete mode 100644 assets/icons/radix/slider.svg delete mode 100644 assets/icons/radix/space-between-horizontally.svg delete mode 100644 assets/icons/radix/space-between-vertically.svg delete mode 100644 assets/icons/radix/space-evenly-horizontally.svg delete mode 100644 assets/icons/radix/space-evenly-vertically.svg delete mode 100644 assets/icons/radix/speaker-moderate.svg delete mode 100644 assets/icons/radix/speaker-quiet.svg delete mode 100644 assets/icons/radix/square.svg delete mode 100644 assets/icons/radix/stack.svg delete mode 100644 assets/icons/radix/star-filled.svg delete mode 100644 assets/icons/radix/star.svg delete mode 100644 assets/icons/radix/stitches-logo.svg delete mode 100644 assets/icons/radix/stop.svg delete mode 100644 assets/icons/radix/stopwatch.svg delete mode 100644 assets/icons/radix/stretch-horizontally.svg delete mode 100644 assets/icons/radix/stretch-vertically.svg delete mode 100644 assets/icons/radix/strikethrough.svg delete mode 100644 assets/icons/radix/sun.svg delete mode 100644 assets/icons/radix/switch.svg delete mode 100644 assets/icons/radix/symbol.svg delete mode 100644 assets/icons/radix/table.svg delete mode 100644 assets/icons/radix/target.svg delete mode 100644 assets/icons/radix/text-align-bottom.svg delete mode 100644 assets/icons/radix/text-align-center.svg delete mode 100644 assets/icons/radix/text-align-justify.svg delete mode 100644 assets/icons/radix/text-align-left.svg delete mode 100644 assets/icons/radix/text-align-middle.svg delete mode 100644 assets/icons/radix/text-align-right.svg delete mode 100644 assets/icons/radix/text-align-top.svg delete mode 100644 assets/icons/radix/text-none.svg delete mode 100644 assets/icons/radix/text.svg delete mode 100644 assets/icons/radix/thick-arrow-down.svg delete mode 100644 assets/icons/radix/thick-arrow-left.svg delete mode 100644 assets/icons/radix/thick-arrow-right.svg delete mode 100644 assets/icons/radix/thick-arrow-up.svg delete mode 100644 assets/icons/radix/timer.svg delete mode 100644 assets/icons/radix/tokens.svg delete mode 100644 assets/icons/radix/track-next.svg delete mode 100644 assets/icons/radix/track-previous.svg delete mode 100644 assets/icons/radix/transform.svg delete mode 100644 assets/icons/radix/transparency-grid.svg delete mode 100644 assets/icons/radix/trash.svg delete mode 100644 assets/icons/radix/triangle-down.svg delete mode 100644 assets/icons/radix/triangle-left.svg delete mode 100644 assets/icons/radix/triangle-right.svg delete mode 100644 assets/icons/radix/triangle-up.svg delete mode 100644 assets/icons/radix/twitter-logo.svg delete mode 100644 assets/icons/radix/underline.svg delete mode 100644 assets/icons/radix/update.svg delete mode 100644 assets/icons/radix/upload.svg delete mode 100644 assets/icons/radix/value-none.svg delete mode 100644 assets/icons/radix/value.svg delete mode 100644 assets/icons/radix/vercel-logo.svg delete mode 100644 assets/icons/radix/video.svg delete mode 100644 assets/icons/radix/view-grid.svg delete mode 100644 assets/icons/radix/view-horizontal.svg delete mode 100644 assets/icons/radix/view-none.svg delete mode 100644 assets/icons/radix/view-vertical.svg delete mode 100644 assets/icons/radix/width.svg delete mode 100644 assets/icons/radix/zoom-in.svg delete mode 100644 assets/icons/radix/zoom-out.svg delete mode 100644 assets/icons/robot_14.svg delete mode 100644 assets/icons/screen.svg rename assets/icons/{radix => }/speaker-loud.svg (100%) rename assets/icons/{radix => }/speaker-off.svg (100%) delete mode 100644 assets/icons/speech_bubble_12.svg delete mode 100644 assets/icons/split_12.svg rename assets/icons/{split_message_15.svg => split_message.svg} (100%) delete mode 100644 assets/icons/stop_sharing.svg delete mode 100644 assets/icons/success.svg delete mode 100644 assets/icons/terminal_12.svg delete mode 100644 assets/icons/terminal_16.svg delete mode 100644 assets/icons/terminal_8.svg delete mode 100644 assets/icons/triangle_exclamation_12.svg delete mode 100644 assets/icons/triangle_exclamation_16.svg delete mode 100644 assets/icons/triangle_exclamation_8.svg delete mode 100644 assets/icons/unlock_8.svg delete mode 100644 assets/icons/user_circle_12.svg delete mode 100644 assets/icons/user_circle_8.svg delete mode 100644 assets/icons/user_group_12.svg delete mode 100644 assets/icons/user_group_16.svg delete mode 100644 assets/icons/user_group_8.svg delete mode 100644 assets/icons/user_plus_12.svg delete mode 100644 assets/icons/user_plus_16.svg delete mode 100644 assets/icons/user_plus_8.svg delete mode 100644 assets/icons/version_control_branch_12.svg rename assets/icons/{word_search_14.svg => word_search.svg} (100%) delete mode 100644 assets/icons/word_search_12.svg delete mode 100644 assets/icons/x_mark_12.svg delete mode 100644 assets/icons/x_mark_16.svg delete mode 100644 assets/icons/x_mark_8.svg rename assets/icons/{zed_plus_copilot_32.svg => zed_x_copilot.svg} (100%) diff --git a/assets/icons/Icons/exit.svg b/assets/icons/Icons/exit.svg deleted file mode 100644 index 6d76849248..0000000000 --- a/assets/icons/Icons/exit.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow_down_12.svg b/assets/icons/arrow_down_12.svg deleted file mode 100644 index dfad5d4876..0000000000 --- a/assets/icons/arrow_down_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_down_16.svg b/assets/icons/arrow_down_16.svg deleted file mode 100644 index ec757a8ab4..0000000000 --- a/assets/icons/arrow_down_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow_down_8.svg b/assets/icons/arrow_down_8.svg deleted file mode 100644 index f70f3920a3..0000000000 --- a/assets/icons/arrow_down_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_left_12.svg b/assets/icons/arrow_left_12.svg deleted file mode 100644 index aaccf25eaf..0000000000 --- a/assets/icons/arrow_left_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_left_16.svg b/assets/icons/arrow_left_16.svg deleted file mode 100644 index 317c31e9f0..0000000000 --- a/assets/icons/arrow_left_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow_left_8.svg b/assets/icons/arrow_left_8.svg deleted file mode 100644 index e2071d55eb..0000000000 --- a/assets/icons/arrow_left_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_right_12.svg b/assets/icons/arrow_right_12.svg deleted file mode 100644 index c5f70a4958..0000000000 --- a/assets/icons/arrow_right_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_right_16.svg b/assets/icons/arrow_right_16.svg deleted file mode 100644 index b41e8fc810..0000000000 --- a/assets/icons/arrow_right_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow_right_8.svg b/assets/icons/arrow_right_8.svg deleted file mode 100644 index fb3f836ef0..0000000000 --- a/assets/icons/arrow_right_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_up_12.svg b/assets/icons/arrow_up_12.svg deleted file mode 100644 index c9f35d868b..0000000000 --- a/assets/icons/arrow_up_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_up_16.svg b/assets/icons/arrow_up_16.svg deleted file mode 100644 index 0d8add4ed7..0000000000 --- a/assets/icons/arrow_up_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/arrow_up_8.svg b/assets/icons/arrow_up_8.svg deleted file mode 100644 index 0a1e2c44bf..0000000000 --- a/assets/icons/arrow_up_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/arrow_up_right_8.svg b/assets/icons/arrow_up_right.svg similarity index 100% rename from assets/icons/arrow_up_right_8.svg rename to assets/icons/arrow_up_right.svg diff --git a/assets/icons/assist_15.svg b/assets/icons/assist_15.svg deleted file mode 100644 index 3baf8df3e9..0000000000 --- a/assets/icons/assist_15.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/backspace _12.svg b/assets/icons/backspace _12.svg deleted file mode 100644 index 68bad3da26..0000000000 --- a/assets/icons/backspace _12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/backspace _16.svg b/assets/icons/backspace _16.svg deleted file mode 100644 index 965470690e..0000000000 --- a/assets/icons/backspace _16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/backspace _8.svg b/assets/icons/backspace _8.svg deleted file mode 100644 index 60972007b6..0000000000 --- a/assets/icons/backspace _8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/bolt_8.svg b/assets/icons/bolt.svg similarity index 100% rename from assets/icons/bolt_8.svg rename to assets/icons/bolt.svg diff --git a/assets/icons/bolt_12.svg b/assets/icons/bolt_12.svg deleted file mode 100644 index 0125c733e2..0000000000 --- a/assets/icons/bolt_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/bolt_16.svg b/assets/icons/bolt_16.svg deleted file mode 100644 index aca476ef50..0000000000 --- a/assets/icons/bolt_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/bolt_slash_12.svg b/assets/icons/bolt_slash_12.svg deleted file mode 100644 index 80d99be616..0000000000 --- a/assets/icons/bolt_slash_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/bolt_slash_16.svg b/assets/icons/bolt_slash_16.svg deleted file mode 100644 index 9520a626c1..0000000000 --- a/assets/icons/bolt_slash_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/bolt_slash_8.svg b/assets/icons/bolt_slash_8.svg deleted file mode 100644 index 3781a91299..0000000000 --- a/assets/icons/bolt_slash_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/radix/caret-down.svg b/assets/icons/caret_down.svg similarity index 100% rename from assets/icons/radix/caret-down.svg rename to assets/icons/caret_down.svg diff --git a/assets/icons/caret_down_12.svg b/assets/icons/caret_down_12.svg deleted file mode 100644 index 6208814bc2..0000000000 --- a/assets/icons/caret_down_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_down_16.svg b/assets/icons/caret_down_16.svg deleted file mode 100644 index cba930287e..0000000000 --- a/assets/icons/caret_down_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_down_8.svg b/assets/icons/caret_down_8.svg deleted file mode 100644 index 932376d6f8..0000000000 --- a/assets/icons/caret_down_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/caret_left_12.svg b/assets/icons/caret_left_12.svg deleted file mode 100644 index 6b6c32513e..0000000000 --- a/assets/icons/caret_left_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_left_16.svg b/assets/icons/caret_left_16.svg deleted file mode 100644 index 5ffd176c59..0000000000 --- a/assets/icons/caret_left_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_left_8.svg b/assets/icons/caret_left_8.svg deleted file mode 100644 index 1b04877a31..0000000000 --- a/assets/icons/caret_left_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/caret_right_12.svg b/assets/icons/caret_right_12.svg deleted file mode 100644 index 6670b80cf8..0000000000 --- a/assets/icons/caret_right_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_right_16.svg b/assets/icons/caret_right_16.svg deleted file mode 100644 index da239b95d7..0000000000 --- a/assets/icons/caret_right_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_right_8.svg b/assets/icons/caret_right_8.svg deleted file mode 100644 index d1350ee809..0000000000 --- a/assets/icons/caret_right_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/radix/caret-up.svg b/assets/icons/caret_up.svg similarity index 100% rename from assets/icons/radix/caret-up.svg rename to assets/icons/caret_up.svg diff --git a/assets/icons/caret_up_12.svg b/assets/icons/caret_up_12.svg deleted file mode 100644 index 9fe93c47ae..0000000000 --- a/assets/icons/caret_up_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_up_16.svg b/assets/icons/caret_up_16.svg deleted file mode 100644 index 10f45523a4..0000000000 --- a/assets/icons/caret_up_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/caret_up_8.svg b/assets/icons/caret_up_8.svg deleted file mode 100644 index bf79244d7d..0000000000 --- a/assets/icons/caret_up_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/case_insensitive_12.svg b/assets/icons/case_insensitive.svg similarity index 100% rename from assets/icons/case_insensitive_12.svg rename to assets/icons/case_insensitive.svg diff --git a/assets/icons/channel_hash.svg b/assets/icons/channel_hash.svg deleted file mode 100644 index edd0462678..0000000000 --- a/assets/icons/channel_hash.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/assets/icons/check_12.svg b/assets/icons/check_12.svg deleted file mode 100644 index 3e15dd7d1f..0000000000 --- a/assets/icons/check_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/check_16.svg b/assets/icons/check_16.svg deleted file mode 100644 index 7e959b5924..0000000000 --- a/assets/icons/check_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/check_8.svg b/assets/icons/check_8.svg deleted file mode 100644 index 268f8bb498..0000000000 --- a/assets/icons/check_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_down_12.svg b/assets/icons/chevron_down_12.svg deleted file mode 100644 index 7bba37857a..0000000000 --- a/assets/icons/chevron_down_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_down_16.svg b/assets/icons/chevron_down_16.svg deleted file mode 100644 index cc7228cdc9..0000000000 --- a/assets/icons/chevron_down_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_down_8.svg b/assets/icons/chevron_down_8.svg deleted file mode 100644 index fe60b4968a..0000000000 --- a/assets/icons/chevron_down_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_left_12.svg b/assets/icons/chevron_left_12.svg deleted file mode 100644 index a230007c7b..0000000000 --- a/assets/icons/chevron_left_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_left_16.svg b/assets/icons/chevron_left_16.svg deleted file mode 100644 index 2cd1bbd4d2..0000000000 --- a/assets/icons/chevron_left_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_left_8.svg b/assets/icons/chevron_left_8.svg deleted file mode 100644 index 88ca274f51..0000000000 --- a/assets/icons/chevron_left_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_right_12.svg b/assets/icons/chevron_right_12.svg deleted file mode 100644 index b463182705..0000000000 --- a/assets/icons/chevron_right_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_right_16.svg b/assets/icons/chevron_right_16.svg deleted file mode 100644 index 270a33db70..0000000000 --- a/assets/icons/chevron_right_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_right_8.svg b/assets/icons/chevron_right_8.svg deleted file mode 100644 index 7349274681..0000000000 --- a/assets/icons/chevron_right_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_up_12.svg b/assets/icons/chevron_up_12.svg deleted file mode 100644 index c6bbee4ff7..0000000000 --- a/assets/icons/chevron_up_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_up_16.svg b/assets/icons/chevron_up_16.svg deleted file mode 100644 index ba2d4e6668..0000000000 --- a/assets/icons/chevron_up_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/chevron_up_8.svg b/assets/icons/chevron_up_8.svg deleted file mode 100644 index 41525aa3ea..0000000000 --- a/assets/icons/chevron_up_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/circle_check_16.svg b/assets/icons/circle_check.svg similarity index 100% rename from assets/icons/circle_check_16.svg rename to assets/icons/circle_check.svg diff --git a/assets/icons/circle_check_12.svg b/assets/icons/circle_check_12.svg deleted file mode 100644 index cb28c8a051..0000000000 --- a/assets/icons/circle_check_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_check_8.svg b/assets/icons/circle_check_8.svg deleted file mode 100644 index c4150f058c..0000000000 --- a/assets/icons/circle_check_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_info_12.svg b/assets/icons/circle_info_12.svg deleted file mode 100644 index 26a569737d..0000000000 --- a/assets/icons/circle_info_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_info_16.svg b/assets/icons/circle_info_16.svg deleted file mode 100644 index 48bd4f79a8..0000000000 --- a/assets/icons/circle_info_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/circle_info_8.svg b/assets/icons/circle_info_8.svg deleted file mode 100644 index 49bb03224d..0000000000 --- a/assets/icons/circle_info_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_up_12.svg b/assets/icons/circle_up_12.svg deleted file mode 100644 index 4236037fbd..0000000000 --- a/assets/icons/circle_up_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_up_16.svg b/assets/icons/circle_up_16.svg deleted file mode 100644 index 4eb3886fe4..0000000000 --- a/assets/icons/circle_up_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/circle_up_8.svg b/assets/icons/circle_up_8.svg deleted file mode 100644 index e08e0ad492..0000000000 --- a/assets/icons/circle_up_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_x_mark_12.svg b/assets/icons/circle_x_mark_12.svg deleted file mode 100644 index 5f11a71ece..0000000000 --- a/assets/icons/circle_x_mark_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/circle_x_mark_16.svg b/assets/icons/circle_x_mark_16.svg deleted file mode 100644 index db3f401615..0000000000 --- a/assets/icons/circle_x_mark_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/circle_x_mark_8.svg b/assets/icons/circle_x_mark_8.svg deleted file mode 100644 index a0acfc3899..0000000000 --- a/assets/icons/circle_x_mark_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/cloud_12.svg b/assets/icons/cloud_12.svg deleted file mode 100644 index 2ed58f4966..0000000000 --- a/assets/icons/cloud_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/cloud_8.svg b/assets/icons/cloud_8.svg deleted file mode 100644 index 0e0337e7ab..0000000000 --- a/assets/icons/cloud_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/cloud_slash_8.svg b/assets/icons/cloud_slash_8.svg deleted file mode 100644 index 785ded0683..0000000000 --- a/assets/icons/cloud_slash_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/copilot_16.svg b/assets/icons/copilot_16.svg deleted file mode 100644 index e14b61ce8b..0000000000 --- a/assets/icons/copilot_16.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/assets/icons/copilot_disabled_16.svg b/assets/icons/copilot_disabled.svg similarity index 100% rename from assets/icons/copilot_disabled_16.svg rename to assets/icons/copilot_disabled.svg diff --git a/assets/icons/copilot_error_16.svg b/assets/icons/copilot_error.svg similarity index 100% rename from assets/icons/copilot_error_16.svg rename to assets/icons/copilot_error.svg diff --git a/assets/icons/copilot_init_16.svg b/assets/icons/copilot_init.svg similarity index 100% rename from assets/icons/copilot_init_16.svg rename to assets/icons/copilot_init.svg diff --git a/assets/icons/copy.svg b/assets/icons/copy.svg deleted file mode 100644 index 4aa44979c3..0000000000 --- a/assets/icons/copy.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/delete_12.svg b/assets/icons/delete_12.svg deleted file mode 100644 index 68bad3da26..0000000000 --- a/assets/icons/delete_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/delete_16.svg b/assets/icons/delete_16.svg deleted file mode 100644 index 965470690e..0000000000 --- a/assets/icons/delete_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/delete_8.svg b/assets/icons/delete_8.svg deleted file mode 100644 index 60972007b6..0000000000 --- a/assets/icons/delete_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/desktop.svg b/assets/icons/desktop.svg similarity index 100% rename from assets/icons/radix/desktop.svg rename to assets/icons/desktop.svg diff --git a/assets/icons/disable_screen_sharing_12.svg b/assets/icons/disable_screen_sharing_12.svg deleted file mode 100644 index c2a4edd45b..0000000000 --- a/assets/icons/disable_screen_sharing_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/cloud_slash_12.svg b/assets/icons/disconnected.svg similarity index 100% rename from assets/icons/cloud_slash_12.svg rename to assets/icons/disconnected.svg diff --git a/assets/icons/dock_bottom_12.svg b/assets/icons/dock_bottom_12.svg deleted file mode 100644 index a8099443be..0000000000 --- a/assets/icons/dock_bottom_12.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/assets/icons/dock_bottom_8.svg b/assets/icons/dock_bottom_8.svg deleted file mode 100644 index 005ac423ad..0000000000 --- a/assets/icons/dock_bottom_8.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/assets/icons/dock_modal_12.svg b/assets/icons/dock_modal_12.svg deleted file mode 100644 index 792baee49c..0000000000 --- a/assets/icons/dock_modal_12.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/assets/icons/dock_modal_8.svg b/assets/icons/dock_modal_8.svg deleted file mode 100644 index c6f4039004..0000000000 --- a/assets/icons/dock_modal_8.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/assets/icons/dock_right_12.svg b/assets/icons/dock_right_12.svg deleted file mode 100644 index 84cc1a0c2b..0000000000 --- a/assets/icons/dock_right_12.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/assets/icons/dock_right_8.svg b/assets/icons/dock_right_8.svg deleted file mode 100644 index 842f41bc8c..0000000000 --- a/assets/icons/dock_right_8.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/assets/icons/download_12.svg b/assets/icons/download.svg similarity index 100% rename from assets/icons/download_12.svg rename to assets/icons/download.svg diff --git a/assets/icons/download_8.svg b/assets/icons/download_8.svg deleted file mode 100644 index fb8b021d6b..0000000000 --- a/assets/icons/download_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/ellipsis_14.svg b/assets/icons/ellipsis_14.svg deleted file mode 100644 index 5d45af2b6f..0000000000 --- a/assets/icons/ellipsis_14.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/enable_screen_sharing_12.svg b/assets/icons/enable_screen_sharing_12.svg deleted file mode 100644 index 6ae37649d2..0000000000 --- a/assets/icons/enable_screen_sharing_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/exit.svg b/assets/icons/exit.svg index 7e45535773..2cc6ce120d 100644 --- a/assets/icons/exit.svg +++ b/assets/icons/exit.svg @@ -1,4 +1,8 @@ - - - + + diff --git a/assets/icons/link_out_12.svg b/assets/icons/external_link.svg similarity index 100% rename from assets/icons/link_out_12.svg rename to assets/icons/external_link.svg diff --git a/assets/icons/feedback_16.svg b/assets/icons/feedback_16.svg deleted file mode 100644 index b85a40b353..0000000000 --- a/assets/icons/feedback_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/file.svg b/assets/icons/file.svg similarity index 100% rename from assets/icons/radix/file.svg rename to assets/icons/file.svg diff --git a/assets/icons/file_12.svg b/assets/icons/file_12.svg deleted file mode 100644 index 191e3d7fae..0000000000 --- a/assets/icons/file_12.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/file_16.svg b/assets/icons/file_16.svg deleted file mode 100644 index 79fd1f81cb..0000000000 --- a/assets/icons/file_16.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/file_8.svg b/assets/icons/file_8.svg deleted file mode 100644 index 2e636bd3b3..0000000000 --- a/assets/icons/file_8.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/filter_12.svg b/assets/icons/filter_12.svg deleted file mode 100644 index 9c1ad5ba5c..0000000000 --- a/assets/icons/filter_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/filter_14.svg b/assets/icons/filter_14.svg deleted file mode 100644 index 379be15b51..0000000000 --- a/assets/icons/filter_14.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/assets/icons/folder_tree_12.svg b/assets/icons/folder_tree_12.svg deleted file mode 100644 index 580514f74d..0000000000 --- a/assets/icons/folder_tree_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/folder_tree_16.svg b/assets/icons/folder_tree_16.svg deleted file mode 100644 index a264a32573..0000000000 --- a/assets/icons/folder_tree_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/folder_tree_8.svg b/assets/icons/folder_tree_8.svg deleted file mode 100644 index 07ac18e19f..0000000000 --- a/assets/icons/folder_tree_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/git_diff_12.svg b/assets/icons/git_diff_12.svg deleted file mode 100644 index 0a3bb473c2..0000000000 --- a/assets/icons/git_diff_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/git_diff_8.svg b/assets/icons/git_diff_8.svg deleted file mode 100644 index 64290de860..0000000000 --- a/assets/icons/git_diff_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/github-copilot-dummy.svg b/assets/icons/github-copilot-dummy.svg deleted file mode 100644 index 4a7ded3976..0000000000 --- a/assets/icons/github-copilot-dummy.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/icons/html.svg b/assets/icons/html.svg deleted file mode 100644 index 1e676fe313..0000000000 --- a/assets/icons/html.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/kebab.svg b/assets/icons/kebab.svg deleted file mode 100644 index 1858c65520..0000000000 --- a/assets/icons/kebab.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/leave_12.svg b/assets/icons/leave_12.svg deleted file mode 100644 index 84491384b8..0000000000 --- a/assets/icons/leave_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/lock.svg b/assets/icons/lock.svg deleted file mode 100644 index 652f45a7e8..0000000000 --- a/assets/icons/lock.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/assets/icons/lock_8.svg b/assets/icons/lock_8.svg deleted file mode 100644 index 8df83dc0b5..0000000000 --- a/assets/icons/lock_8.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/logo_96.svg b/assets/icons/logo_96.svg deleted file mode 100644 index dc98bb8bc2..0000000000 --- a/assets/icons/logo_96.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/magic-wand.svg b/assets/icons/magic-wand.svg similarity index 100% rename from assets/icons/radix/magic-wand.svg rename to assets/icons/magic-wand.svg diff --git a/assets/icons/magnifying_glass_12.svg b/assets/icons/magnifying_glass_12.svg deleted file mode 100644 index b9ac5d35b2..0000000000 --- a/assets/icons/magnifying_glass_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/magnifying_glass_16.svg b/assets/icons/magnifying_glass_16.svg deleted file mode 100644 index f35343e8d3..0000000000 --- a/assets/icons/magnifying_glass_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/magnifying_glass_8.svg b/assets/icons/magnifying_glass_8.svg deleted file mode 100644 index d0deb1cdba..0000000000 --- a/assets/icons/magnifying_glass_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/match_case.svg b/assets/icons/match_case.svg deleted file mode 100644 index 82f4529c1b..0000000000 --- a/assets/icons/match_case.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/match_word.svg b/assets/icons/match_word.svg deleted file mode 100644 index 69ba8eb9e6..0000000000 --- a/assets/icons/match_word.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/maximize.svg b/assets/icons/maximize.svg index 4dc7755714..f37f6a2087 100644 --- a/assets/icons/maximize.svg +++ b/assets/icons/maximize.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/assets/icons/maximize_8.svg b/assets/icons/maximize_8.svg deleted file mode 100644 index 76d29a9d22..0000000000 --- a/assets/icons/maximize_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/hamburger_15.svg b/assets/icons/menu.svg similarity index 100% rename from assets/icons/hamburger_15.svg rename to assets/icons/menu.svg diff --git a/assets/icons/radix/mic-mute.svg b/assets/icons/mic-mute.svg similarity index 100% rename from assets/icons/radix/mic-mute.svg rename to assets/icons/mic-mute.svg diff --git a/assets/icons/radix/mic.svg b/assets/icons/mic.svg similarity index 100% rename from assets/icons/radix/mic.svg rename to assets/icons/mic.svg diff --git a/assets/icons/microphone.svg b/assets/icons/microphone.svg deleted file mode 100644 index 8974fd939d..0000000000 --- a/assets/icons/microphone.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/minimize.svg b/assets/icons/minimize.svg index d8941ee1f0..ec78f152e1 100644 --- a/assets/icons/minimize.svg +++ b/assets/icons/minimize.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/assets/icons/minimize_8.svg b/assets/icons/minimize_8.svg deleted file mode 100644 index b511cbd355..0000000000 --- a/assets/icons/minimize_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/plus.svg b/assets/icons/plus.svg index a54dd0ad66..57ce90219b 100644 --- a/assets/icons/plus.svg +++ b/assets/icons/plus.svg @@ -1,3 +1,8 @@ - - + + diff --git a/assets/icons/plus_12.svg b/assets/icons/plus_12.svg deleted file mode 100644 index f1770fa248..0000000000 --- a/assets/icons/plus_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/plus_16.svg b/assets/icons/plus_16.svg deleted file mode 100644 index c595cf597a..0000000000 --- a/assets/icons/plus_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/plus_8.svg b/assets/icons/plus_8.svg deleted file mode 100644 index 72efa1574e..0000000000 --- a/assets/icons/plus_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/radix/quote.svg b/assets/icons/quote.svg similarity index 100% rename from assets/icons/radix/quote.svg rename to assets/icons/quote.svg diff --git a/assets/icons/quote_15.svg b/assets/icons/quote_15.svg deleted file mode 100644 index be5eabd9b0..0000000000 --- a/assets/icons/quote_15.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/radix/accessibility.svg b/assets/icons/radix/accessibility.svg deleted file mode 100644 index 32d78f2d8d..0000000000 --- a/assets/icons/radix/accessibility.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/activity-log.svg b/assets/icons/radix/activity-log.svg deleted file mode 100644 index 8feab7d449..0000000000 --- a/assets/icons/radix/activity-log.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-baseline.svg b/assets/icons/radix/align-baseline.svg deleted file mode 100644 index 07213dc1ae..0000000000 --- a/assets/icons/radix/align-baseline.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-bottom.svg b/assets/icons/radix/align-bottom.svg deleted file mode 100644 index 7d11c0cd5a..0000000000 --- a/assets/icons/radix/align-bottom.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-center-horizontally.svg b/assets/icons/radix/align-center-horizontally.svg deleted file mode 100644 index 69509a7d09..0000000000 --- a/assets/icons/radix/align-center-horizontally.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-center-vertically.svg b/assets/icons/radix/align-center-vertically.svg deleted file mode 100644 index 4f1b50cc43..0000000000 --- a/assets/icons/radix/align-center-vertically.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-center.svg b/assets/icons/radix/align-center.svg deleted file mode 100644 index caaec36477..0000000000 --- a/assets/icons/radix/align-center.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-end.svg b/assets/icons/radix/align-end.svg deleted file mode 100644 index 18f1b64912..0000000000 --- a/assets/icons/radix/align-end.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-horizontal-centers.svg b/assets/icons/radix/align-horizontal-centers.svg deleted file mode 100644 index 2d1d64ea4b..0000000000 --- a/assets/icons/radix/align-horizontal-centers.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-left.svg b/assets/icons/radix/align-left.svg deleted file mode 100644 index 0d5dba095c..0000000000 --- a/assets/icons/radix/align-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-right.svg b/assets/icons/radix/align-right.svg deleted file mode 100644 index 1b6b3f0ffa..0000000000 --- a/assets/icons/radix/align-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-start.svg b/assets/icons/radix/align-start.svg deleted file mode 100644 index ada50e1079..0000000000 --- a/assets/icons/radix/align-start.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-stretch.svg b/assets/icons/radix/align-stretch.svg deleted file mode 100644 index 3cb28605cb..0000000000 --- a/assets/icons/radix/align-stretch.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-top.svg b/assets/icons/radix/align-top.svg deleted file mode 100644 index 23db80f4dd..0000000000 --- a/assets/icons/radix/align-top.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/align-vertical-centers.svg b/assets/icons/radix/align-vertical-centers.svg deleted file mode 100644 index 07eaee7bf7..0000000000 --- a/assets/icons/radix/align-vertical-centers.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/all-sides.svg b/assets/icons/radix/all-sides.svg deleted file mode 100644 index 8ace7df03f..0000000000 --- a/assets/icons/radix/all-sides.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/angle.svg b/assets/icons/radix/angle.svg deleted file mode 100644 index a0d93f3460..0000000000 --- a/assets/icons/radix/angle.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/archive.svg b/assets/icons/radix/archive.svg deleted file mode 100644 index 74063f1d1e..0000000000 --- a/assets/icons/radix/archive.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-bottom-left.svg b/assets/icons/radix/arrow-bottom-left.svg deleted file mode 100644 index 7a4511aa2d..0000000000 --- a/assets/icons/radix/arrow-bottom-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-bottom-right.svg b/assets/icons/radix/arrow-bottom-right.svg deleted file mode 100644 index 2ba9fef101..0000000000 --- a/assets/icons/radix/arrow-bottom-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-down.svg b/assets/icons/radix/arrow-down.svg deleted file mode 100644 index 5dc21a6689..0000000000 --- a/assets/icons/radix/arrow-down.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-left.svg b/assets/icons/radix/arrow-left.svg deleted file mode 100644 index 3a64c8394f..0000000000 --- a/assets/icons/radix/arrow-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-right.svg b/assets/icons/radix/arrow-right.svg deleted file mode 100644 index e3d30988d5..0000000000 --- a/assets/icons/radix/arrow-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-top-left.svg b/assets/icons/radix/arrow-top-left.svg deleted file mode 100644 index 69fef41dee..0000000000 --- a/assets/icons/radix/arrow-top-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-top-right.svg b/assets/icons/radix/arrow-top-right.svg deleted file mode 100644 index c1016376e3..0000000000 --- a/assets/icons/radix/arrow-top-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/arrow-up.svg b/assets/icons/radix/arrow-up.svg deleted file mode 100644 index ba426119e9..0000000000 --- a/assets/icons/radix/arrow-up.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/aspect-ratio.svg b/assets/icons/radix/aspect-ratio.svg deleted file mode 100644 index 0851f2e1e9..0000000000 --- a/assets/icons/radix/aspect-ratio.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/avatar.svg b/assets/icons/radix/avatar.svg deleted file mode 100644 index cb229c77fe..0000000000 --- a/assets/icons/radix/avatar.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/backpack.svg b/assets/icons/radix/backpack.svg deleted file mode 100644 index a5c9cedbd3..0000000000 --- a/assets/icons/radix/backpack.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/badge.svg b/assets/icons/radix/badge.svg deleted file mode 100644 index aa764d4726..0000000000 --- a/assets/icons/radix/badge.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/bar-chart.svg b/assets/icons/radix/bar-chart.svg deleted file mode 100644 index f8054781d9..0000000000 --- a/assets/icons/radix/bar-chart.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/bell.svg b/assets/icons/radix/bell.svg deleted file mode 100644 index ea1c6dd42e..0000000000 --- a/assets/icons/radix/bell.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/blending-mode.svg b/assets/icons/radix/blending-mode.svg deleted file mode 100644 index bd58cf4ee3..0000000000 --- a/assets/icons/radix/blending-mode.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/bookmark-filled.svg b/assets/icons/radix/bookmark-filled.svg deleted file mode 100644 index 5b725cd88d..0000000000 --- a/assets/icons/radix/bookmark-filled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/bookmark.svg b/assets/icons/radix/bookmark.svg deleted file mode 100644 index 90c4d827f1..0000000000 --- a/assets/icons/radix/bookmark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/border-all.svg b/assets/icons/radix/border-all.svg deleted file mode 100644 index 3bfde7d59b..0000000000 --- a/assets/icons/radix/border-all.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/assets/icons/radix/border-bottom.svg b/assets/icons/radix/border-bottom.svg deleted file mode 100644 index f2d3c3d554..0000000000 --- a/assets/icons/radix/border-bottom.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/border-dashed.svg b/assets/icons/radix/border-dashed.svg deleted file mode 100644 index 85fdcdfe5d..0000000000 --- a/assets/icons/radix/border-dashed.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/border-dotted.svg b/assets/icons/radix/border-dotted.svg deleted file mode 100644 index 5eb514ed2a..0000000000 --- a/assets/icons/radix/border-dotted.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/border-left.svg b/assets/icons/radix/border-left.svg deleted file mode 100644 index 5deb197da5..0000000000 --- a/assets/icons/radix/border-left.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/border-none.svg b/assets/icons/radix/border-none.svg deleted file mode 100644 index 1ad3f59d7c..0000000000 --- a/assets/icons/radix/border-none.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/border-right.svg b/assets/icons/radix/border-right.svg deleted file mode 100644 index c939095ad7..0000000000 --- a/assets/icons/radix/border-right.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/border-solid.svg b/assets/icons/radix/border-solid.svg deleted file mode 100644 index 5c0d26a058..0000000000 --- a/assets/icons/radix/border-solid.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/border-split.svg b/assets/icons/radix/border-split.svg deleted file mode 100644 index 7fdf6cc34e..0000000000 --- a/assets/icons/radix/border-split.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/border-style.svg b/assets/icons/radix/border-style.svg deleted file mode 100644 index f729cb993b..0000000000 --- a/assets/icons/radix/border-style.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/border-top.svg b/assets/icons/radix/border-top.svg deleted file mode 100644 index bde739d755..0000000000 --- a/assets/icons/radix/border-top.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/border-width.svg b/assets/icons/radix/border-width.svg deleted file mode 100644 index 37c270756e..0000000000 --- a/assets/icons/radix/border-width.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/box-model.svg b/assets/icons/radix/box-model.svg deleted file mode 100644 index 45d1a7ce41..0000000000 --- a/assets/icons/radix/box-model.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/box.svg b/assets/icons/radix/box.svg deleted file mode 100644 index 6e035c21ed..0000000000 --- a/assets/icons/radix/box.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/button.svg b/assets/icons/radix/button.svg deleted file mode 100644 index 31622bcf15..0000000000 --- a/assets/icons/radix/button.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/calendar.svg b/assets/icons/radix/calendar.svg deleted file mode 100644 index 2adbe0bc28..0000000000 --- a/assets/icons/radix/calendar.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/camera.svg b/assets/icons/radix/camera.svg deleted file mode 100644 index d7cccf74c2..0000000000 --- a/assets/icons/radix/camera.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/card-stack-minus.svg b/assets/icons/radix/card-stack-minus.svg deleted file mode 100644 index 04d8e51178..0000000000 --- a/assets/icons/radix/card-stack-minus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/card-stack-plus.svg b/assets/icons/radix/card-stack-plus.svg deleted file mode 100644 index a184f4bc1a..0000000000 --- a/assets/icons/radix/card-stack-plus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/card-stack.svg b/assets/icons/radix/card-stack.svg deleted file mode 100644 index defea0e165..0000000000 --- a/assets/icons/radix/card-stack.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/caret-left.svg b/assets/icons/radix/caret-left.svg deleted file mode 100644 index 969bc3b95c..0000000000 --- a/assets/icons/radix/caret-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/caret-right.svg b/assets/icons/radix/caret-right.svg deleted file mode 100644 index 75c55d8676..0000000000 --- a/assets/icons/radix/caret-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/caret-sort.svg b/assets/icons/radix/caret-sort.svg deleted file mode 100644 index a65e20b660..0000000000 --- a/assets/icons/radix/caret-sort.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/chat-bubble.svg b/assets/icons/radix/chat-bubble.svg deleted file mode 100644 index 5766f46de8..0000000000 --- a/assets/icons/radix/chat-bubble.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/check-circled.svg b/assets/icons/radix/check-circled.svg deleted file mode 100644 index 19ee22eb51..0000000000 --- a/assets/icons/radix/check-circled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/check.svg b/assets/icons/radix/check.svg deleted file mode 100644 index 476a3baa18..0000000000 --- a/assets/icons/radix/check.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/checkbox.svg b/assets/icons/radix/checkbox.svg deleted file mode 100644 index d6bb3c7ef2..0000000000 --- a/assets/icons/radix/checkbox.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/chevron-down.svg b/assets/icons/radix/chevron-down.svg deleted file mode 100644 index 175c1312fd..0000000000 --- a/assets/icons/radix/chevron-down.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/chevron-left.svg b/assets/icons/radix/chevron-left.svg deleted file mode 100644 index d7628202f2..0000000000 --- a/assets/icons/radix/chevron-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/chevron-right.svg b/assets/icons/radix/chevron-right.svg deleted file mode 100644 index e3ebd73d99..0000000000 --- a/assets/icons/radix/chevron-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/chevron-up.svg b/assets/icons/radix/chevron-up.svg deleted file mode 100644 index 0e8e796dab..0000000000 --- a/assets/icons/radix/chevron-up.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/circle-backslash.svg b/assets/icons/radix/circle-backslash.svg deleted file mode 100644 index 40c4dd5398..0000000000 --- a/assets/icons/radix/circle-backslash.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/circle.svg b/assets/icons/radix/circle.svg deleted file mode 100644 index ba4a8f22fe..0000000000 --- a/assets/icons/radix/circle.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/clipboard-copy.svg b/assets/icons/radix/clipboard-copy.svg deleted file mode 100644 index 5293fdc493..0000000000 --- a/assets/icons/radix/clipboard-copy.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/clipboard.svg b/assets/icons/radix/clipboard.svg deleted file mode 100644 index e18b32943b..0000000000 --- a/assets/icons/radix/clipboard.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/clock.svg b/assets/icons/radix/clock.svg deleted file mode 100644 index ac3b526fbb..0000000000 --- a/assets/icons/radix/clock.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/code.svg b/assets/icons/radix/code.svg deleted file mode 100644 index 70fe381b68..0000000000 --- a/assets/icons/radix/code.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/codesandbox-logo.svg b/assets/icons/radix/codesandbox-logo.svg deleted file mode 100644 index 4a3f549c2f..0000000000 --- a/assets/icons/radix/codesandbox-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/color-wheel.svg b/assets/icons/radix/color-wheel.svg deleted file mode 100644 index 2153b84428..0000000000 --- a/assets/icons/radix/color-wheel.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/column-spacing.svg b/assets/icons/radix/column-spacing.svg deleted file mode 100644 index aafcf555cb..0000000000 --- a/assets/icons/radix/column-spacing.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/columns.svg b/assets/icons/radix/columns.svg deleted file mode 100644 index e1607611b1..0000000000 --- a/assets/icons/radix/columns.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/commit.svg b/assets/icons/radix/commit.svg deleted file mode 100644 index ac128a2b08..0000000000 --- a/assets/icons/radix/commit.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/component-1.svg b/assets/icons/radix/component-1.svg deleted file mode 100644 index e3e9f38af1..0000000000 --- a/assets/icons/radix/component-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/component-2.svg b/assets/icons/radix/component-2.svg deleted file mode 100644 index df2091d143..0000000000 --- a/assets/icons/radix/component-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/component-boolean.svg b/assets/icons/radix/component-boolean.svg deleted file mode 100644 index 942e8832eb..0000000000 --- a/assets/icons/radix/component-boolean.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/component-instance.svg b/assets/icons/radix/component-instance.svg deleted file mode 100644 index 048c401291..0000000000 --- a/assets/icons/radix/component-instance.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/component-none.svg b/assets/icons/radix/component-none.svg deleted file mode 100644 index a622c3ee96..0000000000 --- a/assets/icons/radix/component-none.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/component-placeholder.svg b/assets/icons/radix/component-placeholder.svg deleted file mode 100644 index b8892d5d23..0000000000 --- a/assets/icons/radix/component-placeholder.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/assets/icons/radix/container.svg b/assets/icons/radix/container.svg deleted file mode 100644 index 1c2a4fd0e1..0000000000 --- a/assets/icons/radix/container.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cookie.svg b/assets/icons/radix/cookie.svg deleted file mode 100644 index 8c165601a2..0000000000 --- a/assets/icons/radix/cookie.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/copy.svg b/assets/icons/radix/copy.svg deleted file mode 100644 index bf2b504ecf..0000000000 --- a/assets/icons/radix/copy.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/corner-bottom-left.svg b/assets/icons/radix/corner-bottom-left.svg deleted file mode 100644 index 26df9dbad8..0000000000 --- a/assets/icons/radix/corner-bottom-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/corner-bottom-right.svg b/assets/icons/radix/corner-bottom-right.svg deleted file mode 100644 index 15e3957123..0000000000 --- a/assets/icons/radix/corner-bottom-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/corner-top-left.svg b/assets/icons/radix/corner-top-left.svg deleted file mode 100644 index 8fc1b84b82..0000000000 --- a/assets/icons/radix/corner-top-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/corner-top-right.svg b/assets/icons/radix/corner-top-right.svg deleted file mode 100644 index 533ea6c678..0000000000 --- a/assets/icons/radix/corner-top-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/corners.svg b/assets/icons/radix/corners.svg deleted file mode 100644 index c41c4e0183..0000000000 --- a/assets/icons/radix/corners.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/countdown-timer.svg b/assets/icons/radix/countdown-timer.svg deleted file mode 100644 index 58494bd416..0000000000 --- a/assets/icons/radix/countdown-timer.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/counter-clockwise-clock.svg b/assets/icons/radix/counter-clockwise-clock.svg deleted file mode 100644 index 0b3acbcebf..0000000000 --- a/assets/icons/radix/counter-clockwise-clock.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/crop.svg b/assets/icons/radix/crop.svg deleted file mode 100644 index 008457fff6..0000000000 --- a/assets/icons/radix/crop.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cross-1.svg b/assets/icons/radix/cross-1.svg deleted file mode 100644 index 62135d27ed..0000000000 --- a/assets/icons/radix/cross-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cross-2.svg b/assets/icons/radix/cross-2.svg deleted file mode 100644 index 4c55700928..0000000000 --- a/assets/icons/radix/cross-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cross-circled.svg b/assets/icons/radix/cross-circled.svg deleted file mode 100644 index df3cb896c8..0000000000 --- a/assets/icons/radix/cross-circled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/crosshair-1.svg b/assets/icons/radix/crosshair-1.svg deleted file mode 100644 index 05b22f8461..0000000000 --- a/assets/icons/radix/crosshair-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/crosshair-2.svg b/assets/icons/radix/crosshair-2.svg deleted file mode 100644 index f5ee0a92af..0000000000 --- a/assets/icons/radix/crosshair-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/crumpled-paper.svg b/assets/icons/radix/crumpled-paper.svg deleted file mode 100644 index 33e9b65581..0000000000 --- a/assets/icons/radix/crumpled-paper.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cube.svg b/assets/icons/radix/cube.svg deleted file mode 100644 index b327158be4..0000000000 --- a/assets/icons/radix/cube.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cursor-arrow.svg b/assets/icons/radix/cursor-arrow.svg deleted file mode 100644 index b0227e4ded..0000000000 --- a/assets/icons/radix/cursor-arrow.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/cursor-text.svg b/assets/icons/radix/cursor-text.svg deleted file mode 100644 index 05939503b8..0000000000 --- a/assets/icons/radix/cursor-text.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/dash.svg b/assets/icons/radix/dash.svg deleted file mode 100644 index d70daf7fed..0000000000 --- a/assets/icons/radix/dash.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/dashboard.svg b/assets/icons/radix/dashboard.svg deleted file mode 100644 index 38008c64e4..0000000000 --- a/assets/icons/radix/dashboard.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/desktop-mute.svg b/assets/icons/radix/desktop-mute.svg deleted file mode 100644 index 83d249176f..0000000000 --- a/assets/icons/radix/desktop-mute.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/radix/dimensions.svg b/assets/icons/radix/dimensions.svg deleted file mode 100644 index 767d1d2896..0000000000 --- a/assets/icons/radix/dimensions.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/disc.svg b/assets/icons/radix/disc.svg deleted file mode 100644 index 6e19caab35..0000000000 --- a/assets/icons/radix/disc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/discord-logo.svg b/assets/icons/radix/discord-logo.svg deleted file mode 100644 index 50567c212e..0000000000 --- a/assets/icons/radix/discord-logo.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/assets/icons/radix/divider-horizontal.svg b/assets/icons/radix/divider-horizontal.svg deleted file mode 100644 index 59e43649c9..0000000000 --- a/assets/icons/radix/divider-horizontal.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/divider-vertical.svg b/assets/icons/radix/divider-vertical.svg deleted file mode 100644 index 95f5cc8f2f..0000000000 --- a/assets/icons/radix/divider-vertical.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/dot-filled.svg b/assets/icons/radix/dot-filled.svg deleted file mode 100644 index 0c1a17b3bd..0000000000 --- a/assets/icons/radix/dot-filled.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/assets/icons/radix/dot-solid.svg b/assets/icons/radix/dot-solid.svg deleted file mode 100644 index 0c1a17b3bd..0000000000 --- a/assets/icons/radix/dot-solid.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/assets/icons/radix/dot.svg b/assets/icons/radix/dot.svg deleted file mode 100644 index c553a1422d..0000000000 --- a/assets/icons/radix/dot.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/dots-horizontal.svg b/assets/icons/radix/dots-horizontal.svg deleted file mode 100644 index 347d1ae13d..0000000000 --- a/assets/icons/radix/dots-horizontal.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/dots-vertical.svg b/assets/icons/radix/dots-vertical.svg deleted file mode 100644 index 5ca1a181e3..0000000000 --- a/assets/icons/radix/dots-vertical.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/double-arrow-down.svg b/assets/icons/radix/double-arrow-down.svg deleted file mode 100644 index 8b86db2f8a..0000000000 --- a/assets/icons/radix/double-arrow-down.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/double-arrow-left.svg b/assets/icons/radix/double-arrow-left.svg deleted file mode 100644 index 0ef30ff955..0000000000 --- a/assets/icons/radix/double-arrow-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/double-arrow-right.svg b/assets/icons/radix/double-arrow-right.svg deleted file mode 100644 index 9997fdc403..0000000000 --- a/assets/icons/radix/double-arrow-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/double-arrow-up.svg b/assets/icons/radix/double-arrow-up.svg deleted file mode 100644 index 8d571fcd66..0000000000 --- a/assets/icons/radix/double-arrow-up.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/download.svg b/assets/icons/radix/download.svg deleted file mode 100644 index 49a05d5f47..0000000000 --- a/assets/icons/radix/download.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/drag-handle-dots-1.svg b/assets/icons/radix/drag-handle-dots-1.svg deleted file mode 100644 index fc046bb9d9..0000000000 --- a/assets/icons/radix/drag-handle-dots-1.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/icons/radix/drag-handle-dots-2.svg b/assets/icons/radix/drag-handle-dots-2.svg deleted file mode 100644 index aed0e702d7..0000000000 --- a/assets/icons/radix/drag-handle-dots-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/drag-handle-horizontal.svg b/assets/icons/radix/drag-handle-horizontal.svg deleted file mode 100644 index c1bb138a24..0000000000 --- a/assets/icons/radix/drag-handle-horizontal.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/drag-handle-vertical.svg b/assets/icons/radix/drag-handle-vertical.svg deleted file mode 100644 index 8d48c7894a..0000000000 --- a/assets/icons/radix/drag-handle-vertical.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/drawing-pin-filled.svg b/assets/icons/radix/drawing-pin-filled.svg deleted file mode 100644 index e1894619c3..0000000000 --- a/assets/icons/radix/drawing-pin-filled.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/assets/icons/radix/drawing-pin-solid.svg b/assets/icons/radix/drawing-pin-solid.svg deleted file mode 100644 index e1894619c3..0000000000 --- a/assets/icons/radix/drawing-pin-solid.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/assets/icons/radix/drawing-pin.svg b/assets/icons/radix/drawing-pin.svg deleted file mode 100644 index 5625e7588f..0000000000 --- a/assets/icons/radix/drawing-pin.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/dropdown-menu.svg b/assets/icons/radix/dropdown-menu.svg deleted file mode 100644 index c938052be8..0000000000 --- a/assets/icons/radix/dropdown-menu.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/enter-full-screen.svg b/assets/icons/radix/enter-full-screen.svg deleted file mode 100644 index d368a6d415..0000000000 --- a/assets/icons/radix/enter-full-screen.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/enter.svg b/assets/icons/radix/enter.svg deleted file mode 100644 index cc57d74cea..0000000000 --- a/assets/icons/radix/enter.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/envelope-closed.svg b/assets/icons/radix/envelope-closed.svg deleted file mode 100644 index 4b5e037840..0000000000 --- a/assets/icons/radix/envelope-closed.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/envelope-open.svg b/assets/icons/radix/envelope-open.svg deleted file mode 100644 index df1e3fea95..0000000000 --- a/assets/icons/radix/envelope-open.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/eraser.svg b/assets/icons/radix/eraser.svg deleted file mode 100644 index bb448d4d23..0000000000 --- a/assets/icons/radix/eraser.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/exclamation-triangle.svg b/assets/icons/radix/exclamation-triangle.svg deleted file mode 100644 index 210d4c45c6..0000000000 --- a/assets/icons/radix/exclamation-triangle.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/exit-full-screen.svg b/assets/icons/radix/exit-full-screen.svg deleted file mode 100644 index 9b6439b043..0000000000 --- a/assets/icons/radix/exit-full-screen.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/exit.svg b/assets/icons/radix/exit.svg deleted file mode 100644 index 2cc6ce120d..0000000000 --- a/assets/icons/radix/exit.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/external-link.svg b/assets/icons/radix/external-link.svg deleted file mode 100644 index 0ee7420162..0000000000 --- a/assets/icons/radix/external-link.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/eye-closed.svg b/assets/icons/radix/eye-closed.svg deleted file mode 100644 index f824fe55f9..0000000000 --- a/assets/icons/radix/eye-closed.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/eye-none.svg b/assets/icons/radix/eye-none.svg deleted file mode 100644 index d4beecd33a..0000000000 --- a/assets/icons/radix/eye-none.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/eye-open.svg b/assets/icons/radix/eye-open.svg deleted file mode 100644 index d39d26b2c1..0000000000 --- a/assets/icons/radix/eye-open.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/face.svg b/assets/icons/radix/face.svg deleted file mode 100644 index 81b14dd8d7..0000000000 --- a/assets/icons/radix/face.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/figma-logo.svg b/assets/icons/radix/figma-logo.svg deleted file mode 100644 index 6c19276554..0000000000 --- a/assets/icons/radix/figma-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/file-minus.svg b/assets/icons/radix/file-minus.svg deleted file mode 100644 index bd1a841881..0000000000 --- a/assets/icons/radix/file-minus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/file-plus.svg b/assets/icons/radix/file-plus.svg deleted file mode 100644 index 2396e20015..0000000000 --- a/assets/icons/radix/file-plus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/file-text.svg b/assets/icons/radix/file-text.svg deleted file mode 100644 index f341ab8abf..0000000000 --- a/assets/icons/radix/file-text.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/font-bold.svg b/assets/icons/radix/font-bold.svg deleted file mode 100644 index 7dc6caf3b0..0000000000 --- a/assets/icons/radix/font-bold.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/assets/icons/radix/font-family.svg b/assets/icons/radix/font-family.svg deleted file mode 100644 index 9134b9086d..0000000000 --- a/assets/icons/radix/font-family.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/assets/icons/radix/font-italic.svg b/assets/icons/radix/font-italic.svg deleted file mode 100644 index 6e6288d6bc..0000000000 --- a/assets/icons/radix/font-italic.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/font-roman.svg b/assets/icons/radix/font-roman.svg deleted file mode 100644 index c595b790fc..0000000000 --- a/assets/icons/radix/font-roman.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/font-size.svg b/assets/icons/radix/font-size.svg deleted file mode 100644 index e389a58d73..0000000000 --- a/assets/icons/radix/font-size.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/font-style.svg b/assets/icons/radix/font-style.svg deleted file mode 100644 index 31c3730130..0000000000 --- a/assets/icons/radix/font-style.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/frame.svg b/assets/icons/radix/frame.svg deleted file mode 100644 index ec61a48efa..0000000000 --- a/assets/icons/radix/frame.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/framer-logo.svg b/assets/icons/radix/framer-logo.svg deleted file mode 100644 index 68be3b317b..0000000000 --- a/assets/icons/radix/framer-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/gear.svg b/assets/icons/radix/gear.svg deleted file mode 100644 index 52f9e17312..0000000000 --- a/assets/icons/radix/gear.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/github-logo.svg b/assets/icons/radix/github-logo.svg deleted file mode 100644 index e46612cf56..0000000000 --- a/assets/icons/radix/github-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/globe.svg b/assets/icons/radix/globe.svg deleted file mode 100644 index 4728b827df..0000000000 --- a/assets/icons/radix/globe.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - diff --git a/assets/icons/radix/grid.svg b/assets/icons/radix/grid.svg deleted file mode 100644 index 5d9af33572..0000000000 --- a/assets/icons/radix/grid.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/group.svg b/assets/icons/radix/group.svg deleted file mode 100644 index c3c91d211f..0000000000 --- a/assets/icons/radix/group.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/half-1.svg b/assets/icons/radix/half-1.svg deleted file mode 100644 index 9890e26bb8..0000000000 --- a/assets/icons/radix/half-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/half-2.svg b/assets/icons/radix/half-2.svg deleted file mode 100644 index 4db1d564cb..0000000000 --- a/assets/icons/radix/half-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/hamburger-menu.svg b/assets/icons/radix/hamburger-menu.svg deleted file mode 100644 index 039168055b..0000000000 --- a/assets/icons/radix/hamburger-menu.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/hand.svg b/assets/icons/radix/hand.svg deleted file mode 100644 index 12afac8f5f..0000000000 --- a/assets/icons/radix/hand.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/heading.svg b/assets/icons/radix/heading.svg deleted file mode 100644 index 0a5e2caaf1..0000000000 --- a/assets/icons/radix/heading.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/heart-filled.svg b/assets/icons/radix/heart-filled.svg deleted file mode 100644 index 94928accd7..0000000000 --- a/assets/icons/radix/heart-filled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/heart.svg b/assets/icons/radix/heart.svg deleted file mode 100644 index 91cbc450fd..0000000000 --- a/assets/icons/radix/heart.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/height.svg b/assets/icons/radix/height.svg deleted file mode 100644 index 28424f4d51..0000000000 --- a/assets/icons/radix/height.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/hobby-knife.svg b/assets/icons/radix/hobby-knife.svg deleted file mode 100644 index c2ed3fb1ed..0000000000 --- a/assets/icons/radix/hobby-knife.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/home.svg b/assets/icons/radix/home.svg deleted file mode 100644 index 733bd79113..0000000000 --- a/assets/icons/radix/home.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/iconjar-logo.svg b/assets/icons/radix/iconjar-logo.svg deleted file mode 100644 index c154b4e864..0000000000 --- a/assets/icons/radix/iconjar-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/id-card.svg b/assets/icons/radix/id-card.svg deleted file mode 100644 index efde9ffa7e..0000000000 --- a/assets/icons/radix/id-card.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/image.svg b/assets/icons/radix/image.svg deleted file mode 100644 index 0ff4475252..0000000000 --- a/assets/icons/radix/image.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/info-circled.svg b/assets/icons/radix/info-circled.svg deleted file mode 100644 index 4ab1b260e3..0000000000 --- a/assets/icons/radix/info-circled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/inner-shadow.svg b/assets/icons/radix/inner-shadow.svg deleted file mode 100644 index 1056a7bffc..0000000000 --- a/assets/icons/radix/inner-shadow.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - diff --git a/assets/icons/radix/input.svg b/assets/icons/radix/input.svg deleted file mode 100644 index 4ed4605b2c..0000000000 --- a/assets/icons/radix/input.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/instagram-logo.svg b/assets/icons/radix/instagram-logo.svg deleted file mode 100644 index 5d78937966..0000000000 --- a/assets/icons/radix/instagram-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/assets/icons/radix/justify-center.svg b/assets/icons/radix/justify-center.svg deleted file mode 100644 index 7999a4ea46..0000000000 --- a/assets/icons/radix/justify-center.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/justify-end.svg b/assets/icons/radix/justify-end.svg deleted file mode 100644 index bb52f493d7..0000000000 --- a/assets/icons/radix/justify-end.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/justify-start.svg b/assets/icons/radix/justify-start.svg deleted file mode 100644 index 648ca0b603..0000000000 --- a/assets/icons/radix/justify-start.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/justify-stretch.svg b/assets/icons/radix/justify-stretch.svg deleted file mode 100644 index 83df0a8959..0000000000 --- a/assets/icons/radix/justify-stretch.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/keyboard.svg b/assets/icons/radix/keyboard.svg deleted file mode 100644 index fc6f86bfc2..0000000000 --- a/assets/icons/radix/keyboard.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/assets/icons/radix/lap-timer.svg b/assets/icons/radix/lap-timer.svg deleted file mode 100644 index 1de0b3be6c..0000000000 --- a/assets/icons/radix/lap-timer.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/laptop.svg b/assets/icons/radix/laptop.svg deleted file mode 100644 index 6aff5d6d44..0000000000 --- a/assets/icons/radix/laptop.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/layers.svg b/assets/icons/radix/layers.svg deleted file mode 100644 index 821993fc70..0000000000 --- a/assets/icons/radix/layers.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/layout.svg b/assets/icons/radix/layout.svg deleted file mode 100644 index 8e4a352f50..0000000000 --- a/assets/icons/radix/layout.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/letter-case-capitalize.svg b/assets/icons/radix/letter-case-capitalize.svg deleted file mode 100644 index 16617ecf7e..0000000000 --- a/assets/icons/radix/letter-case-capitalize.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/letter-case-lowercase.svg b/assets/icons/radix/letter-case-lowercase.svg deleted file mode 100644 index 61aefb9aad..0000000000 --- a/assets/icons/radix/letter-case-lowercase.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/letter-case-toggle.svg b/assets/icons/radix/letter-case-toggle.svg deleted file mode 100644 index a021a2b922..0000000000 --- a/assets/icons/radix/letter-case-toggle.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/letter-case-uppercase.svg b/assets/icons/radix/letter-case-uppercase.svg deleted file mode 100644 index ccd2be04e7..0000000000 --- a/assets/icons/radix/letter-case-uppercase.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/letter-spacing.svg b/assets/icons/radix/letter-spacing.svg deleted file mode 100644 index 073023e0f4..0000000000 --- a/assets/icons/radix/letter-spacing.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/lightning-bolt.svg b/assets/icons/radix/lightning-bolt.svg deleted file mode 100644 index 7c35df9cfe..0000000000 --- a/assets/icons/radix/lightning-bolt.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/line-height.svg b/assets/icons/radix/line-height.svg deleted file mode 100644 index 1c302d1ffc..0000000000 --- a/assets/icons/radix/line-height.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/link-1.svg b/assets/icons/radix/link-1.svg deleted file mode 100644 index d5682b113e..0000000000 --- a/assets/icons/radix/link-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/link-2.svg b/assets/icons/radix/link-2.svg deleted file mode 100644 index be8370606e..0000000000 --- a/assets/icons/radix/link-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/link-break-1.svg b/assets/icons/radix/link-break-1.svg deleted file mode 100644 index 05ae93e47a..0000000000 --- a/assets/icons/radix/link-break-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/link-break-2.svg b/assets/icons/radix/link-break-2.svg deleted file mode 100644 index 78f28f98e8..0000000000 --- a/assets/icons/radix/link-break-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/link-none-1.svg b/assets/icons/radix/link-none-1.svg deleted file mode 100644 index 6ea56a386f..0000000000 --- a/assets/icons/radix/link-none-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/link-none-2.svg b/assets/icons/radix/link-none-2.svg deleted file mode 100644 index 0b19d940d1..0000000000 --- a/assets/icons/radix/link-none-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/linkedin-logo.svg b/assets/icons/radix/linkedin-logo.svg deleted file mode 100644 index 0f0138bdf6..0000000000 --- a/assets/icons/radix/linkedin-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/list-bullet.svg b/assets/icons/radix/list-bullet.svg deleted file mode 100644 index 2630b95ef0..0000000000 --- a/assets/icons/radix/list-bullet.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/lock-closed.svg b/assets/icons/radix/lock-closed.svg deleted file mode 100644 index 3871b5d5ad..0000000000 --- a/assets/icons/radix/lock-closed.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/lock-open-1.svg b/assets/icons/radix/lock-open-1.svg deleted file mode 100644 index 8f6bfd5bbf..0000000000 --- a/assets/icons/radix/lock-open-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/lock-open-2.svg b/assets/icons/radix/lock-open-2.svg deleted file mode 100644 index ce69f67f29..0000000000 --- a/assets/icons/radix/lock-open-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/loop.svg b/assets/icons/radix/loop.svg deleted file mode 100644 index bfa90ed084..0000000000 --- a/assets/icons/radix/loop.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/magnifying-glass.svg b/assets/icons/radix/magnifying-glass.svg deleted file mode 100644 index a3a89bfa50..0000000000 --- a/assets/icons/radix/magnifying-glass.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/margin.svg b/assets/icons/radix/margin.svg deleted file mode 100644 index 1a513b37d6..0000000000 --- a/assets/icons/radix/margin.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/mask-off.svg b/assets/icons/radix/mask-off.svg deleted file mode 100644 index 5f847668e8..0000000000 --- a/assets/icons/radix/mask-off.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/mask-on.svg b/assets/icons/radix/mask-on.svg deleted file mode 100644 index 684c1b934d..0000000000 --- a/assets/icons/radix/mask-on.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/maximize.svg b/assets/icons/radix/maximize.svg deleted file mode 100644 index f37f6a2087..0000000000 --- a/assets/icons/radix/maximize.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/radix/minimize.svg b/assets/icons/radix/minimize.svg deleted file mode 100644 index ec78f152e1..0000000000 --- a/assets/icons/radix/minimize.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/radix/minus-circled.svg b/assets/icons/radix/minus-circled.svg deleted file mode 100644 index 2c6df4cebf..0000000000 --- a/assets/icons/radix/minus-circled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/minus.svg b/assets/icons/radix/minus.svg deleted file mode 100644 index 2b39602979..0000000000 --- a/assets/icons/radix/minus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/mix.svg b/assets/icons/radix/mix.svg deleted file mode 100644 index 9412a01843..0000000000 --- a/assets/icons/radix/mix.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/mixer-horizontal.svg b/assets/icons/radix/mixer-horizontal.svg deleted file mode 100644 index f29ba25548..0000000000 --- a/assets/icons/radix/mixer-horizontal.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/mixer-vertical.svg b/assets/icons/radix/mixer-vertical.svg deleted file mode 100644 index dc85d3a9e7..0000000000 --- a/assets/icons/radix/mixer-vertical.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/mobile.svg b/assets/icons/radix/mobile.svg deleted file mode 100644 index b62b6506ff..0000000000 --- a/assets/icons/radix/mobile.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/modulz-logo.svg b/assets/icons/radix/modulz-logo.svg deleted file mode 100644 index 754b229db6..0000000000 --- a/assets/icons/radix/modulz-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/moon.svg b/assets/icons/radix/moon.svg deleted file mode 100644 index 1dac2ca212..0000000000 --- a/assets/icons/radix/moon.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/move.svg b/assets/icons/radix/move.svg deleted file mode 100644 index 3d0a0e56c9..0000000000 --- a/assets/icons/radix/move.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/notion-logo.svg b/assets/icons/radix/notion-logo.svg deleted file mode 100644 index c2df152619..0000000000 --- a/assets/icons/radix/notion-logo.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/assets/icons/radix/opacity.svg b/assets/icons/radix/opacity.svg deleted file mode 100644 index a2d01bff82..0000000000 --- a/assets/icons/radix/opacity.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/open-in-new-window.svg b/assets/icons/radix/open-in-new-window.svg deleted file mode 100644 index 22baf82cff..0000000000 --- a/assets/icons/radix/open-in-new-window.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/assets/icons/radix/outer-shadow.svg b/assets/icons/radix/outer-shadow.svg deleted file mode 100644 index b44e3d553c..0000000000 --- a/assets/icons/radix/outer-shadow.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - diff --git a/assets/icons/radix/overline.svg b/assets/icons/radix/overline.svg deleted file mode 100644 index 57262c76e6..0000000000 --- a/assets/icons/radix/overline.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/padding.svg b/assets/icons/radix/padding.svg deleted file mode 100644 index 483a25a27e..0000000000 --- a/assets/icons/radix/padding.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/paper-plane.svg b/assets/icons/radix/paper-plane.svg deleted file mode 100644 index 37ad070300..0000000000 --- a/assets/icons/radix/paper-plane.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pause.svg b/assets/icons/radix/pause.svg deleted file mode 100644 index b399fb2f5a..0000000000 --- a/assets/icons/radix/pause.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pencil-1.svg b/assets/icons/radix/pencil-1.svg deleted file mode 100644 index decf0122ef..0000000000 --- a/assets/icons/radix/pencil-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pencil-2.svg b/assets/icons/radix/pencil-2.svg deleted file mode 100644 index 2559a393a9..0000000000 --- a/assets/icons/radix/pencil-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/person.svg b/assets/icons/radix/person.svg deleted file mode 100644 index 051abcc703..0000000000 --- a/assets/icons/radix/person.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pie-chart.svg b/assets/icons/radix/pie-chart.svg deleted file mode 100644 index bb58e47274..0000000000 --- a/assets/icons/radix/pie-chart.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pilcrow.svg b/assets/icons/radix/pilcrow.svg deleted file mode 100644 index 6996765fd6..0000000000 --- a/assets/icons/radix/pilcrow.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pin-bottom.svg b/assets/icons/radix/pin-bottom.svg deleted file mode 100644 index ad0842054f..0000000000 --- a/assets/icons/radix/pin-bottom.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pin-left.svg b/assets/icons/radix/pin-left.svg deleted file mode 100644 index eb89b2912f..0000000000 --- a/assets/icons/radix/pin-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pin-right.svg b/assets/icons/radix/pin-right.svg deleted file mode 100644 index 89a98bae4e..0000000000 --- a/assets/icons/radix/pin-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/pin-top.svg b/assets/icons/radix/pin-top.svg deleted file mode 100644 index edfeb64d5d..0000000000 --- a/assets/icons/radix/pin-top.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/play.svg b/assets/icons/radix/play.svg deleted file mode 100644 index 92af9e1ae7..0000000000 --- a/assets/icons/radix/play.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/plus-circled.svg b/assets/icons/radix/plus-circled.svg deleted file mode 100644 index 808ddc4c2c..0000000000 --- a/assets/icons/radix/plus-circled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/plus.svg b/assets/icons/radix/plus.svg deleted file mode 100644 index 57ce90219b..0000000000 --- a/assets/icons/radix/plus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/question-mark-circled.svg b/assets/icons/radix/question-mark-circled.svg deleted file mode 100644 index be99968787..0000000000 --- a/assets/icons/radix/question-mark-circled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/question-mark.svg b/assets/icons/radix/question-mark.svg deleted file mode 100644 index 577aae5349..0000000000 --- a/assets/icons/radix/question-mark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/radiobutton.svg b/assets/icons/radix/radiobutton.svg deleted file mode 100644 index f0c3a60aee..0000000000 --- a/assets/icons/radix/radiobutton.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/reader.svg b/assets/icons/radix/reader.svg deleted file mode 100644 index e893cfa685..0000000000 --- a/assets/icons/radix/reader.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/reload.svg b/assets/icons/radix/reload.svg deleted file mode 100644 index cf1dfb7fa2..0000000000 --- a/assets/icons/radix/reload.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/reset.svg b/assets/icons/radix/reset.svg deleted file mode 100644 index f21a508514..0000000000 --- a/assets/icons/radix/reset.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/resume.svg b/assets/icons/radix/resume.svg deleted file mode 100644 index 79cdec2374..0000000000 --- a/assets/icons/radix/resume.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/rocket.svg b/assets/icons/radix/rocket.svg deleted file mode 100644 index 2226aacb1a..0000000000 --- a/assets/icons/radix/rocket.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/rotate-counter-clockwise.svg b/assets/icons/radix/rotate-counter-clockwise.svg deleted file mode 100644 index c43c90b90b..0000000000 --- a/assets/icons/radix/rotate-counter-clockwise.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/row-spacing.svg b/assets/icons/radix/row-spacing.svg deleted file mode 100644 index e155bd5947..0000000000 --- a/assets/icons/radix/row-spacing.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/rows.svg b/assets/icons/radix/rows.svg deleted file mode 100644 index fb4ca0f9e3..0000000000 --- a/assets/icons/radix/rows.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/ruler-horizontal.svg b/assets/icons/radix/ruler-horizontal.svg deleted file mode 100644 index db6f1ef488..0000000000 --- a/assets/icons/radix/ruler-horizontal.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/ruler-square.svg b/assets/icons/radix/ruler-square.svg deleted file mode 100644 index 7de70cc5dc..0000000000 --- a/assets/icons/radix/ruler-square.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/scissors.svg b/assets/icons/radix/scissors.svg deleted file mode 100644 index 2893b34712..0000000000 --- a/assets/icons/radix/scissors.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/section.svg b/assets/icons/radix/section.svg deleted file mode 100644 index 1e939e2b2f..0000000000 --- a/assets/icons/radix/section.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/sewing-pin-filled.svg b/assets/icons/radix/sewing-pin-filled.svg deleted file mode 100644 index 97f6f1120d..0000000000 --- a/assets/icons/radix/sewing-pin-filled.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/sewing-pin-solid.svg b/assets/icons/radix/sewing-pin-solid.svg deleted file mode 100644 index 97f6f1120d..0000000000 --- a/assets/icons/radix/sewing-pin-solid.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/sewing-pin.svg b/assets/icons/radix/sewing-pin.svg deleted file mode 100644 index 068dfd7bdf..0000000000 --- a/assets/icons/radix/sewing-pin.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/shadow-inner.svg b/assets/icons/radix/shadow-inner.svg deleted file mode 100644 index 4d073bf35f..0000000000 --- a/assets/icons/radix/shadow-inner.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - diff --git a/assets/icons/radix/shadow-none.svg b/assets/icons/radix/shadow-none.svg deleted file mode 100644 index b02d3466ad..0000000000 --- a/assets/icons/radix/shadow-none.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - diff --git a/assets/icons/radix/shadow-outer.svg b/assets/icons/radix/shadow-outer.svg deleted file mode 100644 index dc7ea84087..0000000000 --- a/assets/icons/radix/shadow-outer.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - diff --git a/assets/icons/radix/shadow.svg b/assets/icons/radix/shadow.svg deleted file mode 100644 index c991af6156..0000000000 --- a/assets/icons/radix/shadow.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - diff --git a/assets/icons/radix/share-1.svg b/assets/icons/radix/share-1.svg deleted file mode 100644 index 58328e4d1e..0000000000 --- a/assets/icons/radix/share-1.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/share-2.svg b/assets/icons/radix/share-2.svg deleted file mode 100644 index 1302ea5fbe..0000000000 --- a/assets/icons/radix/share-2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/shuffle.svg b/assets/icons/radix/shuffle.svg deleted file mode 100644 index 8670e1a048..0000000000 --- a/assets/icons/radix/shuffle.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/size.svg b/assets/icons/radix/size.svg deleted file mode 100644 index dece8c5182..0000000000 --- a/assets/icons/radix/size.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/sketch-logo.svg b/assets/icons/radix/sketch-logo.svg deleted file mode 100644 index 6c54c4c825..0000000000 --- a/assets/icons/radix/sketch-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/slash.svg b/assets/icons/radix/slash.svg deleted file mode 100644 index aa7dac30c1..0000000000 --- a/assets/icons/radix/slash.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/slider.svg b/assets/icons/radix/slider.svg deleted file mode 100644 index 66e0452bc0..0000000000 --- a/assets/icons/radix/slider.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/space-between-horizontally.svg b/assets/icons/radix/space-between-horizontally.svg deleted file mode 100644 index a71638d52b..0000000000 --- a/assets/icons/radix/space-between-horizontally.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/space-between-vertically.svg b/assets/icons/radix/space-between-vertically.svg deleted file mode 100644 index bae247222f..0000000000 --- a/assets/icons/radix/space-between-vertically.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/space-evenly-horizontally.svg b/assets/icons/radix/space-evenly-horizontally.svg deleted file mode 100644 index 70169492e4..0000000000 --- a/assets/icons/radix/space-evenly-horizontally.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/space-evenly-vertically.svg b/assets/icons/radix/space-evenly-vertically.svg deleted file mode 100644 index 469b4c05d4..0000000000 --- a/assets/icons/radix/space-evenly-vertically.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/speaker-moderate.svg b/assets/icons/radix/speaker-moderate.svg deleted file mode 100644 index 0f1d1b4210..0000000000 --- a/assets/icons/radix/speaker-moderate.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/speaker-quiet.svg b/assets/icons/radix/speaker-quiet.svg deleted file mode 100644 index eb68cefcee..0000000000 --- a/assets/icons/radix/speaker-quiet.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/square.svg b/assets/icons/radix/square.svg deleted file mode 100644 index 82843f51c3..0000000000 --- a/assets/icons/radix/square.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/stack.svg b/assets/icons/radix/stack.svg deleted file mode 100644 index 92426ffb0d..0000000000 --- a/assets/icons/radix/stack.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/star-filled.svg b/assets/icons/radix/star-filled.svg deleted file mode 100644 index 2b17b7f579..0000000000 --- a/assets/icons/radix/star-filled.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/assets/icons/radix/star.svg b/assets/icons/radix/star.svg deleted file mode 100644 index 23f09ad7b2..0000000000 --- a/assets/icons/radix/star.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/stitches-logo.svg b/assets/icons/radix/stitches-logo.svg deleted file mode 100644 index 319a1481f3..0000000000 --- a/assets/icons/radix/stitches-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/stop.svg b/assets/icons/radix/stop.svg deleted file mode 100644 index 57aac59cab..0000000000 --- a/assets/icons/radix/stop.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/stopwatch.svg b/assets/icons/radix/stopwatch.svg deleted file mode 100644 index ce5661e5cc..0000000000 --- a/assets/icons/radix/stopwatch.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/stretch-horizontally.svg b/assets/icons/radix/stretch-horizontally.svg deleted file mode 100644 index 37977363b3..0000000000 --- a/assets/icons/radix/stretch-horizontally.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/stretch-vertically.svg b/assets/icons/radix/stretch-vertically.svg deleted file mode 100644 index c4b1fe79ce..0000000000 --- a/assets/icons/radix/stretch-vertically.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/strikethrough.svg b/assets/icons/radix/strikethrough.svg deleted file mode 100644 index b814ef420a..0000000000 --- a/assets/icons/radix/strikethrough.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/sun.svg b/assets/icons/radix/sun.svg deleted file mode 100644 index 1807a51b4c..0000000000 --- a/assets/icons/radix/sun.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/switch.svg b/assets/icons/radix/switch.svg deleted file mode 100644 index 6dea528ce9..0000000000 --- a/assets/icons/radix/switch.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/symbol.svg b/assets/icons/radix/symbol.svg deleted file mode 100644 index b529b2b08b..0000000000 --- a/assets/icons/radix/symbol.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/table.svg b/assets/icons/radix/table.svg deleted file mode 100644 index 8ff059b847..0000000000 --- a/assets/icons/radix/table.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/target.svg b/assets/icons/radix/target.svg deleted file mode 100644 index d67989e01f..0000000000 --- a/assets/icons/radix/target.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-bottom.svg b/assets/icons/radix/text-align-bottom.svg deleted file mode 100644 index 862a5aeb88..0000000000 --- a/assets/icons/radix/text-align-bottom.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-center.svg b/assets/icons/radix/text-align-center.svg deleted file mode 100644 index 673cf8cd0a..0000000000 --- a/assets/icons/radix/text-align-center.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-justify.svg b/assets/icons/radix/text-align-justify.svg deleted file mode 100644 index df877f9513..0000000000 --- a/assets/icons/radix/text-align-justify.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-left.svg b/assets/icons/radix/text-align-left.svg deleted file mode 100644 index b7a64fbd43..0000000000 --- a/assets/icons/radix/text-align-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-middle.svg b/assets/icons/radix/text-align-middle.svg deleted file mode 100644 index e739d04efa..0000000000 --- a/assets/icons/radix/text-align-middle.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-right.svg b/assets/icons/radix/text-align-right.svg deleted file mode 100644 index e7609908ff..0000000000 --- a/assets/icons/radix/text-align-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-align-top.svg b/assets/icons/radix/text-align-top.svg deleted file mode 100644 index 21660fe7d3..0000000000 --- a/assets/icons/radix/text-align-top.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text-none.svg b/assets/icons/radix/text-none.svg deleted file mode 100644 index 2a87f9372a..0000000000 --- a/assets/icons/radix/text-none.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/text.svg b/assets/icons/radix/text.svg deleted file mode 100644 index bd41d8ac19..0000000000 --- a/assets/icons/radix/text.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/thick-arrow-down.svg b/assets/icons/radix/thick-arrow-down.svg deleted file mode 100644 index 32923bec58..0000000000 --- a/assets/icons/radix/thick-arrow-down.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/thick-arrow-left.svg b/assets/icons/radix/thick-arrow-left.svg deleted file mode 100644 index 0cfd863903..0000000000 --- a/assets/icons/radix/thick-arrow-left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/thick-arrow-right.svg b/assets/icons/radix/thick-arrow-right.svg deleted file mode 100644 index a0cb605693..0000000000 --- a/assets/icons/radix/thick-arrow-right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/thick-arrow-up.svg b/assets/icons/radix/thick-arrow-up.svg deleted file mode 100644 index 68687be28d..0000000000 --- a/assets/icons/radix/thick-arrow-up.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/timer.svg b/assets/icons/radix/timer.svg deleted file mode 100644 index 20c52dff95..0000000000 --- a/assets/icons/radix/timer.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/tokens.svg b/assets/icons/radix/tokens.svg deleted file mode 100644 index 2bbbc82030..0000000000 --- a/assets/icons/radix/tokens.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/track-next.svg b/assets/icons/radix/track-next.svg deleted file mode 100644 index 24fd40e36f..0000000000 --- a/assets/icons/radix/track-next.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/track-previous.svg b/assets/icons/radix/track-previous.svg deleted file mode 100644 index d99e7ab53f..0000000000 --- a/assets/icons/radix/track-previous.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/transform.svg b/assets/icons/radix/transform.svg deleted file mode 100644 index e913ccc9a7..0000000000 --- a/assets/icons/radix/transform.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/transparency-grid.svg b/assets/icons/radix/transparency-grid.svg deleted file mode 100644 index 6559ef8c2b..0000000000 --- a/assets/icons/radix/transparency-grid.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/assets/icons/radix/trash.svg b/assets/icons/radix/trash.svg deleted file mode 100644 index 18780e492c..0000000000 --- a/assets/icons/radix/trash.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/triangle-down.svg b/assets/icons/radix/triangle-down.svg deleted file mode 100644 index ebfd8f2a12..0000000000 --- a/assets/icons/radix/triangle-down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/triangle-left.svg b/assets/icons/radix/triangle-left.svg deleted file mode 100644 index 0014139716..0000000000 --- a/assets/icons/radix/triangle-left.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/triangle-right.svg b/assets/icons/radix/triangle-right.svg deleted file mode 100644 index aed1393b9c..0000000000 --- a/assets/icons/radix/triangle-right.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/triangle-up.svg b/assets/icons/radix/triangle-up.svg deleted file mode 100644 index 5eb1b416d3..0000000000 --- a/assets/icons/radix/triangle-up.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/radix/twitter-logo.svg b/assets/icons/radix/twitter-logo.svg deleted file mode 100644 index 7dcf2f58eb..0000000000 --- a/assets/icons/radix/twitter-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/underline.svg b/assets/icons/radix/underline.svg deleted file mode 100644 index 3344685097..0000000000 --- a/assets/icons/radix/underline.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/update.svg b/assets/icons/radix/update.svg deleted file mode 100644 index b529b2b08b..0000000000 --- a/assets/icons/radix/update.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/upload.svg b/assets/icons/radix/upload.svg deleted file mode 100644 index a7f6bddb2e..0000000000 --- a/assets/icons/radix/upload.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/value-none.svg b/assets/icons/radix/value-none.svg deleted file mode 100644 index a86c08be1a..0000000000 --- a/assets/icons/radix/value-none.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/value.svg b/assets/icons/radix/value.svg deleted file mode 100644 index 59dd7d9373..0000000000 --- a/assets/icons/radix/value.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/vercel-logo.svg b/assets/icons/radix/vercel-logo.svg deleted file mode 100644 index 5466fd9f0e..0000000000 --- a/assets/icons/radix/vercel-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/video.svg b/assets/icons/radix/video.svg deleted file mode 100644 index e405396bef..0000000000 --- a/assets/icons/radix/video.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/view-grid.svg b/assets/icons/radix/view-grid.svg deleted file mode 100644 index 04825a870b..0000000000 --- a/assets/icons/radix/view-grid.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/view-horizontal.svg b/assets/icons/radix/view-horizontal.svg deleted file mode 100644 index 2ca7336b99..0000000000 --- a/assets/icons/radix/view-horizontal.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/view-none.svg b/assets/icons/radix/view-none.svg deleted file mode 100644 index 71b08a46d2..0000000000 --- a/assets/icons/radix/view-none.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/view-vertical.svg b/assets/icons/radix/view-vertical.svg deleted file mode 100644 index 0c8f8164b4..0000000000 --- a/assets/icons/radix/view-vertical.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/width.svg b/assets/icons/radix/width.svg deleted file mode 100644 index 3ae2b56e3d..0000000000 --- a/assets/icons/radix/width.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/zoom-in.svg b/assets/icons/radix/zoom-in.svg deleted file mode 100644 index caac722ad0..0000000000 --- a/assets/icons/radix/zoom-in.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/radix/zoom-out.svg b/assets/icons/radix/zoom-out.svg deleted file mode 100644 index 62046a9e0f..0000000000 --- a/assets/icons/radix/zoom-out.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/assets/icons/robot_14.svg b/assets/icons/robot_14.svg deleted file mode 100644 index 7b6dc3f752..0000000000 --- a/assets/icons/robot_14.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/screen.svg b/assets/icons/screen.svg deleted file mode 100644 index 49e097b023..0000000000 --- a/assets/icons/screen.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/radix/speaker-loud.svg b/assets/icons/speaker-loud.svg similarity index 100% rename from assets/icons/radix/speaker-loud.svg rename to assets/icons/speaker-loud.svg diff --git a/assets/icons/radix/speaker-off.svg b/assets/icons/speaker-off.svg similarity index 100% rename from assets/icons/radix/speaker-off.svg rename to assets/icons/speaker-off.svg diff --git a/assets/icons/speech_bubble_12.svg b/assets/icons/speech_bubble_12.svg deleted file mode 100644 index 736f39a984..0000000000 --- a/assets/icons/speech_bubble_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/split_12.svg b/assets/icons/split_12.svg deleted file mode 100644 index e4cf1921fa..0000000000 --- a/assets/icons/split_12.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/assets/icons/split_message_15.svg b/assets/icons/split_message.svg similarity index 100% rename from assets/icons/split_message_15.svg rename to assets/icons/split_message.svg diff --git a/assets/icons/stop_sharing.svg b/assets/icons/stop_sharing.svg deleted file mode 100644 index e9aa7eac5a..0000000000 --- a/assets/icons/stop_sharing.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/success.svg b/assets/icons/success.svg deleted file mode 100644 index 85450cdc43..0000000000 --- a/assets/icons/success.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/assets/icons/terminal_12.svg b/assets/icons/terminal_12.svg deleted file mode 100644 index 9d5a9447b5..0000000000 --- a/assets/icons/terminal_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/terminal_16.svg b/assets/icons/terminal_16.svg deleted file mode 100644 index 95da7ff4e1..0000000000 --- a/assets/icons/terminal_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/terminal_8.svg b/assets/icons/terminal_8.svg deleted file mode 100644 index b09495dcf9..0000000000 --- a/assets/icons/terminal_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/triangle_exclamation_12.svg b/assets/icons/triangle_exclamation_12.svg deleted file mode 100644 index f87d365bdf..0000000000 --- a/assets/icons/triangle_exclamation_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/triangle_exclamation_16.svg b/assets/icons/triangle_exclamation_16.svg deleted file mode 100644 index 2df386203a..0000000000 --- a/assets/icons/triangle_exclamation_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/triangle_exclamation_8.svg b/assets/icons/triangle_exclamation_8.svg deleted file mode 100644 index 96f11015b1..0000000000 --- a/assets/icons/triangle_exclamation_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/unlock_8.svg b/assets/icons/unlock_8.svg deleted file mode 100644 index 7a40f94345..0000000000 --- a/assets/icons/unlock_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/user_circle_12.svg b/assets/icons/user_circle_12.svg deleted file mode 100644 index 8631c36fd6..0000000000 --- a/assets/icons/user_circle_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/user_circle_8.svg b/assets/icons/user_circle_8.svg deleted file mode 100644 index 304001d546..0000000000 --- a/assets/icons/user_circle_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/user_group_12.svg b/assets/icons/user_group_12.svg deleted file mode 100644 index 5eae1d55b7..0000000000 --- a/assets/icons/user_group_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/user_group_16.svg b/assets/icons/user_group_16.svg deleted file mode 100644 index aa99277646..0000000000 --- a/assets/icons/user_group_16.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/user_group_8.svg b/assets/icons/user_group_8.svg deleted file mode 100644 index 69d08b0d3b..0000000000 --- a/assets/icons/user_group_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/user_plus_12.svg b/assets/icons/user_plus_12.svg deleted file mode 100644 index 535d04af45..0000000000 --- a/assets/icons/user_plus_12.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/user_plus_16.svg b/assets/icons/user_plus_16.svg deleted file mode 100644 index 150392f6e0..0000000000 --- a/assets/icons/user_plus_16.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/assets/icons/user_plus_8.svg b/assets/icons/user_plus_8.svg deleted file mode 100644 index 100b43af86..0000000000 --- a/assets/icons/user_plus_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/version_control_branch_12.svg b/assets/icons/version_control_branch_12.svg deleted file mode 100644 index 3571874a89..0000000000 --- a/assets/icons/version_control_branch_12.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/word_search_14.svg b/assets/icons/word_search.svg similarity index 100% rename from assets/icons/word_search_14.svg rename to assets/icons/word_search.svg diff --git a/assets/icons/word_search_12.svg b/assets/icons/word_search_12.svg deleted file mode 100644 index 4cf6401fd2..0000000000 --- a/assets/icons/word_search_12.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/assets/icons/x_mark_12.svg b/assets/icons/x_mark_12.svg deleted file mode 100644 index 1c95f979d0..0000000000 --- a/assets/icons/x_mark_12.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/x_mark_16.svg b/assets/icons/x_mark_16.svg deleted file mode 100644 index 21a7f1c210..0000000000 --- a/assets/icons/x_mark_16.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/x_mark_8.svg b/assets/icons/x_mark_8.svg deleted file mode 100644 index f724b1515e..0000000000 --- a/assets/icons/x_mark_8.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/zed_plus_copilot_32.svg b/assets/icons/zed_x_copilot.svg similarity index 100% rename from assets/icons/zed_plus_copilot_32.svg rename to assets/icons/zed_x_copilot.svg diff --git a/crates/activity_indicator/src/activity_indicator.rs b/crates/activity_indicator/src/activity_indicator.rs index 6d1db5ada5..f9b34add9a 100644 --- a/crates/activity_indicator/src/activity_indicator.rs +++ b/crates/activity_indicator/src/activity_indicator.rs @@ -16,8 +16,8 @@ use workspace::{item::ItemHandle, StatusItemView, Workspace}; actions!(lsp_status, [ShowErrorMessage]); -const DOWNLOAD_ICON: &str = "icons/download_12.svg"; -const WARNING_ICON: &str = "icons/triangle_exclamation_12.svg"; +const DOWNLOAD_ICON: &str = "icons/download.svg"; +const WARNING_ICON: &str = "icons/warning.svg"; pub enum Event { ShowError { lsp_name: Arc, error: String }, diff --git a/crates/ai/src/assistant.rs b/crates/ai/src/assistant.rs index a7028df7a0..7fa66f26fb 100644 --- a/crates/ai/src/assistant.rs +++ b/crates/ai/src/assistant.rs @@ -2376,7 +2376,7 @@ impl ConversationEditor { .with_children( if let MessageStatus::Error(error) = &message.status { Some( - Svg::new("icons/circle_x_mark_12.svg") + Svg::new("icons/error.svg") .with_color(style.error_icon.color) .constrained() .with_width(style.error_icon.width) @@ -2704,7 +2704,7 @@ impl View for InlineAssistant { ) .with_children(if let Some(error) = self.codegen.read(cx).error() { Some( - Svg::new("icons/circle_x_mark_12.svg") + Svg::new("icons/error.svg") .with_color(theme.assistant.error_icon.color) .constrained() .with_width(theme.assistant.error_icon.width) diff --git a/crates/auto_update/src/update_notification.rs b/crates/auto_update/src/update_notification.rs index 8397fa0745..e4a5c23534 100644 --- a/crates/auto_update/src/update_notification.rs +++ b/crates/auto_update/src/update_notification.rs @@ -50,7 +50,7 @@ impl View for UpdateNotification { .with_child( MouseEventHandler::new::(0, cx, |state, _| { let style = theme.dismiss_button.style_for(state); - Svg::new("icons/x_mark_8.svg") + Svg::new("icons/x.svg") .with_color(style.color) .constrained() .with_width(style.icon_width) diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 8e0252ec60..c2a2b35134 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -1249,7 +1249,7 @@ impl CollabPanel { .collab_panel .add_contact_button .style_for(is_selected, state), - "icons/plus_16.svg", + "icons/plus.svg", ) }) .with_cursor_style(CursorStyle::PointingHand) @@ -1668,7 +1668,7 @@ impl CollabPanel { cx.font_cache(), )) .with_child( - Svg::new("icons/radix/file.svg") + Svg::new("icons/file.svg") .with_color(theme.channel_hash.color) .constrained() .with_width(theme.channel_hash.width) diff --git a/crates/collab_ui/src/collab_panel/contact_finder.rs b/crates/collab_ui/src/collab_panel/contact_finder.rs index 539e041ae7..9f96aa4b60 100644 --- a/crates/collab_ui/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui/src/collab_panel/contact_finder.rs @@ -211,7 +211,7 @@ impl PickerDelegate for ContactFinderDelegate { ContactRequestStatus::None | ContactRequestStatus::RequestReceived => { Some("icons/check_8.svg") } - ContactRequestStatus::RequestSent => Some("icons/x_mark_8.svg"), + ContactRequestStatus::RequestSent => Some("icons/x.svg"), ContactRequestStatus::RequestAccepted => None, }; let button_style = if self.user_store.read(cx).is_contact_request_pending(user) { diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index f0e09e139e..4537bf04e0 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -483,10 +483,10 @@ impl CollabTitlebarItem { let icon; let tooltip; if room.read(cx).is_screen_sharing() { - icon = "icons/radix/desktop.svg"; + icon = "icons/desktop.svg"; tooltip = "Stop Sharing Screen" } else { - icon = "icons/radix/desktop.svg"; + icon = "icons/desktop.svg"; tooltip = "Share Screen"; } @@ -533,10 +533,10 @@ impl CollabTitlebarItem { let tooltip; let is_muted = room.read(cx).is_muted(cx); if is_muted { - icon = "icons/radix/mic-mute.svg"; + icon = "icons/mic-mute.svg"; tooltip = "Unmute microphone"; } else { - icon = "icons/radix/mic.svg"; + icon = "icons/mic.svg"; tooltip = "Mute microphone"; } @@ -586,10 +586,10 @@ impl CollabTitlebarItem { let tooltip; let is_deafened = room.read(cx).is_deafened().unwrap_or(false); if is_deafened { - icon = "icons/radix/speaker-off.svg"; + icon = "icons/speaker-off.svg"; tooltip = "Unmute speakers"; } else { - icon = "icons/radix/speaker-loud.svg"; + icon = "icons/speaker-loud.svg"; tooltip = "Mute speakers"; } @@ -625,7 +625,7 @@ impl CollabTitlebarItem { .into_any() } fn render_leave_call(&self, theme: &Theme, cx: &mut ViewContext) -> AnyElement { - let icon = "icons/radix/exit.svg"; + let icon = "icons/exit.svg"; let tooltip = "Leave call"; let titlebar = &theme.titlebar; @@ -748,7 +748,7 @@ impl CollabTitlebarItem { dropdown .with_child( - Svg::new("icons/caret_down_8.svg") + Svg::new("icons/caret_down.svg") .with_color(user_menu_button_style.icon.color) .constrained() .with_width(user_menu_button_style.icon.width) @@ -1116,7 +1116,7 @@ impl CollabTitlebarItem { | client::Status::Reauthenticating { .. } | client::Status::Reconnecting { .. } | client::Status::ReconnectionError { .. } => Some( - Svg::new("icons/cloud_slash_12.svg") + Svg::new("icons/disconnected.svg") .with_color(theme.titlebar.offline_icon.color) .constrained() .with_width(theme.titlebar.offline_icon.width) diff --git a/crates/collab_ui/src/notifications.rs b/crates/collab_ui/src/notifications.rs index 9aff3a3522..5943e016cb 100644 --- a/crates/collab_ui/src/notifications.rs +++ b/crates/collab_ui/src/notifications.rs @@ -53,7 +53,7 @@ where .with_child( MouseEventHandler::new::(user.id as usize, cx, |state, _| { let style = theme.dismiss_button.style_for(state); - Svg::new("icons/x_mark_8.svg") + Svg::new("icons/x.svg") .with_color(style.color) .constrained() .with_width(style.icon_width) diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index f73f854927..ce0f364806 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -78,15 +78,15 @@ impl View for CopilotButton { .with_child( Svg::new({ match status { - Status::Error(_) => "icons/copilot_error_16.svg", + Status::Error(_) => "icons/copilot_error.svg", Status::Authorized => { if enabled { - "icons/copilot_16.svg" + "icons/copilot.svg" } else { - "icons/copilot_disabled_16.svg" + "icons/copilot_disabled.svg" } } - _ => "icons/copilot_init_16.svg", + _ => "icons/copilot_init.svg", } }) .with_color(style.icon_color) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 0e5b714f09..ac45bcbb79 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -686,11 +686,9 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round(); let icon_width = cx.em_width * style.icon_width_factor; let icon = if diagnostic.severity == DiagnosticSeverity::ERROR { - Svg::new("icons/circle_x_mark_12.svg") - .with_color(theme.error_diagnostic.message.text.color) + Svg::new("icons/error.svg").with_color(theme.error_diagnostic.message.text.color) } else { - Svg::new("icons/triangle_exclamation_12.svg") - .with_color(theme.warning_diagnostic.message.text.color) + Svg::new("icons/warning.svg").with_color(theme.warning_diagnostic.message.text.color) }; Flex::row() @@ -748,7 +746,7 @@ pub(crate) fn render_summary( let summary_spacing = theme.tab_summary_spacing; Flex::row() .with_child( - Svg::new("icons/circle_x_mark_12.svg") + Svg::new("icons/error.svg") .with_color(text_style.color) .constrained() .with_width(icon_width) @@ -767,7 +765,7 @@ pub(crate) fn render_summary( .aligned(), ) .with_child( - Svg::new("icons/triangle_exclamation_12.svg") + Svg::new("icons/warning.svg") .with_color(text_style.color) .constrained() .with_width(icon_width) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 26f30a75a8..b36cf9f71d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3827,7 +3827,7 @@ impl Editor { enum CodeActions {} Some( MouseEventHandler::new::(0, cx, |state, _| { - Svg::new("icons/bolt_8.svg").with_color( + Svg::new("icons/bolt.svg").with_color( style .code_actions .indicator diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index b7e34fda53..3390b70530 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1735,7 +1735,7 @@ impl EditorElement { enum JumpIcon {} MouseEventHandler::new::((*id).into(), cx, |state, _| { let style = style.jump_icon.style_for(state); - Svg::new("icons/arrow_up_right_8.svg") + Svg::new("icons/arrow_up_right.svg") .with_color(style.color) .constrained() .with_width(style.icon_width) diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index 0b8a29e114..b3a06b471e 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -276,7 +276,7 @@ impl Item for FeedbackEditor { ) -> AnyElement { Flex::row() .with_child( - Svg::new("icons/feedback_16.svg") + Svg::new("icons/feedback.svg") .with_color(style.label.text.color) .constrained() .with_width(style.type_icon_width) diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs index b3d9784f1f..8a40325203 100644 --- a/crates/quick_action_bar/src/quick_action_bar.rs +++ b/crates/quick_action_bar/src/quick_action_bar.rs @@ -94,7 +94,7 @@ impl View for QuickActionBar { bar.add_child(render_quick_action_bar_button( 2, - "icons/radix/magic-wand.svg", + "icons/magic-wand.svg", false, ("Inline Assist".into(), Some(Box::new(InlineAssist))), cx, diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index ba07a38051..240928d4e0 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -511,7 +511,7 @@ impl Item for ProjectSearchView { ) -> AnyElement { Flex::row() .with_child( - Svg::new("icons/magnifying_glass_12.svg") + Svg::new("icons/magnifying_glass.svg") .with_color(tab_theme.label.text.color) .constrained() .with_width(tab_theme.type_icon_width) @@ -1440,7 +1440,7 @@ impl View for ProjectSearchBar { let search = _search.read(cx); let filter_button = render_option_button_icon( search.filters_enabled, - "icons/filter_12.svg", + "icons/filter.svg", 0, "Toggle filters", Box::new(ToggleFilters), @@ -1471,14 +1471,14 @@ impl View for ProjectSearchBar { }; let case_sensitive = is_semantic_disabled.then(|| { render_option_button_icon( - "icons/case_insensitive_12.svg", + "icons/case_insensitive.svg", SearchOptions::CASE_SENSITIVE, cx, ) }); let whole_word = is_semantic_disabled.then(|| { - render_option_button_icon("icons/word_search_12.svg", SearchOptions::WHOLE_WORD, cx) + render_option_button_icon("icons/word_search.svg", SearchOptions::WHOLE_WORD, cx) }); let search_button_for_mode = |mode, side, cx: &mut ViewContext| { diff --git a/crates/search/src/search.rs b/crates/search/src/search.rs index 5cdeb0a494..dabbc720ce 100644 --- a/crates/search/src/search.rs +++ b/crates/search/src/search.rs @@ -63,8 +63,8 @@ impl SearchOptions { pub fn icon(&self) -> &'static str { match *self { - SearchOptions::WHOLE_WORD => "icons/word_search_12.svg", - SearchOptions::CASE_SENSITIVE => "icons/case_insensitive_12.svg", + SearchOptions::WHOLE_WORD => "icons/word_search.svg", + SearchOptions::CASE_SENSITIVE => "icons/case_insensitive.svg", _ => panic!("{:?} is not a named SearchOption", self), } } diff --git a/crates/storybook/src/collab_panel.rs b/crates/storybook/src/collab_panel.rs index 7bf08febe3..87fd536391 100644 --- a/crates/storybook/src/collab_panel.rs +++ b/crates/storybook/src/collab_panel.rs @@ -132,9 +132,9 @@ impl CollabPanelElement { div().flex().h_full().gap_1().items_center().child( svg() .path(if expanded { - "icons/radix/caret-down.svg" + "icons/caret_down.svg" } else { - "icons/radix/caret-up.svg" + "icons/caret_up.svg" }) .w_3p5() .h_3p5() diff --git a/crates/storybook/src/workspace.rs b/crates/storybook/src/workspace.rs index c37b3f16ea..20b0151a91 100644 --- a/crates/storybook/src/workspace.rs +++ b/crates/storybook/src/workspace.rs @@ -217,7 +217,7 @@ impl TitleBar { .fill(theme.lowest.base.pressed.background) .child( svg() - .path("icons/radix/speaker-loud.svg") + .path("icons/speaker-loud.svg") .size_3p5() .fill(theme.lowest.base.default.foreground), ), @@ -237,7 +237,7 @@ impl TitleBar { .fill(theme.lowest.base.pressed.background) .child( svg() - .path("icons/radix/desktop.svg") + .path("icons/desktop.svg") .size_3p5() .fill(theme.lowest.base.default.foreground), ), @@ -269,7 +269,7 @@ impl TitleBar { ) .child( svg() - .path("icons/caret_down_8.svg") + .path("icons/caret_down.svg") .w_2() .h_2() .fill(theme.lowest.variant.default.foreground), diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 9fb3939e1f..39d2f14f08 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -70,7 +70,7 @@ impl TerminalPanel { Flex::row() .with_child(Pane::render_tab_bar_button( 0, - "icons/plus_12.svg", + "icons/plus.svg", false, Some(("New Terminal", Some(Box::new(workspace::NewTerminal)))), cx, @@ -90,9 +90,9 @@ impl TerminalPanel { .with_child(Pane::render_tab_bar_button( 1, if pane.is_zoomed() { - "icons/minimize_8.svg" + "icons/minimize.svg" } else { - "icons/maximize_8.svg" + "icons/maximize.svg" }, pane.is_zoomed(), Some(("Toggle Zoom".into(), Some(Box::new(workspace::ToggleZoom)))), diff --git a/crates/workspace/src/notifications.rs b/crates/workspace/src/notifications.rs index 55b44e9673..36865eb22c 100644 --- a/crates/workspace/src/notifications.rs +++ b/crates/workspace/src/notifications.rs @@ -292,7 +292,7 @@ pub mod simple_message_notification { .with_child( MouseEventHandler::new::(0, cx, |state, _| { let style = theme.dismiss_button.style_for(state); - Svg::new("icons/x_mark_8.svg") + Svg::new("icons/x.svg") .with_color(style.color) .constrained() .with_width(style.icon_width) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 90a1fdd3f2..1b48275ee9 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -337,7 +337,7 @@ impl Pane { // New menu .with_child(Self::render_tab_bar_button( 0, - "icons/plus_12.svg", + "icons/plus.svg", false, Some(("New...".into(), None)), cx, @@ -352,7 +352,7 @@ impl Pane { )) .with_child(Self::render_tab_bar_button( 1, - "icons/split_12.svg", + "icons/split.svg", false, Some(("Split Pane".into(), None)), cx, @@ -369,10 +369,10 @@ impl Pane { let icon_path; let tooltip_label; if pane.is_zoomed() { - icon_path = "icons/minimize_8.svg"; + icon_path = "icons/minimize.svg"; tooltip_label = "Zoom In"; } else { - icon_path = "icons/maximize_8.svg"; + icon_path = "icons/maximize.svg"; tooltip_label = "Zoom In"; } @@ -1535,7 +1535,7 @@ impl Pane { let close_element = if hovered { let item_id = item.id(); enum TabCloseButton {} - let icon = Svg::new("icons/x_mark_8.svg"); + let icon = Svg::new("icons/x.svg"); MouseEventHandler::new::(item_id, cx, |mouse_state, _| { if mouse_state.hovered() { icon.with_color(tab_style.icon_close_active) @@ -1701,7 +1701,7 @@ impl View for Pane { let mut tab_row = Flex::row() .with_child(nav_button( - "icons/arrow_left_16.svg", + "icons/arrow_left.svg", button_style.clone(), nav_button_height, tooltip_style.clone(), @@ -1726,7 +1726,7 @@ impl View for Pane { )) .with_child( nav_button( - "icons/arrow_right_16.svg", + "icons/arrow_right.svg", button_style.clone(), nav_button_height, tooltip_style, diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index 7a41f45e53..cc6ee4b080 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -141,26 +141,26 @@ export default function assistant(): any { background: background(theme.highest), }, hamburger_button: tab_bar_button(theme, { - icon: "icons/hamburger_15.svg", + icon: "icons/menu.svg", }), split_button: tab_bar_button(theme, { - icon: "icons/split_message_15.svg", + icon: "icons/split_message.svg", }), quote_button: tab_bar_button(theme, { - icon: "icons/radix/quote.svg", + icon: "icons/quote.svg", }), assist_button: tab_bar_button(theme, { - icon: "icons/radix/magic-wand.svg", + icon: "icons/magic-wand.svg", }), zoom_in_button: tab_bar_button(theme, { - icon: "icons/radix/maximize.svg", + icon: "icons/maximize.svg", }), zoom_out_button: tab_bar_button(theme, { - icon: "icons/radix/minimize.svg", + icon: "icons/minimize.svg", }), plus_button: tab_bar_button(theme, { - icon: "icons/radix/plus.svg", + icon: "icons/plus.svg", }), title: { ...text(theme.highest, "sans", "default", { size: "xs" }), diff --git a/styles/src/style_tree/copilot.ts b/styles/src/style_tree/copilot.ts index f002db5ef5..4e3e867c0a 100644 --- a/styles/src/style_tree/copilot.ts +++ b/styles/src/style_tree/copilot.ts @@ -41,7 +41,7 @@ export default function copilot(): any { base: { icon: svg( foreground(theme.middle, "variant"), - "icons/link_out_12.svg", + "icons/external_link.svg", 12, 12 ), @@ -91,7 +91,7 @@ export default function copilot(): any { base: { icon: svg( foreground(theme.middle, "variant"), - "icons/x_mark_8.svg", + "icons/x.svg", 8, 8 ), @@ -112,7 +112,7 @@ export default function copilot(): any { hovered: { icon: svg( foreground(theme.middle, "on"), - "icons/x_mark_8.svg", + "icons/x.svg", 8, 8 ), @@ -120,7 +120,7 @@ export default function copilot(): any { clicked: { icon: svg( foreground(theme.middle, "base"), - "icons/x_mark_8.svg", + "icons/x.svg", 8, 8 ), @@ -141,7 +141,7 @@ export default function copilot(): any { header: { icon: svg( foreground(theme.middle, "default"), - "icons/zed_plus_copilot_32.svg", + "icons/zed_x_copilot.svg", 92, 32 ), diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index 8fd512c5d4..a15cd8dbb8 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -92,8 +92,8 @@ export default function editor(): any { }, folds: { icon_margin_scale: 2.5, - folded_icon: "icons/chevron_right_8.svg", - foldable_icon: "icons/chevron_down_8.svg", + folded_icon: "icons/chevron_right.svg", + foldable_icon: "icons/chevron_down.svg", indicator: toggleable({ base: interactive({ base: { From 29cd00f78d40afd6f7a9e9a86d457b45a6e19189 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Sep 2023 12:56:49 -0400 Subject: [PATCH 23/38] Fix close tab icon size --- styles/src/style_tree/tab_bar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/src/style_tree/tab_bar.ts b/styles/src/style_tree/tab_bar.ts index 23ff03a6a3..e1ad1c6c8b 100644 --- a/styles/src/style_tree/tab_bar.ts +++ b/styles/src/style_tree/tab_bar.ts @@ -32,7 +32,7 @@ export default function tab_bar(): any { type_icon_width: 14, // Close icons - close_icon_width: 8, + close_icon_width: 14, icon_close: foreground(layer, "variant"), icon_close_active: foreground(layer, "hovered"), From 966da652932b63085033fcf0c00fbd9c2fc92914 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Sep 2023 12:59:57 -0400 Subject: [PATCH 24/38] Fix notification close icon size --- styles/src/style_tree/contact_notification.ts | 8 ++++---- styles/src/style_tree/simple_message_notification.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/styles/src/style_tree/contact_notification.ts b/styles/src/style_tree/contact_notification.ts index 365e3a646d..0f52201c16 100644 --- a/styles/src/style_tree/contact_notification.ts +++ b/styles/src/style_tree/contact_notification.ts @@ -42,10 +42,10 @@ export default function contact_notification(): any { dismiss_button: { default: { color: foreground(theme.lowest, "variant"), - icon_width: 8, - icon_height: 8, - button_width: 8, - button_height: 8, + icon_width: 14, + icon_height: 14, + button_width: 14, + button_height: 14, hover: { color: foreground(theme.lowest, "hovered"), }, diff --git a/styles/src/style_tree/simple_message_notification.ts b/styles/src/style_tree/simple_message_notification.ts index 35133f04a2..45ecc0eab9 100644 --- a/styles/src/style_tree/simple_message_notification.ts +++ b/styles/src/style_tree/simple_message_notification.ts @@ -37,10 +37,10 @@ export default function simple_message_notification(): any { dismiss_button: interactive({ base: { color: foreground(theme.middle), - icon_width: 8, - icon_height: 8, - button_width: 8, - button_height: 8, + icon_width: 14, + icon_height: 14, + button_width: 14, + button_height: 14, }, state: { hovered: { From 099969ed79f641854352ed52180c3aeae164fdd2 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Sep 2023 10:12:28 -0700 Subject: [PATCH 25/38] Ensure the chat panel is fully feature flagged --- crates/collab_ui/src/chat_panel.rs | 18 ++++++++++++++++-- crates/zed/src/main.rs | 6 ------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index be2dbf811c..c8f0f9bc8d 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -5,6 +5,7 @@ use channel::{ChannelChat, ChannelChatEvent, ChannelMessageId, ChannelStore}; use client::Client; use db::kvp::KEY_VALUE_STORE; use editor::Editor; +use feature_flags::{ChannelsAlpha, FeatureFlagAppExt}; use gpui::{ actions, elements::*, @@ -628,9 +629,14 @@ impl Panel for ChatPanel { cx.notify(); } + fn set_active(&mut self, active: bool, cx: &mut ViewContext) { + if active && !is_chat_feature_enabled(cx) { + cx.emit(Event::Dismissed); + } + } + fn icon_path(&self, cx: &gpui::WindowContext) -> Option<&'static str> { - settings::get::(cx) - .button + (settings::get::(cx).button && is_chat_feature_enabled(cx)) .then(|| "icons/conversations.svg") } @@ -642,6 +648,10 @@ impl Panel for ChatPanel { matches!(event, Event::DockPositionChanged) } + fn should_close_on_event(event: &Self::Event) -> bool { + matches!(event, Event::Dismissed) + } + fn has_focus(&self, _cx: &gpui::WindowContext) -> bool { self.has_focus } @@ -651,6 +661,10 @@ impl Panel for ChatPanel { } } +fn is_chat_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool { + cx.is_staff() || cx.has_flag::() +} + fn format_timestamp( mut timestamp: OffsetDateTime, mut now: OffsetDateTime, diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index f78a4f6419..c800e4e110 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -119,12 +119,6 @@ fn main() { app.run(move |cx| { cx.set_global(*RELEASE_CHANNEL); - #[cfg(debug_assertions)] - { - use feature_flags::FeatureFlagAppExt; - cx.set_staff(true); - } - let mut store = SettingsStore::default(); store .set_default_settings(default_settings().as_ref(), cx) From b02bd9bce1db3a68dcd606718fa02709020860af Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 15 Sep 2023 11:14:04 -0600 Subject: [PATCH 26/38] Fix Y on last line with no trailing new line For zed-industries/community#2044 --- assets/keymaps/vim.json | 1 + crates/vim/src/utils.rs | 3 ++- crates/vim/src/visual.rs | 22 ++++++++++++++++++++-- crates/vim/test_data/test_visual_yank.json | 6 ++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 4dffb07dfc..8d32d0bccd 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -453,6 +453,7 @@ "d": "vim::VisualDelete", "x": "vim::VisualDelete", "y": "vim::VisualYank", + "shift-y": "vim::VisualYank", "p": "vim::Paste", "shift-p": [ "vim::Paste", diff --git a/crates/vim/src/utils.rs b/crates/vim/src/utils.rs index 4a96b5bbea..797e94b0fa 100644 --- a/crates/vim/src/utils.rs +++ b/crates/vim/src/utils.rs @@ -26,10 +26,11 @@ pub fn copy_selections_content(editor: &mut Editor, linewise: bool, cx: &mut App let is_last_line = linewise && end.row == buffer.max_buffer_row() && buffer.max_point().column > 0 + && start.row < buffer.max_buffer_row() && start == Point::new(start.row, buffer.line_len(start.row)); if is_last_line { - start = Point::new(buffer.max_buffer_row(), 0); + start = Point::new(start.row + 1, 0); } for chunk in buffer.text_for_range(start..end) { text.push_str(chunk); diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index acd55a0954..f59b1fe167 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -12,7 +12,7 @@ use language::{Selection, SelectionGoal}; use workspace::Workspace; use crate::{ - motion::Motion, + motion::{start_of_line, Motion}, object::Object, state::{Mode, Operator}, utils::copy_selections_content, @@ -326,7 +326,10 @@ pub fn yank(_: &mut Workspace, _: &VisualYank, cx: &mut ViewContext) let line_mode = editor.selections.line_mode; copy_selections_content(editor, line_mode, cx); editor.change_selections(None, cx, |s| { - s.move_with(|_, selection| { + s.move_with(|map, selection| { + if line_mode { + selection.start = start_of_line(map, false, selection.start); + }; selection.collapse_to(selection.start, SelectionGoal::None) }); if vim.state().mode == Mode::VisualBlock { @@ -672,6 +675,21 @@ mod test { the lazy dog"}) .await; cx.assert_clipboard_content(Some("The q")); + + cx.set_shared_state(indoc! {" + The quick brown + fox ˇjumps over + the lazy dog"}) + .await; + cx.simulate_shared_keystrokes(["shift-v", "shift-g", "shift-y"]) + .await; + cx.assert_shared_state(indoc! {" + The quick brown + ˇfox jumps over + the lazy dog"}) + .await; + cx.assert_shared_clipboard("fox jumps over\nthe lazy dog\n") + .await; } #[gpui::test] diff --git a/crates/vim/test_data/test_visual_yank.json b/crates/vim/test_data/test_visual_yank.json index edc3b4f83d..2e7b725371 100644 --- a/crates/vim/test_data/test_visual_yank.json +++ b/crates/vim/test_data/test_visual_yank.json @@ -27,3 +27,9 @@ {"Key":"k"} {"Key":"y"} {"Get":{"state":"ˇThe quick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}} +{"Put":{"state":"The quick brown\nfox ˇjumps over\nthe lazy dog"}} +{"Key":"shift-v"} +{"Key":"shift-g"} +{"Key":"shift-y"} +{"Get":{"state":"The quick brown\nˇfox jumps over\nthe lazy dog","mode":"Normal"}} +{"ReadRegister":{"name":"\"","value":"fox jumps over\nthe lazy dog\n"}} From 3dba52340efcfc38492745e8cc17e1e61773a957 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Sep 2023 11:14:04 -0700 Subject: [PATCH 27/38] Update paths to moved icons --- crates/collab_ui/src/chat_panel.rs | 7 ++----- crates/collab_ui/src/collab_panel.rs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index c8f0f9bc8d..087f2e1b8e 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -405,10 +405,7 @@ impl ChatPanel { if matches!(item_type, ItemType::Header) { row.add_children([ MouseEventHandler::new::(0, cx, |mouse_state, _| { - render_icon_button( - theme.icon_button.style_for(mouse_state), - "icons/radix/file.svg", - ) + render_icon_button(theme.icon_button.style_for(mouse_state), "icons/file.svg") }) .on_click(MouseButton::Left, move |_, _, cx| { if let Some(workspace) = workspace.upgrade(cx) { @@ -426,7 +423,7 @@ impl ChatPanel { MouseEventHandler::new::(0, cx, |mouse_state, _| { render_icon_button( theme.icon_button.style_for(mouse_state), - "icons/radix/speaker-loud.svg", + "icons/speaker-loud.svg", ) }) .on_click(MouseButton::Left, move |_, _, cx| { diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 2af77ea2d3..a258151bb8 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -1621,7 +1621,7 @@ impl CollabPanel { })) .into_any() } else if row_hovered { - Svg::new("icons/radix/speaker-loud.svg") + Svg::new("icons/speaker-loud.svg") .with_color(theme.channel_hash.color) .constrained() .with_width(theme.channel_hash.width) From b8fd4f5d40a55df1c4a8e62cb43a7233947d89f0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Sep 2023 11:16:30 -0700 Subject: [PATCH 28/38] Restore user_group_16 icon --- assets/icons/user_group_16.svg | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 assets/icons/user_group_16.svg diff --git a/assets/icons/user_group_16.svg b/assets/icons/user_group_16.svg new file mode 100644 index 0000000000..aa99277646 --- /dev/null +++ b/assets/icons/user_group_16.svg @@ -0,0 +1,3 @@ + + + From 9a4ecf0f88fbf1e085bfb5a35a8d36d755918afc Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Sep 2023 14:21:33 -0400 Subject: [PATCH 29/38] Add missing `logo_96` icon, fix a few incorrect paths --- assets/icons/logo_96.svg | 3 +++ crates/collab_ui/src/collab_panel.rs | 2 +- crates/collab_ui/src/collab_panel/contact_finder.rs | 2 +- crates/collab_ui/src/sharing_status_indicator.rs | 2 +- crates/workspace/src/shared_screen.rs | 2 +- styles/src/style_tree/welcome.ts | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 assets/icons/logo_96.svg diff --git a/assets/icons/logo_96.svg b/assets/icons/logo_96.svg new file mode 100644 index 0000000000..dc98bb8bc2 --- /dev/null +++ b/assets/icons/logo_96.svg @@ -0,0 +1,3 @@ + + + diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index c2a2b35134..764fb67752 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -1132,7 +1132,7 @@ impl CollabPanel { cx.font_cache(), )) .with_child( - Svg::new("icons/disable_screen_sharing_12.svg") + Svg::new("icons/desktop.svg") .with_color(theme.channel_hash.color) .constrained() .with_width(theme.channel_hash.width) diff --git a/crates/collab_ui/src/collab_panel/contact_finder.rs b/crates/collab_ui/src/collab_panel/contact_finder.rs index 9f96aa4b60..d0c12a7f90 100644 --- a/crates/collab_ui/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui/src/collab_panel/contact_finder.rs @@ -209,7 +209,7 @@ impl PickerDelegate for ContactFinderDelegate { let icon_path = match request_status { ContactRequestStatus::None | ContactRequestStatus::RequestReceived => { - Some("icons/check_8.svg") + Some("icons/check.svg") } ContactRequestStatus::RequestSent => Some("icons/x.svg"), ContactRequestStatus::RequestAccepted => None, diff --git a/crates/collab_ui/src/sharing_status_indicator.rs b/crates/collab_ui/src/sharing_status_indicator.rs index 9fcd15aa18..6a6acb4b70 100644 --- a/crates/collab_ui/src/sharing_status_indicator.rs +++ b/crates/collab_ui/src/sharing_status_indicator.rs @@ -48,7 +48,7 @@ impl View for SharingStatusIndicator { }; MouseEventHandler::new::(0, cx, |_, _| { - Svg::new("icons/disable_screen_sharing_12.svg") + Svg::new("icons/desktop.svg") .with_color(color) .constrained() .with_width(18.) diff --git a/crates/workspace/src/shared_screen.rs b/crates/workspace/src/shared_screen.rs index 7b97174dfe..b99c5f3ab9 100644 --- a/crates/workspace/src/shared_screen.rs +++ b/crates/workspace/src/shared_screen.rs @@ -112,7 +112,7 @@ impl Item for SharedScreen { ) -> gpui::AnyElement { Flex::row() .with_child( - Svg::new("icons/disable_screen_sharing_12.svg") + Svg::new("icons/desktop.svg") .with_color(style.label.text.color) .constrained() .with_width(style.type_icon_width) diff --git a/styles/src/style_tree/welcome.ts b/styles/src/style_tree/welcome.ts index 8ff15d5d26..284a262a23 100644 --- a/styles/src/style_tree/welcome.ts +++ b/styles/src/style_tree/welcome.ts @@ -128,7 +128,7 @@ export default function welcome(): any { }, icon: svg( foreground(theme.highest, "on"), - "icons/check_12.svg", + "icons/check.svg", 12, 12 ), From 1433160a08fcfa843a05f27164ef0deec578e6da Mon Sep 17 00:00:00 2001 From: KCaverly Date: Fri, 15 Sep 2023 15:16:20 -0400 Subject: [PATCH 30/38] enable include based filtering for search inside open and modified buffers --- crates/semantic_index/src/semantic_index.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index 06c7aa53fa..f9ac6a0ae1 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -714,7 +714,14 @@ impl SemanticIndex { let search_start = Instant::now(); let modified_buffer_results = this.update(&mut cx, |this, cx| { - this.search_modified_buffers(&project, query.clone(), limit, &excludes, cx) + this.search_modified_buffers( + &project, + query.clone(), + limit, + &includes, + &excludes, + cx, + ) }); let file_results = this.update(&mut cx, |this, cx| { this.search_files(project, query, limit, includes, excludes, cx) @@ -877,6 +884,7 @@ impl SemanticIndex { project: &ModelHandle, query: Embedding, limit: usize, + includes: &[PathMatcher], excludes: &[PathMatcher], cx: &mut ModelContext, ) -> Task>> { @@ -890,7 +898,16 @@ impl SemanticIndex { let excluded = snapshot.resolve_file_path(cx, false).map_or(false, |path| { excludes.iter().any(|matcher| matcher.is_match(&path)) }); - if buffer.is_dirty() && !excluded { + + let included = if includes.len() == 0 { + true + } else { + snapshot.resolve_file_path(cx, false).map_or(false, |path| { + includes.iter().any(|matcher| matcher.is_match(&path)) + }) + }; + + if buffer.is_dirty() && !excluded && included { Some((buffer_handle, snapshot)) } else { None From 5df9a57a8b88c5a66586e2d9c644b3eb9a844bd2 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 15 Sep 2023 15:25:35 -0400 Subject: [PATCH 31/38] Add assistant events (#2978) Add assistant events Release Notes: - N/A --- Cargo.lock | 2 ++ crates/ai/Cargo.toml | 2 ++ crates/ai/src/ai.rs | 1 + crates/ai/src/assistant.rs | 63 ++++++++++++++++++++++++++++++++-- crates/client/src/telemetry.rs | 12 +++++++ crates/theme/src/components.rs | 1 - 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 829ed18bbb..b77ff20af3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "client", "collections", "ctor", "editor", @@ -127,6 +128,7 @@ dependencies = [ "theme", "tiktoken-rs 0.4.5", "util", + "uuid 1.4.1", "workspace", ] diff --git a/crates/ai/Cargo.toml b/crates/ai/Cargo.toml index d96e470d5c..8002b0d35d 100644 --- a/crates/ai/Cargo.toml +++ b/crates/ai/Cargo.toml @@ -9,6 +9,7 @@ path = "src/ai.rs" doctest = false [dependencies] +client = { path = "../client" } collections = { path = "../collections"} editor = { path = "../editor" } fs = { path = "../fs" } @@ -19,6 +20,7 @@ search = { path = "../search" } settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } +uuid = { version = "1.1.2", features = ["v4"] } workspace = { path = "../workspace" } anyhow.workspace = true diff --git a/crates/ai/src/ai.rs b/crates/ai/src/ai.rs index 7d9b93b0a7..dfd9a523b4 100644 --- a/crates/ai/src/ai.rs +++ b/crates/ai/src/ai.rs @@ -61,6 +61,7 @@ struct SavedMessage { #[derive(Serialize, Deserialize)] struct SavedConversation { + id: Option, zed: String, version: String, text: String, diff --git a/crates/ai/src/assistant.rs b/crates/ai/src/assistant.rs index 7fa66f26fb..263382c03e 100644 --- a/crates/ai/src/assistant.rs +++ b/crates/ai/src/assistant.rs @@ -6,6 +6,7 @@ use crate::{ }; use anyhow::{anyhow, Result}; use chrono::{DateTime, Local}; +use client::{telemetry::AssistantKind, ClickhouseEvent, TelemetrySettings}; use collections::{hash_map, HashMap, HashSet, VecDeque}; use editor::{ display_map::{ @@ -48,6 +49,7 @@ use theme::{ AssistantStyle, }; use util::{paths::CONVERSATIONS_DIR, post_inc, ResultExt, TryFutureExt}; +use uuid::Uuid; use workspace::{ dock::{DockPosition, Panel}, searchable::Direction, @@ -296,6 +298,7 @@ impl AssistantPanel { self.include_conversation_in_next_inline_assist, self.inline_prompt_history.clone(), codegen.clone(), + self.workspace.clone(), cx, ); cx.focus_self(); @@ -724,6 +727,7 @@ impl AssistantPanel { self.api_key.clone(), self.languages.clone(), self.fs.clone(), + self.workspace.clone(), cx, ) }); @@ -1059,6 +1063,7 @@ impl AssistantPanel { } let fs = self.fs.clone(); + let workspace = self.workspace.clone(); let api_key = self.api_key.clone(); let languages = self.languages.clone(); cx.spawn(|this, mut cx| async move { @@ -1073,8 +1078,9 @@ impl AssistantPanel { if let Some(ix) = this.editor_index_for_path(&path, cx) { this.set_active_editor_index(Some(ix), cx); } else { - let editor = cx - .add_view(|cx| ConversationEditor::for_conversation(conversation, fs, cx)); + let editor = cx.add_view(|cx| { + ConversationEditor::for_conversation(conversation, fs, workspace, cx) + }); this.add_conversation(editor, cx); } })?; @@ -1348,6 +1354,7 @@ struct Summary { } struct Conversation { + id: Option, buffer: ModelHandle, message_anchors: Vec, messages_metadata: HashMap, @@ -1398,6 +1405,7 @@ impl Conversation { let model = settings.default_open_ai_model.clone(); let mut this = Self { + id: Some(Uuid::new_v4().to_string()), message_anchors: Default::default(), messages_metadata: Default::default(), next_message_id: Default::default(), @@ -1435,6 +1443,7 @@ impl Conversation { fn serialize(&self, cx: &AppContext) -> SavedConversation { SavedConversation { + id: self.id.clone(), zed: "conversation".into(), version: SavedConversation::VERSION.into(), text: self.buffer.read(cx).text(), @@ -1462,6 +1471,10 @@ impl Conversation { language_registry: Arc, cx: &mut ModelContext, ) -> Self { + let id = match saved_conversation.id { + Some(id) => Some(id), + None => Some(Uuid::new_v4().to_string()), + }; let model = saved_conversation.model; let markdown = language_registry.language_for_name("Markdown"); let mut message_anchors = Vec::new(); @@ -1491,6 +1504,7 @@ impl Conversation { }); let mut this = Self { + id, message_anchors, messages_metadata: saved_conversation.message_metadata, next_message_id, @@ -2108,6 +2122,7 @@ struct ScrollPosition { struct ConversationEditor { conversation: ModelHandle, fs: Arc, + workspace: WeakViewHandle, editor: ViewHandle, blocks: HashSet, scroll_position: Option, @@ -2119,15 +2134,17 @@ impl ConversationEditor { api_key: Rc>>, language_registry: Arc, fs: Arc, + workspace: WeakViewHandle, cx: &mut ViewContext, ) -> Self { let conversation = cx.add_model(|cx| Conversation::new(api_key, language_registry, cx)); - Self::for_conversation(conversation, fs, cx) + Self::for_conversation(conversation, fs, workspace, cx) } fn for_conversation( conversation: ModelHandle, fs: Arc, + workspace: WeakViewHandle, cx: &mut ViewContext, ) -> Self { let editor = cx.add_view(|cx| { @@ -2150,6 +2167,7 @@ impl ConversationEditor { blocks: Default::default(), scroll_position: None, fs, + workspace, _subscriptions, }; this.update_message_headers(cx); @@ -2157,6 +2175,13 @@ impl ConversationEditor { } fn assist(&mut self, _: &Assist, cx: &mut ViewContext) { + report_assistant_event( + self.workspace.clone(), + self.conversation.read(cx).id.clone(), + AssistantKind::Panel, + cx, + ); + let cursors = self.cursors(cx); let user_messages = self.conversation.update(cx, |conversation, cx| { @@ -2665,6 +2690,7 @@ enum InlineAssistantEvent { struct InlineAssistant { id: usize, prompt_editor: ViewHandle, + workspace: WeakViewHandle, confirmed: bool, has_focus: bool, include_conversation: bool, @@ -2780,6 +2806,7 @@ impl InlineAssistant { include_conversation: bool, prompt_history: VecDeque, codegen: ModelHandle, + workspace: WeakViewHandle, cx: &mut ViewContext, ) -> Self { let prompt_editor = cx.add_view(|cx| { @@ -2801,6 +2828,7 @@ impl InlineAssistant { Self { id, prompt_editor, + workspace, confirmed: false, has_focus: false, include_conversation, @@ -2859,6 +2887,8 @@ impl InlineAssistant { if self.confirmed { cx.emit(InlineAssistantEvent::Dismissed); } else { + report_assistant_event(self.workspace.clone(), None, AssistantKind::Inline, cx); + let prompt = self.prompt_editor.read(cx).text(cx); self.prompt_editor.update(cx, |editor, cx| { editor.set_read_only(true); @@ -3347,3 +3377,30 @@ mod tests { .collect() } } + +fn report_assistant_event( + workspace: WeakViewHandle, + conversation_id: Option, + assistant_kind: AssistantKind, + cx: &AppContext, +) { + let Some(workspace) = workspace.upgrade(cx) else { + return; + }; + + let client = workspace.read(cx).project().read(cx).client(); + let telemetry = client.telemetry(); + + let model = settings::get::(cx) + .default_open_ai_model + .clone(); + + let event = ClickhouseEvent::Assistant { + conversation_id, + kind: assistant_kind, + model: model.full_name(), + }; + let telemetry_settings = *settings::get::(cx); + + telemetry.report_clickhouse_event(event, telemetry_settings) +} diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index f8642dd7fa..1596e6d850 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -56,6 +56,13 @@ struct ClickhouseEventWrapper { event: ClickhouseEvent, } +#[derive(Serialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum AssistantKind { + Panel, + Inline, +} + #[derive(Serialize, Debug)] #[serde(tag = "type")] pub enum ClickhouseEvent { @@ -76,6 +83,11 @@ pub enum ClickhouseEvent { room_id: Option, channel_id: Option, }, + Assistant { + conversation_id: Option, + kind: AssistantKind, + model: &'static str, + }, } #[cfg(debug_assertions)] diff --git a/crates/theme/src/components.rs b/crates/theme/src/components.rs index 9011821b77..8c5bf21ef9 100644 --- a/crates/theme/src/components.rs +++ b/crates/theme/src/components.rs @@ -26,7 +26,6 @@ impl ComponentExt for C { } pub mod disclosure { - use gpui::{ elements::{Component, ContainerStyle, Empty, Flex, ParentElement, SafeStylable}, Action, Element, From d46816589e9063b172e7490e8e4c1f64e68a390d Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 15 Sep 2023 21:32:58 -0700 Subject: [PATCH 32/38] Added 'open in terminal' action to the project panel context menu Also slightly re-arranged the project panel context menu --- crates/project_panel/src/project_panel.rs | 38 +++++++++++++++++--- crates/terminal_view/src/terminal_panel.rs | 40 ++++++++++++++++------ crates/workspace/src/workspace.rs | 10 +++++- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 617870fcb4..65415c6690 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -122,6 +122,7 @@ actions!( CopyPath, CopyRelativePath, RevealInFinder, + OpenInTerminal, Cut, Paste, Delete, @@ -156,6 +157,7 @@ pub fn init(assets: impl AssetSource, cx: &mut AppContext) { cx.add_action(ProjectPanel::copy_path); cx.add_action(ProjectPanel::copy_relative_path); cx.add_action(ProjectPanel::reveal_in_finder); + cx.add_action(ProjectPanel::open_in_terminal); cx.add_action(ProjectPanel::new_search_in_directory); cx.add_action( |this: &mut ProjectPanel, action: &Paste, cx: &mut ViewContext| { @@ -423,24 +425,30 @@ impl ProjectPanel { menu_entries.push(ContextMenuItem::Separator); menu_entries.push(ContextMenuItem::action("Cut", Cut)); menu_entries.push(ContextMenuItem::action("Copy", Copy)); + if let Some(clipboard_entry) = self.clipboard_entry { + if clipboard_entry.worktree_id() == worktree.id() { + menu_entries.push(ContextMenuItem::action("Paste", Paste)); + } + } menu_entries.push(ContextMenuItem::Separator); menu_entries.push(ContextMenuItem::action("Copy Path", CopyPath)); menu_entries.push(ContextMenuItem::action( "Copy Relative Path", CopyRelativePath, )); + + if entry.is_dir() { + menu_entries.push(ContextMenuItem::Separator); + } menu_entries.push(ContextMenuItem::action("Reveal in Finder", RevealInFinder)); if entry.is_dir() { + menu_entries.push(ContextMenuItem::action("Open in Terminal", OpenInTerminal)); menu_entries.push(ContextMenuItem::action( "Search Inside", NewSearchInDirectory, )); } - if let Some(clipboard_entry) = self.clipboard_entry { - if clipboard_entry.worktree_id() == worktree.id() { - menu_entries.push(ContextMenuItem::action("Paste", Paste)); - } - } + menu_entries.push(ContextMenuItem::Separator); menu_entries.push(ContextMenuItem::action("Rename", Rename)); if !is_root { @@ -965,6 +973,26 @@ impl ProjectPanel { } } + fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext) { + if let Some((worktree, entry)) = self.selected_entry(cx) { + let window = cx.window(); + let view_id = cx.view_id(); + let path = worktree.abs_path().join(&entry.path); + + cx.app_context() + .spawn(|mut cx| async move { + window.dispatch_action( + view_id, + &workspace::OpenTerminal { + working_directory: path, + }, + &mut cx, + ); + }) + .detach(); + } + } + pub fn new_search_in_directory( &mut self, _: &NewSearchInDirectory, diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 39d2f14f08..0bfa84e754 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{path::PathBuf, sync::Arc}; use crate::TerminalView; use db::kvp::KEY_VALUE_STORE; @@ -23,6 +23,7 @@ actions!(terminal_panel, [ToggleFocus]); pub fn init(cx: &mut AppContext) { cx.add_action(TerminalPanel::new_terminal); + cx.add_action(TerminalPanel::open_terminal); } #[derive(Debug)] @@ -79,7 +80,7 @@ impl TerminalPanel { cx.window_context().defer(move |cx| { if let Some(this) = this.upgrade(cx) { this.update(cx, |this, cx| { - this.add_terminal(cx); + this.add_terminal(None, cx); }); } }) @@ -230,6 +231,21 @@ impl TerminalPanel { } } + pub fn open_terminal( + workspace: &mut Workspace, + action: &workspace::OpenTerminal, + cx: &mut ViewContext, + ) { + let Some(this) = workspace.focus_panel::(cx) else { + return; + }; + + this.update(cx, |this, cx| { + this.add_terminal(Some(action.working_directory.clone()), cx) + }) + } + + ///Create a new Terminal in the current working directory or the user's home directory fn new_terminal( workspace: &mut Workspace, _: &workspace::NewTerminal, @@ -239,19 +255,23 @@ impl TerminalPanel { return; }; - this.update(cx, |this, cx| this.add_terminal(cx)) + this.update(cx, |this, cx| this.add_terminal(None, cx)) } - fn add_terminal(&mut self, cx: &mut ViewContext) { + fn add_terminal(&mut self, working_directory: Option, cx: &mut ViewContext) { let workspace = self.workspace.clone(); cx.spawn(|this, mut cx| async move { let pane = this.read_with(&cx, |this, _| this.pane.clone())?; workspace.update(&mut cx, |workspace, cx| { - let working_directory_strategy = settings::get::(cx) - .working_directory - .clone(); - let working_directory = - crate::get_working_directory(workspace, cx, working_directory_strategy); + let working_directory = if let Some(working_directory) = working_directory { + Some(working_directory) + } else { + let working_directory_strategy = settings::get::(cx) + .working_directory + .clone(); + crate::get_working_directory(workspace, cx, working_directory_strategy) + }; + let window = cx.window(); if let Some(terminal) = workspace.project().update(cx, |project, cx| { project @@ -389,7 +409,7 @@ impl Panel for TerminalPanel { fn set_active(&mut self, active: bool, cx: &mut ViewContext) { if active && self.pane.read(cx).items_len() == 0 { - self.add_terminal(cx) + self.add_terminal(None, cx) } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 7d0f6db917..999d968575 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -203,7 +203,15 @@ impl Clone for Toast { } } -impl_actions!(workspace, [ActivatePane, ActivatePaneInDirection, Toast]); +#[derive(Clone, Deserialize, PartialEq)] +pub struct OpenTerminal { + pub working_directory: PathBuf, +} + +impl_actions!( + workspace, + [ActivatePane, ActivatePaneInDirection, Toast, OpenTerminal] +); pub type WorkspaceId = i64; From c4797f87b4ad2e3d27725bd625e2b1d9d5747158 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sat, 16 Sep 2023 12:58:39 -0700 Subject: [PATCH 33/38] clip FoldPoint earlier fold_point_to_display_point calls to_offset on the fold point, which panics if it hasn't been clipped. https://zed-industries.slack.com/archives/C04S6T1T7TQ/p1694850156370919 --- crates/vim/src/motion.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index 3e65e6d504..209b43772f 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -536,9 +536,12 @@ fn down( map.buffer_snapshot.max_point().row, ); let new_col = cmp::min(goal_column, map.fold_snapshot.line_len(new_row)); - let point = map.fold_point_to_display_point(FoldPoint::new(new_row, new_col)); + let point = map.fold_point_to_display_point( + map.fold_snapshot + .clip_point(FoldPoint::new(new_row, new_col), Bias::Left), + ); - (map.clip_point(point, Bias::Left), goal) + (point, goal) } fn down_display( @@ -573,9 +576,12 @@ pub(crate) fn up( let new_row = start.row().saturating_sub(times as u32); let new_col = cmp::min(goal_column, map.fold_snapshot.line_len(new_row)); - let point = map.fold_point_to_display_point(FoldPoint::new(new_row, new_col)); + let point = map.fold_point_to_display_point( + map.fold_snapshot + .clip_point(FoldPoint::new(new_row, new_col), Bias::Left), + ); - (map.clip_point(point, Bias::Left), goal) + (point, goal) } fn up_display( From 0598a8243d291969232d45ee4a3fe1588b1ee488 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 18 Sep 2023 11:55:44 +0200 Subject: [PATCH 34/38] chore: Hoist non-generic part out of add_action_internal. (#2981) add_action_internal shows up often in downstream crates (as it should be, since it's a generic function it's codegened in each crate that uses it); it adds non-trivial amounts of LLVM IR to the build as a whole which we can cut down a bit by doing the inner fn trick. Release Notes: - N/A --- crates/gpui/src/app.rs | 48 +++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index c95c0a6105..6b3cd03e8f 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -684,23 +684,41 @@ impl AppContext { ); }, ); + fn inner( + this: &mut AppContext, + name: &'static str, + deserializer: fn(serde_json::Value) -> anyhow::Result>, + action_id: TypeId, + view_id: TypeId, + handler: Box, + capture: bool, + ) { + this.action_deserializers + .entry(name) + .or_insert((action_id.clone(), deserializer)); - self.action_deserializers - .entry(A::qualified_name()) - .or_insert((TypeId::of::(), A::from_json_str)); + let actions = if capture { + &mut this.capture_actions + } else { + &mut this.actions + }; - let actions = if capture { - &mut self.capture_actions - } else { - &mut self.actions - }; - - actions - .entry(TypeId::of::()) - .or_default() - .entry(TypeId::of::()) - .or_default() - .push(handler); + actions + .entry(view_id) + .or_default() + .entry(action_id) + .or_default() + .push(handler); + } + inner( + self, + A::qualified_name(), + A::from_json_str, + TypeId::of::(), + TypeId::of::(), + handler, + capture, + ); } pub fn add_async_action(&mut self, mut handler: F) From 4244e7893f9faf361b344f691166c751b5ace83f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 18 Sep 2023 08:28:21 -0600 Subject: [PATCH 35/38] Clip twice --- crates/vim/src/motion.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index 209b43772f..08256bffb1 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -541,7 +541,8 @@ fn down( .clip_point(FoldPoint::new(new_row, new_col), Bias::Left), ); - (point, goal) + // clip twice to "clip at end of line" + (map.clip_point(point, Bias::Left), goal) } fn down_display( @@ -581,7 +582,7 @@ pub(crate) fn up( .clip_point(FoldPoint::new(new_row, new_col), Bias::Left), ); - (point, goal) + (map.clip_point(point, Bias::Left), goal) } fn up_display( From 616d328f3c3423ce6c62e44ddabfeb66e0294b3e Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:01:08 +0200 Subject: [PATCH 36/38] chore: Use aho-corasick 1.1 in direct dependencies (#2983) Nothing too fancy, we've depended indirectly on 1.0/1.1 already, so this is essentially bookkeeping. Release Notes: - N/A --- Cargo.lock | 23 ++++-------- crates/collab/src/tests/integration_tests.rs | 2 +- .../random_project_collaboration_tests.rs | 2 +- crates/editor/Cargo.toml | 2 +- crates/editor/src/editor.rs | 22 +++++++----- crates/editor/src/editor_tests.rs | 36 ++++++++++++------- crates/project/Cargo.toml | 2 +- crates/project/src/project_tests.rs | 35 ++++++++++-------- crates/project/src/search.rs | 15 ++++---- crates/search/src/buffer_search.rs | 13 +++++-- crates/search/src/project_search.rs | 14 ++++++-- 11 files changed, 99 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b77ff20af3..c620cb2b88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,18 +79,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0" dependencies = [ "memchr", ] @@ -2332,7 +2323,7 @@ checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" name = "editor" version = "0.1.0" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "anyhow", "client", "clock", @@ -3080,7 +3071,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ - "aho-corasick 1.0.4", + "aho-corasick", "bstr", "fnv", "log", @@ -5462,7 +5453,7 @@ dependencies = [ name = "project" version = "0.1.0" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "anyhow", "async-trait", "backtrace", @@ -5972,7 +5963,7 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ - "aho-corasick 1.0.4", + "aho-corasick", "memchr", "regex-automata 0.3.6", "regex-syntax 0.7.4", @@ -5993,7 +5984,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ - "aho-corasick 1.0.4", + "aho-corasick", "memchr", "regex-syntax 0.7.4", ] diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index a9f4a31eb7..10d6baec19 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -4825,7 +4825,7 @@ async fn test_project_search( let mut results = HashMap::default(); let mut search_rx = project_b.update(cx_b, |project, cx| { project.search( - SearchQuery::text("world", false, false, Vec::new(), Vec::new()), + SearchQuery::text("world", false, false, Vec::new(), Vec::new()).unwrap(), cx, ) }); diff --git a/crates/collab/src/tests/random_project_collaboration_tests.rs b/crates/collab/src/tests/random_project_collaboration_tests.rs index 7570768249..6f9513c325 100644 --- a/crates/collab/src/tests/random_project_collaboration_tests.rs +++ b/crates/collab/src/tests/random_project_collaboration_tests.rs @@ -869,7 +869,7 @@ impl RandomizedTest for ProjectCollaborationTest { let mut search = project.update(cx, |project, cx| { project.search( - SearchQuery::text(query, false, false, Vec::new(), Vec::new()), + SearchQuery::text(query, false, false, Vec::new(), Vec::new()).unwrap(), cx, ) }); diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index 2fdeee56c1..b0f8323a76 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -45,7 +45,7 @@ util = { path = "../util" } sqlez = { path = "../sqlez" } workspace = { path = "../workspace" } -aho-corasick = "0.7" +aho-corasick = "1.1" anyhow.workspace = true convert_case = "0.6.0" futures.workspace = true diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b36cf9f71d..8c30859841 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5936,7 +5936,7 @@ impl Editor { } } - pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext) { + pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext) -> Result<()> { self.push_to_selection_history(); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = &display_map.buffer_snapshot; @@ -6005,7 +6005,7 @@ impl Editor { .text_for_range(selection.start..selection.end) .collect::(); let select_state = SelectNextState { - query: AhoCorasick::new_auto_configured(&[query]), + query: AhoCorasick::new(&[query])?, wordwise: true, done: false, }; @@ -6019,16 +6019,21 @@ impl Editor { .text_for_range(selection.start..selection.end) .collect::(); self.select_next_state = Some(SelectNextState { - query: AhoCorasick::new_auto_configured(&[query]), + query: AhoCorasick::new(&[query])?, wordwise: false, done: false, }); - self.select_next(action, cx); + self.select_next(action, cx)?; } } + Ok(()) } - pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext) { + pub fn select_previous( + &mut self, + action: &SelectPrevious, + cx: &mut ViewContext, + ) -> Result<()> { self.push_to_selection_history(); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = &display_map.buffer_snapshot; @@ -6099,7 +6104,7 @@ impl Editor { .collect::(); let query = query.chars().rev().collect::(); let select_state = SelectNextState { - query: AhoCorasick::new_auto_configured(&[query]), + query: AhoCorasick::new(&[query])?, wordwise: true, done: false, }; @@ -6114,13 +6119,14 @@ impl Editor { .collect::(); let query = query.chars().rev().collect::(); self.select_prev_state = Some(SelectNextState { - query: AhoCorasick::new_auto_configured(&[query]), + query: AhoCorasick::new(&[query])?, wordwise: false, done: false, }); - self.select_previous(action, cx); + self.select_previous(action, cx)?; } } + Ok(()) } pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext) { diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index f11639a770..7acf0c652f 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -3669,10 +3669,12 @@ async fn test_select_next(cx: &mut gpui::TestAppContext) { let mut cx = EditorTestContext::new(cx).await; cx.set_state("abc\nˇabc abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)); + cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)) + .unwrap(); cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)); + cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)) + .unwrap(); cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc"); cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx)); @@ -3681,10 +3683,12 @@ async fn test_select_next(cx: &mut gpui::TestAppContext) { cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx)); cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)); + cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)) + .unwrap(); cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»"); - cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)); + cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»"); } @@ -3696,10 +3700,12 @@ async fn test_select_previous(cx: &mut gpui::TestAppContext) { let mut cx = EditorTestContext::new(cx).await; cx.set_state("abc\nˇabc abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\nabc"); cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx)); @@ -3708,10 +3714,12 @@ async fn test_select_previous(cx: &mut gpui::TestAppContext) { cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx)); cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\n«abcˇ»"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»"); } { @@ -3719,10 +3727,12 @@ async fn test_select_previous(cx: &mut gpui::TestAppContext) { let mut cx = EditorTestContext::new(cx).await; cx.set_state("abc\n«ˇabc» abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\nabc"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\n«abcˇ»"); cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx)); @@ -3731,10 +3741,12 @@ async fn test_select_previous(cx: &mut gpui::TestAppContext) { cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx)); cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\n«abcˇ»"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndef«abcˇ»\n«abcˇ»"); - cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)) + .unwrap(); cx.assert_editor_state("«abcˇ»\n«ˇabc» «abcˇ»\ndef«abcˇ»\n«abcˇ»"); } } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index bfe5f89f68..0dc76ed54a 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -37,7 +37,7 @@ sum_tree = { path = "../sum_tree" } terminal = { path = "../terminal" } util = { path = "../util" } -aho-corasick = "0.7" +aho-corasick = "1.1" anyhow.workspace = true async-trait.workspace = true backtrace = "0.3" diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index b6adb371e1..540915f354 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -3598,7 +3598,7 @@ async fn test_search(cx: &mut gpui::TestAppContext) { assert_eq!( search( &project, - SearchQuery::text("TWO", false, true, Vec::new(), Vec::new()), + SearchQuery::text("TWO", false, true, Vec::new(), Vec::new()).unwrap(), cx ) .await @@ -3623,7 +3623,7 @@ async fn test_search(cx: &mut gpui::TestAppContext) { assert_eq!( search( &project, - SearchQuery::text("TWO", false, true, Vec::new(), Vec::new()), + SearchQuery::text("TWO", false, true, Vec::new(), Vec::new()).unwrap(), cx ) .await @@ -3664,7 +3664,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { true, vec![PathMatcher::new("*.odd").unwrap()], Vec::new() - ), + ) + .unwrap(), cx ) .await @@ -3682,7 +3683,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { true, vec![PathMatcher::new("*.rs").unwrap()], Vec::new() - ), + ) + .unwrap(), cx ) .await @@ -3706,7 +3708,7 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { PathMatcher::new("*.odd").unwrap(), ], Vec::new() - ), + ).unwrap(), cx ) .await @@ -3731,7 +3733,7 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { PathMatcher::new("*.odd").unwrap(), ], Vec::new() - ), + ).unwrap(), cx ) .await @@ -3774,7 +3776,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { true, Vec::new(), vec![PathMatcher::new("*.odd").unwrap()], - ), + ) + .unwrap(), cx ) .await @@ -3797,7 +3800,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { true, Vec::new(), vec![PathMatcher::new("*.rs").unwrap()], - ), + ) + .unwrap(), cx ) .await @@ -3821,7 +3825,7 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { PathMatcher::new("*.ts").unwrap(), PathMatcher::new("*.odd").unwrap(), ], - ), + ).unwrap(), cx ) .await @@ -3846,7 +3850,7 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { PathMatcher::new("*.ts").unwrap(), PathMatcher::new("*.odd").unwrap(), ], - ), + ).unwrap(), cx ) .await @@ -3883,7 +3887,8 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex true, vec![PathMatcher::new("*.odd").unwrap()], vec![PathMatcher::new("*.odd").unwrap()], - ), + ) + .unwrap(), cx ) .await @@ -3901,7 +3906,7 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex true, vec![PathMatcher::new("*.ts").unwrap()], vec![PathMatcher::new("*.ts").unwrap()], - ), + ).unwrap(), cx ) .await @@ -3925,7 +3930,8 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex PathMatcher::new("*.ts").unwrap(), PathMatcher::new("*.odd").unwrap() ], - ), + ) + .unwrap(), cx ) .await @@ -3949,7 +3955,8 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex PathMatcher::new("*.rs").unwrap(), PathMatcher::new("*.odd").unwrap() ], - ), + ) + .unwrap(), cx ) .await diff --git a/crates/project/src/search.rs b/crates/project/src/search.rs index bf81158701..663ad46123 100644 --- a/crates/project/src/search.rs +++ b/crates/project/src/search.rs @@ -35,7 +35,7 @@ impl SearchInputs { #[derive(Clone, Debug)] pub enum SearchQuery { Text { - search: Arc>, + search: Arc, replacement: Option, whole_word: bool, case_sensitive: bool, @@ -84,24 +84,23 @@ impl SearchQuery { case_sensitive: bool, files_to_include: Vec, files_to_exclude: Vec, - ) -> Self { + ) -> Result { let query = query.to_string(); let search = AhoCorasickBuilder::new() - .auto_configure(&[&query]) .ascii_case_insensitive(!case_sensitive) - .build(&[&query]); + .build(&[&query])?; let inner = SearchInputs { query: query.into(), files_to_exclude, files_to_include, }; - Self::Text { + Ok(Self::Text { search: Arc::new(search), replacement: None, whole_word, case_sensitive, inner, - } + }) } pub fn regex( @@ -151,13 +150,13 @@ impl SearchQuery { deserialize_path_matches(&message.files_to_exclude)?, ) } else { - Ok(Self::text( + Self::text( message.query, message.whole_word, message.case_sensitive, deserialize_path_matches(&message.files_to_include)?, deserialize_path_matches(&message.files_to_exclude)?, - )) + ) } } pub fn with_replacement(mut self, new_replacement: Option) -> Self { diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index bf92c2b72e..5fc0854b81 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -783,14 +783,21 @@ impl BufferSearchBar { } } } else { - SearchQuery::text( + match SearchQuery::text( query, self.search_options.contains(SearchOptions::WHOLE_WORD), self.search_options.contains(SearchOptions::CASE_SENSITIVE), Vec::new(), Vec::new(), - ) - .with_replacement(Some(self.replacement(cx)).filter(|s| !s.is_empty())) + ) { + Ok(query) => query + .with_replacement(Some(self.replacement(cx)).filter(|s| !s.is_empty())), + Err(_) => { + self.query_contains_error = true; + cx.notify(); + return done_rx; + } + } } .into(); self.active_search = Some(query.clone()); diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 240928d4e0..1944219117 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -1050,13 +1050,23 @@ impl ProjectSearchView { } } } - _ => Some(SearchQuery::text( + _ => match SearchQuery::text( text, self.search_options.contains(SearchOptions::WHOLE_WORD), self.search_options.contains(SearchOptions::CASE_SENSITIVE), included_files, excluded_files, - )), + ) { + Ok(query) => { + self.panels_with_errors.remove(&InputPanel::Query); + Some(query) + } + Err(_e) => { + self.panels_with_errors.insert(InputPanel::Query); + cx.notify(); + None + } + }, } } From 230061d838718ae7b6fc12b843f0f2695f7439b2 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:58:59 +0200 Subject: [PATCH 37/38] chore: Enable v0 symbol mangling (#2985) https://github.com/rust-lang/rust/issues/60705 Due to modification of .cargo/config.toml your `cargo build` should pick this change up automatically. Use `legacy` instead of `v0` if you find yourself in need of old mangling scheme for whatever reason Release Notes: - Improved precision of backtraces in application crashes --- .cargo/config.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 35049cbcb1..9da6b3be08 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,6 @@ [alias] xtask = "run --package xtask --" + +[build] +# v0 mangling scheme provides more detailed backtraces around closures +rustflags = ["-C", "symbol-mangling-version=v0"] From 417f28effe8af393443e48eaa6b782af0ae36186 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 18 Sep 2023 12:12:23 -0600 Subject: [PATCH 38/38] Fix vim-related panic --- crates/vim/src/editor_events.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/crates/vim/src/editor_events.rs b/crates/vim/src/editor_events.rs index ae6a2808cf..4b6046ae62 100644 --- a/crates/vim/src/editor_events.rs +++ b/crates/vim/src/editor_events.rs @@ -34,11 +34,11 @@ fn focused(EditorFocused(editor): &EditorFocused, cx: &mut AppContext) { fn blurred(EditorBlurred(editor): &EditorBlurred, cx: &mut AppContext) { editor.window().update(cx, |cx| { Vim::update(cx, |vim, cx| { - vim.clear_operator(cx); vim.workspace_state.recording = false; vim.workspace_state.recorded_actions.clear(); if let Some(previous_editor) = vim.active_editor.clone() { if previous_editor == editor.clone() { + vim.clear_operator(cx); vim.active_editor = None; } } @@ -60,3 +60,31 @@ fn released(EditorReleased(editor): &EditorReleased, cx: &mut AppContext) { }); }); } + +#[cfg(test)] +mod test { + use crate::{test::VimTestContext, Vim}; + use editor::Editor; + use gpui::View; + use language::Buffer; + + // regression test for blur called with a different active editor + #[gpui::test] + async fn test_blur_focus(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + let buffer = cx.add_model(|_| Buffer::new(0, 0, "a = 1\nb = 2\n")); + let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx)); + let editor2 = cx.read(|cx| window2.root(cx)).unwrap(); + + cx.update(|cx| { + let vim = Vim::read(cx); + assert_eq!(vim.active_editor.unwrap().id(), editor2.id()) + }); + + // no panic when blurring an editor in a different window. + cx.update_editor(|editor1, cx| { + editor1.focus_out(cx.handle().into_any(), cx); + }); + } +}