Update channel moving to match
This commit is contained in:
parent
c6d33d4bb9
commit
08de0d88b1
6 changed files with 72 additions and 30 deletions
|
@ -995,20 +995,20 @@ impl Database {
|
||||||
let new_parent = self.get_channel_internal(new_parent_id, &*tx).await?;
|
let new_parent = self.get_channel_internal(new_parent_id, &*tx).await?;
|
||||||
|
|
||||||
if new_parent.root_id() != channel.root_id() {
|
if new_parent.root_id() != channel.root_id() {
|
||||||
Err(anyhow!("cannot move a channel into a different root"))?;
|
Err(anyhow!(ErrorCode::WrongMoveTarget))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_parent
|
if new_parent
|
||||||
.ancestors_including_self()
|
.ancestors_including_self()
|
||||||
.any(|id| id == channel.id)
|
.any(|id| id == channel.id)
|
||||||
{
|
{
|
||||||
Err(anyhow!("cannot move a channel into one of its descendants"))?;
|
Err(anyhow!(ErrorCode::CircularNesting))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.visibility == ChannelVisibility::Public
|
if channel.visibility == ChannelVisibility::Public
|
||||||
&& new_parent.visibility != ChannelVisibility::Public
|
&& new_parent.visibility != ChannelVisibility::Public
|
||||||
{
|
{
|
||||||
Err(anyhow!("public channels must descend from public channels"))?;
|
Err(anyhow!(ErrorCode::BadPublicNesting))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let root_id = channel.root_id();
|
let root_id = channel.root_id();
|
||||||
|
|
|
@ -1585,14 +1585,27 @@ impl CollabPanel {
|
||||||
cx: &mut ViewContext<CollabPanel>,
|
cx: &mut ViewContext<CollabPanel>,
|
||||||
) {
|
) {
|
||||||
if let Some(clipboard) = self.channel_clipboard.take() {
|
if let Some(clipboard) = self.channel_clipboard.take() {
|
||||||
self.channel_store
|
self.move_channel(clipboard.channel_id, to_channel_id, cx)
|
||||||
.update(cx, |channel_store, cx| {
|
|
||||||
channel_store.move_channel(clipboard.channel_id, to_channel_id, cx)
|
|
||||||
})
|
|
||||||
.detach_and_prompt_err("Failed to move channel", cx, |_, _| None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn move_channel(&self, channel_id: ChannelId, to: ChannelId, cx: &mut ViewContext<Self>) {
|
||||||
|
self.channel_store
|
||||||
|
.update(cx, |channel_store, cx| {
|
||||||
|
channel_store.move_channel(channel_id, to, cx)
|
||||||
|
})
|
||||||
|
.detach_and_prompt_err("Failed to move channel", cx, |e, _| match e.error_code() {
|
||||||
|
ErrorCode::BadPublicNesting => {
|
||||||
|
Some("Public channels must have public parents".into())
|
||||||
|
}
|
||||||
|
ErrorCode::CircularNesting => Some("You cannot move a channel into itself".into()),
|
||||||
|
ErrorCode::WrongMoveTarget => {
|
||||||
|
Some("You cannot move a channel into a different root channel".into())
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn open_channel_notes(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
fn open_channel_notes(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(workspace) = self.workspace.upgrade() {
|
if let Some(workspace) = self.workspace.upgrade() {
|
||||||
ChannelView::open(channel_id, workspace, cx).detach();
|
ChannelView::open(channel_id, workspace, cx).detach();
|
||||||
|
@ -2285,6 +2298,7 @@ impl CollabPanel {
|
||||||
};
|
};
|
||||||
|
|
||||||
let width = self.width.unwrap_or(px(240.));
|
let width = self.width.unwrap_or(px(240.));
|
||||||
|
let root_id = channel.root_id();
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.h_6()
|
.h_6()
|
||||||
|
@ -2292,19 +2306,28 @@ impl CollabPanel {
|
||||||
.group("")
|
.group("")
|
||||||
.flex()
|
.flex()
|
||||||
.w_full()
|
.w_full()
|
||||||
.on_drag(channel.clone(), move |channel, cx| {
|
.when(!channel.is_root_channel(), |el| {
|
||||||
cx.new_view(|_| DraggedChannelView {
|
el.on_drag(channel.clone(), move |channel, cx| {
|
||||||
channel: channel.clone(),
|
cx.new_view(|_| DraggedChannelView {
|
||||||
width,
|
channel: channel.clone(),
|
||||||
|
width,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.drag_over::<Channel>(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
.drag_over::<Channel>({
|
||||||
|
move |style, dragged_channel: &Channel, cx| {
|
||||||
|
if dragged_channel.root_id() == root_id {
|
||||||
|
style.bg(cx.theme().colors().ghost_element_hover)
|
||||||
|
} else {
|
||||||
|
style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
.on_drop(cx.listener(move |this, dragged_channel: &Channel, cx| {
|
.on_drop(cx.listener(move |this, dragged_channel: &Channel, cx| {
|
||||||
this.channel_store
|
if dragged_channel.root_id() != root_id {
|
||||||
.update(cx, |channel_store, cx| {
|
return;
|
||||||
channel_store.move_channel(dragged_channel.id, channel_id, cx)
|
}
|
||||||
})
|
this.move_channel(dragged_channel.id, channel_id, cx);
|
||||||
.detach_and_prompt_err("Failed to move channel", cx, |_, _| None)
|
|
||||||
}))
|
}))
|
||||||
.child(
|
.child(
|
||||||
ListItem::new(channel_id as usize)
|
ListItem::new(channel_id as usize)
|
||||||
|
|
|
@ -782,10 +782,20 @@ pub trait InteractiveElement: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the given style when the given data type is dragged over this element
|
/// Apply the given style when the given data type is dragged over this element
|
||||||
fn drag_over<S: 'static>(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self {
|
fn drag_over<S: 'static>(
|
||||||
self.interactivity()
|
mut self,
|
||||||
.drag_over_styles
|
f: impl 'static + Fn(StyleRefinement, &S, &WindowContext) -> StyleRefinement,
|
||||||
.push((TypeId::of::<S>(), f(StyleRefinement::default())));
|
) -> Self {
|
||||||
|
self.interactivity().drag_over_styles.push((
|
||||||
|
TypeId::of::<S>(),
|
||||||
|
Box::new(move |currently_dragged: &dyn Any, cx| {
|
||||||
|
f(
|
||||||
|
StyleRefinement::default(),
|
||||||
|
currently_dragged.downcast_ref::<S>().unwrap(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,7 +1184,10 @@ pub struct Interactivity {
|
||||||
pub(crate) group_hover_style: Option<GroupStyle>,
|
pub(crate) group_hover_style: Option<GroupStyle>,
|
||||||
pub(crate) active_style: Option<Box<StyleRefinement>>,
|
pub(crate) active_style: Option<Box<StyleRefinement>>,
|
||||||
pub(crate) group_active_style: Option<GroupStyle>,
|
pub(crate) group_active_style: Option<GroupStyle>,
|
||||||
pub(crate) drag_over_styles: Vec<(TypeId, StyleRefinement)>,
|
pub(crate) drag_over_styles: Vec<(
|
||||||
|
TypeId,
|
||||||
|
Box<dyn Fn(&dyn Any, &mut WindowContext) -> StyleRefinement>,
|
||||||
|
)>,
|
||||||
pub(crate) group_drag_over_styles: Vec<(TypeId, GroupStyle)>,
|
pub(crate) group_drag_over_styles: Vec<(TypeId, GroupStyle)>,
|
||||||
pub(crate) mouse_down_listeners: Vec<MouseDownListener>,
|
pub(crate) mouse_down_listeners: Vec<MouseDownListener>,
|
||||||
pub(crate) mouse_up_listeners: Vec<MouseUpListener>,
|
pub(crate) mouse_up_listeners: Vec<MouseUpListener>,
|
||||||
|
@ -1980,7 +1993,7 @@ impl Interactivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (state_type, drag_over_style) in &self.drag_over_styles {
|
for (state_type, build_drag_over_style) in &self.drag_over_styles {
|
||||||
if *state_type == drag.value.as_ref().type_id()
|
if *state_type == drag.value.as_ref().type_id()
|
||||||
&& bounds
|
&& bounds
|
||||||
.intersect(&cx.content_mask().bounds)
|
.intersect(&cx.content_mask().bounds)
|
||||||
|
@ -1990,7 +2003,7 @@ impl Interactivity {
|
||||||
cx.stacking_order(),
|
cx.stacking_order(),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
style.refine(drag_over_style);
|
style.refine(&build_drag_over_style(drag.value.as_ref(), cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1368,7 +1368,7 @@ impl ProjectPanel {
|
||||||
entry_id: *entry_id,
|
entry_id: *entry_id,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.drag_over::<ProjectEntryId>(|style| {
|
.drag_over::<ProjectEntryId>(|style, _, cx| {
|
||||||
style.bg(cx.theme().colors().drop_target_background)
|
style.bg(cx.theme().colors().drop_target_background)
|
||||||
})
|
})
|
||||||
.on_drop(cx.listener(move |this, dragged_id: &ProjectEntryId, cx| {
|
.on_drop(cx.listener(move |this, dragged_id: &ProjectEntryId, cx| {
|
||||||
|
|
|
@ -214,6 +214,8 @@ enum ErrorCode {
|
||||||
NeedsCla = 7;
|
NeedsCla = 7;
|
||||||
NotARootChannel = 8;
|
NotARootChannel = 8;
|
||||||
BadPublicNesting = 9;
|
BadPublicNesting = 9;
|
||||||
|
CircularNesting = 10;
|
||||||
|
WrongMoveTarget = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Test {
|
message Test {
|
||||||
|
|
|
@ -1334,8 +1334,12 @@ impl Pane {
|
||||||
},
|
},
|
||||||
|tab, cx| cx.new_view(|_| tab.clone()),
|
|tab, cx| cx.new_view(|_| tab.clone()),
|
||||||
)
|
)
|
||||||
.drag_over::<DraggedTab>(|tab| tab.bg(cx.theme().colors().drop_target_background))
|
.drag_over::<DraggedTab>(|tab, _, cx| {
|
||||||
.drag_over::<ProjectEntryId>(|tab| tab.bg(cx.theme().colors().drop_target_background))
|
tab.bg(cx.theme().colors().drop_target_background)
|
||||||
|
})
|
||||||
|
.drag_over::<ProjectEntryId>(|tab, _, cx| {
|
||||||
|
tab.bg(cx.theme().colors().drop_target_background)
|
||||||
|
})
|
||||||
.when_some(self.can_drop_predicate.clone(), |this, p| {
|
.when_some(self.can_drop_predicate.clone(), |this, p| {
|
||||||
this.can_drop(move |a, cx| p(a, cx))
|
this.can_drop(move |a, cx| p(a, cx))
|
||||||
})
|
})
|
||||||
|
@ -1505,10 +1509,10 @@ impl Pane {
|
||||||
.child("")
|
.child("")
|
||||||
.h_full()
|
.h_full()
|
||||||
.flex_grow()
|
.flex_grow()
|
||||||
.drag_over::<DraggedTab>(|bar| {
|
.drag_over::<DraggedTab>(|bar, _, cx| {
|
||||||
bar.bg(cx.theme().colors().drop_target_background)
|
bar.bg(cx.theme().colors().drop_target_background)
|
||||||
})
|
})
|
||||||
.drag_over::<ProjectEntryId>(|bar| {
|
.drag_over::<ProjectEntryId>(|bar, _, cx| {
|
||||||
bar.bg(cx.theme().colors().drop_target_background)
|
bar.bg(cx.theme().colors().drop_target_background)
|
||||||
})
|
})
|
||||||
.on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| {
|
.on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue