wip: refactor
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
76
crates/app/src/views/contacts/mod.rs
Normal file
76
crates/app/src/views/contacts/mod.rs
Normal 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")
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
mod chat;
|
||||
mod contacts;
|
||||
mod profile;
|
||||
mod settings;
|
||||
mod sidebar;
|
||||
mod welcome;
|
||||
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
76
crates/app/src/views/profile/mod.rs
Normal file
76
crates/app/src/views/profile/mod.rs
Normal 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")
|
||||
}
|
||||
}
|
||||
76
crates/app/src/views/settings/mod.rs
Normal file
76
crates/app/src/views/settings/mod.rs
Normal 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")
|
||||
}
|
||||
}
|
||||
@@ -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},
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "chat"
|
||||
name = "chat_state"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user