Compare commits
6 Commits
zeta-exten
...
fix-rust-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f67815df05 | ||
|
|
f2ca21ae44 | ||
|
|
01e5ac0a49 | ||
|
|
306f1c6838 | ||
|
|
2f722e63a1 | ||
|
|
6838b6203a |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -16424,6 +16424,7 @@ name = "zeta"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arrayvec",
|
||||
"call",
|
||||
"client",
|
||||
"clock",
|
||||
|
||||
@@ -11,8 +11,8 @@ use futures::{
|
||||
use fuzzy::StringMatchCandidate;
|
||||
use gpui::{
|
||||
actions, point, size, transparent_black, Action, AppContext, BackgroundExecutor, Bounds,
|
||||
EventEmitter, Global, HighlightStyle, PromptLevel, ReadGlobal, Subscription, Task, TextStyle,
|
||||
TitlebarOptions, UpdateGlobal, View, WindowBounds, WindowHandle, WindowOptions,
|
||||
EventEmitter, Global, PromptLevel, ReadGlobal, Subscription, Task, TextStyle, TitlebarOptions,
|
||||
UpdateGlobal, View, WindowBounds, WindowHandle, WindowOptions,
|
||||
};
|
||||
use heed::{
|
||||
types::{SerdeBincode, SerdeJson, Str},
|
||||
@@ -928,10 +928,8 @@ impl PromptLibrary {
|
||||
status: cx.theme().status().clone(),
|
||||
inlay_hints_style:
|
||||
editor::make_inlay_hints_style(cx),
|
||||
suggestions_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().predictive),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
inline_completion_styles:
|
||||
editor::make_suggestion_styles(cx),
|
||||
..EditorStyle::default()
|
||||
},
|
||||
)),
|
||||
|
||||
@@ -42,10 +42,10 @@ serde_derive.workspace = true
|
||||
settings.workspace = true
|
||||
util.workspace = true
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
[target.'cfg(any())'.dependencies]
|
||||
livekit_client_macos = { workspace = true }
|
||||
|
||||
[target.'cfg(not(target_os = "macos"))'.dependencies]
|
||||
[target.'cfg(all())'.dependencies]
|
||||
livekit_client = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
pub mod call_settings;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(any())]
|
||||
mod macos;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(any())]
|
||||
pub use macos::*;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(all())]
|
||||
mod cross_platform;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(all())]
|
||||
pub use cross_platform::*;
|
||||
|
||||
@@ -1441,7 +1441,7 @@ impl Room {
|
||||
let sources = sources.await??;
|
||||
let source = sources.first().ok_or_else(|| anyhow!("no display found"))?;
|
||||
|
||||
let (track, stream) = capture_local_video_track(&**source).await?;
|
||||
let (track, stream) = capture_local_video_track(&**source, None).await?;
|
||||
|
||||
let publication = participant
|
||||
.publish_track(
|
||||
|
||||
@@ -2078,17 +2078,7 @@ async fn test_mute_deafen(
|
||||
audio_tracks_playing: participant
|
||||
.audio_tracks
|
||||
.values()
|
||||
.map({
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
|track| track.is_playing()
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
|(track, _)| track.rtc_track().enabled()
|
||||
}
|
||||
})
|
||||
.map(|(track, _)| track.rtc_track().enabled())
|
||||
.collect(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
|
||||
@@ -535,10 +535,16 @@ pub(crate) struct Highlights<'a> {
|
||||
pub styles: HighlightStyles,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct InlineCompletionStyles {
|
||||
pub insertion: HighlightStyle,
|
||||
pub whitespace: HighlightStyle,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
pub struct HighlightStyles {
|
||||
pub inlay_hint: Option<HighlightStyle>,
|
||||
pub suggestion: Option<HighlightStyle>,
|
||||
pub inline_completion: Option<InlineCompletionStyles>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -859,7 +865,7 @@ impl DisplaySnapshot {
|
||||
language_aware,
|
||||
HighlightStyles {
|
||||
inlay_hint: Some(editor_style.inlay_hints_style),
|
||||
suggestion: Some(editor_style.suggestions_style),
|
||||
inline_completion: Some(editor_style.inline_completion_styles),
|
||||
},
|
||||
)
|
||||
.flat_map(|chunk| {
|
||||
|
||||
@@ -62,9 +62,9 @@ impl Inlay {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn suggestion<T: Into<Rope>>(id: usize, position: Anchor, text: T) -> Self {
|
||||
pub fn inline_completion<T: Into<Rope>>(id: usize, position: Anchor, text: T) -> Self {
|
||||
Self {
|
||||
id: InlayId::Suggestion(id),
|
||||
id: InlayId::InlineCompletion(id),
|
||||
position,
|
||||
text: text.into(),
|
||||
}
|
||||
@@ -346,7 +346,15 @@ impl<'a> Iterator for InlayChunks<'a> {
|
||||
}
|
||||
|
||||
let mut highlight_style = match inlay.id {
|
||||
InlayId::Suggestion(_) => self.highlight_styles.suggestion,
|
||||
InlayId::InlineCompletion(_) => {
|
||||
self.highlight_styles.inline_completion.map(|s| {
|
||||
if inlay.text.chars().all(|c| c.is_whitespace()) {
|
||||
s.whitespace
|
||||
} else {
|
||||
s.insertion
|
||||
}
|
||||
})
|
||||
}
|
||||
InlayId::Hint(_) => self.highlight_styles.inlay_hint,
|
||||
};
|
||||
let next_inlay_highlight_endpoint;
|
||||
@@ -693,7 +701,7 @@ impl InlayMap {
|
||||
let inlay_id = if i % 2 == 0 {
|
||||
InlayId::Hint(post_inc(next_inlay_id))
|
||||
} else {
|
||||
InlayId::Suggestion(post_inc(next_inlay_id))
|
||||
InlayId::InlineCompletion(post_inc(next_inlay_id))
|
||||
};
|
||||
log::info!(
|
||||
"creating inlay {:?} at buffer offset {} with bias {:?} and text {:?}",
|
||||
@@ -1389,7 +1397,7 @@ mod tests {
|
||||
text: "|123|".into(),
|
||||
},
|
||||
Inlay {
|
||||
id: InlayId::Suggestion(post_inc(&mut next_inlay_id)),
|
||||
id: InlayId::InlineCompletion(post_inc(&mut next_inlay_id)),
|
||||
position: buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
text: "|456|".into(),
|
||||
},
|
||||
@@ -1605,7 +1613,7 @@ mod tests {
|
||||
text: "|456|".into(),
|
||||
},
|
||||
Inlay {
|
||||
id: InlayId::Suggestion(post_inc(&mut next_inlay_id)),
|
||||
id: InlayId::InlineCompletion(post_inc(&mut next_inlay_id)),
|
||||
position: buffer.read(cx).snapshot(cx).anchor_before(7),
|
||||
text: "\n|567|\n".into(),
|
||||
},
|
||||
|
||||
@@ -259,14 +259,14 @@ pub fn render_parsed_markdown(
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) enum InlayId {
|
||||
Suggestion(usize),
|
||||
InlineCompletion(usize),
|
||||
Hint(usize),
|
||||
}
|
||||
|
||||
impl InlayId {
|
||||
fn id(&self) -> usize {
|
||||
match self {
|
||||
Self::Suggestion(id) => *id,
|
||||
Self::InlineCompletion(id) => *id,
|
||||
Self::Hint(id) => *id,
|
||||
}
|
||||
}
|
||||
@@ -405,7 +405,7 @@ pub struct EditorStyle {
|
||||
pub syntax: Arc<SyntaxTheme>,
|
||||
pub status: StatusColors,
|
||||
pub inlay_hints_style: HighlightStyle,
|
||||
pub suggestions_style: HighlightStyle,
|
||||
pub inline_completion_styles: InlineCompletionStyles,
|
||||
pub unnecessary_code_fade: f32,
|
||||
}
|
||||
|
||||
@@ -422,7 +422,10 @@ impl Default for EditorStyle {
|
||||
// style and retrieve them directly from the theme.
|
||||
status: StatusColors::dark(),
|
||||
inlay_hints_style: HighlightStyle::default(),
|
||||
suggestions_style: HighlightStyle::default(),
|
||||
inline_completion_styles: InlineCompletionStyles {
|
||||
insertion: HighlightStyle::default(),
|
||||
whitespace: HighlightStyle::default(),
|
||||
},
|
||||
unnecessary_code_fade: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -440,6 +443,19 @@ pub fn make_inlay_hints_style(cx: &WindowContext) -> HighlightStyle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_suggestion_styles(cx: &WindowContext) -> InlineCompletionStyles {
|
||||
InlineCompletionStyles {
|
||||
insertion: HighlightStyle {
|
||||
color: Some(cx.theme().status().predictive),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
whitespace: HighlightStyle {
|
||||
background_color: Some(cx.theme().status().created_background),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type CompletionId = usize;
|
||||
|
||||
enum InlineCompletion {
|
||||
@@ -4735,7 +4751,7 @@ impl Editor {
|
||||
{
|
||||
let mut inlays = Vec::new();
|
||||
for (range, new_text) in &edits {
|
||||
let inlay = Inlay::suggestion(
|
||||
let inlay = Inlay::inline_completion(
|
||||
post_inc(&mut self.next_inlay_id),
|
||||
range.start,
|
||||
new_text.as_str(),
|
||||
@@ -9901,10 +9917,9 @@ impl Editor {
|
||||
font_weight: Some(FontWeight::BOLD),
|
||||
..make_inlay_hints_style(cx)
|
||||
},
|
||||
suggestions_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().predictive),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
inline_completion_styles: make_suggestion_styles(
|
||||
cx,
|
||||
),
|
||||
..EditorStyle::default()
|
||||
},
|
||||
))
|
||||
@@ -13905,10 +13920,7 @@ impl Render for Editor {
|
||||
syntax: cx.theme().syntax().clone(),
|
||||
status: cx.theme().status().clone(),
|
||||
inlay_hints_style: make_inlay_hints_style(cx),
|
||||
suggestions_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().predictive),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
inline_completion_styles: make_suggestion_styles(cx),
|
||||
unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -841,12 +841,12 @@ mod tests {
|
||||
.flat_map(|offset| {
|
||||
[
|
||||
Inlay {
|
||||
id: InlayId::Suggestion(post_inc(&mut id)),
|
||||
id: InlayId::InlineCompletion(post_inc(&mut id)),
|
||||
position: buffer_snapshot.anchor_at(offset, Bias::Left),
|
||||
text: "test".into(),
|
||||
},
|
||||
Inlay {
|
||||
id: InlayId::Suggestion(post_inc(&mut id)),
|
||||
id: InlayId::InlineCompletion(post_inc(&mut id)),
|
||||
position: buffer_snapshot.anchor_at(offset, Bias::Right),
|
||||
text: "test".into(),
|
||||
},
|
||||
|
||||
@@ -239,7 +239,7 @@ pub trait PlatformDisplay: Send + Sync + Debug {
|
||||
/// A source of on-screen video content that can be captured.
|
||||
pub trait ScreenCaptureSource {
|
||||
/// Returns the video resolution of this source.
|
||||
fn resolution(&self) -> Result<Size<Pixels>>;
|
||||
fn resolution(&self) -> Size<DevicePixels>;
|
||||
|
||||
/// Start capture video from this source, invoking the given callback
|
||||
/// with each frame.
|
||||
@@ -253,6 +253,7 @@ pub trait ScreenCaptureSource {
|
||||
pub trait ScreenCaptureStream {}
|
||||
|
||||
/// A frame of video captured from a screen.
|
||||
#[derive(Clone)]
|
||||
pub struct ScreenCaptureFrame(pub PlatformScreenCaptureFrame);
|
||||
|
||||
/// An opaque identifier for a hardware display
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
platform::{ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream},
|
||||
px, size, Pixels, Size,
|
||||
size, DevicePixels, Size,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use block::ConcreteBlock;
|
||||
@@ -9,6 +9,10 @@ use cocoa::{
|
||||
foundation::NSArray,
|
||||
};
|
||||
use core_foundation::base::TCFType;
|
||||
use core_graphics::display::{
|
||||
CGDirectDisplayID, CGDisplayCopyDisplayMode, CGDisplayModeGetPixelHeight,
|
||||
CGDisplayModeGetPixelWidth, CGDisplayModeRelease,
|
||||
};
|
||||
use ctor::ctor;
|
||||
use futures::channel::oneshot;
|
||||
use media::core_media::{CMSampleBuffer, CMSampleBufferRef};
|
||||
@@ -25,6 +29,7 @@ use std::{cell::RefCell, ffi::c_void, mem, ptr, rc::Rc};
|
||||
#[derive(Clone)]
|
||||
pub struct MacScreenCaptureSource {
|
||||
sc_display: id,
|
||||
size: Size<DevicePixels>,
|
||||
}
|
||||
|
||||
pub struct MacScreenCaptureStream {
|
||||
@@ -43,12 +48,8 @@ const FRAME_CALLBACK_IVAR: &str = "frame_callback";
|
||||
const SCStreamOutputTypeScreen: NSInteger = 0;
|
||||
|
||||
impl ScreenCaptureSource for MacScreenCaptureSource {
|
||||
fn resolution(&self) -> Result<Size<Pixels>> {
|
||||
unsafe {
|
||||
let width: i64 = msg_send![self.sc_display, width];
|
||||
let height: i64 = msg_send![self.sc_display, height];
|
||||
Ok(size(px(width as f32), px(height as f32)))
|
||||
}
|
||||
fn resolution(&self) -> Size<DevicePixels> {
|
||||
self.size
|
||||
}
|
||||
|
||||
fn stream(
|
||||
@@ -61,13 +62,21 @@ impl ScreenCaptureSource for MacScreenCaptureSource {
|
||||
let configuration: id = msg_send![class!(SCStreamConfiguration), alloc];
|
||||
let delegate: id = msg_send![DELEGATE_CLASS, alloc];
|
||||
let output: id = msg_send![OUTPUT_CLASS, alloc];
|
||||
|
||||
let excluded_windows = NSArray::array(nil);
|
||||
let filter: id = msg_send![filter, initWithDisplay:self.sc_display excludingWindows:excluded_windows];
|
||||
let configuration: id = msg_send![configuration, init];
|
||||
let delegate: id = msg_send![delegate, init];
|
||||
let output: id = msg_send![output, init];
|
||||
|
||||
// ASCII for '420f': https://developer.apple.com/documentation/screencapturekit/scstreamconfiguration/pixelformat?language=objc
|
||||
let format = u32::from_be_bytes([52u8, 50u8, 48u8, 102u8]);
|
||||
|
||||
let _: () = msg_send![configuration, setShowsCursor:YES];
|
||||
let _: () = msg_send![configuration, setWidth:self.size.width];
|
||||
let _: () = msg_send![configuration, setHeight:self.size.height];
|
||||
let _: () = msg_send![configuration, setPixelFormat:format];
|
||||
let _: () = msg_send![configuration, setQueueDepth:5i32];
|
||||
|
||||
output.as_mut().unwrap().set_ivar(
|
||||
FRAME_CALLBACK_IVAR,
|
||||
Box::into_raw(Box::new(frame_callback)) as *mut c_void,
|
||||
@@ -94,6 +103,7 @@ impl ScreenCaptureSource for MacScreenCaptureSource {
|
||||
sc_stream: stream,
|
||||
sc_stream_output: output,
|
||||
};
|
||||
|
||||
Ok(Box::new(stream) as Box<dyn ScreenCaptureStream>)
|
||||
} else {
|
||||
let message: id = msg_send![error, localizedDescription];
|
||||
@@ -159,8 +169,16 @@ pub(crate) fn get_sources() -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptur
|
||||
let mut result = Vec::new();
|
||||
for i in 0..displays.count() {
|
||||
let display = displays.objectAtIndex(i);
|
||||
let display: id = msg_send![display, retain];
|
||||
let display_id: CGDirectDisplayID = msg_send![display, displayID];
|
||||
let display_mode_ref = CGDisplayCopyDisplayMode(display_id);
|
||||
let width = CGDisplayModeGetPixelWidth(display_mode_ref);
|
||||
let height = CGDisplayModeGetPixelHeight(display_mode_ref);
|
||||
CGDisplayModeRelease(display_mode_ref);
|
||||
|
||||
let source = MacScreenCaptureSource {
|
||||
sc_display: msg_send![display, retain],
|
||||
sc_display: display,
|
||||
size: size(DevicePixels(width as i32), DevicePixels(height as i32)),
|
||||
};
|
||||
result.push(Box::new(source) as Box<dyn ScreenCaptureSource>);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::{
|
||||
px, size, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, ForegroundExecutor,
|
||||
Keymap, Platform, PlatformDisplay, PlatformTextSystem, ScreenCaptureFrame, ScreenCaptureSource,
|
||||
ScreenCaptureStream, Task, TestDisplay, TestWindow, WindowAppearance, WindowParams,
|
||||
size, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DevicePixels,
|
||||
ForegroundExecutor, Keymap, Platform, PlatformDisplay, PlatformTextSystem, ScreenCaptureFrame,
|
||||
ScreenCaptureSource, ScreenCaptureStream, Task, TestDisplay, TestWindow, WindowAppearance,
|
||||
WindowParams,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use collections::VecDeque;
|
||||
@@ -46,8 +47,8 @@ pub struct TestScreenCaptureSource {}
|
||||
pub struct TestScreenCaptureStream {}
|
||||
|
||||
impl ScreenCaptureSource for TestScreenCaptureSource {
|
||||
fn resolution(&self) -> Result<crate::Size<crate::Pixels>> {
|
||||
Ok(size(px(1.), px(1.)))
|
||||
fn resolution(&self) -> crate::Size<crate::DevicePixels> {
|
||||
size(DevicePixels(1), DevicePixels(1))
|
||||
}
|
||||
|
||||
fn stream(
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
; Identifier naming conventions; these "soft conventions" should stay at the top of the file as they're often overridden
|
||||
|
||||
; CamelCase for classes
|
||||
((identifier) @type.class
|
||||
(#match? @type.class "^_*[A-Z][A-Za-z0-9_]*$"))
|
||||
|
||||
; ALL_CAPS for constants:
|
||||
((identifier) @constant
|
||||
(#match? @constant "^_*[A-Z][A-Z0-9_]*$"))
|
||||
|
||||
(attribute attribute: (identifier) @property)
|
||||
(type (identifier) @type)
|
||||
(generic_type (identifier) @type)
|
||||
(comment) @comment
|
||||
(string) @string
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
; Type alias
|
||||
(type_alias_statement "type" @keyword)
|
||||
|
||||
; Identifier naming conventions
|
||||
|
||||
((identifier) @type.class
|
||||
(#match? @type.class "^[A-Z]"))
|
||||
|
||||
((identifier) @constant
|
||||
(#match? @constant "^_*[A-Z][A-Z\\d_]*$"))
|
||||
|
||||
; TypeVar with constraints in type parameters
|
||||
(type
|
||||
(tuple (identifier) @type)
|
||||
@@ -26,15 +31,20 @@
|
||||
|
||||
; Function calls
|
||||
|
||||
(decorator
|
||||
"@" @punctuation.special
|
||||
(identifier) @function.decorator)
|
||||
|
||||
(call
|
||||
function: (attribute attribute: (identifier) @function.method.call))
|
||||
(call
|
||||
function: (identifier) @function.call)
|
||||
|
||||
(decorator
|
||||
"@" @punctuation.special
|
||||
[
|
||||
(identifier) @function.decorator
|
||||
(attribute attribute: (identifier) @function.decorator)
|
||||
(call function: (identifier) @function.decorator.call)
|
||||
(call (attribute attribute: (identifier) @function.decorator.call))
|
||||
])
|
||||
|
||||
; Function and class definitions
|
||||
|
||||
(function_definition
|
||||
@@ -47,9 +57,9 @@
|
||||
|
||||
(call
|
||||
function: (identifier) @type.class.call
|
||||
(#match? @type.class.call "^[A-Z][A-Z0-9_]*[a-z]"))
|
||||
(#match? @type.class.call "^_*[A-Z][A-Za-z0-9_]*$"))
|
||||
|
||||
; Builtin functions
|
||||
; Builtins
|
||||
|
||||
((call
|
||||
function: (identifier) @function.builtin)
|
||||
@@ -57,6 +67,9 @@
|
||||
@function.builtin
|
||||
"^(abs|all|any|ascii|bin|bool|breakpoint|bytearray|bytes|callable|chr|classmethod|compile|complex|delattr|dict|dir|divmod|enumerate|eval|exec|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|vars|zip|__import__)$"))
|
||||
|
||||
((identifier) @type.builtin
|
||||
(#any-of? @type.builtin "int" "float" "complex" "bool" "list" "tuple" "range" "str" "bytes" "bytearray" "memoryview" "set" "frozenset" "dict"))
|
||||
|
||||
; Literals
|
||||
|
||||
[
|
||||
@@ -79,10 +92,6 @@
|
||||
(#match? @variable.special "^self|cls$")
|
||||
]
|
||||
|
||||
(comment) @comment
|
||||
(string) @string
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
@@ -114,7 +123,10 @@
|
||||
. (expression_statement (string) @string.doc))
|
||||
|
||||
(module
|
||||
(expression_statement (assignment))
|
||||
[
|
||||
(expression_statement (assignment))
|
||||
(type_alias_statement)
|
||||
]
|
||||
. (expression_statement (string) @string.doc))
|
||||
|
||||
(class_definition
|
||||
@@ -163,6 +175,9 @@
|
||||
">>"
|
||||
"|"
|
||||
"~"
|
||||
] @operator
|
||||
|
||||
[
|
||||
"and"
|
||||
"in"
|
||||
"is"
|
||||
@@ -170,7 +185,7 @@
|
||||
"or"
|
||||
"is not"
|
||||
"not in"
|
||||
] @operator
|
||||
] @keyword.operator
|
||||
|
||||
[
|
||||
"as"
|
||||
@@ -185,6 +200,7 @@
|
||||
"elif"
|
||||
"else"
|
||||
"except"
|
||||
"except*"
|
||||
"exec"
|
||||
"finally"
|
||||
"for"
|
||||
|
||||
@@ -49,6 +49,7 @@ livekit.workspace = true
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation.workspace = true
|
||||
coreaudio-rs = "0.12.1"
|
||||
media.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
collections = { workspace = true, features = ["test-support"] }
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
// it causes compile errors.
|
||||
#![cfg_attr(target_os = "macos", allow(unused_imports))]
|
||||
|
||||
use futures::StreamExt;
|
||||
use gpui::{
|
||||
actions, bounds, div, point,
|
||||
prelude::{FluentBuilder as _, IntoElement},
|
||||
px, rgb, size, AsyncAppContext, Bounds, InteractiveElement, KeyBinding, Menu, MenuItem,
|
||||
ParentElement, Pixels, Render, ScreenCaptureStream, SharedString,
|
||||
ParentElement, Pixels, Render, ScreenCaptureFrame, ScreenCaptureStream, SharedString,
|
||||
StatefulInteractiveElement as _, Styled, Task, View, ViewContext, VisualContext, WindowBounds,
|
||||
WindowHandle, WindowOptions,
|
||||
};
|
||||
@@ -22,6 +23,7 @@ use livekit_client::{
|
||||
track::{LocalTrack, RemoteTrack, RemoteVideoTrack, TrackSource},
|
||||
AudioStream, RemoteVideoTrackView, Room, RoomEvent, RoomOptions,
|
||||
};
|
||||
use media::core_video::CVImageBuffer;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use postage::stream::Stream;
|
||||
|
||||
@@ -108,6 +110,7 @@ struct LivekitWindow {
|
||||
screen_share_track: Option<LocalTrackPublication>,
|
||||
microphone_stream: Option<AudioStream>,
|
||||
screen_share_stream: Option<Box<dyn ScreenCaptureStream>>,
|
||||
latest_self_frame: Option<ScreenCaptureFrame>,
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
remote_participants: Vec<(ParticipantIdentity, ParticipantState)>,
|
||||
_events_task: Task<()>,
|
||||
@@ -156,6 +159,7 @@ impl LivekitWindow {
|
||||
microphone_stream: None,
|
||||
screen_share_track: None,
|
||||
screen_share_stream: None,
|
||||
latest_self_frame: None,
|
||||
remote_participants: Vec::new(),
|
||||
_events_task,
|
||||
}
|
||||
@@ -312,7 +316,25 @@ impl LivekitWindow {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let sources = sources.await.unwrap()?;
|
||||
let source = sources.into_iter().next().unwrap();
|
||||
let (track, stream) = capture_local_video_track(&*source).await?;
|
||||
|
||||
let (self_stream_tx, mut self_stream_rx) = futures::channel::mpsc::unbounded();
|
||||
let (track, stream) =
|
||||
capture_local_video_track(&*source, Some(self_stream_tx)).await?;
|
||||
|
||||
cx.spawn({
|
||||
let this = this.clone();
|
||||
|mut cx| async move {
|
||||
while let Some(frame) = self_stream_rx.next().await {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.latest_self_frame = Some(frame);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
let publication = participant
|
||||
.publish_track(
|
||||
LocalTrack::Video(track),
|
||||
@@ -394,6 +416,11 @@ impl Render for LivekitWindow {
|
||||
.on_click(cx.listener(|this, _, cx| this.toggle_screen_share(cx))),
|
||||
]),
|
||||
)
|
||||
.children(
|
||||
self.latest_self_frame
|
||||
.as_ref()
|
||||
.map(|frame| gpui::surface(frame.0.clone()).size_full()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.id("remote-participants")
|
||||
@@ -403,7 +430,7 @@ impl Render for LivekitWindow {
|
||||
.flex_grow()
|
||||
.children(self.remote_participants.iter().map(|(identity, state)| {
|
||||
div()
|
||||
.h(px(300.0))
|
||||
.size_full()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.m_2()
|
||||
|
||||
@@ -142,8 +142,9 @@ pub fn init(
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub async fn capture_local_video_track(
|
||||
capture_source: &dyn ScreenCaptureSource,
|
||||
show_capture: Option<futures::channel::mpsc::UnboundedSender<ScreenCaptureFrame>>,
|
||||
) -> Result<(track::LocalVideoTrack, Box<dyn ScreenCaptureStream>)> {
|
||||
let resolution = capture_source.resolution()?;
|
||||
let resolution = capture_source.resolution();
|
||||
let track_source = NativeVideoSource::new(VideoResolution {
|
||||
width: resolution.width.0 as u32,
|
||||
height: resolution.height.0 as u32,
|
||||
@@ -153,6 +154,10 @@ pub async fn capture_local_video_track(
|
||||
.stream({
|
||||
let track_source = track_source.clone();
|
||||
Box::new(move |frame| {
|
||||
if let Some(show_capture) = show_capture.as_ref() {
|
||||
show_capture.unbounded_send(frame.clone()).unwrap();
|
||||
}
|
||||
|
||||
if let Some(buffer) = video_frame_buffer_to_webrtc(frame) {
|
||||
track_source.capture_frame(&VideoFrame {
|
||||
rotation: VideoRotation::VideoRotation0,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(any())]
|
||||
mod macos;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(any())]
|
||||
pub use macos::*;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(all())]
|
||||
mod cross_platform;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(all())]
|
||||
pub use cross_platform::*;
|
||||
|
||||
@@ -18,6 +18,7 @@ test-support = []
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
arrayvec.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
editor.workspace = true
|
||||
|
||||
@@ -3,6 +3,7 @@ mod rate_completion_modal;
|
||||
pub use rate_completion_modal::*;
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use arrayvec::ArrayVec;
|
||||
use client::Client;
|
||||
use collections::{HashMap, HashSet, VecDeque};
|
||||
use futures::AsyncReadExt;
|
||||
@@ -798,7 +799,7 @@ fn prompt_for_excerpt(
|
||||
}
|
||||
|
||||
fn excerpt_range_for_position(point: Point, snapshot: &BufferSnapshot) -> Range<usize> {
|
||||
const CONTEXT_LINES: u32 = 16;
|
||||
const CONTEXT_LINES: u32 = 32;
|
||||
|
||||
let mut context_lines_before = CONTEXT_LINES;
|
||||
let mut context_lines_after = CONTEXT_LINES;
|
||||
@@ -899,10 +900,15 @@ impl CurrentInlineCompletion {
|
||||
}
|
||||
}
|
||||
|
||||
struct PendingCompletion {
|
||||
id: usize,
|
||||
_task: Task<Result<()>>,
|
||||
}
|
||||
|
||||
pub struct ZetaInlineCompletionProvider {
|
||||
zeta: Model<Zeta>,
|
||||
first_pending_completion: Option<Task<Result<()>>>,
|
||||
last_pending_completion: Option<Task<Result<()>>>,
|
||||
pending_completions: ArrayVec<PendingCompletion, 2>,
|
||||
next_pending_completion_id: usize,
|
||||
current_completion: Option<CurrentInlineCompletion>,
|
||||
}
|
||||
|
||||
@@ -912,8 +918,8 @@ impl ZetaInlineCompletionProvider {
|
||||
pub fn new(zeta: Model<Zeta>) -> Self {
|
||||
Self {
|
||||
zeta,
|
||||
first_pending_completion: None,
|
||||
last_pending_completion: None,
|
||||
pending_completions: ArrayVec::new(),
|
||||
next_pending_completion_id: 0,
|
||||
current_completion: None,
|
||||
}
|
||||
}
|
||||
@@ -944,7 +950,9 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
|
||||
debounce: bool,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
let is_first = self.first_pending_completion.is_none();
|
||||
let pending_completion_id = self.next_pending_completion_id;
|
||||
self.next_pending_completion_id += 1;
|
||||
|
||||
let task = cx.spawn(|this, mut cx| async move {
|
||||
if debounce {
|
||||
cx.background_executor().timer(Self::DEBOUNCE_TIMEOUT).await;
|
||||
@@ -965,9 +973,10 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.first_pending_completion = None;
|
||||
if !is_first {
|
||||
this.last_pending_completion = None;
|
||||
if this.pending_completions[0].id == pending_completion_id {
|
||||
this.pending_completions.remove(0);
|
||||
} else {
|
||||
this.pending_completions.clear();
|
||||
}
|
||||
|
||||
if let Some(new_completion) = completion {
|
||||
@@ -993,10 +1002,19 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
|
||||
})
|
||||
});
|
||||
|
||||
if is_first {
|
||||
self.first_pending_completion = Some(task);
|
||||
} else {
|
||||
self.last_pending_completion = Some(task);
|
||||
// We always maintain at most two pending completions. When we already
|
||||
// have two, we replace the newest one.
|
||||
if self.pending_completions.len() <= 1 {
|
||||
self.pending_completions.push(PendingCompletion {
|
||||
id: pending_completion_id,
|
||||
_task: task,
|
||||
});
|
||||
} else if self.pending_completions.len() == 2 {
|
||||
self.pending_completions.pop();
|
||||
self.pending_completions.push(PendingCompletion {
|
||||
id: pending_completion_id,
|
||||
_task: task,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1011,13 +1029,11 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide
|
||||
}
|
||||
|
||||
fn accept(&mut self, _cx: &mut ModelContext<Self>) {
|
||||
self.first_pending_completion.take();
|
||||
self.last_pending_completion.take();
|
||||
self.pending_completions.clear();
|
||||
}
|
||||
|
||||
fn discard(&mut self, _cx: &mut ModelContext<Self>) {
|
||||
self.first_pending_completion.take();
|
||||
self.last_pending_completion.take();
|
||||
self.pending_completions.clear();
|
||||
self.current_completion.take();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user