{
let nostr = NostrRegistry::global(cx);
let current_user = nostr.read(cx).current_user();
- let mut row = h_flex()
+ h_flex()
.id("sidebar-user")
.w_full()
.h(TABBAR_HEIGHT)
@@ -178,387 +169,139 @@ impl Sidebar {
.px_2()
.when(cfg!(target_os = "macos"), |this| {
this.pl(px(TRAFFIC_LIGHT_PADDING))
- });
+ })
+ .when_some(current_user.as_ref(), |this, public_key| {
+ let persons = PersonRegistry::global(cx);
+ let profile = persons.read(cx).get(public_key, cx);
+ let avatar = profile.avatar();
+ let avatar_seed = profile.avatar_seed();
+ let name = profile.name();
- if let Some(public_key) = current_user.as_ref() {
- let persons = PersonRegistry::global(cx);
- let profile = persons.read(cx).get(public_key, cx);
- let avatar = profile.avatar();
- let avatar_seed = profile.avatar_seed();
- let name = profile.name();
+ this.child(
+ Button::new("current-user")
+ .child(
+ Avatar::new(avatar.clone())
+ .seed(avatar_seed.clone())
+ .xsmall(),
+ )
+ .small()
+ .caret()
+ .compact()
+ .transparent()
+ .dropdown_menu(move |this, _window, cx| {
+ let avatar = avatar.clone();
+ let avatar_seed = avatar_seed.clone();
+ let name = name.clone();
- row = row.child(
- Button::new("current-user")
- .child(
- Avatar::new(avatar.clone())
- .seed(avatar_seed.clone())
- .xsmall(),
- )
- .small()
- .caret()
- .compact()
- .transparent()
- .dropdown_menu(move |this, _window, cx| {
- let avatar = avatar.clone();
- let avatar_seed = avatar_seed.clone();
- let name = name.clone();
-
- this.min_w(px(256.))
- .item(PopupMenuItem::element(move |_window, cx| {
- h_flex()
- .gap_1p5()
- .text_xs()
- .text_color(cx.theme().text_muted)
- .child(
- Avatar::new(avatar.clone())
- .seed(avatar_seed.clone())
- .xsmall(),
- )
- .child(name.clone())
- }))
- .separator()
- .menu_with_icon("Inbox", IconName::Inbox, Box::new(Command::ShowInbox))
- .menu_with_icon(
- "Search",
- IconName::Search,
- Box::new(Command::ShowSearch),
- )
- .menu_with_icon(
- "Profile",
- IconName::Profile,
- Box::new(Command::ShowProfile),
- )
- .menu_with_icon(
- "Contact List",
- IconName::Book,
- Box::new(Command::ShowContactList),
- )
- .menu_with_icon(
- "Backup",
- IconName::UserKey,
- Box::new(Command::ShowBackup),
- )
- .menu_with_icon("Themes", IconName::Sun, Box::new(Command::ToggleTheme))
- .when(AutoUpdater::is_available(cx), |this| {
- this.separator().menu_with_icon(
- "Check for Updates",
- IconName::Device,
- Box::new(Command::Update),
+ this.min_w(px(256.))
+ .item(PopupMenuItem::element(move |_window, cx| {
+ h_flex()
+ .gap_1p5()
+ .text_xs()
+ .text_color(cx.theme().text_muted)
+ .child(
+ Avatar::new(avatar.clone())
+ .seed(avatar_seed.clone())
+ .xsmall(),
+ )
+ .child(name.clone())
+ }))
+ .separator()
+ .menu_with_icon(
+ "Inbox",
+ IconName::Inbox,
+ Box::new(Command::ShowInbox),
)
- })
- .menu_with_icon(
- "Settings",
- IconName::Settings,
- Box::new(Command::ShowSettings),
- )
- }),
- );
- }
-
- if self.community.is_some() {
- row = row.child(div().flex_1()).child(
- Button::new("sidebar-back")
- .icon(IconName::ArrowLeft)
- .tooltip("Back")
- .ghost()
- .small()
- .on_click(cx.listener(|this, _event, _window, cx| {
- this.reset_community(cx);
- })),
- );
- }
-
- title_bar_drag_handlers(row, window, cx).into_any_element()
- }
-}
-
-fn recent_communities(cx: &App) -> Vec
> {
- const LIMIT: usize = 3;
-
- let registry = CommunityRegistry::global(cx);
- let communities = registry.read(cx).communities();
- let recent = AppSettings::get_recent_communities(cx);
-
- let mut rows: Vec> = recent
- .iter()
- .filter_map(|id| {
- communities
- .iter()
- .find(|community| community.read(cx).id().to_hex() == *id)
- })
- .take(LIMIT)
- .cloned()
- .collect();
-
- if rows.is_empty() {
- rows = communities.iter().take(LIMIT).cloned().collect();
- }
-
- rows
-}
-
-fn rows_for(tab: SidebarTab, cx: &App) -> Vec {
- match tab {
- SidebarTab::Recents => {
- let chat = ChatRegistry::global(cx);
- let rooms = chat.read(cx).rooms(&RoomKind::Ongoing, cx);
- let registry = CommunityRegistry::global(cx);
- let community_count = registry.read(cx).communities().len();
- let communities = recent_communities(cx);
-
- if communities.is_empty() && rooms.is_empty() {
- return vec![SidebarRow::Hint {
- text: "Nothing recent yet".into(),
- }];
- }
-
- let mut rows = Vec::new();
-
- if !communities.is_empty() {
- rows.push(SidebarRow::Section {
- label: "Communities".into(),
- count: community_count,
- });
- rows.extend(
- communities
- .into_iter()
- .map(|community| SidebarRow::Community { community }),
- );
- rows.push(SidebarRow::Action {
- label: "Show all communities".into(),
- tab: SidebarTab::Communities,
- });
- }
-
- if !rooms.is_empty() {
- rows.push(SidebarRow::Section {
- label: "Chats".into(),
- count: rooms.len(),
- });
- rows.extend(
- rooms
- .into_iter()
- .take(5)
- .map(|room| SidebarRow::Room { room }),
- );
- rows.push(SidebarRow::Action {
- label: "Show all chats".into(),
- tab: SidebarTab::Chats,
- });
- }
-
- rows
- }
- SidebarTab::Chats => {
- let chat = ChatRegistry::global(cx);
- let chat = chat.read(cx);
- let messages = chat.rooms(&RoomKind::Ongoing, cx);
-
- let mut rows = vec![SidebarRow::Section {
- label: "Chats".into(),
- count: messages.len(),
- }];
-
- if messages.is_empty() {
- rows.push(SidebarRow::Hint {
- text: "No conversations yet".into(),
- });
- } else {
- rows.extend(messages.into_iter().map(|room| SidebarRow::Room { room }));
- }
-
- rows
- }
- SidebarTab::Communities => {
- let registry = CommunityRegistry::global(cx);
- let communities = registry.read(cx).communities();
-
- let mut rows = vec![SidebarRow::Section {
- label: "Communities".into(),
- count: communities.len(),
- }];
-
- if communities.is_empty() {
- rows.push(SidebarRow::Hint {
- text: "No communities yet".into(),
- });
- } else {
- rows.extend(
- communities
- .iter()
- .cloned()
- .map(|community| SidebarRow::Community { community }),
- );
- }
-
- rows
- }
- }
-}
-
-fn render_rows(range: Range, rows: &[SidebarRow], cx: &Context) -> Vec {
- rows.get(range.clone())
- .into_iter()
- .flatten()
- .enumerate()
- .map(|(offset, row)| {
- let index = range.start + offset;
-
- match row {
- SidebarRow::Section { label, count } => TreeRow::new(
- ElementId::NamedInteger("tree-row".into(), index as u64),
- TreeRowKind::Section,
- label.clone(),
+ .menu_with_icon(
+ "Search",
+ IconName::Search,
+ Box::new(Command::ShowSearch),
+ )
+ .menu_with_icon(
+ "Profile",
+ IconName::Profile,
+ Box::new(Command::ShowProfile),
+ )
+ .menu_with_icon(
+ "Contact List",
+ IconName::Book,
+ Box::new(Command::ShowContactList),
+ )
+ .menu_with_icon(
+ "Backup",
+ IconName::UserKey,
+ Box::new(Command::ShowBackup),
+ )
+ .menu_with_icon(
+ "Themes",
+ IconName::Sun,
+ Box::new(Command::ToggleTheme),
+ )
+ .when(AutoUpdater::is_available(cx), |this| {
+ this.separator().menu_with_icon(
+ "Check for Updates",
+ IconName::Device,
+ Box::new(Command::Update),
+ )
+ })
+ .menu_with_icon(
+ "Settings",
+ IconName::Settings,
+ Box::new(Command::ShowSettings),
+ )
+ }),
)
- .count(*count)
- .into_any_element(),
- SidebarRow::Room { room } => {
- let name = room.read(cx).display_name(cx);
- let picture = room.read(cx).display_image(cx);
- let seed = room.read(cx).display_image_seed(cx);
- let created_at = room.read(cx).created_at.to_ago();
- let room_clone = room.clone();
-
- let handler = cx.listener(move |this, _event, window, cx| {
- this.open_room(room_clone.clone(), window, cx);
- });
-
- TreeRow::new(
- ElementId::NamedInteger("tree-row".into(), index as u64),
- TreeRowKind::Room,
- name,
- )
- .avatar(seed)
- .picture(picture)
- .created_at(created_at)
- .on_click(handler)
- .into_any_element()
- }
- SidebarRow::Community { community } => {
- let name = community.read(cx).name();
- let seed = community.read(cx).id().to_hex();
- let picture = community.read(cx).icon();
- let community = community.clone();
-
- TreeRow::new(
- ElementId::NamedInteger("tree-row".into(), index as u64),
- TreeRowKind::Community,
- name,
- )
- .avatar(seed)
- .picture(picture)
- .on_click(cx.listener(move |this, _event, window, cx| {
- this.open_community(community.clone(), window, cx);
- }))
- .into_any_element()
- }
- SidebarRow::Action { label, tab } => {
- let tab = *tab;
-
- TreeRow::new(
- ElementId::NamedInteger("tree-row".into(), index as u64),
- TreeRowKind::Action,
- label.clone(),
- )
- .icon(IconName::ArrowRight)
- .on_click(cx.listener(move |this, _event, _window, cx| {
- this.select_tab(tab, cx);
- }))
- .into_any_element()
- }
- SidebarRow::Hint { text } => TreeRow::new(
- ElementId::NamedInteger("tree-row".into(), index as u64),
- TreeRowKind::Hint,
- text.clone(),
+ })
+ .child(div().flex_1())
+ .when_some(AutoUpdater::try_global(cx), |this, updater| {
+ this.child(self.render_updater(updater, cx))
+ })
+ .when(self.community.is_some(), |this| {
+ this.child(
+ Button::new("sidebar-back")
+ .icon(IconName::ArrowLeft)
+ .tooltip("Back")
+ .ghost()
+ .small()
+ .on_click(cx.listener(|this, _event, _window, cx| {
+ this.reset_community(cx);
+ })),
)
- .into_any_element(),
- }
- })
- .collect()
-}
-
-impl Panel for Sidebar {
- fn panel_id(&self) -> SharedString {
- "Sidebar".into()
+ })
}
- fn title(&self, _cx: &App) -> AnyElement {
- SharedString::from("Sidebar").into_any_element()
- }
+ fn render_updater(&self, updater: Entity, cx: &mut App) -> AnyElement {
+ let status = updater.read(cx).status();
+ let staged = updater.read(cx).staged();
- fn closable(&self, _cx: &App) -> bool {
- false
- }
-
- fn zoomable(&self, _cx: &App) -> bool {
- false
- }
-}
-
-impl EventEmitter for Sidebar {}
-
-impl Focusable for Sidebar {
- fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
- self.focus_handle.clone()
- }
-}
-
-impl Render for Sidebar {
- fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement {
- let (logged_in, ready) = {
- let nostr = NostrRegistry::global(cx);
- (
- nostr.read(cx).current_user().is_some(),
- nostr.read(cx).ready(),
- )
- };
-
- if !logged_in {
- if !ready {
- return v_flex()
- .size_full()
- .bg(cx.theme().surface_background)
- .border_r_1()
- .border_color(cx.theme().border_variant)
- .into_any_element();
- }
- return onboarding::render(window, cx).into_any_element();
- }
-
- let community = self
- .community
- .clone()
- .and_then(|community| community.upgrade());
-
- if community.is_none() {
- self.community = None;
- }
-
- v_flex()
- .image_cache(retain_all("sidebar"))
- .size_full()
- .relative()
+ h_flex()
.gap_2()
- .bg(cx.theme().surface_background)
- .border_r_1()
- .border_color(cx.theme().border_variant)
- .child(self.render_user(window, cx))
- .map(|this| match community {
- Some(community) => this.child(self.render_community(community, cx)),
- None => this.child(self.render_tabs(cx)),
+ .text_xs()
+ .child(status)
+ .when(staged, |this| {
+ this.child(
+ Button::new("restart-to-update")
+ .icon(IconName::ArrowDownCircle)
+ .tooltip("Quit and relaunch into the installed update")
+ .small()
+ .ghost()
+ .on_click(move |_, _window, cx| {
+ updater.update(cx, |this, cx| {
+ this.restart(cx);
+ });
+ }),
+ )
})
.into_any_element()
}
-}
-impl Sidebar {
fn render_tabs(&mut self, cx: &mut Context) -> AnyElement {
let chat = ChatRegistry::global(cx);
let loading = chat.read(cx).loading();
let sidebar = cx.entity().downgrade();
let active_tab = self.active_tab;
- let rows = Rc::new(rows_for(active_tab, cx));
+ let rows = Rc::new(self.rows_for(active_tab, cx));
let scroll_handle = &self.scroll_handles[active_tab.index()];
v_flex()
@@ -653,8 +396,8 @@ impl Sidebar {
uniform_list(
active_tab.list_id(),
rows.len(),
- cx.processor(move |_this, range, _window, cx| {
- render_rows(range, rows.as_slice(), cx)
+ cx.processor(move |this, range, _window, cx| {
+ this.render_rows(range, rows.as_slice(), cx)
}),
)
.track_scroll(scroll_handle)
@@ -742,7 +485,7 @@ impl Sidebar {
.pb_2()
.track_scroll(&self.community_scroll)
.overflow_y_scroll()
- .child(section_row(
+ .child(self.section_row(
"channels",
"Channels",
channels.len(),
@@ -752,10 +495,10 @@ impl Sidebar {
))
.when(self.channels_open, |this| {
this.children(channels.into_iter().map(|(id, name, private)| {
- channel_row(id, name, private, active == Some(id), &community, cx)
+ self.channel_row(id, name, private, active == Some(id), &community, cx)
}))
})
- .child(section_row(
+ .child(self.section_row(
"admins",
"Admins",
admins.len(),
@@ -767,10 +510,10 @@ impl Sidebar {
this.children(
admins
.iter()
- .map(|public_key| member_row("community-admin", *public_key, cx)),
+ .map(|public_key| self.member_row("community-admin", *public_key, cx)),
)
})
- .child(section_row(
+ .child(self.section_row(
"members",
"Members",
members.len(),
@@ -782,7 +525,7 @@ impl Sidebar {
this.children(
members
.iter()
- .map(|public_key| member_row("member", *public_key, cx)),
+ .map(|public_key| self.member_row("member", *public_key, cx)),
)
});
@@ -806,87 +549,392 @@ impl Sidebar {
.child(Scrollbar::vertical(&self.community_scroll))
.into_any_element()
}
-}
-fn section_row(
- id: &'static str,
- label: &'static str,
- count: usize,
- open: bool,
- toggle: impl Fn(&mut Sidebar) + 'static,
- cx: &mut Context,
-) -> AnyElement {
- div()
- .flex_shrink_0()
- .child(
- TreeRow::new(ElementId::Name(id.into()), TreeRowKind::Section, label)
- .icon(if open {
- IconName::CaretDown
+ fn recent_communities(&self, cx: &App) -> Vec> {
+ const LIMIT: usize = 3;
+
+ let registry = CommunityRegistry::global(cx);
+ let communities = registry.read(cx).communities();
+ let recent = AppSettings::get_recent_communities(cx);
+
+ let mut rows: Vec> = recent
+ .iter()
+ .filter_map(|id| {
+ communities
+ .iter()
+ .find(|community| community.read(cx).id().to_hex() == *id)
+ })
+ .take(LIMIT)
+ .cloned()
+ .collect();
+
+ if rows.is_empty() {
+ rows = communities.iter().take(LIMIT).cloned().collect();
+ }
+
+ rows
+ }
+
+ fn rows_for(&self, tab: SidebarTab, cx: &App) -> Vec {
+ match tab {
+ SidebarTab::Recents => {
+ let chat = ChatRegistry::global(cx);
+ let rooms = chat.read(cx).rooms(&RoomKind::Ongoing, cx);
+ let registry = CommunityRegistry::global(cx);
+ let community_count = registry.read(cx).communities().len();
+ let communities = self.recent_communities(cx);
+
+ if communities.is_empty() && rooms.is_empty() {
+ return vec![SidebarRow::Hint {
+ text: "Nothing recent yet".into(),
+ }];
+ }
+
+ let mut rows = Vec::new();
+
+ if !communities.is_empty() {
+ rows.push(SidebarRow::Section {
+ label: "Communities".into(),
+ count: community_count,
+ });
+ rows.extend(
+ communities
+ .into_iter()
+ .map(|community| SidebarRow::Community { community }),
+ );
+ rows.push(SidebarRow::Action {
+ label: "Show all communities".into(),
+ tab: SidebarTab::Communities,
+ });
+ }
+
+ if !rooms.is_empty() {
+ rows.push(SidebarRow::Section {
+ label: "Chats".into(),
+ count: rooms.len(),
+ });
+ rows.extend(
+ rooms
+ .into_iter()
+ .take(5)
+ .map(|room| SidebarRow::Room { room }),
+ );
+ rows.push(SidebarRow::Action {
+ label: "Show all chats".into(),
+ tab: SidebarTab::Chats,
+ });
+ }
+
+ rows
+ }
+ SidebarTab::Chats => {
+ let chat = ChatRegistry::global(cx);
+ let chat = chat.read(cx);
+ let messages = chat.rooms(&RoomKind::Ongoing, cx);
+
+ let mut rows = vec![SidebarRow::Section {
+ label: "Chats".into(),
+ count: messages.len(),
+ }];
+
+ if messages.is_empty() {
+ rows.push(SidebarRow::Hint {
+ text: "No conversations yet".into(),
+ });
} else {
- IconName::CaretRight
+ rows.extend(messages.into_iter().map(|room| SidebarRow::Room { room }));
+ }
+
+ rows
+ }
+ SidebarTab::Communities => {
+ let registry = CommunityRegistry::global(cx);
+ let communities = registry.read(cx).communities();
+
+ let mut rows = vec![SidebarRow::Section {
+ label: "Communities".into(),
+ count: communities.len(),
+ }];
+
+ if communities.is_empty() {
+ rows.push(SidebarRow::Hint {
+ text: "No communities yet".into(),
+ });
+ } else {
+ rows.extend(
+ communities
+ .iter()
+ .cloned()
+ .map(|community| SidebarRow::Community { community }),
+ );
+ }
+
+ rows
+ }
+ }
+ }
+
+ fn render_rows(
+ &self,
+ range: Range,
+ rows: &[SidebarRow],
+ cx: &Context,
+ ) -> Vec {
+ rows.get(range.clone())
+ .into_iter()
+ .flatten()
+ .enumerate()
+ .map(|(offset, row)| {
+ let index = range.start + offset;
+
+ match row {
+ SidebarRow::Section { label, count } => TreeRow::new(
+ ElementId::NamedInteger("tree-row".into(), index as u64),
+ TreeRowKind::Section,
+ label.clone(),
+ )
+ .count(*count)
+ .into_any_element(),
+ SidebarRow::Room { room } => {
+ let name = room.read(cx).display_name(cx);
+ let picture = room.read(cx).display_image(cx);
+ let seed = room.read(cx).display_image_seed(cx);
+ let created_at = room.read(cx).created_at.to_ago();
+ let room_clone = room.clone();
+
+ let handler = cx.listener(move |this, _event, window, cx| {
+ this.open_room(room_clone.clone(), window, cx);
+ });
+
+ TreeRow::new(
+ ElementId::NamedInteger("tree-row".into(), index as u64),
+ TreeRowKind::Room,
+ name,
+ )
+ .avatar(seed)
+ .picture(picture)
+ .created_at(created_at)
+ .on_click(handler)
+ .into_any_element()
+ }
+ SidebarRow::Community { community } => {
+ let name = community.read(cx).name();
+ let seed = community.read(cx).id().to_hex();
+ let picture = community.read(cx).icon();
+ let community = community.clone();
+
+ TreeRow::new(
+ ElementId::NamedInteger("tree-row".into(), index as u64),
+ TreeRowKind::Community,
+ name,
+ )
+ .avatar(seed)
+ .picture(picture)
+ .on_click(cx.listener(move |this, _event, window, cx| {
+ this.open_community(community.clone(), window, cx);
+ }))
+ .into_any_element()
+ }
+ SidebarRow::Action { label, tab } => {
+ let tab = *tab;
+
+ TreeRow::new(
+ ElementId::NamedInteger("tree-row".into(), index as u64),
+ TreeRowKind::Action,
+ label.clone(),
+ )
+ .icon(IconName::ArrowRight)
+ .on_click(cx.listener(move |this, _event, _window, cx| {
+ this.select_tab(tab, cx);
+ }))
+ .into_any_element()
+ }
+ SidebarRow::Hint { text } => TreeRow::new(
+ ElementId::NamedInteger("tree-row".into(), index as u64),
+ TreeRowKind::Hint,
+ text.clone(),
+ )
+ .into_any_element(),
+ }
+ })
+ .collect()
+ }
+
+ fn section_row(
+ &self,
+ id: &'static str,
+ label: &'static str,
+ count: usize,
+ open: bool,
+ toggle: impl Fn(&mut Sidebar) + 'static,
+ cx: &mut Context,
+ ) -> AnyElement {
+ div()
+ .flex_shrink_0()
+ .child(
+ TreeRow::new(ElementId::Name(id.into()), TreeRowKind::Section, label)
+ .icon(if open {
+ IconName::CaretDown
+ } else {
+ IconName::CaretRight
+ })
+ .count(count)
+ .on_click(cx.listener(move |this, _event, _window, cx| {
+ toggle(this);
+ cx.notify();
+ })),
+ )
+ .into_any_element()
+ }
+
+ fn channel_row(
+ &self,
+ id: ChannelId,
+ name: String,
+ private: bool,
+ selected: bool,
+ community: &Entity,
+ cx: &mut Context,
+ ) -> AnyElement {
+ let community = community.clone();
+
+ div()
+ .flex_shrink_0()
+ .rounded(cx.theme().radius)
+ .child(
+ TreeRow::new(
+ ElementId::Name(SharedString::from(format!(
+ "community-channel-{}",
+ id.to_hex()
+ ))),
+ TreeRowKind::Room,
+ name,
+ )
+ .icon(if private {
+ IconName::Lock
+ } else {
+ IconName::Message
})
- .count(count)
- .on_click(cx.listener(move |this, _event, _window, cx| {
- toggle(this);
+ .on_click(cx.listener(move |_this, _event, _window, cx| {
+ community.update(cx, |community, cx| community.set_active_channel(id, cx));
cx.notify();
})),
- )
- .into_any_element()
+ )
+ .when(selected, |this| this.bg(cx.theme().ghost_element_active))
+ .into_any_element()
+ }
+
+ fn member_row(&self, prefix: &str, public_key: PublicKey, cx: &App) -> AnyElement {
+ let persons = PersonRegistry::global(cx);
+ let person = persons.read(cx).get(&public_key, cx);
+
+ div()
+ .flex_shrink_0()
+ .child(
+ TreeRow::new(
+ ElementId::Name(SharedString::from(format!(
+ "{prefix}-{}",
+ public_key.to_hex()
+ ))),
+ TreeRowKind::Room,
+ person.name(),
+ )
+ .avatar(person.avatar_seed())
+ .picture(person.avatar()),
+ )
+ .into_any_element()
+ }
}
-fn channel_row(
- id: ChannelId,
- name: String,
- private: bool,
- selected: bool,
- community: &Entity,
- cx: &mut Context,
-) -> AnyElement {
- let community = community.clone();
+impl Panel for Sidebar {
+ fn panel_id(&self) -> SharedString {
+ "Sidebar".into()
+ }
- div()
- .flex_shrink_0()
- .rounded(cx.theme().radius)
- .child(
- TreeRow::new(
- ElementId::Name(SharedString::from(format!(
- "community-channel-{}",
- id.to_hex()
- ))),
- TreeRowKind::Room,
- name,
- )
- .icon(if private {
- IconName::Lock
- } else {
- IconName::Message
+ fn title(&self, _cx: &App) -> AnyElement {
+ SharedString::from("Sidebar").into_any_element()
+ }
+
+ fn closable(&self, _cx: &App) -> bool {
+ false
+ }
+
+ fn zoomable(&self, _cx: &App) -> bool {
+ false
+ }
+}
+
+impl EventEmitter for Sidebar {}
+
+impl Focusable for Sidebar {
+ fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
+ self.focus_handle.clone()
+ }
+}
+
+impl Render for Sidebar {
+ fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement {
+ let nostr = NostrRegistry::global(cx);
+ let logged_in = { nostr.read(cx).current_user().is_some() };
+
+ let community = self
+ .community
+ .clone()
+ .and_then(|community| community.upgrade());
+
+ v_flex()
+ .image_cache(retain_all("sidebar"))
+ .size_full()
+ .relative()
+ .gap_2()
+ .bg(cx.theme().surface_background)
+ .border_r_1()
+ .border_color(cx.theme().border_variant)
+ .when(!logged_in, |this| {
+ this.relative()
+ .child(title_bar_drag_handlers(
+ div()
+ .id("onboarding-drag")
+ .absolute()
+ .top_0()
+ .left_0()
+ .h(TABBAR_HEIGHT)
+ .w_full(),
+ window,
+ cx,
+ ))
+ .child(
+ v_flex()
+ .size_full()
+ .justify_end()
+ .gap_4()
+ .p_4()
+ .child(
+ v_flex().child(div().font_semibold().child("Coop")).child(
+ div()
+ .text_xs()
+ .text_color(cx.theme().text_muted)
+ .child("TODO"),
+ ),
+ )
+ .child(
+ Button::new("import-identity")
+ .label("Import identity")
+ .primary()
+ .font_semibold()
+ .h_8()
+ .w_full()
+ .on_click(|_, window, cx| {
+ import::open(window, cx);
+ }),
+ ),
+ )
})
- .on_click(cx.listener(move |_this, _event, _window, cx| {
- community.update(cx, |community, cx| community.set_active_channel(id, cx));
- cx.notify();
- })),
- )
- .when(selected, |this| this.bg(cx.theme().ghost_element_active))
- .into_any_element()
-}
-
-fn member_row(prefix: &str, public_key: PublicKey, cx: &App) -> AnyElement {
- let persons = PersonRegistry::global(cx);
- let person = persons.read(cx).get(&public_key, cx);
-
- div()
- .flex_shrink_0()
- .child(
- TreeRow::new(
- ElementId::Name(SharedString::from(format!(
- "{prefix}-{}",
- public_key.to_hex()
- ))),
- TreeRowKind::Room,
- person.name(),
- )
- .avatar(person.avatar_seed())
- .picture(person.avatar()),
- )
- .into_any_element()
+ .child(title_bar_drag_handlers(self.render_user(cx), window, cx))
+ .map(|this| match community {
+ Some(community) => this.child(self.render_community(community, cx)),
+ None => this.child(self.render_tabs(cx)),
+ })
+ .into_any_element()
+ }
}
diff --git a/crates/workspace/src/sidebar/onboarding.rs b/crates/workspace/src/sidebar/onboarding.rs
deleted file mode 100644
index abf2d9d4..00000000
--- a/crates/workspace/src/sidebar/onboarding.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use gpui::{App, InteractiveElement, IntoElement, ParentElement, Styled, Window, div, svg};
-use theme::{ActiveTheme, TABBAR_HEIGHT};
-use ui::button::{Button, ButtonVariants};
-use ui::{StyledExt, h_flex, title_bar_drag_handlers, v_flex};
-
-use crate::dialogs::import;
-
-const TITLE: &str = "Welcome to Coop!";
-const DESCRIPTION: &str = "Chat Freely, Stay Private on Nostr.";
-
-pub(super) fn render(window: &mut Window, cx: &mut App) -> impl IntoElement {
- v_flex()
- .size_full()
- .relative()
- .bg(cx.theme().surface_background)
- .child(title_bar_drag_handlers(
- div()
- .id("onboarding-drag")
- .absolute()
- .top_0()
- .left_0()
- .h(TABBAR_HEIGHT)
- .w_full(),
- window,
- cx,
- ))
- .child(
- v_flex()
- .size_full()
- .justify_end()
- .gap_4()
- .p_4()
- .child(
- h_flex()
- .gap_2()
- .child(
- svg()
- .path("brand/coop.svg")
- .size_8()
- .text_color(cx.theme().icon_muted),
- )
- .child(
- v_flex().child(div().font_semibold().child(TITLE)).child(
- div()
- .text_xs()
- .text_color(cx.theme().text_muted)
- .child(DESCRIPTION),
- ),
- ),
- )
- .child(
- v_flex()
- .gap_2()
- .w_full()
- .child(
- Button::new("join-now")
- .label("Join now")
- .primary()
- .font_semibold()
- .h_8()
- .w_full(),
- )
- .child(
- Button::new("import-identity")
- .label("Import identity")
- .secondary()
- .font_semibold()
- .h_8()
- .w_full()
- .on_click(|_event, window, cx| import::open(window, cx)),
- ),
- ),
- )
-}