Style incoming call notification
This commit is contained in:
parent
79748803a9
commit
d7bac3cea6
6 changed files with 111 additions and 28 deletions
|
@ -3,8 +3,8 @@ use futures::StreamExt;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
elements::*,
|
elements::*,
|
||||||
geometry::{rect::RectF, vector::vec2f},
|
geometry::{rect::RectF, vector::vec2f},
|
||||||
impl_internal_actions, Entity, MouseButton, MutableAppContext, RenderContext, View,
|
impl_internal_actions, CursorStyle, Entity, MouseButton, MutableAppContext, RenderContext,
|
||||||
ViewContext, WindowBounds, WindowKind, WindowOptions,
|
View, ViewContext, WindowBounds, WindowKind, WindowOptions,
|
||||||
};
|
};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
@ -24,11 +24,17 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(incoming_call) = incoming_call {
|
if let Some(incoming_call) = incoming_call {
|
||||||
|
const PADDING: f32 = 16.;
|
||||||
|
let screen_size = cx.platform().screen_size();
|
||||||
|
let window_size = vec2f(304., 64.);
|
||||||
let (window_id, _) = cx.add_window(
|
let (window_id, _) = cx.add_window(
|
||||||
WindowOptions {
|
WindowOptions {
|
||||||
bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), vec2f(300., 400.))),
|
bounds: WindowBounds::Fixed(RectF::new(
|
||||||
|
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
||||||
|
window_size,
|
||||||
|
)),
|
||||||
titlebar: None,
|
titlebar: None,
|
||||||
center: true,
|
center: false,
|
||||||
kind: WindowKind::PopUp,
|
kind: WindowKind::PopUp,
|
||||||
is_movable: false,
|
is_movable: false,
|
||||||
},
|
},
|
||||||
|
@ -84,22 +90,40 @@ impl IncomingCallNotification {
|
||||||
fn render_caller(&self, cx: &mut RenderContext<Self>) -> ElementBox {
|
fn render_caller(&self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_children(
|
.with_children(self.call.caller.avatar.clone().map(|avatar| {
|
||||||
self.call
|
Image::new(avatar)
|
||||||
.caller
|
.with_style(theme.caller_avatar)
|
||||||
.avatar
|
.aligned()
|
||||||
.clone()
|
.boxed()
|
||||||
.map(|avatar| Image::new(avatar).with_style(theme.caller_avatar).boxed()),
|
}))
|
||||||
)
|
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(
|
Flex::column()
|
||||||
self.call.caller.github_login.clone(),
|
.with_child(
|
||||||
theme.caller_username.text.clone(),
|
Label::new(
|
||||||
)
|
self.call.caller.github_login.clone(),
|
||||||
.contained()
|
theme.caller_username.text.clone(),
|
||||||
.with_style(theme.caller_username.container)
|
)
|
||||||
.boxed(),
|
.contained()
|
||||||
|
.with_style(theme.caller_username.container)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
Label::new(
|
||||||
|
"Incoming Zed call...".into(),
|
||||||
|
theme.caller_message.text.clone(),
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.caller_message.container)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.caller_metadata)
|
||||||
|
.aligned()
|
||||||
|
.boxed(),
|
||||||
)
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.caller_container)
|
||||||
|
.flex(1., true)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,33 +131,46 @@ impl IncomingCallNotification {
|
||||||
enum Accept {}
|
enum Accept {}
|
||||||
enum Decline {}
|
enum Decline {}
|
||||||
|
|
||||||
Flex::row()
|
Flex::column()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Accept>::new(0, cx, |_, cx| {
|
MouseEventHandler::<Accept>::new(0, cx, |_, cx| {
|
||||||
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
||||||
Label::new("Accept".to_string(), theme.accept_button.text.clone())
|
Label::new("Accept".to_string(), theme.accept_button.text.clone())
|
||||||
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.accept_button.container)
|
.with_style(theme.accept_button.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(MouseButton::Left, |_, cx| {
|
.on_click(MouseButton::Left, |_, cx| {
|
||||||
cx.dispatch_action(RespondToCall { accept: true });
|
cx.dispatch_action(RespondToCall { accept: true });
|
||||||
})
|
})
|
||||||
|
.flex(1., true)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Decline>::new(0, cx, |_, cx| {
|
MouseEventHandler::<Decline>::new(0, cx, |_, cx| {
|
||||||
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
||||||
Label::new("Decline".to_string(), theme.decline_button.text.clone())
|
Label::new("Decline".to_string(), theme.decline_button.text.clone())
|
||||||
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.decline_button.container)
|
.with_style(theme.decline_button.container)
|
||||||
.boxed()
|
.boxed()
|
||||||
})
|
})
|
||||||
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.on_click(MouseButton::Left, |_, cx| {
|
.on_click(MouseButton::Left, |_, cx| {
|
||||||
cx.dispatch_action(RespondToCall { accept: false });
|
cx.dispatch_action(RespondToCall { accept: false });
|
||||||
})
|
})
|
||||||
|
.flex(1., true)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
|
.constrained()
|
||||||
|
.with_width(
|
||||||
|
cx.global::<Settings>()
|
||||||
|
.theme
|
||||||
|
.incoming_call_notification
|
||||||
|
.button_width,
|
||||||
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,9 +185,17 @@ impl View for IncomingCallNotification {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox {
|
||||||
Flex::column()
|
let background = cx
|
||||||
|
.global::<Settings>()
|
||||||
|
.theme
|
||||||
|
.incoming_call_notification
|
||||||
|
.background;
|
||||||
|
Flex::row()
|
||||||
.with_child(self.render_caller(cx))
|
.with_child(self.render_caller(cx))
|
||||||
.with_child(self.render_buttons(cx))
|
.with_child(self.render_buttons(cx))
|
||||||
|
.contained()
|
||||||
|
.with_background_color(background)
|
||||||
|
.expanded()
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ pub trait Platform: Send + Sync {
|
||||||
fn unhide_other_apps(&self);
|
fn unhide_other_apps(&self);
|
||||||
fn quit(&self);
|
fn quit(&self);
|
||||||
|
|
||||||
|
fn screen_size(&self) -> Vector2F;
|
||||||
|
|
||||||
fn open_window(
|
fn open_window(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
id: usize,
|
||||||
|
|
|
@ -2,7 +2,9 @@ use super::{
|
||||||
event::key_to_native, status_item::StatusItem, BoolExt as _, Dispatcher, FontSystem, Window,
|
event::key_to_native, status_item::StatusItem, BoolExt as _, Dispatcher, FontSystem, Window,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
executor, keymap,
|
executor,
|
||||||
|
geometry::vector::{vec2f, Vector2F},
|
||||||
|
keymap,
|
||||||
platform::{self, CursorStyle},
|
platform::{self, CursorStyle},
|
||||||
Action, ClipboardItem, Event, Menu, MenuItem,
|
Action, ClipboardItem, Event, Menu, MenuItem,
|
||||||
};
|
};
|
||||||
|
@ -12,7 +14,7 @@ use cocoa::{
|
||||||
appkit::{
|
appkit::{
|
||||||
NSApplication, NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
|
NSApplication, NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
|
||||||
NSEventModifierFlags, NSMenu, NSMenuItem, NSModalResponse, NSOpenPanel, NSPasteboard,
|
NSEventModifierFlags, NSMenu, NSMenuItem, NSModalResponse, NSOpenPanel, NSPasteboard,
|
||||||
NSPasteboardTypeString, NSSavePanel, NSWindow,
|
NSPasteboardTypeString, NSSavePanel, NSScreen, NSWindow,
|
||||||
},
|
},
|
||||||
base::{id, nil, selector, YES},
|
base::{id, nil, selector, YES},
|
||||||
foundation::{
|
foundation::{
|
||||||
|
@ -485,6 +487,14 @@ impl platform::Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn screen_size(&self) -> Vector2F {
|
||||||
|
unsafe {
|
||||||
|
let screen = NSScreen::mainScreen(nil);
|
||||||
|
let frame = NSScreen::frame(screen);
|
||||||
|
vec2f(frame.size.width as f32, frame.size.height as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn open_window(
|
fn open_window(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
id: usize,
|
||||||
|
|
|
@ -131,6 +131,10 @@ impl super::Platform for Platform {
|
||||||
|
|
||||||
fn quit(&self) {}
|
fn quit(&self) {}
|
||||||
|
|
||||||
|
fn screen_size(&self) -> Vector2F {
|
||||||
|
vec2f(1024., 768.)
|
||||||
|
}
|
||||||
|
|
||||||
fn open_window(
|
fn open_window(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
|
|
|
@ -479,8 +479,14 @@ pub struct ProjectSharedNotification {
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default)]
|
||||||
pub struct IncomingCallNotification {
|
pub struct IncomingCallNotification {
|
||||||
|
#[serde(default)]
|
||||||
|
pub background: Color,
|
||||||
|
pub caller_container: ContainerStyle,
|
||||||
pub caller_avatar: ImageStyle,
|
pub caller_avatar: ImageStyle,
|
||||||
|
pub caller_metadata: ContainerStyle,
|
||||||
pub caller_username: ContainedText,
|
pub caller_username: ContainedText,
|
||||||
|
pub caller_message: ContainedText,
|
||||||
|
pub button_width: f32,
|
||||||
pub accept_button: ContainedText,
|
pub accept_button: ContainedText,
|
||||||
pub decline_button: ContainedText,
|
pub decline_button: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,38 @@
|
||||||
import Theme from "../themes/common/theme";
|
import Theme from "../themes/common/theme";
|
||||||
import { text } from "./components";
|
import { backgroundColor, borderColor, text } from "./components";
|
||||||
|
|
||||||
export default function incomingCallNotification(theme: Theme): Object {
|
export default function incomingCallNotification(theme: Theme): Object {
|
||||||
const avatarSize = 12;
|
const avatarSize = 32;
|
||||||
return {
|
return {
|
||||||
|
background: backgroundColor(theme, 300),
|
||||||
|
callerContainer: {
|
||||||
|
padding: 12,
|
||||||
|
},
|
||||||
callerAvatar: {
|
callerAvatar: {
|
||||||
height: avatarSize,
|
height: avatarSize,
|
||||||
width: avatarSize,
|
width: avatarSize,
|
||||||
cornerRadius: 6,
|
cornerRadius: avatarSize / 2,
|
||||||
|
},
|
||||||
|
callerMetadata: {
|
||||||
|
margin: { left: 10 },
|
||||||
},
|
},
|
||||||
callerUsername: {
|
callerUsername: {
|
||||||
...text(theme, "sans", "primary", { size: "xs" }),
|
...text(theme, "sans", "active", { size: "sm", weight: "bold" }),
|
||||||
|
margin: { top: -3 },
|
||||||
},
|
},
|
||||||
|
callerMessage: {
|
||||||
|
...text(theme, "sans", "secondary", { size: "xs" }),
|
||||||
|
margin: { top: -3 },
|
||||||
|
},
|
||||||
|
buttonWidth: 96,
|
||||||
acceptButton: {
|
acceptButton: {
|
||||||
...text(theme, "sans", "primary", { size: "xs" })
|
background: backgroundColor(theme, "ok", "active"),
|
||||||
|
border: { left: true, bottom: true, width: 1, color: borderColor(theme, "primary") },
|
||||||
|
...text(theme, "sans", "ok", { size: "xs", weight: "extra_bold" })
|
||||||
},
|
},
|
||||||
declineButton: {
|
declineButton: {
|
||||||
...text(theme, "sans", "primary", { size: "xs" })
|
border: { left: true, width: 1, color: borderColor(theme, "primary") },
|
||||||
|
...text(theme, "sans", "error", { size: "xs", weight: "extra_bold" })
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue