Implement copy paste for ProjectPanel
This commit is contained in:
parent
37a0c7f046
commit
3336bc6ab3
7 changed files with 253 additions and 55 deletions
|
@ -172,6 +172,7 @@ impl Server {
|
||||||
.add_request_handler(Server::forward_project_request::<proto::FormatBuffers>)
|
.add_request_handler(Server::forward_project_request::<proto::FormatBuffers>)
|
||||||
.add_request_handler(Server::forward_project_request::<proto::CreateProjectEntry>)
|
.add_request_handler(Server::forward_project_request::<proto::CreateProjectEntry>)
|
||||||
.add_request_handler(Server::forward_project_request::<proto::RenameProjectEntry>)
|
.add_request_handler(Server::forward_project_request::<proto::RenameProjectEntry>)
|
||||||
|
.add_request_handler(Server::forward_project_request::<proto::CopyProjectEntry>)
|
||||||
.add_request_handler(Server::forward_project_request::<proto::DeleteProjectEntry>)
|
.add_request_handler(Server::forward_project_request::<proto::DeleteProjectEntry>)
|
||||||
.add_request_handler(Server::update_buffer)
|
.add_request_handler(Server::update_buffer)
|
||||||
.add_message_handler(Server::update_buffer_file)
|
.add_message_handler(Server::update_buffer_file)
|
||||||
|
|
|
@ -15,6 +15,7 @@ use text::Rope;
|
||||||
pub trait Fs: Send + Sync {
|
pub trait Fs: Send + Sync {
|
||||||
async fn create_dir(&self, path: &Path) -> Result<()>;
|
async fn create_dir(&self, path: &Path) -> Result<()>;
|
||||||
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()>;
|
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()>;
|
||||||
|
async fn copy(&self, source: &Path, target: &Path, options: CopyOptions) -> Result<()>;
|
||||||
async fn rename(&self, source: &Path, target: &Path, options: RenameOptions) -> Result<()>;
|
async fn rename(&self, source: &Path, target: &Path, options: RenameOptions) -> Result<()>;
|
||||||
async fn remove_dir(&self, path: &Path, options: RemoveOptions) -> Result<()>;
|
async fn remove_dir(&self, path: &Path, options: RemoveOptions) -> Result<()>;
|
||||||
async fn remove_file(&self, path: &Path, options: RemoveOptions) -> Result<()>;
|
async fn remove_file(&self, path: &Path, options: RemoveOptions) -> Result<()>;
|
||||||
|
@ -44,6 +45,12 @@ pub struct CreateOptions {
|
||||||
pub ignore_if_exists: bool,
|
pub ignore_if_exists: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
pub struct CopyOptions {
|
||||||
|
pub overwrite: bool,
|
||||||
|
pub ignore_if_exists: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct RenameOptions {
|
pub struct RenameOptions {
|
||||||
pub overwrite: bool,
|
pub overwrite: bool,
|
||||||
|
@ -84,6 +91,35 @@ impl Fs for RealFs {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn copy(&self, source: &Path, target: &Path, options: CopyOptions) -> Result<()> {
|
||||||
|
if !options.overwrite && smol::fs::metadata(target).await.is_ok() {
|
||||||
|
if options.ignore_if_exists {
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
return Err(anyhow!("{target:?} already exists"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let metadata = smol::fs::metadata(source).await?;
|
||||||
|
let _ = smol::fs::remove_dir_all(target).await;
|
||||||
|
if metadata.is_dir() {
|
||||||
|
self.create_dir(target).await?;
|
||||||
|
let mut children = smol::fs::read_dir(source).await?;
|
||||||
|
while let Some(child) = children.next().await {
|
||||||
|
if let Ok(child) = child {
|
||||||
|
let child_source_path = child.path();
|
||||||
|
let child_target_path = target.join(child.file_name());
|
||||||
|
self.copy(&child_source_path, &child_target_path, options)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
smol::fs::copy(source, target).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn rename(&self, source: &Path, target: &Path, options: RenameOptions) -> Result<()> {
|
async fn rename(&self, source: &Path, target: &Path, options: RenameOptions) -> Result<()> {
|
||||||
if !options.overwrite && smol::fs::metadata(target).await.is_ok() {
|
if !options.overwrite && smol::fs::metadata(target).await.is_ok() {
|
||||||
if options.ignore_if_exists {
|
if options.ignore_if_exists {
|
||||||
|
@ -511,6 +547,40 @@ impl Fs for FakeFs {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn copy(&self, source: &Path, target: &Path, options: CopyOptions) -> Result<()> {
|
||||||
|
let source = normalize_path(source);
|
||||||
|
let target = normalize_path(target);
|
||||||
|
|
||||||
|
let mut state = self.state.lock().await;
|
||||||
|
state.validate_path(&source)?;
|
||||||
|
state.validate_path(&target)?;
|
||||||
|
|
||||||
|
if !options.overwrite && state.entries.contains_key(&target) {
|
||||||
|
if options.ignore_if_exists {
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
return Err(anyhow!("{target:?} already exists"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_entries = Vec::new();
|
||||||
|
for (path, entry) in &state.entries {
|
||||||
|
if let Ok(relative_path) = path.strip_prefix(&source) {
|
||||||
|
new_entries.push((relative_path.to_path_buf(), entry.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut events = Vec::new();
|
||||||
|
for (relative_path, entry) in new_entries {
|
||||||
|
let new_path = normalize_path(&target.join(relative_path));
|
||||||
|
events.push(new_path.clone());
|
||||||
|
state.entries.insert(new_path, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.emit_event(&events).await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn remove_dir(&self, dir_path: &Path, options: RemoveOptions) -> Result<()> {
|
async fn remove_dir(&self, dir_path: &Path, options: RemoveOptions) -> Result<()> {
|
||||||
let dir_path = normalize_path(dir_path);
|
let dir_path = normalize_path(dir_path);
|
||||||
let mut state = self.state.lock().await;
|
let mut state = self.state.lock().await;
|
||||||
|
|
|
@ -281,6 +281,7 @@ impl Project {
|
||||||
client.add_model_message_handler(Self::handle_update_worktree);
|
client.add_model_message_handler(Self::handle_update_worktree);
|
||||||
client.add_model_request_handler(Self::handle_create_project_entry);
|
client.add_model_request_handler(Self::handle_create_project_entry);
|
||||||
client.add_model_request_handler(Self::handle_rename_project_entry);
|
client.add_model_request_handler(Self::handle_rename_project_entry);
|
||||||
|
client.add_model_request_handler(Self::handle_copy_project_entry);
|
||||||
client.add_model_request_handler(Self::handle_delete_project_entry);
|
client.add_model_request_handler(Self::handle_delete_project_entry);
|
||||||
client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
|
client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
|
||||||
client.add_model_request_handler(Self::handle_apply_code_action);
|
client.add_model_request_handler(Self::handle_apply_code_action);
|
||||||
|
@ -778,6 +779,49 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copy_entry(
|
||||||
|
&mut self,
|
||||||
|
entry_id: ProjectEntryId,
|
||||||
|
new_path: impl Into<Arc<Path>>,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Option<Task<Result<Entry>>> {
|
||||||
|
let worktree = self.worktree_for_entry(entry_id, cx)?;
|
||||||
|
let new_path = new_path.into();
|
||||||
|
if self.is_local() {
|
||||||
|
worktree.update(cx, |worktree, cx| {
|
||||||
|
worktree
|
||||||
|
.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.copy_entry(entry_id, new_path, cx)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let client = self.client.clone();
|
||||||
|
let project_id = self.remote_id().unwrap();
|
||||||
|
|
||||||
|
Some(cx.spawn_weak(|_, mut cx| async move {
|
||||||
|
let response = client
|
||||||
|
.request(proto::CopyProjectEntry {
|
||||||
|
project_id,
|
||||||
|
entry_id: entry_id.to_proto(),
|
||||||
|
new_path: new_path.as_os_str().as_bytes().to_vec(),
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
let entry = response
|
||||||
|
.entry
|
||||||
|
.ok_or_else(|| anyhow!("missing entry in response"))?;
|
||||||
|
worktree
|
||||||
|
.update(&mut cx, |worktree, cx| {
|
||||||
|
worktree.as_remote().unwrap().insert_entry(
|
||||||
|
entry,
|
||||||
|
response.worktree_scan_id as usize,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rename_entry(
|
pub fn rename_entry(
|
||||||
&mut self,
|
&mut self,
|
||||||
entry_id: ProjectEntryId,
|
entry_id: ProjectEntryId,
|
||||||
|
@ -4027,6 +4071,34 @@ impl Project {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_copy_project_entry(
|
||||||
|
this: ModelHandle<Self>,
|
||||||
|
envelope: TypedEnvelope<proto::CopyProjectEntry>,
|
||||||
|
_: Arc<Client>,
|
||||||
|
mut cx: AsyncAppContext,
|
||||||
|
) -> Result<proto::ProjectEntryResponse> {
|
||||||
|
let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
|
||||||
|
let worktree = this.read_with(&cx, |this, cx| {
|
||||||
|
this.worktree_for_entry(entry_id, cx)
|
||||||
|
.ok_or_else(|| anyhow!("worktree not found"))
|
||||||
|
})?;
|
||||||
|
let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
|
||||||
|
let entry = worktree
|
||||||
|
.update(&mut cx, |worktree, cx| {
|
||||||
|
let new_path = PathBuf::from(OsString::from_vec(envelope.payload.new_path));
|
||||||
|
worktree
|
||||||
|
.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.copy_entry(entry_id, new_path, cx)
|
||||||
|
.ok_or_else(|| anyhow!("invalid entry"))
|
||||||
|
})?
|
||||||
|
.await?;
|
||||||
|
Ok(proto::ProjectEntryResponse {
|
||||||
|
entry: Some((&entry).into()),
|
||||||
|
worktree_scan_id: worktree_scan_id as u64,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_delete_project_entry(
|
async fn handle_delete_project_entry(
|
||||||
this: ModelHandle<Self>,
|
this: ModelHandle<Self>,
|
||||||
envelope: TypedEnvelope<proto::DeleteProjectEntry>,
|
envelope: TypedEnvelope<proto::DeleteProjectEntry>,
|
||||||
|
|
|
@ -774,6 +774,46 @@ impl LocalWorktree {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copy_entry(
|
||||||
|
&self,
|
||||||
|
entry_id: ProjectEntryId,
|
||||||
|
new_path: impl Into<Arc<Path>>,
|
||||||
|
cx: &mut ModelContext<Worktree>,
|
||||||
|
) -> Option<Task<Result<Entry>>> {
|
||||||
|
let old_path = self.entry_for_id(entry_id)?.path.clone();
|
||||||
|
let new_path = new_path.into();
|
||||||
|
let abs_old_path = self.absolutize(&old_path);
|
||||||
|
let abs_new_path = self.absolutize(&new_path);
|
||||||
|
let copy = cx.background().spawn({
|
||||||
|
let fs = self.fs.clone();
|
||||||
|
let abs_new_path = abs_new_path.clone();
|
||||||
|
async move {
|
||||||
|
fs.copy(&abs_old_path, &abs_new_path, Default::default())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(cx.spawn(|this, mut cx| async move {
|
||||||
|
copy.await?;
|
||||||
|
let entry = this
|
||||||
|
.update(&mut cx, |this, cx| {
|
||||||
|
this.as_local_mut().unwrap().refresh_entry(
|
||||||
|
new_path.clone(),
|
||||||
|
abs_new_path,
|
||||||
|
None,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
this.poll_snapshot(cx);
|
||||||
|
this.as_local().unwrap().broadcast_snapshot()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
Ok(entry)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
fn write_entry_internal(
|
fn write_entry_internal(
|
||||||
&self,
|
&self,
|
||||||
path: impl Into<Arc<Path>>,
|
path: impl Into<Arc<Path>>,
|
||||||
|
|
|
@ -698,6 +698,11 @@ impl ProjectPanel {
|
||||||
})
|
})
|
||||||
.map(|task| task.detach_and_log_err(cx));
|
.map(|task| task.detach_and_log_err(cx));
|
||||||
} else {
|
} else {
|
||||||
|
self.project
|
||||||
|
.update(cx, |project, cx| {
|
||||||
|
project.copy_entry(clipboard_entry.entry_id(), new_path, cx)
|
||||||
|
})
|
||||||
|
.map(|task| task.detach_and_log_err(cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -41,66 +41,67 @@ message Envelope {
|
||||||
|
|
||||||
CreateProjectEntry create_project_entry = 33;
|
CreateProjectEntry create_project_entry = 33;
|
||||||
RenameProjectEntry rename_project_entry = 34;
|
RenameProjectEntry rename_project_entry = 34;
|
||||||
DeleteProjectEntry delete_project_entry = 35;
|
CopyProjectEntry copy_project_entry = 35;
|
||||||
ProjectEntryResponse project_entry_response = 36;
|
DeleteProjectEntry delete_project_entry = 36;
|
||||||
|
ProjectEntryResponse project_entry_response = 37;
|
||||||
|
|
||||||
UpdateDiagnosticSummary update_diagnostic_summary = 37;
|
UpdateDiagnosticSummary update_diagnostic_summary = 38;
|
||||||
StartLanguageServer start_language_server = 38;
|
StartLanguageServer start_language_server = 39;
|
||||||
UpdateLanguageServer update_language_server = 39;
|
UpdateLanguageServer update_language_server = 40;
|
||||||
|
|
||||||
OpenBufferById open_buffer_by_id = 40;
|
OpenBufferById open_buffer_by_id = 41;
|
||||||
OpenBufferByPath open_buffer_by_path = 41;
|
OpenBufferByPath open_buffer_by_path = 42;
|
||||||
OpenBufferResponse open_buffer_response = 42;
|
OpenBufferResponse open_buffer_response = 43;
|
||||||
UpdateBuffer update_buffer = 43;
|
UpdateBuffer update_buffer = 44;
|
||||||
UpdateBufferFile update_buffer_file = 44;
|
UpdateBufferFile update_buffer_file = 45;
|
||||||
SaveBuffer save_buffer = 45;
|
SaveBuffer save_buffer = 46;
|
||||||
BufferSaved buffer_saved = 46;
|
BufferSaved buffer_saved = 47;
|
||||||
BufferReloaded buffer_reloaded = 47;
|
BufferReloaded buffer_reloaded = 48;
|
||||||
ReloadBuffers reload_buffers = 48;
|
ReloadBuffers reload_buffers = 49;
|
||||||
ReloadBuffersResponse reload_buffers_response = 49;
|
ReloadBuffersResponse reload_buffers_response = 50;
|
||||||
FormatBuffers format_buffers = 50;
|
FormatBuffers format_buffers = 51;
|
||||||
FormatBuffersResponse format_buffers_response = 51;
|
FormatBuffersResponse format_buffers_response = 52;
|
||||||
GetCompletions get_completions = 52;
|
GetCompletions get_completions = 53;
|
||||||
GetCompletionsResponse get_completions_response = 53;
|
GetCompletionsResponse get_completions_response = 54;
|
||||||
ApplyCompletionAdditionalEdits apply_completion_additional_edits = 54;
|
ApplyCompletionAdditionalEdits apply_completion_additional_edits = 55;
|
||||||
ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 55;
|
ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 56;
|
||||||
GetCodeActions get_code_actions = 56;
|
GetCodeActions get_code_actions = 57;
|
||||||
GetCodeActionsResponse get_code_actions_response = 57;
|
GetCodeActionsResponse get_code_actions_response = 58;
|
||||||
ApplyCodeAction apply_code_action = 58;
|
ApplyCodeAction apply_code_action = 59;
|
||||||
ApplyCodeActionResponse apply_code_action_response = 59;
|
ApplyCodeActionResponse apply_code_action_response = 60;
|
||||||
PrepareRename prepare_rename = 60;
|
PrepareRename prepare_rename = 61;
|
||||||
PrepareRenameResponse prepare_rename_response = 61;
|
PrepareRenameResponse prepare_rename_response = 62;
|
||||||
PerformRename perform_rename = 62;
|
PerformRename perform_rename = 63;
|
||||||
PerformRenameResponse perform_rename_response = 63;
|
PerformRenameResponse perform_rename_response = 64;
|
||||||
SearchProject search_project = 64;
|
SearchProject search_project = 65;
|
||||||
SearchProjectResponse search_project_response = 65;
|
SearchProjectResponse search_project_response = 66;
|
||||||
|
|
||||||
GetChannels get_channels = 66;
|
GetChannels get_channels = 67;
|
||||||
GetChannelsResponse get_channels_response = 67;
|
GetChannelsResponse get_channels_response = 68;
|
||||||
JoinChannel join_channel = 68;
|
JoinChannel join_channel = 69;
|
||||||
JoinChannelResponse join_channel_response = 69;
|
JoinChannelResponse join_channel_response = 70;
|
||||||
LeaveChannel leave_channel = 70;
|
LeaveChannel leave_channel = 71;
|
||||||
SendChannelMessage send_channel_message = 71;
|
SendChannelMessage send_channel_message = 72;
|
||||||
SendChannelMessageResponse send_channel_message_response = 72;
|
SendChannelMessageResponse send_channel_message_response = 73;
|
||||||
ChannelMessageSent channel_message_sent = 73;
|
ChannelMessageSent channel_message_sent = 74;
|
||||||
GetChannelMessages get_channel_messages = 74;
|
GetChannelMessages get_channel_messages = 75;
|
||||||
GetChannelMessagesResponse get_channel_messages_response = 75;
|
GetChannelMessagesResponse get_channel_messages_response = 76;
|
||||||
|
|
||||||
UpdateContacts update_contacts = 76;
|
UpdateContacts update_contacts = 77;
|
||||||
UpdateInviteInfo update_invite_info = 77;
|
UpdateInviteInfo update_invite_info = 78;
|
||||||
ShowContacts show_contacts = 78;
|
ShowContacts show_contacts = 79;
|
||||||
|
|
||||||
GetUsers get_users = 79;
|
GetUsers get_users = 80;
|
||||||
FuzzySearchUsers fuzzy_search_users = 80;
|
FuzzySearchUsers fuzzy_search_users = 81;
|
||||||
UsersResponse users_response = 81;
|
UsersResponse users_response = 82;
|
||||||
RequestContact request_contact = 82;
|
RequestContact request_contact = 83;
|
||||||
RespondToContactRequest respond_to_contact_request = 83;
|
RespondToContactRequest respond_to_contact_request = 84;
|
||||||
RemoveContact remove_contact = 84;
|
RemoveContact remove_contact = 85;
|
||||||
|
|
||||||
Follow follow = 85;
|
Follow follow = 86;
|
||||||
FollowResponse follow_response = 86;
|
FollowResponse follow_response = 87;
|
||||||
UpdateFollowers update_followers = 87;
|
UpdateFollowers update_followers = 88;
|
||||||
Unfollow unfollow = 88;
|
Unfollow unfollow = 89;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +211,12 @@ message RenameProjectEntry {
|
||||||
bytes new_path = 3;
|
bytes new_path = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message CopyProjectEntry {
|
||||||
|
uint64 project_id = 1;
|
||||||
|
uint64 entry_id = 2;
|
||||||
|
bytes new_path = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message DeleteProjectEntry {
|
message DeleteProjectEntry {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
uint64 entry_id = 2;
|
uint64 entry_id = 2;
|
||||||
|
|
|
@ -84,6 +84,7 @@ messages!(
|
||||||
(BufferSaved, Foreground),
|
(BufferSaved, Foreground),
|
||||||
(RemoveContact, Foreground),
|
(RemoveContact, Foreground),
|
||||||
(ChannelMessageSent, Foreground),
|
(ChannelMessageSent, Foreground),
|
||||||
|
(CopyProjectEntry, Foreground),
|
||||||
(CreateProjectEntry, Foreground),
|
(CreateProjectEntry, Foreground),
|
||||||
(DeleteProjectEntry, Foreground),
|
(DeleteProjectEntry, Foreground),
|
||||||
(Error, Foreground),
|
(Error, Foreground),
|
||||||
|
@ -167,6 +168,7 @@ request_messages!(
|
||||||
ApplyCompletionAdditionalEdits,
|
ApplyCompletionAdditionalEdits,
|
||||||
ApplyCompletionAdditionalEditsResponse
|
ApplyCompletionAdditionalEditsResponse
|
||||||
),
|
),
|
||||||
|
(CopyProjectEntry, ProjectEntryResponse),
|
||||||
(CreateProjectEntry, ProjectEntryResponse),
|
(CreateProjectEntry, ProjectEntryResponse),
|
||||||
(DeleteProjectEntry, ProjectEntryResponse),
|
(DeleteProjectEntry, ProjectEntryResponse),
|
||||||
(Follow, FollowResponse),
|
(Follow, FollowResponse),
|
||||||
|
@ -211,8 +213,8 @@ entity_messages!(
|
||||||
ApplyCompletionAdditionalEdits,
|
ApplyCompletionAdditionalEdits,
|
||||||
BufferReloaded,
|
BufferReloaded,
|
||||||
BufferSaved,
|
BufferSaved,
|
||||||
|
CopyProjectEntry,
|
||||||
CreateProjectEntry,
|
CreateProjectEntry,
|
||||||
RenameProjectEntry,
|
|
||||||
DeleteProjectEntry,
|
DeleteProjectEntry,
|
||||||
Follow,
|
Follow,
|
||||||
FormatBuffers,
|
FormatBuffers,
|
||||||
|
@ -233,6 +235,7 @@ entity_messages!(
|
||||||
ProjectUnshared,
|
ProjectUnshared,
|
||||||
ReloadBuffers,
|
ReloadBuffers,
|
||||||
RemoveProjectCollaborator,
|
RemoveProjectCollaborator,
|
||||||
|
RenameProjectEntry,
|
||||||
RequestJoinProject,
|
RequestJoinProject,
|
||||||
SaveBuffer,
|
SaveBuffer,
|
||||||
SearchProject,
|
SearchProject,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue