chore: Upgrade to GPUI3 (#6)
* wip: gpui3 * wip: gpui3 * chore: fix clippy
This commit is contained in:
@@ -4,8 +4,8 @@ use common::constants::{
|
||||
NEW_MESSAGE_SUB_ID,
|
||||
};
|
||||
use gpui::{
|
||||
actions, point, px, size, App, AppContext, Bounds, SharedString, TitlebarOptions,
|
||||
VisualContext, WindowBounds, WindowKind, WindowOptions,
|
||||
actions, point, px, size, App, AppContext, Application, Bounds, SharedString, TitlebarOptions,
|
||||
WindowBounds, WindowKind, WindowOptions,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
use gpui::{WindowBackgroundAppearance, WindowDecorations};
|
||||
@@ -67,7 +67,7 @@ async fn main() {
|
||||
// Merge all requests into single subscription
|
||||
tokio::spawn(async move { handle_metadata(client, mta_rx).await });
|
||||
|
||||
App::new()
|
||||
Application::new()
|
||||
.with_assets(Assets)
|
||||
.with_http_client(Arc::new(reqwest_client::ReqwestClient::new()))
|
||||
.run(move |cx| {
|
||||
@@ -177,12 +177,11 @@ async fn main() {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
cx.open_window(opts, |cx| {
|
||||
cx.set_window_title(APP_NAME);
|
||||
cx.set_app_id(APP_ID);
|
||||
cx.open_window(opts, |window, cx| {
|
||||
window.set_window_title(APP_NAME);
|
||||
window.set_app_id(APP_ID);
|
||||
cx.activate(true);
|
||||
|
||||
cx.new_view(|cx| Root::new(cx.new_view(AppView::new).into(), cx))
|
||||
cx.new(|cx| Root::new(cx.new(|cx| AppView::new(window, cx)).into(), window, cx))
|
||||
})
|
||||
.expect("System error");
|
||||
});
|
||||
@@ -301,6 +300,6 @@ async fn handle_metadata(client: &'static Client, mut mta_rx: mpsc::Receiver<Pub
|
||||
});
|
||||
}
|
||||
|
||||
fn quit(_: &Quit, cx: &mut AppContext) {
|
||||
fn quit(_: &Quit, cx: &mut App) {
|
||||
cx.quit();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::{chat::ChatPanel, onboarding::Onboarding, sidebar::Sidebar, welcome::WelcomePanel};
|
||||
use gpui::{
|
||||
actions, div, img, impl_internal_actions, px, svg, Axis, BorrowAppContext, Edges,
|
||||
InteractiveElement, IntoElement, ObjectFit, ParentElement, Render, Styled, StyledImage, View,
|
||||
ViewContext, VisualContext, WeakView, WindowContext,
|
||||
actions, div, img, impl_internal_actions, px, svg, App, AppContext, Axis, BorrowAppContext,
|
||||
Context, Edges, Entity, InteractiveElement, IntoElement, ObjectFit, ParentElement, Render,
|
||||
Styled, StyledImage, WeakEntity, Window,
|
||||
};
|
||||
use registry::{app::AppRegistry, chat::ChatRegistry, contact::Contact};
|
||||
use serde::Deserialize;
|
||||
@@ -45,22 +45,22 @@ pub const DOCK_AREA: DockAreaTab = DockAreaTab {
|
||||
};
|
||||
|
||||
pub struct AppView {
|
||||
onboarding: View<Onboarding>,
|
||||
dock: View<DockArea>,
|
||||
onboarding: Entity<Onboarding>,
|
||||
dock: Entity<DockArea>,
|
||||
}
|
||||
|
||||
impl AppView {
|
||||
pub fn new(cx: &mut ViewContext<'_, Self>) -> AppView {
|
||||
let onboarding = cx.new_view(Onboarding::new);
|
||||
let dock = cx.new_view(|cx| DockArea::new(DOCK_AREA.id, Some(DOCK_AREA.version), cx));
|
||||
pub fn new(window: &mut Window, cx: &mut Context<'_, Self>) -> AppView {
|
||||
let onboarding = cx.new(|cx| Onboarding::new(window, cx));
|
||||
let dock = cx.new(|cx| DockArea::new(DOCK_AREA.id, Some(DOCK_AREA.version), window, cx));
|
||||
|
||||
// Get current user from app state
|
||||
let weak_user = cx.global::<AppRegistry>().user();
|
||||
|
||||
if let Some(user) = weak_user.upgrade() {
|
||||
cx.observe(&user, move |view, this, cx| {
|
||||
cx.observe_in(&user, window, |view, this, window, cx| {
|
||||
if this.read(cx).is_some() {
|
||||
Self::render_dock(view.dock.downgrade(), cx);
|
||||
Self::render_dock(view.dock.downgrade(), window, cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
@@ -69,30 +69,33 @@ impl AppView {
|
||||
AppView { onboarding, dock }
|
||||
}
|
||||
|
||||
fn render_dock(dock_area: WeakView<DockArea>, cx: &mut WindowContext) {
|
||||
let left = DockItem::panel(Arc::new(Sidebar::new(cx)));
|
||||
fn render_dock(dock_area: WeakEntity<DockArea>, window: &mut Window, cx: &mut App) {
|
||||
let left = DockItem::panel(Arc::new(Sidebar::new(window, cx)));
|
||||
let center = DockItem::split_with_sizes(
|
||||
Axis::Vertical,
|
||||
vec![DockItem::tabs(
|
||||
vec![Arc::new(WelcomePanel::new(cx))],
|
||||
vec![Arc::new(WelcomePanel::new(window, cx))],
|
||||
None,
|
||||
&dock_area,
|
||||
window,
|
||||
cx,
|
||||
)],
|
||||
vec![None],
|
||||
&dock_area,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
_ = dock_area.update(cx, |view, cx| {
|
||||
view.set_version(DOCK_AREA.version, cx);
|
||||
view.set_left_dock(left, Some(px(240.)), true, cx);
|
||||
view.set_center(center, 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?
|
||||
@@ -112,7 +115,7 @@ impl AppView {
|
||||
.rounded_full()
|
||||
.object_fit(ObjectFit::Cover),
|
||||
)
|
||||
.popup_menu(move |this, _cx| {
|
||||
.popup_menu(move |this, _, _cx| {
|
||||
this.menu("Profile", Box::new(OpenProfile))
|
||||
.menu("Contacts", Box::new(OpenContacts))
|
||||
.menu("Settings", Box::new(OpenSettings))
|
||||
@@ -121,40 +124,58 @@ impl AppView {
|
||||
})
|
||||
}
|
||||
|
||||
fn on_panel_action(&mut self, action: &AddPanel, cx: &mut ViewContext<Self>) {
|
||||
fn on_panel_action(&mut self, action: &AddPanel, window: &mut Window, cx: &mut Context<Self>) {
|
||||
match &action.panel {
|
||||
PanelKind::Room(id) => {
|
||||
if let Some(weak_room) = cx.global::<ChatRegistry>().room(id, cx) {
|
||||
if let Some(room) = weak_room.upgrade() {
|
||||
let panel = Arc::new(ChatPanel::new(room, cx));
|
||||
let panel = Arc::new(ChatPanel::new(room, window, cx));
|
||||
|
||||
self.dock.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel(panel, action.position, cx);
|
||||
dock_area.add_panel(panel, action.position, window, cx);
|
||||
});
|
||||
} else {
|
||||
cx.push_notification((
|
||||
NotificationType::Error,
|
||||
"System error. Cannot open this chat room.",
|
||||
));
|
||||
window.push_notification(
|
||||
(
|
||||
NotificationType::Error,
|
||||
"System error. Cannot open this chat room.",
|
||||
),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn on_profile_action(&mut self, _action: &OpenProfile, cx: &mut ViewContext<Self>) {
|
||||
fn on_profile_action(
|
||||
&mut self,
|
||||
_action: &OpenProfile,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn on_contacts_action(&mut self, _action: &OpenContacts, cx: &mut ViewContext<Self>) {
|
||||
fn on_contacts_action(
|
||||
&mut self,
|
||||
_action: &OpenContacts,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn on_settings_action(&mut self, _action: &OpenSettings, cx: &mut ViewContext<Self>) {
|
||||
fn on_settings_action(
|
||||
&mut self,
|
||||
_action: &OpenSettings,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn on_logout_action(&mut self, _action: &Logout, cx: &mut ViewContext<Self>) {
|
||||
fn on_logout_action(&mut self, _action: &Logout, window: &mut Window, cx: &mut Context<Self>) {
|
||||
cx.update_global::<AppRegistry, _>(|this, cx| {
|
||||
this.logout(cx);
|
||||
// Reset nostr client
|
||||
@@ -166,9 +187,9 @@ impl AppView {
|
||||
}
|
||||
|
||||
impl Render for AppView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let modal_layer = Root::render_modal_layer(cx);
|
||||
let notification_layer = Root::render_notification_layer(cx);
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let modal_layer = Root::render_modal_layer(window, cx);
|
||||
let notification_layer = Root::render_notification_layer(window, cx);
|
||||
let state = cx.global::<AppRegistry>();
|
||||
|
||||
div()
|
||||
@@ -189,7 +210,7 @@ impl Render for AppView {
|
||||
.text_color(cx.theme().base.step(cx, ColorScaleStep::THREE)),
|
||||
),
|
||||
)
|
||||
} else if let Some(contact) = state.current_user(cx) {
|
||||
} else if let Some(contact) = state.current_user(window, cx) {
|
||||
this.child(
|
||||
TitleBar::new()
|
||||
// Left side
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use gpui::{
|
||||
div, img, px, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString, Styled,
|
||||
WindowContext,
|
||||
div, img, px, App, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString,
|
||||
Styled, Window,
|
||||
};
|
||||
use registry::contact::Contact;
|
||||
use ui::{
|
||||
@@ -36,7 +36,7 @@ impl Message {
|
||||
}
|
||||
|
||||
impl RenderOnce for Message {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
div()
|
||||
.group(&self.ago)
|
||||
.relative()
|
||||
|
||||
@@ -4,10 +4,10 @@ use common::{
|
||||
utils::{compare, message_time, nip96_upload},
|
||||
};
|
||||
use gpui::{
|
||||
div, img, list, px, white, AnyElement, AppContext, Context, EventEmitter, Flatten, FocusHandle,
|
||||
FocusableView, InteractiveElement, IntoElement, ListAlignment, ListState, Model, ObjectFit,
|
||||
div, img, list, px, white, AnyElement, App, AppContext, Context, Entity, EventEmitter, Flatten,
|
||||
FocusHandle, Focusable, InteractiveElement, IntoElement, ListAlignment, ListState, ObjectFit,
|
||||
ParentElement, PathPromptOptions, Pixels, Render, SharedString, StatefulInteractiveElement,
|
||||
Styled, StyledImage, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext,
|
||||
Styled, StyledImage, WeakEntity, Window,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use message::Message;
|
||||
@@ -18,10 +18,7 @@ use state::get_client;
|
||||
use tokio::sync::oneshot;
|
||||
use ui::{
|
||||
button::{Button, ButtonRounded, ButtonVariants},
|
||||
dock_area::{
|
||||
panel::{Panel, PanelEvent},
|
||||
state::PanelState,
|
||||
},
|
||||
dock_area::panel::{Panel, PanelEvent},
|
||||
input::{InputEvent, TextInput},
|
||||
popup_menu::PopupMenu,
|
||||
prelude::FluentBuilder,
|
||||
@@ -45,48 +42,51 @@ pub struct ChatPanel {
|
||||
// Chat Room
|
||||
id: SharedString,
|
||||
name: SharedString,
|
||||
room: Model<Room>,
|
||||
state: Model<State>,
|
||||
room: Entity<Room>,
|
||||
state: Entity<State>,
|
||||
list: ListState,
|
||||
// New Message
|
||||
input: View<TextInput>,
|
||||
input: Entity<TextInput>,
|
||||
// Media
|
||||
attaches: Model<Option<Vec<Url>>>,
|
||||
attaches: Entity<Option<Vec<Url>>>,
|
||||
is_uploading: bool,
|
||||
}
|
||||
|
||||
impl ChatPanel {
|
||||
pub fn new(model: Model<Room>, cx: &mut WindowContext) -> View<Self> {
|
||||
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();
|
||||
let name = room.title.clone().unwrap_or("Untitled".into());
|
||||
|
||||
cx.observe_new_views::<Self>(|this, cx| {
|
||||
this.load_messages(cx);
|
||||
})
|
||||
.detach();
|
||||
cx.new(|cx| {
|
||||
cx.observe_new::<Self>(|this, window, cx| {
|
||||
if let Some(window) = window {
|
||||
this.load_messages(window, cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.new_view(|cx| {
|
||||
// Form
|
||||
let input = cx.new_view(|cx| {
|
||||
TextInput::new(cx)
|
||||
let input = cx.new(|cx| {
|
||||
TextInput::new(window, cx)
|
||||
.appearance(false)
|
||||
.text_size(ui::Size::Small)
|
||||
.placeholder("Message...")
|
||||
});
|
||||
|
||||
// List
|
||||
let state = cx.new_model(|_| State {
|
||||
let state = cx.new(|_| State {
|
||||
count: 0,
|
||||
items: vec![],
|
||||
});
|
||||
|
||||
// Send message when user presses enter
|
||||
cx.subscribe(
|
||||
cx.subscribe_in(
|
||||
&input,
|
||||
move |this: &mut ChatPanel, view, input_event, cx| {
|
||||
window,
|
||||
move |this: &mut ChatPanel, view, input_event, window, cx| {
|
||||
if let InputEvent::PressEnter = input_event {
|
||||
this.send_message(view.downgrade(), cx);
|
||||
this.send_message(view.downgrade(), window, cx);
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -100,7 +100,7 @@ impl ChatPanel {
|
||||
items.len(),
|
||||
ListAlignment::Bottom,
|
||||
Pixels(256.),
|
||||
move |idx, _cx| {
|
||||
move |idx, _window, _cx| {
|
||||
let item = items.get(idx).unwrap().clone();
|
||||
div().child(item).into_any_element()
|
||||
},
|
||||
@@ -110,19 +110,19 @@ impl ChatPanel {
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.observe(&model, |this, model, cx| {
|
||||
this.load_new_messages(model.downgrade(), cx);
|
||||
cx.observe_in(&model, window, |this, model, window, cx| {
|
||||
this.load_new_messages(model.downgrade(), window, cx);
|
||||
})
|
||||
.detach();
|
||||
|
||||
let attaches = cx.new_model(|_| None);
|
||||
let attaches = cx.new(|_| None);
|
||||
|
||||
Self {
|
||||
closeable: true,
|
||||
zoomable: true,
|
||||
focus_handle: cx.focus_handle(),
|
||||
room: model,
|
||||
list: ListState::new(0, ListAlignment::Bottom, Pixels(256.), move |_, _| {
|
||||
list: ListState::new(0, ListAlignment::Bottom, Pixels(256.), move |_, _, _| {
|
||||
div().into_any_element()
|
||||
}),
|
||||
is_uploading: false,
|
||||
@@ -135,7 +135,7 @@ impl ChatPanel {
|
||||
})
|
||||
}
|
||||
|
||||
fn load_messages(&self, cx: &mut ViewContext<Self>) {
|
||||
fn load_messages(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let room = self.room.read(cx);
|
||||
let members = room.members.clone();
|
||||
let owner = room.owner.clone();
|
||||
@@ -206,7 +206,7 @@ impl ChatPanel {
|
||||
|
||||
let total = items.len();
|
||||
|
||||
_ = async_cx.update_model(&async_state, |a, b| {
|
||||
_ = async_cx.update_entity(&async_state, |a, b| {
|
||||
a.items = items;
|
||||
a.count = total;
|
||||
b.notify();
|
||||
@@ -216,7 +216,12 @@ impl ChatPanel {
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn load_new_messages(&self, model: WeakModel<Room>, cx: &mut ViewContext<Self>) {
|
||||
fn load_new_messages(
|
||||
&self,
|
||||
model: WeakEntity<Room>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some(model) = model.upgrade() {
|
||||
let room = model.read(cx);
|
||||
let items: Vec<Message> = room
|
||||
@@ -233,7 +238,7 @@ impl ChatPanel {
|
||||
})
|
||||
.collect();
|
||||
|
||||
cx.update_model(&self.state, |model, cx| {
|
||||
cx.update_entity(&self.state, |model, cx| {
|
||||
let messages: Vec<Message> = items
|
||||
.into_iter()
|
||||
.filter_map(|new| {
|
||||
@@ -252,7 +257,12 @@ impl ChatPanel {
|
||||
}
|
||||
}
|
||||
|
||||
fn send_message(&mut self, view: WeakView<TextInput>, cx: &mut ViewContext<Self>) {
|
||||
fn send_message(
|
||||
&mut self,
|
||||
view: WeakEntity<TextInput>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let room = self.room.read(cx);
|
||||
let owner = room.owner.clone();
|
||||
let mut members = room.members.to_vec();
|
||||
@@ -262,7 +272,7 @@ impl ChatPanel {
|
||||
let mut content = self.input.read(cx).text().to_string();
|
||||
|
||||
if content.is_empty() {
|
||||
cx.push_notification("Message cannot be empty");
|
||||
window.push_notification("Message cannot be empty", cx);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -279,12 +289,13 @@ impl ChatPanel {
|
||||
|
||||
// Update input state
|
||||
if let Some(input) = view.upgrade() {
|
||||
cx.update_view(&input, |input, cx| {
|
||||
input.set_loading(true, cx);
|
||||
input.set_disabled(true, cx);
|
||||
cx.update_entity(&input, |input, cx| {
|
||||
input.set_loading(true, window, cx);
|
||||
input.set_disabled(true, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
cx.spawn(|this, mut async_cx| async move {
|
||||
// Send message to all members
|
||||
async_cx
|
||||
@@ -315,8 +326,8 @@ impl ChatPanel {
|
||||
.detach();
|
||||
|
||||
if let Some(view) = this.upgrade() {
|
||||
_ = async_cx.update_view(&view, |this, cx| {
|
||||
cx.update_model(&this.state, |model, cx| {
|
||||
_ = async_cx.update_entity(&view, |this, cx| {
|
||||
cx.update_entity(&this.state, |model, cx| {
|
||||
let message = Message::new(
|
||||
owner,
|
||||
content.to_string().into(),
|
||||
@@ -331,17 +342,18 @@ impl ChatPanel {
|
||||
}
|
||||
|
||||
if let Some(input) = view.upgrade() {
|
||||
_ = async_cx.update_view(&input, |input, cx| {
|
||||
input.set_loading(false, cx);
|
||||
input.set_disabled(false, cx);
|
||||
input.set_text("", cx);
|
||||
_ = async_cx.update_entity(&input, |input, cx| {
|
||||
input.set_loading(false, window, cx);
|
||||
input.set_disabled(false, window, cx);
|
||||
input.set_text("", window, cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
*/
|
||||
}
|
||||
|
||||
fn upload(&mut self, cx: &mut ViewContext<Self>) {
|
||||
fn upload(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let attaches = self.attaches.clone();
|
||||
let paths = cx.prompt_for_paths(PathPromptOptions {
|
||||
files: true,
|
||||
@@ -373,14 +385,14 @@ impl ChatPanel {
|
||||
if let Ok(url) = rx.await {
|
||||
// Stop loading spinner
|
||||
if let Some(view) = this.upgrade() {
|
||||
_ = async_cx.update_view(&view, |this, cx| {
|
||||
_ = async_cx.update_entity(&view, |this, cx| {
|
||||
this.is_uploading = false;
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
|
||||
// Update attaches model
|
||||
_ = async_cx.update_model(&attaches, |model, cx| {
|
||||
_ = async_cx.update_entity(&attaches, |model, cx| {
|
||||
if let Some(model) = model.as_mut() {
|
||||
model.push(url);
|
||||
} else {
|
||||
@@ -398,7 +410,7 @@ impl ChatPanel {
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn remove(&mut self, url: &Url, cx: &mut ViewContext<Self>) {
|
||||
fn remove(&mut self, url: &Url, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.attaches.update(cx, |model, cx| {
|
||||
if let Some(urls) = model.as_mut() {
|
||||
let ix = urls.iter().position(|x| x == url).unwrap();
|
||||
@@ -414,7 +426,7 @@ impl Panel for ChatPanel {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn panel_facepile(&self, cx: &WindowContext) -> Option<Vec<String>> {
|
||||
fn panel_facepile(&self, cx: &App) -> Option<Vec<String>> {
|
||||
Some(
|
||||
self.room
|
||||
.read(cx)
|
||||
@@ -425,41 +437,37 @@ impl Panel for ChatPanel {
|
||||
)
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &WindowContext) -> AnyElement {
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
}
|
||||
|
||||
fn closeable(&self, _cx: &WindowContext) -> bool {
|
||||
fn closeable(&self, _cx: &App) -> bool {
|
||||
self.closeable
|
||||
}
|
||||
|
||||
fn zoomable(&self, _cx: &WindowContext) -> bool {
|
||||
fn zoomable(&self, _cx: &App) -> bool {
|
||||
self.zoomable
|
||||
}
|
||||
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &WindowContext) -> PopupMenu {
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
|
||||
menu.track_focus(&self.focus_handle)
|
||||
}
|
||||
|
||||
fn toolbar_buttons(&self, _cx: &WindowContext) -> Vec<Button> {
|
||||
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn dump(&self, _cx: &AppContext) -> PanelState {
|
||||
PanelState::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for ChatPanel {}
|
||||
|
||||
impl FocusableView for ChatPanel {
|
||||
fn focus_handle(&self, _: &AppContext) -> FocusHandle {
|
||||
impl Focusable for ChatPanel {
|
||||
fn focus_handle(&self, _: &App) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ChatPanel {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(list(self.list.clone()).flex_1())
|
||||
@@ -504,8 +512,8 @@ impl Render for ChatPanel {
|
||||
.text_color(white()),
|
||||
),
|
||||
)
|
||||
.on_click(cx.listener(move |this, _, cx| {
|
||||
this.remove(&url, cx);
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.remove(&url, window, cx);
|
||||
}))
|
||||
}))
|
||||
})
|
||||
@@ -520,8 +528,8 @@ impl Render for ChatPanel {
|
||||
Button::new("upload")
|
||||
.icon(Icon::new(IconName::Upload))
|
||||
.ghost()
|
||||
.on_click(cx.listener(move |this, _, cx| {
|
||||
this.upload(cx);
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.upload(window, cx);
|
||||
}))
|
||||
.loading(self.is_uploading),
|
||||
)
|
||||
@@ -542,8 +550,12 @@ impl Render for ChatPanel {
|
||||
.bold()
|
||||
.rounded(ButtonRounded::Medium)
|
||||
.label("SEND")
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.send_message(this.input.downgrade(), cx)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.send_message(
|
||||
this.input.downgrade(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,34 +1,44 @@
|
||||
use common::constants::KEYRING_SERVICE;
|
||||
use gpui::{div, IntoElement, ParentElement, Render, Styled, View, ViewContext, VisualContext};
|
||||
use gpui::{
|
||||
div, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, Styled, Window,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use registry::{app::AppRegistry, contact::Contact};
|
||||
use state::get_client;
|
||||
use ui::input::{InputEvent, TextInput};
|
||||
|
||||
pub struct Onboarding {
|
||||
input: View<TextInput>,
|
||||
input: Entity<TextInput>,
|
||||
}
|
||||
|
||||
impl Onboarding {
|
||||
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
|
||||
let input = cx.new_view(|cx| {
|
||||
let mut input = TextInput::new(cx);
|
||||
input.set_size(ui::Size::Medium, cx);
|
||||
pub fn new(window: &mut Window, cx: &mut Context<'_, Self>) -> Self {
|
||||
let input = cx.new(|cx| {
|
||||
let mut input = TextInput::new(window, cx);
|
||||
input.set_size(ui::Size::Medium, window, cx);
|
||||
input
|
||||
});
|
||||
|
||||
cx.subscribe(&input, move |_, text_input, input_event, cx| {
|
||||
if let InputEvent::PressEnter = input_event {
|
||||
let content = text_input.read(cx).text().to_string();
|
||||
_ = Self::save_keys(&content, cx);
|
||||
}
|
||||
})
|
||||
cx.subscribe_in(
|
||||
&input,
|
||||
window,
|
||||
move |_, text_input, input_event, window, cx| {
|
||||
if let InputEvent::PressEnter = input_event {
|
||||
let content = text_input.read(cx).text().to_string();
|
||||
_ = Self::save_keys(&content, window, cx);
|
||||
}
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
Self { input }
|
||||
}
|
||||
|
||||
fn save_keys(content: &str, cx: &mut ViewContext<Self>) -> anyhow::Result<(), anyhow::Error> {
|
||||
fn save_keys(
|
||||
content: &str,
|
||||
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()?;
|
||||
@@ -75,7 +85,7 @@ impl Onboarding {
|
||||
}
|
||||
|
||||
impl Render for Onboarding {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.flex()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use common::utils::{random_name, room_hash};
|
||||
use gpui::{
|
||||
div, img, impl_internal_actions, px, uniform_list, Context, FocusHandle, InteractiveElement,
|
||||
IntoElement, Model, ParentElement, Render, SharedString, StatefulInteractiveElement, Styled,
|
||||
View, ViewContext, VisualContext, WindowContext,
|
||||
div, img, impl_internal_actions, px, uniform_list, App, AppContext, Context, Entity,
|
||||
FocusHandle, InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, Window,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use registry::{app::AppRegistry, contact::Contact, room::Room};
|
||||
@@ -24,48 +24,54 @@ struct SelectContact(PublicKey);
|
||||
impl_internal_actions!(contacts, [SelectContact]);
|
||||
|
||||
pub struct Compose {
|
||||
title_input: View<TextInput>,
|
||||
message_input: View<TextInput>,
|
||||
user_input: View<TextInput>,
|
||||
contacts: Model<Option<Vec<Contact>>>,
|
||||
selected: Model<HashSet<PublicKey>>,
|
||||
title_input: Entity<TextInput>,
|
||||
message_input: Entity<TextInput>,
|
||||
user_input: Entity<TextInput>,
|
||||
contacts: Entity<Option<Vec<Contact>>>,
|
||||
selected: Entity<HashSet<PublicKey>>,
|
||||
focus_handle: FocusHandle,
|
||||
is_loading: bool,
|
||||
}
|
||||
|
||||
impl Compose {
|
||||
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
|
||||
let contacts = cx.new_model(|_| None);
|
||||
let selected = cx.new_model(|_| HashSet::new());
|
||||
pub fn new(window: &mut Window, cx: &mut Context<'_, Self>) -> Self {
|
||||
let contacts = cx.new(|_| None);
|
||||
let selected = cx.new(|_| HashSet::new());
|
||||
|
||||
let user_input = cx.new_view(|cx| {
|
||||
TextInput::new(cx)
|
||||
let user_input = cx.new(|cx| {
|
||||
TextInput::new(window, cx)
|
||||
.text_size(ui::Size::Small)
|
||||
.small()
|
||||
.placeholder("npub1...")
|
||||
});
|
||||
|
||||
let title_input = cx.new_view(|cx| {
|
||||
let title_input = cx.new(|cx| {
|
||||
let name = random_name(2);
|
||||
let mut input = TextInput::new(cx).appearance(false).text_size(Size::XSmall);
|
||||
let mut input = TextInput::new(window, cx)
|
||||
.appearance(false)
|
||||
.text_size(Size::XSmall);
|
||||
|
||||
input.set_placeholder("Family... . (Optional)");
|
||||
input.set_text(name, cx);
|
||||
input.set_text(name, window, cx);
|
||||
input
|
||||
});
|
||||
|
||||
let message_input = cx.new_view(|cx| {
|
||||
TextInput::new(cx)
|
||||
let message_input = cx.new(|cx| {
|
||||
TextInput::new(window, cx)
|
||||
.appearance(false)
|
||||
.text_size(Size::XSmall)
|
||||
.placeholder("Hello... (Optional)")
|
||||
});
|
||||
|
||||
cx.subscribe(&user_input, move |this, _, input_event, cx| {
|
||||
if let InputEvent::PressEnter = input_event {
|
||||
this.add(cx);
|
||||
}
|
||||
})
|
||||
cx.subscribe_in(
|
||||
&user_input,
|
||||
window,
|
||||
move |this, _, input_event, window, cx| {
|
||||
if let InputEvent::PressEnter = input_event {
|
||||
this.add(window, cx);
|
||||
}
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
cx.spawn(|this, mut async_cx| {
|
||||
@@ -89,7 +95,7 @@ impl Compose {
|
||||
|
||||
if let Ok(contacts) = query {
|
||||
if let Some(view) = this.upgrade() {
|
||||
_ = async_cx.update_view(&view, |this, cx| {
|
||||
_ = async_cx.update_entity(&view, |this, cx| {
|
||||
this.contacts.update(cx, |this, cx| {
|
||||
*this = Some(contacts);
|
||||
cx.notify();
|
||||
@@ -114,8 +120,8 @@ impl Compose {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn room(&self, cx: &WindowContext) -> Option<Room> {
|
||||
let current_user = cx.global::<AppRegistry>().current_user(cx);
|
||||
pub fn room(&self, window: &Window, cx: &App) -> Option<Room> {
|
||||
let current_user = cx.global::<AppRegistry>().current_user(window, cx);
|
||||
|
||||
if let Some(current_user) = current_user {
|
||||
// Convert selected pubkeys into nostr tags
|
||||
@@ -151,7 +157,7 @@ impl Compose {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn label(&self, cx: &WindowContext) -> SharedString {
|
||||
pub fn label(&self, window: &Window, cx: &App) -> SharedString {
|
||||
if self.selected.read(cx).len() > 1 {
|
||||
"Create Group DM".into()
|
||||
} else {
|
||||
@@ -159,7 +165,7 @@ impl Compose {
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, cx: &mut ViewContext<Self>) {
|
||||
fn add(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let content = self.user_input.read(cx).text().to_string();
|
||||
let input = self.user_input.downgrade();
|
||||
|
||||
@@ -183,7 +189,7 @@ impl Compose {
|
||||
|
||||
if let Ok(metadata) = query {
|
||||
if let Some(view) = this.upgrade() {
|
||||
_ = async_cx.update_view(&view, |this, cx| {
|
||||
_ = async_cx.update_entity(&view, |this, cx| {
|
||||
this.contacts.update(cx, |this, cx| {
|
||||
if let Some(members) = this {
|
||||
members.insert(0, Contact::new(public_key, metadata));
|
||||
@@ -202,8 +208,8 @@ impl Compose {
|
||||
}
|
||||
|
||||
if let Some(input) = input.upgrade() {
|
||||
_ = async_cx.update_view(&input, |input, cx| {
|
||||
input.set_text("", cx);
|
||||
_ = async_cx.update_entity(&input, |input, cx| {
|
||||
// input.set_text("", window, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -214,7 +220,12 @@ impl Compose {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_action_select(&mut self, action: &SelectContact, cx: &mut ViewContext<Self>) {
|
||||
fn on_action_select(
|
||||
&mut self,
|
||||
action: &SelectContact,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.selected.update(cx, |this, cx| {
|
||||
if this.contains(&action.0) {
|
||||
this.remove(&action.0);
|
||||
@@ -227,7 +238,7 @@ impl Compose {
|
||||
}
|
||||
|
||||
impl Render for Compose {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let msg =
|
||||
"Start a conversation with someone using their npub or NIP-05 (like foo@bar.com).";
|
||||
|
||||
@@ -291,7 +302,9 @@ impl Render for Compose {
|
||||
.small()
|
||||
.rounded(ButtonRounded::Size(px(9999.)))
|
||||
.loading(self.is_loading)
|
||||
.on_click(cx.listener(|this, _, cx| this.add(cx))),
|
||||
.on_click(
|
||||
cx.listener(|this, _, window, cx| this.add(window, cx)),
|
||||
),
|
||||
)
|
||||
.child(self.user_input.clone()),
|
||||
)
|
||||
@@ -299,10 +312,10 @@ impl Render for Compose {
|
||||
if let Some(contacts) = self.contacts.read(cx).clone() {
|
||||
this.child(
|
||||
uniform_list(
|
||||
cx.view().clone(),
|
||||
cx.model().clone(),
|
||||
"contacts",
|
||||
contacts.len(),
|
||||
move |this, range, cx| {
|
||||
move |this, range, window, cx| {
|
||||
let selected = this.selected.read(cx);
|
||||
let mut items = Vec::new();
|
||||
|
||||
@@ -348,9 +361,9 @@ impl Render for Compose {
|
||||
.base
|
||||
.step(cx, ColorScaleStep::THREE))
|
||||
})
|
||||
.on_click(move |_, cx| {
|
||||
cx.dispatch_action(Box::new(
|
||||
SelectContact(item.public_key()),
|
||||
.on_click(move |_, window, cx| {
|
||||
cx.dispatch_action(&SelectContact(
|
||||
item.public_key(),
|
||||
));
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::views::app::{AddPanel, PanelKind};
|
||||
use common::utils::message_ago;
|
||||
use gpui::{
|
||||
div, img, percentage, prelude::FluentBuilder, px, InteractiveElement, IntoElement,
|
||||
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, ViewContext,
|
||||
div, img, percentage, prelude::FluentBuilder, px, Context, InteractiveElement, IntoElement,
|
||||
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, Window,
|
||||
};
|
||||
use registry::chat::ChatRegistry;
|
||||
use ui::{
|
||||
@@ -18,7 +18,7 @@ pub struct Inbox {
|
||||
}
|
||||
|
||||
impl Inbox {
|
||||
pub fn new(_cx: &mut ViewContext<'_, Self>) -> Self {
|
||||
pub fn new(_window: &mut Window, _cx: &mut Context<'_, Self>) -> Self {
|
||||
Self {
|
||||
label: "Inbox".into(),
|
||||
is_collapsed: false,
|
||||
@@ -38,7 +38,7 @@ impl Inbox {
|
||||
})
|
||||
}
|
||||
|
||||
fn render_item(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render_item(&self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let weak_model = cx.global::<ChatRegistry>().inbox();
|
||||
|
||||
if let Some(model) = weak_model.upgrade() {
|
||||
@@ -91,8 +91,8 @@ impl Inbox {
|
||||
.text_color(cx.theme().base.step(cx, ColorScaleStep::ELEVEN))
|
||||
.child(ago),
|
||||
)
|
||||
.on_click(cx.listener(move |this, _, cx| {
|
||||
this.action(id, cx);
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.action(id, window, cx);
|
||||
}))
|
||||
}))
|
||||
}
|
||||
@@ -102,11 +102,13 @@ impl Inbox {
|
||||
}
|
||||
}
|
||||
|
||||
fn action(&self, id: u64, cx: &mut ViewContext<Self>) {
|
||||
cx.dispatch_action(Box::new(AddPanel {
|
||||
fn action(&self, id: u64, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
let action = AddPanel {
|
||||
panel: PanelKind::Room(id),
|
||||
position: DockPlacement::Center,
|
||||
}))
|
||||
};
|
||||
|
||||
cx.dispatch_action(&action)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +124,7 @@ impl Collapsible for Inbox {
|
||||
}
|
||||
|
||||
impl Render for Inbox {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.px_2()
|
||||
.gap_1()
|
||||
@@ -145,11 +147,13 @@ impl Render for Inbox {
|
||||
)
|
||||
.child(self.label.clone())
|
||||
.hover(|this| this.bg(cx.theme().base.step(cx, ColorScaleStep::THREE)))
|
||||
.on_click(cx.listener(move |view, _event, cx| {
|
||||
.on_click(cx.listener(move |view, _event, _window, cx| {
|
||||
view.is_collapsed = !view.is_collapsed;
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
.when(!self.is_collapsed, |this| this.child(self.render_item(cx)))
|
||||
.when(!self.is_collapsed, |this| {
|
||||
this.child(self.render_item(window, cx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
use crate::views::sidebar::inbox::Inbox;
|
||||
use compose::Compose;
|
||||
use gpui::{
|
||||
div, px, AnyElement, AppContext, BorrowAppContext, Entity, EntityId, EventEmitter, FocusHandle,
|
||||
FocusableView, InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, View, ViewContext, VisualContext, WindowContext,
|
||||
div, px, AnyElement, App, AppContext, BorrowAppContext, Context, Entity, EntityId,
|
||||
EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render,
|
||||
SharedString, StatefulInteractiveElement, Styled, Window,
|
||||
};
|
||||
use registry::chat::ChatRegistry;
|
||||
use ui::{
|
||||
button::{Button, ButtonRounded, ButtonVariants},
|
||||
dock_area::{
|
||||
panel::{Panel, PanelEvent},
|
||||
state::PanelState,
|
||||
},
|
||||
dock_area::panel::{Panel, PanelEvent},
|
||||
popup_menu::PopupMenu,
|
||||
scroll::ScrollbarAxis,
|
||||
theme::{scale::ColorScaleStep, ActiveTheme},
|
||||
@@ -28,33 +25,33 @@ pub struct Sidebar {
|
||||
zoomable: bool,
|
||||
focus_handle: FocusHandle,
|
||||
// Dock
|
||||
inbox: View<Inbox>,
|
||||
inbox: Entity<Inbox>,
|
||||
view_id: EntityId,
|
||||
}
|
||||
|
||||
impl Sidebar {
|
||||
pub fn new(cx: &mut WindowContext) -> View<Self> {
|
||||
cx.new_view(Self::view)
|
||||
pub fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
cx.new(|cx| Self::view(window, cx))
|
||||
}
|
||||
|
||||
fn view(cx: &mut ViewContext<Self>) -> Self {
|
||||
let inbox = cx.new_view(Inbox::new);
|
||||
fn view(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let inbox = cx.new(|cx| Inbox::new(window, cx));
|
||||
|
||||
Self {
|
||||
name: "Sidebar".into(),
|
||||
closeable: true,
|
||||
zoomable: true,
|
||||
focus_handle: cx.focus_handle(),
|
||||
view_id: cx.view().entity_id(),
|
||||
view_id: cx.model().entity_id(),
|
||||
inbox,
|
||||
}
|
||||
}
|
||||
|
||||
fn show_compose(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let compose = cx.new_view(Compose::new);
|
||||
fn show_compose(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let compose = cx.new(|cx| Compose::new(window, cx));
|
||||
|
||||
cx.open_modal(move |modal, cx| {
|
||||
let label = compose.read(cx).label(cx);
|
||||
window.open_modal(cx, move |modal, window, cx| {
|
||||
let label = compose.read(cx).label(window, cx);
|
||||
|
||||
modal
|
||||
.title("Direct Messages")
|
||||
@@ -72,13 +69,13 @@ impl Sidebar {
|
||||
.bold()
|
||||
.rounded(ButtonRounded::Large)
|
||||
.w_full()
|
||||
.on_click(cx.listener_for(&compose, |this, _, cx| {
|
||||
if let Some(room) = this.room(cx) {
|
||||
.on_click(window.listener_for(&compose, |this, _, window, cx| {
|
||||
if let Some(room) = this.room(window, cx) {
|
||||
cx.update_global::<ChatRegistry, _>(|this, cx| {
|
||||
this.new_room(room, cx);
|
||||
});
|
||||
|
||||
cx.close_modal();
|
||||
window.close_modal(cx);
|
||||
}
|
||||
})),
|
||||
),
|
||||
@@ -92,41 +89,37 @@ impl Panel for Sidebar {
|
||||
"Sidebar".into()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &WindowContext) -> AnyElement {
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
}
|
||||
|
||||
fn closeable(&self, _cx: &WindowContext) -> bool {
|
||||
fn closeable(&self, _cx: &App) -> bool {
|
||||
self.closeable
|
||||
}
|
||||
|
||||
fn zoomable(&self, _cx: &WindowContext) -> bool {
|
||||
fn zoomable(&self, _cx: &App) -> bool {
|
||||
self.zoomable
|
||||
}
|
||||
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &WindowContext) -> PopupMenu {
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
|
||||
menu.track_focus(&self.focus_handle)
|
||||
}
|
||||
|
||||
fn toolbar_buttons(&self, _cx: &WindowContext) -> Vec<Button> {
|
||||
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn dump(&self, _cx: &AppContext) -> PanelState {
|
||||
PanelState::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for Sidebar {}
|
||||
|
||||
impl FocusableView for Sidebar {
|
||||
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||
impl Focusable for Sidebar {
|
||||
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Sidebar {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.scrollable(self.view_id, ScrollbarAxis::Vertical)
|
||||
.py_3()
|
||||
@@ -159,7 +152,7 @@ impl Render for Sidebar {
|
||||
)
|
||||
.child("New Message")
|
||||
.hover(|this| this.bg(cx.theme().base.step(cx, ColorScaleStep::THREE)))
|
||||
.on_click(cx.listener(|this, _, cx| this.show_compose(cx))),
|
||||
.on_click(cx.listener(|this, _, window, cx| this.show_compose(window, cx))),
|
||||
),
|
||||
)
|
||||
.child(self.inbox.clone())
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
use gpui::{
|
||||
div, svg, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView, IntoElement,
|
||||
ParentElement, Render, SharedString, Styled, View, ViewContext, VisualContext, WindowContext,
|
||||
div, svg, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Window,
|
||||
};
|
||||
use ui::{
|
||||
button::Button,
|
||||
dock_area::{
|
||||
panel::{Panel, PanelEvent},
|
||||
state::PanelState,
|
||||
},
|
||||
dock_area::panel::{Panel, PanelEvent},
|
||||
popup_menu::PopupMenu,
|
||||
theme::{scale::ColorScaleStep, ActiveTheme},
|
||||
StyledExt,
|
||||
@@ -21,11 +18,11 @@ pub struct WelcomePanel {
|
||||
}
|
||||
|
||||
impl WelcomePanel {
|
||||
pub fn new(cx: &mut WindowContext) -> View<Self> {
|
||||
cx.new_view(Self::view)
|
||||
pub fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
cx.new(|cx| Self::view(window, cx))
|
||||
}
|
||||
|
||||
fn view(cx: &mut ViewContext<Self>) -> Self {
|
||||
fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
Self {
|
||||
name: "Welcome".into(),
|
||||
closeable: true,
|
||||
@@ -40,41 +37,37 @@ impl Panel for WelcomePanel {
|
||||
"WelcomePanel".into()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &WindowContext) -> AnyElement {
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
}
|
||||
|
||||
fn closeable(&self, _cx: &WindowContext) -> bool {
|
||||
fn closeable(&self, _cx: &App) -> bool {
|
||||
self.closeable
|
||||
}
|
||||
|
||||
fn zoomable(&self, _cx: &WindowContext) -> bool {
|
||||
fn zoomable(&self, _cx: &App) -> bool {
|
||||
self.zoomable
|
||||
}
|
||||
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &WindowContext) -> PopupMenu {
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
|
||||
menu.track_focus(&self.focus_handle)
|
||||
}
|
||||
|
||||
fn toolbar_buttons(&self, _cx: &WindowContext) -> Vec<Button> {
|
||||
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn dump(&self, _cx: &AppContext) -> PanelState {
|
||||
PanelState::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for WelcomePanel {}
|
||||
|
||||
impl FocusableView for WelcomePanel {
|
||||
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||
impl Focusable for WelcomePanel {
|
||||
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for WelcomePanel {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.flex()
|
||||
|
||||
Reference in New Issue
Block a user