Merge branch 'collab-panel' of github.com:zed-industries/zed into collab-panel

This commit is contained in:
Mikayla 2023-08-09 10:44:50 -07:00
commit 707e41ce1f
No known key found for this signature in database
8 changed files with 112 additions and 108 deletions

View File

@ -58,16 +58,20 @@ impl ChannelStore {
client.add_message_handler(cx.handle(), Self::handle_update_channels);
let mut current_user = user_store.read(cx).watch_current_user();
let maintain_user = cx.spawn(|this, mut cx| async move {
let maintain_user = cx.spawn_weak(|this, mut cx| async move {
while let Some(current_user) = current_user.next().await {
if current_user.is_none() {
this.update(&mut cx, |this, cx| {
this.channels.clear();
this.channel_invitations.clear();
this.channel_participants.clear();
this.outgoing_invites.clear();
cx.notify();
});
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| {
this.channels.clear();
this.channel_invitations.clear();
this.channel_participants.clear();
this.outgoing_invites.clear();
cx.notify();
});
} else {
break;
}
}
}
});

View File

@ -192,11 +192,11 @@ CREATE TABLE "channels" (
"created_at" TIMESTAMP NOT NULL DEFAULT now
);
CREATE TABLE "channel_parents" (
"child_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
"parent_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
PRIMARY KEY(child_id, parent_id)
CREATE TABLE "channel_paths" (
"id_path" TEXT NOT NULL PRIMARY KEY,
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE
);
CREATE INDEX "index_channel_paths_on_channel_id" ON "channel_paths" ("channel_id");
CREATE TABLE "channel_members" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,

View File

@ -10,11 +10,11 @@ CREATE TABLE "channels" (
"created_at" TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE "channel_parents" (
"child_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
"parent_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
PRIMARY KEY(child_id, parent_id)
CREATE TABLE "channel_paths" (
"id_path" VARCHAR NOT NULL PRIMARY KEY,
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE
);
CREATE INDEX "index_channel_paths_on_channel_id" ON "channel_paths" ("channel_id");
CREATE TABLE "channel_members" (
"id" SERIAL PRIMARY KEY,

View File

@ -1,7 +1,7 @@
mod access_token;
mod channel;
mod channel_member;
mod channel_parent;
mod channel_path;
mod contact;
mod follower;
mod language_server;
@ -3169,12 +3169,34 @@ impl Database {
.insert(&*tx)
.await?;
let channel_paths_stmt;
if let Some(parent) = parent {
channel_parent::ActiveModel {
child_id: ActiveValue::Set(channel.id),
parent_id: ActiveValue::Set(parent),
}
.insert(&*tx)
let sql = r#"
INSERT INTO channel_paths
(id_path, channel_id)
SELECT
id_path || $1 || '/', $2
FROM
channel_paths
WHERE
channel_id = $3
"#;
channel_paths_stmt = Statement::from_sql_and_values(
self.pool.get_database_backend(),
sql,
[
channel.id.to_proto().into(),
channel.id.to_proto().into(),
parent.to_proto().into(),
],
);
tx.execute(channel_paths_stmt).await?;
} else {
channel_path::Entity::insert(channel_path::ActiveModel {
channel_id: ActiveValue::Set(channel.id),
id_path: ActiveValue::Set(format!("/{}/", channel.id)),
})
.exec(&*tx)
.await?;
}
@ -3213,9 +3235,9 @@ impl Database {
// Don't remove descendant channels that have additional parents.
let mut channels_to_remove = self.get_channel_descendants([channel_id], &*tx).await?;
{
let mut channels_to_keep = channel_parent::Entity::find()
let mut channels_to_keep = channel_path::Entity::find()
.filter(
channel_parent::Column::ChildId
channel_path::Column::ChannelId
.is_in(
channels_to_remove
.keys()
@ -3223,15 +3245,15 @@ impl Database {
.filter(|&id| id != channel_id),
)
.and(
channel_parent::Column::ParentId
.is_not_in(channels_to_remove.keys().copied()),
channel_path::Column::IdPath
.not_like(&format!("%/{}/%", channel_id)),
),
)
.stream(&*tx)
.await?;
while let Some(row) = channels_to_keep.next().await {
let row = row?;
channels_to_remove.remove(&row.child_id);
channels_to_remove.remove(&row.channel_id);
}
}
@ -3631,40 +3653,21 @@ impl Database {
channel_id: ChannelId,
tx: &DatabaseTransaction,
) -> Result<Vec<ChannelId>> {
let sql = format!(
r#"
WITH RECURSIVE channel_tree(child_id, parent_id) AS (
SELECT CAST(NULL as INTEGER) as child_id, root_ids.column1 as parent_id
FROM (VALUES ({})) as root_ids
UNION
SELECT channel_parents.child_id, channel_parents.parent_id
FROM channel_parents, channel_tree
WHERE channel_parents.child_id = channel_tree.parent_id
)
SELECT DISTINCT channel_tree.parent_id
FROM channel_tree
"#,
channel_id
);
#[derive(FromQueryResult, Debug, PartialEq)]
pub struct ChannelParent {
pub parent_id: ChannelId,
}
let stmt = Statement::from_string(self.pool.get_database_backend(), sql);
let mut channel_ids_stream = channel_parent::Entity::find()
.from_raw_sql(stmt)
.into_model::<ChannelParent>()
.stream(&*tx)
let paths = channel_path::Entity::find()
.filter(channel_path::Column::ChannelId.eq(channel_id))
.all(tx)
.await?;
let mut channel_ids = vec![];
while let Some(channel_id) = channel_ids_stream.next().await {
channel_ids.push(channel_id?.parent_id);
let mut channel_ids = Vec::new();
for path in paths {
for id in path.id_path.trim_matches('/').split('/') {
if let Ok(id) = id.parse() {
let id = ChannelId::from_proto(id);
if let Err(ix) = channel_ids.binary_search(&id) {
channel_ids.insert(ix, id);
}
}
}
}
Ok(channel_ids)
}
@ -3687,38 +3690,38 @@ impl Database {
let sql = format!(
r#"
WITH RECURSIVE channel_tree(child_id, parent_id) AS (
SELECT root_ids.column1 as child_id, CAST(NULL as INTEGER) as parent_id
FROM (VALUES {values}) as root_ids
UNION
SELECT channel_parents.child_id, channel_parents.parent_id
FROM channel_parents, channel_tree
WHERE channel_parents.parent_id = channel_tree.child_id
)
SELECT channel_tree.child_id, channel_tree.parent_id
FROM channel_tree
ORDER BY child_id, parent_id IS NOT NULL
"#,
SELECT
descendant_paths.*
FROM
channel_paths parent_paths, channel_paths descendant_paths
WHERE
parent_paths.channel_id IN ({values}) AND
descendant_paths.id_path LIKE (parent_paths.id_path || '%')
"#
);
#[derive(FromQueryResult, Debug, PartialEq)]
pub struct ChannelParent {
pub child_id: ChannelId,
pub parent_id: Option<ChannelId>,
}
let stmt = Statement::from_string(self.pool.get_database_backend(), sql);
let mut parents_by_child_id = HashMap::default();
let mut parents = channel_parent::Entity::find()
let mut paths = channel_path::Entity::find()
.from_raw_sql(stmt)
.into_model::<ChannelParent>()
.stream(tx)
.await?;
while let Some(parent) = parents.next().await {
let parent = parent?;
parents_by_child_id.insert(parent.child_id, parent.parent_id);
while let Some(path) = paths.next().await {
let path = path?;
let ids = path.id_path.trim_matches('/').split('/');
let mut parent_id = None;
for id in ids {
if let Ok(id) = id.parse() {
let id = ChannelId::from_proto(id);
if id == path.channel_id {
break;
}
parent_id = Some(id);
}
}
parents_by_child_id.insert(path.channel_id, parent_id);
}
Ok(parents_by_child_id)

View File

@ -2,12 +2,11 @@ use super::ChannelId;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "channel_parents")]
#[sea_orm(table_name = "channel_paths")]
pub struct Model {
#[sea_orm(primary_key)]
pub child_id: ChannelId,
#[sea_orm(primary_key)]
pub parent_id: ChannelId,
pub id_path: String,
pub channel_id: ChannelId,
}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -1103,9 +1103,12 @@ impl CollabPanel {
enum AddContact {}
let button = match section {
Section::ActiveCall => Some(
MouseEventHandler::<AddContact, Self>::new(0, cx, |_, _| {
MouseEventHandler::<AddContact, Self>::new(0, cx, |state, _| {
render_icon_button(
theme.collab_panel.leave_call_button.in_state(is_selected),
theme
.collab_panel
.leave_call_button
.style_for(is_selected, state),
"icons/radix/exit.svg",
)
})
@ -1122,9 +1125,12 @@ impl CollabPanel {
),
),
Section::Contacts => Some(
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |_, _| {
MouseEventHandler::<LeaveCallContactList, Self>::new(0, cx, |state, _| {
render_icon_button(
theme.collab_panel.add_contact_button.in_state(is_selected),
theme
.collab_panel
.add_contact_button
.style_for(is_selected, state),
"icons/plus_16.svg",
)
})
@ -1141,9 +1147,12 @@ impl CollabPanel {
),
),
Section::Channels => Some(
MouseEventHandler::<AddChannel, Self>::new(0, cx, |_, _| {
MouseEventHandler::<AddChannel, Self>::new(0, cx, |state, _| {
render_icon_button(
theme.collab_panel.add_contact_button.in_state(is_selected),
theme
.collab_panel
.add_contact_button
.style_for(is_selected, state),
"icons/plus_16.svg",
)
})

View File

@ -226,9 +226,9 @@ pub struct CollabPanel {
pub channel_modal: ChannelModal,
pub user_query_editor: FieldEditor,
pub user_query_editor_height: f32,
pub leave_call_button: Toggleable<IconButton>,
pub add_contact_button: Toggleable<IconButton>,
pub add_channel_button: Toggleable<IconButton>,
pub leave_call_button: Toggleable<Interactive<IconButton>>,
pub add_contact_button: Toggleable<Interactive<IconButton>>,
pub add_channel_button: Toggleable<Interactive<IconButton>>,
pub header_row: ContainedText,
pub subheader_row: Toggleable<Interactive<ContainedText>>,
pub leave_call: Interactive<ContainedText>,

View File

@ -8,6 +8,7 @@ import {
import { interactive, toggleable } from "../element"
import { useTheme } from "../theme"
import channel_modal from "./channel_modal"
import { icon_button, toggleable_icon_button } from "../component/icon_button"
export default function contacts_panel(): any {
@ -51,19 +52,7 @@ export default function contacts_panel(): any {
},
}
const headerButton = toggleable({
base: {
color: foreground(layer, "on"),
button_width: 28,
icon_width: 16,
},
state: {
active: {
background: background(layer, "active"),
corner_radius: 8,
}
}
})
const headerButton = toggleable_icon_button(theme, {})
return {
channel_modal: channel_modal(),