move channels UI code to channels-rpc

This commit is contained in:
Mikayla Maki 2023-07-24 12:14:15 -07:00
parent ac35dae66e
commit fe5db3035f
No known key found for this signature in database
5 changed files with 7 additions and 344 deletions

View File

@ -2,102 +2,12 @@ mod channels_panel;
mod channels_panel_settings;
pub use channels_panel::*;
use gpui::{AppContext, Entity};
use gpui::{AppContext};
use std::sync::Arc;
use client::Client;
pub fn init(client: Arc<Client>, cx: &mut AppContext) {
let channels = cx.add_model(|cx| Channels::new(client, cx));
cx.set_global(channels);
channels_panel::init(cx);
}
#[derive(Debug, Clone)]
struct Channel {
id: u64,
name: String,
sub_channels: Vec<Channel>,
_room: Option<()>,
}
impl Channel {
fn new(id: u64, name: impl AsRef<str>, members: Vec<Channel>) -> Channel {
Channel {
name: name.as_ref().to_string(),
id,
sub_channels: members,
_room: None,
}
}
fn members(&self) -> &[Channel] {
&self.sub_channels
}
fn name(&self) -> &str {
&self.name
}
}
struct Channels {
channels: Vec<Channel>,
}
impl Channels {
fn channels(&self) -> Vec<Channel> {
self.channels.clone()
}
}
enum ChannelEvents {}
impl Entity for Channels {
type Event = ChannelEvents;
}
impl Channels {
fn new(_client: Arc<Client>, _cx: &mut AppContext) -> Self {
//TODO: Subscribe to channel updates from the server
Channels {
channels: vec![Channel::new(
0,
"Zed Industries",
vec![
Channel::new(1, "#general", Vec::new()),
Channel::new(2, "#admiral", Vec::new()),
Channel::new(3, "#livestreaming", vec![]),
Channel::new(4, "#crdb", Vec::new()),
Channel::new(5, "#crdb-1", Vec::new()),
Channel::new(6, "#crdb-2", Vec::new()),
Channel::new(7, "#crdb-3", vec![]),
Channel::new(8, "#crdb-4", Vec::new()),
Channel::new(9, "#crdb-1", Vec::new()),
Channel::new(10, "#crdb-1", Vec::new()),
Channel::new(11, "#crdb-1", Vec::new()),
Channel::new(12, "#crdb-1", vec![]),
Channel::new(13, "#crdb-1", Vec::new()),
Channel::new(14, "#crdb-1", Vec::new()),
Channel::new(15, "#crdb-1", Vec::new()),
Channel::new(16, "#crdb-1", Vec::new()),
Channel::new(17, "#crdb", vec![]),
],
),
Channel::new(
18,
"CRDB Consulting",
vec![
Channel::new(19, "#crdb 😭", Vec::new()),
Channel::new(20, "#crdb 😌", Vec::new()),
Channel::new(21, "#crdb 🦀", vec![]),
Channel::new(22, "#crdb 😤", Vec::new()),
Channel::new(23, "#crdb 😤", Vec::new()),
Channel::new(24, "#crdb 😤", Vec::new()),
Channel::new(25, "#crdb 😤", vec![]),
Channel::new(26, "#crdb 😤", Vec::new()),
],
)],
}
}
}

View File

@ -1,23 +1,19 @@
use std::sync::Arc;
use crate::{
channels_panel_settings::{ChannelsPanelDockPosition, ChannelsPanelSettings},
Channel, Channels,
};
use crate::channels_panel_settings::{ChannelsPanelDockPosition, ChannelsPanelSettings};
use anyhow::Result;
use collections::HashMap;
use context_menu::ContextMenu;
use db::kvp::KEY_VALUE_STORE;
use gpui::{
actions,
elements::{ChildView, Empty, Flex, Label, MouseEventHandler, ParentElement, Stack},
serde_json, AnyElement, AppContext, AsyncAppContext, Element, Entity, ModelHandle, Task, View,
ViewContext, ViewHandle, WeakViewHandle,
elements::{ChildView, Flex, Label, ParentElement, Stack},
serde_json, AppContext, AsyncAppContext, Element, Entity, Task, View, ViewContext,
ViewHandle, WeakViewHandle,
};
use project::Fs;
use serde_derive::{Deserialize, Serialize};
use settings::SettingsStore;
use theme::ChannelTreeStyle;
use util::{ResultExt, TryFutureExt};
use workspace::{
dock::{DockPosition, Panel},
@ -37,7 +33,6 @@ pub struct ChannelsPanel {
fs: Arc<dyn Fs>,
has_focus: bool,
pending_serialization: Task<Option<()>>,
channels: ModelHandle<Channels>,
context_menu: ViewHandle<ContextMenu>,
collapsed_channels: HashMap<u64, bool>,
}
@ -67,7 +62,6 @@ impl ChannelsPanel {
has_focus: false,
fs: workspace.app_state().fs.clone(),
pending_serialization: Task::ready(None),
channels: cx.global::<ModelHandle<Channels>>().clone(),
context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)),
collapsed_channels: HashMap::default(),
};
@ -138,101 +132,6 @@ impl ChannelsPanel {
.log_err(),
);
}
fn render_channel(
&mut self,
depth: usize,
channel: &Channel,
style: &ChannelTreeStyle,
root: bool,
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
let has_chilren = !channel.members().is_empty();
let sub_channel_details = has_chilren.then(|| {
let mut sub_channels = Flex::column();
let collapsed = self
.collapsed_channels
.get(&channel.id)
.copied()
.unwrap_or_default();
if !collapsed {
for sub_channel in channel.members() {
sub_channels = sub_channels.with_child(self.render_channel(
depth + 1,
sub_channel,
style,
false,
cx,
));
}
}
(sub_channels, collapsed)
});
let channel_id = channel.id;
enum ChannelCollapser {}
Flex::row()
.with_child(
Empty::new()
.constrained()
.with_width(depth as f32 * style.channel_indent),
)
.with_child(
Flex::column()
.with_child(
Flex::row()
.with_child(
sub_channel_details
.as_ref()
.map(|(_, expanded)| {
MouseEventHandler::<ChannelCollapser, _>::new(
channel.id as usize,
cx,
|state, _cx| {
let icon =
style.channel_icon.style_for(!*expanded, state);
theme::ui::icon(icon)
},
)
.on_click(
gpui::platform::MouseButton::Left,
move |_, v, cx| {
let entry = v
.collapsed_channels
.entry(channel_id)
.or_default();
*entry = !*entry;
v.serialize(cx);
cx.notify();
},
)
.into_any()
})
.unwrap_or_else(|| {
Empty::new()
.constrained()
.with_width(style.channel_icon.default_style().width())
.into_any()
}),
)
.with_child(
Label::new(
channel.name().to_string(),
if root {
style.root_name.clone()
} else {
style.channel_name.clone()
},
)
.into_any(),
),
)
.with_children(sub_channel_details.map(|(elements, _)| elements)),
)
.into_any()
}
}
impl View for ChannelsPanel {
@ -254,42 +153,11 @@ impl View for ChannelsPanel {
fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement<Self> {
let theme = theme::current(cx).clone();
let mut channels_column = Flex::column();
for channel in self.channels.read(cx).channels() {
channels_column = channels_column.with_child(self.render_channel(
0,
&channel,
&theme.channels_panel.channel_tree,
true,
cx,
));
}
let spacing = theme.channels_panel.spacing;
enum ChannelsPanelScrollTag {}
Stack::new()
.with_child(
// Full panel column
Flex::column()
.with_spacing(spacing)
.with_child(
// Channels section column
Flex::column()
.with_child(
Flex::row().with_child(
Label::new(
"Active Channels",
theme.editor.invalid_information_diagnostic.message.clone(),
)
.into_any(),
),
)
// Channels list column
.with_child(channels_column),
)
// TODO: Replace with spacing implementation
.with_child(Empty::new().constrained().with_height(spacing))
.with_child(
Flex::column().with_child(
Flex::row().with_child(

View File

@ -22,7 +22,6 @@ pub struct Flex<V: View> {
children: Vec<AnyElement<V>>,
scroll_state: Option<(ElementStateHandle<Rc<ScrollState>>, usize)>,
child_alignment: f32,
spacing: f32,
}
impl<V: View> Flex<V> {
@ -32,7 +31,6 @@ impl<V: View> Flex<V> {
children: Default::default(),
scroll_state: None,
child_alignment: -1.,
spacing: 0.,
}
}
@ -44,11 +42,6 @@ impl<V: View> Flex<V> {
Self::new(Axis::Vertical)
}
pub fn with_spacing(mut self, spacing: f32) -> Self {
self.spacing = spacing;
self
}
/// Render children centered relative to the cross-axis of the parent flex.
///
/// If this is a flex row, children will be centered vertically. If this is a

View File

@ -1068,61 +1068,9 @@ pub struct FlexStyle {
item_spacing: f32,
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ChannelProjectStyle {
// TODO: Implement Contained Flex
// ContainerStyle + Spacing between elements
// Negative spacing overlaps elements instead of spacing them out
pub container: Contained<FlexStyle>,
pub host: ImageStyle,
pub title: ContainedText,
pub members: Contained<FlexStyle>,
pub member: ImageStyle
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ChanneltemStyle {
pub icon: IconStyle,
pub title: TextStyle,
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ChannelListStyle {
pub section_title: ContainedText,
pub channel: Toggleable<Contained<ChanneltemStyle>>,
pub project: ChannelProjectStyle
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ContactItemStyle {
pub container: Contained<FlexStyle>,
pub avatar: IconStyle,
pub name: TextStyle,
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ContactsListStyle {
pub section_title: ContainedText,
pub contact: ContactItemStyle,
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ChannelTreeStyle {
pub channel_indent: f32,
pub channel_name: TextStyle,
pub root_name: TextStyle,
pub channel_icon: Toggleable<Interactive<IconStyle>>,
}
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct ChanelsPanelStyle {
pub channel_tree: ChannelTreeStyle,
pub spacing: f32,
// TODO: Uncomment:
// pub container: ContainerStyle,
// pub channel_list: ChannelListStyle,
// pub contacts_list: ContactsListStyle
pub contacts_header: TextStyle,
}
#[derive(Clone, Deserialize, Default, JsonSchema)]

View File

@ -1,68 +1,12 @@
// import { with_opacity } from "../theme/color"
import {
// Border,
// TextStyle,
// background,
// border,
foreground,
text,
} from "./components"
import { interactive, toggleable } from "../element"
// import merge from "ts-deepmerge"
import { useTheme } from "../theme"
export default function channels_panel(): any {
const theme = useTheme()
// const { is_light } = theme
return {
spacing: 10,
channel_tree: {
channel_indent: 10,
channel_name: text(theme.middle, "sans", "variant", { size: "md" }),
root_name: text(theme.middle, "sans", "variant", { size: "lg", weight: "bold" }),
channel_icon: (() => {
const base_icon = (asset: any, color: any) => {
return {
icon: {
color,
asset,
dimensions: {
width: 12,
height: 12,
}
},
container: {
corner_radius: 4,
padding: {
top: 4, bottom: 4, left: 4, right: 4
},
margin: {
right: 4,
},
}
}
}
return toggleable({
state: {
inactive: interactive({
state: {
default: base_icon("icons/chevron_right_8.svg", foreground(theme.middle, "variant")),
hovered: base_icon("icons/chevron_right_8.svg", foreground(theme.middle, "hovered")),
clicked: base_icon("icons/chevron_right_8.svg", foreground(theme.middle, "active")),
},
}),
active: interactive({
state: {
default: base_icon("icons/chevron_down_8.svg", foreground(theme.highest, "variant")),
hovered: base_icon("icons/chevron_down_8.svg", foreground(theme.highest, "hovered")),
clicked: base_icon("icons/chevron_down_8.svg", foreground(theme.highest, "active")),
},
}),
},
})
})(),
}
contacts_header: text(theme.middle, "sans", "variant", { size: "lg" }),
}
}