wip: refactor

This commit is contained in:
2025-02-03 08:23:03 +07:00
parent c982c802e2
commit d921720042
29 changed files with 534 additions and 265 deletions

View File

@@ -13,7 +13,7 @@ ui = { path = "../ui" }
common = { path = "../common" }
state = { path = "../state" }
app_state = { path = "../app_state" }
chat = { path = "../chat" }
chat_state = { path = "../chat_state" }
gpui.workspace = true
gpui_tokio.workspace = true

View File

@@ -1,7 +1,7 @@
use app_state::registry::AppRegistry;
use asset::Assets;
use async_utility::task::spawn;
use chat::registry::ChatRegistry;
use chat_state::registry::ChatRegistry;
use common::{
constants::{
ALL_MESSAGES_SUB_ID, APP_ID, APP_NAME, FAKE_SIG, KEYRING_SERVICE, NEW_MESSAGE_SUB_ID,

View File

@@ -1,11 +1,14 @@
use super::{chat::ChatPanel, onboarding::Onboarding, sidebar::Sidebar, welcome::WelcomePanel};
use super::{
chat, contacts, onboarding::Onboarding, profile, settings, sidebar::Sidebar,
welcome::WelcomePanel,
};
use app_state::registry::AppRegistry;
use chat::registry::ChatRegistry;
use chat_state::registry::ChatRegistry;
use common::profile::NostrProfile;
use gpui::{
actions, div, img, impl_internal_actions, px, AppContext, Axis, BorrowAppContext, Context,
Edges, Entity, InteractiveElement, IntoElement, ObjectFit, ParentElement, Render, Styled,
StyledImage, Window,
Entity, InteractiveElement, IntoElement, ObjectFit, ParentElement, Render, Styled, StyledImage,
Window,
};
use serde::Deserialize;
use state::get_client;
@@ -13,24 +16,33 @@ use std::sync::Arc;
use ui::{
button::{Button, ButtonVariants},
dock_area::{dock::DockPlacement, DockArea, DockItem},
notification::NotificationType,
popup_menu::PopupMenuExt,
ContextModal, Icon, IconName, Root, Sizable, TitleBar,
Icon, IconName, Root, Sizable, TitleBar,
};
#[derive(Clone, PartialEq, Eq, Deserialize)]
pub enum PanelKind {
Room(u64),
Profile,
Contacts,
Settings,
}
#[derive(Clone, PartialEq, Eq, Deserialize)]
pub struct AddPanel {
pub panel: PanelKind,
pub position: DockPlacement,
panel: PanelKind,
position: DockPlacement,
}
impl AddPanel {
pub fn new(panel: PanelKind, position: DockPlacement) -> Self {
Self { panel, position }
}
}
// Dock actions
impl_internal_actions!(dock, [AddPanel]);
// Account actions
actions!(account, [OpenProfile, OpenContacts, OpenSettings, Logout]);
@@ -53,9 +65,8 @@ impl AppView {
pub fn new(account: NostrProfile, window: &mut Window, cx: &mut Context<'_, Self>) -> AppView {
let dock = cx.new(|cx| DockArea::new(DOCK_AREA.id, Some(DOCK_AREA.version), window, cx));
let weak_dock = dock.downgrade();
let left = DockItem::panel(Arc::new(Sidebar::new(window, cx)));
let center = DockItem::split_with_sizes(
let left_panel = DockItem::panel(Arc::new(Sidebar::new(window, cx)));
let center_panel = DockItem::split_with_sizes(
Axis::Vertical,
vec![DockItem::tabs(
vec![Arc::new(WelcomePanel::new(window, cx))],
@@ -72,18 +83,8 @@ impl AppView {
_ = weak_dock.update(cx, |view, cx| {
view.set_version(DOCK_AREA.version, window, cx);
view.set_left_dock(left, Some(px(240.)), true, window, cx);
view.set_center(center, window, cx);
view.set_dock_collapsible(
Edges {
left: false,
..Default::default()
},
window,
cx,
);
// TODO: support right dock?
// TODO: support bottom dock?
view.set_left_dock(left_panel, Some(px(240.)), true, window, cx);
view.set_center(center_panel, window, cx);
});
AppView { account, dock }
@@ -102,11 +103,20 @@ impl AppView {
.object_fit(ObjectFit::Cover),
)
.popup_menu(move |this, _, _cx| {
this.menu("Profile", Box::new(OpenProfile))
.menu("Contacts", Box::new(OpenContacts))
.menu("Settings", Box::new(OpenSettings))
.separator()
.menu("Change account", Box::new(Logout))
this.menu(
"Profile",
Box::new(AddPanel::new(PanelKind::Profile, DockPlacement::Right)),
)
.menu(
"Contacts",
Box::new(AddPanel::new(PanelKind::Contacts, DockPlacement::Right)),
)
.menu(
"Settings",
Box::new(AddPanel::new(PanelKind::Settings, DockPlacement::Center)),
)
.separator()
.menu("Change account", Box::new(Logout))
})
}
@@ -115,51 +125,37 @@ impl AppView {
PanelKind::Room(id) => {
if let Some(weak_room) = cx.global::<ChatRegistry>().get_room(id, cx) {
if let Some(room) = weak_room.upgrade() {
let panel = Arc::new(ChatPanel::new(room, window, cx));
let panel = Arc::new(chat::init(room, window, cx));
self.dock.update(cx, |dock_area, cx| {
dock_area.add_panel(panel, action.position, window, cx);
});
} else {
window.push_notification(
(
NotificationType::Error,
"System error. Cannot open this chat room.",
),
cx,
);
}
}
}
PanelKind::Profile => {
let panel = Arc::new(profile::init(window, cx));
self.dock.update(cx, |dock_area, cx| {
dock_area.add_panel(panel, action.position, window, cx);
});
}
PanelKind::Contacts => {
let panel = Arc::new(contacts::init(window, cx));
self.dock.update(cx, |dock_area, cx| {
dock_area.add_panel(panel, action.position, window, cx);
});
}
PanelKind::Settings => {
let panel = Arc::new(settings::init(window, cx));
self.dock.update(cx, |dock_area, cx| {
dock_area.add_panel(panel, action.position, window, cx);
});
}
};
}
fn on_profile_action(
&mut self,
_action: &OpenProfile,
_window: &mut Window,
_cx: &mut Context<Self>,
) {
// TODO
}
fn on_contacts_action(
&mut self,
_action: &OpenContacts,
_window: &mut Window,
_cx: &mut Context<Self>,
) {
// TODO
}
fn on_settings_action(
&mut self,
_action: &OpenSettings,
_window: &mut Window,
_cx: &mut Context<Self>,
) {
// TODO
}
fn on_logout_action(&mut self, _action: &Logout, window: &mut Window, cx: &mut Context<Self>) {
cx.update_global::<AppRegistry, _>(|this, cx| {
cx.background_executor()
@@ -210,8 +206,5 @@ impl Render for AppView {
.children(modal_layer)
.on_action(cx.listener(Self::on_panel_action))
.on_action(cx.listener(Self::on_logout_action))
.on_action(cx.listener(Self::on_profile_action))
.on_action(cx.listener(Self::on_contacts_action))
.on_action(cx.listener(Self::on_settings_action))
}
}

View File

@@ -1,5 +1,5 @@
use async_utility::task::spawn;
use chat::room::Room;
use chat_state::room::Room;
use common::{
constants::IMAGE_SERVICE,
utils::{compare, message_time, nip96_upload},
@@ -28,15 +28,19 @@ use ui::{
mod message;
pub fn init(room: Entity<Room>, window: &mut Window, cx: &mut App) -> Entity<Chat> {
Chat::new(room, window, cx)
}
#[derive(Clone)]
pub struct State {
count: usize,
items: Vec<Message>,
}
pub struct ChatPanel {
pub struct Chat {
// Panel
closeable: bool,
closable: bool,
zoomable: bool,
focus_handle: FocusHandle,
// Chat Room
@@ -52,7 +56,7 @@ pub struct ChatPanel {
is_uploading: bool,
}
impl ChatPanel {
impl Chat {
pub fn new(model: Entity<Room>, window: &mut Window, cx: &mut App) -> Entity<Self> {
let room = model.read(cx);
let id = room.id.to_string().into();
@@ -84,7 +88,7 @@ impl ChatPanel {
cx.subscribe_in(
&input,
window,
move |this: &mut ChatPanel, view, input_event, window, cx| {
move |this: &mut Chat, view, input_event, window, cx| {
if let InputEvent::PressEnter = input_event {
this.send_message(view.downgrade(), window, cx);
}
@@ -118,7 +122,7 @@ impl ChatPanel {
let attaches = cx.new(|_| None);
Self {
closeable: true,
closable: true,
zoomable: true,
focus_handle: cx.focus_handle(),
room: model,
@@ -425,7 +429,7 @@ impl ChatPanel {
}
}
impl Panel for ChatPanel {
impl Panel for Chat {
fn panel_id(&self) -> SharedString {
self.id.clone()
}
@@ -445,8 +449,8 @@ impl Panel for ChatPanel {
self.name.clone().into_any_element()
}
fn closeable(&self, _cx: &App) -> bool {
self.closeable
fn closable(&self, _cx: &App) -> bool {
self.closable
}
fn zoomable(&self, _cx: &App) -> bool {
@@ -462,15 +466,15 @@ impl Panel for ChatPanel {
}
}
impl EventEmitter<PanelEvent> for ChatPanel {}
impl EventEmitter<PanelEvent> for Chat {}
impl Focusable for ChatPanel {
impl Focusable for Chat {
fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for ChatPanel {
impl Render for Chat {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.size_full()

View File

@@ -0,0 +1,76 @@
use gpui::{
div, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Window,
};
use ui::{
button::Button,
dock_area::panel::{Panel, PanelEvent},
popup_menu::PopupMenu,
};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Contacts> {
Contacts::new(window, cx)
}
pub struct Contacts {
name: SharedString,
closable: bool,
zoomable: bool,
focus_handle: FocusHandle,
}
impl Contacts {
pub fn new(_window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self {
name: "Contacts".into(),
closable: true,
zoomable: true,
focus_handle: cx.focus_handle(),
})
}
}
impl Panel for Contacts {
fn panel_id(&self) -> SharedString {
"ContactPanel".into()
}
fn title(&self, _cx: &App) -> AnyElement {
self.name.clone().into_any_element()
}
fn closable(&self, _cx: &App) -> bool {
self.closable
}
fn zoomable(&self, _cx: &App) -> bool {
self.zoomable
}
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
menu.track_focus(&self.focus_handle)
}
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
vec![]
}
}
impl EventEmitter<PanelEvent> for Contacts {}
impl Focusable for Contacts {
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for Contacts {
fn render(&mut self, _window: &mut gpui::Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.flex()
.items_center()
.justify_center()
.child("Contacts")
}
}

View File

@@ -1,4 +1,7 @@
mod chat;
mod contacts;
mod profile;
mod settings;
mod sidebar;
mod welcome;

View File

@@ -1,8 +1,17 @@
use common::constants::KEYRING_SERVICE;
use gpui::{div, AppContext, Context, Entity, IntoElement, ParentElement, Render, Styled, Window};
use app_state::registry::AppRegistry;
use common::{constants::KEYRING_SERVICE, profile::NostrProfile};
use gpui::{
div, AppContext, BorrowAppContext, Context, Entity, IntoElement, ParentElement, Render, Styled,
Window,
};
use nostr_sdk::prelude::*;
use state::get_client;
use ui::input::{InputEvent, TextInput};
use ui::{
input::{InputEvent, TextInput},
Root,
};
use super::app::AppView;
pub struct Onboarding {
input: Entity<TextInput>,
@@ -33,47 +42,60 @@ impl Onboarding {
fn save_keys(
content: &str,
_window: &mut Window,
window: &mut Window,
cx: &mut Context<Self>,
) -> anyhow::Result<(), anyhow::Error> {
let keys = Keys::parse(content)?;
let public_key = keys.public_key();
let bech32 = public_key.to_bech32()?;
let secret = keys.secret_key().to_secret_hex();
let window_handle = window.window_handle();
let task = cx.write_credentials(KEYRING_SERVICE, &bech32, secret.as_bytes());
let async_cx = cx.to_async();
cx.spawn(|_, mut cx| async move {
let client = get_client();
cx.foreground_executor()
.spawn({
let client = get_client();
let task = cx.write_credentials(KEYRING_SERVICE, &bech32, secret.as_bytes());
if task.await.is_ok() {
let (tx, mut rx) = tokio::sync::mpsc::channel::<NostrProfile>(1);
async move {
if task.await.is_ok() {
let query: anyhow::Result<Metadata, anyhow::Error> = async_cx
.background_executor()
.spawn(async move {
// Update signer
_ = client.set_signer(keys).await;
cx.background_executor()
.spawn(async move {
// Update signer
_ = client.set_signer(keys).await;
// Get metadata
if let Some(metadata) =
client.database().metadata(public_key).await?
{
Ok(metadata)
} else {
Ok(Metadata::new())
}
})
.await;
// Get metadata
let metadata = if let Ok(Some(metadata)) =
client.database().metadata(public_key).await
{
metadata
} else {
Metadata::new()
};
if let Ok(_metadata) = query {
//
}
}
_ = tx.send(NostrProfile::new(public_key, metadata)).await;
})
.await;
while let Some(profile) = rx.recv().await {
cx.update_window(window_handle, |_, window, cx| {
cx.update_global::<AppRegistry, _>(|this, cx| {
this.set_user(Some(profile.clone()));
if let Some(root) = this.root() {
cx.update_entity(&root, |this: &mut Root, cx| {
this.set_view(
cx.new(|cx| AppView::new(profile, window, cx)).into(),
cx,
);
});
}
});
})
.unwrap();
}
})
.detach();
}
})
.detach();
Ok(())
}

View File

@@ -0,0 +1,76 @@
use gpui::{
div, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Window,
};
use ui::{
button::Button,
dock_area::panel::{Panel, PanelEvent},
popup_menu::PopupMenu,
};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Profile> {
Profile::new(window, cx)
}
pub struct Profile {
name: SharedString,
closable: bool,
zoomable: bool,
focus_handle: FocusHandle,
}
impl Profile {
pub fn new(_window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self {
name: "Profile".into(),
closable: true,
zoomable: true,
focus_handle: cx.focus_handle(),
})
}
}
impl Panel for Profile {
fn panel_id(&self) -> SharedString {
"ProfilePanel".into()
}
fn title(&self, _cx: &App) -> AnyElement {
self.name.clone().into_any_element()
}
fn closable(&self, _cx: &App) -> bool {
self.closable
}
fn zoomable(&self, _cx: &App) -> bool {
self.zoomable
}
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
menu.track_focus(&self.focus_handle)
}
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
vec![]
}
}
impl EventEmitter<PanelEvent> for Profile {}
impl Focusable for Profile {
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for Profile {
fn render(&mut self, _window: &mut gpui::Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.flex()
.items_center()
.justify_center()
.child("Profile")
}
}

View File

@@ -0,0 +1,76 @@
use gpui::{
div, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Window,
};
use ui::{
button::Button,
dock_area::panel::{Panel, PanelEvent},
popup_menu::PopupMenu,
};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Settings> {
Settings::new(window, cx)
}
pub struct Settings {
name: SharedString,
closable: bool,
zoomable: bool,
focus_handle: FocusHandle,
}
impl Settings {
pub fn new(_window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self {
name: "Settings".into(),
closable: true,
zoomable: true,
focus_handle: cx.focus_handle(),
})
}
}
impl Panel for Settings {
fn panel_id(&self) -> SharedString {
"SettingsPanel".into()
}
fn title(&self, _cx: &App) -> AnyElement {
self.name.clone().into_any_element()
}
fn closable(&self, _cx: &App) -> bool {
self.closable
}
fn zoomable(&self, _cx: &App) -> bool {
self.zoomable
}
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
menu.track_focus(&self.focus_handle)
}
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
vec![]
}
}
impl EventEmitter<PanelEvent> for Settings {}
impl Focusable for Settings {
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for Settings {
fn render(&mut self, _window: &mut gpui::Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.flex()
.items_center()
.justify_center()
.child("Settings")
}
}

View File

@@ -1,5 +1,5 @@
use app_state::registry::AppRegistry;
use chat::room::Room;
use chat_state::room::Room;
use common::{
profile::NostrProfile,
utils::{random_name, room_hash},

View File

@@ -1,5 +1,5 @@
use crate::views::app::{AddPanel, PanelKind};
use chat::registry::ChatRegistry;
use chat_state::registry::ChatRegistry;
use common::utils::message_ago;
use gpui::{
div, img, percentage, prelude::FluentBuilder, px, Context, InteractiveElement, IntoElement,
@@ -104,10 +104,7 @@ impl Inbox {
fn action(&self, id: u64, window: &mut Window, cx: &mut Context<Self>) {
window.dispatch_action(
Box::new(AddPanel {
panel: PanelKind::Room(id),
position: DockPlacement::Center,
}),
Box::new(AddPanel::new(PanelKind::Room(id), DockPlacement::Center)),
cx,
);
}

View File

@@ -1,5 +1,5 @@
use crate::views::sidebar::inbox::Inbox;
use chat::registry::ChatRegistry;
use chat_state::registry::ChatRegistry;
use compose::Compose;
use gpui::{
div, px, AnyElement, App, AppContext, BorrowAppContext, Context, Entity, EntityId,
@@ -21,7 +21,7 @@ mod inbox;
pub struct Sidebar {
// Panel
name: SharedString,
closeable: bool,
closable: bool,
zoomable: bool,
focus_handle: FocusHandle,
// Dock
@@ -39,7 +39,7 @@ impl Sidebar {
Self {
name: "Sidebar".into(),
closeable: true,
closable: true,
zoomable: true,
focus_handle: cx.focus_handle(),
view_id: cx.entity().entity_id(),
@@ -93,8 +93,8 @@ impl Panel for Sidebar {
self.name.clone().into_any_element()
}
fn closeable(&self, _cx: &App) -> bool {
self.closeable
fn closable(&self, _cx: &App) -> bool {
self.closable
}
fn zoomable(&self, _cx: &App) -> bool {

View File

@@ -12,7 +12,7 @@ use ui::{
pub struct WelcomePanel {
name: SharedString,
closeable: bool,
closable: bool,
zoomable: bool,
focus_handle: FocusHandle,
}
@@ -25,7 +25,7 @@ impl WelcomePanel {
fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self {
Self {
name: "Welcome".into(),
closeable: true,
closable: true,
zoomable: true,
focus_handle: cx.focus_handle(),
}
@@ -41,8 +41,8 @@ impl Panel for WelcomePanel {
self.name.clone().into_any_element()
}
fn closeable(&self, _cx: &App) -> bool {
self.closeable
fn closable(&self, _cx: &App) -> bool {
self.closable
}
fn zoomable(&self, _cx: &App) -> bool {

View File

@@ -1,5 +1,5 @@
[package]
name = "chat"
name = "chat_state"
version = "0.1.0"
edition = "2021"
publish = false

View File

@@ -244,7 +244,8 @@ impl Dock {
.right(px(1.))
.h_full()
.w(HANDLE_SIZE)
.py_10()
.pt_12()
.pb_4()
})
.when(self.placement.is_right(), |this| {
this.cursor_col_resize()
@@ -252,7 +253,8 @@ impl Dock {
.left(px(1.))
.h_full()
.w(HANDLE_SIZE)
.py_10()
.pt_12()
.pb_4()
})
.when(self.placement.is_bottom(), |this| {
this.cursor_row_resize()

View File

@@ -5,7 +5,7 @@ use crate::dock_area::{
tab_panel::TabPanel,
};
use gpui::{
actions, canvas, div, prelude::FluentBuilder, AnyElement, AnyView, App, AppContext, Axis,
actions, canvas, div, prelude::FluentBuilder, px, AnyElement, AnyView, App, AppContext, Axis,
Bounds, Context, Edges, Entity, EntityId, EventEmitter, InteractiveElement as _, IntoElement,
ParentElement as _, Pixels, Render, SharedString, Styled, Subscription, WeakEntity, Window,
};
@@ -543,7 +543,7 @@ impl DockArea {
} else {
self.set_left_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
None,
Some(px(320.)),
true,
window,
cx,
@@ -569,7 +569,7 @@ impl DockArea {
} else {
self.set_right_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
None,
Some(px(320.)),
true,
window,
cx,

View File

@@ -42,7 +42,7 @@ pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
}
/// Whether the panel can be closed, default is `true`.
fn closeable(&self, _cx: &App) -> bool {
fn closable(&self, _cx: &App) -> bool {
true
}
@@ -66,7 +66,7 @@ pub trait PanelView: 'static + Send + Sync {
fn panel_id(&self, cx: &App) -> SharedString;
fn panel_facepile(&self, cx: &App) -> Option<Vec<String>>;
fn title(&self, cx: &App) -> AnyElement;
fn closeable(&self, cx: &App) -> bool;
fn closable(&self, cx: &App) -> bool;
fn zoomable(&self, cx: &App) -> bool;
fn popup_menu(&self, menu: PopupMenu, cx: &App) -> PopupMenu;
fn toolbar_buttons(&self, window: &Window, cx: &App) -> Vec<Button>;
@@ -87,8 +87,8 @@ impl<T: Panel> PanelView for Entity<T> {
self.read(cx).title(cx)
}
fn closeable(&self, cx: &App) -> bool {
self.read(cx).closeable(cx)
fn closable(&self, cx: &App) -> bool {
self.read(cx).closable(cx)
}
fn zoomable(&self, cx: &App) -> bool {

View File

@@ -89,14 +89,14 @@ impl Panel for TabPanel {
.unwrap_or("Empty Tab".into_any_element())
}
fn closeable(&self, cx: &App) -> bool {
fn closable(&self, cx: &App) -> bool {
if !self.closeable {
return false;
}
self.active_panel()
.map(|panel| panel.closeable(cx))
.unwrap_or(false)
.map(|panel| panel.closable(cx))
.unwrap_or(true)
}
fn zoomable(&self, cx: &App) -> bool {
@@ -409,6 +409,7 @@ impl TabPanel {
}
let dock_area = self.dock_area.upgrade()?.read(cx);
if !dock_area.is_dock_collapsible(placement, cx) {
return None;
}
@@ -651,6 +652,7 @@ impl TabPanel {
.h_full()
.flex_grow()
.min_w_16()
.rounded(px(cx.theme().radius))
.when(state.droppable, |this| {
this.drag_over::<DragPanel>(|this, _, _, cx| {
this.bg(cx.theme().base.step(cx, ColorScaleStep::TWO))
@@ -1013,7 +1015,7 @@ impl Render for TabPanel {
let focus_handle = self.focus_handle(cx);
let mut state = TabState {
closeable: self.closeable(cx),
closeable: self.closable(cx),
draggable: self.draggable(cx),
droppable: self.droppable(cx),
zoomable: self.zoomable(cx),

View File

@@ -51,7 +51,8 @@ impl RenderOnce for ResizeHandle {
.left(px(-1.))
.w(HANDLE_SIZE)
.h_full()
.py_10()
.pt_12()
.pb_4()
})
.when(self.axis.is_vertical(), |this| {
this.cursor_row_resize()
@@ -59,7 +60,7 @@ impl RenderOnce for ResizeHandle {
.left_0()
.w_full()
.h(HANDLE_SIZE)
.px_10()
.px_6()
})
.child(
div()

View File

@@ -1,7 +1,7 @@
use crate::theme::{scale::ColorScaleStep, ActiveTheme};
use gpui::{
div, px, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString,
Styled, Window,
div, px, relative, App, AppContext, Context, Entity, IntoElement, ParentElement, Render,
SharedString, Styled, Window,
};
pub struct Tooltip {
@@ -21,13 +21,15 @@ impl Render for Tooltip {
div()
.font_family(".SystemUIFont")
.m_3()
.bg(cx.theme().base.step(cx, ColorScaleStep::TWELVE))
.text_color(cx.theme().base.step(cx, ColorScaleStep::ONE))
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::FIVE))
.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))
.shadow_md()
.rounded(px(6.))
.py_0p5()
.py_1()
.px_2()
.text_sm()
.text_xs()
.line_height(relative(1.))
.child(self.text.clone()),
)
}