From 86247bf657b3643cd81999c95f1cfb6c43c3f999 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:48:36 +0200 Subject: [PATCH 001/104] editor: Highlight search results Z-1292 --- assets/settings/default.json | 4 +- crates/editor/src/editor_settings.rs | 2 + crates/editor/src/element.rs | 47 ++- crates/theme/src/theme.rs | 1 + styles/src/styleTree/editor.ts | 531 ++++++++++++++------------- 5 files changed, 317 insertions(+), 268 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index bd73bcbf08..8576c1ed65 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -71,7 +71,9 @@ // "never" "show": "auto", // Whether to show git diff indicators in the scrollbar. - "git_diff": true + "git_diff": true, + // Whether to show selections in the scrollbar. + "selections": true }, "project_panel": { // Whether to show the git status in the project panel. diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index 387d4d2c34..f4499b5651 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -15,6 +15,7 @@ pub struct EditorSettings { pub struct Scrollbar { pub show: ShowScrollbar, pub git_diff: bool, + pub selections: bool, } #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -39,6 +40,7 @@ pub struct EditorSettingsContent { pub struct ScrollbarContent { pub show: Option, pub git_diff: Option, + pub selections: Option, } impl Setting for EditorSettings { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index d6f9a2e906..5f7843f721 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1008,6 +1008,7 @@ impl EditorElement { bounds: RectF, layout: &mut LayoutState, cx: &mut ViewContext, + editor: &Editor, ) { enum ScrollbarMouseHandlers {} if layout.mode != EditorMode::Full { @@ -1050,9 +1051,49 @@ impl EditorElement { background: style.track.background_color, ..Default::default() }); + let scrollbar_settings = settings::get::(cx).scrollbar; + let theme = theme::current(cx); + let scrollbar_theme = &theme.editor.scrollbar; + if layout.is_singleton && scrollbar_settings.selections { + let start_anchor = Anchor::min(); + let end_anchor = Anchor::max(); + for (row, _) in &editor.background_highlights_in_range( + start_anchor..end_anchor, + &layout.position_map.snapshot, + &theme, + ) { + let start_display = row.start; + let end_display = row.end; + let start_y = y_for_row(start_display.row() as f32); + let mut end_y = y_for_row((end_display.row()) as f32); + if end_y - start_y < 1. { + end_y = start_y + 1.; + } + let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); - if layout.is_singleton && settings::get::(cx).scrollbar.git_diff { - let diff_style = theme::current(cx).editor.scrollbar.git.clone(); + let color = scrollbar_theme.selections; + + let border = Border { + width: 1., + color: style.thumb.border.color, + overlay: false, + top: false, + right: true, + bottom: false, + left: true, + }; + + scene.push_quad(Quad { + bounds, + background: Some(color), + border, + corner_radius: style.thumb.corner_radius, + }) + } + } + + if layout.is_singleton && scrollbar_settings.git_diff { + let diff_style = scrollbar_theme.git.clone(); for hunk in layout .position_map .snapshot @@ -2359,7 +2400,7 @@ impl Element for EditorElement { if !layout.blocks.is_empty() { self.paint_blocks(scene, bounds, visible_bounds, layout, editor, cx); } - self.paint_scrollbar(scene, bounds, layout, cx); + self.paint_scrollbar(scene, bounds, layout, cx, &editor); scene.pop_layer(); scene.pop_layer(); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index c7563ec87a..95d6348c62 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -700,6 +700,7 @@ pub struct Scrollbar { pub width: f32, pub min_height_factor: f32, pub git: GitDiffColors, + pub selections: Color, } #[derive(Clone, Deserialize, Default)] diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 55f3da6e90..859f9fe1b9 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -6,273 +6,276 @@ import hoverPopover from "./hoverPopover" import { buildSyntax } from "../theme/syntax" export default function editor(colorScheme: ColorScheme) { - const { isLight } = colorScheme + const { isLight } = colorScheme - let layer = colorScheme.highest + let layer = colorScheme.highest - const autocompleteItem = { - cornerRadius: 6, - padding: { - bottom: 2, - left: 6, - right: 6, - top: 2, - }, - } - - function diagnostic(layer: Layer, styleSet: StyleSets) { - return { - textScaleFactor: 0.857, - header: { - border: border(layer, { - top: true, - }), - }, - message: { - text: text(layer, "sans", styleSet, "default", { size: "sm" }), - highlightText: text(layer, "sans", styleSet, "default", { - size: "sm", - weight: "bold", - }), - }, - } - } - - const syntax = buildSyntax(colorScheme) + const autocompleteItem = { + cornerRadius: 6, + padding: { + bottom: 2, + left: 6, + right: 6, + top: 2, + }, + } + function diagnostic(layer: Layer, styleSet: StyleSets) { return { - textColor: syntax.primary.color, - background: background(layer), - activeLineBackground: withOpacity(background(layer, "on"), 0.75), - highlightedLineBackground: background(layer, "on"), - // Inline autocomplete suggestions, Co-pilot suggestions, etc. - suggestion: syntax.predictive, - codeActions: { - indicator: { - color: foreground(layer, "variant"), - - clicked: { - color: foreground(layer, "base"), - }, - hover: { - color: foreground(layer, "on"), - }, - active: { - color: foreground(layer, "on"), - }, - }, - verticalScale: 0.55, - }, - folds: { - iconMarginScale: 2.5, - foldedIcon: "icons/chevron_right_8.svg", - foldableIcon: "icons/chevron_down_8.svg", - indicator: { - color: foreground(layer, "variant"), - - clicked: { - color: foreground(layer, "base"), - }, - hover: { - color: foreground(layer, "on"), - }, - active: { - color: foreground(layer, "on"), - }, - }, - ellipses: { - textColor: colorScheme.ramps.neutral(0.71).hex(), - cornerRadiusFactor: 0.15, - background: { - // Copied from hover_popover highlight - color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(), - - hover: { - color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(), - }, - - clicked: { - color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(), - }, - }, - }, - foldBackground: foreground(layer, "variant"), - }, - diff: { - deleted: isLight - ? colorScheme.ramps.red(0.5).hex() - : colorScheme.ramps.red(0.4).hex(), - modified: isLight - ? colorScheme.ramps.yellow(0.5).hex() - : colorScheme.ramps.yellow(0.5).hex(), - inserted: isLight - ? colorScheme.ramps.green(0.4).hex() - : colorScheme.ramps.green(0.5).hex(), - removedWidthEm: 0.275, - widthEm: 0.15, - cornerRadius: 0.05, - }, - /** Highlights matching occurrences of what is under the cursor - * as well as matched brackets - */ - documentHighlightReadBackground: withOpacity( - foreground(layer, "accent"), - 0.1 - ), - documentHighlightWriteBackground: colorScheme.ramps - .neutral(0.5) - .alpha(0.4) - .hex(), // TODO: This was blend * 2 - errorColor: background(layer, "negative"), - gutterBackground: background(layer), - gutterPaddingFactor: 3.5, - lineNumber: withOpacity(foreground(layer), 0.35), - lineNumberActive: foreground(layer), - renameFade: 0.6, - unnecessaryCodeFade: 0.5, - selection: colorScheme.players[0], - whitespace: colorScheme.ramps.neutral(0.5).hex(), - guestSelections: [ - colorScheme.players[1], - colorScheme.players[2], - colorScheme.players[3], - colorScheme.players[4], - colorScheme.players[5], - colorScheme.players[6], - colorScheme.players[7], - ], - autocomplete: { - background: background(colorScheme.middle), - cornerRadius: 8, - padding: 4, - margin: { - left: -14, - }, - border: border(colorScheme.middle), - shadow: colorScheme.popoverShadow, - matchHighlight: foreground(colorScheme.middle, "accent"), - item: autocompleteItem, - hoveredItem: { - ...autocompleteItem, - matchHighlight: foreground( - colorScheme.middle, - "accent", - "hovered" - ), - background: background(colorScheme.middle, "hovered"), - }, - selectedItem: { - ...autocompleteItem, - matchHighlight: foreground( - colorScheme.middle, - "accent", - "active" - ), - background: background(colorScheme.middle, "active"), - }, - }, - diagnosticHeader: { - background: background(colorScheme.middle), - iconWidthFactor: 1.5, - textScaleFactor: 0.857, - border: border(colorScheme.middle, { - bottom: true, - top: true, - }), - code: { - ...text(colorScheme.middle, "mono", { size: "sm" }), - margin: { - left: 10, - }, - }, - source: { - text: text(colorScheme.middle, "sans", { - size: "sm", - weight: "bold", - }), - }, - message: { - highlightText: text(colorScheme.middle, "sans", { - size: "sm", - weight: "bold", - }), - text: text(colorScheme.middle, "sans", { size: "sm" }), - }, - }, - diagnosticPathHeader: { - background: background(colorScheme.middle), - textScaleFactor: 0.857, - filename: text(colorScheme.middle, "mono", { size: "sm" }), - path: { - ...text(colorScheme.middle, "mono", { size: "sm" }), - margin: { - left: 12, - }, - }, - }, - errorDiagnostic: diagnostic(colorScheme.middle, "negative"), - warningDiagnostic: diagnostic(colorScheme.middle, "warning"), - informationDiagnostic: diagnostic(colorScheme.middle, "accent"), - hintDiagnostic: diagnostic(colorScheme.middle, "warning"), - invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"), - invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"), - invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"), - invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"), - hoverPopover: hoverPopover(colorScheme), - linkDefinition: { - color: syntax.linkUri.color, - underline: syntax.linkUri.underline, - }, - jumpIcon: { - color: foreground(layer, "on"), - iconWidth: 20, - buttonWidth: 20, - cornerRadius: 6, - padding: { - top: 6, - bottom: 6, - left: 6, - right: 6, - }, - hover: { - background: background(layer, "on", "hovered"), - }, - }, - scrollbar: { - width: 12, - minHeightFactor: 1.0, - track: { - border: border(layer, "variant", { left: true }), - }, - thumb: { - background: withOpacity(background(layer, "inverted"), 0.3), - border: { - width: 1, - color: borderColor(layer, "variant"), - top: false, - right: true, - left: true, - bottom: false, - }, - }, - git: { - deleted: isLight - ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8) - : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8), - modified: isLight - ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8) - : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8), - inserted: isLight - ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8) - : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8), - }, - }, - compositionMark: { - underline: { - thickness: 1.0, - color: borderColor(layer), - }, - }, - syntax, + textScaleFactor: 0.857, + header: { + border: border(layer, { + top: true, + }), + }, + message: { + text: text(layer, "sans", styleSet, "default", { size: "sm" }), + highlightText: text(layer, "sans", styleSet, "default", { + size: "sm", + weight: "bold", + }), + }, } + } + + const syntax = buildSyntax(colorScheme) + + return { + textColor: syntax.primary.color, + background: background(layer), + activeLineBackground: withOpacity(background(layer, "on"), 0.75), + highlightedLineBackground: background(layer, "on"), + // Inline autocomplete suggestions, Co-pilot suggestions, etc. + suggestion: syntax.predictive, + codeActions: { + indicator: { + color: foreground(layer, "variant"), + + clicked: { + color: foreground(layer, "base"), + }, + hover: { + color: foreground(layer, "on"), + }, + active: { + color: foreground(layer, "on"), + }, + }, + verticalScale: 0.55, + }, + folds: { + iconMarginScale: 2.5, + foldedIcon: "icons/chevron_right_8.svg", + foldableIcon: "icons/chevron_down_8.svg", + indicator: { + color: foreground(layer, "variant"), + + clicked: { + color: foreground(layer, "base"), + }, + hover: { + color: foreground(layer, "on"), + }, + active: { + color: foreground(layer, "on"), + }, + }, + ellipses: { + textColor: colorScheme.ramps.neutral(0.71).hex(), + cornerRadiusFactor: 0.15, + background: { + // Copied from hover_popover highlight + color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(), + + hover: { + color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(), + }, + + clicked: { + color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(), + }, + }, + }, + foldBackground: foreground(layer, "variant"), + }, + diff: { + deleted: isLight + ? colorScheme.ramps.red(0.5).hex() + : colorScheme.ramps.red(0.4).hex(), + modified: isLight + ? colorScheme.ramps.yellow(0.5).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.4).hex() + : colorScheme.ramps.green(0.5).hex(), + removedWidthEm: 0.275, + widthEm: 0.15, + cornerRadius: 0.05, + }, + /** Highlights matching occurrences of what is under the cursor + * as well as matched brackets + */ + documentHighlightReadBackground: withOpacity( + foreground(layer, "accent"), + 0.1 + ), + documentHighlightWriteBackground: colorScheme.ramps + .neutral(0.5) + .alpha(0.4) + .hex(), // TODO: This was blend * 2 + errorColor: background(layer, "negative"), + gutterBackground: background(layer), + gutterPaddingFactor: 3.5, + lineNumber: withOpacity(foreground(layer), 0.35), + lineNumberActive: foreground(layer), + renameFade: 0.6, + unnecessaryCodeFade: 0.5, + selection: colorScheme.players[0], + whitespace: colorScheme.ramps.neutral(0.5).hex(), + guestSelections: [ + colorScheme.players[1], + colorScheme.players[2], + colorScheme.players[3], + colorScheme.players[4], + colorScheme.players[5], + colorScheme.players[6], + colorScheme.players[7], + ], + autocomplete: { + background: background(colorScheme.middle), + cornerRadius: 8, + padding: 4, + margin: { + left: -14, + }, + border: border(colorScheme.middle), + shadow: colorScheme.popoverShadow, + matchHighlight: foreground(colorScheme.middle, "accent"), + item: autocompleteItem, + hoveredItem: { + ...autocompleteItem, + matchHighlight: foreground( + colorScheme.middle, + "accent", + "hovered" + ), + background: background(colorScheme.middle, "hovered"), + }, + selectedItem: { + ...autocompleteItem, + matchHighlight: foreground( + colorScheme.middle, + "accent", + "active" + ), + background: background(colorScheme.middle, "active"), + }, + }, + diagnosticHeader: { + background: background(colorScheme.middle), + iconWidthFactor: 1.5, + textScaleFactor: 0.857, + border: border(colorScheme.middle, { + bottom: true, + top: true, + }), + code: { + ...text(colorScheme.middle, "mono", { size: "sm" }), + margin: { + left: 10, + }, + }, + source: { + text: text(colorScheme.middle, "sans", { + size: "sm", + weight: "bold", + }), + }, + message: { + highlightText: text(colorScheme.middle, "sans", { + size: "sm", + weight: "bold", + }), + text: text(colorScheme.middle, "sans", { size: "sm" }), + }, + }, + diagnosticPathHeader: { + background: background(colorScheme.middle), + textScaleFactor: 0.857, + filename: text(colorScheme.middle, "mono", { size: "sm" }), + path: { + ...text(colorScheme.middle, "mono", { size: "sm" }), + margin: { + left: 12, + }, + }, + }, + errorDiagnostic: diagnostic(colorScheme.middle, "negative"), + warningDiagnostic: diagnostic(colorScheme.middle, "warning"), + informationDiagnostic: diagnostic(colorScheme.middle, "accent"), + hintDiagnostic: diagnostic(colorScheme.middle, "warning"), + invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"), + invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"), + invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"), + invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"), + hoverPopover: hoverPopover(colorScheme), + linkDefinition: { + color: syntax.linkUri.color, + underline: syntax.linkUri.underline, + }, + jumpIcon: { + color: foreground(layer, "on"), + iconWidth: 20, + buttonWidth: 20, + cornerRadius: 6, + padding: { + top: 6, + bottom: 6, + left: 6, + right: 6, + }, + hover: { + background: background(layer, "on", "hovered"), + }, + }, + scrollbar: { + width: 12, + minHeightFactor: 1.0, + track: { + border: border(layer, "variant", { left: true }), + }, + thumb: { + background: withOpacity(background(layer, "inverted"), 0.3), + border: { + width: 1, + color: borderColor(layer, "variant"), + top: false, + right: true, + left: true, + bottom: false, + }, + }, + git: { + deleted: isLight + ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8), + modified: isLight + ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8), + inserted: isLight + ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8), + }, + selections: isLight + ? withOpacity(colorScheme.ramps.blue(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.blue(0.4).hex(), 0.8) + }, + compositionMark: { + underline: { + thickness: 1.0, + color: borderColor(layer), + }, + }, + syntax, + } } From 18dd3102bfbda57411153d215cae110ea8cd8617 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 28 Jun 2023 09:29:49 -0700 Subject: [PATCH 002/104] WIP: Add click out event to fix context menus --- crates/context_menu/src/context_menu.rs | 27 +++++++++++--------- crates/gpui/src/app/window.rs | 6 ++++- crates/gpui/src/scene/mouse_event.rs | 22 +++++++++++++++++ crates/gpui/src/scene/mouse_region.rs | 33 ++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 13 deletions(-) diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index de78b51e9c..9bdf146da4 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -301,18 +301,23 @@ impl ContextMenu { cx: &mut ViewContext, ) { let mut items = items.into_iter().peekable(); - if items.peek().is_some() { - self.items = items.collect(); - self.anchor_position = anchor_position; - self.anchor_corner = anchor_corner; - self.visible = true; - self.show_count += 1; - if !cx.is_self_focused() { - self.previously_focused_view_id = cx.focused_view_id(); - } - cx.focus_self(); - } else { + dbg!(self.visible); + if (self.visible) { self.visible = false; + } else { + if items.peek().is_some() { + self.items = items.collect(); + self.anchor_position = anchor_position; + self.anchor_corner = anchor_corner; + self.visible = true; + self.show_count += 1; + if !cx.is_self_focused() { + self.previously_focused_view_id = cx.focused_view_id(); + } + cx.focus_self(); + } else { + self.visible = false; + } } cx.notify(); } diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index cffce6c3a6..cc6778c930 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -9,7 +9,7 @@ use crate::{ }, scene::{ CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, - MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene, + MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene, MouseClickOut, }, text_layout::TextLayoutCache, util::post_inc, @@ -524,6 +524,10 @@ impl<'a> WindowContext<'a> { region: Default::default(), platform_event: e.clone(), })); + mouse_events.push(MouseEvent::ClickOut(MouseClickOut { + region: Default::default(), + platform_event: e.clone(), + })); } Event::MouseMoved( diff --git a/crates/gpui/src/scene/mouse_event.rs b/crates/gpui/src/scene/mouse_event.rs index cf0a08f33e..a492da771b 100644 --- a/crates/gpui/src/scene/mouse_event.rs +++ b/crates/gpui/src/scene/mouse_event.rs @@ -99,6 +99,20 @@ impl Deref for MouseClick { } } +#[derive(Debug, Default, Clone)] +pub struct MouseClickOut { + pub region: RectF, + pub platform_event: MouseButtonEvent, +} + +impl Deref for MouseClickOut { + type Target = MouseButtonEvent; + + fn deref(&self) -> &Self::Target { + &self.platform_event + } +} + #[derive(Debug, Default, Clone)] pub struct MouseDownOut { pub region: RectF, @@ -150,6 +164,7 @@ pub enum MouseEvent { Down(MouseDown), Up(MouseUp), Click(MouseClick), + ClickOut(MouseClickOut), DownOut(MouseDownOut), UpOut(MouseUpOut), ScrollWheel(MouseScrollWheel), @@ -165,6 +180,7 @@ impl MouseEvent { MouseEvent::Down(r) => r.region = region, MouseEvent::Up(r) => r.region = region, MouseEvent::Click(r) => r.region = region, + MouseEvent::ClickOut(r) => r.region = region, MouseEvent::DownOut(r) => r.region = region, MouseEvent::UpOut(r) => r.region = region, MouseEvent::ScrollWheel(r) => r.region = region, @@ -182,6 +198,7 @@ impl MouseEvent { MouseEvent::Down(_) => true, MouseEvent::Up(_) => true, MouseEvent::Click(_) => true, + MouseEvent::ClickOut(_) => true, MouseEvent::DownOut(_) => false, MouseEvent::UpOut(_) => false, MouseEvent::ScrollWheel(_) => true, @@ -222,6 +239,10 @@ impl MouseEvent { discriminant(&MouseEvent::Click(Default::default())) } + pub fn click_out_disc() -> Discriminant { + discriminant(&MouseEvent::ClickOut(Default::default())) + } + pub fn down_out_disc() -> Discriminant { discriminant(&MouseEvent::DownOut(Default::default())) } @@ -239,6 +260,7 @@ impl MouseEvent { MouseEvent::Down(e) => HandlerKey::new(Self::down_disc(), Some(e.button)), MouseEvent::Up(e) => HandlerKey::new(Self::up_disc(), Some(e.button)), MouseEvent::Click(e) => HandlerKey::new(Self::click_disc(), Some(e.button)), + MouseEvent::ClickOut(e) => HandlerKey::new(Self::click_out_disc(), Some(e.button)), MouseEvent::UpOut(e) => HandlerKey::new(Self::up_out_disc(), Some(e.button)), MouseEvent::DownOut(e) => HandlerKey::new(Self::down_out_disc(), Some(e.button)), MouseEvent::ScrollWheel(_) => HandlerKey::new(Self::scroll_wheel_disc(), None), diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs index 0efc794148..7e1d5d6e1e 100644 --- a/crates/gpui/src/scene/mouse_region.rs +++ b/crates/gpui/src/scene/mouse_region.rs @@ -14,7 +14,7 @@ use super::{ MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, MouseMove, MouseUp, MouseUpOut, }, - MouseMoveOut, MouseScrollWheel, + MouseMoveOut, MouseScrollWheel, MouseClickOut, }; #[derive(Clone)] @@ -89,6 +89,15 @@ impl MouseRegion { self } + pub fn on_click_out(mut self, button: MouseButton, handler: F) -> Self + where + V: View, + F: Fn(MouseClickOut, &mut V, &mut EventContext) + 'static, + { + self.handlers = self.handlers.on_click(button, handler); + self + } + pub fn on_down_out(mut self, button: MouseButton, handler: F) -> Self where V: View, @@ -405,6 +414,28 @@ impl HandlerSet { self } + pub fn on_click_out(mut self, button: MouseButton, handler: F) -> Self + where + V: View, + F: Fn(MouseClickOut, &mut V, &mut EventContext) + 'static, + { + self.insert(MouseEvent::click_out_disc(), Some(button), + Rc::new(move |region_event, view, cx, view_id| { + if let MouseEvent::ClickOut(e) = region_event { + let view = view.downcast_mut().unwrap(); + let mut cx = ViewContext::mutable(cx, view_id); + let mut cx = EventContext::new(&mut cx); + handler(e, view, &mut cx); + cx.handled + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::ClickOut, found {:?}", + region_event); + } + })); + self + } + pub fn on_down_out(mut self, button: MouseButton, handler: F) -> Self where V: View, From e0d618862c410741b65200ed3e7058184bef58d3 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 28 Jun 2023 16:23:07 -0700 Subject: [PATCH 003/104] Add click out handler Make all context menus on button click toggles instead of re-shows --- crates/context_menu/src/context_menu.rs | 31 ++++++++----------- crates/gpui/src/app/window.rs | 2 +- .../gpui/src/elements/mouse_event_handler.rs | 12 ++++++- crates/gpui/src/scene/mouse_region.rs | 6 +++- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index 9bdf146da4..a603b3578a 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -301,23 +301,18 @@ impl ContextMenu { cx: &mut ViewContext, ) { let mut items = items.into_iter().peekable(); - dbg!(self.visible); - if (self.visible) { - self.visible = false; - } else { - if items.peek().is_some() { - self.items = items.collect(); - self.anchor_position = anchor_position; - self.anchor_corner = anchor_corner; - self.visible = true; - self.show_count += 1; - if !cx.is_self_focused() { - self.previously_focused_view_id = cx.focused_view_id(); - } - cx.focus_self(); - } else { - self.visible = false; + if items.peek().is_some() { + self.items = items.collect(); + self.anchor_position = anchor_position; + self.anchor_corner = anchor_corner; + self.visible = true; + self.show_count += 1; + if !cx.is_self_focused() { + self.previously_focused_view_id = cx.focused_view_id(); } + cx.focus_self(); + } else { + self.visible = false; } cx.notify(); } @@ -482,10 +477,10 @@ impl ContextMenu { .contained() .with_style(style.container) }) - .on_down_out(MouseButton::Left, |_, this, cx| { + .on_click_out(MouseButton::Left, |_, this, cx| { this.cancel(&Default::default(), cx); }) - .on_down_out(MouseButton::Right, |_, this, cx| { + .on_click_out(MouseButton::Right, |_, this, cx| { this.cancel(&Default::default(), cx); }) } diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index cc6778c930..5b15e62efa 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -716,7 +716,7 @@ impl<'a> WindowContext<'a> { } } - MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => { + MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) | MouseEvent::ClickOut(_) => { for (mouse_region, _) in self.window.mouse_regions.iter().rev() { // NOT contains if !mouse_region diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 6f2762db66..03f481b071 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -8,7 +8,7 @@ use crate::{ platform::MouseButton, scene::{ CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover, - MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, + MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, MouseClickOut, }, AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, SceneBuilder, SizeConstraint, View, ViewContext, @@ -136,6 +136,16 @@ impl MouseEventHandler { self } + pub fn on_click_out( + mut self, + button: MouseButton, + handler: impl Fn(MouseClickOut, &mut V, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_click_out(button, handler); + self + } + + pub fn on_down_out( mut self, button: MouseButton, diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs index 7e1d5d6e1e..3576529eec 100644 --- a/crates/gpui/src/scene/mouse_region.rs +++ b/crates/gpui/src/scene/mouse_region.rs @@ -94,7 +94,7 @@ impl MouseRegion { V: View, F: Fn(MouseClickOut, &mut V, &mut EventContext) + 'static, { - self.handlers = self.handlers.on_click(button, handler); + self.handlers = self.handlers.on_click_out(button, handler); self } @@ -255,6 +255,10 @@ impl HandlerSet { HandlerKey::new(MouseEvent::click_disc(), Some(button)), SmallVec::from_buf([Rc::new(|_, _, _, _| true)]), ); + set.insert( + HandlerKey::new(MouseEvent::click_out_disc(), Some(button)), + SmallVec::from_buf([Rc::new(|_, _, _, _| true)]), + ); set.insert( HandlerKey::new(MouseEvent::down_out_disc(), Some(button)), SmallVec::from_buf([Rc::new(|_, _, _, _| true)]), From 6ffa6afd20c693dadcc0cd5ca733c809cf465e7e Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 28 Jun 2023 16:35:57 -0700 Subject: [PATCH 004/104] fmt --- crates/gpui/src/app/window.rs | 9 ++++++--- crates/gpui/src/elements/mouse_event_handler.rs | 5 ++--- crates/gpui/src/scene/mouse_region.rs | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 5b15e62efa..23fbb33fe1 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -8,8 +8,8 @@ use crate::{ MouseButton, MouseMovedEvent, PromptLevel, WindowBounds, }, scene::{ - CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, - MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene, MouseClickOut, + CursorRegion, MouseClick, MouseClickOut, MouseDown, MouseDownOut, MouseDrag, MouseEvent, + MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene, }, text_layout::TextLayoutCache, util::post_inc, @@ -716,7 +716,10 @@ impl<'a> WindowContext<'a> { } } - MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) | MouseEvent::ClickOut(_) => { + MouseEvent::MoveOut(_) + | MouseEvent::UpOut(_) + | MouseEvent::DownOut(_) + | MouseEvent::ClickOut(_) => { for (mouse_region, _) in self.window.mouse_regions.iter().rev() { // NOT contains if !mouse_region diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 03f481b071..1b8142d964 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -7,8 +7,8 @@ use crate::{ platform::CursorStyle, platform::MouseButton, scene::{ - CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover, - MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, MouseClickOut, + CursorRegion, HandlerSet, MouseClick, MouseClickOut, MouseDown, MouseDownOut, MouseDrag, + MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, }, AnyElement, Element, EventContext, LayoutContext, MouseRegion, MouseState, SceneBuilder, SizeConstraint, View, ViewContext, @@ -145,7 +145,6 @@ impl MouseEventHandler { self } - pub fn on_down_out( mut self, button: MouseButton, diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs index 3576529eec..ca2cc04b9d 100644 --- a/crates/gpui/src/scene/mouse_region.rs +++ b/crates/gpui/src/scene/mouse_region.rs @@ -14,7 +14,7 @@ use super::{ MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, MouseMove, MouseUp, MouseUpOut, }, - MouseMoveOut, MouseScrollWheel, MouseClickOut, + MouseClickOut, MouseMoveOut, MouseScrollWheel, }; #[derive(Clone)] From 53666311733e591caf5b712ff10954fd40ea8c87 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 17:10:51 -0700 Subject: [PATCH 005/104] Remove on_click_out handler from context menu Add 'delay_cancel()' method and on_down handler to relevant buttons --- crates/collab_ui/src/collab_titlebar_item.rs | 5 +- crates/context_menu/src/context_menu.rs | 58 ++++++++++++++++---- crates/copilot_button/src/copilot_button.rs | 7 ++- crates/terminal_view/src/terminal_element.rs | 21 +++---- crates/terminal_view/src/terminal_panel.rs | 2 + crates/workspace/src/pane.rs | 13 +++-- 6 files changed, 79 insertions(+), 27 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 2ab8928166..5caebb9f0c 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -317,7 +317,7 @@ impl CollabTitlebarItem { ), ] }; - user_menu.show(Default::default(), AnchorCorner::TopRight, items, cx); + user_menu.toggle(Default::default(), AnchorCorner::TopRight, items, cx); }); } @@ -683,6 +683,9 @@ impl CollabTitlebarItem { .into_any() }) .with_cursor_style(CursorStyle::PointingHand) + .on_down(MouseButton::Left, move |_, this, cx| { + this.user_menu.update(cx, |menu, _| menu.delay_cancel()); + }) .on_click(MouseButton::Left, move |_, this, cx| { this.toggle_user_menu(&Default::default(), cx) }) diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index a603b3578a..296f6bc04a 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -124,6 +124,7 @@ pub struct ContextMenu { items: Vec, selected_index: Option, visible: bool, + delay_cancel: bool, previously_focused_view_id: Option, parent_view_id: usize, _actions_observation: Subscription, @@ -178,6 +179,7 @@ impl ContextMenu { pub fn new(parent_view_id: usize, cx: &mut ViewContext) -> Self { Self { show_count: 0, + delay_cancel: false, anchor_position: Default::default(), anchor_corner: AnchorCorner::TopLeft, position_mode: OverlayPositionMode::Window, @@ -232,15 +234,23 @@ impl ContextMenu { } } + pub fn delay_cancel(&mut self) { + self.delay_cancel = true; + } + fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { - self.reset(cx); - let show_count = self.show_count; - cx.defer(move |this, cx| { - if cx.handle().is_focused(cx) && this.show_count == show_count { - let window_id = cx.window_id(); - (**cx).focus(window_id, this.previously_focused_view_id.take()); - } - }); + if !self.delay_cancel { + self.reset(cx); + let show_count = self.show_count; + cx.defer(move |this, cx| { + if cx.handle().is_focused(cx) && this.show_count == show_count { + let window_id = cx.window_id(); + (**cx).focus(window_id, this.previously_focused_view_id.take()); + } + }); + } else { + self.delay_cancel = false; + } } fn reset(&mut self, cx: &mut ViewContext) { @@ -293,6 +303,34 @@ impl ContextMenu { } } + pub fn toggle( + &mut self, + anchor_position: Vector2F, + anchor_corner: AnchorCorner, + items: Vec, + cx: &mut ViewContext, + ) { + if self.visible() { + self.cancel(&Cancel, cx); + } else { + let mut items = items.into_iter().peekable(); + if items.peek().is_some() { + self.items = items.collect(); + self.anchor_position = anchor_position; + self.anchor_corner = anchor_corner; + self.visible = true; + self.show_count += 1; + if !cx.is_self_focused() { + self.previously_focused_view_id = cx.focused_view_id(); + } + cx.focus_self(); + } else { + self.visible = false; + } + } + cx.notify(); + } + pub fn show( &mut self, anchor_position: Vector2F, @@ -477,10 +515,10 @@ impl ContextMenu { .contained() .with_style(style.container) }) - .on_click_out(MouseButton::Left, |_, this, cx| { + .on_down_out(MouseButton::Left, |_, this, cx| { this.cancel(&Default::default(), cx); }) - .on_click_out(MouseButton::Right, |_, this, cx| { + .on_down_out(MouseButton::Right, |_, this, cx| { this.cancel(&Default::default(), cx); }) } diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 9b0581492f..5576451b1b 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -102,6 +102,9 @@ impl View for CopilotButton { } }) .with_cursor_style(CursorStyle::PointingHand) + .on_down(MouseButton::Left, |_, this, cx| { + this.popup_menu.update(cx, |menu, _| menu.delay_cancel()); + }) .on_click(MouseButton::Left, { let status = status.clone(); move |_, this, cx| match status { @@ -186,7 +189,7 @@ impl CopilotButton { })); self.popup_menu.update(cx, |menu, cx| { - menu.show( + menu.toggle( Default::default(), AnchorCorner::BottomRight, menu_options, @@ -266,7 +269,7 @@ impl CopilotButton { menu_options.push(ContextMenuItem::action("Sign Out", SignOut)); self.popup_menu.update(cx, |menu, cx| { - menu.show( + menu.toggle( Default::default(), AnchorCorner::BottomRight, menu_options, diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 2f2ff2cdc3..b92059f5d6 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -395,16 +395,17 @@ impl TerminalElement { // Terminal Emulator controlled behavior: region = region // Start selections - .on_down( - MouseButton::Left, - TerminalElement::generic_button_handler( - connection, - origin, - move |terminal, origin, e, _cx| { - terminal.mouse_down(&e, origin); - }, - ), - ) + .on_down(MouseButton::Left, move |event, v: &mut TerminalView, cx| { + cx.focus_parent(); + v.context_menu.update(cx, |menu, _cx| menu.delay_cancel()); + if let Some(conn_handle) = connection.upgrade(cx) { + conn_handle.update(cx, |terminal, cx| { + terminal.mouse_down(&event, origin); + + cx.notify(); + }) + } + }) // Update drag selections .on_drag(MouseButton::Left, move |event, _: &mut TerminalView, cx| { if cx.is_self_focused() { diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 6de6527a26..11f8f7abde 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -87,6 +87,7 @@ impl TerminalPanel { } }) }, + |_, _| {}, None, )) .with_child(Pane::render_tab_bar_button( @@ -100,6 +101,7 @@ impl TerminalPanel { Some(("Toggle Zoom".into(), Some(Box::new(workspace::ToggleZoom)))), cx, move |pane, cx| pane.toggle_zoom(&Default::default(), cx), + |_, _| {}, None, )) .into_any() diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 9776fede2c..e61e60d68f 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -273,6 +273,7 @@ impl Pane { Some(("New...".into(), None)), cx, |pane, cx| pane.deploy_new_menu(cx), + |pane, cx| pane.tab_bar_context_menu.handle.update(cx, |menu, _| menu.delay_cancel()), pane.tab_bar_context_menu .handle_if_kind(TabBarContextMenuKind::New), )) @@ -283,6 +284,7 @@ impl Pane { Some(("Split Pane".into(), None)), cx, |pane, cx| pane.deploy_split_menu(cx), + |pane, cx| pane.tab_bar_context_menu.handle.update(cx, |menu, _| menu.delay_cancel()), pane.tab_bar_context_menu .handle_if_kind(TabBarContextMenuKind::Split), )) @@ -304,6 +306,7 @@ impl Pane { Some((tooltip_label, Some(Box::new(ToggleZoom)))), cx, move |pane, cx| pane.toggle_zoom(&Default::default(), cx), + move |_, _| {}, None, ) }) @@ -988,7 +991,7 @@ impl Pane { fn deploy_split_menu(&mut self, cx: &mut ViewContext) { self.tab_bar_context_menu.handle.update(cx, |menu, cx| { - menu.show( + menu.toggle( Default::default(), AnchorCorner::TopRight, vec![ @@ -1006,7 +1009,7 @@ impl Pane { fn deploy_new_menu(&mut self, cx: &mut ViewContext) { self.tab_bar_context_menu.handle.update(cx, |menu, cx| { - menu.show( + menu.toggle( Default::default(), AnchorCorner::TopRight, vec![ @@ -1416,13 +1419,14 @@ impl Pane { .into_any() } - pub fn render_tab_bar_button)>( + pub fn render_tab_bar_button), F2: 'static + Fn(&mut Pane, &mut EventContext)>( index: usize, icon: &'static str, is_active: bool, tooltip: Option<(String, Option>)>, cx: &mut ViewContext, - on_click: F, + on_click: F1, + on_down: F2, context_menu: Option>, ) -> AnyElement { enum TabBarButton {} @@ -1440,6 +1444,7 @@ impl Pane { .with_height(style.button_width) }) .with_cursor_style(CursorStyle::PointingHand) + .on_down(MouseButton::Left, move |_, pane, cx| on_down(pane, cx)) .on_click(MouseButton::Left, move |_, pane, cx| on_click(pane, cx)) .into_any(); if let Some((tooltip, action)) = tooltip { From 73b0f3b23d126a9f06eec8cbf3fbcd15a4c3745f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 17:19:35 -0700 Subject: [PATCH 006/104] fmt --- crates/workspace/src/pane.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index e61e60d68f..6a20fab9a2 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -273,7 +273,11 @@ impl Pane { Some(("New...".into(), None)), cx, |pane, cx| pane.deploy_new_menu(cx), - |pane, cx| pane.tab_bar_context_menu.handle.update(cx, |menu, _| menu.delay_cancel()), + |pane, cx| { + pane.tab_bar_context_menu + .handle + .update(cx, |menu, _| menu.delay_cancel()) + }, pane.tab_bar_context_menu .handle_if_kind(TabBarContextMenuKind::New), )) @@ -284,7 +288,11 @@ impl Pane { Some(("Split Pane".into(), None)), cx, |pane, cx| pane.deploy_split_menu(cx), - |pane, cx| pane.tab_bar_context_menu.handle.update(cx, |menu, _| menu.delay_cancel()), + |pane, cx| { + pane.tab_bar_context_menu + .handle + .update(cx, |menu, _| menu.delay_cancel()) + }, pane.tab_bar_context_menu .handle_if_kind(TabBarContextMenuKind::Split), )) @@ -1419,7 +1427,10 @@ impl Pane { .into_any() } - pub fn render_tab_bar_button), F2: 'static + Fn(&mut Pane, &mut EventContext)>( + pub fn render_tab_bar_button< + F1: 'static + Fn(&mut Pane, &mut EventContext), + F2: 'static + Fn(&mut Pane, &mut EventContext), + >( index: usize, icon: &'static str, is_active: bool, From 33f5248d4f6c2395f8633aa307571e3b69dc7ff6 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 21 Jun 2023 15:23:52 -0700 Subject: [PATCH 007/104] Add the ability to make new directories by adding slashes to a file name --- Cargo.lock | 1 + Cargo.toml | 1 + crates/collab/Cargo.toml | 2 +- crates/fs/src/fs.rs | 6 + crates/project/Cargo.toml | 2 +- crates/project/src/worktree.rs | 23 +++- crates/project/src/worktree_tests.rs | 77 +++++++++++ crates/project_panel/Cargo.toml | 1 + crates/project_panel/src/project_panel.rs | 152 +++++++++++++++++++++- crates/settings/Cargo.toml | 2 +- 10 files changed, 259 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9b2e29ea0..3748f24933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5033,6 +5033,7 @@ dependencies = [ "language", "menu", "postage", + "pretty_assertions", "project", "schemars", "serde", diff --git a/Cargo.toml b/Cargo.toml index 3f3953096e..26555f32cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ time = { version = "0.3", features = ["serde", "serde-well-known"] } toml = { version = "0.5" } tree-sitter = "0.20" unindent = { version = "0.1.7" } +pretty_assertions = "1.3.0" [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "49226023693107fba9a1191136a4f47f38cdca73" } diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index a87234ded7..0c752a2047 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -67,7 +67,7 @@ fs = { path = "../fs", features = ["test-support"] } git = { path = "../git", features = ["test-support"] } live_kit_client = { path = "../live_kit_client", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } -pretty_assertions = "1.3.0" +pretty_assertions = "*" project = { path = "../project", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 592e6c9a53..ec8a249ff4 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -279,6 +279,9 @@ impl Fs for RealFs { async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()> { let buffer_size = text.summary().len.min(10 * 1024); + if let Some(path) = path.parent() { + self.create_dir(path).await?; + } let file = smol::fs::File::create(path).await?; let mut writer = smol::io::BufWriter::with_capacity(buffer_size, file); for chunk in chunks(text, line_ending) { @@ -1077,6 +1080,9 @@ impl Fs for FakeFs { self.simulate_random_delay().await; let path = normalize_path(path); let content = chunks(text, line_ending).collect(); + if let Some(path) = path.parent() { + self.create_dir(path).await?; + } self.write_file_internal(path, content)?; Ok(()) } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index d6578c87ba..dbc0c617f2 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -64,7 +64,7 @@ itertools = "0.10" [dev-dependencies] ctor.workspace = true env_logger.workspace = true -pretty_assertions = "1.3.0" +pretty_assertions = "*" client = { path = "../client", features = ["test-support"] } collections = { path = "../collections", features = ["test-support"] } db = { path = "../db", features = ["test-support"] } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 20e693770f..a0497fa677 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1001,10 +1001,25 @@ impl LocalWorktree { cx.spawn(|this, mut cx| async move { write.await?; - this.update(&mut cx, |this, cx| { - this.as_local_mut().unwrap().refresh_entry(path, None, cx) - }) - .await + let (result, refreshes) = this.update(&mut cx, |this, cx| { + let mut refreshes = Vec::new(); + for path in path.ancestors().skip(1) { + refreshes.push(this.as_local_mut().unwrap().refresh_entry( + path.into(), + None, + cx, + )); + } + ( + this.as_local_mut().unwrap().refresh_entry(path, None, cx), + refreshes, + ) + }); + for refresh in refreshes { + refresh.await.log_err(); + } + + result.await }) } diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index f908d702eb..efc5f42369 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -936,6 +936,83 @@ async fn test_create_directory_during_initial_scan(cx: &mut TestAppContext) { ); } +#[gpui::test] +async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { + let client_fake = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); + + let fs_fake = FakeFs::new(cx.background()); + fs_fake.insert_tree( + "/root", + json!({ + "a": {}, + }), + ) + .await; + + let tree_fake = Worktree::local( + client_fake, + "/root".as_ref(), + true, + fs_fake, + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + + let entry = tree_fake + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("a/b/c/d.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_fake.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("a/b/c/d.txt").unwrap().is_file()); + assert!(tree.entry_for_path("a/b/c/").unwrap().is_dir()); + assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); + }); + + let client_real = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); + + let fs_real = Arc::new(RealFs); + let temp_root = temp_tree(json!({ + "a": {} + })); + + let tree_real = Worktree::local( + client_real, + temp_root.path(), + true, + fs_real, + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + + let entry = tree_real + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("a/b/c/d.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_real.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("a/b/c/d.txt").unwrap().is_file()); + assert!(tree.entry_for_path("a/b/c/").unwrap().is_dir()); + assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); + }); +} + #[gpui::test(iterations = 100)] async fn test_random_worktree_operations_during_initial_scan( cx: &mut TestAppContext, diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 55efc09deb..33606fccc4 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -27,6 +27,7 @@ serde_derive.workspace = true serde_json.workspace = true anyhow.workspace = true schemars.workspace = true +pretty_assertions.workspace = true unicase = "2.6" [dev-dependencies] diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 3f80e02317..57a45ddb16 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -64,7 +64,7 @@ pub struct ProjectPanel { pending_serialization: Task>, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] struct Selection { worktree_id: WorktreeId, entry_id: ProjectEntryId, @@ -588,6 +588,7 @@ impl ProjectPanel { if selection.entry_id == edited_entry_id { selection.worktree_id = worktree_id; selection.entry_id = new_entry.id; + this.expand_to_selection(cx); } } this.update_visible_entries(None, cx); @@ -965,6 +966,25 @@ impl ProjectPanel { Some((worktree, entry)) } + fn expand_to_selection(&mut self, cx: &mut ViewContext) -> Option<()> { + let (worktree, entry) = self.selected_entry(cx)?; + let expanded_dir_ids = self.expanded_dir_ids.entry(worktree.id()).or_default(); + + for path in entry.path.ancestors() { + let Some(entry) = worktree.entry_for_path(path) else { + continue; + }; + if entry.is_dir() { + if let Err(idx) = expanded_dir_ids.binary_search(&entry.id) { + expanded_dir_ids.insert(idx, entry.id); + } + } + } + + + Some(()) + } + fn update_visible_entries( &mut self, new_selected_entry: Option<(WorktreeId, ProjectEntryId)>, @@ -1139,6 +1159,7 @@ impl ProjectPanel { for entry in visible_worktree_entries[entry_range].iter() { let status = git_status_setting.then(|| entry.git_status).flatten(); + let mut details = EntryDetails { filename: entry .path @@ -1592,6 +1613,7 @@ impl ClipboardEntry { mod tests { use super::*; use gpui::{TestAppContext, ViewHandle}; + use pretty_assertions::assert_eq; use project::FakeFs; use serde_json::json; use settings::SettingsStore; @@ -2002,6 +2024,134 @@ mod tests { ); } + #[gpui::test(iterations = 30)] + async fn test_adding_directories_via_file(cx: &mut gpui::TestAppContext) { + init_test(cx); + + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/root1", + json!({ + ".dockerignore": "", + ".git": { + "HEAD": "", + }, + "a": { + "0": { "q": "", "r": "", "s": "" }, + "1": { "t": "", "u": "" }, + "2": { "v": "", "w": "", "x": "", "y": "" }, + }, + "b": { + "3": { "Q": "" }, + "4": { "R": "", "S": "", "T": "", "U": "" }, + }, + "C": { + "5": {}, + "6": { "V": "", "W": "" }, + "7": { "X": "" }, + "8": { "Y": {}, "Z": "" } + } + }), + ) + .await; + fs.insert_tree( + "/root2", + json!({ + "d": { + "9": "" + }, + "e": {} + }), + ) + .await; + + let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await; + let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); + let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)); + + select_path(&panel, "root1", cx); + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1 <== selected", + " > .git", + " > a", + " > b", + " > C", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + + // Add a file with the root folder selected. The filename editor is placed + // before the first file in the root folder. + panel.update(cx, |panel, cx| panel.new_file(&NewFile, cx)); + cx.read_window(window_id, |cx| { + let panel = panel.read(cx); + assert!(panel.filename_editor.is_focused(cx)); + }); + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1", + " > .git", + " > a", + " > b", + " > C", + " [EDITOR: ''] <== selected", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + + + let confirm = panel.update(cx, |panel, cx| { + panel.filename_editor.update(cx, |editor, cx| { + editor.set_text("bdir1/dir2/the-new-filename", cx) + }); + panel.confirm(&Confirm, cx).unwrap() + }); + + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1", + " > .git", + " > a", + " > b", + " > C", + " [PROCESSING: 'bdir1/dir2/the-new-filename'] <== selected", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + + confirm.await.unwrap(); + assert_eq!( + visible_entries_as_strings(&panel, 0..13, cx), + &[ + "v root1", + " > .git", + " > a", + " > b", + " v bdir1", + " v dir2", + " the-new-filename <== selected", + " > C", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + } + #[gpui::test] async fn test_copy_paste(cx: &mut gpui::TestAppContext) { init_test(cx); diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index b5dc301a5c..6c1ded805b 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -38,5 +38,5 @@ tree-sitter-json = "*" gpui = { path = "../gpui", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } indoc.workspace = true -pretty_assertions = "1.3.0" +pretty_assertions = "*" unindent.workspace = true From cd670e340fa4a7e5c6d452a87ceee6329ae0ee21 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 17:48:01 -0700 Subject: [PATCH 008/104] Fix edge case with absolute file paths --- crates/project_panel/src/project_panel.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 57a45ddb16..fe8c649420 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -547,7 +547,7 @@ impl ProjectPanel { worktree_id, entry_id: NEW_ENTRY_ID, }); - let new_path = entry.path.join(&filename); + let new_path = entry.path.join(&filename.trim_start_matches("/")); if path_already_exists(new_path.as_path()) { return None; } @@ -2111,7 +2111,7 @@ mod tests { let confirm = panel.update(cx, |panel, cx| { panel.filename_editor.update(cx, |editor, cx| { - editor.set_text("bdir1/dir2/the-new-filename", cx) + editor.set_text("/bdir1/dir2/the-new-filename", cx) }); panel.confirm(&Confirm, cx).unwrap() }); @@ -2124,7 +2124,7 @@ mod tests { " > a", " > b", " > C", - " [PROCESSING: 'bdir1/dir2/the-new-filename'] <== selected", + " [PROCESSING: '/bdir1/dir2/the-new-filename'] <== selected", " .dockerignore", "v root2", " > d", From 787412b545cd6e9e4cb0f40f5d33d3b9a4480a22 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 17:49:42 -0700 Subject: [PATCH 009/104] fmt and update dependency --- crates/collab/Cargo.toml | 2 +- crates/project/Cargo.toml | 2 +- crates/project/src/worktree_tests.rs | 15 ++++++++------- crates/project_panel/src/project_panel.rs | 3 --- crates/settings/Cargo.toml | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 0c752a2047..c787287a0c 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -67,7 +67,7 @@ fs = { path = "../fs", features = ["test-support"] } git = { path = "../git", features = ["test-support"] } live_kit_client = { path = "../live_kit_client", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } -pretty_assertions = "*" +pretty_assertions.workspace = true project = { path = "../project", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index dbc0c617f2..bfe5f89f68 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -64,7 +64,7 @@ itertools = "0.10" [dev-dependencies] ctor.workspace = true env_logger.workspace = true -pretty_assertions = "*" +pretty_assertions.workspace = true client = { path = "../client", features = ["test-support"] } collections = { path = "../collections", features = ["test-support"] } db = { path = "../db", features = ["test-support"] } diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index efc5f42369..63f1f28eea 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -941,13 +941,14 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { let client_fake = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); let fs_fake = FakeFs::new(cx.background()); - fs_fake.insert_tree( - "/root", - json!({ - "a": {}, - }), - ) - .await; + fs_fake + .insert_tree( + "/root", + json!({ + "a": {}, + }), + ) + .await; let tree_fake = Worktree::local( client_fake, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index fe8c649420..c329ae4e51 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -981,7 +981,6 @@ impl ProjectPanel { } } - Some(()) } @@ -1159,7 +1158,6 @@ impl ProjectPanel { for entry in visible_worktree_entries[entry_range].iter() { let status = git_status_setting.then(|| entry.git_status).flatten(); - let mut details = EntryDetails { filename: entry .path @@ -2108,7 +2106,6 @@ mod tests { ] ); - let confirm = panel.update(cx, |panel, cx| { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("/bdir1/dir2/the-new-filename", cx) diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 6c1ded805b..06b81a0c61 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -38,5 +38,5 @@ tree-sitter-json = "*" gpui = { path = "../gpui", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } indoc.workspace = true -pretty_assertions = "*" +pretty_assertions.workspace = true unindent.workspace = true From a6dabf7acfef0f235bdd41d81daf8433b1955f59 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 18:15:40 -0700 Subject: [PATCH 010/104] Make path updates minimal --- crates/project/src/worktree.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index a0497fa677..2b166bf6ef 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -981,6 +981,19 @@ impl LocalWorktree { }) } + /// Find the lowest path in the worktree's datastructures that is an ancestor + pub fn lowest_ancestor(&self, path: &Path) -> PathBuf { + let mut lowest_ancestor = None; + for path in path.ancestors() { + if self.entry_for_path(path).is_some() { + lowest_ancestor = Some(path.to_path_buf()); + break; + } + } + + lowest_ancestor.unwrap_or_else(|| PathBuf::from("")) + } + pub fn create_entry( &self, path: impl Into>, @@ -988,6 +1001,7 @@ impl LocalWorktree { cx: &mut ModelContext, ) -> Task> { let path = path.into(); + let lowest_ancestor = self.lowest_ancestor(&path); let abs_path = self.absolutize(&path); let fs = self.fs.clone(); let write = cx.background().spawn(async move { @@ -1003,9 +1017,14 @@ impl LocalWorktree { write.await?; let (result, refreshes) = this.update(&mut cx, |this, cx| { let mut refreshes = Vec::new(); - for path in path.ancestors().skip(1) { + let refresh_paths = path.strip_prefix(&lowest_ancestor).unwrap(); + for refresh_path in refresh_paths.ancestors() { + let refresh_full_path = lowest_ancestor.join(refresh_path); + if refresh_full_path.as_path() == path.deref() { + continue; + } refreshes.push(this.as_local_mut().unwrap().refresh_entry( - path.into(), + refresh_full_path.into(), None, cx, )); From a9a51ab3addfda7c97a96d3194099077d13fc7a1 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 18:21:35 -0700 Subject: [PATCH 011/104] Added more tests and minimal file updates --- crates/project/src/worktree_tests.rs | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index 63f1f28eea..8f130f648a 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -1012,6 +1012,41 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { assert!(tree.entry_for_path("a/b/c/").unwrap().is_dir()); assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); }); + + // Test smallest change + let entry = tree_real + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("a/b/c/e.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_real.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("a/b/c/e.txt").unwrap().is_file()); + }); + + // Test largest change + let entry = tree_real + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("d/e/f/g.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_real.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("d/e/f/g.txt").unwrap().is_file()); + assert!(tree.entry_for_path("d/e/f").unwrap().is_dir()); + assert!(tree.entry_for_path("d/e/").unwrap().is_dir()); + assert!(tree.entry_for_path("d/").unwrap().is_dir()); + }); } #[gpui::test(iterations = 100)] From 9ee2707d43c877e8f2f9f7efa7b0d26e90d48833 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 29 Jun 2023 22:45:54 -0600 Subject: [PATCH 012/104] vim: Add }/{ for start/end of paragraph Fixes: zed-industries/community#470 --- assets/keymaps/vim.json | 2 + crates/editor/src/editor.rs | 14 ++-- crates/editor/src/movement.rs | 24 +++++-- crates/vim/src/motion.rs | 118 +++++++++++++++++++++++++++++++++- 4 files changed, 149 insertions(+), 9 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index afee6fcd2e..e4c489c5b5 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -37,6 +37,8 @@ "$": "vim::EndOfLine", "shift-g": "vim::EndOfDocument", "w": "vim::NextWordStart", + "{": "vim::StartOfParagraph", + "}": "vim::EndOfParagraph", "shift-w": [ "vim::NextWordStart", { diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 64332c102a..824802630d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5120,7 +5120,7 @@ impl Editor { self.change_selections(Some(Autoscroll::fit()), cx, |s| { s.move_with(|map, selection| { selection.collapse_to( - movement::start_of_paragraph(map, selection.head()), + movement::start_of_paragraph(map, selection.head(), 1), SelectionGoal::None, ) }); @@ -5140,7 +5140,7 @@ impl Editor { self.change_selections(Some(Autoscroll::fit()), cx, |s| { s.move_with(|map, selection| { selection.collapse_to( - movement::end_of_paragraph(map, selection.head()), + movement::end_of_paragraph(map, selection.head(), 1), SelectionGoal::None, ) }); @@ -5159,7 +5159,10 @@ impl Editor { self.change_selections(Some(Autoscroll::fit()), cx, |s| { s.move_heads_with(|map, head, _| { - (movement::start_of_paragraph(map, head), SelectionGoal::None) + ( + movement::start_of_paragraph(map, head, 1), + SelectionGoal::None, + ) }); }) } @@ -5176,7 +5179,10 @@ impl Editor { self.change_selections(Some(Autoscroll::fit()), cx, |s| { s.move_heads_with(|map, head, _| { - (movement::end_of_paragraph(map, head), SelectionGoal::None) + ( + movement::end_of_paragraph(map, head, 1), + SelectionGoal::None, + ) }); }) } diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 523a0af964..8f1e6172e9 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -193,7 +193,11 @@ pub fn next_subword_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPo }) } -pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint { +pub fn start_of_paragraph( + map: &DisplaySnapshot, + display_point: DisplayPoint, + mut count: usize, +) -> DisplayPoint { let point = display_point.to_point(map); if point.row == 0 { return map.max_point(); @@ -203,7 +207,11 @@ pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> for row in (0..point.row + 1).rev() { let blank = map.buffer_snapshot.is_line_blank(row); if found_non_blank_line && blank { - return Point::new(row, 0).to_display_point(map); + if count <= 1 { + return Point::new(row, 0).to_display_point(map); + } + count -= 1; + found_non_blank_line = false; } found_non_blank_line |= !blank; @@ -212,7 +220,11 @@ pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint::zero() } -pub fn end_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint { +pub fn end_of_paragraph( + map: &DisplaySnapshot, + display_point: DisplayPoint, + mut count: usize, +) -> DisplayPoint { let point = display_point.to_point(map); if point.row == map.max_buffer_row() { return DisplayPoint::zero(); @@ -222,7 +234,11 @@ pub fn end_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> D for row in point.row..map.max_buffer_row() + 1 { let blank = map.buffer_snapshot.is_line_blank(row); if found_non_blank_line && blank { - return Point::new(row, 0).to_display_point(map); + if count <= 1 { + return Point::new(row, 0).to_display_point(map); + } + count -= 1; + found_non_blank_line = false; } found_non_blank_line |= !blank; diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index faf69d9473..f39cd82fc1 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -31,6 +31,8 @@ pub enum Motion { CurrentLine, StartOfLine, EndOfLine, + StartOfParagraph, + EndOfParagraph, StartOfDocument, EndOfDocument, Matching, @@ -72,6 +74,8 @@ actions!( StartOfLine, EndOfLine, CurrentLine, + StartOfParagraph, + EndOfParagraph, StartOfDocument, EndOfDocument, Matching, @@ -92,6 +96,12 @@ pub fn init(cx: &mut AppContext) { cx.add_action(|_: &mut Workspace, _: &StartOfLine, cx: _| motion(Motion::StartOfLine, cx)); cx.add_action(|_: &mut Workspace, _: &EndOfLine, cx: _| motion(Motion::EndOfLine, cx)); cx.add_action(|_: &mut Workspace, _: &CurrentLine, cx: _| motion(Motion::CurrentLine, cx)); + cx.add_action(|_: &mut Workspace, _: &StartOfParagraph, cx: _| { + motion(Motion::StartOfParagraph, cx) + }); + cx.add_action(|_: &mut Workspace, _: &EndOfParagraph, cx: _| { + motion(Motion::EndOfParagraph, cx) + }); cx.add_action(|_: &mut Workspace, _: &StartOfDocument, cx: _| { motion(Motion::StartOfDocument, cx) }); @@ -142,7 +152,8 @@ impl Motion { pub fn linewise(&self) -> bool { use Motion::*; match self { - Down | Up | StartOfDocument | EndOfDocument | CurrentLine | NextLineStart => true, + Down | Up | StartOfDocument | EndOfDocument | CurrentLine | NextLineStart + | StartOfParagraph | EndOfParagraph => true, EndOfLine | NextWordEnd { .. } | Matching @@ -172,6 +183,8 @@ impl Motion { | Backspace | Right | StartOfLine + | StartOfParagraph + | EndOfParagraph | NextWordStart { .. } | PreviousWordStart { .. } | FirstNonWhitespace @@ -197,6 +210,8 @@ impl Motion { | Backspace | Right | StartOfLine + | StartOfParagraph + | EndOfParagraph | NextWordStart { .. } | PreviousWordStart { .. } | FirstNonWhitespace @@ -235,6 +250,14 @@ impl Motion { FirstNonWhitespace => (first_non_whitespace(map, point), SelectionGoal::None), StartOfLine => (start_of_line(map, point), SelectionGoal::None), EndOfLine => (end_of_line(map, point), SelectionGoal::None), + StartOfParagraph => ( + movement::start_of_paragraph(map, point, times), + SelectionGoal::None, + ), + EndOfParagraph => ( + movement::end_of_paragraph(map, point, times), + SelectionGoal::None, + ), CurrentLine => (end_of_line(map, point), SelectionGoal::None), StartOfDocument => (start_of_document(map, point, times), SelectionGoal::None), EndOfDocument => ( @@ -590,3 +613,96 @@ fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> let new_row = (point.row() + times as u32).min(map.max_buffer_row()); map.clip_point(DisplayPoint::new(new_row, 0), Bias::Left) } + +#[cfg(test)] + +mod test { + + use crate::{state::Mode, test::VimTestContext}; + use indoc::indoc; + + #[gpui::test] + async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + let initial_state = indoc! {r"ˇabc + def + + paragraph + the second + + + + third and + final"}; + + // goes down once + cx.set_state(initial_state, Mode::Normal); + cx.simulate_keystrokes(["}"]); + cx.assert_state( + indoc! {r"abc + def + ˇ + paragraph + the second + + + + third and + final"}, + Mode::Normal, + ); + + // goes up once + cx.simulate_keystrokes(["{"]); + cx.assert_state(initial_state, Mode::Normal); + + // goes down twice + cx.simulate_keystrokes(["2", "}"]); + cx.assert_state( + indoc! {r"abc + def + + paragraph + the second + ˇ + + + third and + final"}, + Mode::Normal, + ); + + // goes down over multiple blanks + cx.simulate_keystrokes(["}"]); + cx.assert_state( + indoc! {r"abc + def + + paragraph + the second + + + + third and + finalˇ"}, + Mode::Normal, + ); + + // goes up twice + cx.simulate_keystrokes(["2", "{"]); + cx.assert_state( + indoc! {r"abc + def + ˇ + paragraph + the second + + + + third and + final"}, + Mode::Normal, + ) + } +} From abb58c41dbc8b31c02873ba294daf7530ff51e5e Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 29 Jun 2023 23:24:51 -0600 Subject: [PATCH 013/104] vim: Fix edge-case in } when trailing newline is absent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added .assert_shared_state() to NeovimBackedTestContext – although it's not strictly necessary to show the expected behaviour in the test file (as we can just compare to neovim's JSON recording), it makes it much easier to understand what we're testing. --- crates/editor/src/test/editor_test_context.rs | 26 ++++++---- crates/vim/src/motion.rs | 52 ++++++++----------- .../src/test/neovim_backed_test_context.rs | 51 ++++++++++++++---- .../test_start_end_of_paragraph.json | 13 +++++ 4 files changed, 94 insertions(+), 48 deletions(-) create mode 100644 crates/vim/test_data/test_start_end_of_paragraph.json diff --git a/crates/editor/src/test/editor_test_context.rs b/crates/editor/src/test/editor_test_context.rs index 95da7ff297..bac70f139a 100644 --- a/crates/editor/src/test/editor_test_context.rs +++ b/crates/editor/src/test/editor_test_context.rs @@ -210,6 +210,10 @@ impl<'a> EditorTestContext<'a> { self.assert_selections(expected_selections, marked_text.to_string()) } + pub fn editor_state(&mut self) -> String { + generate_marked_text(self.buffer_text().as_str(), &self.editor_selections(), true) + } + #[track_caller] pub fn assert_editor_background_highlights(&mut self, marked_text: &str) { let expected_ranges = self.ranges(marked_text); @@ -248,14 +252,8 @@ impl<'a> EditorTestContext<'a> { self.assert_selections(expected_selections, expected_marked_text) } - #[track_caller] - fn assert_selections( - &mut self, - expected_selections: Vec>, - expected_marked_text: String, - ) { - let actual_selections = self - .editor + fn editor_selections(&self) -> Vec> { + self.editor .read_with(self.cx, |editor, cx| editor.selections.all::(cx)) .into_iter() .map(|s| { @@ -265,12 +263,22 @@ impl<'a> EditorTestContext<'a> { s.start..s.end } }) - .collect::>(); + .collect::>() + } + + #[track_caller] + fn assert_selections( + &mut self, + expected_selections: Vec>, + expected_marked_text: String, + ) { + let actual_selections = self.editor_selections(); let actual_marked_text = generate_marked_text(&self.buffer_text(), &actual_selections, true); if expected_selections != actual_selections { panic!( indoc! {" + {}Editor has unexpected selections. Expected selections: diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index f39cd82fc1..e8084cb4be 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -255,7 +255,7 @@ impl Motion { SelectionGoal::None, ), EndOfParagraph => ( - movement::end_of_paragraph(map, point, times), + map.clip_at_line_end(movement::end_of_paragraph(map, point, times)), SelectionGoal::None, ), CurrentLine => (end_of_line(map, point), SelectionGoal::None), @@ -618,12 +618,12 @@ fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> mod test { - use crate::{state::Mode, test::VimTestContext}; + use crate::test::NeovimBackedTestContext; use indoc::indoc; #[gpui::test] async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) { - let mut cx = VimTestContext::new(cx, true).await; + let mut cx = NeovimBackedTestContext::new(cx).await; let initial_state = indoc! {r"ˇabc def @@ -637,10 +637,9 @@ mod test { final"}; // goes down once - cx.set_state(initial_state, Mode::Normal); - cx.simulate_keystrokes(["}"]); - cx.assert_state( - indoc! {r"abc + cx.set_shared_state(initial_state).await; + cx.simulate_shared_keystrokes(["}"]).await; + cx.assert_shared_state(indoc! {r"abc def ˇ paragraph @@ -649,18 +648,16 @@ mod test { third and - final"}, - Mode::Normal, - ); + final"}) + .await; // goes up once - cx.simulate_keystrokes(["{"]); - cx.assert_state(initial_state, Mode::Normal); + cx.simulate_shared_keystrokes(["{"]).await; + cx.assert_shared_state(initial_state).await; // goes down twice - cx.simulate_keystrokes(["2", "}"]); - cx.assert_state( - indoc! {r"abc + cx.simulate_shared_keystrokes(["2", "}"]).await; + cx.assert_shared_state(indoc! {r"abc def paragraph @@ -669,14 +666,12 @@ mod test { third and - final"}, - Mode::Normal, - ); + final"}) + .await; // goes down over multiple blanks - cx.simulate_keystrokes(["}"]); - cx.assert_state( - indoc! {r"abc + cx.simulate_shared_keystrokes(["}"]).await; + cx.assert_shared_state(indoc! {r"abc def paragraph @@ -685,14 +680,12 @@ mod test { third and - finalˇ"}, - Mode::Normal, - ); + finaˇl"}) + .await; // goes up twice - cx.simulate_keystrokes(["2", "{"]); - cx.assert_state( - indoc! {r"abc + cx.simulate_shared_keystrokes(["2", "{"]).await; + cx.assert_shared_state(indoc! {r"abc def ˇ paragraph @@ -701,8 +694,7 @@ mod test { third and - final"}, - Mode::Normal, - ) + final"}) + .await } } diff --git a/crates/vim/src/test/neovim_backed_test_context.rs b/crates/vim/src/test/neovim_backed_test_context.rs index 9b6bf976ca..7f9a84b666 100644 --- a/crates/vim/src/test/neovim_backed_test_context.rs +++ b/crates/vim/src/test/neovim_backed_test_context.rs @@ -1,9 +1,10 @@ -use std::ops::{Deref, DerefMut}; +use indoc::indoc; +use std::ops::{Deref, DerefMut, Range}; use collections::{HashMap, HashSet}; use gpui::ContextHandle; use language::OffsetRangeExt; -use util::test::marked_text_offsets; +use util::test::{generate_marked_text, marked_text_offsets}; use super::{neovim_connection::NeovimConnection, NeovimBackedBindingTestContext, VimTestContext}; use crate::state::Mode; @@ -112,6 +113,43 @@ impl<'a> NeovimBackedTestContext<'a> { context_handle } + pub async fn assert_shared_state(&mut self, marked_text: &str) { + let neovim = self.neovim_state().await; + if neovim != marked_text { + panic!( + indoc! {"Test is incorrect (currently expected != neovim state) + + # currently expected: + {} + # neovim state: + {} + # zed state: + {}"}, + marked_text, + neovim, + self.editor_state(), + ) + } + self.assert_editor_state(marked_text) + } + + pub async fn neovim_state(&mut self) -> String { + generate_marked_text( + self.neovim.text().await.as_str(), + &vec![self.neovim_selection().await], + true, + ) + } + + async fn neovim_selection(&mut self) -> Range { + let mut neovim_selection = self.neovim.selection().await; + // Zed selections adjust themselves to make the end point visually make sense + if neovim_selection.start > neovim_selection.end { + neovim_selection.start.column += 1; + } + neovim_selection.to_offset(&self.buffer_snapshot()) + } + pub async fn assert_state_matches(&mut self) { assert_eq!( self.neovim.text().await, @@ -120,13 +158,8 @@ impl<'a> NeovimBackedTestContext<'a> { self.assertion_context() ); - let mut neovim_selection = self.neovim.selection().await; - // Zed selections adjust themselves to make the end point visually make sense - if neovim_selection.start > neovim_selection.end { - neovim_selection.start.column += 1; - } - let neovim_selection = neovim_selection.to_offset(&self.buffer_snapshot()); - self.assert_editor_selections(vec![neovim_selection]); + let selections = vec![self.neovim_selection().await]; + self.assert_editor_selections(selections); if let Some(neovim_mode) = self.neovim.mode().await { assert_eq!(neovim_mode, self.mode(), "{}", self.assertion_context(),); diff --git a/crates/vim/test_data/test_start_end_of_paragraph.json b/crates/vim/test_data/test_start_end_of_paragraph.json new file mode 100644 index 0000000000..0de4d84f50 --- /dev/null +++ b/crates/vim/test_data/test_start_end_of_paragraph.json @@ -0,0 +1,13 @@ +{"Put":{"state":"ˇabc\ndef\n\nparagraph\nthe second\n\n\n\nthird and\nfinal"}} +{"Key":"}"} +{"Get":{"state":"abc\ndef\nˇ\nparagraph\nthe second\n\n\n\nthird and\nfinal","mode":"Normal"}} +{"Key":"{"} +{"Get":{"state":"ˇabc\ndef\n\nparagraph\nthe second\n\n\n\nthird and\nfinal","mode":"Normal"}} +{"Key":"2"} +{"Key":"}"} +{"Get":{"state":"abc\ndef\n\nparagraph\nthe second\nˇ\n\n\nthird and\nfinal","mode":"Normal"}} +{"Key":"}"} +{"Get":{"state":"abc\ndef\n\nparagraph\nthe second\n\n\n\nthird and\nfinaˇl","mode":"Normal"}} +{"Key":"2"} +{"Key":"{"} +{"Get":{"state":"abc\ndef\nˇ\nparagraph\nthe second\n\n\n\nthird and\nfinal","mode":"Normal"}} From d22a576f5e05f0a3b1a83e67b40489f9068c4e74 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 23:50:24 -0700 Subject: [PATCH 014/104] fix failing test --- crates/project/src/worktree.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 2b166bf6ef..7596b0fcb7 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1016,13 +1016,14 @@ impl LocalWorktree { cx.spawn(|this, mut cx| async move { write.await?; let (result, refreshes) = this.update(&mut cx, |this, cx| { - let mut refreshes = Vec::new(); + let mut refreshes = Vec::>>::new(); let refresh_paths = path.strip_prefix(&lowest_ancestor).unwrap(); for refresh_path in refresh_paths.ancestors() { - let refresh_full_path = lowest_ancestor.join(refresh_path); - if refresh_full_path.as_path() == path.deref() { + if refresh_path == Path::new("") { continue; } + let refresh_full_path = lowest_ancestor.join(refresh_path); + refreshes.push(this.as_local_mut().unwrap().refresh_entry( refresh_full_path.into(), None, From 3d6e063a6dcabe7644a10891417dc648793afa70 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 23:53:57 -0700 Subject: [PATCH 015/104] Fix method header --- crates/project/src/worktree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 7596b0fcb7..d86b98e0ec 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -982,7 +982,7 @@ impl LocalWorktree { } /// Find the lowest path in the worktree's datastructures that is an ancestor - pub fn lowest_ancestor(&self, path: &Path) -> PathBuf { + fn lowest_ancestor(&self, path: &Path) -> PathBuf { let mut lowest_ancestor = None; for path in path.ancestors() { if self.entry_for_path(path).is_some() { From d8d0bdc479ce926512697bc04a6c0a485b611ad4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 27 Jun 2023 12:02:30 +0200 Subject: [PATCH 016/104] WIP: git menu --- crates/collab_ui/src/branch_list.rs | 178 +++++++++++++++++++ crates/collab_ui/src/collab_titlebar_item.rs | 123 ++++++++++--- crates/collab_ui/src/collab_ui.rs | 2 + crates/fs/src/repository.rs | 32 +++- 4 files changed, 311 insertions(+), 24 deletions(-) create mode 100644 crates/collab_ui/src/branch_list.rs diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs new file mode 100644 index 0000000000..8d755e8aa4 --- /dev/null +++ b/crates/collab_ui/src/branch_list.rs @@ -0,0 +1,178 @@ +use client::{ContactRequestStatus, User, UserStore}; +use fuzzy::{StringMatch, StringMatchCandidate}; +use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext}; +use picker::{Picker, PickerDelegate, PickerEvent}; +use project::Project; +use std::sync::Arc; +use util::{ResultExt, TryFutureExt}; + +pub fn init(cx: &mut AppContext) { + Picker::::init(cx); +} + +pub type BranchList = Picker; + +pub fn build_branch_list( + project: ModelHandle, + cx: &mut ViewContext, +) -> BranchList { + Picker::new( + BranchListDelegate { + branches: vec!["Foo".into(), "bar/baz".into()], + matches: vec![], + project, + selected_index: 0, + }, + cx, + ) + .with_theme(|theme| theme.picker.clone()) +} + +pub struct BranchListDelegate { + branches: Vec, + matches: Vec, + project: ModelHandle, + selected_index: usize, +} + +impl PickerDelegate for BranchListDelegate { + fn placeholder_text(&self) -> Arc { + "Select branch...".into() + } + + fn match_count(&self) -> usize { + self.matches.len() + } + + fn selected_index(&self) -> usize { + self.selected_index + } + + fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext>) { + self.selected_index = ix; + } + + fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()> { + cx.spawn(move |picker, mut cx| async move { + let candidates = picker + .read_with(&mut cx, |view, cx| { + let delegate = view.delegate(); + let project = delegate.project.read(&cx); + let mut cwd = project + .visible_worktrees(cx) + .next() + .unwrap() + .read(cx) + .root_entry() + .unwrap() + .path + .to_path_buf(); + cwd.push(".git"); + let branches = project.fs().open_repo(&cwd).unwrap().lock().branches(); + branches + .unwrap() + .iter() + .cloned() + .enumerate() + .map(|(ix, command)| StringMatchCandidate { + id: ix, + string: command.clone(), + char_bag: command.chars().collect(), + }) + .collect::>() + }) + .unwrap(); + let matches = if query.is_empty() { + candidates + .into_iter() + .enumerate() + .map(|(index, candidate)| StringMatch { + candidate_id: index, + string: candidate.string, + positions: Vec::new(), + score: 0.0, + }) + .collect() + } else { + fuzzy::match_strings( + &candidates, + &query, + true, + 10000, + &Default::default(), + cx.background(), + ) + .await + }; + picker + .update(&mut cx, |picker, _| { + let delegate = picker.delegate_mut(); + //delegate.branches = actions; + delegate.matches = matches; + if delegate.matches.is_empty() { + delegate.selected_index = 0; + } else { + delegate.selected_index = + core::cmp::min(delegate.selected_index, delegate.matches.len() - 1); + } + }) + .log_err(); + }) + } + + fn confirm(&mut self, cx: &mut ViewContext>) { + log::error!("confirm {}", self.selected_index()); + let current_pick = self.selected_index(); + let current_pick = self.matches[current_pick].string.clone(); + log::error!("Hi? {current_pick}"); + let project = self.project.read(cx); + let mut cwd = project + .visible_worktrees(cx) + .next() + .unwrap() + .read(cx) + .root_entry() + .unwrap() + .path + .to_path_buf(); + cwd.push(".git"); + log::error!("{current_pick}"); + project + .fs() + .open_repo(&cwd) + .unwrap() + .lock() + .change_branch(¤t_pick) + .log_err(); + cx.emit(PickerEvent::Dismiss); + } + + fn dismissed(&mut self, cx: &mut ViewContext>) { + cx.emit(PickerEvent::Dismiss); + } + + fn render_match( + &self, + ix: usize, + mouse_state: &mut MouseState, + selected: bool, + cx: &gpui::AppContext, + ) -> AnyElement> { + let theme = &theme::current(cx); + let user = &self.matches[ix]; + let style = theme.picker.item.in_state(selected).style_for(mouse_state); + Flex::row() + .with_child( + Label::new(user.string.clone(), style.label.clone()) + .with_highlights(user.positions.clone()) + .contained() + .aligned() + .left(), + ) + .contained() + .with_style(style.container) + .constrained() + .with_height(theme.contact_finder.row_height) + .into_any() + } +} diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 5caebb9f0c..338ba6cf27 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -1,5 +1,8 @@ use crate::{ - contact_notification::ContactNotification, contacts_popover, face_pile::FacePile, + branch_list::{build_branch_list, BranchList}, + contact_notification::ContactNotification, + contacts_popover, + face_pile::FacePile, toggle_deafen, toggle_mute, toggle_screen_sharing, LeaveCall, ToggleDeafen, ToggleMute, ToggleScreenSharing, }; @@ -12,12 +15,14 @@ use gpui::{ actions, color::Color, elements::*, + fonts::TextStyle, geometry::{rect::RectF, vector::vec2f, PathBuilder}, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, AppContext, Entity, ImageData, LayoutContext, ModelHandle, SceneBuilder, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, }; +use picker::PickerEvent; use project::{Project, RepositoryEntry}; use std::{ops::Range, sync::Arc}; use theme::{AvatarStyle, Theme}; @@ -31,6 +36,8 @@ actions!( [ ToggleContactsMenu, ToggleUserMenu, + ToggleVcsMenu, + SwitchBranch, ShareProject, UnshareProject, ] @@ -41,6 +48,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(CollabTitlebarItem::share_project); cx.add_action(CollabTitlebarItem::unshare_project); cx.add_action(CollabTitlebarItem::toggle_user_menu); + cx.add_action(CollabTitlebarItem::toggle_vcs_menu); } pub struct CollabTitlebarItem { @@ -49,6 +57,7 @@ pub struct CollabTitlebarItem { client: Arc, workspace: WeakViewHandle, contacts_popover: Option>, + branch_popover: Option>, user_menu: ViewHandle, _subscriptions: Vec, } @@ -69,12 +78,11 @@ impl View for CollabTitlebarItem { return Empty::new().into_any(); }; - let project = self.project.read(cx); let theme = theme::current(cx).clone(); let mut left_container = Flex::row(); let mut right_container = Flex::row().align_children_center(); - left_container.add_child(self.collect_title_root_names(&project, theme.clone(), cx)); + left_container.add_child(self.collect_title_root_names(theme.clone(), cx)); let user = self.user_store.read(cx).current_user(); let peer_id = self.client.peer_id(); @@ -182,22 +190,28 @@ impl CollabTitlebarItem { menu.set_position_mode(OverlayPositionMode::Local); menu }), + branch_popover: None, _subscriptions: subscriptions, } } fn collect_title_root_names( &self, - project: &Project, theme: Arc, - cx: &ViewContext, + cx: &mut ViewContext, ) -> AnyElement { - let mut names_and_branches = project.visible_worktrees(cx).map(|worktree| { - let worktree = worktree.read(cx); - (worktree.root_name(), worktree.root_git_entry()) - }); + let project = self.project.read(cx); - let (name, entry) = names_and_branches.next().unwrap_or(("", None)); + let (name, entry) = { + let mut names_and_branches = project.visible_worktrees(cx).map(|worktree| { + let worktree = worktree.read(cx); + (worktree.root_name(), worktree.root_git_entry()) + }); + + names_and_branches.next().unwrap_or(("", None)) + }; + + let name = name.to_owned(); let branch_prepended = entry .as_ref() .and_then(RepositoryEntry::branch) @@ -212,22 +226,37 @@ impl CollabTitlebarItem { text: text_style, highlight_text: Some(highlight), }; + let highlights = (0..name.len()).into_iter().collect(); let mut ret = Flex::row().with_child( - Label::new(name.to_owned(), style.clone()) - .with_highlights((0..name.len()).into_iter().collect()) - .contained() - .aligned() - .left() - .into_any_named("title-project-name"), + Stack::new().with_child( + Label::new(name, style.clone()) + .with_highlights(highlights) + .contained() + .aligned() + .left() + .into_any_named("title-project-name"), + ), ); if let Some(git_branch) = branch_prepended { ret = ret.with_child( - Label::new(git_branch, style) - .contained() - .with_margin_right(item_spacing) - .aligned() - .left() - .into_any_named("title-project-branch"), + Stack::new() + .with_child( + MouseEventHandler::::new(0, cx, |state, _| { + Label::new(git_branch, style) + .contained() + .with_margin_right(item_spacing) + .aligned() + .left() + .into_any_named("title-project-branch") + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, this, cx| { + this.toggle_vcs_menu(&Default::default(), cx) + }), + ) + .with_children( + self.render_branches_popover_host(&theme.workspace.titlebar, cx), + ), ) } ret.into_any() @@ -320,7 +349,55 @@ impl CollabTitlebarItem { user_menu.toggle(Default::default(), AnchorCorner::TopRight, items, cx); }); } + fn render_branches_popover_host<'a>( + &'a self, + _theme: &'a theme::Titlebar, + cx: &'a mut ViewContext, + ) -> Option> { + self.branch_popover.as_ref().map(|child| { + let theme = theme::current(cx).clone(); + let child = ChildView::new(child, cx); + let child = MouseEventHandler::::new(0, cx, |_, _| { + Flex::column() + .with_child(child.flex(1., true)) + .contained() + .with_style(theme.contacts_popover.container) + .constrained() + .with_width(theme.contacts_popover.width) + .with_height(theme.contacts_popover.height) + }) + .on_click(MouseButton::Left, |_, _, _| {}) + .on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(())) + .into_any(); + Overlay::new(child) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .aligned() + .bottom() + .left() + .into_any() + }) + } + pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext) { + if self.branch_popover.take().is_none() { + let view = cx.add_view(|cx| build_branch_list(self.project.clone(), cx)); + cx.subscribe(&view, |this, _, event, cx| { + match event { + PickerEvent::Dismiss => { + this.contacts_popover = None; + } + } + + cx.notify(); + }) + .detach(); + self.branch_popover = Some(view); + } + + cx.notify(); + } fn render_toggle_contacts_button( &self, theme: &Theme, @@ -733,7 +810,7 @@ impl CollabTitlebarItem { self.contacts_popover.as_ref().map(|popover| { Overlay::new(ChildView::new(popover, cx)) .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopRight) + .with_anchor_corner(AnchorCorner::TopLeft) .with_z_index(999) .aligned() .bottom() diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs index a809b9c7e6..26d9c70a43 100644 --- a/crates/collab_ui/src/collab_ui.rs +++ b/crates/collab_ui/src/collab_ui.rs @@ -1,3 +1,4 @@ +mod branch_list; mod collab_titlebar_item; mod contact_finder; mod contact_list; @@ -28,6 +29,7 @@ actions!( ); pub fn init(app_state: &Arc, cx: &mut AppContext) { + branch_list::init(cx); collab_titlebar_item::init(cx); contact_list::init(cx); contact_finder::init(cx); diff --git a/crates/fs/src/repository.rs b/crates/fs/src/repository.rs index 488262887f..af6198eda4 100644 --- a/crates/fs/src/repository.rs +++ b/crates/fs/src/repository.rs @@ -1,6 +1,6 @@ use anyhow::Result; use collections::HashMap; -use git2::ErrorCode; +use git2::{BranchType, ErrorCode}; use parking_lot::Mutex; use rpc::proto; use serde_derive::{Deserialize, Serialize}; @@ -27,6 +27,12 @@ pub trait GitRepository: Send { fn statuses(&self) -> Option>; fn status(&self, path: &RepoPath) -> Result>; + fn branches(&self) -> Result> { + Ok(vec![]) + } + fn change_branch(&self, _: &str) -> Result<()> { + Ok(()) + } } impl std::fmt::Debug for dyn GitRepository { @@ -106,6 +112,30 @@ impl GitRepository for LibGitRepository { } } } + fn branches(&self) -> Result> { + let local_branches = self.branches(Some(BranchType::Local))?; + let valid_branches = local_branches + .filter_map(|branch| { + branch + .ok() + .map(|(branch, _)| branch.name().ok().flatten().map(String::from)) + .flatten() + }) + .collect(); + Ok(valid_branches) + } + fn change_branch(&self, name: &str) -> Result<()> { + let revision = self.find_branch(name, BranchType::Local)?; + let revision = revision.get(); + let as_tree = revision.peel_to_tree()?; + self.checkout_tree(as_tree.as_object(), None)?; + self.set_head( + revision + .name() + .ok_or_else(|| anyhow::anyhow!("Branch name could not be retrieved"))?, + )?; + Ok(()) + } } fn read_status(status: git2::Status) -> Option { From ac6e9c88e9400da223e2d0996c11c40d58ee24cd Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 27 Jun 2023 12:22:44 +0200 Subject: [PATCH 017/104] Render header and footer of git menu --- crates/collab_ui/src/branch_list.rs | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 8d755e8aa4..d946b9da3d 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -22,6 +22,7 @@ pub fn build_branch_list( matches: vec![], project, selected_index: 0, + last_query: String::default(), }, cx, ) @@ -33,6 +34,7 @@ pub struct BranchListDelegate { matches: Vec, project: ModelHandle, selected_index: usize, + last_query: String, } impl PickerDelegate for BranchListDelegate { @@ -109,6 +111,7 @@ impl PickerDelegate for BranchListDelegate { let delegate = picker.delegate_mut(); //delegate.branches = actions; delegate.matches = matches; + delegate.last_query = query; if delegate.matches.is_empty() { delegate.selected_index = 0; } else { @@ -175,4 +178,34 @@ impl PickerDelegate for BranchListDelegate { .with_height(theme.contact_finder.row_height) .into_any() } + fn render_header(&self, cx: &AppContext) -> Option>> { + let theme = &theme::current(cx); + let style = theme.picker.no_matches.label.clone(); + if self.last_query.is_empty() { + Some( + Flex::row() + .with_child(Label::new("Recent branches", style)) + .into_any(), + ) + } else { + Some( + Flex::row() + .with_child(Label::new("Branches", style)) + .into_any(), + ) + } + } + fn render_footer(&self, cx: &AppContext) -> Option>> { + if !self.last_query.is_empty() && !self.matches.is_empty() { + let theme = &theme::current(cx); + let style = theme.picker.no_matches.label.clone(); + Some( + Flex::row() + .with_child(Label::new(format!("{} matches", self.matches.len()), style)) + .into_any(), + ) + } else { + None + } + } } From 6747acbb84e9787fa530ba015fd4f17a4f085877 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 27 Jun 2023 12:40:53 +0200 Subject: [PATCH 018/104] Trail off branch names --- crates/collab_ui/src/branch_list.rs | 25 +++++++++++++------- crates/collab_ui/src/collab_titlebar_item.rs | 1 - 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index d946b9da3d..ddd884523a 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,4 +1,3 @@ -use client::{ContactRequestStatus, User, UserStore}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext}; use picker::{Picker, PickerDelegate, PickerEvent}; @@ -124,10 +123,8 @@ impl PickerDelegate for BranchListDelegate { } fn confirm(&mut self, cx: &mut ViewContext>) { - log::error!("confirm {}", self.selected_index()); let current_pick = self.selected_index(); let current_pick = self.matches[current_pick].string.clone(); - log::error!("Hi? {current_pick}"); let project = self.project.read(cx); let mut cwd = project .visible_worktrees(cx) @@ -139,7 +136,6 @@ impl PickerDelegate for BranchListDelegate { .path .to_path_buf(); cwd.push(".git"); - log::error!("{current_pick}"); project .fs() .open_repo(&cwd) @@ -161,13 +157,21 @@ impl PickerDelegate for BranchListDelegate { selected: bool, cx: &gpui::AppContext, ) -> AnyElement> { + const DISPLAYED_MATCH_LEN: usize = 29; let theme = &theme::current(cx); - let user = &self.matches[ix]; + let hit = &self.matches[ix]; + let shortened_branch_name = util::truncate_and_trailoff(&hit.string, DISPLAYED_MATCH_LEN); + let highlights = hit + .positions + .iter() + .copied() + .filter(|index| index < &DISPLAYED_MATCH_LEN) + .collect(); let style = theme.picker.item.in_state(selected).style_for(mouse_state); Flex::row() .with_child( - Label::new(user.string.clone(), style.label.clone()) - .with_highlights(user.positions.clone()) + Label::new(shortened_branch_name.clone(), style.label.clone()) + .with_highlights(highlights) .contained() .aligned() .left(), @@ -199,9 +203,14 @@ impl PickerDelegate for BranchListDelegate { if !self.last_query.is_empty() && !self.matches.is_empty() { let theme = &theme::current(cx); let style = theme.picker.no_matches.label.clone(); + // Render "1 match" and "0 matches", "42 matches"etc. + let suffix = if self.matches.len() == 1 { "" } else { "es" }; Some( Flex::row() - .with_child(Label::new(format!("{} matches", self.matches.len()), style)) + .with_child(Label::new( + format!("{} match{}", self.matches.len(), suffix), + style, + )) .into_any(), ) } else { diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 338ba6cf27..e306aa20b3 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -361,7 +361,6 @@ impl CollabTitlebarItem { Flex::column() .with_child(child.flex(1., true)) .contained() - .with_style(theme.contacts_popover.container) .constrained() .with_width(theme.contacts_popover.width) .with_height(theme.contacts_popover.height) From 3027e4729abf2d9c83fe0d06683fa9834a4180f4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:28:50 +0200 Subject: [PATCH 019/104] Add timestamps to branches --- Cargo.lock | 1 + crates/collab_ui/src/branch_list.rs | 6 ++---- crates/fs/Cargo.toml | 1 + crates/fs/src/repository.rs | 21 +++++++++++++++------ 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9b2e29ea0..a59332520b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2549,6 +2549,7 @@ dependencies = [ "smol", "sum_tree", "tempfile", + "time 0.3.21", "util", ] diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index ddd884523a..7da984a599 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -17,7 +17,6 @@ pub fn build_branch_list( ) -> BranchList { Picker::new( BranchListDelegate { - branches: vec!["Foo".into(), "bar/baz".into()], matches: vec![], project, selected_index: 0, @@ -29,7 +28,6 @@ pub fn build_branch_list( } pub struct BranchListDelegate { - branches: Vec, matches: Vec, project: ModelHandle, selected_index: usize, @@ -77,8 +75,8 @@ impl PickerDelegate for BranchListDelegate { .enumerate() .map(|(ix, command)| StringMatchCandidate { id: ix, - string: command.clone(), - char_bag: command.chars().collect(), + char_bag: command.name.chars().collect(), + string: command.name.into(), }) .collect::>() }) diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index cb738f567c..b3ebd224b0 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -31,6 +31,7 @@ serde_derive.workspace = true serde_json.workspace = true log.workspace = true libc = "0.2" +time.workspace = true [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } diff --git a/crates/fs/src/repository.rs b/crates/fs/src/repository.rs index af6198eda4..36df0dfb98 100644 --- a/crates/fs/src/repository.rs +++ b/crates/fs/src/repository.rs @@ -16,6 +16,12 @@ use util::ResultExt; pub use git2::Repository as LibGitRepository; +#[derive(Clone, Debug, Hash, PartialEq)] +pub struct Branch { + pub name: Box, + /// Timestamp of most recent commit, normalized to Unix Epoch format. + pub unix_timestamp: Option, +} #[async_trait::async_trait] pub trait GitRepository: Send { fn reload_index(&self); @@ -27,7 +33,7 @@ pub trait GitRepository: Send { fn statuses(&self) -> Option>; fn status(&self, path: &RepoPath) -> Result>; - fn branches(&self) -> Result> { + fn branches(&self) -> Result> { Ok(vec![]) } fn change_branch(&self, _: &str) -> Result<()> { @@ -112,14 +118,17 @@ impl GitRepository for LibGitRepository { } } } - fn branches(&self) -> Result> { + fn branches(&self) -> Result> { let local_branches = self.branches(Some(BranchType::Local))?; let valid_branches = local_branches .filter_map(|branch| { - branch - .ok() - .map(|(branch, _)| branch.name().ok().flatten().map(String::from)) - .flatten() + branch.ok().and_then(|(branch, _)| { + let name = branch.name().ok().flatten().map(Box::from)?; + Some(Branch { + name, + unix_timestamp: None, + }) + }) }) .collect(); Ok(valid_branches) From 54fad5969f5f0aa649cccb27493e48d7cf99f5b3 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 27 Jun 2023 14:20:36 +0200 Subject: [PATCH 020/104] List recent branches --- crates/collab_ui/src/branch_list.rs | 23 ++++++++++++++++++----- crates/fs/src/repository.rs | 9 ++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 7da984a599..146e4c8041 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -2,7 +2,7 @@ use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext}; use picker::{Picker, PickerDelegate, PickerEvent}; use project::Project; -use std::sync::Arc; +use std::{cmp::Ordering, sync::Arc}; use util::{ResultExt, TryFutureExt}; pub fn init(cx: &mut AppContext) { @@ -67,9 +67,23 @@ impl PickerDelegate for BranchListDelegate { .path .to_path_buf(); cwd.push(".git"); - let branches = project.fs().open_repo(&cwd).unwrap().lock().branches(); - branches + let mut branches = project + .fs() + .open_repo(&cwd) .unwrap() + .lock() + .branches() + .unwrap(); + if query.is_empty() { + const RECENT_BRANCHES_COUNT: usize = 10; + // Do a partial sort to show recent-ish branches first. + branches.select_nth_unstable_by(RECENT_BRANCHES_COUNT, |lhs, rhs| { + rhs.unix_timestamp.cmp(&lhs.unix_timestamp) + }); + branches.truncate(RECENT_BRANCHES_COUNT); + branches.sort_unstable_by(|lhs, rhs| lhs.name.cmp(&rhs.name)); + } + branches .iter() .cloned() .enumerate() @@ -106,15 +120,14 @@ impl PickerDelegate for BranchListDelegate { picker .update(&mut cx, |picker, _| { let delegate = picker.delegate_mut(); - //delegate.branches = actions; delegate.matches = matches; - delegate.last_query = query; if delegate.matches.is_empty() { delegate.selected_index = 0; } else { delegate.selected_index = core::cmp::min(delegate.selected_index, delegate.matches.len() - 1); } + delegate.last_query = query; }) .log_err(); }) diff --git a/crates/fs/src/repository.rs b/crates/fs/src/repository.rs index 36df0dfb98..0e5fd8343f 100644 --- a/crates/fs/src/repository.rs +++ b/crates/fs/src/repository.rs @@ -124,9 +124,16 @@ impl GitRepository for LibGitRepository { .filter_map(|branch| { branch.ok().and_then(|(branch, _)| { let name = branch.name().ok().flatten().map(Box::from)?; + let timestamp = branch.get().peel_to_commit().ok()?.time(); + let unix_timestamp = timestamp.seconds(); + let timezone_offset = timestamp.offset_minutes(); + let utc_offset = + time::UtcOffset::from_whole_seconds(timezone_offset * 60).ok()?; + let unix_timestamp = + time::OffsetDateTime::from_unix_timestamp(unix_timestamp).ok()?; Some(Branch { name, - unix_timestamp: None, + unix_timestamp: Some(unix_timestamp.to_offset(utc_offset).unix_timestamp()), }) }) }) From c84f3b3bfc2a2434017ab23e3bcaeae98424623f Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 27 Jun 2023 20:12:20 +0200 Subject: [PATCH 021/104] Add toast for git checkout failure --- crates/collab_ui/src/branch_list.rs | 31 ++++++++++++++------ crates/collab_ui/src/collab_titlebar_item.rs | 22 +++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 146e4c8041..2558b24ae8 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,9 +1,10 @@ use fuzzy::{StringMatch, StringMatchCandidate}; -use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext}; +use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext, ViewHandle}; use picker::{Picker, PickerDelegate, PickerEvent}; use project::Project; use std::{cmp::Ordering, sync::Arc}; use util::{ResultExt, TryFutureExt}; +use workspace::{Toast, Workspace}; pub fn init(cx: &mut AppContext) { Picker::::init(cx); @@ -12,13 +13,13 @@ pub fn init(cx: &mut AppContext) { pub type BranchList = Picker; pub fn build_branch_list( - project: ModelHandle, + workspace: ViewHandle, cx: &mut ViewContext, ) -> BranchList { Picker::new( BranchListDelegate { matches: vec![], - project, + workspace, selected_index: 0, last_query: String::default(), }, @@ -29,7 +30,7 @@ pub fn build_branch_list( pub struct BranchListDelegate { matches: Vec, - project: ModelHandle, + workspace: ViewHandle, selected_index: usize, last_query: String, } @@ -56,7 +57,7 @@ impl PickerDelegate for BranchListDelegate { let candidates = picker .read_with(&mut cx, |view, cx| { let delegate = view.delegate(); - let project = delegate.project.read(&cx); + let project = delegate.workspace.read(cx).project().read(&cx); let mut cwd = project .visible_worktrees(cx) .next() @@ -136,7 +137,7 @@ impl PickerDelegate for BranchListDelegate { fn confirm(&mut self, cx: &mut ViewContext>) { let current_pick = self.selected_index(); let current_pick = self.matches[current_pick].string.clone(); - let project = self.project.read(cx); + let project = self.workspace.read(cx).project().read(cx); let mut cwd = project .visible_worktrees(cx) .next() @@ -147,13 +148,25 @@ impl PickerDelegate for BranchListDelegate { .path .to_path_buf(); cwd.push(".git"); - project + let status = project .fs() .open_repo(&cwd) .unwrap() .lock() - .change_branch(¤t_pick) - .log_err(); + .change_branch(¤t_pick); + if let Err(err) = &status { + const GIT_CHECKOUT_FAILURE_ID: usize = 2048; + self.workspace.update(cx, |model, ctx| { + model.show_toast( + Toast::new( + GIT_CHECKOUT_FAILURE_ID, + format!("Failed to check out branch `{current_pick}`, error: `{err}`"), + ), + ctx, + ) + }); + } + status.log_err(); cx.emit(PickerEvent::Dismiss); } diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index e306aa20b3..b38ac39798 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -381,18 +381,20 @@ impl CollabTitlebarItem { } pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext) { if self.branch_popover.take().is_none() { - let view = cx.add_view(|cx| build_branch_list(self.project.clone(), cx)); - cx.subscribe(&view, |this, _, event, cx| { - match event { - PickerEvent::Dismiss => { - this.contacts_popover = None; + if let Some(workspace) = self.workspace.upgrade(cx) { + let view = cx.add_view(|cx| build_branch_list(workspace, cx)); + cx.subscribe(&view, |this, _, event, cx| { + match event { + PickerEvent::Dismiss => { + this.contacts_popover = None; + } } - } - cx.notify(); - }) - .detach(); - self.branch_popover = Some(view); + cx.notify(); + }) + .detach(); + self.branch_popover = Some(view); + } } cx.notify(); From aeafa6f6d6242dd81c0162e6528b240f3c4b61c2 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:40:10 +0200 Subject: [PATCH 022/104] Fix build after rebase --- crates/collab_ui/src/collab_titlebar_item.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index b38ac39798..48a4e12ff5 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -254,9 +254,7 @@ impl CollabTitlebarItem { this.toggle_vcs_menu(&Default::default(), cx) }), ) - .with_children( - self.render_branches_popover_host(&theme.workspace.titlebar, cx), - ), + .with_children(self.render_branches_popover_host(&theme.titlebar, cx)), ) } ret.into_any() From e57364ede6d4e3f89a560934ed814e9ec93138a0 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:42:20 +0200 Subject: [PATCH 023/104] Remove unnecessary imports --- crates/collab_ui/src/branch_list.rs | 7 +++---- crates/collab_ui/src/collab_titlebar_item.rs | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 2558b24ae8..2fb8721c94 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,9 +1,8 @@ use fuzzy::{StringMatch, StringMatchCandidate}; -use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext, ViewHandle}; +use gpui::{elements::*, AppContext, MouseState, Task, ViewContext, ViewHandle}; use picker::{Picker, PickerDelegate, PickerEvent}; -use project::Project; -use std::{cmp::Ordering, sync::Arc}; -use util::{ResultExt, TryFutureExt}; +use std::sync::Arc; +use util::ResultExt; use workspace::{Toast, Workspace}; pub fn init(cx: &mut AppContext) { diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 48a4e12ff5..e6a0c98265 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -15,7 +15,6 @@ use gpui::{ actions, color::Color, elements::*, - fonts::TextStyle, geometry::{rect::RectF, vector::vec2f, PathBuilder}, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, @@ -241,7 +240,7 @@ impl CollabTitlebarItem { ret = ret.with_child( Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |_, _| { Label::new(git_branch, style) .contained() .with_margin_right(item_spacing) From 98f71a7fa3822840665c5fe7a1e25909b12d98ed Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 11:47:50 +0200 Subject: [PATCH 024/104] Trail off project/branch name --- crates/collab_ui/src/collab_titlebar_item.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index e6a0c98265..5bef89d1ee 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -28,7 +28,8 @@ use theme::{AvatarStyle, Theme}; use util::ResultExt; use workspace::{FollowNextCollaborator, Workspace}; -// const MAX_TITLE_LENGTH: usize = 75; +const MAX_PROJECT_NAME_LENGTH: usize = 40; +const MAX_BRANCH_NAME_LENGTH: usize = 40; actions!( collab, @@ -210,11 +211,16 @@ impl CollabTitlebarItem { names_and_branches.next().unwrap_or(("", None)) }; - let name = name.to_owned(); + let name = util::truncate_and_trailoff(name, MAX_PROJECT_NAME_LENGTH); let branch_prepended = entry .as_ref() .and_then(RepositoryEntry::branch) - .map(|branch| format!("/{branch}")); + .map(|branch| { + format!( + "/{}", + util::truncate_and_trailoff(&branch, MAX_BRANCH_NAME_LENGTH) + ) + }); let text_style = theme.titlebar.title.clone(); let item_spacing = theme.titlebar.item_spacing; From 1eb0f3d09156f01c280793d080702e3c0b78a7fb Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 12:12:35 +0200 Subject: [PATCH 025/104] Update toast for checkout failure --- crates/collab_ui/src/branch_list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 2fb8721c94..eb6b9c6f54 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -159,7 +159,7 @@ impl PickerDelegate for BranchListDelegate { model.show_toast( Toast::new( GIT_CHECKOUT_FAILURE_ID, - format!("Failed to check out branch `{current_pick}`, error: `{err}`"), + format!("Failed to checkout branch '{current_pick}', check for conflicts or unstashed files"), ), ctx, ) From d000ea97398d64613056a4dba9f6602257bb1e36 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 12:57:49 +0200 Subject: [PATCH 026/104] Fix warning about unused variable --- crates/collab_ui/src/branch_list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index eb6b9c6f54..2d014cc1b9 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -153,7 +153,7 @@ impl PickerDelegate for BranchListDelegate { .unwrap() .lock() .change_branch(¤t_pick); - if let Err(err) = &status { + if status.is_err() { const GIT_CHECKOUT_FAILURE_ID: usize = 2048; self.workspace.update(cx, |model, ctx| { model.show_toast( From 888d3b3fd620722a44483222cd4c3201153b15a4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:03:01 +0200 Subject: [PATCH 027/104] Project dropdown menu --- Cargo.lock | 2 + crates/collab_ui/Cargo.toml | 2 + crates/collab_ui/src/collab_titlebar_item.rs | 79 +++++++++++++++++-- crates/recent_projects/Cargo.toml | 1 + crates/recent_projects/src/recent_projects.rs | 21 ++++- 5 files changed, 95 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a59332520b..d16248c85a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1415,6 +1415,7 @@ dependencies = [ "picker", "postage", "project", + "recent_projects", "serde", "serde_derive", "settings", @@ -5376,6 +5377,7 @@ version = "0.1.0" dependencies = [ "db", "editor", + "futures 0.3.28", "fuzzy", "gpui", "language", diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index ee410ccba7..f81885c07a 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -35,6 +35,7 @@ gpui = { path = "../gpui" } menu = { path = "../menu" } picker = { path = "../picker" } project = { path = "../project" } +recent_projects = {path = "../recent_projects"} settings = { path = "../settings" } theme = { path = "../theme" } theme_selector = { path = "../theme_selector" } @@ -42,6 +43,7 @@ util = { path = "../util" } workspace = { path = "../workspace" } zed-actions = {path = "../zed-actions"} + anyhow.workspace = true futures.workspace = true log.workspace = true diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 5bef89d1ee..8dccf2a71a 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -23,6 +23,7 @@ use gpui::{ }; use picker::PickerEvent; use project::{Project, RepositoryEntry}; +use recent_projects::{build_recent_projects, RecentProjects}; use std::{ops::Range, sync::Arc}; use theme::{AvatarStyle, Theme}; use util::ResultExt; @@ -37,6 +38,7 @@ actions!( ToggleContactsMenu, ToggleUserMenu, ToggleVcsMenu, + ToggleProjectMenu, SwitchBranch, ShareProject, UnshareProject, @@ -49,6 +51,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(CollabTitlebarItem::unshare_project); cx.add_action(CollabTitlebarItem::toggle_user_menu); cx.add_action(CollabTitlebarItem::toggle_vcs_menu); + cx.add_action(CollabTitlebarItem::toggle_project_menu); } pub struct CollabTitlebarItem { @@ -58,6 +61,7 @@ pub struct CollabTitlebarItem { workspace: WeakViewHandle, contacts_popover: Option>, branch_popover: Option>, + project_popover: Option>, user_menu: ViewHandle, _subscriptions: Vec, } @@ -191,6 +195,7 @@ impl CollabTitlebarItem { menu }), branch_popover: None, + project_popover: None, _subscriptions: subscriptions, } } @@ -233,14 +238,22 @@ impl CollabTitlebarItem { }; let highlights = (0..name.len()).into_iter().collect(); let mut ret = Flex::row().with_child( - Stack::new().with_child( - Label::new(name, style.clone()) - .with_highlights(highlights) - .contained() - .aligned() - .left() - .into_any_named("title-project-name"), - ), + Stack::new() + .with_child( + MouseEventHandler::::new(0, cx, |_, _| { + Label::new(name, style.clone()) + .with_highlights(highlights) + .contained() + .aligned() + .left() + .into_any_named("title-project-name") + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, this, cx| { + this.toggle_project_menu(&Default::default(), cx) + }), + ) + .with_children(self.render_project_popover_host(&theme.titlebar, cx)), ); if let Some(git_branch) = branch_prepended { ret = ret.with_child( @@ -382,6 +395,36 @@ impl CollabTitlebarItem { .into_any() }) } + fn render_project_popover_host<'a>( + &'a self, + _theme: &'a theme::Titlebar, + cx: &'a mut ViewContext, + ) -> Option> { + self.project_popover.as_ref().map(|child| { + let theme = theme::current(cx).clone(); + let child = ChildView::new(child, cx); + let child = MouseEventHandler::::new(0, cx, |_, _| { + Flex::column() + .with_child(child.flex(1., true)) + .contained() + .constrained() + .with_width(theme.contacts_popover.width) + .with_height(theme.contacts_popover.height) + }) + .on_click(MouseButton::Left, |_, _, _| {}) + .on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(())) + .into_any(); + + Overlay::new(child) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .aligned() + .bottom() + .left() + .into_any() + }) + } pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext) { if self.branch_popover.take().is_none() { if let Some(workspace) = self.workspace.upgrade(cx) { @@ -402,6 +445,26 @@ impl CollabTitlebarItem { cx.notify(); } + + pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { + log::error!("Toggling project menu"); + if self.project_popover.take().is_none() { + let view = cx.add_view(|cx| build_recent_projects(self.workspace.clone(), cx)); + cx.subscribe(&view, |this, _, event, cx| { + match event { + PickerEvent::Dismiss => { + this.project_popover = None; + } + } + + cx.notify(); + }) + .detach(); + self.project_popover = Some(view); + } + + cx.notify(); + } fn render_toggle_contacts_button( &self, theme: &Theme, diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index 14f8853c9c..51774e8feb 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -21,6 +21,7 @@ util = { path = "../util"} theme = { path = "../theme" } workspace = { path = "../workspace" } +futures.workspace = true ordered-float.workspace = true postage.workspace = true smol.workspace = true diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index b13f72da0b..ed901a7da8 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -64,9 +64,26 @@ fn toggle( })) } -type RecentProjects = Picker; +pub fn build_recent_projects( + workspace: WeakViewHandle, + cx: &mut ViewContext, +) -> RecentProjects { + let workspaces = futures::executor::block_on(async { + WORKSPACE_DB + .recent_workspaces_on_disk() + .await + .unwrap_or_default() + .into_iter() + .map(|(_, location)| location) + .collect() + }); + Picker::new(RecentProjectsDelegate::new(workspace, workspaces), cx) + .with_theme(|theme| theme.picker.clone()) +} -struct RecentProjectsDelegate { +pub type RecentProjects = Picker; + +pub struct RecentProjectsDelegate { workspace: WeakViewHandle, workspace_locations: Vec, selected_match_index: usize, From 818ddbc7031f764a444e103b77eecd4eb2aba91b Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:04:58 +0200 Subject: [PATCH 028/104] Make project dropdown exclusive wrt git menu --- crates/collab_ui/src/collab_titlebar_item.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 8dccf2a71a..c78ce2f4e1 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -439,6 +439,7 @@ impl CollabTitlebarItem { cx.notify(); }) .detach(); + self.project_popover.take(); self.branch_popover = Some(view); } } @@ -447,7 +448,6 @@ impl CollabTitlebarItem { } pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { - log::error!("Toggling project menu"); if self.project_popover.take().is_none() { let view = cx.add_view(|cx| build_recent_projects(self.workspace.clone(), cx)); cx.subscribe(&view, |this, _, event, cx| { @@ -460,6 +460,7 @@ impl CollabTitlebarItem { cx.notify(); }) .detach(); + self.branch_popover.take(); self.project_popover = Some(view); } From 081e340d26285692785871fe3c754153463d54e7 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 29 Jun 2023 19:07:51 +0200 Subject: [PATCH 029/104] Do not query db on foreground thread. Co-authored-by: Mikayla --- crates/collab_ui/src/collab_titlebar_item.rs | 42 +++++++++++++------ crates/recent_projects/src/recent_projects.rs | 10 +---- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index c78ce2f4e1..511113a360 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -27,7 +27,7 @@ use recent_projects::{build_recent_projects, RecentProjects}; use std::{ops::Range, sync::Arc}; use theme::{AvatarStyle, Theme}; use util::ResultExt; -use workspace::{FollowNextCollaborator, Workspace}; +use workspace::{FollowNextCollaborator, Workspace, WORKSPACE_DB}; const MAX_PROJECT_NAME_LENGTH: usize = 40; const MAX_BRANCH_NAME_LENGTH: usize = 40; @@ -448,23 +448,39 @@ impl CollabTitlebarItem { } pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { + let workspace = self.workspace.clone(); if self.project_popover.take().is_none() { - let view = cx.add_view(|cx| build_recent_projects(self.workspace.clone(), cx)); - cx.subscribe(&view, |this, _, event, cx| { - match event { - PickerEvent::Dismiss => { - this.project_popover = None; - } - } + cx.spawn(|this, mut cx| async move { + let workspaces = WORKSPACE_DB + .recent_workspaces_on_disk() + .await + .unwrap_or_default() + .into_iter() + .map(|(_, location)| location) + .collect(); - cx.notify(); + let workspace = workspace.clone(); + this.update(&mut cx, move |this, cx| { + let view = cx.add_view(|cx| build_recent_projects(workspace, workspaces, cx)); + + cx.subscribe(&view, |this, _, event, cx| { + match event { + PickerEvent::Dismiss => { + this.project_popover = None; + } + } + + cx.notify(); + }) + .detach(); + this.branch_popover.take(); + this.project_popover = Some(view); + cx.notify(); + }) + .log_err(); }) .detach(); - self.branch_popover.take(); - self.project_popover = Some(view); } - - cx.notify(); } fn render_toggle_contacts_button( &self, diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index ed901a7da8..b3c9655645 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -66,17 +66,9 @@ fn toggle( pub fn build_recent_projects( workspace: WeakViewHandle, + workspaces: Vec, cx: &mut ViewContext, ) -> RecentProjects { - let workspaces = futures::executor::block_on(async { - WORKSPACE_DB - .recent_workspaces_on_disk() - .await - .unwrap_or_default() - .into_iter() - .map(|(_, location)| location) - .collect() - }); Picker::new(RecentProjectsDelegate::new(workspace, workspaces), cx) .with_theme(|theme| theme.picker.clone()) } From c1a629215269b255b75629866fa79e229dd037fc Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 12:15:47 +0200 Subject: [PATCH 030/104] Add missing call to cx.notify --- crates/collab_ui/src/collab_titlebar_item.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 511113a360..1fdce6f186 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -481,6 +481,7 @@ impl CollabTitlebarItem { }) .detach(); } + cx.notify(); } fn render_toggle_contacts_button( &self, From 3be8977ee86a3fb86ff27fbeb9c39e4797e28c9f Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 14:00:37 +0200 Subject: [PATCH 031/104] Switch branches within spawn() --- crates/collab_ui/src/branch_list.rs | 87 +++++++++++++++-------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 2d014cc1b9..038180b671 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,3 +1,4 @@ +use anyhow::{anyhow, bail}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{elements::*, AppContext, MouseState, Task, ViewContext, ViewHandle}; use picker::{Picker, PickerDelegate, PickerEvent}; @@ -53,7 +54,7 @@ impl PickerDelegate for BranchListDelegate { fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()> { cx.spawn(move |picker, mut cx| async move { - let candidates = picker + let Some(candidates) = picker .read_with(&mut cx, |view, cx| { let delegate = view.delegate(); let project = delegate.workspace.read(cx).project().read(&cx); @@ -67,13 +68,10 @@ impl PickerDelegate for BranchListDelegate { .path .to_path_buf(); cwd.push(".git"); - let mut branches = project - .fs() - .open_repo(&cwd) - .unwrap() + let Some(repo) = project.fs().open_repo(&cwd) else {bail!("Project does not have associated git repository.")}; + let mut branches = repo .lock() - .branches() - .unwrap(); + .branches()?; if query.is_empty() { const RECENT_BRANCHES_COUNT: usize = 10; // Do a partial sort to show recent-ish branches first. @@ -83,7 +81,7 @@ impl PickerDelegate for BranchListDelegate { branches.truncate(RECENT_BRANCHES_COUNT); branches.sort_unstable_by(|lhs, rhs| lhs.name.cmp(&rhs.name)); } - branches + Ok(branches .iter() .cloned() .enumerate() @@ -92,9 +90,10 @@ impl PickerDelegate for BranchListDelegate { char_bag: command.name.chars().collect(), string: command.name.into(), }) - .collect::>() + .collect::>()) }) - .unwrap(); + .log_err() else { return; }; + let Some(candidates) = candidates.log_err() else {return;}; let matches = if query.is_empty() { candidates .into_iter() @@ -136,37 +135,43 @@ impl PickerDelegate for BranchListDelegate { fn confirm(&mut self, cx: &mut ViewContext>) { let current_pick = self.selected_index(); let current_pick = self.matches[current_pick].string.clone(); - let project = self.workspace.read(cx).project().read(cx); - let mut cwd = project - .visible_worktrees(cx) - .next() - .unwrap() - .read(cx) - .root_entry() - .unwrap() - .path - .to_path_buf(); - cwd.push(".git"); - let status = project - .fs() - .open_repo(&cwd) - .unwrap() - .lock() - .change_branch(¤t_pick); - if status.is_err() { - const GIT_CHECKOUT_FAILURE_ID: usize = 2048; - self.workspace.update(cx, |model, ctx| { - model.show_toast( - Toast::new( - GIT_CHECKOUT_FAILURE_ID, - format!("Failed to checkout branch '{current_pick}', check for conflicts or unstashed files"), - ), - ctx, - ) - }); - } - status.log_err(); - cx.emit(PickerEvent::Dismiss); + cx.spawn(|picker, mut cx| async move { + picker.update(&mut cx, |this, cx| { + let project = this.delegate().workspace.read(cx).project().read(cx); + let mut cwd = project + .visible_worktrees(cx) + .next() + .ok_or_else(|| anyhow!("There are no visisible worktrees."))? + .read(cx) + .root_entry() + .ok_or_else(|| anyhow!("Worktree has no root entry."))? + .path + .to_path_buf(); + cwd.push(".git"); + let status = project + .fs() + .open_repo(&cwd) + .ok_or_else(|| anyhow!("Could not open repository at path `{}`", cwd.as_os_str().to_string_lossy()))? + .lock() + .change_branch(¤t_pick); + if status.is_err() { + const GIT_CHECKOUT_FAILURE_ID: usize = 2048; + this.delegate().workspace.update(cx, |model, ctx| { + model.show_toast( + Toast::new( + GIT_CHECKOUT_FAILURE_ID, + format!("Failed to checkout branch '{current_pick}', check for conflicts or unstashed files"), + ), + ctx, + ) + }); + status?; + } + cx.emit(PickerEvent::Dismiss); + + Ok::<(), anyhow::Error>(()) + }).log_err(); + }).detach(); } fn dismissed(&mut self, cx: &mut ViewContext>) { From b699e5c142f900ae0e38574ec2ad1e11e1a693cf Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 16:23:27 +0200 Subject: [PATCH 032/104] Add styles to git menu --- crates/collab_ui/src/branch_list.rs | 40 +++++++++++-------------- crates/theme/src/theme.rs | 2 ++ styles/src/style_tree/contact_finder.ts | 2 ++ styles/src/style_tree/picker.ts | 29 ++++++++++++++++++ 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 038180b671..95e418e67f 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, bail}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{elements::*, AppContext, MouseState, Task, ViewContext, ViewHandle}; use picker::{Picker, PickerDelegate, PickerEvent}; -use std::sync::Arc; +use std::{ops::Not, sync::Arc}; use util::ResultExt; use workspace::{Toast, Workspace}; @@ -212,7 +212,7 @@ impl PickerDelegate for BranchListDelegate { } fn render_header(&self, cx: &AppContext) -> Option>> { let theme = &theme::current(cx); - let style = theme.picker.no_matches.label.clone(); + let style = theme.picker.header.clone(); if self.last_query.is_empty() { Some( Flex::row() @@ -221,28 +221,24 @@ impl PickerDelegate for BranchListDelegate { ) } else { Some( - Flex::row() - .with_child(Label::new("Branches", style)) + Stack::new() + .with_child( + Flex::row() + .with_child(Label::new("Branches", style.clone()).aligned().left()), + ) + .with_children(self.matches.is_empty().not().then(|| { + let suffix = if self.matches.len() == 1 { "" } else { "es" }; + Flex::row() + .align_children_center() + .with_child(Label::new( + format!("{} match{}", self.matches.len(), suffix), + style, + )) + .aligned() + .right() + })) .into_any(), ) } } - fn render_footer(&self, cx: &AppContext) -> Option>> { - if !self.last_query.is_empty() && !self.matches.is_empty() { - let theme = &theme::current(cx); - let style = theme.picker.no_matches.label.clone(); - // Render "1 match" and "0 matches", "42 matches"etc. - let suffix = if self.matches.len() == 1 { "" } else { "es" }; - Some( - Flex::row() - .with_child(Label::new( - format!("{} match{}", self.matches.len(), suffix), - style, - )) - .into_any(), - ) - } else { - None - } - } } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index e54dcdfd1e..687547a306 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -585,6 +585,8 @@ pub struct Picker { pub empty_input_editor: FieldEditor, pub no_matches: ContainedLabel, pub item: Toggleable>, + pub header: LabelStyle, + pub footer: LabelStyle, } #[derive(Clone, Debug, Deserialize, Default, JsonSchema)] diff --git a/styles/src/style_tree/contact_finder.ts b/styles/src/style_tree/contact_finder.ts index e61d100264..4815a4e98e 100644 --- a/styles/src/style_tree/contact_finder.ts +++ b/styles/src/style_tree/contact_finder.ts @@ -44,6 +44,8 @@ export default function contact_finder(theme: ColorScheme): any { no_matches: picker_style.no_matches, input_editor: picker_input, empty_input_editor: picker_input, + header: picker_style.header, + footer: picker_style.footer, }, row_height: 28, contact_avatar: { diff --git a/styles/src/style_tree/picker.ts b/styles/src/style_tree/picker.ts index 7ca76cd85f..9918d1a2d6 100644 --- a/styles/src/style_tree/picker.ts +++ b/styles/src/style_tree/picker.ts @@ -108,5 +108,34 @@ export default function picker(theme: ColorScheme): any { top: 8, }, }, + header: { + text: text(theme.lowest, "sans", "variant", { size: "xs" }), + padding: { + bottom: 4, + left: 12, + right: 12, + top: 4, + }, + margin: { + top: 1, + left: 4, + right: 4, + }, + }, + footer: { + text: text(theme.lowest, "sans", "variant", { size: "xs" }), + padding: { + bottom: 4, + left: 12, + right: 12, + top: 4, + }, + margin: { + top: 1, + left: 4, + right: 4, + }, + + } } } From ed75c316405814d2d06c96affb0d07de292ec3ad Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 16:38:38 +0200 Subject: [PATCH 033/104] Improve styling of git menu --- crates/collab_ui/src/branch_list.rs | 23 +++++++++++++++++++---- crates/theme/src/theme.rs | 4 ++-- styles/src/style_tree/picker.ts | 21 +++++---------------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 95e418e67f..0abe83f766 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -215,8 +215,16 @@ impl PickerDelegate for BranchListDelegate { let style = theme.picker.header.clone(); if self.last_query.is_empty() { Some( - Flex::row() - .with_child(Label::new("Recent branches", style)) + Stack::new() + .with_child( + Flex::row() + .with_child(Label::new("Recent branches", style.label.clone())) + .contained() + .with_style(style.container) + .into_any(), + ) + .contained() + .with_style(style.container) .into_any(), ) } else { @@ -224,7 +232,11 @@ impl PickerDelegate for BranchListDelegate { Stack::new() .with_child( Flex::row() - .with_child(Label::new("Branches", style.clone()).aligned().left()), + .with_child( + Label::new("Branches", style.label.clone()).aligned().left(), + ) + .contained() + .with_style(style.container), ) .with_children(self.matches.is_empty().not().then(|| { let suffix = if self.matches.len() == 1 { "" } else { "es" }; @@ -232,11 +244,14 @@ impl PickerDelegate for BranchListDelegate { .align_children_center() .with_child(Label::new( format!("{} match{}", self.matches.len(), suffix), - style, + style.label, )) .aligned() .right() })) + .contained() + .with_style(style.container) + .constrained() .into_any(), ) } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 687547a306..c224131d1e 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -585,8 +585,8 @@ pub struct Picker { pub empty_input_editor: FieldEditor, pub no_matches: ContainedLabel, pub item: Toggleable>, - pub header: LabelStyle, - pub footer: LabelStyle, + pub header: ContainedLabel, + pub footer: ContainedLabel, } #[derive(Clone, Debug, Deserialize, Default, JsonSchema)] diff --git a/styles/src/style_tree/picker.ts b/styles/src/style_tree/picker.ts index 9918d1a2d6..6a7221efb0 100644 --- a/styles/src/style_tree/picker.ts +++ b/styles/src/style_tree/picker.ts @@ -110,30 +110,19 @@ export default function picker(theme: ColorScheme): any { }, header: { text: text(theme.lowest, "sans", "variant", { size: "xs" }), - padding: { - bottom: 4, - left: 12, - right: 12, - top: 4, - }, + margin: { top: 1, - left: 4, - right: 4, + left: 8, + right: 8, }, }, footer: { text: text(theme.lowest, "sans", "variant", { size: "xs" }), - padding: { - bottom: 4, - left: 12, - right: 12, - top: 4, - }, margin: { top: 1, - left: 4, - right: 4, + left: 8, + right: 8, }, } From 4a654f52527bb2431478a778bc5771a45c489a04 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 30 Jun 2023 13:27:48 -0400 Subject: [PATCH 034/104] Fix bug preventing the assist command from working in certain keymaps --- assets/keymaps/atom.json | 4 +--- assets/keymaps/sublime_text.json | 4 +--- assets/keymaps/textmate.json | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/assets/keymaps/atom.json b/assets/keymaps/atom.json index 60acf5ea6f..af845ae4f2 100644 --- a/assets/keymaps/atom.json +++ b/assets/keymaps/atom.json @@ -24,9 +24,7 @@ ], "ctrl-shift-down": "editor::AddSelectionBelow", "ctrl-shift-up": "editor::AddSelectionAbove", - "cmd-shift-backspace": "editor::DeleteToBeginningOfLine", - "cmd-shift-enter": "editor::NewlineAbove", - "cmd-enter": "editor::NewlineBelow" + "cmd-shift-backspace": "editor::DeleteToBeginningOfLine" } }, { diff --git a/assets/keymaps/sublime_text.json b/assets/keymaps/sublime_text.json index 2d32b77d58..ca20802295 100644 --- a/assets/keymaps/sublime_text.json +++ b/assets/keymaps/sublime_text.json @@ -24,9 +24,7 @@ "ctrl-.": "editor::GoToHunk", "ctrl-,": "editor::GoToPrevHunk", "ctrl-backspace": "editor::DeleteToPreviousWordStart", - "ctrl-delete": "editor::DeleteToNextWordEnd", - "cmd-shift-enter": "editor::NewlineAbove", - "cmd-enter": "editor::NewlineBelow" + "ctrl-delete": "editor::DeleteToNextWordEnd" } }, { diff --git a/assets/keymaps/textmate.json b/assets/keymaps/textmate.json index 06be727429..591d6e443f 100644 --- a/assets/keymaps/textmate.json +++ b/assets/keymaps/textmate.json @@ -12,8 +12,6 @@ "ctrl-shift-d": "editor::DuplicateLine", "cmd-b": "editor::GoToDefinition", "cmd-j": "editor::ScrollCursorCenter", - "cmd-alt-enter": "editor::NewlineAbove", - "cmd-enter": "editor::NewlineBelow", "cmd-shift-l": "editor::SelectLine", "cmd-shift-t": "outline::Toggle", "alt-backspace": "editor::DeleteToPreviousWordStart", @@ -56,7 +54,9 @@ }, { "context": "Editor && mode == full", - "bindings": {} + "bindings": { + "cmd-alt-enter": "editor::NewlineAbove" + } }, { "context": "BufferSearchBar", From a5d9a10d7bf423b44bf43064b1a2dbb57ab235ea Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 19:48:28 +0200 Subject: [PATCH 035/104] Focus dropdowns on open --- crates/collab_ui/src/collab_titlebar_item.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 1fdce6f186..b68095878d 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -440,6 +440,7 @@ impl CollabTitlebarItem { }) .detach(); self.project_popover.take(); + cx.focus(&view); self.branch_popover = Some(view); } } @@ -473,6 +474,7 @@ impl CollabTitlebarItem { cx.notify(); }) .detach(); + cx.focus(&view); this.branch_popover.take(); this.project_popover = Some(view); cx.notify(); From cec884b5a52f076029b1e7851531ebce593ae555 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 20:07:44 +0200 Subject: [PATCH 036/104] Add styles for project name/git menu --- crates/collab_ui/src/collab_titlebar_item.rs | 67 ++++++++++---------- styles/src/style_tree/titlebar.ts | 5 +- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index b68095878d..0857b2b79a 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -220,29 +220,17 @@ impl CollabTitlebarItem { let branch_prepended = entry .as_ref() .and_then(RepositoryEntry::branch) - .map(|branch| { - format!( - "/{}", - util::truncate_and_trailoff(&branch, MAX_BRANCH_NAME_LENGTH) - ) - }); - let text_style = theme.titlebar.title.clone(); + .map(|branch| util::truncate_and_trailoff(&branch, MAX_BRANCH_NAME_LENGTH)); + let project_style = theme.titlebar.title.clone(); + let git_style = theme.titlebar.git_branch.clone(); + let divider_style = theme.titlebar.project_name_divider.clone(); let item_spacing = theme.titlebar.item_spacing; - let mut highlight = text_style.clone(); - highlight.color = theme.titlebar.highlight_color; - - let style = LabelStyle { - text: text_style, - highlight_text: Some(highlight), - }; - let highlights = (0..name.len()).into_iter().collect(); let mut ret = Flex::row().with_child( Stack::new() .with_child( MouseEventHandler::::new(0, cx, |_, _| { - Label::new(name, style.clone()) - .with_highlights(highlights) + Label::new(name, project_style.text.clone()) .contained() .aligned() .left() @@ -251,28 +239,43 @@ impl CollabTitlebarItem { .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, this, cx| { this.toggle_project_menu(&Default::default(), cx) - }), + }) + .contained() + .with_style(project_style.container), ) .with_children(self.render_project_popover_host(&theme.titlebar, cx)), ); if let Some(git_branch) = branch_prepended { ret = ret.with_child( - Stack::new() + Flex::row() .with_child( - MouseEventHandler::::new(0, cx, |_, _| { - Label::new(git_branch, style) - .contained() - .with_margin_right(item_spacing) - .aligned() - .left() - .into_any_named("title-project-branch") - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, this, cx| { - this.toggle_vcs_menu(&Default::default(), cx) - }), + Label::new("/", divider_style.text) + .contained() + .with_style(divider_style.container) + .aligned() + .left(), ) - .with_children(self.render_branches_popover_host(&theme.titlebar, cx)), + .with_child( + Stack::new() + .with_child( + MouseEventHandler::::new(0, cx, |_, _| { + Label::new(git_branch, git_style.text) + .contained() + .with_margin_right(item_spacing) + .aligned() + .left() + .into_any_named("title-project-branch") + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click( + MouseButton::Left, + move |_, this, cx| { + this.toggle_vcs_menu(&Default::default(), cx) + }, + ), + ) + .with_children(self.render_branches_popover_host(&theme.titlebar, cx)), + ), ) } ret.into_any() diff --git a/styles/src/style_tree/titlebar.ts b/styles/src/style_tree/titlebar.ts index 067d619bb5..686f814a5d 100644 --- a/styles/src/style_tree/titlebar.ts +++ b/styles/src/style_tree/titlebar.ts @@ -173,8 +173,9 @@ export function titlebar(theme: ColorScheme): any { }, // Project - title: text(theme.lowest, "sans", "variant"), - highlight_color: text(theme.lowest, "sans", "active").color, + title: text(theme.lowest, "sans", "active"), + project_name_divider: text(theme.lowest, "sans", "variant"), + git_branch: text(theme.lowest, "sans", "variant"), // Collaborators leader_avatar: { From 7c2c1a279b2b78f9703707339781cd6ecc6f0bca Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 30 Jun 2023 20:09:30 +0200 Subject: [PATCH 037/104] Add missing rust-side definitions --- crates/theme/src/theme.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index c224131d1e..a4fbcedd32 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -118,8 +118,9 @@ pub struct Titlebar { #[serde(flatten)] pub container: ContainerStyle, pub height: f32, - pub title: TextStyle, - pub highlight_color: Color, + pub title: ContainedText, + pub project_name_divider: ContainedText, + pub git_branch: ContainedText, pub item_spacing: f32, pub face_pile_spacing: f32, pub avatar_ribbon: AvatarRibbon, From 92df76e632f7f76a5f064043d67ed09c4bf931b5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 30 Jun 2023 11:20:50 -0700 Subject: [PATCH 038/104] Fix accidental ignoring of git FS events --- crates/project/src/worktree.rs | 80 +++++++++++++++------------- crates/project/src/worktree_tests.rs | 50 ++++++++--------- 2 files changed, 69 insertions(+), 61 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 20e693770f..2f793c84c9 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -2140,6 +2140,7 @@ impl LocalSnapshot { impl BackgroundScannerState { fn should_scan_directory(&self, entry: &Entry) -> bool { (!entry.is_external && !entry.is_ignored) + || entry.path.file_name() == Some(&*DOT_GIT) || self.scanned_dirs.contains(&entry.id) // If we've ever scanned it, keep scanning || self .paths_to_scan @@ -2319,6 +2320,7 @@ impl BackgroundScannerState { .entry_for_id(entry_id) .map(|entry| RepositoryWorkDirectory(entry.path.clone())) else { continue }; + log::info!("reload git repository {:?}", dot_git_dir); let repository = repository.repo_ptr.lock(); let branch = repository.branch_name(); repository.reload_index(); @@ -2359,6 +2361,8 @@ impl BackgroundScannerState { } fn build_repository(&mut self, dot_git_path: Arc, fs: &dyn Fs) -> Option<()> { + log::info!("build git repository {:?}", dot_git_path); + let work_dir_path: Arc = dot_git_path.parent().unwrap().into(); // Guard against repositories inside the repository metadata @@ -3138,8 +3142,6 @@ impl BackgroundScanner { } async fn process_events(&mut self, mut abs_paths: Vec) { - log::debug!("received fs events {:?}", abs_paths); - let root_path = self.state.lock().snapshot.abs_path.clone(); let root_canonical_path = match self.fs.canonicalize(&root_path).await { Ok(path) => path, @@ -3150,7 +3152,6 @@ impl BackgroundScanner { }; let mut relative_paths = Vec::with_capacity(abs_paths.len()); - let mut unloaded_relative_paths = Vec::new(); abs_paths.sort_unstable(); abs_paths.dedup_by(|a, b| a.starts_with(&b)); abs_paths.retain(|abs_path| { @@ -3173,7 +3174,6 @@ impl BackgroundScanner { }); if !parent_dir_is_loaded { log::debug!("ignoring event {relative_path:?} within unloaded directory"); - unloaded_relative_paths.push(relative_path); return false; } @@ -3182,27 +3182,30 @@ impl BackgroundScanner { } }); - if !relative_paths.is_empty() { - let (scan_job_tx, scan_job_rx) = channel::unbounded(); - self.reload_entries_for_paths( - root_path, - root_canonical_path, - &relative_paths, - abs_paths, - Some(scan_job_tx.clone()), - ) - .await; - drop(scan_job_tx); - self.scan_dirs(false, scan_job_rx).await; - - let (scan_job_tx, scan_job_rx) = channel::unbounded(); - self.update_ignore_statuses(scan_job_tx).await; - self.scan_dirs(false, scan_job_rx).await; + if relative_paths.is_empty() { + return; } + log::debug!("received fs events {:?}", relative_paths); + + let (scan_job_tx, scan_job_rx) = channel::unbounded(); + self.reload_entries_for_paths( + root_path, + root_canonical_path, + &relative_paths, + abs_paths, + Some(scan_job_tx.clone()), + ) + .await; + drop(scan_job_tx); + self.scan_dirs(false, scan_job_rx).await; + + let (scan_job_tx, scan_job_rx) = channel::unbounded(); + self.update_ignore_statuses(scan_job_tx).await; + self.scan_dirs(false, scan_job_rx).await; + { let mut state = self.state.lock(); - relative_paths.extend(unloaded_relative_paths); state.reload_repositories(&relative_paths, self.fs.as_ref()); state.snapshot.completed_scan_id = state.snapshot.scan_id; for (_, entry_id) in mem::take(&mut state.removed_entry_ids) { @@ -3610,23 +3613,28 @@ impl BackgroundScanner { } } - let fs_entry = state.insert_entry(fs_entry, self.fs.as_ref()); - - if let Some(scan_queue_tx) = &scan_queue_tx { - let mut ancestor_inodes = state.snapshot.ancestor_inodes_for_path(&path); - if metadata.is_dir && !ancestor_inodes.contains(&metadata.inode) { - ancestor_inodes.insert(metadata.inode); - smol::block_on(scan_queue_tx.send(ScanJob { - abs_path, - path: path.clone(), - ignore_stack, - ancestor_inodes, - is_external: fs_entry.is_external, - scan_queue: scan_queue_tx.clone(), - })) - .unwrap(); + if let (Some(scan_queue_tx), true) = (&scan_queue_tx, fs_entry.is_dir()) { + if state.should_scan_directory(&fs_entry) { + let mut ancestor_inodes = + state.snapshot.ancestor_inodes_for_path(&path); + if !ancestor_inodes.contains(&metadata.inode) { + ancestor_inodes.insert(metadata.inode); + smol::block_on(scan_queue_tx.send(ScanJob { + abs_path, + path: path.clone(), + ignore_stack, + ancestor_inodes, + is_external: fs_entry.is_external, + scan_queue: scan_queue_tx.clone(), + })) + .unwrap(); + } + } else { + fs_entry.kind = EntryKind::UnloadedDir; } } + + state.insert_entry(fs_entry, self.fs.as_ref()); } Ok(None) => { self.remove_repo_path(&path, &mut state.snapshot); diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index f908d702eb..c9ed06dea7 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -1654,6 +1654,23 @@ async fn test_git_status(deterministic: Arc, cx: &mut TestAppCont })); + const A_TXT: &'static str = "a.txt"; + const B_TXT: &'static str = "b.txt"; + const E_TXT: &'static str = "c/d/e.txt"; + const F_TXT: &'static str = "f.txt"; + const DOTGITIGNORE: &'static str = ".gitignore"; + const BUILD_FILE: &'static str = "target/build_file"; + let project_path = Path::new("project"); + + // Set up git repository before creating the worktree. + let work_dir = root.path().join("project"); + let mut repo = git_init(work_dir.as_path()); + repo.add_ignore_rule(IGNORE_RULE).unwrap(); + git_add(A_TXT, &repo); + git_add(E_TXT, &repo); + git_add(DOTGITIGNORE, &repo); + git_commit("Initial commit", &repo); + let tree = Worktree::local( build_client(cx), root.path(), @@ -1665,26 +1682,9 @@ async fn test_git_status(deterministic: Arc, cx: &mut TestAppCont .await .unwrap(); + tree.flush_fs_events(cx).await; cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; - - const A_TXT: &'static str = "a.txt"; - const B_TXT: &'static str = "b.txt"; - const E_TXT: &'static str = "c/d/e.txt"; - const F_TXT: &'static str = "f.txt"; - const DOTGITIGNORE: &'static str = ".gitignore"; - const BUILD_FILE: &'static str = "target/build_file"; - let project_path: &Path = &Path::new("project"); - - let work_dir = root.path().join("project"); - let mut repo = git_init(work_dir.as_path()); - repo.add_ignore_rule(IGNORE_RULE).unwrap(); - git_add(Path::new(A_TXT), &repo); - git_add(Path::new(E_TXT), &repo); - git_add(Path::new(DOTGITIGNORE), &repo); - git_commit("Initial commit", &repo); - - tree.flush_fs_events(cx).await; deterministic.run_until_parked(); // Check that the right git state is observed on startup @@ -1704,39 +1704,39 @@ async fn test_git_status(deterministic: Arc, cx: &mut TestAppCont ); }); + // Modify a file in the working copy. std::fs::write(work_dir.join(A_TXT), "aa").unwrap(); - tree.flush_fs_events(cx).await; deterministic.run_until_parked(); + // The worktree detects that the file's git status has changed. tree.read_with(cx, |tree, _cx| { let snapshot = tree.snapshot(); - assert_eq!( snapshot.status_for_file(project_path.join(A_TXT)), Some(GitFileStatus::Modified) ); }); - git_add(Path::new(A_TXT), &repo); - git_add(Path::new(B_TXT), &repo); + // Create a commit in the git repository. + git_add(A_TXT, &repo); + git_add(B_TXT, &repo); git_commit("Committing modified and added", &repo); tree.flush_fs_events(cx).await; deterministic.run_until_parked(); - // Check that repo only changes are tracked + // The worktree detects that the files' git status have changed. tree.read_with(cx, |tree, _cx| { let snapshot = tree.snapshot(); - assert_eq!( snapshot.status_for_file(project_path.join(F_TXT)), Some(GitFileStatus::Added) ); - assert_eq!(snapshot.status_for_file(project_path.join(B_TXT)), None); assert_eq!(snapshot.status_for_file(project_path.join(A_TXT)), None); }); + // Modify files in the working copy and perform git operations on other files. git_reset(0, &repo); git_remove_index(Path::new(B_TXT), &repo); git_stash(&mut repo); From ae54e1d224e747ca9a997530184913adb3fe2b79 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 30 Jun 2023 08:19:57 +0300 Subject: [PATCH 039/104] Remove excessive hint update queries * Filter out queries for outdated buffers just before hint tasks spawn: multicared edits might empit standalone events simultaneously * Only spawn inlay update tasks for visible buffers with corresponding language * Do not spawn tasks for local projects' buffers without LSP servers --- crates/editor/src/editor.rs | 71 ++++- crates/editor/src/inlay_hint_cache.rs | 434 ++++++++++++++++++++------ crates/text/src/text.rs | 7 +- 3 files changed, 405 insertions(+), 107 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 64332c102a..81f073ed62 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -26,7 +26,7 @@ use aho_corasick::AhoCorasick; use anyhow::{anyhow, Result}; use blink_manager::BlinkManager; use client::{ClickhouseEvent, TelemetrySettings}; -use clock::ReplicaId; +use clock::{Global, ReplicaId}; use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque}; use copilot::Copilot; pub use display_map::DisplayPoint; @@ -1195,11 +1195,11 @@ enum GotoDefinitionKind { Type, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] enum InlayRefreshReason { SettingsChange(InlayHintSettings), NewLinesShown, - ExcerptEdited, + BufferEdited(HashSet>), RefreshRequested, } @@ -2617,7 +2617,7 @@ impl Editor { return; } - let invalidate_cache = match reason { + let (invalidate_cache, required_languages) = match reason { InlayRefreshReason::SettingsChange(new_settings) => { match self.inlay_hint_cache.update_settings( &self.buffer, @@ -2633,16 +2633,18 @@ impl Editor { return; } ControlFlow::Break(None) => return, - ControlFlow::Continue(()) => InvalidationStrategy::RefreshRequested, + ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None), } } - InlayRefreshReason::NewLinesShown => InvalidationStrategy::None, - InlayRefreshReason::ExcerptEdited => InvalidationStrategy::ExcerptEdited, - InlayRefreshReason::RefreshRequested => InvalidationStrategy::RefreshRequested, + InlayRefreshReason::NewLinesShown => (InvalidationStrategy::None, None), + InlayRefreshReason::BufferEdited(buffer_languages) => { + (InvalidationStrategy::BufferEdited, Some(buffer_languages)) + } + InlayRefreshReason::RefreshRequested => (InvalidationStrategy::RefreshRequested, None), }; self.inlay_hint_cache.refresh_inlay_hints( - self.excerpt_visible_offsets(cx), + self.excerpt_visible_offsets(required_languages.as_ref(), cx), invalidate_cache, cx, ) @@ -2661,8 +2663,9 @@ impl Editor { fn excerpt_visible_offsets( &self, + restrict_to_languages: Option<&HashSet>>, cx: &mut ViewContext<'_, '_, Editor>, - ) -> HashMap, Range)> { + ) -> HashMap, Global, Range)> { let multi_buffer = self.buffer().read(cx); let multi_buffer_snapshot = multi_buffer.snapshot(cx); let multi_buffer_visible_start = self @@ -2680,8 +2683,22 @@ impl Editor { .range_to_buffer_ranges(multi_buffer_visible_range, cx) .into_iter() .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty()) - .map(|(buffer, excerpt_visible_range, excerpt_id)| { - (excerpt_id, (buffer, excerpt_visible_range)) + .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| { + let buffer = buffer_handle.read(cx); + let language = buffer.language()?; + if let Some(restrict_to_languages) = restrict_to_languages { + if !restrict_to_languages.contains(language) { + return None; + } + } + Some(( + excerpt_id, + ( + buffer_handle, + buffer.version().clone(), + excerpt_visible_range, + ), + )) }) .collect() } @@ -7256,7 +7273,7 @@ impl Editor { fn on_buffer_event( &mut self, - _: ModelHandle, + multibuffer: ModelHandle, event: &multi_buffer::Event, cx: &mut ViewContext, ) { @@ -7268,7 +7285,33 @@ impl Editor { self.update_visible_copilot_suggestion(cx); } cx.emit(Event::BufferEdited); - self.refresh_inlays(InlayRefreshReason::ExcerptEdited, cx); + + if let Some(project) = &self.project { + let project = project.read(cx); + let languages_affected = multibuffer + .read(cx) + .all_buffers() + .into_iter() + .filter_map(|buffer| { + let buffer = buffer.read(cx); + let language = buffer.language()?; + if project.is_local() + && project.language_servers_for_buffer(buffer, cx).count() == 0 + { + None + } else { + Some(language) + } + }) + .cloned() + .collect::>(); + if !languages_affected.is_empty() { + self.refresh_inlays( + InlayRefreshReason::BufferEdited(languages_affected), + cx, + ); + } + } } multi_buffer::Event::ExcerptsAdded { buffer, diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index af7bf3e4c5..3f9f8e4288 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -38,7 +38,7 @@ pub struct CachedExcerptHints { #[derive(Debug, Clone, Copy)] pub enum InvalidationStrategy { RefreshRequested, - ExcerptEdited, + BufferEdited, None, } @@ -94,7 +94,7 @@ impl InvalidationStrategy { fn should_invalidate(&self) -> bool { matches!( self, - InvalidationStrategy::RefreshRequested | InvalidationStrategy::ExcerptEdited + InvalidationStrategy::RefreshRequested | InvalidationStrategy::BufferEdited ) } } @@ -197,7 +197,7 @@ impl InlayHintCache { pub fn refresh_inlay_hints( &mut self, - mut excerpts_to_query: HashMap, Range)>, + mut excerpts_to_query: HashMap, Global, Range)>, invalidate: InvalidationStrategy, cx: &mut ViewContext, ) { @@ -342,104 +342,113 @@ impl InlayHintCache { fn spawn_new_update_tasks( editor: &mut Editor, - excerpts_to_query: HashMap, Range)>, + excerpts_to_query: HashMap, Global, Range)>, invalidate: InvalidationStrategy, update_cache_version: usize, cx: &mut ViewContext<'_, '_, Editor>, ) { let visible_hints = Arc::new(editor.visible_inlay_hints(cx)); - for (excerpt_id, (buffer_handle, excerpt_visible_range)) in excerpts_to_query { - if !excerpt_visible_range.is_empty() { - let buffer = buffer_handle.read(cx); - let buffer_snapshot = buffer.snapshot(); - let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned(); - if let Some(cached_excerpt_hints) = &cached_excerpt_hints { - let new_task_buffer_version = buffer_snapshot.version(); - let cached_excerpt_hints = cached_excerpt_hints.read(); - let cached_buffer_version = &cached_excerpt_hints.buffer_version; - if cached_excerpt_hints.version > update_cache_version - || cached_buffer_version.changed_since(new_task_buffer_version) - { - return; - } - if !new_task_buffer_version.changed_since(&cached_buffer_version) - && !matches!(invalidate, InvalidationStrategy::RefreshRequested) - { - return; - } + for (excerpt_id, (buffer_handle, new_task_buffer_version, excerpt_visible_range)) in + excerpts_to_query + { + if excerpt_visible_range.is_empty() { + continue; + } + let buffer = buffer_handle.read(cx); + let buffer_snapshot = buffer.snapshot(); + if buffer_snapshot + .version() + .changed_since(&new_task_buffer_version) + { + continue; + } + + let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned(); + if let Some(cached_excerpt_hints) = &cached_excerpt_hints { + let cached_excerpt_hints = cached_excerpt_hints.read(); + let cached_buffer_version = &cached_excerpt_hints.buffer_version; + if cached_excerpt_hints.version > update_cache_version + || cached_buffer_version.changed_since(&new_task_buffer_version) + { + continue; + } + if !new_task_buffer_version.changed_since(&cached_buffer_version) + && !matches!(invalidate, InvalidationStrategy::RefreshRequested) + { + continue; + } + }; + + let buffer_id = buffer.remote_id(); + let excerpt_visible_range_start = buffer.anchor_before(excerpt_visible_range.start); + let excerpt_visible_range_end = buffer.anchor_after(excerpt_visible_range.end); + + let (multi_buffer_snapshot, full_excerpt_range) = + editor.buffer.update(cx, |multi_buffer, cx| { + let multi_buffer_snapshot = multi_buffer.snapshot(cx); + ( + multi_buffer_snapshot, + multi_buffer + .excerpts_for_buffer(&buffer_handle, cx) + .into_iter() + .find(|(id, _)| id == &excerpt_id) + .map(|(_, range)| range.context), + ) + }); + + if let Some(full_excerpt_range) = full_excerpt_range { + let query = ExcerptQuery { + buffer_id, + excerpt_id, + dimensions: ExcerptDimensions { + excerpt_range_start: full_excerpt_range.start, + excerpt_range_end: full_excerpt_range.end, + excerpt_visible_range_start, + excerpt_visible_range_end, + }, + cache_version: update_cache_version, + invalidate, }; - let buffer_id = buffer.remote_id(); - let excerpt_visible_range_start = buffer.anchor_before(excerpt_visible_range.start); - let excerpt_visible_range_end = buffer.anchor_after(excerpt_visible_range.end); - - let (multi_buffer_snapshot, full_excerpt_range) = - editor.buffer.update(cx, |multi_buffer, cx| { - let multi_buffer_snapshot = multi_buffer.snapshot(cx); - ( - multi_buffer_snapshot, - multi_buffer - .excerpts_for_buffer(&buffer_handle, cx) - .into_iter() - .find(|(id, _)| id == &excerpt_id) - .map(|(_, range)| range.context), - ) - }); - - if let Some(full_excerpt_range) = full_excerpt_range { - let query = ExcerptQuery { - buffer_id, - excerpt_id, - dimensions: ExcerptDimensions { - excerpt_range_start: full_excerpt_range.start, - excerpt_range_end: full_excerpt_range.end, - excerpt_visible_range_start, - excerpt_visible_range_end, - }, - cache_version: update_cache_version, - invalidate, - }; - - let new_update_task = |is_refresh_after_regular_task| { - new_update_task( - query, - multi_buffer_snapshot, - buffer_snapshot, - Arc::clone(&visible_hints), - cached_excerpt_hints, - is_refresh_after_regular_task, - cx, - ) - }; - match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) { - hash_map::Entry::Occupied(mut o) => { - let update_task = o.get_mut(); - match (update_task.invalidate, invalidate) { - (_, InvalidationStrategy::None) => {} - ( - InvalidationStrategy::ExcerptEdited, - InvalidationStrategy::RefreshRequested, - ) if !update_task.task.is_running_rx.is_closed() => { - update_task.pending_refresh = Some(query); - } - _ => { - o.insert(UpdateTask { - invalidate, - cache_version: query.cache_version, - task: new_update_task(false), - pending_refresh: None, - }); - } + let new_update_task = |is_refresh_after_regular_task| { + new_update_task( + query, + multi_buffer_snapshot, + buffer_snapshot, + Arc::clone(&visible_hints), + cached_excerpt_hints, + is_refresh_after_regular_task, + cx, + ) + }; + match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) { + hash_map::Entry::Occupied(mut o) => { + let update_task = o.get_mut(); + match (update_task.invalidate, invalidate) { + (_, InvalidationStrategy::None) => {} + ( + InvalidationStrategy::BufferEdited, + InvalidationStrategy::RefreshRequested, + ) if !update_task.task.is_running_rx.is_closed() => { + update_task.pending_refresh = Some(query); + } + _ => { + o.insert(UpdateTask { + invalidate, + cache_version: query.cache_version, + task: new_update_task(false), + pending_refresh: None, + }); } } - hash_map::Entry::Vacant(v) => { - v.insert(UpdateTask { - invalidate, - cache_version: query.cache_version, - task: new_update_task(false), - pending_refresh: None, - }); - } + } + hash_map::Entry::Vacant(v) => { + v.insert(UpdateTask { + invalidate, + cache_version: query.cache_version, + task: new_update_task(false), + pending_refresh: None, + }); } } } @@ -961,6 +970,247 @@ mod tests { }); } + #[gpui::test] + async fn test_no_hint_updates_for_unrelated_language_files(cx: &mut gpui::TestAppContext) { + let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); + init_test(cx, |settings| { + settings.defaults.inlay_hints = Some(InlayHintSettings { + enabled: true, + show_type_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Type)), + show_parameter_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Parameter)), + show_other_hints: allowed_hint_kinds.contains(&None), + }) + }); + + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/a", + json!({ + "main.rs": "fn main() { a } // and some long comment to ensure inlays are not trimmed out", + "other.md": "Test md file with some text", + }), + ) + .await; + let project = Project::test(fs, ["/a".as_ref()], cx).await; + let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); + let worktree_id = workspace.update(cx, |workspace, cx| { + workspace.project().read_with(cx, |project, cx| { + project.worktrees(cx).next().unwrap().read(cx).id() + }) + }); + + let mut rs_fake_servers = None; + let mut md_fake_servers = None; + for (name, path_suffix) in [("Rust", "rs"), ("Markdown", "md")] { + let mut language = Language::new( + LanguageConfig { + name: name.into(), + path_suffixes: vec![path_suffix.to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let fake_servers = language + .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { + name, + capabilities: lsp::ServerCapabilities { + inlay_hint_provider: Some(lsp::OneOf::Left(true)), + ..Default::default() + }, + ..Default::default() + })) + .await; + match name { + "Rust" => rs_fake_servers = Some(fake_servers), + "Markdown" => md_fake_servers = Some(fake_servers), + _ => unreachable!(), + } + project.update(cx, |project, _| { + project.languages().add(Arc::new(language)); + }); + } + + let _rs_buffer = project + .update(cx, |project, cx| { + project.open_local_buffer("/a/main.rs", cx) + }) + .await + .unwrap(); + cx.foreground().run_until_parked(); + cx.foreground().start_waiting(); + let rs_fake_server = rs_fake_servers.unwrap().next().await.unwrap(); + let rs_editor = workspace + .update(cx, |workspace, cx| { + workspace.open_path((worktree_id, "main.rs"), None, true, cx) + }) + .await + .unwrap() + .downcast::() + .unwrap(); + let rs_lsp_request_count = Arc::new(AtomicU32::new(0)); + rs_fake_server + .handle_request::(move |params, _| { + let task_lsp_request_count = Arc::clone(&rs_lsp_request_count); + async move { + assert_eq!( + params.text_document.uri, + lsp::Url::from_file_path("/a/main.rs").unwrap(), + ); + let i = Arc::clone(&task_lsp_request_count).fetch_add(1, Ordering::SeqCst); + Ok(Some(vec![lsp::InlayHint { + position: lsp::Position::new(0, i), + label: lsp::InlayHintLabel::String(i.to_string()), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }])) + } + }) + .next() + .await; + cx.foreground().run_until_parked(); + rs_editor.update(cx, |editor, cx| { + let expected_layers = vec!["0".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Should get its first hints when opening the editor" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!( + inlay_cache.allowed_hint_kinds, allowed_hint_kinds, + "Cache should use editor settings to get the allowed hint kinds" + ); + assert_eq!( + inlay_cache.version, 1, + "Rust editor update the cache version after every cache/view change" + ); + }); + + cx.foreground().run_until_parked(); + let _md_buffer = project + .update(cx, |project, cx| { + project.open_local_buffer("/a/other.md", cx) + }) + .await + .unwrap(); + cx.foreground().run_until_parked(); + cx.foreground().start_waiting(); + let md_fake_server = md_fake_servers.unwrap().next().await.unwrap(); + let md_editor = workspace + .update(cx, |workspace, cx| { + workspace.open_path((worktree_id, "other.md"), None, true, cx) + }) + .await + .unwrap() + .downcast::() + .unwrap(); + let md_lsp_request_count = Arc::new(AtomicU32::new(0)); + md_fake_server + .handle_request::(move |params, _| { + let task_lsp_request_count = Arc::clone(&md_lsp_request_count); + async move { + assert_eq!( + params.text_document.uri, + lsp::Url::from_file_path("/a/other.md").unwrap(), + ); + let i = Arc::clone(&task_lsp_request_count).fetch_add(1, Ordering::SeqCst); + Ok(Some(vec![lsp::InlayHint { + position: lsp::Position::new(0, i), + label: lsp::InlayHintLabel::String(i.to_string()), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }])) + } + }) + .next() + .await; + cx.foreground().run_until_parked(); + md_editor.update(cx, |editor, cx| { + let expected_layers = vec!["0".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Markdown editor should have a separate verison, repeating Rust editor rules" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); + assert_eq!(inlay_cache.version, 1); + }); + + rs_editor.update(cx, |editor, cx| { + editor.change_selections(None, cx, |s| s.select_ranges([13..13])); + editor.handle_input("some rs change", cx); + }); + cx.foreground().run_until_parked(); + rs_editor.update(cx, |editor, cx| { + let expected_layers = vec!["1".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Rust inlay cache should change after the edit" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); + assert_eq!( + inlay_cache.version, 2, + "Every time hint cache changes, cache version should be incremented" + ); + }); + md_editor.update(cx, |editor, cx| { + let expected_layers = vec!["0".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Markdown editor should not be affected by Rust editor changes" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); + assert_eq!(inlay_cache.version, 1); + }); + + md_editor.update(cx, |editor, cx| { + editor.change_selections(None, cx, |s| s.select_ranges([13..13])); + editor.handle_input("some md change", cx); + }); + cx.foreground().run_until_parked(); + md_editor.update(cx, |editor, cx| { + let expected_layers = vec!["1".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Rust editor should not be affected by Markdown editor changes" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); + assert_eq!(inlay_cache.version, 2); + }); + rs_editor.update(cx, |editor, cx| { + let expected_layers = vec!["1".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Markdown editor should also change independently" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); + assert_eq!(inlay_cache.version, 2); + }); + } + #[gpui::test] async fn test_hint_setting_changes(cx: &mut gpui::TestAppContext) { let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 28c5125de2..7c94f25e1e 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -2489,7 +2489,12 @@ impl ToOffset for Point { impl ToOffset for usize { fn to_offset(&self, snapshot: &BufferSnapshot) -> usize { - assert!(*self <= snapshot.len(), "offset {self} is out of range"); + assert!( + *self <= snapshot.len(), + "offset {} is out of range, max allowed is {}", + self, + snapshot.len() + ); *self } } From 138de37cbffef208c2e0f9f171796afd73d91e4f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 30 Jun 2023 16:10:49 -0700 Subject: [PATCH 040/104] Add basic sound handling infrastructure --- Cargo.lock | 463 ++++++++++++++++++++++++++++++++++--- crates/call/Cargo.toml | 1 + crates/call/src/call.rs | 14 +- crates/call/src/room.rs | 42 ++++ crates/collab/src/tests.rs | 2 +- crates/zed/src/assets.rs | 1 + crates/zed/src/main.rs | 2 +- crates/zed/src/zed.rs | 2 +- 8 files changed, 495 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3748f24933..6dcf614e08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,6 +177,28 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" +[[package]] +name = "alsa" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44" +dependencies = [ + "alsa-sys", + "bitflags", + "libc", + "nix", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "ambient-authority" version = "0.0.1" @@ -756,6 +778,26 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.64.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 1.0.109", +] + [[package]] name = "bindgen" version = "0.65.1" @@ -857,7 +899,7 @@ checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", - "proc-macro-crate", + "proc-macro-crate 0.1.5", "proc-macro2", "syn 1.0.109", ] @@ -997,6 +1039,7 @@ dependencies = [ "media", "postage", "project", + "rodio", "settings", "util", ] @@ -1082,6 +1125,12 @@ dependencies = [ "jobserver", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -1155,7 +1204,7 @@ dependencies = [ "bitflags", "clap_derive 3.2.25", "clap_lex 0.2.4", - "indexmap", + "indexmap 1.9.3", "once_cell", "strsim", "termcolor", @@ -1226,6 +1275,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +[[package]] +name = "claxon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" + [[package]] name = "cli" version = "0.1.0" @@ -1444,6 +1499,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes 1.4.0", + "memchr", +] + [[package]] name = "command_palette" version = "0.1.0" @@ -1540,11 +1605,17 @@ name = "core-foundation" version = "0.9.3" source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.8.3", "libc", "uuid 0.5.1", ] +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -1594,6 +1665,51 @@ dependencies = [ "libc", ] +[[package]] +name = "coreaudio-rs" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb17e2d1795b1996419648915df94bc7103c28f7b48062d7acf4652fc371b2ff" +dependencies = [ + "bitflags", + "core-foundation-sys 0.6.2", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" +dependencies = [ + "bindgen 0.64.0", +] + +[[package]] +name = "cpal" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" +dependencies = [ + "alsa", + "core-foundation-sys 0.8.3", + "coreaudio-rs", + "dasp_sample", + "jni 0.19.0", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "oboe", + "once_cell", + "parking_lot 0.12.1", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.46.0", +] + [[package]] name = "cpp_demangle" version = "0.3.5" @@ -1924,6 +2040,12 @@ dependencies = [ "parking_lot_core 0.9.7", ] +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + [[package]] name = "data-url" version = "0.1.1" @@ -2233,6 +2355,12 @@ dependencies = [ "serde", ] +[[package]] +name = "equivalent" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" + [[package]] name = "erased-serde" version = "0.3.25" @@ -2793,7 +2921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] @@ -2889,7 +3017,7 @@ dependencies = [ "anyhow", "async-task", "backtrace", - "bindgen", + "bindgen 0.65.1", "block", "cc", "cocoa", @@ -2961,7 +3089,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util 0.7.8", @@ -2995,6 +3123,12 @@ dependencies = [ "ahash 0.8.3", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "hashlink" version = "0.8.1" @@ -3105,6 +3239,12 @@ dependencies = [ "digest 0.10.6", ] +[[package]] +name = "hound" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1" + [[package]] name = "http" version = "0.2.9" @@ -3213,11 +3353,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", - "core-foundation-sys", + "core-foundation-sys 0.8.3", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows 0.48.0", ] [[package]] @@ -3287,6 +3427,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "indoc" version = "1.0.9" @@ -3459,6 +3609,40 @@ dependencies = [ "cc", ] +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.26" @@ -3661,6 +3845,17 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" +[[package]] +name = "lewton" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" +dependencies = [ + "byteorder", + "ogg", + "tinyvec", +] + [[package]] name = "libc" version = "0.2.144" @@ -3893,6 +4088,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -3949,7 +4153,7 @@ name = "media" version = "0.1.0" dependencies = [ "anyhow", - "bindgen", + "bindgen 0.65.1", "block", "bytes 1.4.0", "core-foundation", @@ -4207,6 +4411,35 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys", +] + [[package]] name = "net2" version = "0.2.38" @@ -4315,6 +4548,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -4367,6 +4611,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "nvim-rs" version = "0.5.0" @@ -4409,7 +4674,7 @@ checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "crc32fast", "hashbrown 0.11.2", - "indexmap", + "indexmap 1.9.3", "memchr", ] @@ -4422,6 +4687,38 @@ dependencies = [ "memchr", ] +[[package]] +name = "oboe" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8868cc237ee02e2d9618539a23a8d228b9bb3fc2e7a5b11eed3831de77c395d0" +dependencies = [ + "jni 0.20.0", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f44155e7fb718d3cfddcf70690b2b51ac4412f347cd9e4fbe511abe9cd7b5f2" +dependencies = [ + "cc", +] + +[[package]] +name = "ogg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" +dependencies = [ + "byteorder", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -4711,7 +5008,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -4788,7 +5085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" dependencies = [ "base64 0.21.0", - "indexmap", + "indexmap 1.9.3", "line-wrap", "quick-xml", "serde", @@ -4921,6 +5218,16 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -5333,6 +5640,12 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + [[package]] name = "rayon" version = "1.7.0" @@ -5616,6 +5929,19 @@ dependencies = [ "rmp", ] +[[package]] +name = "rodio" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf1d4dea18dff2e9eb6dca123724f8b60ef44ad74a9ad283cdfe025df7e73fa" +dependencies = [ + "claxon", + "cpal", + "hound", + "lewton", + "symphonia", +] + [[package]] name = "rope" version = "0.1.0" @@ -6117,7 +6443,7 @@ checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", - "core-foundation-sys", + "core-foundation-sys 0.8.3", "libc", "security-framework-sys", ] @@ -6128,7 +6454,7 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.8.3", "libc", ] @@ -6202,7 +6528,7 @@ version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ - "indexmap", + "indexmap 1.9.3", "itoa 1.0.6", "ryu", "serde", @@ -6214,7 +6540,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d7b9ce5b0a63c6269b9623ed828b39259545a6ec0d8a35d6135ad6af6232add" dependencies = [ - "indexmap", + "indexmap 1.9.3", "itoa 0.4.8", "ryu", "serde", @@ -6249,7 +6575,7 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", + "indexmap 1.9.3", "ryu", "serde", "yaml-rust", @@ -6623,7 +6949,7 @@ dependencies = [ "hex", "hkdf", "hmac 0.12.1", - "indexmap", + "indexmap 1.9.3", "itoa 1.0.6", "libc", "libsqlite3-sys", @@ -6774,6 +7100,56 @@ dependencies = [ "siphasher", ] +[[package]] +name = "symphonia" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" +dependencies = [ + "lazy_static", + "symphonia-bundle-mp3", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" +dependencies = [ + "bitflags", + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" +dependencies = [ + "arrayvec 0.7.2", + "bitflags", + "bytemuck", + "lazy_static", + "log", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + [[package]] name = "syn" version = "1.0.109" @@ -6819,7 +7195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a902e9050fca0a5d6877550b769abd2bd1ce8c04634b941dbe2809735e1a1e33" dependencies = [ "cfg-if 1.0.0", - "core-foundation-sys", + "core-foundation-sys 0.8.3", "libc", "ntapi 0.4.1", "once_cell", @@ -6988,7 +7364,7 @@ dependencies = [ "anyhow", "fs", "gpui", - "indexmap", + "indexmap 1.9.3", "parking_lot 0.11.2", "schemars", "serde", @@ -7294,6 +7670,23 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tonic" version = "0.6.2" @@ -7333,7 +7726,7 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "indexmap", + "indexmap 1.9.3", "pin-project", "pin-project-lite 0.2.9", "rand 0.8.5", @@ -8190,7 +8583,7 @@ version = "0.85.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "570460c58b21e9150d2df0eaaedbb7816c34bcec009ae0dcc976e40ba81463e7" dependencies = [ - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -8204,7 +8597,7 @@ dependencies = [ "backtrace", "bincode", "cfg-if 1.0.0", - "indexmap", + "indexmap 1.9.3", "lazy_static", "libc", "log", @@ -8278,7 +8671,7 @@ dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", - "indexmap", + "indexmap 1.9.3", "log", "more-asserts", "object 0.28.4", @@ -8348,7 +8741,7 @@ dependencies = [ "backtrace", "cc", "cfg-if 1.0.0", - "indexmap", + "indexmap 1.9.3", "libc", "log", "mach", @@ -8604,6 +8997,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows" version = "0.48.0" @@ -8760,6 +9162,15 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winnow" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.10.1" @@ -8949,7 +9360,7 @@ dependencies = [ "gpui", "ignore", "image", - "indexmap", + "indexmap 1.9.3", "install_cli", "isahc", "journal", diff --git a/crates/call/Cargo.toml b/crates/call/Cargo.toml index 4e83b552fb..86ff1a5543 100644 --- a/crates/call/Cargo.toml +++ b/crates/call/Cargo.toml @@ -30,6 +30,7 @@ media = { path = "../media" } project = { path = "../project" } settings = { path = "../settings" } util = { path = "../util" } +rodio = "0.17.1" anyhow.workspace = true async-broadcast = "0.4" diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index 0a8f150194..42cb5f2f87 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -1,24 +1,32 @@ +mod assets; pub mod participant; pub mod room; use std::sync::Arc; use anyhow::{anyhow, Result}; +use assets::SoundRegistry; use client::{proto, Client, TypedEnvelope, User, UserStore}; use collections::HashSet; use futures::{future::Shared, FutureExt}; use postage::watch; use gpui::{ - AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, Task, - WeakModelHandle, + AppContext, AssetSource, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, + Task, WeakModelHandle, }; use project::Project; pub use participant::ParticipantLocation; pub use room::Room; -pub fn init(client: Arc, user_store: ModelHandle, cx: &mut AppContext) { +pub fn init( + client: Arc, + user_store: ModelHandle, + source: impl AssetSource, + cx: &mut AppContext, +) { + cx.set_global(SoundRegistry::new(source)); let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx)); cx.set_global(active_call); } diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index da298f9ca2..b80e994fcf 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -1,4 +1,5 @@ use crate::{ + assets::SoundRegistry, participant::{LocalParticipant, ParticipantLocation, RemoteParticipant, RemoteVideoTrack}, IncomingCall, }; @@ -18,11 +19,30 @@ use live_kit_client::{ }; use postage::stream::Stream; use project::Project; +use rodio::{OutputStream, OutputStreamHandle, Source}; use std::{future::Future, mem, pin::Pin, sync::Arc, time::Duration}; use util::{post_inc, ResultExt, TryFutureExt}; pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30); +enum Sound { + Joined, + Leaved, + Mute, + Unmute, +} + +impl Sound { + fn file(&self) -> &'static str { + match self { + Self::Joined => "joined", + Self::Leaved => "leave", + Self::Mute => "mute", + Self::Unmute => "unmute", + } + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { ParticipantLocationChanged { @@ -48,6 +68,8 @@ pub enum Event { pub struct Room { id: u64, live_kit: Option, + _sound_output_stream: Option, + sound_output_handle: Option, status: RoomStatus, shared_projects: HashSet>, joined_projects: HashSet>, @@ -176,9 +198,14 @@ impl Room { let maintain_connection = cx.spawn_weak(|this, cx| Self::maintain_connection(this, client.clone(), cx).log_err()); + let (sound_output_stream, sound_output_handle) = + OutputStream::try_default().log_err().unzip(); + Self { id, live_kit: live_kit_room, + _sound_output_stream: sound_output_stream, + sound_output_handle, status: RoomStatus::Online, shared_projects: Default::default(), joined_projects: Default::default(), @@ -910,6 +937,18 @@ impl Room { }) } + fn play_sound(&self, sound: Sound, cx: &AppContext) { + let Some(output_handle) = self.sound_output_handle.as_ref() else { + return; + }; + + let Some(source) = SoundRegistry::global(cx).get(sound.file()) else { + return; + }; + + output_handle.play_raw(source.convert_samples()).log_err(); + } + pub fn join_project( &mut self, id: u64, @@ -922,6 +961,9 @@ impl Room { cx.spawn(|this, mut cx| async move { let project = Project::remote(id, client, user_store, language_registry, fs, cx.clone()).await?; + + cx.read(|cx| this.read(cx).play_sound(Sound::Joined, cx)); + this.update(&mut cx, |this, cx| { this.joined_projects.retain(|project| { if let Some(project) = project.upgrade(cx) { diff --git a/crates/collab/src/tests.rs b/crates/collab/src/tests.rs index b51c5240a8..5906eecee1 100644 --- a/crates/collab/src/tests.rs +++ b/crates/collab/src/tests.rs @@ -203,7 +203,7 @@ impl TestServer { language::init(cx); editor::init_settings(cx); workspace::init(app_state.clone(), cx); - call::init(client.clone(), user_store.clone(), cx); + call::init(client.clone(), user_store.clone(), (), cx); }); client diff --git a/crates/zed/src/assets.rs b/crates/zed/src/assets.rs index 6eb8a44f0f..574016c25d 100644 --- a/crates/zed/src/assets.rs +++ b/crates/zed/src/assets.rs @@ -7,6 +7,7 @@ use rust_embed::RustEmbed; #[include = "fonts/**/*"] #[include = "icons/**/*"] #[include = "themes/**/*"] +#[include = "sounds/**/*"] #[include = "*.md"] #[exclude = "*.DS_Store"] pub struct Assets; diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 31a00cb916..0fb540ece6 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -190,7 +190,7 @@ fn main() { theme_selector::init(cx); activity_indicator::init(cx); language_tools::init(cx); - call::init(app_state.client.clone(), app_state.user_store.clone(), cx); + call::init(app_state.client.clone(), app_state.user_store.clone(), Assets, cx); collab_ui::init(&app_state, cx); feedback::init(cx); welcome::init(cx); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index a7c6956a34..9d75ad9952 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2160,7 +2160,7 @@ mod tests { state.initialize_workspace = initialize_workspace; state.build_window_options = build_window_options; theme::init((), cx); - call::init(app_state.client.clone(), app_state.user_store.clone(), cx); + call::init(app_state.client.clone(), app_state.user_store.clone(), (), cx); workspace::init(app_state.clone(), cx); Project::init_settings(cx); language::init(cx); From 525521eeb39ccb97f3f8ecba72e0d3e5aeb66f01 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:38:36 +0200 Subject: [PATCH 041/104] Render match count next to branch label --- crates/collab_ui/src/branch_list.rs | 93 ++++++++++++++++------------- crates/picker/src/picker.rs | 10 +++- 2 files changed, 58 insertions(+), 45 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 0abe83f766..8c06326780 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,6 +1,8 @@ use anyhow::{anyhow, bail}; use fuzzy::{StringMatch, StringMatchCandidate}; -use gpui::{elements::*, AppContext, MouseState, Task, ViewContext, ViewHandle}; +use gpui::{ + elements::*, platform::MouseButton, AppContext, MouseState, Task, ViewContext, ViewHandle, +}; use picker::{Picker, PickerDelegate, PickerEvent}; use std::{ops::Not, sync::Arc}; use util::ResultExt; @@ -210,50 +212,55 @@ impl PickerDelegate for BranchListDelegate { .with_height(theme.contact_finder.row_height) .into_any() } - fn render_header(&self, cx: &AppContext) -> Option>> { + fn render_header( + &self, + cx: &mut ViewContext>, + ) -> Option>> { let theme = &theme::current(cx); let style = theme.picker.header.clone(); - if self.last_query.is_empty() { - Some( - Stack::new() - .with_child( - Flex::row() - .with_child(Label::new("Recent branches", style.label.clone())) - .contained() - .with_style(style.container) - .into_any(), - ) - .contained() - .with_style(style.container) - .into_any(), - ) + let label = if self.last_query.is_empty() { + Stack::new() + .with_child( + Flex::row() + .with_child(Label::new("Recent branches", style.label.clone())) + .contained() + .with_style(style.container) + .into_any(), + ) + .contained() + .with_style(style.container) + .into_any() } else { - Some( - Stack::new() - .with_child( - Flex::row() - .with_child( - Label::new("Branches", style.label.clone()).aligned().left(), - ) - .contained() - .with_style(style.container), - ) - .with_children(self.matches.is_empty().not().then(|| { - let suffix = if self.matches.len() == 1 { "" } else { "es" }; - Flex::row() - .align_children_center() - .with_child(Label::new( - format!("{} match{}", self.matches.len(), suffix), - style.label, - )) - .aligned() - .right() - })) - .contained() - .with_style(style.container) - .constrained() - .into_any(), - ) - } + Stack::new() + .with_child( + Flex::row() + .with_child(Label::new("Branches", style.label.clone()).aligned().left()) + .contained() + .with_style(style.container), + ) + .with_children(self.matches.is_empty().not().then(|| { + let suffix = if self.matches.len() == 1 { "" } else { "es" }; + Flex::row() + .align_children_center() + .with_child(Label::new( + format!("{} match{}", self.matches.len(), suffix), + style.label, + )) + .aligned() + .right() + })) + .contained() + .with_style(style.container) + .constrained() + .into_any() + }; + Some( + MouseEventHandler::::new(0, cx, move |_, _| label) + .on_click(MouseButton::Left, move |_, _, _| {}) + .on_down_out(MouseButton::Left, move |_, _, cx| { + cx.emit(PickerEvent::Dismiss) + }) + .into_any(), + ) } } diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index 33d6e84241..978d018ccf 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -45,10 +45,16 @@ pub trait PickerDelegate: Sized + 'static { fn center_selection_after_match_updates(&self) -> bool { false } - fn render_header(&self, _cx: &AppContext) -> Option>> { + fn render_header( + &self, + _cx: &mut ViewContext>, + ) -> Option>> { None } - fn render_footer(&self, _cx: &AppContext) -> Option>> { + fn render_footer( + &self, + _cx: &mut ViewContext>, + ) -> Option>> { None } } From 026ad191ebefce8234035295175e16ebe9263978 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:49:00 +0200 Subject: [PATCH 042/104] Dismiss dropdowns on click out --- crates/collab_ui/src/collab_titlebar_item.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 0857b2b79a..ea90a879ce 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -385,7 +385,11 @@ impl CollabTitlebarItem { .with_height(theme.contacts_popover.height) }) .on_click(MouseButton::Left, |_, _, _| {}) - .on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(())) + .on_down_out(MouseButton::Left, move |_, this, cx| { + this.branch_popover.take(); + cx.emit(()); + cx.notify(); + }) .into_any(); Overlay::new(child) @@ -415,7 +419,11 @@ impl CollabTitlebarItem { .with_height(theme.contacts_popover.height) }) .on_click(MouseButton::Left, |_, _, _| {}) - .on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(())) + .on_down_out(MouseButton::Left, move |_, this, cx| { + this.project_popover.take(); + cx.emit(()); + cx.notify(); + }) .into_any(); Overlay::new(child) From e36d5f41c8a29bbb81ae683fa262251c3f103e41 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 30 Jun 2023 12:38:28 -0600 Subject: [PATCH 043/104] Fix % when on the last character of the line Contributes: zed-industries/community#682 --- crates/vim/src/motion.rs | 50 ++++++++++++++++++++++++- crates/vim/test_data/test_matching.json | 17 +++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 crates/vim/test_data/test_matching.json diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index e8084cb4be..07b095dd5e 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -525,10 +525,13 @@ fn matching(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint if line_end == point { line_end = map.max_point().to_point(map); } - line_end.column = line_end.column.saturating_sub(1); let line_range = map.prev_line_boundary(point).0..line_end; - let ranges = map.buffer_snapshot.bracket_ranges(line_range.clone()); + let visible_line_range = + line_range.start..Point::new(line_range.end.row, line_range.end.column.saturating_sub(1)); + let ranges = map + .buffer_snapshot + .bracket_ranges(visible_line_range.clone()); if let Some(ranges) = ranges { let line_range = line_range.start.to_offset(&map.buffer_snapshot) ..line_range.end.to_offset(&map.buffer_snapshot); @@ -697,4 +700,47 @@ mod test { final"}) .await } + + #[gpui::test] + async fn test_matching(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {r"func ˇ(a string) { + do(something(with.and_arrays[0, 2])) + }"}) + .await; + cx.simulate_shared_keystrokes(["%"]).await; + cx.assert_shared_state(indoc! {r"func (a stringˇ) { + do(something(with.and_arrays[0, 2])) + }"}) + .await; + + // test it works on the last character of the line + cx.set_shared_state(indoc! {r"func (a string) ˇ{ + do(something(with.and_arrays[0, 2])) + }"}) + .await; + cx.simulate_shared_keystrokes(["%"]).await; + cx.assert_shared_state(indoc! {r"func (a string) { + do(something(with.and_arrays[0, 2])) + ˇ}"}) + .await; + + // test it works on immediate nesting + cx.set_shared_state("ˇ{()}").await; + cx.simulate_shared_keystrokes(["%"]).await; + cx.assert_shared_state("{()ˇ}").await; + cx.simulate_shared_keystrokes(["%"]).await; + cx.assert_shared_state("ˇ{()}").await; + + // test it works on immediate nesting inside braces + cx.set_shared_state("{\n ˇ{()}\n}").await; + cx.simulate_shared_keystrokes(["%"]).await; + cx.assert_shared_state("{\n {()ˇ}\n}").await; + + // test it jumps to the next paren on a line + cx.set_shared_state("func ˇboop() {\n}").await; + cx.simulate_shared_keystrokes(["%"]).await; + cx.assert_shared_state("func boop(ˇ) {\n}").await; + } } diff --git a/crates/vim/test_data/test_matching.json b/crates/vim/test_data/test_matching.json new file mode 100644 index 0000000000..5c8d7529b9 --- /dev/null +++ b/crates/vim/test_data/test_matching.json @@ -0,0 +1,17 @@ +{"Put":{"state":"func ˇ(a string) {\n do(something(with.and_arrays[0, 2]))\n}"}} +{"Key":"%"} +{"Get":{"state":"func (a stringˇ) {\n do(something(with.and_arrays[0, 2]))\n}","mode":"Normal"}} +{"Put":{"state":"func (a string) ˇ{\ndo(something(with.and_arrays[0, 2]))\n}"}} +{"Key":"%"} +{"Get":{"state":"func (a string) {\ndo(something(with.and_arrays[0, 2]))\nˇ}","mode":"Normal"}} +{"Put":{"state":"ˇ{()}"}} +{"Key":"%"} +{"Get":{"state":"{()ˇ}","mode":"Normal"}} +{"Key":"%"} +{"Get":{"state":"ˇ{()}","mode":"Normal"}} +{"Put":{"state":"{\n ˇ{()}\n}"}} +{"Key":"%"} +{"Get":{"state":"{\n {()ˇ}\n}","mode":"Normal"}} +{"Put":{"state":"func ˇboop() {\n}"}} +{"Key":"%"} +{"Get":{"state":"func boop(ˇ) {\n}","mode":"Normal"}} From 43d4f043312407dd20923bc2d2cbec6771bfe217 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 3 Jul 2023 11:17:12 +0300 Subject: [PATCH 044/104] Do not add extra spaces to hints --- crates/editor/src/display_map/inlay_map.rs | 89 ++++++++++++++++++++++ crates/editor/src/editor.rs | 11 +-- 2 files changed, 90 insertions(+), 10 deletions(-) diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index affb75f58d..99b22dcbb6 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -49,6 +49,19 @@ pub struct InlayProperties { pub text: T, } +impl InlayProperties { + pub fn new(position: Anchor, hint: &project::InlayHint) -> Self { + let mut text = hint.text(); + if hint.padding_right && !text.ends_with(' ') { + text.push(' '); + } + if hint.padding_left && !text.starts_with(' ') { + text.insert(0, ' '); + } + Self { position, text } + } +} + impl sum_tree::Item for Transform { type Summary = TransformSummary; @@ -1095,6 +1108,7 @@ mod tests { use super::*; use crate::{InlayId, MultiBuffer}; use gpui::AppContext; + use project::{InlayHint, InlayHintLabel}; use rand::prelude::*; use settings::SettingsStore; use std::{cmp::Reverse, env, sync::Arc}; @@ -1102,6 +1116,81 @@ mod tests { use text::Patch; use util::post_inc; + #[test] + fn test_inlay_properties_label_padding() { + assert_eq!( + InlayProperties::new( + Anchor::min(), + &InlayHint { + label: InlayHintLabel::String("a".to_string()), + buffer_id: 0, + position: text::Anchor::default(), + padding_left: false, + padding_right: false, + tooltip: None, + kind: None, + }, + ) + .text, + "a", + "Should not pad label if not requested" + ); + + assert_eq!( + InlayProperties::new( + Anchor::min(), + &InlayHint { + label: InlayHintLabel::String("a".to_string()), + buffer_id: 0, + position: text::Anchor::default(), + padding_left: true, + padding_right: true, + tooltip: None, + kind: None, + }, + ) + .text, + " a ", + "Should pad label for every side requested" + ); + + assert_eq!( + InlayProperties::new( + Anchor::min(), + &InlayHint { + label: InlayHintLabel::String(" a ".to_string()), + buffer_id: 0, + position: text::Anchor::default(), + padding_left: false, + padding_right: false, + tooltip: None, + kind: None, + }, + ) + .text, + " a ", + "Should not change already padded label" + ); + + assert_eq!( + InlayProperties::new( + Anchor::min(), + &InlayHint { + label: InlayHintLabel::String(" a ".to_string()), + buffer_id: 0, + position: text::Anchor::default(), + padding_left: true, + padding_right: true, + tooltip: None, + kind: None, + }, + ) + .text, + " a ", + "Should not change already padded label" + ); + } + #[gpui::test] fn test_basic_inlays(cx: &mut AppContext) { let buffer = MultiBuffer::build_simple("abcdefghi", cx); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 81f073ed62..016b2c7a28 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2712,16 +2712,7 @@ impl Editor { let buffer = self.buffer.read(cx).read(cx); let new_inlays = to_insert .into_iter() - .map(|(position, id, hint)| { - let mut text = hint.text(); - if hint.padding_right { - text.push(' '); - } - if hint.padding_left { - text.insert(0, ' '); - } - (id, InlayProperties { position, text }) - }) + .map(|(position, id, hint)| (id, InlayProperties::new(position, &hint))) .collect(); drop(buffer); self.display_map.update(cx, |display_map, cx| { From 4eedc3e6464564ab536c7cd1470a6c3262ccf4f1 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 3 Jul 2023 16:15:41 +0200 Subject: [PATCH 045/104] Remove flex from underneath the pickers --- crates/collab_ui/src/collab_titlebar_item.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index ea90a879ce..1a4869a583 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -377,8 +377,8 @@ impl CollabTitlebarItem { let theme = theme::current(cx).clone(); let child = ChildView::new(child, cx); let child = MouseEventHandler::::new(0, cx, |_, _| { - Flex::column() - .with_child(child.flex(1., true)) + child + .flex(1., true) .contained() .constrained() .with_width(theme.contacts_popover.width) @@ -390,6 +390,7 @@ impl CollabTitlebarItem { cx.emit(()); cx.notify(); }) + .contained() .into_any(); Overlay::new(child) @@ -411,8 +412,8 @@ impl CollabTitlebarItem { let theme = theme::current(cx).clone(); let child = ChildView::new(child, cx); let child = MouseEventHandler::::new(0, cx, |_, _| { - Flex::column() - .with_child(child.flex(1., true)) + child + .flex(1., true) .contained() .constrained() .with_width(theme.contacts_popover.width) From 85701c9b80e2addbb7eb11e9fdafa1a9517f2c3a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 3 Jul 2023 17:05:45 +0300 Subject: [PATCH 046/104] Do not perform OnTypeFormating after pair brace insert Co-Authored-By: Julia Risley --- crates/editor/src/editor.rs | 6 +- crates/editor/src/editor_tests.rs | 105 ++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 016b2c7a28..992ecd7459 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2026,6 +2026,7 @@ impl Editor { } let selections = self.selections.all_adjusted(cx); + let mut brace_inserted = false; let mut edits = Vec::new(); let mut new_selections = Vec::with_capacity(selections.len()); let mut new_autoclose_regions = Vec::new(); @@ -2084,6 +2085,7 @@ impl Editor { selection.range(), format!("{}{}", text, bracket_pair.end).into(), )); + brace_inserted = true; continue; } } @@ -2110,6 +2112,7 @@ impl Editor { selection.end..selection.end, bracket_pair.end.as_str().into(), )); + brace_inserted = true; new_selections.push(( Selection { id: selection.id, @@ -2177,8 +2180,7 @@ impl Editor { let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx); this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections)); - // When buffer contents is updated and caret is moved, try triggering on type formatting. - if settings::get::(cx).use_on_type_format { + if !brace_inserted && settings::get::(cx).use_on_type_format { if let Some(on_type_format_task) = this.trigger_on_type_formatting(text.to_string(), cx) { diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 657a7a744e..9e726d6cc4 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -6979,6 +6979,111 @@ async fn test_copilot_disabled_globs( assert!(copilot_requests.try_next().is_ok()); } +#[gpui::test] +async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + brackets: BracketPairConfig { + pairs: vec![BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: true, + newline: true, + }], + disabled_scopes_by_bracket_ix: Vec::new(), + }, + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_servers = language + .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { + capabilities: lsp::ServerCapabilities { + document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions { + first_trigger_character: "{".to_string(), + more_trigger_character: None, + }), + ..Default::default() + }, + ..Default::default() + })) + .await; + + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/a", + json!({ + "main.rs": "fn main() { let a = 5; }", + "other.rs": "// Test file", + }), + ) + .await; + let project = Project::test(fs, ["/a".as_ref()], cx).await; + project.update(cx, |project, _| project.languages().add(Arc::new(language))); + let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); + let worktree_id = workspace.update(cx, |workspace, cx| { + workspace.project().read_with(cx, |project, cx| { + project.worktrees(cx).next().unwrap().read(cx).id() + }) + }); + + let buffer = project + .update(cx, |project, cx| { + project.open_local_buffer("/a/main.rs", cx) + }) + .await + .unwrap(); + cx.foreground().run_until_parked(); + cx.foreground().start_waiting(); + let fake_server = fake_servers.next().await.unwrap(); + let editor_handle = workspace + .update(cx, |workspace, cx| { + workspace.open_path((worktree_id, "main.rs"), None, true, cx) + }) + .await + .unwrap() + .downcast::() + .unwrap(); + + fake_server.handle_request::(|params, _| async move { + assert_eq!( + params.text_document_position.text_document.uri, + lsp::Url::from_file_path("/a/main.rs").unwrap(), + ); + assert_eq!( + params.text_document_position.position, + lsp::Position::new(0, 21), + ); + + Ok(Some(vec![lsp::TextEdit { + new_text: "]".to_string(), + range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)), + }])) + }); + + editor_handle.update(cx, |editor, cx| { + cx.focus(&editor_handle); + editor.change_selections(None, cx, |s| { + s.select_ranges([Point::new(0, 21)..Point::new(0, 20)]) + }); + editor.handle_input("{", cx); + }); + + cx.foreground().run_until_parked(); + + buffer.read_with(cx, |buffer, _| { + assert_eq!( + buffer.text(), + "fn main() { let a = {5}; }", + "No extra braces from on type formatting should appear in the buffer" + ) + }); +} + fn empty_range(row: usize, column: usize) -> Range { let point = DisplayPoint::new(row as u32, column as u32); point..point From 14eab4e94fae61b860bba70c8e74ba979bbf53c4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 3 Jul 2023 19:22:43 +0200 Subject: [PATCH 047/104] branch list: dismiss correct window on PickerEvent. Query proper window --- crates/collab_ui/src/branch_list.rs | 18 ++++++++---------- crates/collab_ui/src/collab_titlebar_item.rs | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 8c06326780..e0f85aa65a 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -60,24 +60,24 @@ impl PickerDelegate for BranchListDelegate { .read_with(&mut cx, |view, cx| { let delegate = view.delegate(); let project = delegate.workspace.read(cx).project().read(&cx); - let mut cwd = project + let mut cwd = + project .visible_worktrees(cx) .next() .unwrap() .read(cx) - .root_entry() - .unwrap() - .path + .abs_path() .to_path_buf(); cwd.push(".git"); let Some(repo) = project.fs().open_repo(&cwd) else {bail!("Project does not have associated git repository.")}; let mut branches = repo .lock() .branches()?; - if query.is_empty() { - const RECENT_BRANCHES_COUNT: usize = 10; + const RECENT_BRANCHES_COUNT: usize = 10; + if query.is_empty() && branches.len() > RECENT_BRANCHES_COUNT { + // Truncate list of recent branches // Do a partial sort to show recent-ish branches first. - branches.select_nth_unstable_by(RECENT_BRANCHES_COUNT, |lhs, rhs| { + branches.select_nth_unstable_by(RECENT_BRANCHES_COUNT - 1, |lhs, rhs| { rhs.unix_timestamp.cmp(&lhs.unix_timestamp) }); branches.truncate(RECENT_BRANCHES_COUNT); @@ -145,9 +145,7 @@ impl PickerDelegate for BranchListDelegate { .next() .ok_or_else(|| anyhow!("There are no visisible worktrees."))? .read(cx) - .root_entry() - .ok_or_else(|| anyhow!("Worktree has no root entry."))? - .path + .abs_path() .to_path_buf(); cwd.push(".git"); let status = project diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 1a4869a583..8af3acf7be 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -444,7 +444,7 @@ impl CollabTitlebarItem { cx.subscribe(&view, |this, _, event, cx| { match event { PickerEvent::Dismiss => { - this.contacts_popover = None; + this.branch_popover = None; } } From b055f594b06bd0ad56dab64b24c5af613f538ddd Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 12:50:17 -0600 Subject: [PATCH 048/104] vim: ctrl-c to exit visual mode Fixes: zed-industries/community#1447 Contributes: zed-industries/community#1089 --- assets/keymaps/vim.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index afee6fcd2e..d019078834 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -305,6 +305,10 @@ "vim::PushOperator", "Replace" ], + "ctrl-c": [ + "vim::SwitchMode", + "Normal" + ], "> >": "editor::Indent", "< <": "editor::Outdent" } From fe57e04016c120eb83441b8722febed1f6b4984f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 12:55:41 -0600 Subject: [PATCH 049/104] vim: Allow ^ as a motion Fixes: zed-industries/community#856 --- assets/keymaps/vim.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index d019078834..86e5b51f19 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -35,6 +35,7 @@ "l": "vim::Right", "right": "vim::Right", "$": "vim::EndOfLine", + "^": "vim::FirstNonWhitespace", "shift-g": "vim::EndOfDocument", "w": "vim::NextWordStart", "shift-w": [ @@ -165,7 +166,6 @@ "shift-a": "vim::InsertEndOfLine", "x": "vim::DeleteRight", "shift-x": "vim::DeleteLeft", - "^": "vim::FirstNonWhitespace", "o": "vim::InsertLineBelow", "shift-o": "vim::InsertLineAbove", "~": "vim::ChangeCase", From d2127825e3e2f16fc756344246a7c58448514c7a Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 3 Jul 2023 13:30:04 -0700 Subject: [PATCH 050/104] Add first-pass sound support to Zed --- Cargo.lock | 17 ++++- Cargo.toml | 1 + assets/sounds/joined.wav | Bin 0 -> 16142 bytes assets/sounds/leave.wav | Bin 0 -> 137188 bytes assets/sounds/mute.wav | Bin 0 -> 29314 bytes assets/sounds/unmute.wav | Bin 0 -> 133336 bytes crates/audio/Cargo.toml | 23 +++++++ crates/audio/src/assets.rs | 44 +++++++++++++ crates/audio/src/audio.rs | 59 +++++++++++++++++ crates/call/Cargo.toml | 2 +- crates/call/src/call.rs | 6 +- crates/call/src/room.rs | 128 +++++++++++++++++-------------------- crates/collab/Cargo.toml | 1 + crates/collab/src/tests.rs | 3 +- crates/zed/Cargo.toml | 1 + crates/zed/src/main.rs | 4 +- crates/zed/src/zed.rs | 3 +- 17 files changed, 213 insertions(+), 79 deletions(-) create mode 100644 assets/sounds/joined.wav create mode 100644 assets/sounds/leave.wav create mode 100644 assets/sounds/mute.wav create mode 100644 assets/sounds/unmute.wav create mode 100644 crates/audio/Cargo.toml create mode 100644 crates/audio/src/assets.rs create mode 100644 crates/audio/src/audio.rs diff --git a/Cargo.lock b/Cargo.lock index 6dcf614e08..07db6c0e7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -612,6 +612,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "audio" +version = "0.1.0" +dependencies = [ + "anyhow", + "collections", + "gpui", + "log", + "parking_lot 0.11.2", + "rodio", + "util", +] + [[package]] name = "auto_update" version = "0.1.0" @@ -1028,6 +1041,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-broadcast", + "audio", "client", "collections", "fs", @@ -1039,7 +1053,6 @@ dependencies = [ "media", "postage", "project", - "rodio", "settings", "util", ] @@ -1392,6 +1405,7 @@ version = "0.15.0" dependencies = [ "anyhow", "async-tungstenite", + "audio", "axum", "axum-extra", "base64 0.13.1", @@ -9331,6 +9345,7 @@ dependencies = [ "async-recursion 0.3.2", "async-tar", "async-trait", + "audio", "auto_update", "backtrace", "breadcrumbs", diff --git a/Cargo.toml b/Cargo.toml index 26555f32cd..1708ccfc0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "crates/activity_indicator", "crates/ai", + "crates/audio", "crates/auto_update", "crates/breadcrumbs", "crates/call", diff --git a/assets/sounds/joined.wav b/assets/sounds/joined.wav new file mode 100644 index 0000000000000000000000000000000000000000..70cd41d16f9b21dcb46a0f91e7f446a4157f8239 GIT binary patch literal 16142 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

-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�>;(#`b*dUN70#w)$sjs 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%0DKkn{W3HQMgB4vg~2rt8sP{I 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 Zw!dq+{npEOfBcho-u>arx85j~J_Zedc$EME literal 0 HcmV?d00001 diff --git a/assets/sounds/unmute.wav b/assets/sounds/unmute.wav new file mode 100644 index 0000000000000000000000000000000000000000..d87decead02aa91fbcccbd661631636b5ee0975b GIT binary patch literal 133336 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

*xdFeH?dx;nq&{_=fa#81(@Li;$R(vv&BJgoI&O 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 IF1cO*2aA8;;Q#;t literal 0 HcmV?d00001 diff --git a/crates/audio/Cargo.toml b/crates/audio/Cargo.toml new file mode 100644 index 0000000000..182e421eb8 --- /dev/null +++ b/crates/audio/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "audio" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/audio.rs" +doctest = false + +[dependencies] +gpui = { path = "../gpui" } +collections = { path = "../collections" } +util = { path = "../util" } + +rodio = "0.17.1" + +log.workspace = true + +anyhow.workspace = true +parking_lot.workspace = true + +[dev-dependencies] diff --git a/crates/audio/src/assets.rs b/crates/audio/src/assets.rs new file mode 100644 index 0000000000..b58e1f6aee --- /dev/null +++ b/crates/audio/src/assets.rs @@ -0,0 +1,44 @@ +use std::{io::Cursor, sync::Arc}; + +use anyhow::Result; +use collections::HashMap; +use gpui::{AppContext, AssetSource}; +use rodio::{ + source::{Buffered, SamplesConverter}, + Decoder, Source, +}; + +type Sound = Buffered>>, f32>>; + +pub struct SoundRegistry { + cache: Arc>>, + assets: Box, +} + +impl SoundRegistry { + pub fn new(source: impl AssetSource) -> Arc { + Arc::new(Self { + cache: Default::default(), + assets: Box::new(source), + }) + } + + pub fn global(cx: &AppContext) -> Arc { + cx.global::>().clone() + } + + pub fn get(&self, name: &str) -> Result> { + if let Some(wav) = self.cache.lock().get(name) { + return Ok(wav.clone()); + } + + let path = format!("sounds/{}.wav", name); + let bytes = self.assets.load(&path)?.into_owned(); + let cursor = Cursor::new(bytes); + let source = Decoder::new(cursor)?.convert_samples::().buffered(); + + self.cache.lock().insert(name.to_string(), source.clone()); + + Ok(source) + } +} diff --git a/crates/audio/src/audio.rs b/crates/audio/src/audio.rs new file mode 100644 index 0000000000..fd3f4e0515 --- /dev/null +++ b/crates/audio/src/audio.rs @@ -0,0 +1,59 @@ +use assets::SoundRegistry; +use gpui::{AppContext, AssetSource}; +use rodio::{OutputStream, OutputStreamHandle}; +use util::ResultExt; + +mod assets; + +pub fn init(source: impl AssetSource, cx: &mut AppContext) { + cx.set_global(SoundRegistry::new(source)); + cx.set_global(Audio::new()); +} + +pub enum Sound { + Joined, + Leave, + Mute, + Unmute, +} + +impl Sound { + fn file(&self) -> &'static str { + match self { + Self::Joined => "joined", + Self::Leave => "leave", + Self::Mute => "mute", + Self::Unmute => "unmute", + } + } +} + +pub struct Audio { + _output_stream: Option, + output_handle: Option, +} + +impl Audio { + pub fn new() -> Self { + let (_output_stream, output_handle) = OutputStream::try_default().log_err().unzip(); + + Self { + _output_stream, + output_handle, + } + } + + pub fn play_sound(sound: Sound, cx: &AppContext) { + let this = cx.global::(); + + let Some(output_handle) = this.output_handle.as_ref() else { + return; + }; + + let Some(source) = SoundRegistry::global(cx).get(sound.file()).log_err() else { + return; + }; + + output_handle.play_raw(source).log_err(); + } +} diff --git a/crates/call/Cargo.toml b/crates/call/Cargo.toml index 86ff1a5543..61f3593247 100644 --- a/crates/call/Cargo.toml +++ b/crates/call/Cargo.toml @@ -19,6 +19,7 @@ test-support = [ ] [dependencies] +audio = { path = "../audio" } client = { path = "../client" } collections = { path = "../collections" } gpui = { path = "../gpui" } @@ -30,7 +31,6 @@ media = { path = "../media" } project = { path = "../project" } settings = { path = "../settings" } util = { path = "../util" } -rodio = "0.17.1" anyhow.workspace = true async-broadcast = "0.4" diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index 42cb5f2f87..74ce7c2e75 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -1,18 +1,16 @@ -mod assets; pub mod participant; pub mod room; use std::sync::Arc; use anyhow::{anyhow, Result}; -use assets::SoundRegistry; use client::{proto, Client, TypedEnvelope, User, UserStore}; use collections::HashSet; use futures::{future::Shared, FutureExt}; use postage::watch; use gpui::{ - AppContext, AssetSource, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, + AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, Task, WeakModelHandle, }; use project::Project; @@ -23,10 +21,8 @@ pub use room::Room; pub fn init( client: Arc, user_store: ModelHandle, - source: impl AssetSource, cx: &mut AppContext, ) { - cx.set_global(SoundRegistry::new(source)); let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx)); cx.set_global(active_call); } diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index b80e994fcf..10cfc862e9 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -1,9 +1,9 @@ use crate::{ - assets::SoundRegistry, participant::{LocalParticipant, ParticipantLocation, RemoteParticipant, RemoteVideoTrack}, IncomingCall, }; use anyhow::{anyhow, Result}; +use audio::{Audio, Sound}; use client::{ proto::{self, PeerId}, Client, TypedEnvelope, User, UserStore, @@ -19,30 +19,11 @@ use live_kit_client::{ }; use postage::stream::Stream; use project::Project; -use rodio::{OutputStream, OutputStreamHandle, Source}; use std::{future::Future, mem, pin::Pin, sync::Arc, time::Duration}; use util::{post_inc, ResultExt, TryFutureExt}; pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30); -enum Sound { - Joined, - Leaved, - Mute, - Unmute, -} - -impl Sound { - fn file(&self) -> &'static str { - match self { - Self::Joined => "joined", - Self::Leaved => "leave", - Self::Mute => "mute", - Self::Unmute => "unmute", - } - } -} - #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { ParticipantLocationChanged { @@ -68,8 +49,6 @@ pub enum Event { pub struct Room { id: u64, live_kit: Option, - _sound_output_stream: Option, - sound_output_handle: Option, status: RoomStatus, shared_projects: HashSet>, joined_projects: HashSet>, @@ -173,6 +152,7 @@ impl Room { let connect = room.connect(&connection_info.server_url, &connection_info.token); cx.spawn(|this, mut cx| async move { connect.await?; + this.update(&mut cx, |this, cx| this.share_microphone(cx)) .await?; @@ -198,14 +178,11 @@ impl Room { let maintain_connection = cx.spawn_weak(|this, cx| Self::maintain_connection(this, client.clone(), cx).log_err()); - let (sound_output_stream, sound_output_handle) = - OutputStream::try_default().log_err().unzip(); + Audio::play_sound(Sound::Joined, cx); Self { id, live_kit: live_kit_room, - _sound_output_stream: sound_output_stream, - sound_output_handle, status: RoomStatus::Online, shared_projects: Default::default(), joined_projects: Default::default(), @@ -292,6 +269,7 @@ impl Room { room.apply_room_update(room_proto, cx)?; anyhow::Ok(()) })?; + Ok(room) }) } @@ -333,6 +311,8 @@ impl Room { } } + Audio::play_sound(Sound::Leave, cx); + self.status = RoomStatus::Offline; self.remote_participants.clear(); self.pending_participants.clear(); @@ -937,18 +917,6 @@ impl Room { }) } - fn play_sound(&self, sound: Sound, cx: &AppContext) { - let Some(output_handle) = self.sound_output_handle.as_ref() else { - return; - }; - - let Some(source) = SoundRegistry::global(cx).get(sound.file()) else { - return; - }; - - output_handle.play_raw(source.convert_samples()).log_err(); - } - pub fn join_project( &mut self, id: u64, @@ -962,8 +930,6 @@ impl Room { let project = Project::remote(id, client, user_store, language_registry, fs, cx.clone()).await?; - cx.read(|cx| this.read(cx).play_sound(Sound::Joined, cx)); - this.update(&mut cx, |this, cx| { this.joined_projects.retain(|project| { if let Some(project) = project.upgrade(cx) { @@ -1269,38 +1235,20 @@ impl Room { }) }) } - fn set_mute( - live_kit: &mut LiveKitRoom, - should_mute: bool, - cx: &mut ModelContext, - ) -> Result>> { - if !should_mute { - // clear user muting state. - live_kit.muted_by_user = false; - } - match &mut live_kit.microphone_track { - LocalTrack::None => Err(anyhow!("microphone was not shared")), - LocalTrack::Pending { muted, .. } => { - *muted = should_mute; - cx.notify(); - Ok(Task::Ready(Some(Ok(())))) - } - LocalTrack::Published { - track_publication, - muted, - } => { - *muted = should_mute; - cx.notify(); - Ok(cx.background().spawn(track_publication.set_mute(*muted))) - } - } - } + pub fn toggle_mute(&mut self, cx: &mut ModelContext) -> Result>> { let should_mute = !self.is_muted(); if let Some(live_kit) = self.live_kit.as_mut() { - let ret = Self::set_mute(live_kit, should_mute, cx); + let (ret_task, old_muted) = live_kit.set_mute(should_mute, cx)?; live_kit.muted_by_user = should_mute; - ret + + if old_muted == true && live_kit.deafened == true { + if let Some(task) = self.toggle_deafen(cx).ok() { + task.detach(); + } + } + + Ok(ret_task) } else { Err(anyhow!("LiveKit not started")) } @@ -1316,7 +1264,7 @@ impl Room { // When deafening, mute user's mic as well. // When undeafening, unmute user's mic unless it was manually muted prior to deafening. if live_kit.deafened || !live_kit.muted_by_user { - mute_task = Some(Self::set_mute(live_kit, live_kit.deafened, cx)?); + mute_task = Some(live_kit.set_mute(live_kit.deafened, cx)?.0); }; for participant in self.remote_participants.values() { for track in live_kit @@ -1389,6 +1337,48 @@ struct LiveKitRoom { _maintain_tracks: [Task<()>; 2], } +impl LiveKitRoom { + fn set_mute( + self: &mut LiveKitRoom, + should_mute: bool, + cx: &mut ModelContext, + ) -> Result<(Task>, bool)> { + if !should_mute { + // clear user muting state. + self.muted_by_user = false; + } + + let (result, old_muted) = match &mut self.microphone_track { + LocalTrack::None => Err(anyhow!("microphone was not shared")), + LocalTrack::Pending { muted, .. } => { + let old_muted = *muted; + *muted = should_mute; + cx.notify(); + Ok((Task::Ready(Some(Ok(()))), old_muted)) + } + LocalTrack::Published { + track_publication, + muted, + } => { + let old_muted = *muted; + *muted = should_mute; + cx.notify(); + Ok((cx.background().spawn(track_publication.set_mute(*muted)), old_muted)) + } + }?; + + if old_muted != should_mute { + if should_mute { + Audio::play_sound(Sound::Mute, cx); + } else { + Audio::play_sound(Sound::Unmute, cx); + } + } + + Ok((result, old_muted)) + } +} + enum LocalTrack { None, Pending { diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index c787287a0c..cc7263aa97 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -14,6 +14,7 @@ name = "seed" required-features = ["seed-support"] [dependencies] +audio = { path = "../audio" } collections = { path = "../collections" } live_kit_server = { path = "../live_kit_server" } rpc = { path = "../rpc" } diff --git a/crates/collab/src/tests.rs b/crates/collab/src/tests.rs index 5906eecee1..b1d0bedb2c 100644 --- a/crates/collab/src/tests.rs +++ b/crates/collab/src/tests.rs @@ -203,7 +203,8 @@ impl TestServer { language::init(cx); editor::init_settings(cx); workspace::init(app_state.clone(), cx); - call::init(client.clone(), user_store.clone(), (), cx); + audio::init((), cx); + call::init(client.clone(), user_store.clone(), cx); }); client diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 6434d36951..97d7f717ce 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -16,6 +16,7 @@ name = "Zed" path = "src/main.rs" [dependencies] +audio = { path = "../audio" } activity_indicator = { path = "../activity_indicator" } auto_update = { path = "../auto_update" } breadcrumbs = { path = "../breadcrumbs" } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 0fb540ece6..3da8c24617 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -180,6 +180,8 @@ fn main() { background_actions, }); cx.set_global(Arc::downgrade(&app_state)); + + audio::init(Assets, cx); auto_update::init(http.clone(), client::ZED_SERVER_URL.clone(), cx); workspace::init(app_state.clone(), cx); @@ -190,7 +192,7 @@ fn main() { theme_selector::init(cx); activity_indicator::init(cx); language_tools::init(cx); - call::init(app_state.client.clone(), app_state.user_store.clone(), Assets, cx); + call::init(app_state.client.clone(), app_state.user_store.clone(), cx); collab_ui::init(&app_state, cx); feedback::init(cx); welcome::init(cx); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 9d75ad9952..874fea6500 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2160,7 +2160,8 @@ mod tests { state.initialize_workspace = initialize_workspace; state.build_window_options = build_window_options; theme::init((), cx); - call::init(app_state.client.clone(), app_state.user_store.clone(), (), cx); + audio::init((), cx); + call::init(app_state.client.clone(), app_state.user_store.clone(), cx); workspace::init(app_state.clone(), cx); Project::init_settings(cx); language::init(cx); From 0e4c9040914551d2c429e2bd5eedc9df4b4da2d6 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 3 Jul 2023 13:36:03 -0700 Subject: [PATCH 051/104] Add joined sound effect when new participants join the room --- crates/call/src/call.rs | 10 +++------- crates/call/src/room.rs | 7 ++++++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index 74ce7c2e75..0a8f150194 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -10,19 +10,15 @@ use futures::{future::Shared, FutureExt}; use postage::watch; use gpui::{ - AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, - Task, WeakModelHandle, + AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, Task, + WeakModelHandle, }; use project::Project; pub use participant::ParticipantLocation; pub use room::Room; -pub fn init( - client: Arc, - user_store: ModelHandle, - cx: &mut AppContext, -) { +pub fn init(client: Arc, user_store: ModelHandle, cx: &mut AppContext) { let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx)); cx.set_global(active_call); } diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index 10cfc862e9..eed73ba1b1 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -663,6 +663,8 @@ impl Room { }, ); + Audio::play_sound(Sound::Joined, cx); + if let Some(live_kit) = this.live_kit.as_ref() { let video_tracks = live_kit.room.remote_video_tracks(&user.id.to_string()); @@ -1363,7 +1365,10 @@ impl LiveKitRoom { let old_muted = *muted; *muted = should_mute; cx.notify(); - Ok((cx.background().spawn(track_publication.set_mute(*muted)), old_muted)) + Ok(( + cx.background().spawn(track_publication.set_mute(*muted)), + old_muted, + )) } }?; From c700342a1c4fdc3b11265f81b6281dc54e0e80c0 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 3 Jul 2023 13:48:17 -0700 Subject: [PATCH 052/104] Guard against uninstantiated globals in tests --- crates/audio/src/audio.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/audio/src/audio.rs b/crates/audio/src/audio.rs index fd3f4e0515..0216bf47be 100644 --- a/crates/audio/src/audio.rs +++ b/crates/audio/src/audio.rs @@ -44,6 +44,10 @@ impl Audio { } pub fn play_sound(sound: Sound, cx: &AppContext) { + if !cx.has_global::() { + return; + } + let this = cx.global::(); let Some(output_handle) = this.output_handle.as_ref() else { From 0733e8d50f0ffa3339cb03c14b661ca2f4334d9f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 15:20:10 -0600 Subject: [PATCH 053/104] Remove editor::Cancel binding from vim When you hit in the command palette, it first editor::Cancel because the command palette is also a focused editor; this binding was catching before the `menu::Cancel` that you probably want. From looking at the uses of editor::Cancel it seems like the only way to trigger this is with in an editor. Rather than trying to hook into the existing editor cancel and add vim-specific behaviour, we'll instead take responsibility for binding directly to when necessary. Fixes: zed-industries/community#1347 --- assets/keymaps/vim.json | 10 ++++++++-- crates/vim/src/test.rs | 14 ++++++++++++++ crates/vim/src/test/vim_test_context.rs | 2 ++ crates/vim/src/vim.rs | 23 ++--------------------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 86e5b51f19..e08ce47caf 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -93,7 +93,10 @@ ], "ctrl-o": "pane::GoBack", "ctrl-]": "editor::GoToDefinition", - "escape": "editor::Cancel", + "escape": [ + "vim::SwitchMode", + "Normal" + ], "0": "vim::StartOfLine", // When no number operator present, use start of line motion "1": [ "vim::Number", @@ -325,7 +328,10 @@ "bindings": { "tab": "vim::Tab", "enter": "vim::Enter", - "escape": "editor::Cancel" + "escape": [ + "vim::SwitchMode", + "Normal" + ] } } ] diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index b6c5b7ca51..a6efbd4da1 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -4,6 +4,7 @@ mod neovim_connection; mod vim_binding_test_context; mod vim_test_context; +use command_palette::CommandPalette; pub use neovim_backed_binding_test_context::*; pub use neovim_backed_test_context::*; pub use vim_binding_test_context::*; @@ -139,3 +140,16 @@ async fn test_indent_outdent(cx: &mut gpui::TestAppContext) { cx.simulate_keystrokes(["shift-v", "down", ">", ">"]); cx.assert_editor_state("aa\n b«b\n cˇ»c"); } + +#[gpui::test] +async fn test_escape_command_palette(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state("aˇbc\n", Mode::Normal); + cx.simulate_keystrokes(["i", "cmd-shift-p"]); + + assert!(cx.workspace(|workspace, _| workspace.modal::().is_some())); + cx.simulate_keystroke("escape"); + assert!(!cx.workspace(|workspace, _| workspace.modal::().is_some())); + cx.assert_state("aˇbc\n", Mode::Insert); +} diff --git a/crates/vim/src/test/vim_test_context.rs b/crates/vim/src/test/vim_test_context.rs index 3e66d6bb1c..f9ba577231 100644 --- a/crates/vim/src/test/vim_test_context.rs +++ b/crates/vim/src/test/vim_test_context.rs @@ -21,12 +21,14 @@ impl<'a> VimTestContext<'a> { cx.update(|cx| { search::init(cx); crate::init(cx); + command_palette::init(cx); }); cx.update(|cx| { cx.update_global(|store: &mut SettingsStore, cx| { store.update_user_settings::(cx, |s| *s = Some(enabled)); }); + settings::KeymapFile::load_asset("keymaps/default.json", cx).unwrap(); settings::KeymapFile::load_asset("keymaps/vim.json", cx).unwrap(); }); diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index eae8643cf3..2bcc2254ee 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -12,7 +12,7 @@ mod visual; use anyhow::Result; use collections::CommandPaletteFilter; -use editor::{Bias, Cancel, Editor, EditorMode, Event}; +use editor::{Bias, Editor, EditorMode, Event}; use gpui::{ actions, impl_actions, AppContext, Subscription, ViewContext, ViewHandle, WeakViewHandle, WindowContext, @@ -64,22 +64,6 @@ pub fn init(cx: &mut AppContext) { Vim::update(cx, |vim, cx| vim.push_number(n, cx)); }); - // Editor Actions - cx.add_action(|_: &mut Editor, _: &Cancel, cx| { - // If we are in aren't in normal mode or have an active operator, swap to normal mode - // Otherwise forward cancel on to the editor - let vim = Vim::read(cx); - if vim.state.mode != Mode::Normal || vim.active_operator().is_some() { - WindowContext::defer(cx, |cx| { - Vim::update(cx, |state, cx| { - state.switch_mode(Mode::Normal, false, cx); - }); - }); - } else { - cx.propagate_action(); - } - }); - cx.add_action(|_: &mut Workspace, _: &Tab, cx| { Vim::active_editor_input_ignored(" ".into(), cx) }); @@ -109,10 +93,7 @@ pub fn observe_keystrokes(cx: &mut WindowContext) { cx.observe_keystrokes(|_keystroke, _result, handled_by, cx| { if let Some(handled_by) = handled_by { // Keystroke is handled by the vim system, so continue forward - // Also short circuit if it is the special cancel action - if handled_by.namespace() == "vim" - || (handled_by.namespace() == "editor" && handled_by.name() == "Cancel") - { + if handled_by.namespace() == "vim" { return true; } } From d5acfe8fc12e21fd01ded66cc3433795c9acf9aa Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 00:13:04 -0400 Subject: [PATCH 054/104] Use theme store to pass `color_scheme` directly to components --- styles/package-lock.json | 64 ++++++++++++++++++- styles/package.json | 15 +++-- styles/src/build_themes.ts | 14 ++-- styles/src/component/icon_button.ts | 13 ++-- styles/src/component/text_button.ts | 17 +++-- styles/src/styleTree/editor.ts | 0 styles/src/style_tree/app.ts | 56 ++++++++-------- styles/src/style_tree/assistant.ts | 6 +- styles/src/style_tree/command_palette.ts | 6 +- styles/src/style_tree/contact_finder.ts | 8 ++- styles/src/style_tree/contact_list.ts | 6 +- styles/src/style_tree/contact_notification.ts | 6 +- styles/src/style_tree/contacts_popover.ts | 6 +- styles/src/style_tree/context_menu.ts | 6 +- styles/src/style_tree/copilot.ts | 6 +- styles/src/style_tree/editor.ts | 9 ++- styles/src/style_tree/feedback.ts | 6 +- styles/src/style_tree/hover_popover.ts | 6 +- .../style_tree/incoming_call_notification.ts | 8 +-- styles/src/style_tree/picker.ts | 6 +- styles/src/style_tree/project_diagnostics.ts | 6 +- styles/src/style_tree/project_panel.ts | 23 +++---- .../style_tree/project_shared_notification.ts | 8 +-- styles/src/style_tree/search.ts | 6 +- styles/src/style_tree/shared_screen.ts | 6 +- .../style_tree/simple_message_notification.ts | 6 +- styles/src/style_tree/status_bar.ts | 6 +- styles/src/style_tree/tab_bar.ts | 6 +- styles/src/style_tree/terminal.ts | 6 +- styles/src/style_tree/titlebar.ts | 20 ++++-- .../src/style_tree/toolbar_dropdown_menu.ts | 6 +- styles/src/style_tree/tooltip.ts | 6 +- styles/src/style_tree/update_notification.ts | 6 +- styles/src/style_tree/welcome.ts | 6 +- styles/src/style_tree/workspace.ts | 14 ++-- styles/src/theme/index.ts | 21 ++++++ 36 files changed, 280 insertions(+), 136 deletions(-) delete mode 100644 styles/src/styleTree/editor.ts diff --git a/styles/package-lock.json b/styles/package-lock.json index 3f73a0b4e5..6fc5f746e5 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -27,7 +27,8 @@ "ts-node": "^10.9.1", "typescript": "^5.1.5", "utility-types": "^3.10.0", - "vitest": "^0.32.0" + "vitest": "^0.32.0", + "zustand": "^4.3.8" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2595,6 +2596,12 @@ "node": ">= 0.8" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2706,6 +2713,18 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/loupe": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", @@ -3292,6 +3311,18 @@ } ] }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -4025,6 +4056,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/utility-types": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", @@ -4305,6 +4344,29 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.8.tgz", + "integrity": "sha512-4h28KCkHg5ii/wcFFJ5Fp+k1J3gJoasaIbppdgZFO4BPJnsNxL0mQXBSFgOgAdCdBj35aDTPvdAJReTMntFPGg==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/styles/package.json b/styles/package.json index d82bbb7e81..16e95d90d5 100644 --- a/styles/package.json +++ b/styles/package.json @@ -16,21 +16,22 @@ "@tokens-studio/types": "^0.2.3", "@types/chroma-js": "^2.4.0", "@types/node": "^18.14.1", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", + "@vitest/coverage-v8": "^0.32.0", "ayu": "^8.0.1", "chroma-js": "^2.4.2", "deepmerge": "^4.3.0", + "eslint": "^8.43.0", + "eslint-import-resolver-typescript": "^3.5.5", + "eslint-plugin-import": "^2.27.5", "json-schema-to-typescript": "^13.0.2", "toml": "^3.0.0", "ts-deepmerge": "^6.0.3", "ts-node": "^10.9.1", + "typescript": "^5.1.5", "utility-types": "^3.10.0", "vitest": "^0.32.0", - "@typescript-eslint/eslint-plugin": "^5.60.1", - "@typescript-eslint/parser": "^5.60.1", - "@vitest/coverage-v8": "^0.32.0", - "eslint": "^8.43.0", - "eslint-import-resolver-typescript": "^3.5.5", - "eslint-plugin-import": "^2.27.5", - "typescript": "^5.1.5" + "zustand": "^4.3.8" } } diff --git a/styles/src/build_themes.ts b/styles/src/build_themes.ts index 5a091719df..a9cbad94e7 100644 --- a/styles/src/build_themes.ts +++ b/styles/src/build_themes.ts @@ -4,6 +4,7 @@ import * as path from "path" import app from "./style_tree/app" import { ColorScheme, create_color_scheme } from "./theme/color_scheme" import { themes } from "./themes" +import { useThemeStore } from "./theme" const assets_directory = `${__dirname}/../../assets` const temp_directory = fs.mkdtempSync(path.join(tmpdir(), "build-themes")) @@ -20,10 +21,17 @@ function clear_themes(theme_directory: string) { } } +const all_themes: ColorScheme[] = themes.map((theme) => + create_color_scheme(theme) +) + function write_themes(themes: ColorScheme[], output_directory: string) { clear_themes(output_directory) for (const color_scheme of themes) { - const style_tree = app(color_scheme) + const { setTheme } = useThemeStore.getState() + setTheme(color_scheme) + + const style_tree = app() const style_tree_json = JSON.stringify(style_tree, null, 2) const temp_path = path.join(temp_directory, `${color_scheme.name}.json`) const out_path = path.join( @@ -36,8 +44,4 @@ function write_themes(themes: ColorScheme[], output_directory: string) { } } -const all_themes: ColorScheme[] = themes.map((theme) => - create_color_scheme(theme) -) - write_themes(all_themes, `${assets_directory}/themes`) diff --git a/styles/src/component/icon_button.ts b/styles/src/component/icon_button.ts index 79891c2477..18b900e833 100644 --- a/styles/src/component/icon_button.ts +++ b/styles/src/component/icon_button.ts @@ -1,6 +1,6 @@ import { interactive, toggleable } from "../element" import { background, foreground } from "../style_tree/components" -import { ColorScheme } from "../theme/color_scheme" +import { useTheme, ColorScheme } from "../theme" export type Margin = { top: number @@ -22,10 +22,9 @@ type ToggleableIconButtonOptions = IconButtonOptions & { active_color?: keyof ColorScheme["lowest"] } -export function icon_button( - theme: ColorScheme, - { color, margin, layer }: IconButtonOptions -) { +export function icon_button({ color, margin, layer }: IconButtonOptions) { + const theme = useTheme() + if (!color) color = "base" const m = { @@ -75,8 +74,8 @@ export function toggleable_icon_button( return toggleable({ state: { - inactive: icon_button(theme, { color, margin }), - active: icon_button(theme, { + inactive: icon_button({ color, margin }), + active: icon_button({ color: active_color ? active_color : color, margin, layer: theme.middle, diff --git a/styles/src/component/text_button.ts b/styles/src/component/text_button.ts index 477c2515e3..50737f9766 100644 --- a/styles/src/component/text_button.ts +++ b/styles/src/component/text_button.ts @@ -5,7 +5,7 @@ import { foreground, text, } from "../style_tree/components" -import { ColorScheme } from "../theme/color_scheme" +import { useTheme, ColorScheme } from "../theme" import { Margin } from "./icon_button" interface TextButtonOptions { @@ -22,10 +22,13 @@ type ToggleableTextButtonOptions = TextButtonOptions & { active_color?: keyof ColorScheme["lowest"] } -export function text_button( - theme: ColorScheme, - { color, layer, margin, text_properties }: TextButtonOptions -) { +export function text_button({ + color, + layer, + margin, + text_properties, +}: TextButtonOptions) { + const theme = useTheme() if (!color) color = "base" const text_options: TextProperties = { @@ -79,8 +82,8 @@ export function toggleable_text_button( return toggleable({ state: { - inactive: text_button(theme, { color, margin }), - active: text_button(theme, { + inactive: text_button({ color, margin }), + active: text_button({ color: active_color ? active_color : color, margin, layer: theme.middle, diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/styles/src/style_tree/app.ts b/styles/src/style_tree/app.ts index 684614d073..e4bf232b62 100644 --- a/styles/src/style_tree/app.ts +++ b/styles/src/style_tree/app.ts @@ -17,45 +17,47 @@ import terminal from "./terminal" import contact_list from "./contact_list" import toolbar_dropdown_menu from "./toolbar_dropdown_menu" import incoming_call_notification from "./incoming_call_notification" -import { ColorScheme } from "../theme/color_scheme" import welcome from "./welcome" import copilot from "./copilot" import assistant from "./assistant" import { titlebar } from "./titlebar" import editor from "./editor" import feedback from "./feedback" +import { useTheme } from "../common" + +export default function app(): any { + const theme = useTheme() -export default function app(theme: ColorScheme): any { return { meta: { name: theme.name, is_light: theme.is_light, }, - command_palette: command_palette(theme), - contact_notification: contact_notification(theme), - project_shared_notification: project_shared_notification(theme), - incoming_call_notification: incoming_call_notification(theme), - picker: picker(theme), - workspace: workspace(theme), - titlebar: titlebar(theme), - copilot: copilot(theme), - welcome: welcome(theme), - context_menu: context_menu(theme), - editor: editor(theme), - project_diagnostics: project_diagnostics(theme), - project_panel: project_panel(theme), - contacts_popover: contacts_popover(theme), - contact_finder: contact_finder(theme), - contact_list: contact_list(theme), - toolbar_dropdown_menu: toolbar_dropdown_menu(theme), - search: search(theme), - shared_screen: shared_screen(theme), - update_notification: update_notification(theme), - simple_message_notification: simple_message_notification(theme), - tooltip: tooltip(theme), - terminal: terminal(theme), - assistant: assistant(theme), - feedback: feedback(theme), + command_palette: command_palette(), + contact_notification: contact_notification(), + project_shared_notification: project_shared_notification(), + incoming_call_notification: incoming_call_notification(), + picker: picker(), + workspace: workspace(), + titlebar: titlebar(), + copilot: copilot(), + welcome: welcome(), + context_menu: context_menu(), + editor: editor(), + project_diagnostics: project_diagnostics(), + project_panel: project_panel(), + contacts_popover: contacts_popover(), + contact_finder: contact_finder(), + contact_list: contact_list(), + toolbar_dropdown_menu: toolbar_dropdown_menu(), + search: search(), + shared_screen: shared_screen(), + update_notification: update_notification(), + simple_message_notification: simple_message_notification(), + tooltip: tooltip(), + terminal: terminal(), + assistant: assistant(), + feedback: feedback(), color_scheme: { ...theme, players: Object.values(theme.players), diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index bdde221aca..6df02a0e33 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { text, border, background, foreground } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function assistant(): any { + const theme = useTheme() -export default function assistant(theme: ColorScheme): any { return { container: { background: background(theme.highest), diff --git a/styles/src/style_tree/command_palette.ts b/styles/src/style_tree/command_palette.ts index 289deef54b..2f7404c8d4 100644 --- a/styles/src/style_tree/command_palette.ts +++ b/styles/src/style_tree/command_palette.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { text, background } from "./components" import { toggleable } from "../element" +import { useTheme } from "../theme" + +export default function command_palette(): any { + const theme = useTheme() -export default function command_palette(theme: ColorScheme): any { const key = toggleable({ base: { text: text(theme.highest, "mono", "variant", "default", { diff --git a/styles/src/style_tree/contact_finder.ts b/styles/src/style_tree/contact_finder.ts index e61d100264..2d57e16dfd 100644 --- a/styles/src/style_tree/contact_finder.ts +++ b/styles/src/style_tree/contact_finder.ts @@ -1,8 +1,10 @@ import picker from "./picker" -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, text } from "./components" +import { useTheme } from "../theme" + +export default function contact_finder(): any { + const theme = useTheme() -export default function contact_finder(theme: ColorScheme): any { const side_margin = 6 const contact_button = { background: background(theme.middle, "variant"), @@ -12,7 +14,7 @@ export default function contact_finder(theme: ColorScheme): any { corner_radius: 8, } - const picker_style = picker(theme) + const picker_style = picker() const picker_input = { background: background(theme.middle, "on"), corner_radius: 6, diff --git a/styles/src/style_tree/contact_list.ts b/styles/src/style_tree/contact_list.ts index 93f88e2d4a..1955231f59 100644 --- a/styles/src/style_tree/contact_list.ts +++ b/styles/src/style_tree/contact_list.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, @@ -7,7 +6,10 @@ import { text, } from "./components" import { interactive, toggleable } from "../element" -export default function contacts_panel(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function contacts_panel(): any { + const theme = useTheme() + const name_margin = 8 const side_padding = 12 diff --git a/styles/src/style_tree/contact_notification.ts b/styles/src/style_tree/contact_notification.ts index 8de5496d91..365e3a646d 100644 --- a/styles/src/style_tree/contact_notification.ts +++ b/styles/src/style_tree/contact_notification.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, foreground, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function contact_notification(): any { + const theme = useTheme() -export default function contact_notification(theme: ColorScheme): any { const avatar_size = 12 const header_padding = 8 diff --git a/styles/src/style_tree/contacts_popover.ts b/styles/src/style_tree/contacts_popover.ts index 4e3f8899e0..0ce63d088a 100644 --- a/styles/src/style_tree/contacts_popover.ts +++ b/styles/src/style_tree/contacts_popover.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border } from "./components" -export default function contacts_popover(theme: ColorScheme): any { +export default function contacts_popover(): any { + const theme = useTheme() + return { background: background(theme.middle), corner_radius: 6, diff --git a/styles/src/style_tree/context_menu.ts b/styles/src/style_tree/context_menu.ts index af45942d2d..d4266a71fe 100644 --- a/styles/src/style_tree/context_menu.ts +++ b/styles/src/style_tree/context_menu.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, border_color, text } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function context_menu(): any { + const theme = useTheme() -export default function context_menu(theme: ColorScheme): any { return { background: background(theme.middle), corner_radius: 10, diff --git a/styles/src/style_tree/copilot.ts b/styles/src/style_tree/copilot.ts index eee6880e0c..f002db5ef5 100644 --- a/styles/src/style_tree/copilot.ts +++ b/styles/src/style_tree/copilot.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, svg, text } from "./components" import { interactive } from "../element" -export default function copilot(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function copilot(): any { + const theme = useTheme() + const content_width = 264 const cta_button = diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index af58276d16..31fa86110d 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -1,5 +1,5 @@ import { with_opacity } from "../theme/color" -import { ColorScheme, Layer, StyleSets } from "../theme/color_scheme" +import { Layer, StyleSets } from "../theme/color_scheme" import { background, border, @@ -11,8 +11,11 @@ import hover_popover from "./hover_popover" import { build_syntax } from "../theme/syntax" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function editor(): any { + const theme = useTheme() -export default function editor(theme: ColorScheme): any { const { is_light } = theme const layer = theme.highest @@ -248,7 +251,7 @@ export default function editor(theme: ColorScheme): any { invalid_hint_diagnostic: diagnostic(theme.middle, "base"), invalid_information_diagnostic: diagnostic(theme.middle, "base"), invalid_warning_diagnostic: diagnostic(theme.middle, "base"), - hover_popover: hover_popover(theme), + hover_popover: hover_popover(), link_definition: { color: syntax.link_uri.color, underline: syntax.link_uri.underline, diff --git a/styles/src/style_tree/feedback.ts b/styles/src/style_tree/feedback.ts index 9217b60929..2bb63e951b 100644 --- a/styles/src/style_tree/feedback.ts +++ b/styles/src/style_tree/feedback.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function feedback(): any { + const theme = useTheme() -export default function feedback(theme: ColorScheme): any { return { submit_button: interactive({ base: { diff --git a/styles/src/style_tree/hover_popover.ts b/styles/src/style_tree/hover_popover.ts index f469505741..80f2250349 100644 --- a/styles/src/style_tree/hover_popover.ts +++ b/styles/src/style_tree/hover_popover.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, foreground, text } from "./components" -export default function hover_popover(theme: ColorScheme): any { +export default function hover_popover(): any { + const theme = useTheme() + const base_container = { background: background(theme.middle), corner_radius: 8, diff --git a/styles/src/style_tree/incoming_call_notification.ts b/styles/src/style_tree/incoming_call_notification.ts index ca46596e57..294ec00a73 100644 --- a/styles/src/style_tree/incoming_call_notification.ts +++ b/styles/src/style_tree/incoming_call_notification.ts @@ -1,9 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, text } from "./components" -export default function incoming_call_notification( - theme: ColorScheme -): unknown { +export default function incoming_call_notification(): unknown { + const theme = useTheme() + const avatar_size = 48 return { window_height: 74, diff --git a/styles/src/style_tree/picker.ts b/styles/src/style_tree/picker.ts index 7ca76cd85f..d57021efb8 100644 --- a/styles/src/style_tree/picker.ts +++ b/styles/src/style_tree/picker.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { background, border, text } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function picker(): any { + const theme = useTheme() -export default function picker(theme: ColorScheme): any { const container = { background: background(theme.lowest), border: border(theme.lowest), diff --git a/styles/src/style_tree/project_diagnostics.ts b/styles/src/style_tree/project_diagnostics.ts index 5962b98a26..1c13b31a4a 100644 --- a/styles/src/style_tree/project_diagnostics.ts +++ b/styles/src/style_tree/project_diagnostics.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, text } from "./components" -export default function project_diagnostics(theme: ColorScheme): any { +export default function project_diagnostics(): any { + const theme = useTheme() + return { background: background(theme.highest), tab_icon_spacing: 4, diff --git a/styles/src/style_tree/project_panel.ts b/styles/src/style_tree/project_panel.ts index d1024778f1..af997d0a6e 100644 --- a/styles/src/style_tree/project_panel.ts +++ b/styles/src/style_tree/project_panel.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { Border, @@ -10,7 +9,10 @@ import { } from "./components" import { interactive, toggleable } from "../element" import merge from "ts-deepmerge" -export default function project_panel(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function project_panel(): any { + const theme = useTheme() + const { is_light } = theme type EntryStateProps = { @@ -65,13 +67,12 @@ export default function project_panel(theme: ColorScheme): any { const unselected_hovered_style = merge( base_properties, { background: background(theme.middle, "hovered") }, - unselected?.hovered ?? {}, + unselected?.hovered ?? {} ) const unselected_clicked_style = merge( base_properties, - { background: background(theme.middle, "pressed"), } - , - unselected?.clicked ?? {}, + { background: background(theme.middle, "pressed") }, + unselected?.clicked ?? {} ) const selected_default_style = merge( base_properties, @@ -79,18 +80,15 @@ export default function project_panel(theme: ColorScheme): any { background: background(theme.lowest), text: text(theme.lowest, "sans", { size: "sm" }), }, - selected_style?.default ?? {}, - + selected_style?.default ?? {} ) const selected_hovered_style = merge( base_properties, { background: background(theme.lowest, "hovered"), text: text(theme.lowest, "sans", { size: "sm" }), - }, - selected_style?.hovered ?? {}, - + selected_style?.hovered ?? {} ) const selected_clicked_style = merge( base_properties, @@ -98,8 +96,7 @@ export default function project_panel(theme: ColorScheme): any { background: background(theme.lowest, "pressed"), text: text(theme.lowest, "sans", { size: "sm" }), }, - selected_style?.clicked ?? {}, - + selected_style?.clicked ?? {} ) return toggleable({ diff --git a/styles/src/style_tree/project_shared_notification.ts b/styles/src/style_tree/project_shared_notification.ts index ffda0f4b70..e7c1dcedd5 100644 --- a/styles/src/style_tree/project_shared_notification.ts +++ b/styles/src/style_tree/project_shared_notification.ts @@ -1,9 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, text } from "./components" -export default function project_shared_notification( - theme: ColorScheme -): unknown { +export default function project_shared_notification(): unknown { + const theme = useTheme() + const avatar_size = 48 return { window_height: 74, diff --git a/styles/src/style_tree/search.ts b/styles/src/style_tree/search.ts index df260f95b7..5c16d03233 100644 --- a/styles/src/style_tree/search.ts +++ b/styles/src/style_tree/search.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { background, border, foreground, text } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function search(): any { + const theme = useTheme() -export default function search(theme: ColorScheme): any { // Search input const editor = { background: background(theme.highest), diff --git a/styles/src/style_tree/shared_screen.ts b/styles/src/style_tree/shared_screen.ts index b57c483f1c..aca7fd7f07 100644 --- a/styles/src/style_tree/shared_screen.ts +++ b/styles/src/style_tree/shared_screen.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background } from "./components" -export default function sharedScreen(theme: ColorScheme) { +export default function sharedScreen() { + const theme = useTheme() + return { background: background(theme.highest), } diff --git a/styles/src/style_tree/simple_message_notification.ts b/styles/src/style_tree/simple_message_notification.ts index 0b5c1e0c29..35133f04a2 100644 --- a/styles/src/style_tree/simple_message_notification.ts +++ b/styles/src/style_tree/simple_message_notification.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function simple_message_notification(): any { + const theme = useTheme() -export default function simple_message_notification(theme: ColorScheme): any { const header_padding = 8 return { diff --git a/styles/src/style_tree/status_bar.ts b/styles/src/style_tree/status_bar.ts index bde40d570c..9aeea866f3 100644 --- a/styles/src/style_tree/status_bar.ts +++ b/styles/src/style_tree/status_bar.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, text } from "./components" import { interactive, toggleable } from "../element" -export default function status_bar(theme: ColorScheme): any { +import { useTheme } from "../common" +export default function status_bar(): any { + const theme = useTheme() + const layer = theme.lowest const status_container = { diff --git a/styles/src/style_tree/tab_bar.ts b/styles/src/style_tree/tab_bar.ts index 55fd2c314a..29769f9bae 100644 --- a/styles/src/style_tree/tab_bar.ts +++ b/styles/src/style_tree/tab_bar.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { text, border, background, foreground } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../common" + +export default function tab_bar(): any { + const theme = useTheme() -export default function tab_bar(theme: ColorScheme): any { const height = 32 const active_layer = theme.highest diff --git a/styles/src/style_tree/terminal.ts b/styles/src/style_tree/terminal.ts index e902aa4264..5b98eebfcd 100644 --- a/styles/src/style_tree/terminal.ts +++ b/styles/src/style_tree/terminal.ts @@ -1,6 +1,8 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" + +export default function terminal() { + const theme = useTheme() -export default function terminal(theme: ColorScheme) { /** * Colors are controlled per-cell in the terminal grid. * Cells can be set to any of these more 'theme-capable' colors diff --git a/styles/src/style_tree/titlebar.ts b/styles/src/style_tree/titlebar.ts index 067d619bb5..4dbd8f08f9 100644 --- a/styles/src/style_tree/titlebar.ts +++ b/styles/src/style_tree/titlebar.ts @@ -1,7 +1,7 @@ -import { ColorScheme } from "../common" import { icon_button, toggleable_icon_button } from "../component/icon_button" import { toggleable_text_button } from "../component/text_button" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" import { with_opacity } from "../theme/color" import { background, border, foreground, text } from "./components" @@ -22,7 +22,9 @@ function build_spacing( } } -function call_controls(theme: ColorScheme) { +function call_controls() { + const theme = useTheme() + const button_height = 18 const space = build_spacing(TITLEBAR_HEIGHT, button_height, ITEM_SPACING) @@ -69,7 +71,9 @@ function call_controls(theme: ColorScheme) { * When logged in shows the user's avatar and a chevron, * When logged out only shows a chevron. */ -function user_menu(theme: ColorScheme) { +function user_menu() { + const theme = useTheme() + const button_height = 18 const space = build_spacing(TITLEBAR_HEIGHT, button_height, ITEM_SPACING) @@ -155,7 +159,9 @@ function user_menu(theme: ColorScheme) { } } -export function titlebar(theme: ColorScheme): any { +export function titlebar(): any { + const theme = useTheme() + const avatar_width = 15 const avatar_outer_width = avatar_width + 4 const follower_avatar_width = 14 @@ -237,14 +243,14 @@ export function titlebar(theme: ColorScheme): any { corner_radius: 6, }, - leave_call_button: icon_button(theme, { + leave_call_button: icon_button({ margin: { left: ITEM_SPACING / 2, right: ITEM_SPACING, }, }), - ...call_controls(theme), + ...call_controls(), toggle_contacts_button: toggleable_icon_button(theme, { margin: { @@ -261,6 +267,6 @@ export function titlebar(theme: ColorScheme): any { background: foreground(theme.lowest, "accent"), }, share_button: toggleable_text_button(theme, {}), - user_menu: user_menu(theme), + user_menu: user_menu(), } } diff --git a/styles/src/style_tree/toolbar_dropdown_menu.ts b/styles/src/style_tree/toolbar_dropdown_menu.ts index dc22ac73cf..97f29ab18c 100644 --- a/styles/src/style_tree/toolbar_dropdown_menu.ts +++ b/styles/src/style_tree/toolbar_dropdown_menu.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, text } from "./components" import { interactive, toggleable } from "../element" -export default function dropdown_menu(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function dropdown_menu(): any { + const theme = useTheme() + return { row_height: 30, background: background(theme.middle), diff --git a/styles/src/style_tree/tooltip.ts b/styles/src/style_tree/tooltip.ts index 2fa5db04d4..54a2d7b78d 100644 --- a/styles/src/style_tree/tooltip.ts +++ b/styles/src/style_tree/tooltip.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, text } from "./components" -export default function tooltip(theme: ColorScheme): any { +export default function tooltip(): any { + const theme = useTheme() + return { background: background(theme.middle), border: border(theme.middle), diff --git a/styles/src/style_tree/update_notification.ts b/styles/src/style_tree/update_notification.ts index d14e840450..2d0c36d74c 100644 --- a/styles/src/style_tree/update_notification.ts +++ b/styles/src/style_tree/update_notification.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { foreground, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function update_notification(): any { + const theme = useTheme() -export default function update_notification(theme: ColorScheme): any { const header_padding = 8 return { diff --git a/styles/src/style_tree/welcome.ts b/styles/src/style_tree/welcome.ts index fad8dfe235..8ff15d5d26 100644 --- a/styles/src/style_tree/welcome.ts +++ b/styles/src/style_tree/welcome.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { border, @@ -9,8 +8,11 @@ import { svg, } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function welcome(): any { + const theme = useTheme() -export default function welcome(theme: ColorScheme): any { const checkbox_base = { corner_radius: 4, padding: { diff --git a/styles/src/style_tree/workspace.ts b/styles/src/style_tree/workspace.ts index 0326de414a..5aee3c987d 100644 --- a/styles/src/style_tree/workspace.ts +++ b/styles/src/style_tree/workspace.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { background, @@ -11,9 +10,12 @@ import { import statusBar from "./status_bar" import tabBar from "./tab_bar" import { interactive } from "../element" - import { titlebar } from "./titlebar" -export default function workspace(theme: ColorScheme): any { +import { useTheme } from "../theme" + +export default function workspace(): any { + const theme = useTheme() + const { is_light } = theme return { @@ -85,7 +87,7 @@ export default function workspace(theme: ColorScheme): any { }, leader_border_opacity: 0.7, leader_border_width: 2.0, - tab_bar: tabBar(theme), + tab_bar: tabBar(), modal: { margin: { bottom: 52, @@ -123,8 +125,8 @@ export default function workspace(theme: ColorScheme): any { color: border_color(theme.lowest), width: 1, }, - status_bar: statusBar(theme), - titlebar: titlebar(theme), + status_bar: statusBar(), + titlebar: titlebar(), toolbar: { height: 34, background: background(theme.highest), diff --git a/styles/src/theme/index.ts b/styles/src/theme/index.ts index 22287bf669..100248b1a8 100644 --- a/styles/src/theme/index.ts +++ b/styles/src/theme/index.ts @@ -1,3 +1,24 @@ +import { create } from "zustand" +import { ColorScheme } from "./color_scheme" + +type ThemeState = { + theme: ColorScheme | undefined + setTheme: (theme: ColorScheme) => void +} + +export const useThemeStore = create((set) => ({ + theme: undefined, + setTheme: (theme) => set(() => ({ theme })), +})) + +export const useTheme = (): ColorScheme => { + const { theme } = useThemeStore.getState() + + if (!theme) throw new Error("Tried to use theme before it was loaded") + + return theme +} + export * from "./color_scheme" export * from "./ramps" export * from "./syntax" From 8a5e7047f0e59178e11eadd96a4a7b3ef417fbf7 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 00:32:27 -0400 Subject: [PATCH 055/104] Update a few more components --- styles/src/build_tokens.ts | 2 +- styles/src/theme/tokens/color_scheme.ts | 23 ++++++++++++-------- styles/src/theme/tokens/players.ts | 28 ++++++++++++++----------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/styles/src/build_tokens.ts b/styles/src/build_tokens.ts index e33c3712e6..f51e5eb6cf 100644 --- a/styles/src/build_tokens.ts +++ b/styles/src/build_tokens.ts @@ -60,7 +60,7 @@ function write_tokens(themes: ColorScheme[], tokens_directory: string) { for (const theme of themes) { const file_name = slugify(theme.name) + ".json" - const tokens = theme_tokens(theme) + const tokens = theme_tokens() const tokens_json = JSON.stringify(tokens, null, 2) const out_path = path.join(tokens_directory, file_name) fs.writeFileSync(out_path, tokens_json, { mode: 0o644 }) diff --git a/styles/src/theme/tokens/color_scheme.ts b/styles/src/theme/tokens/color_scheme.ts index a8ce4ec2d2..efbeaaa901 100644 --- a/styles/src/theme/tokens/color_scheme.ts +++ b/styles/src/theme/tokens/color_scheme.ts @@ -15,6 +15,7 @@ import { PlayersToken, players_token } from "./players" import { color_token } from "./token" import { Syntax } from "../syntax" import editor from "../../style_tree/editor" +import { useTheme } from "@/src/common" interface ColorSchemeTokens { name: SingleOtherToken @@ -39,12 +40,14 @@ const create_shadow_token = ( } } -const popover_shadow_token = (theme: ColorScheme): SingleBoxShadowToken => { +const popover_shadow_token = (): SingleBoxShadowToken => { + const theme = useTheme() const shadow = theme.popover_shadow return create_shadow_token(shadow, "popover_shadow") } -const modal_shadow_token = (theme: ColorScheme): SingleBoxShadowToken => { +const modal_shadow_token = (): SingleBoxShadowToken => { + const theme = useTheme() const shadow = theme.modal_shadow return create_shadow_token(shadow, "modal_shadow") } @@ -68,13 +71,15 @@ function syntax_highlight_style_color_tokens( }, {} as ThemeSyntaxColorTokens) } -const syntax_tokens = (theme: ColorScheme): ColorSchemeTokens["syntax"] => { - const syntax = editor(theme).syntax +const syntax_tokens = (): ColorSchemeTokens["syntax"] => { + const syntax = editor().syntax return syntax_highlight_style_color_tokens(syntax) } -export function theme_tokens(theme: ColorScheme): ColorSchemeTokens { +export function theme_tokens(): ColorSchemeTokens { + const theme = useTheme() + return { name: { name: "themeName", @@ -89,9 +94,9 @@ export function theme_tokens(theme: ColorScheme): ColorSchemeTokens { lowest: layer_token(theme.lowest, "lowest"), middle: layer_token(theme.middle, "middle"), highest: layer_token(theme.highest, "highest"), - popover_shadow: popover_shadow_token(theme), - modal_shadow: modal_shadow_token(theme), - players: players_token(theme), - syntax: syntax_tokens(theme), + popover_shadow: popover_shadow_token(), + modal_shadow: modal_shadow_token(), + players: players_token(), + syntax: syntax_tokens(), } } diff --git a/styles/src/theme/tokens/players.ts b/styles/src/theme/tokens/players.ts index 545a712ff1..85573a1a8f 100644 --- a/styles/src/theme/tokens/players.ts +++ b/styles/src/theme/tokens/players.ts @@ -1,12 +1,14 @@ import { SingleColorToken } from "@tokens-studio/types" import { color_token } from "./token" -import { ColorScheme, Players } from "../color_scheme" +import { Players } from "../color_scheme" +import { useTheme } from "@/src/common" export type PlayerToken = Record<"selection" | "cursor", SingleColorToken> export type PlayersToken = Record -function build_player_token(theme: ColorScheme, index: number): PlayerToken { +function build_player_token(index: number): PlayerToken { + const theme = useTheme() const player_number = index.toString() as keyof Players return { @@ -21,13 +23,15 @@ function build_player_token(theme: ColorScheme, index: number): PlayerToken { } } -export const players_token = (theme: ColorScheme): PlayersToken => ({ - "0": build_player_token(theme, 0), - "1": build_player_token(theme, 1), - "2": build_player_token(theme, 2), - "3": build_player_token(theme, 3), - "4": build_player_token(theme, 4), - "5": build_player_token(theme, 5), - "6": build_player_token(theme, 6), - "7": build_player_token(theme, 7), -}) +export const players_token = (): PlayersToken => { + return { + "0": build_player_token(0), + "1": build_player_token(1), + "2": build_player_token(2), + "3": build_player_token(3), + "4": build_player_token(4), + "5": build_player_token(5), + "6": build_player_token(6), + "7": build_player_token(7), + } +} From 5a1476a1e58c43e64d051e5af9786d8edaa85088 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 00:40:01 -0400 Subject: [PATCH 056/104] Remove unused `color_scheme` field in the theme --- crates/theme/src/theme.rs | 1 - styles/src/style_tree/app.ts | 17 +---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index e54dcdfd1e..20f0787826 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -65,7 +65,6 @@ pub struct Theme { pub assistant: AssistantStyle, pub feedback: FeedbackStyle, pub welcome: WelcomeStyle, - pub color_scheme: ColorScheme, pub titlebar: Titlebar, } diff --git a/styles/src/style_tree/app.ts b/styles/src/style_tree/app.ts index e4bf232b62..ccfdd60a98 100644 --- a/styles/src/style_tree/app.ts +++ b/styles/src/style_tree/app.ts @@ -57,21 +57,6 @@ export default function app(): any { tooltip: tooltip(), terminal: terminal(), assistant: assistant(), - feedback: feedback(), - color_scheme: { - ...theme, - players: Object.values(theme.players), - ramps: { - neutral: theme.ramps.neutral.colors(100, "hex"), - red: theme.ramps.red.colors(100, "hex"), - orange: theme.ramps.orange.colors(100, "hex"), - yellow: theme.ramps.yellow.colors(100, "hex"), - green: theme.ramps.green.colors(100, "hex"), - cyan: theme.ramps.cyan.colors(100, "hex"), - blue: theme.ramps.blue.colors(100, "hex"), - violet: theme.ramps.violet.colors(100, "hex"), - magenta: theme.ramps.magenta.colors(100, "hex"), - }, - }, + feedback: feedback() } } From c409059dc45e0a677bd61239c35405df6f26bbd1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 00:41:13 -0400 Subject: [PATCH 057/104] Revert "Remove unused `color_scheme` field in the theme" This reverts commit 5a1476a1e58c43e64d051e5af9786d8edaa85088. --- crates/theme/src/theme.rs | 1 + styles/src/style_tree/app.ts | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 20f0787826..e54dcdfd1e 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -65,6 +65,7 @@ pub struct Theme { pub assistant: AssistantStyle, pub feedback: FeedbackStyle, pub welcome: WelcomeStyle, + pub color_scheme: ColorScheme, pub titlebar: Titlebar, } diff --git a/styles/src/style_tree/app.ts b/styles/src/style_tree/app.ts index ccfdd60a98..e4bf232b62 100644 --- a/styles/src/style_tree/app.ts +++ b/styles/src/style_tree/app.ts @@ -57,6 +57,21 @@ export default function app(): any { tooltip: tooltip(), terminal: terminal(), assistant: assistant(), - feedback: feedback() + feedback: feedback(), + color_scheme: { + ...theme, + players: Object.values(theme.players), + ramps: { + neutral: theme.ramps.neutral.colors(100, "hex"), + red: theme.ramps.red.colors(100, "hex"), + orange: theme.ramps.orange.colors(100, "hex"), + yellow: theme.ramps.yellow.colors(100, "hex"), + green: theme.ramps.green.colors(100, "hex"), + cyan: theme.ramps.cyan.colors(100, "hex"), + blue: theme.ramps.blue.colors(100, "hex"), + violet: theme.ramps.violet.colors(100, "hex"), + magenta: theme.ramps.magenta.colors(100, "hex"), + }, + }, } } From a732b2e04347be269fc096ff5314035e4e492c8c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 00:44:12 -0400 Subject: [PATCH 058/104] Remove unused `color_scheme` field in the theme I totally didn't mean to commit this right to main T_T --- crates/theme/src/theme.rs | 1 - styles/src/style_tree/app.ts | 17 +---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index e54dcdfd1e..20f0787826 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -65,7 +65,6 @@ pub struct Theme { pub assistant: AssistantStyle, pub feedback: FeedbackStyle, pub welcome: WelcomeStyle, - pub color_scheme: ColorScheme, pub titlebar: Titlebar, } diff --git a/styles/src/style_tree/app.ts b/styles/src/style_tree/app.ts index e4bf232b62..ccfdd60a98 100644 --- a/styles/src/style_tree/app.ts +++ b/styles/src/style_tree/app.ts @@ -57,21 +57,6 @@ export default function app(): any { tooltip: tooltip(), terminal: terminal(), assistant: assistant(), - feedback: feedback(), - color_scheme: { - ...theme, - players: Object.values(theme.players), - ramps: { - neutral: theme.ramps.neutral.colors(100, "hex"), - red: theme.ramps.red.colors(100, "hex"), - orange: theme.ramps.orange.colors(100, "hex"), - yellow: theme.ramps.yellow.colors(100, "hex"), - green: theme.ramps.green.colors(100, "hex"), - cyan: theme.ramps.cyan.colors(100, "hex"), - blue: theme.ramps.blue.colors(100, "hex"), - violet: theme.ramps.violet.colors(100, "hex"), - magenta: theme.ramps.magenta.colors(100, "hex"), - }, - }, + feedback: feedback() } } From 65dbb3892672447af726b5875dc1e529a8b9ccc1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 01:20:56 -0400 Subject: [PATCH 059/104] `color_scheme` -> `theme` --- docs/zed/syntax-highlighting.md | 2 +- styles/src/build_themes.ts | 16 ++-- styles/src/build_tokens.ts | 17 ++-- styles/src/component/icon_button.ts | 14 +-- styles/src/component/text_button.ts | 14 +-- styles/src/style_tree/components.ts | 2 +- styles/src/style_tree/editor.ts | 4 +- .../{color_scheme.ts => create_theme.ts} | 4 +- styles/src/theme/index.ts | 10 +-- styles/src/theme/ramps.ts | 2 +- styles/src/theme/syntax.ts | 86 +++++++++---------- styles/src/theme/theme_config.ts | 67 --------------- styles/src/theme/tokens/layer.ts | 2 +- styles/src/theme/tokens/players.ts | 4 +- .../tokens/{color_scheme.ts => theme.ts} | 11 ++- 15 files changed, 93 insertions(+), 162 deletions(-) rename styles/src/theme/{color_scheme.ts => create_theme.ts} (98%) rename styles/src/theme/tokens/{color_scheme.ts => theme.ts} (93%) diff --git a/docs/zed/syntax-highlighting.md b/docs/zed/syntax-highlighting.md index 3878fcc6e9..d4331ee367 100644 --- a/docs/zed/syntax-highlighting.md +++ b/docs/zed/syntax-highlighting.md @@ -35,7 +35,7 @@ Match a property identifier and highlight it using the identifier `@property`. I ``` ```ts -function buildDefaultSyntax(colorScheme: ColorScheme): Partial { +function buildDefaultSyntax(colorScheme: Theme): Partial { // ... } ``` diff --git a/styles/src/build_themes.ts b/styles/src/build_themes.ts index a9cbad94e7..17575663a1 100644 --- a/styles/src/build_themes.ts +++ b/styles/src/build_themes.ts @@ -2,7 +2,7 @@ import * as fs from "fs" import { tmpdir } from "os" import * as path from "path" import app from "./style_tree/app" -import { ColorScheme, create_color_scheme } from "./theme/color_scheme" +import { Theme, create_theme } from "./theme/create_theme" import { themes } from "./themes" import { useThemeStore } from "./theme" @@ -21,22 +21,22 @@ function clear_themes(theme_directory: string) { } } -const all_themes: ColorScheme[] = themes.map((theme) => - create_color_scheme(theme) +const all_themes: Theme[] = themes.map((theme) => + create_theme(theme) ) -function write_themes(themes: ColorScheme[], output_directory: string) { +function write_themes(themes: Theme[], output_directory: string) { clear_themes(output_directory) - for (const color_scheme of themes) { + for (const theme of themes) { const { setTheme } = useThemeStore.getState() - setTheme(color_scheme) + setTheme(theme) const style_tree = app() const style_tree_json = JSON.stringify(style_tree, null, 2) - const temp_path = path.join(temp_directory, `${color_scheme.name}.json`) + const temp_path = path.join(temp_directory, `${theme.name}.json`) const out_path = path.join( output_directory, - `${color_scheme.name}.json` + `${theme.name}.json` ) fs.writeFileSync(temp_path, style_tree_json) fs.renameSync(temp_path, out_path) diff --git a/styles/src/build_tokens.ts b/styles/src/build_tokens.ts index f51e5eb6cf..fd6aa18ced 100644 --- a/styles/src/build_tokens.ts +++ b/styles/src/build_tokens.ts @@ -1,9 +1,9 @@ import * as fs from "fs" import * as path from "path" -import { ColorScheme, create_color_scheme } from "./common" +import { Theme, create_theme, useThemeStore } from "./common" import { themes } from "./themes" import { slugify } from "./utils/slugify" -import { theme_tokens } from "./theme/tokens/color_scheme" +import { theme_tokens } from "./theme/tokens/theme" const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens") const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json") @@ -27,7 +27,7 @@ type TokenSet = { selected_token_sets: { [key: string]: "enabled" } } -function build_token_set_order(theme: ColorScheme[]): { +function build_token_set_order(theme: Theme[]): { token_set_order: string[] } { const token_set_order: string[] = theme.map((scheme) => @@ -36,7 +36,7 @@ function build_token_set_order(theme: ColorScheme[]): { return { token_set_order } } -function build_themes_index(theme: ColorScheme[]): TokenSet[] { +function build_themes_index(theme: Theme[]): TokenSet[] { const themes_index: TokenSet[] = theme.map((scheme, index) => { const id = `${scheme.is_light ? "light" : "dark"}_${scheme.name .toLowerCase() @@ -55,10 +55,13 @@ function build_themes_index(theme: ColorScheme[]): TokenSet[] { return themes_index } -function write_tokens(themes: ColorScheme[], tokens_directory: string) { +function write_tokens(themes: Theme[], tokens_directory: string) { clear_tokens(tokens_directory) for (const theme of themes) { + const { setTheme } = useThemeStore.getState() + setTheme(theme) + const file_name = slugify(theme.name) + ".json" const tokens = theme_tokens() const tokens_json = JSON.stringify(tokens, null, 2) @@ -80,8 +83,8 @@ function write_tokens(themes: ColorScheme[], tokens_directory: string) { console.log(`- ${METADATA_FILE} created`) } -const all_themes: ColorScheme[] = themes.map((theme) => - create_color_scheme(theme) +const all_themes: Theme[] = themes.map((theme) => + create_theme(theme) ) write_tokens(all_themes, TOKENS_DIRECTORY) diff --git a/styles/src/component/icon_button.ts b/styles/src/component/icon_button.ts index 18b900e833..6887fc7c30 100644 --- a/styles/src/component/icon_button.ts +++ b/styles/src/component/icon_button.ts @@ -1,6 +1,6 @@ import { interactive, toggleable } from "../element" import { background, foreground } from "../style_tree/components" -import { useTheme, ColorScheme } from "../theme" +import { useTheme, Theme } from "../theme" export type Margin = { top: number @@ -11,15 +11,15 @@ export type Margin = { interface IconButtonOptions { layer?: - | ColorScheme["lowest"] - | ColorScheme["middle"] - | ColorScheme["highest"] - color?: keyof ColorScheme["lowest"] + | Theme["lowest"] + | Theme["middle"] + | Theme["highest"] + color?: keyof Theme["lowest"] margin?: Partial } type ToggleableIconButtonOptions = IconButtonOptions & { - active_color?: keyof ColorScheme["lowest"] + active_color?: keyof Theme["lowest"] } export function icon_button({ color, margin, layer }: IconButtonOptions) { @@ -67,7 +67,7 @@ export function icon_button({ color, margin, layer }: IconButtonOptions) { } export function toggleable_icon_button( - theme: ColorScheme, + theme: Theme, { color, active_color, margin }: ToggleableIconButtonOptions ) { if (!color) color = "base" diff --git a/styles/src/component/text_button.ts b/styles/src/component/text_button.ts index 50737f9766..58b2a1cbf2 100644 --- a/styles/src/component/text_button.ts +++ b/styles/src/component/text_button.ts @@ -5,21 +5,21 @@ import { foreground, text, } from "../style_tree/components" -import { useTheme, ColorScheme } from "../theme" +import { useTheme, Theme } from "../theme" import { Margin } from "./icon_button" interface TextButtonOptions { layer?: - | ColorScheme["lowest"] - | ColorScheme["middle"] - | ColorScheme["highest"] - color?: keyof ColorScheme["lowest"] + | Theme["lowest"] + | Theme["middle"] + | Theme["highest"] + color?: keyof Theme["lowest"] margin?: Partial text_properties?: TextProperties } type ToggleableTextButtonOptions = TextButtonOptions & { - active_color?: keyof ColorScheme["lowest"] + active_color?: keyof Theme["lowest"] } export function text_button({ @@ -75,7 +75,7 @@ export function text_button({ } export function toggleable_text_button( - theme: ColorScheme, + theme: Theme, { color, active_color, margin }: ToggleableTextButtonOptions ) { if (!color) color = "base" diff --git a/styles/src/style_tree/components.ts b/styles/src/style_tree/components.ts index db32712f41..43a5fa9d28 100644 --- a/styles/src/style_tree/components.ts +++ b/styles/src/style_tree/components.ts @@ -1,5 +1,5 @@ import { font_families, font_sizes, FontWeight } from "../common" -import { Layer, Styles, StyleSets, Style } from "../theme/color_scheme" +import { Layer, Styles, StyleSets, Style } from "../theme/create_theme" function is_style_set(key: any): key is StyleSets { return [ diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index 31fa86110d..a2fec11642 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -1,5 +1,5 @@ import { with_opacity } from "../theme/color" -import { Layer, StyleSets } from "../theme/color_scheme" +import { Layer, StyleSets } from "../theme/create_theme" import { background, border, @@ -48,7 +48,7 @@ export default function editor(): any { } } - const syntax = build_syntax(theme) + const syntax = build_syntax() return { text_color: syntax.primary.color, diff --git a/styles/src/theme/color_scheme.ts b/styles/src/theme/create_theme.ts similarity index 98% rename from styles/src/theme/color_scheme.ts rename to styles/src/theme/create_theme.ts index 933c616053..dff4c3dbc4 100644 --- a/styles/src/theme/color_scheme.ts +++ b/styles/src/theme/create_theme.ts @@ -8,7 +8,7 @@ import { } from "./theme_config" import { get_ramps } from "./ramps" -export interface ColorScheme { +export interface Theme { name: string is_light: boolean @@ -105,7 +105,7 @@ export interface Style { foreground: string } -export function create_color_scheme(theme: ThemeConfig): ColorScheme { +export function create_theme(theme: ThemeConfig): Theme { const { name, appearance, diff --git a/styles/src/theme/index.ts b/styles/src/theme/index.ts index 100248b1a8..ca8aaa461f 100644 --- a/styles/src/theme/index.ts +++ b/styles/src/theme/index.ts @@ -1,9 +1,9 @@ import { create } from "zustand" -import { ColorScheme } from "./color_scheme" +import { Theme } from "./create_theme" type ThemeState = { - theme: ColorScheme | undefined - setTheme: (theme: ColorScheme) => void + theme: Theme | undefined + setTheme: (theme: Theme) => void } export const useThemeStore = create((set) => ({ @@ -11,7 +11,7 @@ export const useThemeStore = create((set) => ({ setTheme: (theme) => set(() => ({ theme })), })) -export const useTheme = (): ColorScheme => { +export const useTheme = (): Theme => { const { theme } = useThemeStore.getState() if (!theme) throw new Error("Tried to use theme before it was loaded") @@ -19,7 +19,7 @@ export const useTheme = (): ColorScheme => { return theme } -export * from "./color_scheme" +export * from "./create_theme" export * from "./ramps" export * from "./syntax" export * from "./theme_config" diff --git a/styles/src/theme/ramps.ts b/styles/src/theme/ramps.ts index 118d0c7274..c5b915a8c5 100644 --- a/styles/src/theme/ramps.ts +++ b/styles/src/theme/ramps.ts @@ -1,5 +1,5 @@ import chroma, { Color, Scale } from "chroma-js" -import { RampSet } from "./color_scheme" +import { RampSet } from "./create_theme" import { ThemeConfigInputColors, ThemeConfigInputColorsKeys, diff --git a/styles/src/theme/syntax.ts b/styles/src/theme/syntax.ts index c0d68e418e..540a1d0ff9 100644 --- a/styles/src/theme/syntax.ts +++ b/styles/src/theme/syntax.ts @@ -1,6 +1,5 @@ import deepmerge from "deepmerge" -import { FontWeight, font_weights } from "../common" -import { ColorScheme } from "./color_scheme" +import { FontWeight, font_weights, useTheme } from "../common" import chroma from "chroma-js" export interface SyntaxHighlightStyle { @@ -123,7 +122,9 @@ const default_syntax_highlight_style: Omit = { italic: false, } -function build_default_syntax(color_scheme: ColorScheme): Syntax { +function build_default_syntax(): Syntax { + const theme = useTheme() + // Make a temporary object that is allowed to be missing // the "color" property for each style const syntax: { @@ -141,8 +142,8 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { // predictive color distinct from any other color in the theme const predictive = chroma .mix( - color_scheme.ramps.neutral(0.4).hex(), - color_scheme.ramps.blue(0.4).hex(), + theme.ramps.neutral(0.4).hex(), + theme.ramps.blue(0.4).hex(), 0.45, "lch" ) @@ -151,32 +152,32 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { // hint color distinct from any other color in the theme const hint = chroma .mix( - color_scheme.ramps.neutral(0.6).hex(), - color_scheme.ramps.blue(0.4).hex(), + theme.ramps.neutral(0.6).hex(), + theme.ramps.blue(0.4).hex(), 0.45, "lch" ) .hex() const color = { - primary: color_scheme.ramps.neutral(1).hex(), - comment: color_scheme.ramps.neutral(0.71).hex(), - punctuation: color_scheme.ramps.neutral(0.86).hex(), + primary: theme.ramps.neutral(1).hex(), + comment: theme.ramps.neutral(0.71).hex(), + punctuation: theme.ramps.neutral(0.86).hex(), predictive: predictive, hint: hint, - emphasis: color_scheme.ramps.blue(0.5).hex(), - string: color_scheme.ramps.orange(0.5).hex(), - function: color_scheme.ramps.yellow(0.5).hex(), - type: color_scheme.ramps.cyan(0.5).hex(), - constructor: color_scheme.ramps.blue(0.5).hex(), - variant: color_scheme.ramps.blue(0.5).hex(), - property: color_scheme.ramps.blue(0.5).hex(), - enum: color_scheme.ramps.orange(0.5).hex(), - operator: color_scheme.ramps.orange(0.5).hex(), - number: color_scheme.ramps.green(0.5).hex(), - boolean: color_scheme.ramps.green(0.5).hex(), - constant: color_scheme.ramps.green(0.5).hex(), - keyword: color_scheme.ramps.blue(0.5).hex(), + emphasis: theme.ramps.blue(0.5).hex(), + string: theme.ramps.orange(0.5).hex(), + function: theme.ramps.yellow(0.5).hex(), + type: theme.ramps.cyan(0.5).hex(), + constructor: theme.ramps.blue(0.5).hex(), + variant: theme.ramps.blue(0.5).hex(), + property: theme.ramps.blue(0.5).hex(), + enum: theme.ramps.orange(0.5).hex(), + operator: theme.ramps.orange(0.5).hex(), + number: theme.ramps.green(0.5).hex(), + boolean: theme.ramps.green(0.5).hex(), + constant: theme.ramps.green(0.5).hex(), + keyword: theme.ramps.blue(0.5).hex(), } // Then assign colors and use Syntax to enforce each style getting it's own color @@ -211,11 +212,11 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { weight: font_weights.bold, }, link_uri: { - color: color_scheme.ramps.green(0.5).hex(), + color: theme.ramps.green(0.5).hex(), underline: true, }, link_text: { - color: color_scheme.ramps.orange(0.5).hex(), + color: theme.ramps.orange(0.5).hex(), italic: true, }, "text.literal": { @@ -231,7 +232,7 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { color: color.punctuation, }, "punctuation.special": { - color: color_scheme.ramps.neutral(0.86).hex(), + color: theme.ramps.neutral(0.86).hex(), }, "punctuation.list_marker": { color: color.punctuation, @@ -252,10 +253,10 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { color: color.string, }, constructor: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, variant: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, type: { color: color.type, @@ -264,16 +265,16 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { color: color.primary, }, label: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, tag: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, attribute: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, property: { - color: color_scheme.ramps.blue(0.5).hex(), + color: theme.ramps.blue(0.5).hex(), }, constant: { color: color.constant, @@ -307,17 +308,18 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax { return default_syntax } -function merge_syntax( - default_syntax: Syntax, - color_scheme: ColorScheme -): Syntax { - if (!color_scheme.syntax) { +export function build_syntax(): Syntax { + const theme = useTheme() + + const default_syntax: Syntax = build_default_syntax() + + if (!theme.syntax) { return default_syntax } - return deepmerge>( + const syntax = deepmerge>( default_syntax, - color_scheme.syntax, + theme.syntax, { arrayMerge: (destinationArray, sourceArray) => [ ...destinationArray, @@ -325,12 +327,6 @@ function merge_syntax( ], } ) -} - -export function build_syntax(color_scheme: ColorScheme): Syntax { - const default_syntax: Syntax = build_default_syntax(color_scheme) - - const syntax = merge_syntax(default_syntax, color_scheme) return syntax } diff --git a/styles/src/theme/theme_config.ts b/styles/src/theme/theme_config.ts index 26462bee6d..bc8f07425f 100644 --- a/styles/src/theme/theme_config.ts +++ b/styles/src/theme/theme_config.ts @@ -66,35 +66,10 @@ type ThemeConfigProperties = ThemeMeta & { override: ThemeConfigOverrides } -// This should be the format a theme is defined as export type ThemeConfig = { [K in keyof ThemeConfigProperties]: ThemeConfigProperties[K] } -interface ThemeColors { - neutral: string[] - red: string[] - orange: string[] - yellow: string[] - green: string[] - cyan: string[] - blue: string[] - violet: string[] - magenta: string[] -} - -type ThemeSyntax = Required - -export type ThemeProperties = ThemeMeta & { - color: ThemeColors - syntax: ThemeSyntax -} - -// This should be a theme after all its properties have been resolved -export type Theme = { - [K in keyof ThemeProperties]: ThemeProperties[K] -} - export enum ThemeAppearance { Light = "light", Dark = "dark", @@ -104,45 +79,3 @@ export enum ThemeLicenseType { MIT = "MIT", Apache2 = "Apache License 2.0", } - -export type ThemeFamilyItem = - | ThemeConfig - | { light: ThemeConfig; dark: ThemeConfig } - -type ThemeFamilyProperties = Partial> & { - name: string - default: ThemeFamilyItem - variants: { - [key: string]: ThemeFamilyItem - } -} - -// Idea: A theme family is a collection of themes that share the same name -// For example, a theme family could be `One Dark` and have a `light` and `dark` variant -// The Ayu family could have `light`, `mirage`, and `dark` variants - -type ThemeFamily = { - [K in keyof ThemeFamilyProperties]: ThemeFamilyProperties[K] -} - -/** The collection of all themes - * - * Example: - * ```ts - * { - * one_dark, - * one_light, - * ayu: { - * name: 'Ayu', - * default: 'ayu_mirage', - * variants: { - * light: 'ayu_light', - * mirage: 'ayu_mirage', - * dark: 'ayu_dark', - * }, - * }, - * ... - * } - * ``` - */ -export type ThemeIndex = Record diff --git a/styles/src/theme/tokens/layer.ts b/styles/src/theme/tokens/layer.ts index a2e539092e..6b4e1d79f7 100644 --- a/styles/src/theme/tokens/layer.ts +++ b/styles/src/theme/tokens/layer.ts @@ -1,5 +1,5 @@ import { SingleColorToken } from "@tokens-studio/types" -import { Layer, Style, StyleSet } from "../color_scheme" +import { Layer, Style, StyleSet } from "../create_theme" import { color_token } from "./token" interface StyleToken { diff --git a/styles/src/theme/tokens/players.ts b/styles/src/theme/tokens/players.ts index 85573a1a8f..4bf605aa93 100644 --- a/styles/src/theme/tokens/players.ts +++ b/styles/src/theme/tokens/players.ts @@ -1,7 +1,7 @@ import { SingleColorToken } from "@tokens-studio/types" import { color_token } from "./token" -import { Players } from "../color_scheme" -import { useTheme } from "@/src/common" +import { Players } from "../create_theme" +import { useTheme } from "../../../src/common" export type PlayerToken = Record<"selection" | "cursor", SingleColorToken> diff --git a/styles/src/theme/tokens/color_scheme.ts b/styles/src/theme/tokens/theme.ts similarity index 93% rename from styles/src/theme/tokens/color_scheme.ts rename to styles/src/theme/tokens/theme.ts index efbeaaa901..f759bc8139 100644 --- a/styles/src/theme/tokens/color_scheme.ts +++ b/styles/src/theme/tokens/theme.ts @@ -5,19 +5,18 @@ import { TokenTypes, } from "@tokens-studio/types" import { - ColorScheme, Shadow, SyntaxHighlightStyle, ThemeSyntax, -} from "../color_scheme" +} from "../create_theme" import { LayerToken, layer_token } from "./layer" import { PlayersToken, players_token } from "./players" import { color_token } from "./token" import { Syntax } from "../syntax" import editor from "../../style_tree/editor" -import { useTheme } from "@/src/common" +import { useTheme } from "../../../src/common" -interface ColorSchemeTokens { +interface ThemeTokens { name: SingleOtherToken appearance: SingleOtherToken lowest: LayerToken @@ -71,13 +70,13 @@ function syntax_highlight_style_color_tokens( }, {} as ThemeSyntaxColorTokens) } -const syntax_tokens = (): ColorSchemeTokens["syntax"] => { +const syntax_tokens = (): ThemeTokens["syntax"] => { const syntax = editor().syntax return syntax_highlight_style_color_tokens(syntax) } -export function theme_tokens(): ColorSchemeTokens { +export function theme_tokens(): ThemeTokens { const theme = useTheme() return { From f461a709702110fec0b1587187e36210bebf1a55 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 01:37:45 -0400 Subject: [PATCH 060/104] Remove unused ts aliases --- styles/tsconfig.json | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/styles/tsconfig.json b/styles/tsconfig.json index 925935ebb5..281bd74b21 100644 --- a/styles/tsconfig.json +++ b/styles/tsconfig.json @@ -22,17 +22,9 @@ "strictPropertyInitialization": false, "skipLibCheck": true, "useUnknownInCatchVariables": false, - "baseUrl": ".", - "paths": { - "@/*": ["./*"], - "@element/*": ["./src/element/*"], - "@component/*": ["./src/component/*"], - "@styleTree/*": ["./src/styleTree/*"], - "@theme/*": ["./src/theme/*"], - "@types/*": ["./src/util/*"], - "@themes/*": ["./src/themes/*"], - "@util/*": ["./src/util/*"] - } + "baseUrl": "." }, - "exclude": ["node_modules"] + "exclude": [ + "node_modules" + ] } From 0d18b72cf86d74287f4cfc61da5ecaacd82498cb Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 23:52:11 -0600 Subject: [PATCH 061/104] vim: Further improve ~ handling Now works with Visual{line} mode, collapses selections like nvim, and doesn't fall off the end of the line. --- crates/vim/src/normal/case.rs | 96 +++++++++++++++------- crates/vim/src/test/neovim_connection.rs | 16 +++- crates/vim/test_data/test_change_case.json | 18 ++++ 3 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 crates/vim/test_data/test_change_case.json diff --git a/crates/vim/src/normal/case.rs b/crates/vim/src/normal/case.rs index ba527af0bb..b3e101262d 100644 --- a/crates/vim/src/normal/case.rs +++ b/crates/vim/src/normal/case.rs @@ -1,29 +1,51 @@ +use editor::scroll::autoscroll::Autoscroll; use gpui::ViewContext; -use language::Point; +use language::{Bias, Point}; use workspace::Workspace; -use crate::{motion::Motion, normal::ChangeCase, Vim}; +use crate::{normal::ChangeCase, state::Mode, Vim}; pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext) { Vim::update(cx, |vim, cx| { - let count = vim.pop_number_operator(cx); + let count = vim.pop_number_operator(cx).unwrap_or(1) as u32; vim.update_active_editor(cx, |editor, cx| { - editor.set_clip_at_line_ends(false, cx); - editor.transact(cx, |editor, cx| { - editor.change_selections(None, cx, |s| { - s.move_with(|map, selection| { - if selection.start == selection.end { - Motion::Right.expand_selection(map, selection, count, true); + let mut ranges = Vec::new(); + let mut cursor_positions = Vec::new(); + let snapshot = editor.buffer().read(cx).snapshot(cx); + for selection in editor.selections.all::(cx) { + match vim.state.mode { + Mode::Visual { line: true } => { + let start = Point::new(selection.start.row, 0); + let end = + Point::new(selection.end.row, snapshot.line_len(selection.end.row)); + ranges.push(start..end); + cursor_positions.push(start..start); + } + Mode::Visual { line: false } => { + ranges.push(selection.start..selection.end); + cursor_positions.push(selection.start..selection.start); + } + Mode::Insert | Mode::Normal => { + let start = selection.start; + let mut end = start; + for _ in 0..count { + end = snapshot.clip_point(end + Point::new(0, 1), Bias::Right); } - }) - }); - let selections = editor.selections.all::(cx); - for selection in selections.into_iter().rev() { + ranges.push(start..end); + + if end.column == snapshot.line_len(end.row) { + end = snapshot.clip_point(end - Point::new(0, 1), Bias::Left); + } + cursor_positions.push(end..end) + } + } + } + editor.transact(cx, |editor, cx| { + for range in ranges.into_iter().rev() { let snapshot = editor.buffer().read(cx).snapshot(cx); editor.buffer().update(cx, |buffer, cx| { - let range = selection.start..selection.end; let text = snapshot - .text_for_range(selection.start..selection.end) + .text_for_range(range.start..range.end) .flat_map(|s| s.chars()) .flat_map(|c| { if c.is_lowercase() { @@ -37,28 +59,46 @@ pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext Date: Tue, 4 Jul 2023 16:00:59 +0200 Subject: [PATCH 062/104] Fix click behaviour of vcs/project dropdowns --- crates/collab_ui/src/collab_titlebar_item.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 8af3acf7be..3bc890f91b 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -237,9 +237,10 @@ impl CollabTitlebarItem { .into_any_named("title-project-name") }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, this, cx| { + .on_down(MouseButton::Left, move |_, this, cx| { this.toggle_project_menu(&Default::default(), cx) }) + .on_click(MouseButton::Left, move |_, _, _| {}) .contained() .with_style(project_style.container), ) @@ -267,12 +268,10 @@ impl CollabTitlebarItem { .into_any_named("title-project-branch") }) .with_cursor_style(CursorStyle::PointingHand) - .on_click( - MouseButton::Left, - move |_, this, cx| { - this.toggle_vcs_menu(&Default::default(), cx) - }, - ), + .on_down(MouseButton::Left, move |_, this, cx| { + this.toggle_vcs_menu(&Default::default(), cx) + }) + .on_click(MouseButton::Left, move |_, _, _| {}), ) .with_children(self.render_branches_popover_host(&theme.titlebar, cx)), ), From 48371ab8b2ba823278dc5fb0853673128e3a71c5 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 4 Jul 2023 16:30:17 +0200 Subject: [PATCH 063/104] Remove PickerEvent::Dismiss emission from picker header --- crates/collab_ui/src/branch_list.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index e0f85aa65a..a1693fd6c4 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -255,9 +255,7 @@ impl PickerDelegate for BranchListDelegate { Some( MouseEventHandler::::new(0, cx, move |_, _| label) .on_click(MouseButton::Left, move |_, _, _| {}) - .on_down_out(MouseButton::Left, move |_, _, cx| { - cx.emit(PickerEvent::Dismiss) - }) + .on_down_out(MouseButton::Left, move |_, _, _| {}) .into_any(), ) } From 4c51ab8a255910cb30efb2cd819b4bfec13623e0 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 4 Jul 2023 20:58:33 +0300 Subject: [PATCH 064/104] Accept `null` as a valid action, to disable a keystroke co-authored-by: Mikayla Maki --- crates/gpui/src/app/window.rs | 8 +- crates/gpui/src/gpui.rs | 2 + crates/settings/src/keymap_file.rs | 47 +++++---- crates/zed/src/zed.rs | 161 +++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 21 deletions(-) diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 23fbb33fe1..743f99ee62 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -14,8 +14,8 @@ use crate::{ text_layout::TextLayoutCache, util::post_inc, Action, AnyView, AnyViewHandle, AppContext, BorrowAppContext, BorrowWindowContext, Effect, - Element, Entity, Handle, LayoutContext, MouseRegion, MouseRegionId, SceneBuilder, Subscription, - View, ViewContext, ViewHandle, WindowInvalidation, + Element, Entity, Handle, LayoutContext, MouseRegion, MouseRegionId, NoAction, SceneBuilder, + Subscription, View, ViewContext, ViewHandle, WindowInvalidation, }; use anyhow::{anyhow, bail, Result}; use collections::{HashMap, HashSet}; @@ -434,7 +434,11 @@ impl<'a> WindowContext<'a> { MatchResult::None => false, MatchResult::Pending => true, MatchResult::Matches(matches) => { + let no_action_id = (NoAction {}).id(); for (view_id, action) in matches { + if action.id() == no_action_id { + return false; + } if self.dispatch_action(Some(*view_id), action.as_ref()) { self.keystroke_matcher.clear_pending(); handled_by = Some(action.boxed_clone()); diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 25d022d8ed..3442934b3a 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -31,3 +31,5 @@ pub use window::{Axis, SizeConstraint, Vector2FExt, WindowContext}; pub use anyhow; pub use serde_json; + +actions!(zed, [NoAction]); diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index d2e656ebe3..93cb2ab3d7 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -1,7 +1,7 @@ use crate::{settings_store::parse_json_with_comments, SettingsAssets}; use anyhow::{anyhow, Context, Result}; use collections::BTreeMap; -use gpui::{keymap_matcher::Binding, AppContext}; +use gpui::{keymap_matcher::Binding, AppContext, NoAction}; use schemars::{ gen::{SchemaGenerator, SchemaSettings}, schema::{InstanceType, Schema, SchemaObject, SingleOrVec, SubschemaValidation}, @@ -11,18 +11,18 @@ use serde::Deserialize; use serde_json::Value; use util::{asset_str, ResultExt}; -#[derive(Deserialize, Default, Clone, JsonSchema)] +#[derive(Debug, Deserialize, Default, Clone, JsonSchema)] #[serde(transparent)] pub struct KeymapFile(Vec); -#[derive(Deserialize, Default, Clone, JsonSchema)] +#[derive(Debug, Deserialize, Default, Clone, JsonSchema)] pub struct KeymapBlock { #[serde(default)] context: Option, bindings: BTreeMap, } -#[derive(Deserialize, Default, Clone)] +#[derive(Debug, Deserialize, Default, Clone)] #[serde(transparent)] pub struct KeymapAction(Value); @@ -61,21 +61,22 @@ impl KeymapFile { // We want to deserialize the action data as a `RawValue` so that we can // deserialize the action itself dynamically directly from the JSON // string. But `RawValue` currently does not work inside of an untagged enum. - if let Value::Array(items) = action { - let Ok([name, data]): Result<[serde_json::Value; 2], _> = items.try_into() else { - return Some(Err(anyhow!("Expected array of length 2"))); - }; - let serde_json::Value::String(name) = name else { - return Some(Err(anyhow!("Expected first item in array to be a string."))) - }; - cx.deserialize_action( - &name, - Some(data), - ) - } else if let Value::String(name) = action { - cx.deserialize_action(&name, None) - } else { - return Some(Err(anyhow!("Expected two-element array, got {:?}", action))); + match action { + Value::Array(items) => { + let Ok([name, data]): Result<[serde_json::Value; 2], _> = items.try_into() else { + return Some(Err(anyhow!("Expected array of length 2"))); + }; + let serde_json::Value::String(name) = name else { + return Some(Err(anyhow!("Expected first item in array to be a string."))) + }; + cx.deserialize_action( + &name, + Some(data), + ) + }, + Value::String(name) => cx.deserialize_action(&name, None), + Value::Null => Ok(no_action()), + _ => return Some(Err(anyhow!("Expected two-element array, got {action:?}"))), } .with_context(|| { format!( @@ -115,6 +116,10 @@ impl KeymapFile { instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Array))), ..Default::default() }), + Schema::Object(SchemaObject { + instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Null))), + ..Default::default() + }), ]), ..Default::default() })), @@ -129,6 +134,10 @@ impl KeymapFile { } } +fn no_action() -> Box { + Box::new(NoAction {}) +} + #[cfg(test)] mod tests { use crate::KeymapFile; diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 874fea6500..0df16f4bab 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2074,6 +2074,167 @@ mod tests { line!(), ); + #[track_caller] + fn assert_key_bindings_for<'a>( + window_id: usize, + cx: &TestAppContext, + actions: Vec<(&'static str, &'a dyn Action)>, + line: u32, + ) { + for (key, action) in actions { + // assert that... + assert!( + cx.available_actions(window_id, 0) + .into_iter() + .any(|(_, bound_action, b)| { + // action names match... + bound_action.name() == action.name() + && bound_action.namespace() == action.namespace() + // and key strokes contain the given key + && b.iter() + .any(|binding| binding.keystrokes().iter().any(|k| k.key == key)) + }), + "On {} Failed to find {} with key binding {}", + line, + action.name(), + key + ); + } + } + } + + #[gpui::test] + async fn test_disabled_keymap_binding(cx: &mut gpui::TestAppContext) { + struct TestView; + + impl Entity for TestView { + type Event = (); + } + + impl View for TestView { + fn ui_name() -> &'static str { + "TestView" + } + + fn render(&mut self, _: &mut ViewContext) -> AnyElement { + Empty::new().into_any() + } + } + + let executor = cx.background(); + let fs = FakeFs::new(executor.clone()); + + actions!(test, [A, B]); + // From the Atom keymap + actions!(workspace, [ActivatePreviousPane]); + // From the JetBrains keymap + actions!(pane, [ActivatePrevItem]); + + fs.save( + "/settings.json".as_ref(), + &r#" + { + "base_keymap": "Atom" + } + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + fs.save( + "/keymap.json".as_ref(), + &r#" + [ + { + "bindings": { + "backspace": "test::A" + } + } + ] + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + cx.update(|cx| { + cx.set_global(SettingsStore::test(cx)); + theme::init(Assets, cx); + welcome::init(cx); + + cx.add_global_action(|_: &A, _cx| {}); + cx.add_global_action(|_: &B, _cx| {}); + cx.add_global_action(|_: &ActivatePreviousPane, _cx| {}); + cx.add_global_action(|_: &ActivatePrevItem, _cx| {}); + + let settings_rx = watch_config_file( + executor.clone(), + fs.clone(), + PathBuf::from("/settings.json"), + ); + let keymap_rx = + watch_config_file(executor.clone(), fs.clone(), PathBuf::from("/keymap.json")); + + handle_keymap_file_changes(keymap_rx, cx); + handle_settings_file_changes(settings_rx, cx); + }); + + cx.foreground().run_until_parked(); + + let (window_id, _view) = cx.add_window(|_| TestView); + + // Test loading the keymap base at all + assert_key_bindings_for( + window_id, + cx, + vec![("backspace", &A), ("k", &ActivatePreviousPane)], + line!(), + ); + + // Test disabling the key binding for the base keymap + fs.save( + "/keymap.json".as_ref(), + &r#" + [ + { + "bindings": { + "backspace": null + } + } + ] + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + cx.foreground().run_until_parked(); + + assert_key_bindings_for(window_id, cx, vec![("k", &ActivatePreviousPane)], line!()); + + // Test modifying the base, while retaining the users keymap + fs.save( + "/settings.json".as_ref(), + &r#" + { + "base_keymap": "JetBrains" + } + "# + .into(), + Default::default(), + ) + .await + .unwrap(); + + cx.foreground().run_until_parked(); + + assert_key_bindings_for(window_id, cx, vec![("[", &ActivatePrevItem)], line!()); + + #[track_caller] fn assert_key_bindings_for<'a>( window_id: usize, cx: &TestAppContext, From a7ce602bac0902e62c544b3cf0a9132160d9aef1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 4 Jul 2023 16:18:42 -0400 Subject: [PATCH 065/104] Update collaboration sounds, add sounds to screensharing --- assets/sounds/joined.wav | Bin 16142 -> 0 bytes assets/sounds/joined_call.wav | Bin 0 -> 28808 bytes assets/sounds/leave.wav | Bin 137188 -> 0 bytes assets/sounds/leave_call.wav | Bin 0 -> 30916 bytes assets/sounds/mute.wav | Bin 29314 -> 56088 bytes assets/sounds/start_screenshare.wav | Bin 0 -> 12188 bytes assets/sounds/stop_screenshare.wav | Bin 0 -> 14024 bytes assets/sounds/unmute.wav | Bin 133336 -> 48834 bytes crates/audio/src/audio.rs | 8 ++++++-- crates/call/src/room.rs | 5 +++++ 10 files changed, 11 insertions(+), 2 deletions(-) delete mode 100644 assets/sounds/joined.wav create mode 100644 assets/sounds/joined_call.wav delete mode 100644 assets/sounds/leave.wav create mode 100644 assets/sounds/leave_call.wav create mode 100644 assets/sounds/start_screenshare.wav create mode 100644 assets/sounds/stop_screenshare.wav diff --git a/assets/sounds/joined.wav b/assets/sounds/joined.wav deleted file mode 100644 index 70cd41d16f9b21dcb46a0f91e7f446a4157f8239..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16142 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 X{gU3qehEd1tFLp;JMvsaMG*cUnYqlI literal 0 HcmV?d00001 diff --git a/assets/sounds/leave.wav b/assets/sounds/leave.wav deleted file mode 100644 index 27dcea38f450b6f4ff48abf6cc4346258c5aa17d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137188 zcmW)n2Y6HU_y5m1pPO{0&FbE5I@sVqMQ{LuIKTTvpf_Cmn#c%EKQX1Ukz_E6)IC+;{-gc^44jSn) z_BxD@Ty&;WmAK`7CqLr`bYZ{^b6s#oI==0a2h;h83%^KLnp6q$P8`HVb#W$s^EiTMSH?DKRZZ{>l;2O7l=!91DvQAj&!k-*) z$SJ2f;1nlrvcuC3;WRj8$IH_o)h=(O%9J#$vC+a*Nw66Y*l>J`_H>F|oE%@9jEj;i ztCQsR#Q2ItyfZ<&K0%gPd5RUUwP1!tW@^%|aE!t)NRo-~MQR0g8W=wahndzgeq_je zLvGN)qk}6>-7)%Y*!Xf-zk3MpAJWPO;p{=9x*xOwda4ip?vpd4@LCijVObdA9U+ob{pRWjlEs!^=^8nlOOJq`#bQCPPiceH+SG{KQ9c(^mg?>Kg?`1 z?rX=(Th&W#ved_4x6)cKw)%|kTR7iG{mt4UFPz;R|FT71Zn8L9Xs}U#u$h-MQn(2M z4RCK0-P-_(O@_Mxwl}I@>tTK)KU5FtjWDYoS{ksd9)4;Ndp&&6fGPE`p#ie$aZ7`o zTrWR0;Ena*Ymm3=F{=>*^?Yq3o!6i~Z!|t@U{{kG-3X628Q(M_HPfX{@?tX#H^JBz z`KlRfTkydadCn_yym+M#C-|hiRf<~C(nk4h+|$OMcJjC5B)@d{;pzYm1?0&NPV1x} zJJrcuJlv&U-%ZnlmRExOa!>3~4+eX!Ss|Gdj^7lfoe}N(2$%O6u0DLTpO*KFbC8b? z;0r@EbqE|W`D7Sgj!R)&vJACe$4#tT87e_rCGa`w5rET`_CJ!JG`&&LRI9quV(dwf zy;kkqB%YY4|B!6ioTMh$;>jtzF;%rLi zGU)tt=+2Y}GbAq?wq(+@9Nd@1*X443HZIGft{k{4pSyBpNrCd_;bn!!U->Y;h(0M0 zF5-s^X-_eoSH$;}fL=uTrM$J6zbd5}C3u#H50}8V9-3PUo-+8O6do>J+b<$fd^_WBc=j6$DnCQU1RE(#|78~zM#rY}pkWI8?IV}ahOoZMfxGn)d zOcaY%u1UbpHL#lp3ifDZCAdc!UjU9GZJ|gL=uXDhMD5dg4)dxwr5JQ(O#X};u_1Ua zru{mIR}AaV4shX+x~`vk2l$je+1n4UsBG+`!7x1@HGCoC)`+U>Ro8}%qdk0SNHqoF zvR>}##;bZLp_`WkjgejIv2L2zsc-6%wH?}Do%naakPgTW&^aBl%nz#r@LxOE_;E_R zn&_7=+xYEvoY;o;cHYwp&$g-STE*F>Ln~})wS3{DX|4KgKBL1&r~1^pKCt@uIv@MI zSm{%Lc_rpGe(}?+$o2Aoq8|=nfdug;gEs>*9wy`Q2_hsY~4$x-K4h+);L&p0tt{lddaZHH8Wjgp{P;T&VaTqkzCLQ)OKWN}9f>*L}J;)fb zlp_+v{K$vFx}DSq7+WCZxf$7TBl3=~jHo0xedVW`(B`AZCRTiTFtZ z{+`I!nmw7wqd3XR@>x#8^mldIu&nCg-=uY zNGgm?qbX^yB~9K*gKWDDrNL^uy2K8>cHJykmpfFC9X@l&LxAzdxXmeH z2lqO$(n+VdWUdqLa?#^X-tIECJ5_^={&E`0Zs~N=scy8m;3_xdx%ghUjB(L=H%@lR z7B^3K;kRyekxO>Fjf-9Ir(2nif4PmBE;!&;=eY1Uw|=rqzIAJ5F4*oioGyILO>rl$ za)Z}Ni`;B(Xw%)a)yYL}e$uIiU9`Zd|K*a?o!Ukhq&kh;UC`{HGhFbwgLNmYa?oxk zp6}pCot);Nvz=6J=K+VjX2*{mFyD?hIv~StzJ!O;=qI~8lg2mM;oLNHJ3X=9KTG2+ zseDNq%}=H7R8gt?l=(5*s3aBU+xQzB>M3-gP2Nr6+7vi91(&2?V=_dN`GI6unXJ;2 z1(NxrBwC#W=OnQ;39AxuO(HK$1eHj=3Gh&YJdgl=R!|9OHcQV~xzWNYR=UJO&s+Fs z&9GV2SWR22>2D}q(=1A9t5obZGNNQXjJT9yXCTy}bpyZ!7-xZRK`j(41OAoyIl*G4 z0ft8mzLue0r`?8}p-Y*8ug2ji9l|jP#9?*}X2oUOFl>vF8U}03xPC|$4XYmq>DM97 z9OS$qyn6ueAB6wxbSbxA)VfNe(bI!}_Q1xVoZiC)LHsDFHg!u;kjuN_t#0_D z3$wa$T9>@h#YZ}^sEh9G!eAY_+^Lu-67X>;Qu-xxdW0q;Fo}W8o&nwa7}=x z1ke^x)`0Bw>(zdI%CGJ4!zF&>89x{L=?=ddXqT(am)c>DU;D8gF7osCcAVpfO(%Yj zo7(XXzie&iXZ-L(yZX$J)$PV{zYMf1X8=8ZV@?3B_S5SDe$6j!0c!N0*ipv^jExk^E26Z!Q-?LZP%C+U%7aHOa_n_OVyX{q=`DlJWeAJX_KyY$#; zn}dp-yvJ$GcHwcCcAp!1-1=MT5KC7-WPr-#!A8?-s*^QW{-?`$~Cx z3D5RWVJRK($djdVMj1Ah!dqoL#)H8!b%#ezD%Ur9;D6oKVV^Vt%Xy=M~YuVtKPrVnz600hAQUU_PE%i0*uzZa&SUbMv7*SH|Z_P7b(o zNz2BLY{Q$$Uu0?DWzhd+8jq%PX$GC+rh{&YI(ex}-gA)Qp!4jq+AfWzSV)8AHhSEK zMl$y$^Akz5Ac<5W?@i#9R;sX4SmQ@ES){0z;6Id62$KLF64}Ubz#yvuSvubyhnr$_ zXc#^l;!}rEAE37e_`-gsetJ8K%c2|%!?7^U2*HIR+0=u-^Z*9=j36xSqVKxkNC%(Q z2^R$LKmhl(!;OBvunqJ!Rp*2ETaCNCaG8&?S|G*Cdz<8+W_qkqz1zgI8ua@cRbjoh zph1V@#+CJ2+#v{X^=VVGFO z`PFh?72Qw`|5VAR)o5NP{fK;Z7}p-b^Qzf(RNAWPlcV_d5uR5Ai;hxyt(;lI-dd`t zrQOH4Lx-ZaKw|5x@RJfM4%Wvpea6F7|hc3es~y_@l>|+zYRSR3wB;BK%o|&+WtI zeN-}lXAQ7rh*O5BcbJ-nr7q52$IbsEzF^3Yg0~8NiZT;n$uAKaxQ8R=6XH zze%L4Qt0_)=+4!WANos5E;X_j)pJC(u6UvU>tkL!0rZpoI69NwNux0`!fI)9r1d2Wom;e02Uy~i>;-0pzqQsK=s*p>pjZSYGH zv?gO!f?yJREmV*|5ycZN0z|VFq=76#EMU1`WQS% zRt1}@@VY8^qKZnY;Jzw-=nyyunqflKOU; z9((F2qmfm;Ol_i(4Y0DAuWp2&Tj=#BNbyNyGc0U{310Z64W9Esg&(4=@Jav{wPR8z z*82I0E}q*#mLMJP51X!4? zmM7tX6dq3IF{yaJjh;?}-c&heha2rs=7fC?yx9enE`HMu54mZ7I{c9?fecK{1jyp4 zS!m0qW!apZBkOXMU~m-6}L0-9Su_Y_KUq0B0RuL{9c40DR$ zKrtRKf)yolO))r1;h$o7uM|!$fnpClQv&NfP*oxk52TjT%rZH%RGurtYfItxGFVm$ zU1hMmR8+a#T8hr{6DB}vxp8tS#>+HS%5`P&y(RcrndRXUxVuarRRSZ+=wLBad0;^? znAN$n2*8847Qqvx&{znu5;?yR7MI}m0@+s#SU`EjGACbdE}~cRWOE_^m#gXuC?Qw3 z7VxP#+NgZICfhhK4<5|I`ML0FCM?Q>#v^)|2O_G}uU{j*Z zx5}Lfbg>1`wemDg(k!NA1Fw>aL^}yiMPnVpM4+1iCJCP-a1K)m!$k&I47gU8jyU{Z z9FNB2>6q*vR@;X0mm&S{A^BlY8ydtP2lR?T_^n@EKfs6j_>F!Qh*Eu@fl)5&Qxy@q zC(4(Fje`+f9a5tr{A({iA6D3l@ep6s19yh-y`XgTg3*n)_rij1>FbfdyJ$@h&FJF7 z9{#8agl|$oF-?!EVg&fTz3Vj{siWjSmGlr`y~>u)B*?0QPn9VLxo? zLbHE`YwF(#NPrnJuFbGSAj6;KvFihtS!Pa5eIV3Y;QaMb47`{EstK*Ow zLyyi6$K+>Sg=2KBVJwRCfT51W@kQntx>N{#tK%*)Dh;>-)SCvhgOSK`FKQ1kT1gKu zyiD3v0>w(-C$L?a9xqJL_yd4%G;|}JX@SQOezZup+2dL18p3a^#y;W+33RHW?dBI% zaX}*6G+LjiJ)kir>1`U_l|+|YxIPJXS!iamjIi>@$@sFB(o=w~d`}82O`szwU{iyGrPVv7z@$#Ls7P8#dhb~*V>xBiZk&U0%II^}#f zU+RRJZgZQ(vrQ1-;0bQt<)A{hdcq-^+n8?NfQ!I^yIr!=&ab%ORy*C~!Yn(FG<&Kv z>T;@^O|QUds5H9TNgGnxT)I9Z-f!;4Jc zCQW`$!bePJCW(7(^m-y)Ycuo&`8kDdNPxl=`N0bJCPTUv{z$^57D!K$?=-kJ5v&@# zlOS^x)LQ8kGA&0wf^e>dG7*+(d?~=I3fBt!K(L#!4q?EM0TAzKOOAn&kowQi&i)6%$_G$eP&_~t=)co^0X;4?$GtDn~oN=F~QGk{rru(e-iMCFS< zye~pOM|pdg4@Rgdg!N&`3_(u_F7E{u!WVlauU8HQ>5Lx83i4G!T-Z&ky7{v%{;-R* zE;`yN*L8AoC;Zq!Gdr-jgVzL%X9M`JUo-qzJ+|va+2gw?Rrfe$oo> zw?RcKPHltjJ`S|PM4x)A6%Km!D_Z3?uO+J$v%PVj5B_P+1NsBd~!;Q zJm|yh7Fg+n#1>fX6V+lmkYsDYAALqq3%C2UsV!8{8o#53uW!}1wa|`M?rC9a!)abz z+y?J?!Mqup59YL+Z->L}nA|Fh{PI>S8GbsWjo%M&a~odKL9e%CYA4V0^Px^G3($LA z5I2p=ZfNX~YlCpG6KD0no-R167k=-C$szbJ2-CvQ+5?wHfI_@D3M0d6bst<6;g9;| z`6$*5kO^**hQv95(}v;tL3uc4syW;fH+>sPG-N>>u4J`a$IYUbu|z>zCwM*?{U93@ zEhOyM_#Y(~S?Mebevlv^Ss|W?If;CEvaC*0+fp!`Y{YDGwM|`=hQFrr8+P#6!RLU- z9a!m-<4#%Z#*^ImLApGW4z(HdM+RH6I4Mhw&Bp23#zi@@B8P6tg?Dphc^>V`gZuOK zs(ie=z|vSCw-m-33-RJ2t-8n*^~O)dG*C=$mhiVFvb2=$Dupo~$?-so2X=bk=`xcG zU`aWcP~f9-m{g7x6|kY)SYH9*a;>KV&Zy8QRl*$=+I^MqN`=0u5_VM3u1fr(0{^Jw z?G?PIlGazyCzZUog4a~ixC*?qQrgNTp%T}X<7X9OUVLT+Y%i08_o(C6{(5g~cTWsne+**V`7t2?L_(u_ZUBJH;!q$BHvOu2Alb7<g%@YgS((u7mYQ^U%q2_Qrcp_~PI%GI%N&xNMy+Y|h>b5# z<*sD>DFrV}f`VlDG65b;lvJzyXQd@((`e!EiSJQpL;4-%8WB63Kz^pPHxQ?-x=fFW zS#e$-f^&uq-vF)~RA=;aLqD&L(#d_;9_D8wGCiaMA==hsT-eKLLG^VIAMG+c-7wTa zZ+FW50mZ)mRHI6(Y`>W-tBXH&sj2(erkI1T{aMe-Ds1c|!eypLNYP99Gyrxz^^BCT8 zjMD4m@;Wf;@Y3TFJucVRqh3!d8^BZzA2!OFP1M{(%bK~eg+FeghrJZ@a+8lQZ>2eH z_-&i)Z#Pu~&I!oI0M~b@vQE0EOaHu!GlObI5cl+OOAoCG;hK;>IwIpEsw;}kQTe1_ zUh0Pj2JzxSoG}bZ!{Us~{+M`m(}|_;882X23!DtNfYje8Cuzo7W#S~d$U@Z#Vo8v9 zli-&`xFrQvBtvB?l-eMW1}5@**8z9hakdL=PKml z3vXuQ=Xqe{NMQla%Y#*g{C+8;V1GHKkEG2NyniImuEaY=k-t)S6yG@lA0DmzBcOA%F?%GOKSsSj zQl1-Qw2q|RV<=;k;T1pIfQ*zo$I$+fSUN^uITC&u ztrd@y3rFjwneh84?X(dxW)yFx2VQlYXHd|Dutg=iX#f9Lb*d9XN-x^u8UM_x0nk8C+3 zi~BRFI)j#En3SKZ+}P`)(_L`46JBvh#Lj^UyX$j8~aXQLi*~@&EO}t(~egh+2nH-v!(KYI7%F-OhJ) zXqjy|I}oe$$;tkNFT7aZKKybERJ0|mZk7qHu}7M4me2BhqulP*KWdNPD zJ=E2}<@Io|2By}-Uo~)cJv7$9h4o_8z%BK3QY}1J&ns%-_j>xH7E&5y)G@rFLEbsW zyBesdj>a^~XLY=#5#}7Hu_hBe&c8IlxAnB386IumllwQhh;8#49|!Uw~qGcFl% zIWYbY{F{xR6=HIZxj(a(G3dabpghT1aQ*h`#{rIk>(+YO-N`0lk?m zzvmm5Wy7WU%94%$=w3HEGq~9$XQ$cFtiHYY#j!UQL7b;1G%{N|8v>{4f^6gzdN@il3N zo{HO3RZ1%K+c?W6XWP(|g3qMD$YlI4Sx!na+{rj4QM)Dy&P&kWO_U3)sx^VGuyAF9 zah-|uUH<{JOkLSPpB(1} zLN~|Mx2AR**6qxDhqT)bO$POYx;|x48>g#>2aK2Fysuwz3^V)nTVrrrpLTp$ev2BH z3}Z!9{V^o#B0PNv<6-!HP?m*p)*yC<L`y3k}V4T-MlA)d%EGF2)x=&QzCMEx4~hW-L3Y8 zjZ?b$g|I5_#v8-z>XwtjXzRwLFr=7pDkS!9+!Ml_ZulSsBfI69ket;GD?)TtH!TS9 z{oQ;?2u%rZ@`C-QX%LdWZaghSBZD$A#MhfWe+b_U8fIHt8&uOmP|(8{g=A3=Tob}i zdhphe#Cl{^2rur%mqPGfFMJ%5fnMGp0yEFhZk`h|EMc~V)u^z#BWzp}HvS8%`@?j4 zMBf~i4H3(sFeFCf5P`d++NmexysZpdaFV@gSe7(~d#V04gXNmTbLzAw>04LTCldX275G72rcKS}$< zf~O_NCtKzHWXnM-I#Tqj&Gs@ybtHfK=sKaUes6#Hc(*cM4W@m@F zr#a{fCvS7edM9Q&iG>Lja+Tb;%vm$|OBTV1f(rJI5}?ozv4GTUu5xzsyu#V+0F z<}9~XnQjVpzB!$zxaFO6Jl{?Kq{D1C52f?PZYs>sX1Qf@M*J){T$y1R>xP>%^h~!b z%P?a+bXSJdy7;yX{KCu$WXR(#z9<9dxbUP5NOwV6h8%K&FCEu9;q!Ev;)HwCp~Fn> zrPK2c=y3CB2fXIS-|cXgTjtuK&IK)L@P976B@Nk({H5{}PPi`BG%@6F8{g-^NjCD^ zc|(fKwriX$pQP#Yk|`lg?MUMJsXUZOn{7Bfk=s*bO#+pr&^{|)lgw;U>ymJyMcfF>&?jE6VfWDkUhNOBk>ic8_0rxJ?HaGFY~ho=cuossdnL7n61~*XtShhaZ?l%- zRlhYGg_rc#S&~JMFUS8S?>%1z^ zD(p4xZo`Ltn9?qZt@LR-ZEDr8_4D*LOGW_u+Vo=q_`F?h?~r>;G+^?(050t^$~$Ck zx0cokbAoZ{#LIdtMwc0B&?zW)gp|7n*M@miFMk@ri$iog3ipM@)-PKlFmr&KqqusI z3;N~25ZyF@8DQJQGQI}7m_d|RYj8J)->Z%8~$vkk5eVZ$z;bXT{O=juey1& z6RXmx%Oy#fVk(6*vS4Wj+>niLXM$PW_h#YCxn!!>4S9mOv@suCdHiYtW#`l5g}SSN zZz|HXLY!1=_zS_jx!pzZQwcs_Y~lcYb_u3=tXRsMJh3gMs-nztj>mYnOyBRJgmRi* zCJV~tvohFGj%nrCUM|;_i?f2>E{Aay#({F0RH3@d^@$a%ms>m)z~yl+r`~eyU^)M1 zYV&e>zZ_33=bOvnP#I>G%k^dOeHkA2n2|y`-$Va-Xlv;SiZ@V#+e+#5666wNX)(_z zQR|B6kz!+0A#X2I+Y4}iA#cuyqXqa;<*G?Ad zCxI#3A4`B|6h$oHM={%s836l<-(whuBs#nzd|e!327WgT3v|dHf_*V~Z~(>)OOu%$ z9i;Q4Y#rdQ!gPNhR)(ZIA{))bNEnNP5a^Znx@1`ooz#i(Zew2nUg%Ow{4%=Ju(eZF zK<#ejNBxHR^`6vD7kI&FmAn=?;6rJ`EnW#W;@TGMYS33TbAP>cRg;!lAA7b@KlQlw zVS`#$C;!$PUmfFwdX;!gU3#2N74Tsl`fI>Z2Y1%snqy+A;gn^BP$^PbgE?? zCi38eou)sDr*z{Dz3_ezA|c7_g%>0EN{GkzNoGVl(vKUX@l}H|s^2np7=IdwACJi; zL)vpX`iG6Pm>-U-K2bS_u?3B|81-;)!|2NyT)2zB;8uE-KK=O5wahEy)98iu48#CKp>iD3hAv z*wy8x+h&z={AIc9uEdq)a8)IoQVxw3e7p?i zR;YW+;Ky=<%D`2w9`eAoW!zZ`uX^yJQuwu$H;kiWPoLgikb_n*gPXgBExV z=_w6tz(ookXZ0h(psrsDaCh7iVTcaLUo_y}A?;Kh%=}et44&?W!><4yZm1l zyxm5tI^pA1Uf%(K`p`Tf>NSO}RC*1!pKfo_=C$*#W_@!T7B(xR71lQKqE<6MPe*+6 zQloLX&lK0H!OK+*yuwS*G+>TbW;ehAQ$9Dq(=DVm$fYgZS5G5aRDZpsv>4O?Ml%&R zz;H8P&;Y819&do07XG6F&u+njM!vlT9%-a4Ez;A-oh@{06P@MdaFe{@#iyD9d{Ef} z%Y9H~p5TLLymW6XT;yY|4RTs(V;l6g^0apNrwx1CVP`vh;D@b#SP+0s0r7OedmR+& zkZqm3rxU;JqPM%?pKgAz+r)pkASl*exTpt5hhS2#Tp5OOA$&9f6=C=+3MG*fJ7iH5 z-2+n4Cl?GtX+J(XgcSqw^{|W?q^=mAGGvtKFnL(bJ7K&SPqVr(PTz}hiJ8;|y3&wz zf~y$MQfv~pg_^n=_z{b7C2H?lX%6XMCdhQ9eow^HH2ynDJQl1@hEyw5rBKAgF*g0* z1o$@9@=+qZn-*V{1drOa*~u{9!RaYt;;Nby>UQGGHu=cK=cmE~x9U%Ylyu|mH2653 z%vAY|3^{C4p$xd$!B?3Uv4g5Jaha3P%i?w?eVj#Cxi}%4e|6Ed*;HZ{?rd4VFUXPS(&@e&_&J>)%K?A7T5XE=41HA&7iC!P%u%Og#IMXTCTFOV zbLgB5vE<0445-S6u^ISkHsoi>>}4Eb~lVPUK91+5wQ;d=% zIXQ)HN`w!S;e!OsPL@_HKbwSQRuxZ_TP*r*iMUNu#}lMe$%P3xLBWq!xtm~=*+nC~ zX%Q<*q6M!2TB*rK;Vy;d$jl8&&SN%p{RZO%A{o%(CsbGHaxxlU$LV8GIdL|7kjG;9 zzF=?|iUqD8HUo9?-;mkh-~~gl#Sl}fk1}xPAbqXF!2#neU9K2V2jk@J=d0qzihk^j zX=d-YDyDzfhv_jjt4}@}=B_Bs9L86pM%xfhi>ft49E}(whG<8G{u<=P5m+&Zl@Tcz zgsw0i7=W+CaQ^^29+r^O|eYhf|>Y}hTWPA{Xg(12-3O9scY7}k^u{$b@LevoFl-IO$6?$MmYT4< z5~hR*yclLPwz@7%w?~Y1VSX<{FNEosX+(q#bDZIwuy$#bwuOy#QT`^3e@Ag&80>ve z7nUpfAQZ;8`XDKS-aaXd@aTRzFM{{=pZIY0_2asTqz}M15n4PT%@O`?fE-au8|0}` zlUm~aQQ9>qpGS?%Aq+;<@*x=8$Nvt=oqaTZn0EH@^TUSpVPsg%>6f`N-q4Rf#VFDb zp15(rfUJ$H4+l=TwaV$I5YX+v6xGgxj?xP_HZ!5O08q{%_i+B94Q z`YjfSfflgHD`+gW;z@*^R``eT_5`_2aaRJFWPe$ru|wlvqBh%t%aYYD-o}68Odxz9$juQXne{FSp^hNyZ;GnU}22O2vU>`7~A5r$|8>jkr5lQ7=?CQxhEO8iayR34kjdrMY7?tLnom2bRA*-D6F;4u;Y5B-0ZkJwS zru|*&HIqBISh?|#nSXP$#XNAUiEbH}uHWE>r_!}2+;}Wqf6vWj8QKqSb!&!x(5-LF z&}!Y5<_x{T9k*wy2DdgTldIi)btdk2!-`D!!j0yH&Z};DJ`&| zZq7d7CbztpCL`QLX}H5Q3R1=6!vAdeiWA1#M0dy&DR{kujwH+1b}mdttDSC6;yG!& zIg!?Y55WccvBI3^$BOl~< zO-&HkulQ_+eS~ui*o}Ct4&Q^ZIF6r+c2|ryaeU>lddaXnHKaeL8|w$vU2)tnz&FI; zqkft_EZ_C#4bn);ys;I(rx_Ip-=A8QaY?Rbm|KNu{9mq&wk6d0mI|hd;IuPyPDvK zq;|f)9iDE(gKgk!gUUAez|_&LFtrtQpZI;U!bc`aH+k7ypJBEE1wK{oV@zUfLG5d3^g+B6PU9<6x7j`vke|zPVW27k+@~*AWbp!=Z1_mteS>Z zt;nfn`9OJIrw0hT3_hUXLZM=dYzJexm29N_p1^k~!);E5XmoQjoNDFIQsC7D9I`=w zB1}n>%aY+CQ@^L+_YS61?s3w*G%9k-W;@SH7qeTqJ%c8=cul5pn_In=rM;JKY|b|R z$)GJJ*vga*x!}r%b$L*cgLmf3_*|J;piatz%tE~)A8QIVX92G(;@$!}tyq39gu}(A zOy-3p`ix@LT4IS78}m!`mrLlEQmQP4Y>(_H<%J$8@zA>-dd4FMJnZ#Ahlj?M!LWyy zo_M6!%Am``UzXuN9@F}_#|4-}!bRDLMr+e75i@Wii14>q@>zq?LrHCGa5Nw-$Am7!x(4%h0|g zTB7S?ki9XrRp^FcDPgW3l(%(SFhJRHZtLS$hw1;K=F}L+!~Eue37)XDpGWq}Cs8^W zq;n$jf8Bf}gvDKWcQ4m;KxPlU8Q@>LWuaeN(FLcs>*G5ivyJ)#U=HH_?uP-dIi?2# zE!rb(XlaQpYvrP5>rx-hYKq_P<%b%zM_OoigR!BR-3@fGiSDUqt%+NYtJ#fk^Ks+- z28`CJ#0FSj$1CgQtU43Dk$w!HKW_YaOvW9jt;e9bPF^`i@7Ccf#|+a1c<&g^uEX8O z;H*07JtkA?U~C;+ScebQ!T;*Gt`1(WqYIA1(K<1c!zIV@%6eIKoO|n`^EkcT0E_G8 zvPKBjLtYcEX`oOOjA=9uHM6%-?P;McO~x*-+|{i8Va91%;>TO@bgw1eCZm0NsUJqS zs%rvxTALZ3=Zo60sgrK^n;ME=4an-C+TTHe9-X>)PDney8-EPz>w_>Rs`+|gOP_9X zhmry9tuSmFG>iy%hVhm@(;bDXemY5)se}BjLEj9~Il?1jvKMeuTrMHVHt2`~GpaY= z0*OGiR#}BSFOi~Tra<`?4X3B58Vi4BGo~d_P8xok$SdvONJcY9dS?obbm4v*FL!fp z8tzP2i|x>pp?~C%yex~~N#|zA^UTtgqn)3QOL7gIIDnP%7*en zZEcQ33uE`>;?5%L{5-g|SRa!wX(c$2Pg_gyivk{3$~P9`_EN$kNcYHVMRKP(BwLKT zJoIWY=pL407*(cjEP)HkjE_s;>M{zJh&gX-j>(v_w=+tO(Pel|sU{v-P#WLsF^?@P zJu`EO zmN{!r=Vnrxi_gg5Lk=}M9bdE?S!R$vjm+^qw!v`+e3oLmB5-}OdNvKLNyas)@L2*? z+R)5ShmzUQcxMuQpwy~Fo<)3)8LbB(E4(fAyJpN_liz7!U0p!>dvQ)dH7|x$BB{gj z2Fo9Vw8)@!13XUWEBX=QSlS0ihG8Hg9}mHQVOl!~UxoON0od3}SM|e7Ju;&Y%-M}8 zQGBTzCq-ma7oQb|?>p(@5Y%^wX(Aim9KpT8e9FVhp@U9<&Ua0iThhF@?9hP}{emhL{61GFJm%nKP zo0slx1FKi2m{~Y4xZ5z_Ylhg3)4kBxsx9Z*Afo8U4wes! zy`oruo)HqA{QJ@)*(! z;(Qt#$uSKBeYUiR(JrixDl(Vr1JJPL>J%Xg#!@RUF!}`Xn$7R|l`^>6L{kadrnN*M_c~umWe^C~+ zr{UHtnCxdA;MM-VF;mot> zsP_W&zYJOwP@6K;Lje*J?=tD(XTXpEMKd6gr37gICyQel@KTnv6Jw=+;CUvo3)#|)gFp{~vl_?ANHTC!#@rQ4g+sU+Q6mae|=o2%0K48O{e zIeQxH^TUN{wAc^Ze0`C$i+mhQ)0@4xCe1$A%Tv;<-#kb@`&18q?6W>kg-JfUBo*7e z)^az!?6nzU;N&5x@TCJKBU9#pE8Vc%g8DwX zm1QpZghrR->lLp|fjblqNr7VsKRRJ5!Ua+mNj}VhlK}2;&_B%G;vQj~XVE4?zlD>? zyrW^av4(1#Zj9h_RW?pic)yK@5$q)0jl4LCalq0fE&}*ILHWRw6Y2}brZ`PtSP;j( z!~^1ZC*hV}N*It)?@|NVy)@A9h9331t?uukX|^fsky_8%72}0T`}r7`C-wN4-jLv) zsC`3%zl~bSxSky~Z^rG>Q8hMhB_n*S*Zdj5dA;i82$%QrwGrIfgC|7zp&m|#Az$*g zVf-rwpM-g44CjTRFvi!0acdODgz51prvg?UmJeiN2EBv*z-R)GEpUfacIMFew#$096<{+AK;N*A?6%qLy) zpVFJV_?{?9e0W_HvbwQ1if4Ay*)e{oTfHVPNH^ESu(lgc@8NzST++jmo@?&WUxoCA zy*7o+nqKS5u=2*uXJL9IjwumU5r?~_LzsZw5&Ss;W1~DY37<##{UnygbiQp?#_VOb zmEB`y7_+j+EHzl#ive+}^x{gQGvZXtYDXMDVY)4WBSCS(tQVv<>6naomYq0?TyHyO zDp+C+D;Pt#Ok*?QAdBB(`o+RaLGXLl$c+yC1^Fo_&r&MT*Q%mVQ@B;DGhO(pMf+TQ zr$gN>VXl4* zJ(G*FpeYkR$%0W?N@jvjXPM6e@Ozdj4{{=lmk06W0I*C6<&KoiF9i6vY_&RofgJk1 zFK8q4ME*DjDgvq|2dV=mm@6OavvXljfNsl`wxoJG7d{NoE4lDYK&{BdsR3G+OQivP zF;_KY;VfZgvuJ8AUY(^*lDS3}$8+G*O#D3u&&#AaIdnKfosgsM%HUnu)Rqo2v(??{ zh}lr-=S4xf#LuZg{au=xA25M5>dewJed?+#`rXT43K;1Horzb7W+#JRNyR1UxY-R7 zPe`~RnTA7LFd&UCPvHxEdX`h&?lsFCG{>XAwA8{>+Nk>`s)rOVb5RrGt0_7L=0DcO z5LIWy`N9YVdtrK5MPndu<9$(nqFepg*TLhr!}Mh*KOd4JR6W#9v38OxtGr!J>!d5& z=+X}La;v(uowl~nls1*of;Y8F?$s=)frWIYAv-?@@2K^-%2&7mNr$=XSHf;rD~})2P^5cIvuUVm+Ppw z3cBjl^eVVXG$U1TxE|Z9;N}Lnq?)@L;OAoq<{bp>h)prYH zP)Db?!WH!xY=i6u>}`VvfePB;k4AmC1J*Rr{!VzK87sQ*wH9vfrZ-xVLV8Ub=SIx> zb{rQ~$2;J*7(2S?l^z(~tvB?-%#ex1;q$N>k%X=Y%(QV#jQ(e6VUO-2Rncos1v)LE z=c0ZsX?|BmX8S3YnnHZ3gT7@H)H4tHUoogb z;X3@*mQ=VU-IRLyg$#Vur#{Zaf6{1u7W>oHu7H>{j8OE;Gxd>dvn`9{oSY1(zjCQO zn?A|ovvcr;e0@zWOfRr+&*Q>E>+XDYxR7otpcjkal0r4C7>5_}#$wjRa7793Du&%9 z{89;=Rf^+EVRb1~mVzne*=2lQnKETKzl>(}<8@`Ksvqttqp{^sQ>GS|Lwy--Er%mz zDp}4O$~eEjdaH~DroFXHjqI<>%BX*T+F7dH{nZ1dR9SAg1Xq{q=S%qda!M2{s~qnr zrnmdSA4NE%AEy_w(DGA-94LcD1?r(v{x;wIRU$!S%T+@4x%Px&-I=3j6q&YcnqR1D zf@(zpZwt^{`LH%iEzg4mne<#PPRmd;a=0*^&&tNiG{_9{n?5+41($m9%}h+D@}(KD z#*OUfi(R}r4cna{hm%DPZ1ms&3!YAe-xR02c`B;+QdAq;CpgWsWPNK{xrWAQ`-`M> z-t>hDJYTdly|jhYGd=1u!=*9WpM-xR>ZSxd7^bFPE()o~deq)7a>ZzIr+PPnmvzt? zVM(g?7={JT~k zYJlz<+F1`n`%diqKs8p?;-6LAQ^RFds-y;9tu#}rwWm_8sIr$Ghnh-DpxN=2_MQs$ z>2bB7g36A=MHOmw1?N@p*b0?6235zX=@=|OrsU6Q$0&RZ2ONWp3U(aBaTO3d%CjmU zdQ|;Vfq0BEk8|-coO2v6KE}<*X~8kLw^HprhVe=oTmdVp)Y1wXU(L?rR=65pI-dBt zhVv^^=GVgd%Ea|`aCen;c0H6=(})Iatmcy%>8BcfN|Rn$OJ_FQ&x*#U#d@?J9&4qC z8~D98c&ZU)&c37xT%Gh;GoRO`ceTi9z$98}pS0B4Re8j|yMrEyTAz2S?J*PTqW-<= z%n;6t^Q&Q~OmIVlr4~3VrrtC5+daf&*}Zr(7&%|9N3|h|MViYDKW4!TguCTEz%U?% zE9HacOcwiCt3ac&x+`D7D`&u@fbFLy6vBLjRV~yCv#i3Eo^{wwG|A#QLEG ze<`+KFX1bT^_?YHQ$#~b;PxUsUd)FJ;l*NgULg-DHXjz?`XX)T!+Aw?em?(Es21j_ zQH8WVm);g6J_qCZl#v6I^VRTdUXjOV1(lG!mj{e57p}>&#^*@4-@Y{)rex^(K{z*^ z-U{F;e)wM&6{e~0GnGhke$L=p5B@B*Ln;f;@SYn!OQXkKxXP!mOo4@78sy}MJir!S zn+p3iPjutw3d>#mEV7k?*8w&<_*CZ27D{^WGtHegzoc+)5*|SMA)%&%{vd9~FfHlT z5>vw~2L% zpp8#x!db2QU?W6Y?8S{dw?$vlh-od9BPDz@b~NB*iP<*vCBMFH;IEtT(*`xW2}Cb5 zu8F^FfXpWKXM^f$G!+fzV57Dg^_E5+(a3)_vSe&GHLA6ZxWCcF8lkDtn%u0(B5qAZ-N;u$)aX%X|ZND%a24Go55;>{w?@+n|i55JRYXE1&_9? z`&(gt2Q;?A@J@-hON18N+i*n}&uJIP7E?PcUms#*?+mH2oz}829qBYzN8stc)}8C>KKRt9}n5OnZRao_p8sMATr5)Qd{Y|EOjn|S zcqH9yOXFEmWv7Xt&kXddJJPMmels=QzRz!+m97{0?Lq10J-E=n_R`q7c5=lSV3A4!&Wwhu0n z@9D!qe(R7|KxFfR7muW&WP86z!=oO4CXJu-z@>8f^9*j8gL=U{;G)Gctpi?hQ)f?nD zm1?Ft@R(b?H2Az57FjgJ&HXIg<-%VzJnVvLnzLNgsnmBV`XxnEQv~!Arb7LJBpsOR z5r;Z4A*7rG-T=780jB}PE!fZSngz3&2V0QMYJ-L!h^A`1mQ;%}#?VvB`oLhOvM(^O z8m&$nMx$9_^Jc&^ZFK`ci}aM3<(>I7>$8%W&bEwe-y{8YLXRXCPWetk z*yiRqKWyt@TxpxO^qSX_>REAVCe7$x`@4kd?2*F*eA>f@;(S{V-xpV9JqqHcB4(EN z>UUy}p}llNEFn(6(wO7w9;k`hT`^uA)i1^H{wNKM!Kf(y9c7B}Em5^Cf+}iOM)<>s zo)JMQ4Ni}6yHv6fcs)!4j!q2YPhoBifuQWGLXuwRiv=+a1ITy-NLFtr%{J!CZ8Zag zxdkV}--bUzLBHU91!prhD|7%Y*0crm2#M7r9kA$Xg;D^PYwG93cCEKK=|{`HU)qKa zXTU|5IpaULurS4Wof{fbY}*a%T3n&*-kq*?rkh7I`1}kl@%CRb==)3=Jdhy=jE`7ttzvzD?>e;4KtC_gmfA-@w0W04Rzh;?-(jb_n{_?>cndJ4s+6;BM7uwTF^o9c@Q=bY`{Ty<` zlWAP!hIf4W92flHwQo%kgNpUE1mRQ7a)+vLOH+j_T=;_)`LOv@;U0MkApPkudq90{ zseR0EYu-=zLSL?j??yOa!zI#GOyWt5`x5LW-YZEE8~66|<|OZxcVj{%c=$pb4n_I) zUaXA3`90JaRzqSc8nS&+wnA1c%(>lmRY;HMvi5Y_mv)*zyR3&h^sk-vo9*_G9ePWf z^=mtuR{O6u9Mfv;Yvm_fOiK%FZWap-6g1=TW_Yy8T-OAL8?9xc*lo1;HsG%fy0C%9 zH1K`(YGXZZsiW!j)`&Wc)g?cu#dqr*rL}ZLompL@GU{+l4IQq9!`14GT7JHoUa7?~ z)hL;Fs)9!(7heUB*24d)`tt9~s^I-vTvP=zgL}COlC}I!6`Wp&zf{5eIY2Q~T1osX{<^oe%I6)G|F94Vy5g?vwux}*rYiU^BghK%-#VP7$v zQv#=yz@8F#p@c3k#cd_l#!`}2_24o!tkjw(pl>N{DTC`vA*G+Xp%hQ;XRavaDgE>r zrEpt6$|!}q`e8*$pR4D;B|NboTvh@({Ww&Nm6Gr+rnkx{qgY>1rj`^@T`6%P%q~^8 z7pjCf_X^C+63bnn4;I@O=F`c=)-!qVOp*ObuKKf3Z_c5f0;ubzl={rN9~$mKzQV@WLF*)r z*Dr%5t!Pm?+mjY4ILG5US%j>DK zf!`3Et6sI$(!hHA;#zf0o#TfZv$ED6R%12QsBf$7Gi&htYW-2Qsjs4(YW-RjuB@U- zRXm^yq=EKlrK+ujyDQDcN+_+gzN_T=4jvHS!Ib_OTttVA-L$!Ic67Q^0J(V1)fm^H8qFO#&Wro(FT)Btp zxVsvb)#H*H5!2D>wW@!k?x>|?qgh*r6-{bRJ#TL2$ql%^1x{?_A6g;U1V6Q*s~I=8 z%K?iHbSP)5?(F3BHskGv{_Sc+2*-Eu)nUHA6Bb0^xi0uVifj8yEv^VrX)k0&^fht3 zIBJ$9NOU^8lWJoR`3yPYY7*gv3ArTUrKI{3V5iMVge(H_$zR2AkA-sZd&j{C5Vkup zS3_?KTxmgx8|3YARx1DIgd2szO@Y~7yU-0U_?+jY!jiOvOqX8sJD&E!%jxEIA3U3Z zAEv>*(%JUQM2tU92MLtDn*lumTAT^%gX*Cycp{rF4#0^yP!xoHIjT9x59ZS9Y-Q!) zbvd*+4@B7L&gYMEc}_l_k%!0g;g38XUBKh>aY2FlIv+L_n4AJK1=hm_dPt$Yp@1$b z)K($fP)Kr_-&Tk-3hBl|{!gL0tWd2gq>+W@qeA5=)E^Y`!2()Z2=5etB-5uBs4EHq z3+$3Y@pn0D3*e0W|6!oqwwH5YU8;oTg5JCBVhtn>8LYri$V>}#hxyWo~~bxh8#Z6uPYrEPeugGRN% z9Ua)v3h{P$rxjjr=j&VHjCLH*3iWLeYk@b~ct;CdDOvIsankZzEmYHrOIpV|TT!?wPD5j8$MLrqeUN}DJ^G>~*Y}vtBs|rtUbitb z&Sw}9U2uiraS3>aS#a|GfA+T6_i zuhtzxQ(NXSz*v*JoNjaD`Ck0O4G#%%=jIh&K0Q_c7dvxjuc92M79S ziHC>#)Ort$_EDn;&hTNnL`!^dsuxc6@l{?tQG8imD)G^)UdhtpXI>KD?gp=F_X_Av z`@C4^RX=+nJd$ilk}wbN5+saNlJt2thJ!!0#CUhCEqypS(h zU@sqXDdQ2x6d&}MDK7Zhqx~*i=rLPT_y&)DJ_Sd3%-9q{kB&Ok?o{)+lUJpxTb+1U zD(5(Pcq;C2a73xjdof*tk2+i6qaB!_!GMI1V!B-Pa5AMA^{`DnTdr z;`4E+>gjuaz1pJ|_L?($Bm=I)G4)CheH`QT9=tZjug4%gret3KPn158OiEOpD8bt( zeG5&2=P6E@w*W1ZpVg@>S?EfF!b+G)50`eZm?mstb-4Sd0&U_AA#adTO77CJ01T- z?7uth;;2>LrJjtM1zm7Fs>5A$Zp_@#t-p$?%5Ey_A;Ayc=u!0{Nbl|Q^1aeaRz%Qx zEz1s8#O?7>DoN*({OyJB@Ay8b|gUsDf-=ps17WsKT9~*Ju!r?sN-YQS5f$gIfRMpedGppHv49 zU7UjXPTrYfj6i@ct13mE=(hiG(IL0~(5;?NrFp4ls0VNKSbIHuy4RlN#SEVn^l_cf z{>q2nrCArJ@jSm>nWiSC>xca0%OKm25`ljqonOdAR|cHXC$U$JStwqZ#Q}IA(>f_g zM>3NegVtGD*45eeyIE9~t$VZZ)*QYl07r9pSpX*Is)GUkCYREKn3<=}3&LG_{6LVu z%0n5`NAl>4AP>z~e+KcIeBKu1C-Om%;AQ!^IcUG1&p!kmAIZrfm|T^QPY10R^J!|3 z?#);If^begHw4h1FOz!Sm50*;upo~p3rFTD;r93B(ivHLMy}eHX@_!nN~Sd{2li%| z=4_lKWO6qBm`>jZb!oct2hB5nx;~%|rKu0HcyJn3NVz2U$xQsw3uDAnB+bKgkXLWE zAFodp@g^;BqY(A~bMbO7ZBK!v9@XpwnZHXr=5eGJ{X41=$7ZK>emIGos`iD*_|q-1J3Rs)ef`U zm9wo67x%StM=O-J;OJHu)65H6@CI?wG}8->FtJ(v(m<=5qzYDfO?-Aezt*VVsDs=_ zJ5;MyH(1x#n(+;0ca5s9$0;>^8TpE8KChls%TlANvTp_*Qx9(I$TF5S1Dh;y0(fY*VB?Je6wEdtAfsY>R-*5 zH>mm5>bC}JuclKQ)g1yEHk#%dIKRo7TT4fq?A$u*>1OM%y5tEh_G9&qD)H?%*#B(> zXQL8nXGNnNjrwH!86EI>Glo0({T4Xdi4sHJ)&-xn;osfxOFRD=f_)uoljuh}&7KGs zb?X|*EQBZ)BLSKGy=r{~PmD7~`?e39+ry$oUEGUr*wROZ-wh5v z_F0R4(o&XjV3 zE1RFrwbtd}oq0yQvS;V(j64n&n00w@tUz6uk1GmkUp}8xq^~N#h9Y}Q0Y6pjJf#p) zO5#fjabAg|rjR?tcUJ^cO5x@r{J0dC6md%_e^CVe%HS`l{mWo$kv*dfHWoP_Efcd` zVpbWfD6;M=#S@dj< z-khlyWYhi(GcPFEt$H+|L_U0r0EB6Db|(Jm)1?`*{K7>1yxgN?IPzF3$g6sln=kkB zaF<9$(3Qg5+rs`>L;BUZ`vwc1w=M{7wwqw4UqYBjo!udAj< z>eQ>%_uL7?-3N~LLBBY;77sPhmRh*A5wED@Xd~3t;nF6UC)92; z3~pdShz~cYcUxe2qq(sauW8bQ+Gs#CMccI93_IHGLoNEV4(qqp4ahrT*wuk57D!uq`~yhOnGZW-IbPa(cMhTFqxS`XDl=%!wzDBctAV-X)q;2FK} ze3Gw;v+S#SDj`#N`ft*#CH04G{lZXd?0+QoE}|s4TERY~_#Ct2_&_#_c`PvmepJpCKtA6^MYJ>B^##Z!ui>d zlMAsR@6N$@gKB;bPY9B@_znj2wrsd7U^}z%^(<>_kk@D0GXhwdVJ*p`c)D4asWPP1 zpF!nfnMhZsq(QGACJN){Hy6lSpESo69xC-Eu1b|grQH$P?J(%mS|v|@U+&~JK!Z{&#>?<>~jQt4zy6IzZl;|t{};s0U18PSZ*Lrbcu~3 zGJ0A95k}mw@VqUVcU+&u)8%Uke!f>@*1`$;`!?3+ut1wh_lQ^8C-IyDO+z^}`hVw!&B`kU?o*RZ=L%2?y zr!pgx;#c6Vi2RkFjF2o$`8Oh^t{E2P_K23`>W6&P6bPwF$Bk-pf z-Sug`{B$oJ=!J|pJQc?^aXcZxXD8@r0&5e3gz2ZWp z*>v_bQ`H*AMj+Yx^fd}ChR-VAi*SiXIc?@!e4)lB3mg`I>ww=aeAWq%J0!f^CwB_C zpvB2YT=;$pzVD_hU3_b*vfS9u!(X|nLI{>ry+V9V9($6H)_5FApSsYSl#Na`Uh5J+ z&h^>te)6X2Md|9TG%CrUQomX!SBjs;WD4Mozh$Zw=`c2noEf|>OFf*SN&~zv!z>8E z$V}ZBfQ6YfF$f1UVQCP`vec0v-kN0>WYelF>#A(MD~n#pwi8*fF54=V(NDG+7cfoP zO0Kwsw3`B~a^UU&>Kwc~0Li}3i1rPy48Y!O9v9$s(l-v^!fe4x@#<{cokhjj@ZT&| z73ABp=#3!u&%%p>AScF<@S>SQ#S2u=Ck3cl;MFYgN71EOoR@(IGT{qZ;gkvE`c^LD zMoH6W@P&T-M)1xwDoCfZ#H#AoKlu1q8V&OCs5DsNRf~N{9zN=&TRl9;Yi&%`4|Ow*K}@&y;PI%L*h7U;y&|S>ikOb5`5>$>mUnN+{xkxk zLXOl3Ki_TNFMi-Iy*~sebs0&PE$Gz$>sIw0rcm|=b?BvC_(i*MbwO^se!f$b?}VLT zx8e&OFsqeQJ0R48E81aJ3zWBmJU+e`7^WFSkdoI74XtWj6THyM7dOG6R`IBSG`N;G z!s9J)W+Mz~f$jzgzrZIAyu2CiXi!rmQ`tb7&CpSghnpm)2_H4l%k}(7le(*3UC>15 z)l*56lBcR^q^x?VY*bb~|J_JEb!uIsiqx6^Hd3TcFK<-II$GRFDfMbmqsp(Rm*ja} zkINd>W%Vro=AnB0vQfQNFUdICT+hcEm0horjdWTA6*Z~Z4S0SN{n)?{2_VvlA2!kD zjVurS)r~69Ow?$mG^-n%w1mt4Xfl<}YG|__)v!=?MYF)AmWg~%eF|OA_h-KQ~uY(r^OOa_p0ug zB^|kSg4rZ+b}zbPe$~U^KW)Dtx+f`n; zEL9&7U!_ORfpE5034AivXV$0Vs5I;A3?AmUKgv{t)AfohmRrsI00%SGgF*E6g}8yU z)R{Tl6`=B5xxmrNGuyMFD$n{M2Y$-8-^qoS3#@s0d|jb^Q@$EhWQ{MNwjz^Rh--^g zLm|v4;jfFJs1)WF!?seG(6^-m5+xAqhhLV$m;G2WZfBRHOO{rY(f-<7&*vP4}{wXsiA{-(ICEi zkXkbc-WxNc@V50Wb8rw#ULwXFup#>)`Q`}K`J%~CJusQgIEoM?+2-0 z2Ey}$=&pfq{vhR+)6YPDX8?RWkOvNcvj?h=`oq5iDA*sS4^VT6&BLrA`{8C4i#DzdC9E>$zO7< zuk)R+=7^;;acwr=lOnd7zARH4RL^JXH)MBhhMAbfoBgUPL*0}{kIInUs~mnM zw*SRG6Lpi@s~>dfd8t(Aw7Xq+rNg>D1=ef&%>n%s6j?kE@KL3zh_`}~u5TgBvkzw& zYKZe!NgUe?i8w5YsWW@IDq^0C;i+N0DFXlLHtsMV?bMfc?;!$Kc@#dg&;2 zAH@@o=qHZgzC*VAFfBM}eSA=zd%&J_fIRyxdmmQ)Yrg*%Htbc;?1lgBp)2>m$GdUV zZuoo`57@=O?^OMEs+t`%Y=_C*p(bs&uG~(uw%PA(Q(tVgU>o&pF*CQSE4QeQE%e)F zerk&vx0#E!(3VYV_hxm^CR)0g3O1>`HmmA?c+zJ2{vSAJvwH6zn7o-*{R1;Lzi@MKd^r@;U*ZkMP0OsU)(|;ituZT%GylNZ>85ZL&-KZXp7pmjdpA?3%28bw(4m+ zaLP7w+D;n2T@Bo&N_W8E-Bh|0PT!+W-No1L<>|ZO<$vMjJ+ONp{<{~;4$$CzFz=vx zbw6|;5)BvMe*|7Sggr;0_y{bifIp7X$Vzyy!m6u+6Dt$%)<9HZ!gZ3Ax6f#R&+C+o z_Cz-nZ-&K9a(ic4w{fgpFKdIto%Z`3SkZ0$)J64Sd%qYzqE;fpu3o#m2TBvx6>%7A z+w+p5&5_-w9j z0dUVi_0=HA9Za)^z)wT)#Gx>GC>%Hu_MQk24ugw^fju0*8P1Q6AkPS_8>z1v2@_AX z7oP$zp62-ORQO|*z4bJ19IbbcLi=>{$7p$HTOXeetz(i8p8*@kI){znm&PUbkHPWd z9ruofqvK8MSh#(Hx^^5Kp1|LX4KHmH! zt>v@@*Q(~w5fo>S?_DERUe{P;9AcO=|+su?u`Qclse!{NOV^vp0Aax(f) z;tz-MlA+)`N$C^RJwwgigUwGv^xp%u8AKTajNI|ADp%L{SFe=u6aDDd5?ES_wMFWk zVt_*PP9X>K^~!uK&owXQ@(I~`PPT-A=(+$6&Qucwhfb$_ks77-?Zk9?VY5fZCAi8B zH7Rs|3hZ*|i4tqlwh)d2-PM48oy~Vd&r7t{R*xm=_5=wUcV;i%*~4WqzBLN&2;LRO zXg5F5O^u!SOsA@9=hxe*x)r}`)osmkoUpl(Jxx|Y1D@MppIyfb>MW^__t%)OtIV)! zOdhwESHhHvq;(v=J8C_53ePQ>$v(FC z@XUYV&~A0pUi@>HxnU2j-)YU9Vcx{U&qL zR@}BpU%Zt`*uVVO9_Ok1)UmyZbN3Vf z>$v5B8ouBD&q11TK>v71tvg7e!(6eo?WZbYN4Z!-mHUr8q^65s0&@&vfYLomB5ME*DbIh45&x`cDzu&_~Y0Sh?qvfUgYxEx`k2Fu#rOUR}SXW2lDE{c-BDpVlYn}h@TCHQ3Gk!VEKmXxxtV!kgpdV-vAgi zn7O@rW>0W5ni&KiK14uWKVjt<1N{b9vGnBE^w8pyrn>X!lddbyEJ7K6(5#{TNN zel(#!jO_>2s0f1dSf9$lSlzRp!I=BR&j`1@?`$cE}5 zOJ~C^TJIo9kZ^cFU77_Gvq(1cUXrO6iEtx>KTOA4)8S`7&+x-;!KBlm-UpBPpv_A% zMhScLqaN-}HM3KJ-TF~CT5eHuklTe1r)Xaa&vcqhCrXPW&jI&YTw;NUy9aByOX0~1 z?m#{R;SRv_fNy8IjMW{aZXmkT(0xYTDlTrDuTR>q%6`3sV|7AJkH>$F)3jdK!CrNJ zPp^!YZi%I2^x(bG)ZWQsx>Z)Ev>)lz z4*0SYr?qoq2h455vJUv9m2YT=LoFcr7g-!HjKQR4GeWR|COyA}|7|pfo3X4>jcSJ3 z4Iukuch!^KXpOAbcQ+8;YGGfMI=>d5tm3X38d`-P)aaT@xVFZAuafg?95X7hx;iNag|ohzaBSf)v)8Z6{yC#<91m!>q=~w4fNJh zyoO`}-*dHkUmd2`naTCMx=!t=M;Uos(Lhc0SSig|S!&Q|&TmwnCK(mer%n8Ole)Ya z7Bq9R8K<TDR3R7nG)ZOUL6Wz-PBQN$CGPGg*|)M)X2X&#O6yalH#c*D^Ly?o}R(H8uYqDDJl ztBa+vbHEKJrRX6(Nn8ej-9P_|oKh}6*TRLy`!4Da-fg1js z$*=g~*(| j_1Y#0)+;sAQA|*>p6MHf5_1v*ZG#TLW}ft_ZPpB$xIC%{zJOnQVP# zJ`KpR59Oby+@o^3C2nzB5lhIGz*N=bRO8&HP9_>IN3{jFrX(t~6wZ!g z3SMxS!-%h2a0Ga@)<+qCQg#K=R@8MyRRXoz5Mk&^iW*!wk`i2^oP<5Ws9|w^gH0Dm z%Q30$lC2X7S`>rrarLbvm3pZSK+C1I` z--hu(C%VHVd8OMz>Z1$(Y=du`&8}AXsM%UAs?ug# zx+1HZt-D+KgJ%1xR{W+}U)+ka$nSzy)7*>~w^|u3d{wJGu|>SudUgvx(@I~psP|e0 ztTG#0@yu2oZiS_y)NYdyrM^YB3AE9>ZM?b->)X)Z&JwnIvRysf4(;tm;#aqI=;0l3 zyn|lu;Ojau)S)Un;o45Ry^H_uRP9|Ts|V(Yim*%cgDj1&H$u3gTMY?wMu>h5 zBNndGC_~sqn%}YTaV=g=yj{~Y%Uq(>NK22>lxk6)#%hh?LlFF41U4^g*eGz9=G96d zPh6-VRr3r5$7Ob};2Q-)m3)%jif&NYhUzrMJCVKeC6rf2twi-F8qqQR7u6l8o<_J7 z`9`GEQ7{1AA7$Z=$&@HCYKMq?Kz!=Z45|}Yu19gb?(P$4(I&t;P=5gn2rtlSi$uu) z!vH&g1VTFiDg#BdL;X=4jA}f}#y_5pJQQILs!7Nzk!B)pkjosQ6=4HHzTyt)>MK>I z_&G(_C?zPuazzQnVip~zW$_?AtA$urTQz>DIcRZ*7SBIUut2u>i7GJ7ApjNJ|L=7cKz)Y#on-8 zQQ>02hKkn)*n6R;H%RZ(XTG!dzjN1O&0=MRtc1**IcJ~ueV$i+e58*vGVwhh=~haY zuhvYwDHD&&f}NT0NtVpbf{JW4i*=9jDD&u8UwnAN0PoubaI4;MW<%gGY z+zg;1rugki0lU~wD+10MzcdBhW|kJT)4nLCc4V?!^VL5N|j6j_naKg2{?&tqtu#5v)x1eRFv)c zBS%(br55CjL1ll>#^sszkZex*=-n*mLZA4vlG^pVE;Fq%gTMEsu1}|YpYyd>)R*CS zWkot2nP#?n`5up(=B3XaXYVxbH1;eH6&S_K$N>ZjmN^gMQ-c2k_!;3vf$abvF|-N% zXhpFPJCsbOgR&I&x)e@gUyAi9)s<8%iL@r9AddBMtctNhxE@+~iE%wYN9%`XWny8=^?r7q9 zt@3IU-O);aH1VcZ_BNZmHeAqbuWo}knrUmBxXp4zJ1uUJP3m83F~@e8i(B1>4m;ZF zxosCNZ*!}6!(Q#QWjE|@m*t(fvIG9rrQk=H&@FrKMz@>tIz^FO@lN@<7kawPmwnjL z?S9tJyL+7f4$x>Xe>cdUe%Ure)dNO5X!8d(0%xuta^{5Wo5QR$s%CxnjDRAhf6&lu zSZoYG(jcD(SG4__)LMbNAq8s_9$E*)O*8aD%Nx;sBp&ht4BYqK)b{V7{2vK=*qs$cb>0RHW#rMWUL zmsjTLHimx7m-YEFP=LvTv5V||ig-dXUR6xG5qc>o`2a zt*(*pCdpi-L{5^gC-AO`wBH20V4_a=;qO|?883U)vZiGotD*JPR5w9vm0L0a_OJ3R z91qu2rtTUiFH|@ytCb9CKd+L%%IK#`Xf5SmE13WJ3+v&=;~P@d`fv!Oo2 zS)U2dr`xl9u)s^4j_GOgs#i8RpwZTw4Kz41gXk6ms`@P?d`-+J0H-l86bM)tvGTk6 z;9Pt(X%!iIY{IEenC!TFZ=AP8&CD45JHibSygH0eg!!Nl92qhNss|mlL&Ngzu=!_* zmJQiY2l>=NdSd|9zVvKA=-cP=K5p%mM|&OZls(zwe%h@y7V};gecZ)wck&;d_~C9E z*$v<9lJecKwF4IJg3)$WqU&i9Hn-F9ZBo(B54O?`ZSZ@GY;L8}7C4~Qy}lXVZSibt zg4!1M&?Z^aY(8tGy_?;=8~N8J=i3IlqRBn2f%BT2cs>2tXjj(rJ&klmJss7^MfF_N zXj9t46qWSjjUcG@=PZ>kTQUfU3jpLt1@}IL}4xX;EGkOS>Tk>*I-M z;`nRA`$>YElF4mJ6HYnGqt38gVpS=Q2eIrcq8_@1K=%SHM*HSiz`&>m`gx;~NP1tR z1s?4=lFC?iq}hYL*y}Zm(m9pR*JV(a4KFg*(bJS(bbNtSa zewq_V{Tz^4xt^bLWm2BIDbG~o)93kaR)MT3aN-5{e4%YFggcAq+afu?SgR;_aFA~b zN?{2dTSDC>TwKcQN~xt3ZYzV8Ww?JipH(iSO_}dK~^VPRDL==y*C%M_A*n-tm=9F#ZYne-rGL6J+}YvuOfN zuCduQd|i!mat(b{<1Vk^?i#bH21{zWw?+=BrR-Wfx7OCw!qQr2POZ++-2H0ho?2($ zTDqgwPOG(7)lyNdb80O|YuvqR>8~2&tL0Z}czX?9s3e>kF0bKJYUr;C=&9kGC*XS% zsCWV&JAvOFPp#u=-|=$wc>Z!6jEtjw#=%wN?5b*Ls&;bpr>J(XuA_*9$g-6+0&je{fF}zXCCl~SCMRZc3 z^IjnzQQ)pBpuLs%tH2Fq|LT@E09WTigP%?ez=t_J#SiyngJjEbN(0Nn{7m~wCTz_x zN*I1BohN3167oB}A|6l@n5+ zY^#w3e4Au_a$b?ZxiQI&OG5;{P&{22E>`EQhmn&giLc&U+w>h&UkOY5P&o=&P0Z#_S;lMYjf z%nrVHC-1QX|K34QZ-*&b9@r+2ZpT};QED65t$gD)d3-C`tu%cr>m9+iEi`MZEZ@R) zTj-Q6_{T(boa+iJsG+_$$n3%7czwz>b^ntEfKGkcpeXS@Am8*ko@M{LJCci^t= zFn1?Eu|qUDcg#-stB(D3^g%s!)Y%mcys6%Kx{=;*aG!1BHyh1c&G?@t{<;M}YsQXN z{;LJ@+9}#9D&44Urzdvd`5NWjjc@J3y}EdKw>;I2M|PoJ_Gu3JvOdY`rDoM|_t~=s zIn-}jhH%NCy=+7xLlhsSdq(83Fb6c@AEmd#xG}~DMdiE%Hpb9s2`Is?00UT-gdz1ln%^P?wP0BpDe>(h_2F)3GO}gBfDFr?%&&K~|+D~(MQ8pbP zpm+|b!~MwsUzU%xd1jyhKGi{S5g$|tyNk`HB0Rms9vI{erRL)j8dq*B%iz`ub6>gq zSZSLpAgkK!QH4j2v$s^+o5s^;c`AQ4O`e_xXHJJBr_0xg_L;D97CbN$&zS`iXNq^0d^Q7D&BXm@@E$Yez3KGP49cI*RWo?;G`f2_uA9n# zPlLfJSU63}r{J+u>EOwH-4wfUl6iEpIdh`>!X)`ut@F}EnO|d<*V5DpbW@FM#=|KS z(zaCdgz@eRRZd?u{;M*j#%gbc=d4Qpu*`KT=#)~kx=i|md~hk;U5tMRF}n!PEas;R zpsCOlBD)18oalI}TiEL1>xRJlEBT!m-^ z8$x3+hl@w0XB5K2boB^mU^O}flLzS`t-1Ac)d1es2OIl%W-l%7HG|!@w8wth1K0uv-!1& zmp0kVCU~!r&T6EQ2KlVP9^OFJ4bEHj?z8o&K)oke?>tuLuBo$mb>_%A^Y%_2-pR-B zgts-@x&yA+X}{huILLoAHMh4z$Q~s^o5=>)Py(t@fmL^FbT!uND4wn7T`z z?cnO&^vo_()oEYYZO3&vZ+6nOZg*Xm?Av30?S|ufxuXZPx9IfYo&Bi!;g<*agaPyQ zAl)+Pwhh@ghn(~gXN$_PMy(lzMIqWJg!hN}vM|3N!IvYZAqsy+ttXBcH?tGGSHdnz zj=50pP4P1+`yW^1!SuV8J_`d31tOUM`vFZtI1}wb1UD0%tiWv}7dY^iI#@NH_Elu1v?ZHn=g7(&<{Vh; z$DjN#H2@CqsThNIzp#2it*-Rd81gANZDD8QY=+L*f)qL2jOz%W(47> zAiWlZkAq|Aj9-K1*B~?o-OWMh3_9C_dg5^Z3PMNF`926cgZ9IqUPmehQ{D-R;xd*6 z;e?=aGO;R%bA#Md44R1euvmU6mTT3*Q>+SaKC&2Eib$)zPZaUmBH6Eq&MeYM6=MLKXK=a{--Dz&8|db3UbO3R**znk&wuntZx%tn9!UdAN5TJ(dgq&6Vt2 zI6$eG0Z_|ub^!JZ@FRZs)UT=wnC-`Va`5dOPG-xv99)tO3g7F?fm5&-dZEKKv$ww`AbH8RobQ{xIEcOjk7_?UxSkc=4tLKVj4VfDW_8{ve_!7;l z2uC9Cg|JP_<9gEvcm+^Q#0&h0Rs}^%srFbM!m~EQ>_X<}*%`FvFt(3c*6QC3i?3Mx z%jM&&EOn7xD0A^+7qvTfnakItV4Q2pQ`nH=Uz7Iv6yA~aoSKqZ$z)LqcPG+R`}In~ zeMyG^2|Pau0d@E$<@Y!bBG(8IME44nNE2Q}+qD>`!D+04)s0Chc3{H+fOH`&r zV11O7WA;Q;n!|Wi6uu105m9(i&lFLuGO@yNP7C9aXv@-s>LNYoE z>q4lF$bUlOXx%$R`gMxJTpglA!nkKhE)B!cA$TSX=Y?QX7;X#UXc%4$*$G;32svkJ z2|DCH9Z^WK`6~j`!kiU_Gs1LS6dw-T}-kBNZ2in@sxHMUr#k_*;^$i1UmTe;21`Qe!08 zcuF2h-~~!XPrz?3pPGcZmNq5j4Xd9_v*-`6|J$!8bPoH^I zfF-qQc%6gKDMH`TH)&p?2z0L#@o>F2bz>UMPxnOA23Kg0uki64}2yx1=@a``ep9+rz2`(c49di`UO zgA@I9PA(m+wZvSW><5LP=lbb{Tn^>9hvedx9MAMzc|XU^%cX}DR1)B`)k+qi89BH% zpbMaSjq&?zb8-M4&9=%TJt13Fzxor&JAVE(3$O6g16f?_w+CdIrW`YzX`jsD*E3b= zNGD~2=2a9d^ISHr_Tja`km}OqgiN?O9XouW2q_Ie z=)gb2r^A1KUZYlNRFeU>rpelL2&BQjYD3fFfENz*z>!}0TLX+~bg2Ui(l}{wn+G2^ zV-Ab)`h0M-de3J$csxf-P2_WVp*}9960;ylv?_1*}R zVlpk3dOHTKQO|X;F%9?J7%Yeq#V|7}zeo9(h`bb~Wf8hEYEOvR1EZ!O;^ZoRBy2k) zvL;L$B6M?@UyRtJ!gOQADGT$$h#d*h>z0|7l#nu8P>%Lt_Z7W3>Jm)&rv)k%wLVl0b!-0!OSrKTlFI0F|JxkSRNh4Kp5^H zh4e7oHOd%<+sDe?aO7<+W$A-H9fBO(1bL__*H7*iwgC?`Vv=qTCH*w>*jzc$L= zFugNM{;;yvb$x?xM|D_)+5w*$X8lg~37gO;9v-&Zc3BXn5*50IVP*)f4fDJZ-W?{T zvOJ~znvlv+_>mCmvbHM3e}&zRA*V}S=b;pb!G@fYh?IxjIT1QI>@18Z7>BQk(7j=u zd$StrK8nzvVc8ntNLcA=RIPuatT>mWqI7G7mgvALBCkbhM+E9so8O5fd?H;YsSB=AaIbt27M9N1zsRbU+OG|6@&}(U_C22g>YxK70zj}Y9)Y){H zt*d1^{*=y_WXQQ0sL}dp20WyU8lMzq;^a(Pohd3+pQC(+EciZ)hqK`1Z1YGqG-tcj zIdXZ9XMK(d=OmBwyLb3KtqM>G*rfq}AV8j6EsyilddrqeRe9vevupC~U3q49zKQ0^ zx_n-oFMAbWUA|dY07n$0rWdMi(s`p${DquXMAsJ5-9`L!p>!3IR&S0g=4*=J?PB_( zNFc~sWIH`bhiEe{$Tt^LUy#-o^VAZq8!Nyf24O`Bj@R@>2_F!o{t{XcWM3(t8N}LB zI4=l$m(tlmIj~d~21&0W4hix;8tf0!q*C?-*wC2(W0yi@{v7t@6$ zFi^x*CGbiSZ4biyB73jymJ6LpLAbpz^=&cu3e!$2hNlaX?M0AV;JKs-AIZ0kg&fPH z6AS5rJpQymHs(@M0hH$QRrz`?NMGv*{i64eI%GI1m*@OX)_g@ayzhq1sV zExOn$qXT?6DNBknWH0^Iq~k$qdH1du0d|e}% zdKlNpFX?Qpfex*+D;s2Jr@5g)kH&mb11{Z(`#12>J7rb_P2Wj-G)UP_dr$+E>@=r0 zK+R5jM*|+P)A^u*&)(_wH<%}OI&&NO&z2dqxwiZA%85;pTRys~NPVyP-wBQLwsIOSSky8+beA z>2@?-s9@^!ZdtR7ihJOP-7=#W`;BXIc(%i>+!)Eq?Ic>y! zc+kE+>ggUbL!s1(BYbGY`Fa#qMC~l4S;n;3h^HoGLQFnO;_A3^n?z+&_gVZX1%rw_ z(j^GsSC;P(7lFDSL=E7tIG{H{>1qS?=m}S&@=})$`jngJ!%s5cKbd@RCVR8#r!2ZO z2aeB?4SxB}55>87w6f6ictak4oKO1dP89IJ3uWIT<0+;k#rC40eIrO;l{kNth_B2J zmBPv8m{E>TRbZ*+tSW6)C55Y;swyrVXY;GgjPb3rc7o-+gfZwj7010R`!H_ng;r|_LK@Rlib>kK%13STk<_MC!; z&ydt)D42ntPsT0N;j+nm|8($8Hj}2qzbCn0OoPdjoWrKcTNB;Sr&8fWXTnszwbtG< z1vl5wKa;VlhI1#|^CsZYlbq+r!*vtg4dY;Wt9vOzy)dw*Ir9*bp0JIO7%lqZSelF~zhx+ih9=@m-9`2@Ndf>z^p3^Pm zojA3NLc4Hcr`^)Q({?)>)W*2W{iKZ-c9>6EacMh$(*m#Q;-JvER){nyo({$}$)XlK zy%FDUmK6<>*$ln)q!{@l>$$5D-mk;U8gYD`3^m9bJMn=A*kdP5Y=B>Pz(4hH{SJAk z9%^^svGuTfyA;>M$J=S74wi4{ZFRVGJN{V5mu{C$b>_0|_)DF8{dQ=m^E|p85_PE$ zx5K!4r+xdF|GjDlJ)^R@9o$e)8+Op_2Cmx4k2T<9J2BD#rcN$x5urc8HdYKxCMg>xOL<*M?ASIDdrU6*b#NV0%RJV~`gk?bM$bx2g_& zBw-#%(oacwC&lQ>KQ10*DQ@K^wiSXOh?xhlTc;c-B_t0J9dBrrac^_%M#u9XkJI3B z|I!Xu8bx#yk`6@~tnX!e`l!Z-$7PE0na|6DJ+tKMY}_*&Z_eQvIdHq*)cWPtfGrB3 zR)9^eqE@9hmru&a-}B7e0{Krq7w83F0Spwv35B$w2#SjAL&dnWh>i>LGsTcrg2x2q z^AhdC<0Yk_B)ar6IIt8~mBE%$-mhFPEOUM=r~b0kF%^7Ox$|R%cKYnTm2z4It*Vrb zV`&7MP>B~+vG)5ut)f3GnX9Cz${bn^XH@Ym)$mjmyi*O|R?+5a=&Rz9YMuFmZyeTC zQ^`2qtJC4ctd5&GG5T+e50CQis=1F~M+B}4LrRZ4At(yVYooHK%9lsXDWkS|*u81QIK$3s z!!muy{xl?K4pMXw9~+QKgYa!Xo--hBA3xtu2lbileSCMXThfQW_c#~!LV1sUzX!&8 zy9%=Cl11GxQ;C#a@?0mDb)lyd?(dXacSBgsnA%m@ZExNMUAqkJlEu61(;XD)YKg+qtUUT-a`Qw6VY4)!Y9c+RWK)aBrJTX_F&0w$(=YZKk!AyIS2J zTj~2&^I0peY2~%8D&WBPTX|V4u5UFDx5`hgT26%aR#K6T(~N!&oc7 z+9ng*OnV!i+h%99%WG|Pe>-&kFAP7oosZ~1-GHs@U`^>y-sPOtfvb0=e(L~TjgQ#H z>v!{yyUg*OuwXZLc2di3T-If8>clzSrl`yA>gKPy%&R?gWw)H!%auJ+)rSo|)Yk{E z^zxVeaIyB32Vl>Bxn>a324LY3v<~3D!?z<$=DTZC<$|4SLe?4lfKT#xq?;d^!NZ z(M(zCgCWf!WI|WAyqg7$I(5kg-S(`>kxv8gx}Wr=@l3$pkw^FCI*ao8$~<>Q0WQop zZUM|L;O`4T`z8+-K|`T3J>Wk@5-NtPit+UzObg2V5@-uzdkH*Q0ymYy+)}|Z*gl5t zgsaO0)WlH+OUvP&a%?Ie%cUP!!Pn`lzJeMnv?3=5R?5Umd8QIBtTgSF_>9VPtN4pb z=YlFzUumDJ;=xM#yb6<*ytPWD9@Jf>h+Q74!Zr!k-WpIvUyKG=uAa5~#i; z?gRRqu~pmKR{+9TKw76pT%W{EDe6tgH%W2hxG4bzariL~vtsgR3{H%aHsY5= z>_7xw3Ok+%{2X$tb-@`m^FlCZlrJBJr6Zd020bzTGAuL@6r zH&pg0MnD?6Io5@5bQ=v&UE6JM=rTujo5Q-errQ>FQC2sFJ8iN{>O0M-f`U7FxC_5k zSyh*O+X-pi@O!6}cSCb09@q_uPPnjJ*D-lqNeEr|UAMWlOSs$pxC`d>IMFVAtj8YG zt=UD=i~Bjf+|xbg4AqTXq*ruRRMby-FZ|Ib%X?v7KY07#tA2P;$zucP>zA(w;MsmU za*)Rj@IQm*(*e9_$URQc1Vc{upe!G@4-L`e5t^pR{So;@O^hX7 zS0?$D6rPsC`K|^Vp~p2}y6~9gD=f@pEMfSA@q30Vgs&2D05o3r3ebAs*=SEi{0^N_ zgoR|6k<=4b8@$NK2b!HTc#s2^I4V!)R)>!EI2v5}$&>uWgY(k7`=-ffX-N&VO!hin zuYJbLmwBCp7rytV7NuiZy64k$9bday8T4hkIaf_U8N4O~j?U19h#tzo**?251FrNr zu?%_LXSL|D*@vh2Tvt^fK2J?1yy~;_GvP}gUXTgfd~i!9^!oT=-R=9F=Q7Eg>AsT5 z{!F7I--1kjEt3l}VMQk8X3`Ux8pGzhGf8}SO(qZf;EYUa^~nL5@~aQ4G>q*7_JQJ$ z>U?sCkJkC<9G_M2-TppvwvUQ^Jl)5`8I;VxUo!ZI4ET2jJ(VF#Gk8%39hE`jGHftI zI@6urbd?di|4moSsd*%w=A_H%=^XY-Z91*@QphW}czL6ai@o%OR}ralmKQdvdDDyc zrBNb{k4&>arcq{^qX*KzJod6Qc-{m1rQx|A{UA^B*k%unI%b`Rzj63s4=s1_d=H=F z$UYvL?NFYF$zjcY)EoTGk&g|$?SKkd9&z9*<6Pyy@y1=?z$|0-aj?K}xx*;}RjPFo zjT+uew%O2kGWy&3C$OV$uo!V**f4pd%TTUI2l7(l;eU)&dFVT1YCZh1 zacezF=kU~eV3|oNuVaZZWgfFgg(;rY0S3IDvC2S}cC z_;iAs9GpzB(1EBDX&lj>g1RRkLHOIq38>k1%tg4=h+dmcGxV6YB*-2K_B}HCO?c3t^*`&QXPUT6=h|9_Z zu8QHL1RolccjKlhN_)laZBe^EMoN@AFeYC_?4~H59Wlp7$M8D;L}*nQ&x*)#Vc4yc znUE|A!^#lqdHbZ0JU(_)iQ_}+8iw_wu8K_;j5-rXP2Y%B2l2xrv}(jm8#)2vzcO=MbM10u2DK z3&E6OF4c8=7#|8_|1ieG%7wO9N8qOsrz?U7j;1b-^5>(TuBbU6RKGG3RIqBn$t@ z#A(?o6oap`;m~Xym+?rpY|C-p%)zt$sT2JwY4RvMZBf9!qL8Qn9GI(+DB6(=>vDAu zDP<}O$}{)m@%{O3a~}E%oPG1*kpim%Wh&J9IowpJtSV?PWMx<#RYb29!0IB|TmY;; zQX!mJj5=C>u~<$lg!*E*vJi`cbWb548?;Xp(k($+Q7A75;pIa4Z&02uG=By0u|jSf zn`y(YAYWLB8VEU}kQ;)j>O%TG=tTdAb^X48o(QI6qI8W%Ika7|SAmuAH02R|VkvO#IQ06Em^QFAw5XAZHydzfk{^xZqX|;8+c$AOFoxk6t%$;mn2kmFvZ&tjo7EBb8@&V!n~7nX z9+syXx;=x>2MDdd-F|KEGEU?!tM!a{3rYi}a9N(96CqOzXv= z&M^#^Y9ix3@YC3%e5K8_9+kpNdM|w0NhQ6qsZ$ei=I>5Crq|uo2^x))PI$bRtGeLx zUd?<$S1&B-l2R>fcEKrqpn$9=`=q#=H}}z5-Bj9d6^eC9zcbp6pY^*(^oVc3yw-yk z4{)kS7cM-n7shLoR0oNJuvZ_94#Hb~a-NFwlz%mZ&-dG-hPhzCY#MeH6MgWATRn&y zN6gwmH8%Z$?+Esf^1e}dHbmQ^cvzU1 z#8k#g1-kx6WuXcao&+!P8QFSi+Kvn4}L~`8Fx%T6i!8e#YZm z+{ln?d5OqQYbFA$WVa6RO7T2_G6zzJ69_nQQv8N}&&YE`7il`eNU?{eI|?>;wcdDl zn)%j)dwb>4H0kuhsa{x-J|;LgRwW4O63>8lGhmGmul3=-GI@_o=1il!g158mM_G13 zwz)Q&B8rR8k>_(vM-J@kA5*h!^P3X_qUtvrfb?ARPAb@@BEDD8kwxU@@!=(#6FPEU_Dl z;gJ#w>d3l8t_aGRrSN%>z9>ZrN=JTMo$Xx~Jt}pXs1>vGH_uXPhFT?r8 z_*N-yFH*w=pQpv`66(+~V+o&M2)_qudjZS~^85n)sF>c*=U_4W^XaxCyfTkB7sAF| zQ(FjuT=&`nUE7^c^YK-`JDSIJInLBP%*(Nhbe+#8O^GbYk~J#P%Y>g)x$DE$Y;{7} z(JYRodq@*0=}DimG`(p7AI(m4b24Oq-R`Et{IN*P7}+o8f#ZpF=XL@b-3lHL_G^Np zb%8=SoZ%7BD;~Z=dtR(?mNf9}_* zf~MH{oH3c5^SA;chTTmO`Dw%?qom=tIdOYs7;j9N?<4SelC{F=rtqFP9ByHE0v^?A zY6?^<_K6G1fvjd&tOpR$0}-XbScfks_Xq_+80T@X9PY7O((xm;+xVa&UFW)>N6{7P zTlDefY&<24d>X~fX60Mv`RU4BSsY;1xNOMP8jk4bcv}H2D!_q4ez_2(i0X>it4#PH z`AXo>5_U>SAuX{|`#>4DmN~DMtGUU(T_Gzf@PkTRTnTHcWJZ;|R1LjVbk8_=xth-& zkMqXSj0w;(jz=cQb>s298jO#JGi!Ot1aNE3t_kqeM0-??lue?QHMC-q4A!uBGR&^U zD<$@1 z#?|sAQ>eKH_MT#us}r5<>{%mkPqx2Ippz%#855*;lI$E0w@kv5#zTA}Xv^kGEf0=^ z&9$nelw0QkArTx#fqG`F0%#c{TR zS!(Puu^z&COe+9gSEh@6mXdF++>kV9x@MmQk0#wj44z1s@1i&}F3ThK@2H#;c9g8E zIm`)R$sDC^qtZLfkB-paLwNMCd^rf2L$G#0whZ8Z`suBHS=DE6?}N3y&e^^ARZr^h z9^TyT*}Ge3Q?8ntOS;S+op78gXm`{7yYZA=?vJ}*Nr#iaOI~j0%RBI&Hu$Ao{B5*n zJD%BUSGB>1EmYGc{uWr+X5>aDcTH2H}cob;5Oh> z&G=;lT-(fgEqF#Vo!bD%HS?hja7?pa;latxGOYnFZHB!X>OL`MXKCJqLDju$L6Y z6YjOXZrR*tlHIVrpA~$eYA_Y^JvInEeQ^7b^!4L4!x$cri$+8S;p|b&(R8}@hrM2n}5x=d*qlGbDZuRd#>Mo-cMBl zb65cC0;*z^Wx057F3rt@l05ZLz}tCvOTO%x4><+2J|A8w;5`dKt&wjRz#D~7TnMGg z#xI0N#)9ZFT*MkmKe?D5E8=&Gc}EeZim{>?=Lg}eV*5Z)o+>sQgZOPR4+o*I7|Kf| zOM^xwI5}t+{Vz>)jW!2^qQmWzf^c_(K~Vhu)F7TzLU}>ivqVOU zAy9&U6jNtVRut%*pA>AK>*~v|gz6!uejhFHJV3*)9*M zU03NG4}0v#j?qzDiNd`dxl;qZ20Mw%bhblyAHiq;V^e6r;1tv?iXO>Pu`^Ra>!O-@ zgFnZHPjC?P4UB88CWM-=-*;#6wf|2DPgvjRL?`nYtt) z8xtlH$0HN=mbhqmPZQB+#FG!lurroc5R)5Ysg+Skk2!lr@ztnGUF}{`I4k1Opmivm zx-y~_W+yws)5G?Iu=!It^I@w*CJvF(yx$G+rm=#FxpovXL$-1hH;mHe5xHp;)XKfb zC?7V$gCoSl^x=qnJ!}7rp-7t*z5AiX>aQ2YV zNzPm~h!0WmkZB#V@j>}^$g~W~nj!va&^$eapANcr>YQiLxn@XS8gwrh!e<7ZGlpdO zpu2DgA0IR)4#|^)a>5Y2FenR$=#4>IG-Tf&h>nOZ4ir?vuQ9T+V9#ijy=#vnw4RLPRV%S-# z#=UTIdze28ryU%@>_}>LMExcvUztJ?zFWHnQ5sb@ca$&EtxJ^ZVsM#~h2pR!M!&@I zusF<5*bm~eA>o;jz(bO$=Mt<>0FAXDl9GGWkDL;HVjSVpO)2@=<>3^ZXz3akwps3R z;Vjkx5q2kX)<8Y(t|ehBI~v*=ddm zk@?Wkv8UbBBcsNA>Y?i$J11>yyu2(%7!kw>m}U_TEI8-?D> z^#+e{C`|mDu{RJcG)A4C+sW!%-q|YL25d*Z6XbFPGd4-Zhed7z)-_c>@B+&+ajUfd zB+k25R5^Po+smSV$3}UQi<|U>-5s|FCQNmLmS__&0jm@AY=YI*`)9%lB$Zp9nxCY3 zNsl_$ZcC=#OTs6~w3Z|dB$I&@Pe^&@rBK<7*QfOEfZj;KPbv62r6(-m6wG#Mnl@rw zd#a1iy3XA${NTF(aWU)~t#OUFHtga_)|6Pd-SR;eR#`mH!vC{$-ceE&PaCf4zLWE8 z-epN944{aJU_ucAMa+O%6eEIQ7PE+AR?H$MFktv0Mi30BpqNDg!ARINv$J9H%)MRp z)p)*tILL7qSZ42ZSH17^{Ai@G0C_`;gpU2~H8A@PAv&Cy8%oTtez8=C_I8WLa&)=S(ts`i<2F;ufZ# zNV;6OnaB(92Pqk={7baAB)AAi0=E-P04Aq;O#b6m};dNk$z&{s1ok zx>+rk^&s;n!XRN3N|hW^{sh&BML#70LQ&trzN{k1!`OX?c$zjNv2p^r43*5&o<_4(!w;x^B1cekh()6m%4+Ny1us}; zxq{y;)g{y~7Y){MlswgS#d-0b<`ph1Yn62I(H8CDh6gM)&5fHZdd@ApdJ#dY*)FK{ z@TV?5#RCyHKH|Z1-SC5lm%G{L1Ne3BPO`qV2jk@iu} zE1pN3AhJRqFY@Vre(dp?)BP~oukZK6Lt={b!(VlJ|&3 zL3OUYM+E7XFuz=345Iw}y)Zm0Ed4M)9Hh-*bw?2Y4V#%kZVg-VuGAKGMh0O=ST_V= zbC^Vzwk|AYb6gRIMY8w^!=(Z1+AtgtFcZU&_2WQ!w)>$c#54T#k$9T?*4&W&lg}I+ za^LK$$RY>G;y7r1<>d)Mn&z!s3LFnS5|FPX>=S_g^0oC#a!gI~>jT|lxHIp&@Eo5$ z$OV6S4^S`uea5xqI$1v z#H-j@(ye(MRHDQ3IIW0J=FBsdL9y$%JWR}%BYDX!xQ@%A92)0md1e~dWz?^|=*rNj zUOFzVUhC11^qQI;^LvlJw{iv}aZp{`t#0lDp;Fi>?AL|2r$m4Vev!j=!ZV#TrV|Et z>g7pTpLF^q`J$wLGNA$z3s1wwPI3WRQ1D@cT6W-D%M$3t7?CeG1T^=rG}cW7HXZEjJ?cJ;M98an8+7BxUp zrY$tC1HNz3*LC1OEzVmVWVcw!4mF_F9FP!$8{U?Hdt33h1Z-%f1Cm(PrXEky^fus-WLY^Ol11Kt{b&w8Y8vK#9)J zshMRsDGw*wO5P2JInLpdhd0)tB}OubmQf7SN7%fDg#&==fF_!X7H0~T1O8=*hsKO_3rFuxUb)QR^y=+Oeh9x zK!7$|YT&?H>-kz-U+bJ*N2k{5ntCPH#V_jljC!8Yz`xY1V52^&fnIGiuQ%ZECh@t$ znkGKKkw^7`6^&|zAXOWwvAIIux~-XJH1Y4v>e(jTw=aF#1atc8KbrWhzD}x1{oB_n zHW_a}rzFnkepaT54(sRaXu=8otZ&8j+|PNvNfhwbZB1}MKQpljBqtVY;zVEku~Dt= zYi@6(+xl9A8`Y@3_D>C*Y<6GKz>hVTsa_3hcHLJ`>-#uzzdp5(uwnVPrpn6l#3q3vP!!Lq zw$F&*yeex!n3hNfA*4Qw;npAt%C8iVE+jStC>^F@er1QOi9VvBbG}!}k@8v(+kSJm zTMCc*DHkNYMr!{5c=WrPesRkuCnpUB6!PmuN)kU>h(Mq3cMi)a>41!Vs8%XvLxlcqchsh z;MHl8XTqz!P@Pu)_TXN<)ZD|Pd$br-&*?VHy7;y(T}+7@)j2LjTRN?!ojTNMlq|WD zcv%wfOQ1x>eiO85f_CfBYdh49?PhcbZ*EgxxAS3be46mJTCt789LuT_uTg@?78?K{C~(F=Cc7cJ)CooZo=?v|Nb3%$KVjcbAHcF=w;IBth( zYT*GpDAEGf4v{%x_jZW2(2niYr$tE4>VOt(-Ok6gP-Z*KY*GFl>d6)ww8N}x!IO80 z1P5;40i#;^!yR;Mt19f!5=c8@r;+HaP_3?QgI&UlZew9(9MX=j?GiH%RJTxd2jA18 z9_T>bO0r>`->M!+aHx%|l4@}qyp%Ktw!^Sa{bM_P+sRjUz{M%9OQ5GqtxM1wUFN!^ zI;~sp-&wipCOY-IJu;9K(<@xnrJAKI*-a8H^Y^I7GxSFfosv~6dR1+X7o>S>PI}_} zVqP6B-SYwsl%YXUx$_E2oXGQcC1E7OqO!E+afU5@KpyqqIyh+LU{8M*fd^ z9x;bR>CcGnjVcM%FO6|DrcRB+D=`o(=|OQ4gX$-7eRQ=NQ)T|BrZ211oEkM+441Y1 zVKptN1(`<$>)>&jr`3U7!(0dF)T-I_u&S1})nlX%j%c9s>hyCB>diVk-9X)St}%`3 zfO_ZtM!u|G{nQB0*F&I5)@MAr39^E_Z-Uwee5wg#Tqe7}aSgb!38pmg&L%j&0lS;v z!UieAfMnNunuL&#?M-lO18tE9PJ{YPXjBdGViWhuM6O9~sK-f7^lUvfH0g`$@t;PS z#liE9Dp3bh8tG-(=ryV-b?{yTTXj6SLA_mz`Fb;{mLIHFN!eZ2!<{v}td8R~ctD+c zp_-T1n%$~VOcSqE@pCoQuS%Z4>Zv$iUCo|2Y^j24VmQ1?G?esU9FB~t9WhuOfuS)d zglTS6k{)_(1fG}5afFjWYjjv095gqC=w_M83q;Y++XKu#j0Ny;A0OuD>%4fe5C11y zT`zBU<8lvFyWwXyj&VV^i>|aF=u*#V*vq1Isv?-~LY}I)8r5usLxJX3rf0Z_)qE1j zC%tYY<)VIc@DHbwQs}l-osDjr4l7fivbwOOB@cOT(M&4hy9Iek!=HJ&TgGB}lu^vV zIbNTIOR|s<$!tamXX!^-f~UcqM)_tLEjr5{xV4AYcjISbMCc;9CyeM)le*M(DS9?V zD?3%Hvoc1JBgzR$5RkI?AB9Dm?|@4ZEaI(SMcvg7V>_T8Uh zFlwCH|=x@ zUax1TGjRu2?b5S$@L{|7$sIU*7k{&Z-`J(}f3k^VcH+nud}Jrz*Md8DVrvT>u?r@& z;>)|}-Bt{>=snuZ?JdsYHp^*o^=&t|wmPr2D}M!>&x_jlJ2`8$^JNM6yx^u-~t>{!b2pVT*gC7xVKHC%e=dzCfG1g z$j^?f{P-N1sj`|uFaY=lRs#|40cW7XCxsrT%@SqrW?AoQYd0Y+Th!mJzIS0?4{dgH zomc%+nPPE^7u|jo{CLsN3BT?LKu5s&HHbTddW`@lL;OM*z7O-Q5m+73XGX=R;Ork$ z3t|?=>EgKaU0jJjdSMk+RhyHmaYwZZ)WEVD{|TfQI@nyt%j;NX=Hu(d z=D=G7wACO_27yG0qRafxefjS`Jh`uWs}JnimuC0DWV70@553Y%e>dqfn(^KygU!5mlX^+^n2kK5 z51rg7hHCuwHB6H|mVPL51qnCG~VkEw8RqpVWZAj{G%n zvMed8VPOqDRt4WztDoZt)#Q>eMiq{TReXXMMsaQo?w1&R6#f^+6%qI$B=;|F4dRyn z?14LjEXm$fK$2-D?T4X0otKAvdB>MG(?qbI)Awb~=&boDgBSjXOu0X82BcwSuRgCAl9eGd?A8NG@x^!J zsBV6(iyrP$xs>Wm@wgP9kb)(hu(A_fov?Q&%}UC9z5X`={gY;D0$)q0Z5?z_f-mS$ z-*!M&2yz|xU^|97ct|_1YKN_DIIA7+Z{vO1S<>v?ZQyI;)ork;6&`7WH(Ft48{E^1 zr?lY}t$aiqo!JT^o)+BS&^9`$6%KAg`IRwkFryWwwz0rAuWiFuTH)C?_^B1vw+ZwF zOY#tFqhaklw@qEwF0w!Vv|UxVL!^T*Z^w%|U_(2v?SLU2uzP}^>3|32vX%fR0rL_# zCrOZ`WKzvfR-OrAS?YD-;!br_3Wlc0*ToxBdT|$A+T{%IMt`@pu^Zm$HgkIT%pO(S zi@si7)61)R;gYnVJE1y*dt~s-4F8p(YqIc6Ru2-)PR{u=M^$<2@x1yqZ;mU_!h+I8 zby|^D7rDBmt}Wr_5)Cek?NPOtajH!(+EnMLGaS9eA&CV&VbnK9pGtfSnK1K#tT(W3 zVRJi}CqR!tH5N?*xd+vAil0?HL93%RW-F<9e%7M-R;8jY<%@q@wAzI?x$zV?#64=K zn_uxbvpq1}YuO(7%xi9waEni&4<$){tB*(fNkmSo{Q7b~?-Ovg_$9UO8WR8v+OG%j zqM+pu!WTiB9^{4)tO??*%G{Vf4)K{X0tn-h5FHy9-#yL`%Lsy3hxv@K>JH-rVQP%< zsxS(qWk(of25v=IT%5Z_)KkJpiSTO?JShV2N7Q){{y5?YQT)@0H9JBgWtbCD??(8_ z2)`1sgyr%?qN5R|oaVptEO?ogUx^{p1bcA%3;S58GwI>gNSM)n6h*KKjY$Z1$?#e6Cx(G}vbb zc-5c6eDKgcUYzMs!@VZv5n8+c$c+zs=q%CJdl22w=7!f?{Foa~aH*pN_AbeJiARc@ z*JZ|9Fy5tmHRmNosnu&1PS9qG?Aes|Tat38)dKBTI9pf1_OkZP zs?xR5O1%!W25CB|8&T~JbP&=m7SO$Lv1CfaS1`;09L8`UP+0=htkw~(WD>f|Ev(KZ z7{ff6*v}#c#!WKVH1Go98wO?&-CQ<9J&b zbbO?(k1VSZw%NVx47RO6*|mplcbA+#wrfjC*VxV{CGy*PX-Tk_BwGO4YRxG@ZyBbR zphG^q1b>$$f)1O?94>*x*Na8?vTU{&VO3dwSA^wd^L`OtE$bJH@SHe1ioCEa&Iq-j zOcxaSma;y%$XAuk;YD?6Sr0DK*=1@h;>l(36=AF(O$sowOv1O>uPmc=-M?(UDL7SS zwWgrmWq!Lrr4qhe5Ka_5Q4nIhexLxGO6JZ2Y$)lQ3h-Hpt}fsQCA_l0%SwDj0beMo z83mSYog6qHE}{I&Jtde`;9E;@RRM1(!3_ntx+Ebqak23|1$A)=7Z!M037#+Dc_nzW zz-N_URRLsZzoAgMTyHDDA|5@ zHjgz*);*6Js(0uwqfcW8Y*<`BFJV!1WX#Y+2r^x-;su86Wo6D4vQU7Pk^e|OxeF$hF!`ucU%TOCY)ymit z`Em=-k^826pCVSfWVFtgxYTGFo4cI*g|_5&NgL&Cx7l68TW-8cW7!R#YC6^feoHU( z@adMb)uUdrto~k;w9Is`mU7MOf=+dDyO-CycrTv{xz$CYgm&`_K6u6rzx&kRZV3CS zp9hZetLYxN+D}V8xWtbw9{SPG1H4%BtMj}tAV3miJvM;9dFj#s1bk{i0FLyTmjf~$ zx7GyID?al}!2Ifyd#+|5Nh@o`K zkWa!>1Mr0(P72`TejF1J;WZx^!2SI=AOMoN4Fp)Ag1vsc)2HN3YK)IRkl)t_Px$3c z4d?jbMlVh9^H8tq=T{vbO8W%BuGabRWDh;&BlM{Aed=AQJNf85H)OmzJLf8S&En3LYX5PuVa+NxyG3 z0^?G57_3J#$nZ*#rzM^VX0F3!hP@nomeod^N3yxa#%*NnYx50cwwAG;;Jz|{Xp{_B zrx*bba^69Cnmy^jnI(C~a;${gZ1sJSWlpl72m@?2PFj0qau>}Nq7N>pnle3D;58+6 zx?})K)Lg)-lJ1brX3@N#2Pxy+mB&6sJ}pl_6kxBsl3k~r;{!!nk%M-by6519JkHO- z)I3kiL0lr-IruRL19SLb4%|69A;-xq#&WnRi<`6jS(cv5$_7(in&rh=J}8TiWLalv zURH0;h@9P7mf@?j)*Tt1m31Tsaz)k}o^dYAnpnoVBC9fKGc(JZ(s*?iR;S^{EWVtE zJG1;?8Xl0XXd0i+;^k?2CCg`~)rV62Nt3u}C#2P1Sw1Gs>8u))hG355$GviRTpEta z!71sAjPjhcnkN|v`PiILx$wIjJer2ItX$L3lo#$6ACrfF(rQkgIc*l_l{ATjb~P?T zc3xeX!65}&l!0l53Qz3G0tjMJzFb4H=q^^A5l0r`#Vp<=pzJJvB>kow6pD0C4o8-h zY;12TQ7VU@m*jTI?lLXN2qVL#e5O7_k+JX?f%N0p0s znPbi>@yCt`7BM7_;xeCatVhf6fiZR&1EeprX&TWMTS-r6g2QovjX1(~lL;z+!}>J? zQn=_xFc08a!tEfNbRLcT7~@Nbvc!=k=%XNjIEbT6MeuPk?1;Zc(S2HcuR5i%NgH{o zKde;C+w#Q;#Gx%FSN$ zf!BSD*Bb6C|LJw!^|=rASqJ#-r+xIMU#?WJSAb6T!wVIQjc8oJ6~G6Ae0G3MP`w+# znIUoqX3@R|sTgJx+&-4fRuBlJPskw``&ZtWJOx+*g^s>f8Ri=xh@ zRd7etbzhZS5ACH@@MhFnQzecYAa8BRoq~+7a9@PQxSO z)4_aLJrQGJypN87(1F^cSRa-E349fzflES(nIMD;QdGRAR{N@oM z5$xfCyIpXV8`>>cdXc)C~PWChd?~eY3m^A zs-Kv^mF=)L!9zN5L=u;G@cT(VI01)t;<|+Tx)aVwI#W}WNxIT0>&Z_0kuLkllpfJ- zb*FfHH;Ft>hLGoXaCQj{GP}(m*|;)DK$nuKcN`@2>=h%snoC(XH=xt4BR_yN7P|;#{wq;e)Gubef+p z_T%9Jb!Gqu21$0@lDZrbQvZaYf0#ZBgFB)hh(K$^oE62jQMFghJQ<^8%(^VD-i$lL zs(5;pRjz{iYG-9NuB*1LuAvz<&Yra@RBQcKORv;Ag2EeFr|atZt2+K)JswwI$=I*2 zM~Rdl-az9U`OOCPRU^h5`Jg7gQbzGjxULaR6UUn9v_3GUNiXe#3!9vdKJ-d`!yO_etg@YUTvatE2Ic3RoM>MbLweI zqr1CKZEYxDSVt!|xHi_}=k?BrTG(4))c@@rx?~$z%STl6uv&be3U8}{U*hm(HALfp z)o@%4q#$`)6fTd$@(4T?!#~3CS(H_nw?}YLNXvbEe9$z6X?j2(5VCIb8_Byq;S&g| ze#6UW`RQX1PWR!r5()G27MGggQM)Xmf{?tMT<%f@MHfkL8r20FCB$)-WZA%)Qt2Q& zCxLiR^hBn84IL{f8V8OxFwVx&4o@z_k+zyq;?ZSuTP41zo+;q*6?q?@TENXYJU>sR zEX>a70a>~;>rBj8&t_b=q@DNE_KIG;saMO0tk^??delIH&v(Nw++ADW&PB~wJpv*?J%Q7KhTbnI>@%u-mP$9he%h| zmJZ{RpKXPK0W&8l-}Co4C^xY^;$h$>Zmj=@1}AZuI*7WpFEUMtbz4&Pl?Uc(pL=4U}7JC;}m z1{r4>D<4@Ba_%50VY5unK18()=tcnrpgLTuixe46qcwhFVIK?Tx*%(bk`=ynsZKXM z@1_?;E9}8jg#9R)EgyJ&yvzqb$xGJ{kNHW)yr%^4(E!WEXP=;27gTG5bbW|U4ynDu z_)my_l1xq*ua#|77zL;`BVyi($^*w5ALFy4&eoXvF{&?))2JAC#_{DC&#D4fTqUYl z*p=s1tB>RA=V}U8(a0KgW|dl8LoZfwsYdOP<3TMoSK~{ycv>}e)Z$&$YQH*qyP7W% z=W;bXU&p=G_SDl8Ub(!Ez3(!Sm{2?;1F( z9vW)+#Cnj+?dW>!5YKx(Z>UzmdVHmt+UjU-wfeNKf{}lyj_ajoREPgoQBxhiRHe4n z!g*EnNG;S=sWG+iU7WgVaBf^ZQNz2-K}G6&;*Y3?D`R{~HAG@is)9G7cy|?yiBhNv zwnWrI3Drk97MEQfiq~&mm<2u-2;&V=emF$JRjvx@(<1a}(5w!tNKg+53u?pMA(YO5 z{#Pb-elt=cQa-gX0F!;(=7+DmILgllc=;Tv}WBs704(-Xfd_g?%*+RdAuA$B|yIludOH&^cg+1ANK)X2wBGQc`|^R8T+y z#++)@8UIbUK69weR)ZWh%!Ws7y1mS$viiA%7nP}BW!!;R7in}!0+V`0QF4{ETTv3B z@N9v9GeM&-=?d3Zi6p-^yV;oh9kdO47Tf75DV7Eeu6LzXs({x74B=>>7pt?hyJ zX=`i`oSAmM6ZvVcHCZz1z0R&K*ss^Rp$mTOaUxxCO^<#%g?)R(;{fu%Wjp!iZg@eC zHxfth1P4+gl2E}Eot~g*%DOnA8&l5Qgc+2o0Hs>_NXs=@zEXu?mnnWugJ3&H+SQIn`S6}^$E zEvh9&{aKM@rF*F`+e=tmRu`0|cTA-+US;EBHura6h=Us)$-{%dKQA&oj3md2Ed>WG~ixsMkwxc<^DLmc+s!KYi_0pZoC?pE)%kHaaaisB`@^D`@@e zSB0Q`PJrfyT)zh-nd3|fnrp-Ai=a-0VQ7eC{Qg`>{TM-4m=2B#b67nWMVY1BQI=W# zl$byQ>8%(_>|DIpf;}G}hl`{5a2(%=@=tN@h(e$Wc8|g6Dm){GS60zIF_BH+ikMnm zg_~lurHaxq?5zWMg>p>a5XHA*&d?}L zi3v0wAtwDMcsW{GLr8?6U9LhAb8lG9h^RqfQx3xyA?uznPYyZZFeZX}VTf-CQapqb z_ID zi`;yo+ia3}i3`WMPzvTB3is7=cC+Aj?OG_VaP5%7rzIb&IFBgiXgTMMMfeEteURt} z>;`xf(?aIINL!3!$XrMKy3wMph#NZJ@J$YGbFf2hPYzG9m6*yml+7etpxOH8GQV4* zlgo0A!rx1RRTqB~?@?4qiAWX9^+npZpk)dzcH_kbbyOaQ7mOsvf6fd4jc4VloK;nM zd@5^JRpb%YMLG3H##HCbybOMu)dyy9UY2*IW#P!r2@)u)&Pz z-t5&QWu(*VL^Cw0*Of}Ey?brRIk0T!4_%q2XM6Mwa;NJt^W+rKBWQG7+r!J!u%!pSOmlBfZ%gHSR{d^xJ#0a;dPd) zIJm$}05}iSLV#63TL8pp+>CrN!uhDzAiRi9P~l%_oujBuIm;BDtaR=_^YUTZe5_!e zcBK@q*X1TnZp$q#_+u^mDh+p9mQa{Jw#?^RWh`vbLWM$)g(8pM(}Me5Qsv;4E}CXx zt4rN%Nlu#{vuLa$5xpJKY9cGNjdBm#*>1 zB-ZTi(E>*r=5b;!KHOtfxlkksQL(N|{M&_-Js5QHR1bMvc(zALpY3c9IacN8c?-_; zNKuF<9u%k|4M&p@qr#*Y2jWTmKa#0N4;!e$U~1?z;3m` zf-X1RWWire7}o-*LZ^qw`jW1MZaow zvP*B&e3;ApqH!OW5;jz=i+>iTluJ-lkhbtw@p@RiN%Qv>Zq>NjV);C8Shz#uB1^bZ ze4nMdHQr*GoaR}U#Tutsj>m#iEgiSuSWD6YH1^_3R=ruljczSeNNg`yx|VDX!xZL%t)tfwr2Yr*rDptnTf1lMSI z!{UpyAh2+%#`i5Aug!-Rj?#Ly1^a4RV?lGp9u7ebpIBTLn~$YB6pQ+2lTz&J1R1Q)o z{Rozc1mgzz_F;M$aWJdXP*NCNi@26hWGf4Zp9VOYU@{0kUvPH#r-2`sUov<%!^KiX zVcgfKJW;1ZZ<2mTAge@k9I7EW$k7`N=56O@!ynkz5TkCe&EF1CBOLDPw_@lDy zM)7*_4cTz8NHlEDmQ22k@0au|WxlFJr<8G6NkN%2MHYh7hebZ8BsL9CR5Dp;o$__2cBr=TVlTpf9G7n~3C_*Guro##9AFgdTr(>yXDOEoLF`AF*#nFHG7CZD64%rx;$&T5&EjhL|=4fk%?@!8$3`pMeCrxmTw<3!@~b*Y!~FF1sA&DU3pTuV5kcw%b48-Ke};<8;=d{UI^qv`@tz(;9T z)QpIV2;LeUm9(cB6IFAgYD|=`iPGUwm=VQcQ8+6K1EVlbI1Eu360J}gqW{$@J0mQ! zsjsA2DHEy)O^v`sGMkFP{t@m8Lne$LhWXtvTo=}}E7l=^JB=`%mxBNQM%)%u~ur%x1b)ZnU!dhfLO7AZn%mDhBU zHZ!%_tn@BL$4FvX;roa`qsS&;EYd^3t3W%_)dJ^I>2tC58|iv>jufvMS#KLHZHszC z*BLe6!A^%Io_c}9;z`+N>mSN|ie2eq{7}ZXN<6--`jv2f$zE9GV@hsc5!V;(+X_6P zsO>!dT;S{SJf#2yfjs9ct;5*@uE}cr&y)37j^kOiPfj3v@MTtRReWxizD`$!GUuk@ zg^VMN`eQQc>0TCr*T`P=RGR+op|NSbpoa^+G_1#3-ixi>_NBeBsN34Bmrw2H_8y3L zSB`m`y7XK*B6gVxJ=SHC9`CV7c8Q$Sign?}Zc3(jMK^w*f~UH9c}i;6N`_H0yNz&i z&g+)xlYA<=It7!uVRj0R7Yus}PUtq*Rd~qyjuf8NO%J8$l5Sj*(sR3EP0Bpn%_69M zvs>9I{-)dX?}E;5J*f+Y?00JyAKruScd3~@(B0+8eRKbAYikc))9qCE!kTW^>Amdh zah~dx6@&Vxmsj)%Mim3SbWIvA?UhU^f75H~GHOU#7KM(OeZG;CQ-%kMWG91nW^udl z{Ih&|7LU!Lcy`{((fAzH=GE8#)icNEO-~+v$Xgc_@U()xslf8+o>+t#Mf#$MvH?82 z#1dSQb7tQ%50^8489yk)@iq*%ai=YBD15V1nUvNU76j{i29GpwqR@8@B#6fo+{5@2 z@j#%{7}tXSlldH^X`sr837{t{)odIt5F}(dgxsodmZjXfQr~+(i+l>JEg0<<+$C>y zLw^@u<$7mtdVT@0&1{p?OR}JsSKu|E7WALgpgJLXZnNVD>tya6mo%Pi;EN*>Wt&WPD zwbe8}j9AzQ+O^@meBPt)U zgAuwT;(jkIfS}T8VR|6!&4i?HSbQKv3qqdVLJC9ndqKV?sE-apOMt!$;K>0zB|xkE zyvbk5NXW)SP$571@Gr@P_-KTeS9vR7*nPY#qOqqvaFE+5K~K2!47c;6Wqx*9jg}hj zGSdW`W+}Nf$l0w?&?KK zk!%BROz9hYpwQ_QyLoP>b!)e>I*qH_JepJsyY%i!9@u48Cty`dohi${6qpX^?W9*a z1gdPE)&YlimZeYEnRI{EjxQyh`R#OOQk~eYnv#;Yr|k*Owc-B~Qm(-}61Ymh^$C8Z zjYlT%nKsow!H>65Fo93CiD-&nkX&nrTG2+u4)b-J;tti;M!p0D+p$?j>+LW?LhS84 zIU$TbbxT6Ew3}rK*snwXC8+8Ss!gh&I@Hvp*(YHZC-p-K-I=69f<||$%aUqQC;giw zr&FERS)uvu=!A_aH7f;UyNFWwNf!#abW}GCt+Wi_*KT2Gh_IVC^}rszN}kET^&0Bs zd(zgTv_2~1jLJB6M*p3$)?}q(X>QHw19Nz6p8m~YtbkAC>8}DzEU5n#B_~F=m(*89 zHKj}fjUQs;xC##qf;P7}EVtb+4L;<`Mp-=V5hT7-6=Yb`DOWb+0g-hw9LxL*j z(-7i!{LU94xJ=B&VeA*=!y@#vsP}}l5Q5jDG$;(G$JEbZc4C#lz)NuqNBQt7S{mg| zReD5BurSV-G3u?hj*F}7Ys|NC%G9W1tCZB}R#(y1THaggJaxFRnuN=ju9h1$oLIvr z)#K6{SX|G&HA0?;QMKH+0dA^Qr#HX{wKT5*I%?IM4Om@gHZ<@dbz0E$Q|hR<0cO^z zvdG`-OsN6yscYF=OCuBygyHRUB${CTx| zNEIGjZLf&)k}7Mc%;lZ!YwUFH$e`alOy1@xmEi0f)kq9twG2qZ^02K~6zu zh`!K;w_0$E1utv-K*Ksk2}NzF21w);X)@A&AdF%>iD|8P2}u`;o-&Rcsy}h8ON`lR zJ1;moXzM?0GrUZ-ww_kP$z}6!5uYx}N}B#CaxSlSE5eXG%@j3fPJNQ+WmyX6u`8o4 z%F)3Y$tJ1!Y3Q5f&AoVM2KMiz_B7nzqb8>z)y?aB;k0fzycY%bva*K{?4l7ehDzyA zyY*fv!2&zWI&oWiI7v6RD|y1qZs${yd|Bm3xV&AR zkrXusU6h2|+Vu@dc)ZD)cHSwX;dWpboWvC!E_s(>w9m4)t;;{nom#*)%e(I9Zx-+#KtJ7ASfI!pchMr1mINYn2Rw|Y}B&&{2^O~%f3e^d6n91

-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�>;(#`b*dUN70#w)$sjs ze9m^4Ldp_Zv+pGe$r8zyH9LufO7^r-$&xKgBx{xsDf^ZXWi6>BWEY{u)>qxRGv}O{ z-~Ih}|G3Y6p8GsAXU=@i`~7+mm_Rn?kS^=U?NcOb5ox-Xh!e@i>11O+(!rh#Zb3d0 zVrn*BdV|GMd^Ht|S-4;|?syFAM&mgVcy<$k6XOK3wmx1 z_ufuJ2k?{;bf{t?7f`c%ta+CFIGVXc$(!BSoB^_nmU(mO(^KkkS6Z`+c8iv*OwAoP zDY+RvVJ5ZtDi3;Y+?XogK45&cO1AbjYF*`t_QrvA!zHw-A+_;bHOGu!AFVJLGkKAC4oYGJJO zF!U3QANm@OeG~U~GR6A#txYJm>EkMkc zYgfz@@2j=;v&BfQ;l@nS(#p_erZ}yYVX&7t&)(2%p4i^a@ZDd0Hr+5QNVHjLNM9@V z*=fk#DKuzS4ww}O80I^YhOw&6v?Kp z>^fWy8ZM8Bldr9l>wJ{2-;*=D(j5ZrznbkbiYFwM3Pb>v+HhrK*6Zeo{PIDnr5YOR9+kZW?I)SO6lX2w$_ooHIgEOK5^7-U^4J2goai7mk7qJGAXDDBO(3 z41u3Yk;86C`(gD9>=1{mdZOU(xMVH5)t@}gM}u~dl4khkXHvBg2iR*mU&cM7G@E7I zAW!pk2x)7rox6qjdTaIhu5cG=+cL2 zb6e}@M`%N*>ib^N&flgV{at(NmOjE-XQ;7&w zEBv8LI%DQxrVoE)M!M*ae>Q96uJ0_GInLGRnww{b=!=@0hsWw|yO^&_)Tj40zmull z>0<7du1_Cq-Y`qwd5C%I$NH*4=F4;S=FaA7u6{vJ^Qy=CIvva{v-PHW&bpg=H)3vo zUZ45btlcsFu@bZCJM}m2m{o=A`y4g9Gf)36(ky$F{^Ja@mOb>HdYj#=r_a-yCI8eN z{h)vSSaxA17z~{N{u^luHwmK*!utea=Lw;+vtSq}?0WxyYH4MZdLu<0-d1feRlV>? z2{Vn>0+gqhmEd}c%N*t26@H+eB2VW9nYE8g|## zEI4NnYikCWyjN1ql?=mqp|<9Mp@ms()pLVOG-yu`bkKg~Q_;@Pw zyQvOoish>RC%zusR?o~R9Xs0_6h-kg4+i{d?+YwK};)O<8&<^ znho^QmAy0DnzKyvOt^3%vYv!%-y1N zySkVsh3P^%n)h6xd)?Z+xu0&cwYkeI-EMR917mf6nAxa-y8D%8eY)u?UYgBpqVvx* zdkb{4PMGbg&?av*+f<+(HQ(&w746U=X8reS_cu3tze?*?qkr$I9g(ANWUoy*q~B_$ z^5^9kyw?$o5@>hAhz&hFBUa@5qHr0YU7j~eQF7L&3f?ULifai{j> zVp1?tyR0v{1GJL>skxyUn}g>BYJzrQ>sFe=$+&F+nPh_}MG~tI=xJ9{aukKV#_#8# zDeG{VE!x}#cQ1txi_q$0a7Y;XF&lnsi6WZAv-hFJTX1;+%u4`SCIi?+@Gli?sRum9 zfXz9=+22CQMxpyoA#srKx`%LGRu>egIoH(IOV#pa>YIA1SvPgV1;y@%VmDryourVz zeA#T}XdK^Sqm1aqV_x&3mu!1H4+v%P6Zn(n%+CY?%Ax}b*qnt_-oZla(WB#7*mb#+ zC3Bx6AACVe%;i4`bVj;VcNRUkKx)*6UTQ2E%jI=Xj8`tn<`KrhtL5bm#$FOL zO7=Y|{`o9@pCe{nl=`$1S4B%*J{zh%rJNH6tIkq`07Em?Xyah`_R5&fYr`%Y|30lf z7i%mzT$}H2oV%=c%SdDJ@Y+UQjbmHax>y*u^O`QT;;Iid_dkg2ZcW1{V*TWr-dDww zJ8OO?i62(i1nm)zE~<$)9r1hB%vmE=c-EA!6i1J#X}CljII5;1Ks-CDW|_ZuXG~36 zfM`FtCS-{?%)7=aNPHJqGklHsUqnsQO=4PH&9yz^$1^qGlf>``HCb21{L-4K|>AC(~ZGv3}K&* zrbY6NUP==UZylvueZ_=%Qs5f#*B&l@p>$?gbiK7 zp0wa|^I4oP?`zLJQ#sjfI_2Qc{_zdY%GjxjVV!a>LvhJddbd<#8mR}P)vVd-n{Vp- zGisla!mt0-b!mc${r=nnw2cw0R)Wrj!qS((ttt571igL0#QiYtEHKFov;PA}rXq7^ z7<~30N1rJ}UIlKp} znVOEzv9q~WSBJz-(K-$zK1Z}c5hSQgYq&ywbkt>*lMFvyiH)WzS!e5^iTQW@RqUE+*S{;SMq6;bffbM8-D7YfS02cW7cfewm2E zUGeML=+Q4z${h_ofVzEx*={H~5pMqtkr#A50F!OtfFZE=8_@D6zzIN`05Uy6(?KA_ z64a>>X6FmtcMG<$LJt?=*GR$ghk9Epw2M<0KT?0WsBJc?+2zW|q3V{WeQGK!@a$_tvX)p7EUa{6MD9CwpeHkBvD(p{xe&K%0mN^knmCc)Ap3wqv7 zT2vuR4W(xfOo(#h-6VO{ZR3)4a>^cK(LC92vGG55`SD2OlaJaka8Aw~!Wx#!MFFg3BYGsBy&FY+GFf0WZClR78}zmn zpZSMQ7{GURWTgxF18=rsH?P^pUfkjN&so0;UTDVS8Y;)#_}@Xw!3e%6K$&-g-`lHn zujYO4DL=a?sg+8quhP7cy5NX%X`njrwc_fh*3?&@$Eg(~)aVTLcCs9 z|5aP}6!JR?1E&gjwlFC|n7K#TnIxQfA{ZVCqnR+KO88(0SY43l1CHB+6MMk!3E;#7 zuz3Zj{Rgt*fJ4|XeT@-f(mX@MDPoO8prSD+#_Sn=G?d*ng1mx?3cUYo3QFxUt3Os~k z>`|ZV`1U|Fs{l9iKnH%{CsR>x1+Sck>NgIBLWey_r%hMTLNRm$?YZJNsG#YW9>^_4EuM*c3v?_zNNCi2M-d9EhC=c0{E$k}NqeJ&Y44h{AshGFR6 zP;$TpJ?ll>dZE{Ch(%{aEQx6o63g-X2B={r{$OJ4y~M9L49~(P|H0@~%)i6y@mPHa zts-!zLKr$9PkI15df=2B@Vf&RQsILpc={1|PC;*W!P{Sv;|AE_F-i}HKB;JsKcw5y zgPCyWG88%nPMwH44T3{^p^x^^xgpx!26nB5D;mJn#c&da53iUQB*115wD}HpFNf+Y z;5H7{dko6E!8SKQl4%&241#`uLwmuj2jJrd;Cl?%1c6m+K&%hgGz~nR03P-N{)2#- ziCNekjI9(_H3N4a2v&N~_o#5yAf$x}kza-GlLXu6!s#Bu-#bDVy>R!eaQ>?rzfYKZ zN8PbrsMx3OS}L4euI`>G^z=}74;TJxuRe4TVob4v7DDTHN_)NV?W!`nMxD7!x%pA$ z0g7#o8sx4-Ur}4xDwT=qQqEUzQVk{CYPsrhjVI4gqjvMbZtB&g+_a|u@ZiT9t8y2< zNL93Y-n(4+?*|i}D;FQLqMM5Q8FnN|`M8+{ZBxSi*{~obYcy-&rRaOG|Ar}@Em=Vi zQ*V!+u~sVI&<%pJ>n?SvKj=m8&Eu}E zXxJD&zYZ<$%jd~*cw4Til&k9Tb8lo%neklt$amKIj{Lre{kkX@-eWsY$=}a0d`P}@ zn6=$4FWbf%ZIuUyvrFscW%5i0Eu45!pQ zf6zEzy`2EM8q|;3pjj(H{0+q6LW5@T>oQ^8Fu3iY@NgMibYGZt5L*2b+TMrdjlj1m zm@yC(H9(sdf?v*P(k@^(7d5>Jl46iWDHxQBOb94afSTIF?$xOGR2XW7!y};NfWIZd zqZ9G0C-B8mT=f&`w&R}`$U6nUbU?NbaNcCp^8>aFLE*J{$3A3ThxELG%56!nm&n42 z*!@F`N0MC@xaCYTunX?9$OOp3Nnymv3!7G_s8x9I9?~=xFF!&okK@j#iR(4o-~!2f zjAvXU5pVE|46>;LCub5x#HIJhAwrgCk%N}R?;d&5oNUh|>)R8HTVz>xV!TFf_9D&~ z$b!D);%O4tpKLioQU{ROcrth(>AaZ?96TKm!1T9knLTFu^;Kv zhPZbiBb$&sOR}XdxkPa{Kyu4)_kY+e5AXYmYcAt%FL2?0+$jr}N8m~4@$|X)>j8}2 zaPfNlwLO*tais>2pN#wbK;|y^_#sO&}~&0N%iDuTbC!#xD{Q>wqb)!pSd!ueA_z zQ&{y&-LzBKcwgN$Us!rjP3bReT&CVIAufiir^?m2E!8`jYI~D=GhQu!rW7qw&!1AV zhp3|>mD^3#vMEYTwKCCO8K0xv*DLLgD@A2|XSmY%E_d`)_(7i5P5Bhee`}PyiM-Ai z?rG0k-QgeV@=pi2%TE>`%zdA-X`b9Sm0j-1d&IKO^|>0ztp2hiW0^%EduO^CFR^Bg zSj%{3l<2l#_Ua=&JcDg|Ktl(y!c^L>J^Q_fnqqXX*3gW9^x=H^`W zi*#Qn>U5ZTHKyIS(4UxI4WZ*|U?R{R} z)tWv{m&?0S`v-EVG*=!ii{3IXrq#nQJKRz^AksGh13oZUX_pY&}llIYJj`YY` z>M)9CWKtV%dgKK?xQaHcq!+hSFTk=-(fLi;qPuj61N;1jejd$!)KZTH?58D*j%M5J zSVST#AH%F}vDS;($r4s?JChA8@jPqOn0G8>Iwun}f{By4S7W|Bgq!#0zxMOBbGXAT zUb~U^|HzdzKEmW`dcm#RD~A}rG*ao@UTM5k**sQR9ab^O%Ma?MTD6I}(6XiQp`S2*xUk1hxV}`d z-7kFFFBCiyT(g9U24P;M@TfhwWd(FofMtIWwh?sp1>diNuvjp*4BWd4t~Y>YAAr?R z7=>Z*3Mh4j!g0936Yea4^}^u@4!<3RgAYRDaTEEQq&cvkOuDXVafZ}B(U@N+#y6U7_sP-<&DH|4&Y+2WLkgkxcPY73N4u$l zG;O5a`-fOJ)0)?iF|D=#45WQqt(%c7YNyRNlId-=CJsYdYwf;&B)qwH$sdx^SX)+3 zGV5ydKNBt1R=p+$QFA$u#8zm&-6b>LYPMY>nkSmW$4Q&3nl`)0g(DiP2=X~b6YfX0 zEY^&iND3!tb~}@}-kPDd#L!T)NJH}e5nPGK7ZP0_9-KWRLi*a`=_NQrM*e5;=_0f~6c?wUkYRX96uM-IJtmcg&L?M`m;DEzmoM-bmsvY|{(C9YO6+fUR-VPO zf6~NlY*rd=Foiu1q&~Jx?oI=K(MNyfi5YatRr&U2x*<%aQ|a+eBL2PG0`n_?b%^QjN)Pqz=(Wm+R8BX~y!s(wCmb z`N7ity2ik1Qtv7;$3@D1Dz0rSeLN>pGs$L;m{4o{6ej-rYOMlW-5K&&y_T%5Gs*xN#kjx%Z+ zi39f;zqAmC9W^%TES^d+9&{2XTsJxn7d;*t%Vvm2UKv|26PHyO12>C@731?0;;Y8e zhAi==owT7;{54v7g^Z&Dq-C9q{kKZ(#v7NUNz=lNj)hY4DdS*+_64G+_k(ah#6Exf~?cVW?#OfG7YKTkYinW4RN?(HA>pv#lr4Pu zEIhOVbJ~H?^S}W=puYkv(|`fMkUt=G0-V_s-aiWMSHhOR;NYt;sUM1|f%7&ZwHKOF zh_0?c(Kh(S1vJ?QJN`uTQ!wp-PyWH$xp-eM5^@0F3MPJqIPM0?CgiPw%ycHZdTWjZ z5_PF&Mk0BYqKU~PUA}0#%4EK^c3=lhqtROP@tRd@v};2&n^Lta5;dbrw6C%>cc8BF ztLAGL-3_G87_YOl)kdw<`M7BB#Ou%$ZM)05#6T^|*PV{m7Jb(x@6pCF-SiV$TwlNb zlD508{^)J3yPbadL+u1-z4TPuaH!s~Q2TI%zH5=z-a}vXT)W*v?^vMyI8whgNBiAP zKOwdaJ*EL2<-OD)5j0)|9K+VcbZLFJSOq@2{M)P^Dw)Quv zvDbdgA`iJ{${ynRL=)jd=EiCM*^_S5G|e~;ZK2um1na(#HM?=#2~s%&`}mThZSaM* zkzGbXKJe^_XMu`(EZ4z|ny zzkJ};Fp$~=Ztn|{o&l4#^vpUCcTK2v0ue#NfGS~eFCqS@Fz-M0kEbyAl8KZf*e+KG zWvajI)w3(quxjO0C)Mh*lJrsO5~Kv~RXm-P-X2OHiN|53>Nfv&o6nBsyF>Ww;XJG- zx2?x7{9;R9vC0${b(EzpWS;&^?7%`DndS$b0$I`-no~$K7t!jYv};egbUBST$bN2g zOr~7bgbv#*8-L4nJmrW-vSn*|#xeQiZ|Ur6IpnSsJ54T%lT!M~K?|fwP2__vQa>t@ zMpD`*DgBRe<|C>6sd4-TY2jI8-2;;CHe>cispAr(Hc0aGG_LoR49>=_Q>4sx#%H4> z%lgL2uF@Pu^y(+o{uWR7lIoO-4)#(TlZ&v26!AjPjER86T zpLLSF|H*5{N|{aR++ayRm_9u!CHc`)xl;Q$Du|N(E!wD^{P!F6^_06=vBm4<`2*R1 zSLNx8nB5Qg(E;|uhT1=2v&YdXB6HhFdw1mLZ&RzOylxFWxruk|#+=jno%w8i1=k*9 zJDMpI-?9P^#j-Kak5mdwM<*ARK|6Tn7bWN^Ki^Q@t5Xu))vRI4x=?lhdL=bQU6G~a zzEy{+O1ZgUF+ddt2>Vv6`vZk3H`VgPLPJpv&lBqO7KWNg+slOsok7}pVbWCavQl`z z9>^WQtczfl4`}utq$h$FTDa#msP6z5TEaauVZ(lU#J7mjUy#FJyevUsYBmqM)S&+*dNyP>Pp-%X}lds#C^@CSw3;UZ&~pN}gA1 zz7HjnxyIj(Ow($+x{>b|+R!1SUt=vEOd2%Pdi5vET51iBB(asYxg8nNN*mdctZSiN z){;b;qU;TbzM(czM;g@CzN7dY)}A(LnqgmZHQ)QY?@__M3I-lcx&`%J2+eh8~cNPmtde9 zXchr)w*u}Xptp&l*8s9&q2>cPc0ssu8hC6qz0reeU!kZUI627V766_$!q}&RwpP8k zN4Q_0wwxt|pH=hQ3gSl9{inKOu8Oa!H7@GfHL62XRX0psRjX{Ps|FP*&0Zr?p?xze6P@Xv`k47k8Oh~s*O8R3yLaU71!?%9t<+HiRV?LxSH#@@{No?p={^t>k z4&;LpSnxPLaRKYmi?`^*j#~2zI#$TowRbe+D+|9sTj#Qj4Rp|Dc4Y?jImo&>P`aKq zHmBxG+5IxvW(GTQPd??&`X$O;da==~<#JnAJVQQGpS|cWzYv&5OZj#+?E~djWprw} zwDuM4Ss+TlXvN@Bx&JwdU=P`@f>}*Mw)$!E)SISN2&8{Y0&{1JV6?{mv(WN zUdB=V0I75*o$V+c*+D}hWomA>9HQ!B#c9Ht+rDolvtOK;x?*G3q$%Ior zMZda8L22~EFlp*FYCb`#%B07=B=;QZ7bt<3bZUgOzLZ|yDFyzan@>nq3SDo%#&n%`<4F7x(y1+lKSQ4OydoymAP;eU&GzU`<}| zyb~;_npYLGb@i19EgxyG+;Zl+@yhijeB&}@hAEA(OTi_){bgl(U4_3;<_}dm)G8gq z71mgNe^H6;r^f$Kyl1LITdLn9)RU9dMaNX_cJ*hrI^%&F_)Wb`)gM|xbr5EE5q9|t zFFk~kW5SLlLh>t9e^BUb0{vbVs)v9xF9c%dvY8wUn zn&I^a;DVmG?G@-Z1zY98tKoRVR~VCs35C@rQjI10@)6JMfUYq7%^77kB@M_&1Ni9L=qr^tWj(Shsa*e#Uxi0plg9u$-2MQCy<>GKXf zs3QBmq6am^wF(`lrWiS@3rvD(WI;5oDXP?H?sGI#tGTP9(?l~^z?-3_v4CYxLKHMc zBqo1?{T~uwL}}m1zkdk4B~5>$|MJMA?`TOT+3*Q%Jx}VtLJo6n7B1 zepBuA!j@ZVOqE&|rzYmBs-JrPlKO10niH>1ZK@`Os-@LR3oo_fQ{|MaYI{m?=%AKF zDIMylLuM*Vs+EO(6q^#owV_gwsk}5@@X5-{LOyke^6~=j8lt%E;u&+4W-IuxQHtcr z2RkYQ`*7#h%HL+Z!rVlZ;Tnkt|6sP?xlq9Vz2Jjxupak$#WA+{GMBfp`X~6K5VkCy z5A|ia8+n(BY*#2>>&of|^5~w-c@D2_!`e*d){R);Xr8QNw_HtwF1oxQ-}4`R+mk0% zP}2ZEu$1Pto`aVn1i`tg)=w0=~nG!DZZLF^do9VkPkipVhs_PrqX4v-rshHZ7lvoSlEiPnq!b6+EQ_HxoH` z=2k?>7|$CtP_EDCdA7>3)jYypDTw1e2Psjf`Ij+D=^Z}QOZi#MYZfVEs`!}I%0#Hl z-==ssRc;)$B(+m+YlO72PJy-`_tTd~urw#ABl z6V6vYR^6D(j+w` zNli*u$tCr9zPk6WO3T#t`D&=FUU;u2))!o=)CL`dMv@xSU#QRs?&F1r4Fxn`*waS1 z7bYyW7s7T3n+FJMlZ11lgqZ8Xlc~byT%p2O*z!>TD}*=I!jec~B?gFGzZu|5xy-4&tC`@>%qED!jO2dwoiaQFuNZ9z>9@aYCHhNqoCqXzJZD_Cj^%SMBIJJ@at2pIqu&jBq*L!&>i znFa?20kiq=X#~)$fOR&5p^gNcHIwNC$nB5)WA#j#GS~wh5JD@BN__{ZG zJ`q|vp~$IlSRd4N7A)w4y3B#eeNYEqSmcC)7eb>W$_{{`y^+sixT7aBQDJ@TQ1x>7 zq$_&667K4VTCaj5+M?7|aBfTF8Vu_~EHA@h}Royq9F3`YJ3 zuPuQQ6|mPL*y;*5w@BHS0_QIG4N(Q9N`X+ZG@Kw z!kA#V&{3;;q0@+@mHWKt72Kp@q^}B(R8KBGxJRAnJe?rSSN(sh6~ola#j5F+nVg|6(y1eks`^T0=mwSM zDlYzNb*j>TteUW0+2NoLUaFKeRtJt(Oa!LNp31P#%GicV(gTwhl#>*t!5h9{yAphh zKU=QE9^qf7C@Il=On=3+nE1C=5=QY&M5%AbCsgr%4Y}=e-dJYGZ}0=3+0!Guo2m4@ zkO8rpyAnGW4B2ZNiMtSsM*Ik;z`y z(En1|_cA)>06YGYp4`mRA5$F4R%g)Ler*4FnmdEdIYB>ru$Tk1W-yz$i`H{wk(=q- zF6_)YI>MHftf5&=m?n(wuw><{Xu3IT8br5f*x8lz24q`&F7;@~jL&FH54Pt6_3OtX ze$#R8?5@Dxd9t(yEYpYm=*YwsZ0!J6vYuslvU&-uW)a($!W=d*Q*+1n2vc6L#B|oZ zk`)!3=>9yVnr*V-4i;S3+vKn0Z^rUXWBB9%p0b$RZsMUk_^%Uu-$ky^=Cfb$g3mnP zV6yTmr8Wv}t<(%uuDB}Ge3h(u%G|BW(~XM%MWsWE(&)7knWy+Eipd4Hpo7|`kveUx zdcU7KE?BMWt$sbCj^CiJd8`gNtD5~)^9$9XO@+$_^{J~cpoKsKgzTY0+jyZmKp1~V zSR5zZ`zBP~5Gv|{IUj{_eZVUW9(#kKT|tMp!lv_3m&WMI zI<&kuI(!`YO+bC_qLjs`^?NjO3%V?#ttZe4E8O7@>fQ|pyhN>rVf+iF&ccZh|6PHd zo8aP2xUeg3b{Ib%h}H9W?s)v~E;YX8xXfZ(q5P=!*(m7;WeBz9)?_n zrQP7=ov@7#{tSTgzk>H}P@f4_w}NN)gU3dISAg*6z;`r=NzK*d^<6hbgg14CX3 z*>+&=`Ttu%*2f6f-V0}E3!AS9#ZE$lEyApN!U%6+$9FZ#QMjL}nixOAK6Of|>bz8y zuB*|*)gjx}z}D&yA9bdreC?<5BBgJAH9k%0_e1#}qqv&3aC4OrdzB&=ljBLTZmP^4 zruf(LJ1vx%Mf|ye3m5tNLVj{PuR6>32l6o+c^?lxXAbYwo!hu@>w3I>Q$F)A>uq4e zU$CDqSkw(xbD7;e#Lnzy)h3_UO4iYjU6{lsjAue0*1jJTY}oL&%tN8|>#@OKO&VCb zDTnU*L9H**gD>f%114!TeZP(-UZWO^Y2s)m+qu59ca=9+N%xivYL*y zqK8*f8PYp}^n9&syO18LkbC*i!5?LNZ~CNIj`X4+PhLEWu74np^P<(6@~hd@GD9Bi zLoIK}ix$wFtMao&^!61wdIe3nDu;yAzSrfZ>*=+d^2zP=?H##fKmC1Qo^XmD&y^cp zp{I-FHCc4md%4?l+WCjv{tG?xPtN*Bp9%D&hV`?cU2NFCR+RQ&arU&{F!p{3&6~-x zCsW&%EFpmAY-8zbss0pOwvX0ivZxC*>4h4nzmPneWy0a5XS3-$d7`hqhMl$=gk$4b^z;l z2$M#EcejLq#o+4?p>QYY)d=*z3|_i|BgLS2F}P;3lpF;4jp5u!z_|~+R1NS{Slb-t z1jGI#p!;6vumW0Nf$a~&KZS7RL%94G%=itb>rqByw5J`aI}mjlgzoyH=F`#Rt?0pW z)bS#ExCIR)nxZ> zZ1;}{v3To0Qn&&CsV39b;5L8Au$7osk`aD*VHruAg>62NXX8xm7;?@PS3V)59Wc8^ z+}q&Xb7XFPJmm;kZBq8dlB<SN?c<2lGegqzJ6=t@>$Kv5!70nHTnI&kWC#<}P z^bYXJCgf>yaeJYIKS7iON_hgtnv`NE!TS=}buB193)LB5<7(K~5u6?ki|c{b&EWEK zL0<{1vxT!aK=VU_*G3StQg|={7)A?jEy4VDLW4@-BU5Kw6RsDlQj`#%rk)rjglF09WU45WSrI-?0a|AE^5lY2g* zrm^6*uAooH${ps?KnFQ~JQc0wFRpZ^Dn0K-b>))Mfo?C7 z>NclxrZnA(9#4}h^z_+b=@O()JEXZ>wpk~gGRogVq!k9aY>8A{BQNojn%BxX^Q40Y zSvOajCCMGJdu!y^>sF>HeS6=Ht|g$aT_bhn8|)0ln5w&MBvjr^+)SOJ5~F zYr(oD$U)95B3+(5jU9V0zYJyqq?;4i-cEGQ4W^kukG^4N!l@r)9g^wn*8EKomE3qc zfwd3dBkkC(T^xBcyL2A6i#`3s?`E@OI%Rb&TijD=*oBA8R8Gz2!5bC7c;4uulAFuj z-zl@8($wU|>Zg2kQ0uQSeL;PGR>9lUwq?q+8)|S1)w4{UHC5ejdP$5^w+;}jpQ^e3 z!WJUbO%Q4a36;5&b4l>%WLO#J{qT{jtH(8Kqz<4|NmOP&rwPuiiO%fBzd|fwk~-yS995dJonS2)F(3+YaUsU`pYzFbxGAS&0Rh5S*kgN z$?ibS366ahYJzI9=NwH?6%L-N>Gv7udT8=r;30!Gu@7-=Pfg?NIM-HFcoM(1&{XZl zbr~5Dg+soRbbp*&Kn{8071zla7pxp2UEAXMYe}&V|MVeMztH8OEY+hMIxMr!MSkfu?)|rJvxaJK)C!)7BI`j)Xyr!09n?)DZBu8Eo7Xq*j3Ge}u=^ zLBd0!dOdJEBs84>VwVeJTY^u+g&&ndkCsC04Pi@-YQI4!%T>cC2%nCtom&cDLe;fZ z>eq4Vi*(htlbRo+E)Z1T$?Bjt3TUU=UshcHDT88_=xjx^P?2^k_gt06zRJxOO1`5q zQRbaZoW&BJ{*M2<#(!VnhIpR7fe%>4AI;#6r*P=N?fddFJ^y6G*%y|lu;F*u&#&y| zewLiWwyk1)FR`tj%k9?Ua_r;TC@lK3G%7L>`?#<0k@eE%tyVaoeIV4e+?A7!kygL0GbZ{w6! z9r@YC%7zi#f1A=^5zk6d61VfZPn4{SeC~JU)eC+Kt2;!#y{($lOv!Oo>kn2e=cvPd zm5ULo^%mvNA@$oiCHAIzrby}XT3sS4oom$l&DAVRA<|WC(?f7tpl%o?ly6l_7YM=y zwaz->>W~6Hii>g zLenR=e$d$o_MZf24}%L9Ltj&3Dh58B1GgT5N+7Jb29JfpD|s+^J^c6uHrfG8MOeKL zrkSJt$6!TEbm0tK*AsQQ2n|C}=ymwa6WQN}X1>TX3vOM3+#W)|wWxm%Oy7=_r?B_{ za>$1>PNCif@X7_`TnIm>qk4rfC<|2;z;{p3?tFNm0G-Q&V_%~99Qf=FTKfp5d_Y68 z;k?gCxdSUp(ZO{1`3vfJ1-g7i2h-s4F9;;Vkk82N2(0{oHYdQIZ_(lHuFzX{E04Lh$! ziyFWki&3-&&hjVK!Djehs=Iw>ilR!okyzK_6{owrGpws^-I@7qCx+o5>wQtI-Bne5B zCJB{PB12@#9Ey+-Nn|LLA}UidC8^Bv3T4O?nIf4988T&-h)8kvTJQ1o{(kq%t+UTw zYyH>r3>Qt!u+T+}Xo4@>h}v5Cv#vN<3G-EM!%`^khCgS6QyV-r5u$Z)@lbI40>$p|=PqpP2<>u!T0_}Z7^?>@mZ%mB z_~Z|!KiIe*EGy-oHn6mat#n~wK8OG0MLF#8gv0l-O&&K)X6@a)cO`#_W4FaTHJBgG z^%8tW$UMmjn&1?m4-&N`n?jYPiI~zlNu5iD`V@>*n7%LEgExEnE^DV zK#5VLdA`!6M!r=qY${(cPia>vJ;GDgG+|lqrWRq{lC%aivUD1(Q`W zv5wqOBiA*N*-{#}mRFGOw3qX>NzX;)c2lUQ{H#llz2zW78a-9+F{T&uWoq%R+}=3{fYz6;l1!yo(euRVNiET2-Bnx}KxL)KlypUOFM6?fH!w<#Rm z3i@Yq*DlcOEQfnRr(0|{70h4o!${cujpH`MI)K!J(6BLNUxt{r;Pe#05n5NkD-YPE zjozc-PYWyvgkhb~X%QIp#XYOR(+8tcA#4_oIRq`1VaGgZxfyHSft?xn^d&@|#%2}p zDQcR}2zj`+uT!J<;=^c-&ZgJ}eX?@hnT2nTm(mqMe0sIU+jSikNKCxU;yKC1e*- zeMnq#5s8^%b$8KZzv$FcB;2#Xgr9>QR$ z80;a87m7u_#g5scZBJnmC>*+r7(da`Mfi*q=3T_@{$gV%F`>Jd-Ch{miw^C?AT=&- zA|^K%ZHDD#jsSaqTti`WEM%#??=7+yVS>8_%Sm z>18xnjR7YyVlnDxV!t4CO-FNIoU|T)4?rabJzTK<0^DeYYo}ppGi*E-Gjy=-0Q_AA z8dtpf4nl1(_5qZ(z;TyB)s$r)RmJHLvlB!aj7o%nr(hKY=hYWnFswfX)5b$p23#8i zg-LM0751%w#x@W!52BjG9e;?b3z@@U;U8Y>4og1s+YS)%l&>0t?hVea54&@D^Ivv4 z$T6RJoVtMXgrgJK?;3ZB=8}{AWe$(a;N6qCB#FO_;(%Dr_2ke6oZ`wWr}Fd;++j37 zHs#y>*wuh_oVimScDClzD(JKYJO3c(27L8B#WPJVp;zB2LOluJ(!m1STTDaFQR^F| zf1K9j(VYX7bd)ykq}CZ!noK9RQC=cVSWnyHsbL&NL{n}A&0a{=q4atV4VppzL9}xc zeF>nyV`#1)1rDPXW9UVHvKc|ey=a&hP3cB|JgLHw+V!E09qDxs>SjaM-6*gf&FM

7L%M21vzpLRE4rmeJ1r=$5ha+DOGDBzqwWnTrVV-4r#Mr3 zT#weYrr-6*q&4lRPe)8>Km+P-qB^5!vI!Nc@=OzoZ%h`g>0uKZX-fN40KO?TY(bsc z(v((IVMe3dP-Z(SY)8SCQ1L&gXrXJ8aRxmgi}9nN{c2}U%D4h1rurGdUBsigHveK zOiJBNZ$s(XLHZR=)+Z=7iYm_2zF5jHr2Mti>;VOCrdcnjNg7@KNJsZjdL?~0NYO-% za#Ue2-#AC-nsCHb+GN7#?@+W2*F2_|UHDQdUF*fMU&zdhA6C&OA3lh@a4J{T3i(sO;Q|a<0IP3-Z!AoE2A`7P%tw$Ju%!xCodWfi zw6zdA>!ImWh-`(nW#DduE(*kVMHSHQ>4E)QAr8kOc6iAThq&W{AiOaY4~AjEBrJ+S zw@}nh#LQ*5XB(PsM9&Odxf>@O#lOce^c+6AjBBo8=OS!egeyuh?KwXAj@v)r9uRup zRnzIebmakKF;^pA+K5T@g|4%>*hF;dE4H;1<41_uW@6?9;bJ3J1gXjxQ9DeybQKMk ziG|(8vNd9RZxNCt`g@Av?c(hqad^Mb3=>*M#Kw{0)+u2yS~R#IlE;d|t74t62)_Am zmwEj?Q8r$fKN1Dwh4WLfYrJrLE-J@~BQJ%EuW0&OM2rM#NqayN$%(Q$kBujLQ}! zwZy4?B2%>sriw-1@Zoy(YKp5?i10^vE?hViVpWisn2U+yMZ!Vs;3cxt(7C%PT8r0h z#n(vmY$-Isn5RmleO2ck#u)BO_)f3T8w0FuB^0Hz8q0>+A2-5m3qdC zOO|5VObN?UoSG;$*~$k!W&Tm6p|0YdqugzzB%N0D_0-ByDOJ09`HD+ZrQn8=+FUtR zq||Dyba}4Sv{PI@D8D)=-G3;5oRkry#P?Dr)stHXD=|jW!AIF?DT}8mx4KHLFlBCk zc{Elr_myQ^lyS4f$GFxX|iwX*`OmH_A^TG$vcRt)^bLWZewP_$7^|t9tm6JOjWRV6voxt^HIu?L8*XVlqclyPYs_Oc zQgvgk)`V7TiW4>JKDhZNjdLTd`AHgmBdxPrG{L4?wURY?mRcTLG>z=Ev^Q&t?X@nh z*Q7gXEncg6>8xcRuW99~^{GEIZ`qO?Slb6>>W(tOMl z*5@?(2gLnM&6Q1J&Q?v>5|JLO$($zg=4f6I5kccLTb;y)z8V!-*27MdSWC<>)C?)Z ztt52s;f=TAaSldZ7u!1Y=Y@sYU22d0n1#BR{X6}3#Dvk@*u*!&yl4cB=HF<1G|QPBC1 zXD5Qe8vYRsCL#QJ0OSnkg_dx&3)j?wx6N7a4J$;c7ue)2Ii+*YLK+dl9}m-PAJ*GU z$z9nkg4_%_WHJR+QOkjp_K+Ui(~um}Hm3N^RG>|L77$lRt8#GhyuB`Ik_H} z-cl~zDR;k;eb>pKm!9w`r8l!1?wj-3=JR&*_uBaf9St(Ec5l=DVPotMgnCQ9cw z%9}>Y@Q+HD`bzj$C900n=$A66wvweNb!#i#Ysm+-l~E1ls=CT6LpiX4GE>Dv>#A!< z@`!;_;Vg?=C|~=^*fz?Pk#dK%GS**u*elm(%O~9w`)K*CpJJ3K7miROcgR{3mC;A! z@?fR&Who*Q%|p3hwKC#^oW4yl{Ue7SR9-e9=R76Dl-A!>o;%XlH%iL^`JGl`~GztZ8z^O)`jUT=<%$Z(#w(;zL!2d zcmQY_ z?Xh6h6w|_BnKhnCf-&9k#&K{Rh7*fGF92tKhl&NbxDj5BM{Qd?kb?RHFgg>Brs4Fn zxI^vn-o$o0(53`4b8$@>+7)A^>NNX~<7*42`l7%TBVDZZ6}56igDE2Ex@bB}9DFHSFA({a;#j2c*U?;AE<|(9xYgo-%Ck-s z54&kvB?--7O@4}S8>g9*E`H6>Wb70<;TqpPB3ccZ?-PU8YbIofov9k@{i0@{raD8s z$5dBYSZ1#yu=QWM@2&b!>$erTC4b9ASG3c)5Rf?EWq?wc?YCqBhtQXnEnu^up zW3guW3bC(Pvtx;v`AE|W|aeuMll%`b= zVVkX~wioyIX}m1OvQ$l{mZBh0)4GvZyIj*yh$&$j)$!7Qx@N_Dbn?;EevC&3Xp9Q+ zw6iAjG!|KCuK$O#4KzVp(M)IzS7LFwC%~sBX6NqQ(am%UgS4XJTBeTha3vS#r%V zMQ?^&)mPD;D#N-dW&YB~UKub^wzpAC{p1ug<^4Fhxs|egoNU)zxj9ZcH&y13mu;IU zbtlM##>$3C(z~&;HbAb|S84^y<0>#=ro7fn=`%<6Ggcae$u@13E0J=Ul@hsJ9_^%T zTO%jCC>=J-xqTGZbUA;BVz*yD@>O;ml_vs~m~(Pkm@=|ZCdVpi59Q$`|B zkekjZ$s|K=DeW83@z+XrOL|(RShlA>^<_#o`q5T~4yI67dBcxxj*#`{P^)0+5kpU6 z<)6(IyHjrZkBrXAj_1haiFCV1slVjKcl5V0x&NU_9ch0f-t9&D<~${sLS1;>8X7W` z&ty{aRQA3>uOisLjLbLk`+EH1KlW?Sn=kN_L42l|bAvhfD`zC|>RPZgi=A4+q`N%K z9_+vK^Z^jr80t)d{`O!L4*DbEcmhnE2mSWKf1AKR7Zx0c=zGxn0j&K1T0cR3;XGHf ze~t0KPWZ_J#ZXM>hR=i1VHg&y!Vdv>Bm=jHJAP#FTWj{DW$T`B)Rt?Giq* z6`PCjPhTP5pxp%Vvl9Qz7pfEN`WhkiMEhN$VQXP}Qe@eR7B_^yi?Dwow)7RFD#Vvz zA`vyY}GD3Wxrui{XESjKcIa3@RrFrTv zY6fWbjS+r5G_}3N)6SYDy+p9Nra>2BY^d2`CEn_22DB8He~ShUMVAl4pV8x?aI3(w zOCtLfW@L$dck#zIaq&F*#EA)qaZspekcNKa#MM>!$3wIX$M$w&#uN-S6oZH31;*U& znECxv0c)BSj9XR{oKTBIK&S zGH8+9sK|hDxt!$TF!=%~C`=yLP@{0^uR|sa<=T4GY_V*mOHq;1%7Cs%%N@-re!2Y9 zn%b?D1s2pLK?*xMwNW1KLd{d;`0n&=hkW0c9QOa4(0#~~-eYO$DS5`9VlGPkVB+g? zR2YRkko%UB+e>+O4bdn0dkb~_B~>Uv36NzLEvZkAxuj!6T?#1HoU)4Ob7yMxik|kM zO(6ykgzH|90EshN>za zHur&@b>Qq|urq|WGa=Uu>MejLo#4U}SkfKl#DUd7IJFLZN5k?huzoW5Zih=DaBLqe zT@3pV!Tng+a2$*`K%-pvlL`qJ;Xwv$E&$h~V1Em`oP`_r!TKu16+`R0kX-`yPoU-% z^ecs)@4%-F;y*!kCH(pVHVXJus8I#HTnSCZ`gTINBU<{e?tRER`_J5)&C7 zb--PSeH`(%KsQ%3RIOs}III?q?2E?Q7&H(UXk+|PRs4>2qp*YO6B~=MI=Fj0&ey@0 zlkmGXI!(b@+9;-Dc`Y126Q|e0J|VbJ3-jk-yao@g-cX>Ev$~hXI0QITGdy=wrG6#1InT?tpaXGqyJaPj>fz)Xs0G2KS4?q zK7S88mf-%ka6nbVmx5aaj(Z6&7U8K9)dz}upQspo#A1k^hm#&a&rlq24-!Mr{WdI^ zi8eQ2^z?rl0Yy`=-WBNMkJ^{uq92y$L7@*u$GuCEVwWfE`x~Q@Ma0vRzTV!2>A$J3!wii&gE|vo zUJi`*g$4&LD|4Kc&u_*Qr@2wtp%XG^PVwDa?0tw03b-8WW@tKM|c;qWO*PR`UDa(oVZ`1aU{5_v)thm=%8rPQB z9HX3;+&`0ynsVrFDs99`+sLC1ciKcz8n#|bgC#k}QrvG!jUu}rv}hqc{6eGV(vlCP znMIpQ>0BV~eNIJ_$?6FOOrXXOX{0Zy)UQ*csr)7xj-)-Y4m{C#9UAtNm%f39=kWH953$5H&eL7DFic z1o;i4*poDMB)vREPe#-BGj!6I0?yK(3G_RU4hB%dMY=Sd*5*@I2vru)w)u4Z27Osf zbcYTuqXQ4<_DVYPKq#%=YiLG=_MA${Om3d zeZwv@^&R z^}OnwhBgHA2gYdD<@&|NE{l7{gxXGSPu5yf_F}##a4Wki}kl*QXZ~I#n21rl!hZO zVR#x&yNo_*I6oinq~e);e68mB^U*W~XXhht!MB(3@n&3o2|sMWYZowa9o9XMH&?^)2(0Yz#dTO_j@R?l5hmU`3e~!Jb{|A&V_phm{Dlz-aH9g^mO|n?XgeQ9 zKLy`F$hi$F&9C`oxaS2?Cn2LJL}kK92Uxxxu2?|qM%dXLtm5EP1Gu>eZUW4i1qMIa z&>vLqv)?Ef@RZX%q3bRF>Iz>ka0ff+dz@Rffs_mmFo5yf_;hV(wvPAyWseyC{gs2l zxcoJz1aXgtY&(&=UE>QQIWd>>`g6@;KHHr??_?7P9=(~rT5(Q1pEltY5xmNP%R{(r zeLg>#FR8}z(R{gvrVZr63fkU-RZie@dsg@GTUoN(V;bL*pWG!KJyy5s47B;xB{Kg@ z!_JaZ1sR>7qwmN&o2;Kv`2lKhk1F=k*Q->ygSwuhv#IJ$kJcnprvr3m6Mfi0C)d-T zEp#k_qSw)()l?Nr^H$ypf)_BZn>2 z%ZwhUkZ~I-PNxB_>G>}5GNIiW)UOo<9i#)sWPgN0jOqLd`fE&s&r)0~D!xchOvvgQ z*_zVg+tjBmU41|k&FR%Ma?Br`E2B(d@4-i4|nNd2EQ+%?nn9TCpvVNqpL`_fDdW- z`90pM$307Uxe051;Jdbb<2#3UpiMr^Tm$kJ3`vKF#bA>S171U&OK|=(EGdGUmEipjUMY}Y z1s`kS=GvIl5Yvs&%@AwZV2laY>xP9ExNi{tXNUd9<7%gWwXJp!JRXU$eKBS&rVqyN zsd!=}jz5UAeGzl<{3P68h$pAv+hW`ujFaBsrn&g^2VM@xwT$X?>`gs!Y8l=%6m8ce(22Vr@hb35Ru~-m}tLKX&q4;x_aGHslKrw0x z4xA`j_+i9ovD6y}dWje>^y?!!_eC{qHrEaNcMyRN*t(5Ku*Osak>45>9kH${Dm7TQ zKK3lb=7?4$_~;jS-^9+J;bJaYzfh45Xn!AWCS%YQxE71Kr=adU+?EL|C!$R{=nuwI ziT}>S_sigGTg;mW+KsT|RPd{TBctK$8z}IE3Af;@GyHb~4p>9wb_i<$ALIXdcNfor z0}7uR3(d>9swdby=T}y+`xfWx!5OvbTEhNUk-cK7O*EE;Su4d((i-!2UA7E18ax4SJKFzcliqqakwMSgOB7 zCQhMNYbAtIk2Gl=MHddqx@)O2Pku-t=X)~ZKYFSTRZo%aZ`tq~mDHuWk7>IJ>3pOk z4wO?(HUsEV9qu=gOk1#Z7_Df}-U+m&JHOvcnM3*VIWm~cnnzSTpVxh*>Ue&p!}U_R zsVSRh@o2SOc8NVkvht8S&f;^Q*eIT(B#+p|j(U)ImVcSS`A6KRD-8Y4av*GEn z)Hlb&*68Ynqg?U8NZdIPo6N-3zIbsNwhTi3t?0Q3F$*upW7m9qoP@_8W6~b9F2|%J zmdSOkA=0p_@m|o97L0MVuPc& z{7GDJ6pg=%_Kw2)yC}04?<&RM&SJtZvC~f2REeJLMd>fm!BTwsDK4}XuYL%RR>G`8 z%xNY@eG%*RM9Bv+vaZ-yDuRTVQ6jF@;KGOEK?R205*8oO?25Qmf_b^3*?k;wL>#+{ z@%u#88O%))afh*Uf(YD+VyPIg3Fplf5wZ9pKzN5^@+c8A9jiUWK_5KqsAe1RkeS%; zil8qdY*2z2&;mWb;_SNU{tP$Pz^ekB`VsCQ!;(i3ydB3~fs?CHU2_;P9}n$>vI!Wq z4mu3L(UDMSkLp||z!*=Bfh=v@+82I*0}BVJd<;3Jka!VxHv+c<&{gu94PaZQMoFRd z6Hb{7CI$R!AcW-bL%b0+_?QV_oy;z}oI9AqkkxWbuadOd@Yr{Bygp|ZlR-88cb%f&P}Vu>b%&-Np|iPk zYcF-(Pa9JHrGSpEqk%EhZUs5cp+k%5)&#N(RbS;4FrBV;C$C9lW=9EQsdH@RKqyhaxV>u@}hUx*UFk93RL{ zkLc?Q`SLY+ewMe&>94waSwlk5fm(dLA$`*0Q!OZ}6*smbT^lxVqADkz=|LrZxYkqjA0&P71(%mKZe~m$t_~5qQiF zkHleVXS}fiXF6h+G%R<*K^bV~f(?$K`aHHcgLZEC`Vvm*j_x5ft!*);p;%{v`x}U*Ezq>SurkEmb;Z@j*s8W@ z*$_w85{7lqQV6v>mqTd4kn{)V*1)Y_SWpS)D$x2X3@St0kFe<-b}NOBFY)Iyhd z4^@adPQL@;g?RTGEWC&xE`sH09FYrMvvKBeDBp*%hrl-tGxovkjW}aFyopD*WEiJj zrPhPhTr6G*5QrJepyN1fyBO*Z#r<=kvNxK~1Y0LO7yu#G_-q{b8{_0rp!xxm2g68# zw>@CUPtfiT-tWP^3+OzChz>BT5Kgv(yJuja36y0*ydj7*xX}o1uZ4zc>uCuL2WS=o zTdR571b9`!t%gG6Cm!VvS6}msju7~iTbP2Th;{T}%nj~`pqlg6f9D@(`TlF(l*1PH zxyNA+zQkQK_{vds+QEjq*?ud}-pFwqxYcrAzMAjMV|4=lU_!2n5_9#0M|9j}N=$>J6zbmP+(DBg+B zAE(&PZ2BL?+VagbDz@au>T_qt*70=Pgl(2kXbZNOM>7oh&I~%H&-(rZx;$|#CD-Rc z!>DT=Ue}*2w0TZ13efODS2_T^)R9&a9k(MBg>0>9$)RgpoldUm*`bD3N z==@Lm+LXSk7WyVMsgk}lrcRZ#Mo+aQ(rsNbsHBOy6kAE_b*aZsnxRL7f6=qXG_H#F zG@+Bf)fNyH03Yp8`B|4d96tU%x07%_@foAuEjxibg4G?bfls6d9o`#ZNwJ6 z=%hZ!sUuWFb{a-wTXO7Jy4#vf{VB~RhV5fR z5|*sTmsQ}DgrZwg*e>%=si$na$c<{)0*jX4_3-HWqo;iL>K(#8|}@w*O&{)eY) zW8#0n)rp-C<5o`Q}VoS%e! z5gTnleFnd^|KhBT<8gKkELnzwsvso-Km3513$Xn+*c*cF%V0wwT73Y=N%*W3R*l78 zFCcjs`aFS={jvQ6xb2Qrw;{s`mlndR4oH`wr8!ofgX1l*-6=S#hj)&^bR7)Igc%YH z_rjAO&^8@vK0x#qnDrdiCxXX)@LmaK1u$b7XwJg>MesHoj?IN7d!fTjXqEye17KMX$N+HqU>`8}iw(h!f8+-sDx; z{5zi?@8b@6Y?{WiPxASVoR!UcR+{6n+_E;`9>Sqo+;=c*Bl7^Rlr*|OoBSoee!Qcapf69W zqSQWY_mkH2=Jh}5TrV!GpdP*W-8Xe>l8e65%AP#=D|z?i&*c={|ZQ;ErC!1a@ z%c-arAO1>(y?N?4%I(ABE7TPjp7fm@`*GP1y5Pyne^Q?T>|I4hgV?E>-VWw5s{MB; zUs0&paCTsd9?2h(pL_EsE$%&5#ouwcFTbnHTl}~~LtZn9&*|}!0QNHAIn%hL8Bd~G3Vf?;5-(19Aop{g^KI+If)gRo2aRp!Q&e8Ear#JUo z!_7Q7e;r>N#633h^kJ&df&INXB83O|^4~P>uKq1{vgH(Z+{=bD_}hLS5W+zR*>N75 zXY;g$oPLbGmhkA492vugxttZxEAqH_E&sj9^)~X6D{Pz0W`*pR#_Ml#%r12*#+ex$ zQp80E`N<=$I>Me$x#dYd`ka@a<)T-7@FKgv<;z#u_XC&T;KI*5;2ys%=io=I^_^p% zahspK^A)@OX07+E|A&prxV>ci3f2H5{^F(@*z=E%>&CQO;tf&D$8$&7zr(F=h$ec=3D z$mj>B!Xa<~OpOHd!Qi_L%7%bW9PAnnM^{7ODA=0_rei>BGraVH?5&VC9)_jE=!u~0 z0-wn+Is=+ag`7;d9S9Ax;Z_g?9fy^(VDTw%odb`~g8MvpcLBaFfS>u0xe(4?gWVCZ z;wFrZf_`_Q!7{j31m~B-nqrt62N#}#*(&Jq0ut6h$ZP1SrfT29zV)!~0~n|or_Zn; z35?4jJsFmL1Kb8CKcGz-IRAv++hK4O80`fAYN*-;9n^v59ys$C{Pw|51h(?FO4)Nh(&_(phg71Jj+0YlzEgRAp0<+;DL3%cXN$8Oc zfB(X}EQt97YqKD{8a^HdhbpLj7)mRl_#ha3hpbHK`W4&{KRpm-msuZiM4 zkgcZBcfpEhV6X#jKY|fy(CR)cPl49AAaVeL+P%)Tr&yK2Xpfj<`XFJN)Vbi=5z>9XzxJ#S+??!6{Q%)*PanLy|81RkzQy zA-W!1R~WTm-w*Dsu=7Wb`^ha|@bWKwtcY*F<TZ1ggv}Dp(+3L;_nUArZlJ3;u3fEl;r2aF25+*o==pMzb$uu zPi7We^@1Etxu%$ww%~+&^w@xnZ&0>+*j}M~^?2)fs?cV~Gn68@T@JYuC1lgQKje9k zK2%Y+{WQLk^7fE#1zp}rDdluCohFshm{hXR{WtYC+Q|p#aSAm;oFy}Rc-!wjb=39wRh-5W1jYi3Yzgfbx7KZ zXTPJF<~*jHe%f&EFKT4Z0Yu|n*i(n?d+}^tRtYmrn{)Hwe6B5r_;9H$_nyoHx^lCb zT;7W<=5x_tUb2L9#_+W`ZW_R;>p4t4MYnO2#q6+`D`Pn(i?46s8>iWNJL~7OQzmay z5rQYV`4cwD=QnTo*j@Jd$~~U5aSi8x;s+W?tm2yup`iwr8NvNV;AjSGTf*xO;AsWx zo#C7#bnOEjdcjLC*y#m*#zGxmcrzL7r-7ISqvnEdI5UP+A2rBl&?o&{G1m;`@c?O(rL)2x6d<@DBSX>G&41Y#9i(2@>tBZ!)AV%)EPVY<2MI9KLvH1@IfGMSLx_MnB$C9!FbyRaW=cSO?GfhS*6dg?5~CQJ<*B4p*K$d4KKRk zwhCC@1vhyR)dYVAi1n6o2nIqwET?pt8zf~+>ceq%^R`zh|3xBqNJEff4 z5*|I~C_OO0!=toe?iFtHm&IBB`;A8(3-y*2%GzGMCXh?}vdaW^cIUED|4PoM zgLtMrH|)bhZ8_YPcUW*|duCI9Zq0XEvVL3sWXMZea94e<)aQC?X0kp%uFLmpv4sw+ zyWMj&e7Kt2fXDryrIOVBxGR6C;yuMy)0Wq?qKcwQDDNljDkj%T>QhA4Kj__Un)sbG zH)u@-jW3{u737dl6Dp|hMY^bdl1J*5%;GF{`$0cX(}+rPJw+dW{u}MhucD@lJ*~?dce<)k&|jaK2BlUeE2xMsKd8%=yn4xJ3+_vc*Q9yR(W@4s7rI6 zc9!ax@Q*wyZOcb4Qnn=@%O~u>Uka$VJ*VHG+RmJChw{7gks^xj!zx-fX8>oH(7U0$ z;WZhI<|psz?0BB>g(e1Y`FG+O{Pj1L&S49+SXSxoT6`~xJ?n8vEVpmWwh27Mi05tQ z{jE7qtrji0#~!Yuh8!}v*oobaaT9kwd4|0`xzi=Su15X}xz||Uc#kdoS?38i3F70g z*mfR|`^dv1S*L=x$8yGRc1mPJ=CfP*s5W@+=H?Bd?;$>60OBM!F$Q^o!_2_?2CugP z=>8 z;R<8t|0_o3E`}dNz;`Kh@_|3G&@}+|t^p+&bT)ttgU~H-b}4L2g+8kxekc6d1l{*R z?{p|X0LwDKKMO8o!?R;>^)%c+3Cl0RliYt~@(t(VRuQyTtEv*%aTUzoLQWxc`~sJ5 zLVhJA-+_^Tq4Ry1BQWs+tg3@29>Ek{eDWCXHpTd-(AgNBOTerxWlv7gMYpF=%Lj)%hI2k>_Xz&@V7&*Rf~Ugo!4?(Tc^kfs#pX9* z#~3sygyEy{=@l3;3Ii^I`3U@#2RTErPcD=U#ttW8^#Jrd26g&jwR+3yjk6BGf$sQr zFVuHIvz_qQ0RvOvv>kTY0?yW0cLOvr!~N>XZ;bA7(8drCE`)`(#T?sr? zZyP;h8DX^1o=A&|N+Cph+EbB28zmK`lJ>q4>vGXV3jiDt-n}Ka#;V~7F87P>D zfLGWu21RMe8V2W^a2SAT0PskZz2#1q0WBx-OWYYsocuXtND68 zm;3YBN_xy;{!&`IvCNN?$4e-3$xs$~Qq7hpr}02fx=*2ZCytrK6XN(7ibRe3)i|E{vJS@G?bE?^fTy|P@tQ|vQR0G>`+zFLY8?HF2>eHGz5vp~qcs5*eN-y89 zDs9Pk!74>77VcFoXvJlFR6SeMTL>gt^U-cqm$nSwtqN&JwIG$3ArpdBHb%U@M-|wS z{r9O#I?**m721`Fp{n@qj6R^cVa_LqRJIm89H}a^WY|g7I~xJ^&1-pkb&4}#}vqcXsJjoMQ3^~PZgV-#Ifn#_$g|}VV>JAlN zeD#ob7IMQ&`mN%e4;;UZBeFRogeC>_jimYyCY)yDTDG~uQYE+C<4+A#yyPPV#%A)F z0g4J4(H;)JDBReD&$qcbCMi&DiTKvoW{*x?pf?QueGoYYNdr(m3AaXLh&vv+Vvi?6 zy%0DLvlqeHA3s;2-*QaahD;$?4Tkd;gdM@Iomd}-C;RX>2@&B4yaDec*q8>@3An$4 zXB=uWF!c<~zri^Prln|h88@qO>>5Ukejv9nKwb9rE^2jT$I>vWxopxC%x)u#d5-4B zvK_DB(N*UE26pDM(s%gUM`rmE#x}B%pKxFFTl@@*!7|@0SPz$N`hrHIWP7t=H&$ks z105&X+8p>!l-O7mxU+4Y~=-f?kRhlh<4p%mGS6pA}fhPPCHqABxVRl#0acvEQ{Qaxmq%15Xy)? z|6$}`^xg#fDyXf2O))+$!}DCMSOlvK{P2O_E6ni3u!qQSN1Iz{?}Dev@EL~z3E1R_ z;1hU05Sa&1VFOhV-do_uX0SW*SEAGe35(FGJp$%Hw*`i|!=^E^oiI-eTZh97Fzt^+ z|M;pml-1nW1yHL;))vSKbh+@8Z$kZHuN@dA=mR{$$ z=j?u&nfDlVo~y5kB32Gc;=LH^$200UM;v3~VXh13pKz83(JF+yw(?>S_pfEp4n{1a z&sM(o?~PU8+84xh#W zjp#Xz#&VvU#)TR*o6c`){4kxjWV||qPr+1?S%S3BcT_F#Vj5M7IaE@WF0xGEJ0CjA z_;fx^)mZDxb?Th3h}9bWxR~j3h6M0)BMx6qeO>lk#kG2phmT`ZPT4>^eTHr3td`W; z&P#2$d?&39nIFUgV{Q)S@6H?>Mp<{ZilBc_W*=cjAAUSe|9*TXD1Lk1ju)H=lh1Ip zBh%0Gph(swGk*dVSGmWPW;ZFH#=um5^5nh;Jm0DGk~eicW&=gSRr z{>0zgIPZ&ukz>B{=zd80v8Kpm||sL9PKH|K|5OFYCmkX#T#3E8GwWR zVLc4n958bf3L&Y2pENo zrC2r^pO?dF3@)t3&oS7x9w*1bY%_+9!-;LUI}Rl~U^gDUg7DvXjNFI!<1u4D44u#> z9D|*Zeh|}~F!L}bI-%q!20FpuI4qqo>Lg5@Ff1Cy<1r!@XUC&B4ok*k?w!<=ZMH87&*cy3DbvT!+D$-hBxQ%Z74L)p=Jnh7Pdp6m59}Yk(q$ogRuQH z-VOv#p`~Eu;@~y_u`yWcfHzUNY>$U0@S;DS9YcYgl;P=SharbC%oZ09V!92i#gg6+ ziTiQO8t=tySmAFFsw`2v6S|hD68WFLc(4V7`e4CEcv+xmEmrhK$SNG_h3|pF5&`{} zB3*@dp+rq-C=0kbX8*$}JEP~8r@yW&7wobCwEHn`m$^47>~h4(G- zqB&Nyz+FB3(#O?C2yc#U>KN1vn^e5g1mpkFx-llzFi8R9O7;?vri7ccA^H?h3%R*; zmg7<;6EyJX0~^#3olY|ulAm)jdH)fU8u;!Wv+7xVi{JjS;VPT_<={(f@taBK*}jI= z3G7tOd2uwaV&+L&R&cct^OVz2B=$>L97YuLYB2K(m=eUa?>xVQ3E!BxmHTqpV-rVa zbL%?x$s$(M;4?2QCoAI^Wl5#Drv#wsrkd&1aR zob`xtGdMntXQy$X5Mz7L?XHyj3cN$zsSLfv%dR{tdcjZT>ubE?!e&?5%!M6*$3GDG^ZS) zdjji^GvSOhXhR~sPV>Y$PCUmUN%Tx+-UTkd%EV-Dy~QJ!dF382q_F%EpI&3@7gWE= zfHz!ln`IyQG*uFXPQB0MZ~T(RUPavZm`BTL_l%9J+5aU)pst@khP`n5C{E)I6aekP$6MlZE+zz=P zT(@GQFRpJw`T~4jkIoBFy#~(n@pC2I=bEyiPu3%ZV$$PQCS6gr{p5O|M+(gEK_ zxa!iUo23Md7H1YGatHc+wDxI*KHDWi9))f=VbK^r2J1vrW;mlneAQsgUD! zur-gmS`ZQ1YjqfAaUZZIgRbJVe9yLZ+>y?_-?V$l#9u6U%EMK>@rXNqaQ_3YE#UjD- zXLT%;mqZ4HP?bQn5ayibrC@$M#h_rS z;<+W5hVfh-%sFw42$lkv^TBKy%b&rFiedKbNPSLz3 z#){^;FnUDOF`Qx1G&>+w3+f+a*BBZ_aBB=Z9g=Xg>tUXV<;o)*5XUn|$v8GX#@u*% z9%q_Z_f9bOH2X#IR08is^Tio1jb&9L|HiT3Ii5Ymwdc7cfw@T>naGhBseO(wlG$*c z&cg5I0_(2uZ8DEtl@tr}uCpkGJ#O;nHA&^t?j}Fnq2q1dyvseQymy}|_jo^z?bG=D z5q%!9^a-CnVejYC&E+M-Uozx1Tcz{k8yw3FchxiZ zAD64RPZ<2jFpz>r7S5*d*1|yzEYd-HElklvp|;4PV4nhW^(Dg5w4FWu0wiM9LWE4g1bWtq0NScT$KV&%J&;rrt5AEkcJ{Eht@pBYDdg1N}RLn%caB!L^_JL9? z^@DKT6}AJg#u*p;0~4Tci``@4VvUa@v92$A3`bON%p8mh=5Tkw&F*lsMN(JTT47Ts zbhN-MV>~rOFGH*o--B(S-3j|!VrK_f>!YC!a++Xv3(QvFZd24Yf{p?+H8E8Se`MIC zCP9hM4g6Ne;=i={!)`T9{>4F+Y*{544DKuEi30vD=F6}2C}33m_bsnv z^6EaXM_^ z(MZl+%PmKEVHFb&(P{;siUn{P8z11orQ9CIJ&UOs%D6?m6v8S$E)C{vUryae*#ger z%NO&wXAh%%BtV@#mrg;{oy+{)JmAg4yJ_#u|911w9QyBO8;s$+-(qCJyKQ#5ak^#+)!kCUwt)fx%y@z@ZTj8S2N3!S0U4L7>MyeAHtqe)-P zv4Fw`-K`+%%ZhDqb}-i4Bft@=f%r8V!9%gx3E7S)5SP+ujGro@ymiyCZUVw)iBuA{ z&%tz8%%6wOZZP)43lE(0$LtyC5P;XSFn>8jA=?>|Tk}TLT6p?k#Rl}9k1m^`>x-LP zk?05G|6sKUPCIeZA6~ohWif{DLERE)?L)~@YzxM%0DKkn{W3HQMgB4vg~2rt8sP{I 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 literal 29314 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 Zw!dq+{npEOfBcho-u>arx85j~J_Zedc$EME diff --git a/assets/sounds/start_screenshare.wav b/assets/sounds/start_screenshare.wav new file mode 100644 index 0000000000000000000000000000000000000000..7b72a90af16a0c3b539d0400fd175c4152369083 GIT binary patch literal 12188 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 E0~PTRx&QzG literal 0 HcmV?d00001 diff --git a/assets/sounds/stop_screenshare.wav b/assets/sounds/stop_screenshare.wav new file mode 100644 index 0000000000000000000000000000000000000000..1fe13e21b4246ed0fdf9d3778955b02b64468e99 GIT binary patch literal 14024 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 H$sqp)Rh24{ literal 0 HcmV?d00001 diff --git a/assets/sounds/unmute.wav b/assets/sounds/unmute.wav index d87decead02aa91fbcccbd661631636b5ee0975b..f8c90f691670f01f90505bb26592410dc7733d62 100644 GIT binary patch literal 48834 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

*xdFeH?dx;nq&{_=fa#81(@Li;$R(vv&BJgoI&O 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 IF1cO*2aA8;;Q#;t diff --git a/crates/audio/src/audio.rs b/crates/audio/src/audio.rs index 0216bf47be..233b0f62aa 100644 --- a/crates/audio/src/audio.rs +++ b/crates/audio/src/audio.rs @@ -15,15 +15,19 @@ pub enum Sound { Leave, Mute, Unmute, + StartScreenshare, + StopScreenshare, } impl Sound { fn file(&self) -> &'static str { match self { - Self::Joined => "joined", - Self::Leave => "leave", + Self::Joined => "joined_call", + Self::Leave => "leave_call", Self::Mute => "mute", Self::Unmute => "unmute", + Self::StartScreenshare => "start_screenshare", + Self::StopScreenshare => "stop_screenshare", } } } diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index eed73ba1b1..87e6faf988 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -1222,6 +1222,9 @@ impl Room { }; cx.notify(); } + + Audio::play_sound(Sound::StartScreenshare, cx); + Ok(()) } Err(error) => { @@ -1311,6 +1314,8 @@ impl Room { } => { live_kit.room.unpublish_track(track_publication); cx.notify(); + + Audio::play_sound(Sound::StopScreenshare, cx); Ok(()) } } From 25564ea0585120863ba80e8c58eacaa27fbf8c2a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 5 Jul 2023 09:39:04 +0200 Subject: [PATCH 066/104] Introduce a `WindowContext::focus` method that implies the window id --- crates/context_menu/src/context_menu.rs | 3 +-- crates/gpui/src/app.rs | 9 +++------ crates/gpui/src/app/window.rs | 4 ++++ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index 296f6bc04a..f58afab361 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -244,8 +244,7 @@ impl ContextMenu { let show_count = self.show_count; cx.defer(move |this, cx| { if cx.handle().is_focused(cx) && this.show_count == show_count { - let window_id = cx.window_id(); - (**cx).focus(window_id, this.previously_focused_view_id.take()); + (**cx).focus(this.previously_focused_view_id.take()); } }); } else { diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 20043a9093..fec2ca595b 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -2971,14 +2971,12 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> { } pub fn focus(&mut self, handle: &AnyViewHandle) { - self.window_context - .focus(handle.window_id, Some(handle.view_id)); + self.window_context.focus(Some(handle.view_id)); } pub fn focus_self(&mut self) { - let window_id = self.window_id; let view_id = self.view_id; - self.window_context.focus(window_id, Some(view_id)); + self.window_context.focus(Some(view_id)); } pub fn is_self_focused(&self) -> bool { @@ -2997,8 +2995,7 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> { } pub fn blur(&mut self) { - let window_id = self.window_id; - self.window_context.focus(window_id, None); + self.window_context.focus(None); } pub fn on_window_should_close(&mut self, mut callback: F) diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 743f99ee62..4edfa5b284 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -1096,6 +1096,10 @@ impl<'a> WindowContext<'a> { self.window.focused_view_id } + pub fn focus(&mut self, view_id: Option) { + self.app_context.focus(self.window_id, view_id); + } + pub fn window_bounds(&self) -> WindowBounds { self.window.platform_window.bounds() } From a8602b2a0ce9d71593cddea0f8fdec3533aa1783 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 5 Jul 2023 09:39:56 +0200 Subject: [PATCH 067/104] Add `Modal::has_focus` and introduce a `ModalHandle` trait object --- crates/go_to_line/src/go_to_line.rs | 11 +++++++++++ crates/picker/src/picker.rs | 11 +++++++++++ crates/workspace/src/workspace.rs | 16 ++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 0b41ee6dca..769f2eda55 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -24,6 +24,7 @@ pub struct GoToLine { prev_scroll_position: Option, cursor_point: Point, max_point: Point, + has_focus: bool, } pub enum Event { @@ -57,6 +58,7 @@ impl GoToLine { prev_scroll_position: scroll_position, cursor_point, max_point, + has_focus: false, } } @@ -178,11 +180,20 @@ impl View for GoToLine { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + self.has_focus = true; cx.focus(&self.line_editor); } + + fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext) { + self.has_focus = false; + } } impl Modal for GoToLine { + fn has_focus(&self) -> bool { + self.has_focus + } + fn dismiss_on_event(event: &Self::Event) -> bool { matches!(event, Event::Dismissed) } diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index 33d6e84241..ac0f3b5a19 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -25,6 +25,7 @@ pub struct Picker { theme: Arc theme::Picker>>>, confirmed: bool, pending_update_matches: Task>, + has_focus: bool, } pub trait PickerDelegate: Sized + 'static { @@ -140,13 +141,22 @@ impl View for Picker { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + self.has_focus = true; if cx.is_self_focused() { cx.focus(&self.query_editor); } } + + fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext) { + self.has_focus = false; + } } impl Modal for Picker { + fn has_focus(&self) -> bool { + self.has_focus + } + fn dismiss_on_event(event: &Self::Event) -> bool { matches!(event, PickerEvent::Dismiss) } @@ -191,6 +201,7 @@ impl Picker { theme, confirmed: false, pending_update_matches: Task::ready(None), + has_focus: false, }; this.update_matches(String::new(), cx); this diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 066ea5f8a6..0a9b1f6c83 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -97,9 +97,25 @@ lazy_static! { } pub trait Modal: View { + fn has_focus(&self) -> bool; fn dismiss_on_event(event: &Self::Event) -> bool; } +trait ModalHandle { + fn as_any(&self) -> &AnyViewHandle; + fn has_focus(&self, cx: &WindowContext) -> bool; +} + +impl ModalHandle for ViewHandle { + fn as_any(&self) -> &AnyViewHandle { + self + } + + fn has_focus(&self, cx: &WindowContext) -> bool { + self.read(cx).has_focus() + } +} + #[derive(Clone, PartialEq)] pub struct RemoveWorktreeFromProject(pub WorktreeId); From 03a00df8b1f7addf1dacde7cdb3d63739561e8f8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 5 Jul 2023 09:40:26 +0200 Subject: [PATCH 068/104] Restore focus to previously focused view when dismissing a modal --- crates/workspace/src/workspace.rs | 36 +++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 0a9b1f6c83..60aefe4213 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -482,7 +482,7 @@ pub enum Event { pub struct Workspace { weak_self: WeakViewHandle, remote_entity_subscription: Option, - modal: Option, + modal: Option, zoomed: Option, zoomed_position: Option, center: PaneGroup, @@ -511,6 +511,11 @@ pub struct Workspace { pane_history_timestamp: Arc, } +struct ActiveModal { + view: Box, + previously_focused_view_id: Option, +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct ViewId { pub creator: PeerId, @@ -1498,8 +1503,10 @@ impl Workspace { cx.notify(); // Whatever modal was visible is getting clobbered. If its the same type as V, then return // it. Otherwise, create a new modal and set it as active. - let already_open_modal = self.modal.take().and_then(|modal| modal.downcast::()); - if let Some(already_open_modal) = already_open_modal { + if let Some(already_open_modal) = self + .dismiss_modal(cx) + .and_then(|modal| modal.downcast::()) + { cx.focus_self(); Some(already_open_modal) } else { @@ -1510,8 +1517,12 @@ impl Workspace { } }) .detach(); + let previously_focused_view_id = cx.focused_view_id(); cx.focus(&modal); - self.modal = Some(modal.into_any()); + self.modal = Some(ActiveModal { + view: Box::new(modal), + previously_focused_view_id, + }); None } } @@ -1519,13 +1530,20 @@ impl Workspace { pub fn modal(&self) -> Option> { self.modal .as_ref() - .and_then(|modal| modal.clone().downcast::()) + .and_then(|modal| modal.view.as_any().clone().downcast::()) } - pub fn dismiss_modal(&mut self, cx: &mut ViewContext) { - if self.modal.take().is_some() { - cx.focus(&self.active_pane); + pub fn dismiss_modal(&mut self, cx: &mut ViewContext) -> Option { + if let Some(modal) = self.modal.take() { + if let Some(previously_focused_view_id) = modal.previously_focused_view_id { + if modal.view.has_focus(cx) { + cx.window_context().focus(Some(previously_focused_view_id)); + } + } cx.notify(); + Some(modal.view.as_any().clone()) + } else { + None } } @@ -3512,7 +3530,7 @@ impl View for Workspace { ) })) .with_children(self.modal.as_ref().map(|modal| { - ChildView::new(modal, cx) + ChildView::new(modal.view.as_any(), cx) .contained() .with_style(theme.workspace.modal) .aligned() From d5f0df94f7a923da5259d8799851037862fd721c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 5 Jul 2023 11:41:24 +0200 Subject: [PATCH 069/104] Support `assistant: quote selection` on multibuffers --- crates/ai/src/assistant.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ai/src/assistant.rs b/crates/ai/src/assistant.rs index 9ca54e661a..2b4f733c80 100644 --- a/crates/ai/src/assistant.rs +++ b/crates/ai/src/assistant.rs @@ -1911,7 +1911,7 @@ impl ConversationEditor { let Some(panel) = workspace.panel::(cx) else { return; }; - let Some(editor) = workspace.active_item(cx).and_then(|item| item.downcast::()) else { + let Some(editor) = workspace.active_item(cx).and_then(|item| item.act_as::(cx)) else { return; }; From 64b77bfa8d194cfddfc8e8b98db0abf6b711e73f Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 14:04:16 +0200 Subject: [PATCH 070/104] Remove stacks from branch list header Co-authored-by: Antonio --- crates/collab_ui/src/branch_list.rs | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index a1693fd6c4..25999bf995 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -217,25 +217,13 @@ impl PickerDelegate for BranchListDelegate { let theme = &theme::current(cx); let style = theme.picker.header.clone(); let label = if self.last_query.is_empty() { - Stack::new() - .with_child( - Flex::row() - .with_child(Label::new("Recent branches", style.label.clone())) - .contained() - .with_style(style.container) - .into_any(), - ) + Flex::row() + .with_child(Label::new("Recent branches", style.label.clone())) .contained() .with_style(style.container) - .into_any() } else { - Stack::new() - .with_child( - Flex::row() - .with_child(Label::new("Branches", style.label.clone()).aligned().left()) - .contained() - .with_style(style.container), - ) + Flex::row() + .with_child(Label::new("Branches", style.label.clone()).aligned().left()) .with_children(self.matches.is_empty().not().then(|| { let suffix = if self.matches.len() == 1 { "" } else { "es" }; Flex::row() @@ -249,14 +237,7 @@ impl PickerDelegate for BranchListDelegate { })) .contained() .with_style(style.container) - .constrained() - .into_any() }; - Some( - MouseEventHandler::::new(0, cx, move |_, _| label) - .on_click(MouseButton::Left, move |_, _, _| {}) - .on_down_out(MouseButton::Left, move |_, _, _| {}) - .into_any(), - ) + Some(label.into_any()) } } From 8b3b1a607458a41fb8c2a9a9bb4d671da81ff97e Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 14:08:21 +0200 Subject: [PATCH 071/104] fixup! Remove stacks from branch list header --- crates/collab_ui/src/branch_list.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 25999bf995..229d1fdc29 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,8 +1,6 @@ use anyhow::{anyhow, bail}; use fuzzy::{StringMatch, StringMatchCandidate}; -use gpui::{ - elements::*, platform::MouseButton, AppContext, MouseState, Task, ViewContext, ViewHandle, -}; +use gpui::{elements::*, AppContext, MouseState, Task, ViewContext, ViewHandle}; use picker::{Picker, PickerDelegate, PickerEvent}; use std::{ops::Not, sync::Arc}; use util::ResultExt; From 6ba1c3071a53e566e9c0fdfd75326589e0fc6cb1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 5 Jul 2023 15:23:56 +0300 Subject: [PATCH 072/104] Simplify inlay map data --- crates/editor/src/display_map/inlay_map.rs | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index 99b22dcbb6..90e5c8a9ce 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -2,7 +2,7 @@ use crate::{ multi_buffer::{MultiBufferChunks, MultiBufferRows}, Anchor, InlayId, MultiBufferSnapshot, ToOffset, }; -use collections::{BTreeMap, BTreeSet, HashMap}; +use collections::{BTreeMap, BTreeSet}; use gpui::fonts::HighlightStyle; use language::{Chunk, Edit, Point, Rope, TextSummary}; use std::{ @@ -19,7 +19,6 @@ use super::TextHighlights; pub struct InlayMap { snapshot: InlaySnapshot, - inlays_by_id: HashMap, inlays: Vec, } @@ -381,7 +380,6 @@ impl InlayMap { ( Self { snapshot: snapshot.clone(), - inlays_by_id: HashMap::default(), inlays: Vec::new(), }, snapshot, @@ -531,13 +529,14 @@ impl InlayMap { let snapshot = &mut self.snapshot; let mut edits = BTreeSet::new(); - self.inlays.retain(|inlay| !to_remove.contains(&inlay.id)); - for inlay_id in to_remove { - if let Some(inlay) = self.inlays_by_id.remove(&inlay_id) { + self.inlays.retain(|inlay| { + let retain = !to_remove.contains(&inlay.id); + if !retain { let offset = inlay.position.to_offset(&snapshot.buffer); edits.insert(offset); } - } + retain + }); for (existing_id, properties) in to_insert { let inlay = Inlay { @@ -551,7 +550,6 @@ impl InlayMap { continue; } - self.inlays_by_id.insert(inlay.id, inlay.clone()); match self .inlays .binary_search_by(|probe| probe.position.cmp(&inlay.position, &snapshot.buffer)) @@ -627,7 +625,13 @@ impl InlayMap { }, )); } else { - to_remove.push(*self.inlays_by_id.keys().choose(rng).unwrap()); + to_remove.push( + self.inlays + .iter() + .choose(rng) + .map(|inlay| inlay.id) + .unwrap(), + ); } } log::info!("removing inlays: {:?}", to_remove); @@ -1478,8 +1482,10 @@ mod tests { ); // The inlays can be manually removed. - let (inlay_snapshot, _) = inlay_map - .splice::(inlay_map.inlays_by_id.keys().copied().collect(), Vec::new()); + let (inlay_snapshot, _) = inlay_map.splice::( + inlay_map.inlays.iter().map(|inlay| inlay.id).collect(), + Vec::new(), + ); assert_eq!(inlay_snapshot.text(), "abxJKLyDzefghi"); } From d7f6b5e1a07f645a22160df2f39f424d02d69998 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 5 Jul 2023 15:58:31 +0300 Subject: [PATCH 073/104] Remove InlayProperties --- crates/editor/src/display_map.rs | 7 +- crates/editor/src/display_map/inlay_map.rs | 167 ++++++++++----------- crates/editor/src/editor.rs | 41 +++-- crates/editor/src/inlay_hint_cache.rs | 28 ++-- 4 files changed, 117 insertions(+), 126 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 714dc74509..6e04833f17 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -20,7 +20,6 @@ use language::{ use std::{any::TypeId, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc}; use sum_tree::{Bias, TreeMap}; use tab_map::TabMap; -use text::Rope; use wrap_map::WrapMap; pub use block_map::{ @@ -28,7 +27,7 @@ pub use block_map::{ BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock, }; -pub use self::inlay_map::{Inlay, InlayProperties}; +pub use self::inlay_map::Inlay; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum FoldStatus { @@ -246,10 +245,10 @@ impl DisplayMap { self.inlay_map.current_inlays() } - pub fn splice_inlays>( + pub fn splice_inlays( &mut self, to_remove: Vec, - to_insert: Vec<(InlayId, InlayProperties)>, + to_insert: Vec, cx: &mut ModelContext, ) { if to_remove.is_empty() && to_insert.is_empty() { diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index 90e5c8a9ce..6a59cecae8 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -4,7 +4,7 @@ use crate::{ }; use collections::{BTreeMap, BTreeSet}; use gpui::fonts::HighlightStyle; -use language::{Chunk, Edit, Point, Rope, TextSummary}; +use language::{Chunk, Edit, Point, TextSummary}; use std::{ any::TypeId, cmp, @@ -13,7 +13,7 @@ use std::{ vec, }; use sum_tree::{Bias, Cursor, SumTree}; -use text::Patch; +use text::{Patch, Rope}; use super::TextHighlights; @@ -42,14 +42,8 @@ pub struct Inlay { pub text: text::Rope, } -#[derive(Debug, Clone)] -pub struct InlayProperties { - pub position: Anchor, - pub text: T, -} - -impl InlayProperties { - pub fn new(position: Anchor, hint: &project::InlayHint) -> Self { +impl Inlay { + pub fn hint(id: usize, position: Anchor, hint: &project::InlayHint) -> Self { let mut text = hint.text(); if hint.padding_right && !text.ends_with(' ') { text.push(' '); @@ -57,7 +51,19 @@ impl InlayProperties { if hint.padding_left && !text.starts_with(' ') { text.insert(0, ' '); } - Self { position, text } + Self { + id: InlayId::Hint(id), + position, + text: text.into(), + } + } + + pub fn suggestion>(id: usize, position: Anchor, text: T) -> Self { + Self { + id: InlayId::Suggestion(id), + position, + text: text.into(), + } } } @@ -521,10 +527,10 @@ impl InlayMap { } } - pub fn splice>( + pub fn splice( &mut self, to_remove: Vec, - to_insert: Vec<(InlayId, InlayProperties)>, + to_insert: Vec, ) -> (InlaySnapshot, Vec) { let snapshot = &mut self.snapshot; let mut edits = BTreeSet::new(); @@ -538,28 +544,23 @@ impl InlayMap { retain }); - for (existing_id, properties) in to_insert { - let inlay = Inlay { - id: existing_id, - position: properties.position, - text: properties.text.into(), - }; - + for inlay_to_insert in to_insert { // Avoid inserting empty inlays. - if inlay.text.is_empty() { + if inlay_to_insert.text.is_empty() { continue; } - match self - .inlays - .binary_search_by(|probe| probe.position.cmp(&inlay.position, &snapshot.buffer)) - { + let offset = inlay_to_insert.position.to_offset(&snapshot.buffer); + match self.inlays.binary_search_by(|probe| { + probe + .position + .cmp(&inlay_to_insert.position, &snapshot.buffer) + }) { Ok(ix) | Err(ix) => { - self.inlays.insert(ix, inlay.clone()); + self.inlays.insert(ix, inlay_to_insert); } } - let offset = inlay.position.to_offset(&snapshot.buffer); edits.insert(offset); } @@ -617,13 +618,11 @@ impl InlayMap { } else { InlayId::Suggestion(post_inc(next_inlay_id)) }; - to_insert.push(( - inlay_id, - InlayProperties { - position: snapshot.buffer.anchor_at(position, bias), - text, - }, - )); + to_insert.push(Inlay { + id: inlay_id, + position: snapshot.buffer.anchor_at(position, bias), + text: text.into(), + }); } else { to_remove.push( self.inlays @@ -1123,7 +1122,8 @@ mod tests { #[test] fn test_inlay_properties_label_padding() { assert_eq!( - InlayProperties::new( + Inlay::hint( + 0, Anchor::min(), &InlayHint { label: InlayHintLabel::String("a".to_string()), @@ -1135,13 +1135,15 @@ mod tests { kind: None, }, ) - .text, + .text + .to_string(), "a", "Should not pad label if not requested" ); assert_eq!( - InlayProperties::new( + Inlay::hint( + 0, Anchor::min(), &InlayHint { label: InlayHintLabel::String("a".to_string()), @@ -1153,13 +1155,15 @@ mod tests { kind: None, }, ) - .text, + .text + .to_string(), " a ", "Should pad label for every side requested" ); assert_eq!( - InlayProperties::new( + Inlay::hint( + 0, Anchor::min(), &InlayHint { label: InlayHintLabel::String(" a ".to_string()), @@ -1171,13 +1175,15 @@ mod tests { kind: None, }, ) - .text, + .text + .to_string(), " a ", "Should not change already padded label" ); assert_eq!( - InlayProperties::new( + Inlay::hint( + 0, Anchor::min(), &InlayHint { label: InlayHintLabel::String(" a ".to_string()), @@ -1189,7 +1195,8 @@ mod tests { kind: None, }, ) - .text, + .text + .to_string(), " a ", "Should not change already padded label" ); @@ -1205,13 +1212,11 @@ mod tests { let (inlay_snapshot, _) = inlay_map.splice( Vec::new(), - vec![( - InlayId::Hint(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_after(3), - text: "|123|", - }, - )], + vec![Inlay { + id: InlayId::Hint(post_inc(&mut next_inlay_id)), + position: buffer.read(cx).snapshot(cx).anchor_after(3), + text: "|123|".into(), + }], ); assert_eq!(inlay_snapshot.text(), "abc|123|defghi"); assert_eq!( @@ -1284,20 +1289,16 @@ mod tests { let (inlay_snapshot, _) = inlay_map.splice( Vec::new(), vec![ - ( - InlayId::Hint(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(3), - text: "|123|", - }, - ), - ( - InlayId::Suggestion(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_after(3), - text: "|456|", - }, - ), + Inlay { + id: InlayId::Hint(post_inc(&mut next_inlay_id)), + position: buffer.read(cx).snapshot(cx).anchor_before(3), + text: "|123|".into(), + }, + Inlay { + id: InlayId::Suggestion(post_inc(&mut next_inlay_id)), + position: buffer.read(cx).snapshot(cx).anchor_after(3), + text: "|456|".into(), + }, ], ); assert_eq!(inlay_snapshot.text(), "abx|123||456|yDzefghi"); @@ -1482,7 +1483,7 @@ mod tests { ); // The inlays can be manually removed. - let (inlay_snapshot, _) = inlay_map.splice::( + let (inlay_snapshot, _) = inlay_map.splice( inlay_map.inlays.iter().map(|inlay| inlay.id).collect(), Vec::new(), ); @@ -1499,27 +1500,21 @@ mod tests { let (inlay_snapshot, _) = inlay_map.splice( Vec::new(), vec![ - ( - InlayId::Hint(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(0), - text: "|123|\n", - }, - ), - ( - InlayId::Hint(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(4), - text: "|456|", - }, - ), - ( - InlayId::Suggestion(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(7), - text: "\n|567|\n", - }, - ), + Inlay { + id: InlayId::Hint(post_inc(&mut next_inlay_id)), + position: buffer.read(cx).snapshot(cx).anchor_before(0), + text: "|123|\n".into(), + }, + Inlay { + id: InlayId::Hint(post_inc(&mut next_inlay_id)), + position: buffer.read(cx).snapshot(cx).anchor_before(4), + text: "|456|".into(), + }, + Inlay { + id: InlayId::Suggestion(post_inc(&mut next_inlay_id)), + position: buffer.read(cx).snapshot(cx).anchor_before(7), + text: "\n|567|\n".into(), + }, ], ); assert_eq!(inlay_snapshot.text(), "|123|\nabc\n|456|def\n|567|\n\nghi"); @@ -1609,7 +1604,7 @@ mod tests { (offset, inlay.clone()) }) .collect::>(); - let mut expected_text = Rope::from(buffer_snapshot.text().as_str()); + let mut expected_text = Rope::from(buffer_snapshot.text()); for (offset, inlay) in inlays.into_iter().rev() { expected_text.replace(offset..offset, &inlay.text.to_string()); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 992ecd7459..e979bd9c1e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -190,6 +190,15 @@ pub enum InlayId { Hint(usize), } +impl InlayId { + fn id(&self) -> usize { + match self { + Self::Suggestion(id) => *id, + Self::Hint(id) => *id, + } + } +} + actions!( editor, [ @@ -2708,17 +2717,11 @@ impl Editor { fn splice_inlay_hints( &self, to_remove: Vec, - to_insert: Vec<(Anchor, InlayId, project::InlayHint)>, + to_insert: Vec, cx: &mut ViewContext, ) { - let buffer = self.buffer.read(cx).read(cx); - let new_inlays = to_insert - .into_iter() - .map(|(position, id, hint)| (id, InlayProperties::new(position, &hint))) - .collect(); - drop(buffer); self.display_map.update(cx, |display_map, cx| { - display_map.splice_inlays(to_remove, new_inlays, cx); + display_map.splice_inlays(to_remove, to_insert, cx); }); } @@ -3403,7 +3406,7 @@ impl Editor { } self.display_map.update(cx, |map, cx| { - map.splice_inlays::<&str>(vec![suggestion.id], Vec::new(), cx) + map.splice_inlays(vec![suggestion.id], Vec::new(), cx) }); cx.notify(); true @@ -3436,7 +3439,7 @@ impl Editor { fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext) -> Option { let suggestion = self.copilot_state.suggestion.take()?; self.display_map.update(cx, |map, cx| { - map.splice_inlays::<&str>(vec![suggestion.id], Default::default(), cx); + map.splice_inlays(vec![suggestion.id], Default::default(), cx); }); let buffer = self.buffer.read(cx).read(cx); @@ -3467,21 +3470,11 @@ impl Editor { to_remove.push(suggestion.id); } - let suggestion_inlay_id = InlayId::Suggestion(post_inc(&mut self.next_inlay_id)); - let to_insert = vec![( - suggestion_inlay_id, - InlayProperties { - position: cursor, - text: text.clone(), - }, - )]; + let suggestion_inlay = + Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text); + self.copilot_state.suggestion = Some(suggestion_inlay.clone()); self.display_map.update(cx, move |map, cx| { - map.splice_inlays(to_remove, to_insert, cx) - }); - self.copilot_state.suggestion = Some(Inlay { - id: suggestion_inlay_id, - position: cursor, - text, + map.splice_inlays(to_remove, vec![suggestion_inlay], cx) }); cx.notify(); } else { diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 3f9f8e4288..a6ea3962d2 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -45,7 +45,7 @@ pub enum InvalidationStrategy { #[derive(Debug, Default)] pub struct InlaySplice { pub to_remove: Vec, - pub to_insert: Vec<(Anchor, InlayId, InlayHint)>, + pub to_insert: Vec, } struct UpdateTask { @@ -285,13 +285,13 @@ impl InlayHintCache { if !old_kinds.contains(&cached_hint.kind) && new_kinds.contains(&cached_hint.kind) { - to_insert.push(( + to_insert.push(Inlay::hint( + cached_hint_id.id(), multi_buffer_snapshot.anchor_in_excerpt( *excerpt_id, cached_hint.position, ), - *cached_hint_id, - cached_hint.clone(), + &cached_hint, )); } excerpt_cache.next(); @@ -307,11 +307,11 @@ impl InlayHintCache { for (cached_hint_id, maybe_missed_cached_hint) in excerpt_cache { let cached_hint_kind = maybe_missed_cached_hint.kind; if !old_kinds.contains(&cached_hint_kind) && new_kinds.contains(&cached_hint_kind) { - to_insert.push(( + to_insert.push(Inlay::hint( + cached_hint_id.id(), multi_buffer_snapshot .anchor_in_excerpt(*excerpt_id, maybe_missed_cached_hint.position), - *cached_hint_id, - maybe_missed_cached_hint.clone(), + &maybe_missed_cached_hint, )); } } @@ -657,18 +657,22 @@ async fn fetch_and_update_hints( for new_hint in new_update.add_to_cache { let new_hint_position = multi_buffer_snapshot .anchor_in_excerpt(query.excerpt_id, new_hint.position); - let new_inlay_id = InlayId::Hint(post_inc(&mut editor.next_inlay_id)); + let new_inlay_id = post_inc(&mut editor.next_inlay_id); if editor .inlay_hint_cache .allowed_hint_kinds .contains(&new_hint.kind) { - splice - .to_insert - .push((new_hint_position, new_inlay_id, new_hint.clone())); + splice.to_insert.push(Inlay::hint( + new_inlay_id, + new_hint_position, + &new_hint, + )); } - cached_excerpt_hints.hints.push((new_inlay_id, new_hint)); + cached_excerpt_hints + .hints + .push((InlayId::Hint(new_inlay_id), new_hint)); } cached_excerpt_hints From cc88bff1ff6d378429a61fa34bcd36caed05214e Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 15:25:33 +0200 Subject: [PATCH 074/104] Fix click-through behaviour of git panel Co-authored-by: Antonio --- crates/gpui/src/app/window.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 23fbb33fe1..a04aaf8a28 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -482,20 +482,19 @@ impl<'a> WindowContext<'a> { // If there is already clicked_button stored, don't replace it. if self.window.clicked_button.is_none() { - self.window.clicked_region_ids = self - .window - .mouse_regions - .iter() - .filter_map(|(region, _)| { - if region.bounds.contains_point(e.position) { - Some(region.id()) - } else { - None - } - }) - .collect(); + let window = &mut *self.window; + window.clicked_region_ids.clear(); - self.window.clicked_button = Some(e.button); + let mut highest_z_index = 0; + for (region, z_index) in window.mouse_regions.iter() { + if region.bounds.contains_point(e.position) && *z_index >= highest_z_index { + highest_z_index = *z_index; + window.clicked_region_ids.clear(); + window.clicked_region_ids.insert(region.id()); + } + } + + window.clicked_button = Some(e.button); } mouse_events.push(MouseEvent::Down(MouseDown { From 85add260f6fbde3d412dc8afa6ce60e65ac77413 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:48:52 +0200 Subject: [PATCH 075/104] Track regions instead of clicks. Get rid of superfluous params in RenderParams related to hover & click state. Co-authored-by: Antonio --- crates/gpui/src/app.rs | 14 ++++++---- crates/gpui/src/app/window.rs | 49 ++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 20043a9093..dfd5fe7bb2 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -3304,11 +3304,15 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> { let region_id = MouseRegionId::new::(self.view_id, region_id); MouseState { hovered: self.window.hovered_region_ids.contains(®ion_id), - clicked: self - .window - .clicked_region_ids - .get(®ion_id) - .and_then(|_| self.window.clicked_button), + clicked: if let Some((clicked_region_id, button)) = self.window.clicked_region { + if region_id == clicked_region_id { + Some(button) + } else { + None + } + } else { + None + }, accessed_hovered: false, accessed_clicked: false, } diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index a04aaf8a28..5a77017a11 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -53,7 +53,7 @@ pub struct Window { last_mouse_moved_event: Option, pub(crate) hovered_region_ids: HashSet, pub(crate) clicked_region_ids: HashSet, - pub(crate) clicked_button: Option, + pub(crate) clicked_region: Option<(MouseRegionId, MouseButton)>, mouse_position: Vector2F, text_layout_cache: TextLayoutCache, } @@ -86,7 +86,7 @@ impl Window { last_mouse_moved_event: None, hovered_region_ids: Default::default(), clicked_region_ids: Default::default(), - clicked_button: None, + clicked_region: None, mouse_position: vec2f(0., 0.), titlebar_height, appearance, @@ -480,21 +480,32 @@ impl<'a> WindowContext<'a> { // specific ancestor element that contained both [positions]' // So we need to store the overlapping regions on mouse down. - // If there is already clicked_button stored, don't replace it. - if self.window.clicked_button.is_none() { - let window = &mut *self.window; - window.clicked_region_ids.clear(); + // If there is already region being clicked, don't replace it. + if self.window.clicked_region.is_none() { + self.window.clicked_region_ids = self + .window + .mouse_regions + .iter() + .filter_map(|(region, _)| { + if region.bounds.contains_point(e.position) { + Some(region.id()) + } else { + None + } + }) + .collect(); let mut highest_z_index = 0; - for (region, z_index) in window.mouse_regions.iter() { + let mut clicked_region_id = None; + for (region, z_index) in self.window.mouse_regions.iter() { if region.bounds.contains_point(e.position) && *z_index >= highest_z_index { highest_z_index = *z_index; - window.clicked_region_ids.clear(); - window.clicked_region_ids.insert(region.id()); + clicked_region_id = Some(region.id()); } } - window.clicked_button = Some(e.button); + self.window.clicked_region = + clicked_region_id.map(|region_id| (region_id, e.button)); } mouse_events.push(MouseEvent::Down(MouseDown { @@ -559,7 +570,7 @@ impl<'a> WindowContext<'a> { prev_mouse_position: self.window.mouse_position, platform_event: e.clone(), })); - } else if let Some(clicked_button) = self.window.clicked_button { + } else if let Some((_, clicked_button)) = self.window.clicked_region { // Mouse up event happened outside the current window. Simulate mouse up button event let button_event = e.to_button_event(clicked_button); mouse_events.push(MouseEvent::Up(MouseUp { @@ -682,8 +693,8 @@ impl<'a> WindowContext<'a> { // Only raise click events if the released button is the same as the one stored if self .window - .clicked_button - .map(|clicked_button| clicked_button == e.button) + .clicked_region + .map(|(_, clicked_button)| clicked_button == e.button) .unwrap_or(false) { // Clear clicked regions and clicked button @@ -691,7 +702,7 @@ impl<'a> WindowContext<'a> { &mut self.window.clicked_region_ids, Default::default(), ); - self.window.clicked_button = None; + self.window.clicked_region = None; // Find regions which still overlap with the mouse since the last MouseDown happened for (mouse_region, _) in self.window.mouse_regions.iter().rev() { @@ -866,18 +877,10 @@ impl<'a> WindowContext<'a> { } for view_id in &invalidation.updated { let titlebar_height = self.window.titlebar_height; - let hovered_region_ids = self.window.hovered_region_ids.clone(); - let clicked_region_ids = self - .window - .clicked_button - .map(|button| (self.window.clicked_region_ids.clone(), button)); - let element = self .render_view(RenderParams { view_id: *view_id, titlebar_height, - hovered_region_ids, - clicked_region_ids, refreshing: false, appearance, }) @@ -1182,8 +1185,6 @@ impl<'a> WindowContext<'a> { pub struct RenderParams { pub view_id: usize, pub titlebar_height: f32, - pub hovered_region_ids: HashSet, - pub clicked_region_ids: Option<(HashSet, MouseButton)>, pub refreshing: bool, pub appearance: Appearance, } From ec47464bba1e77379a0f3ca7b8cb169a9300b50b Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:56:08 +0200 Subject: [PATCH 076/104] branch_list: Show match count on the right hand side of a header. Co-authored-by: Antonio --- crates/collab_ui/src/branch_list.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 229d1fdc29..16fefbd2eb 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -221,17 +221,14 @@ impl PickerDelegate for BranchListDelegate { .with_style(style.container) } else { Flex::row() - .with_child(Label::new("Branches", style.label.clone()).aligned().left()) + .with_child(Label::new("Branches", style.label.clone())) .with_children(self.matches.is_empty().not().then(|| { let suffix = if self.matches.len() == 1 { "" } else { "es" }; - Flex::row() - .align_children_center() - .with_child(Label::new( - format!("{} match{}", self.matches.len(), suffix), - style.label, - )) - .aligned() - .right() + Label::new( + format!("{} match{}", self.matches.len(), suffix), + style.label, + ) + .flex_float() })) .contained() .with_style(style.container) From 0e0d78df84f49b07f2b337985da235975c873943 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 18:04:40 +0200 Subject: [PATCH 077/104] Do not render recent paths in toolbar's project switcher --- crates/recent_projects/src/recent_projects.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index b3c9655645..4ba6103167 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -48,7 +48,7 @@ fn toggle( let workspace = cx.weak_handle(); cx.add_view(|cx| { RecentProjects::new( - RecentProjectsDelegate::new(workspace, workspace_locations), + RecentProjectsDelegate::new(workspace, workspace_locations, true), cx, ) .with_max_size(800., 1200.) @@ -69,8 +69,11 @@ pub fn build_recent_projects( workspaces: Vec, cx: &mut ViewContext, ) -> RecentProjects { - Picker::new(RecentProjectsDelegate::new(workspace, workspaces), cx) - .with_theme(|theme| theme.picker.clone()) + Picker::new( + RecentProjectsDelegate::new(workspace, workspaces, false), + cx, + ) + .with_theme(|theme| theme.picker.clone()) } pub type RecentProjects = Picker; @@ -80,18 +83,21 @@ pub struct RecentProjectsDelegate { workspace_locations: Vec, selected_match_index: usize, matches: Vec, + render_paths: bool, } impl RecentProjectsDelegate { fn new( workspace: WeakViewHandle, workspace_locations: Vec, + render_paths: bool, ) -> Self { Self { workspace, workspace_locations, selected_match_index: 0, matches: Default::default(), + render_paths, } } } @@ -197,6 +203,7 @@ impl PickerDelegate for RecentProjectsDelegate { highlighted_location .paths .into_iter() + .filter(|_| self.render_paths) .map(|highlighted_path| highlighted_path.render(style.label.clone())), ) .flex(1., false) From 1baa13561d374152a82c182da2b417e66a64280d Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 5 Jul 2023 12:50:56 -0400 Subject: [PATCH 078/104] Update project & git menus to be Toggleable> Co-Authored-By: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> --- crates/collab_ui/src/collab_titlebar_item.rs | 18 ++++++++++-------- crates/theme/src/theme.rs | 4 ++-- styles/src/style_tree/titlebar.ts | 9 +++++++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 3bc890f91b..c8f1d7cf30 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -221,17 +221,19 @@ impl CollabTitlebarItem { .as_ref() .and_then(RepositoryEntry::branch) .map(|branch| util::truncate_and_trailoff(&branch, MAX_BRANCH_NAME_LENGTH)); - let project_style = theme.titlebar.title.clone(); - let git_style = theme.titlebar.git_branch.clone(); + let project_style = theme.titlebar.project_menu_button.clone(); + let git_style = theme.titlebar.git_menu_button.clone(); let divider_style = theme.titlebar.project_name_divider.clone(); let item_spacing = theme.titlebar.item_spacing; let mut ret = Flex::row().with_child( Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |_, _| { - Label::new(name, project_style.text.clone()) + MouseEventHandler::::new(0, cx, |mouse_state, _| { + let style = project_style.in_state(self.project_popover.is_some()).style_for(mouse_state); + Label::new(name, style.text.clone()) .contained() + .with_style(style.container) .aligned() .left() .into_any_named("title-project-name") @@ -241,8 +243,6 @@ impl CollabTitlebarItem { this.toggle_project_menu(&Default::default(), cx) }) .on_click(MouseButton::Left, move |_, _, _| {}) - .contained() - .with_style(project_style.container), ) .with_children(self.render_project_popover_host(&theme.titlebar, cx)), ); @@ -259,9 +259,11 @@ impl CollabTitlebarItem { .with_child( Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |_, _| { - Label::new(git_branch, git_style.text) + MouseEventHandler::::new(0, cx, |mouse_state, _| { + let style = git_style.in_state(self.branch_popover.is_some()).style_for(mouse_state); + Label::new(git_branch, style.text.clone()) .contained() + .with_style(style.container.clone()) .with_margin_right(item_spacing) .aligned() .left() diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index a4fbcedd32..3a7924f36e 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -118,9 +118,9 @@ pub struct Titlebar { #[serde(flatten)] pub container: ContainerStyle, pub height: f32, - pub title: ContainedText, + pub project_menu_button: Toggleable>, pub project_name_divider: ContainedText, - pub git_branch: ContainedText, + pub git_menu_button: Toggleable>, pub item_spacing: f32, pub face_pile_spacing: f32, pub avatar_ribbon: AvatarRibbon, diff --git a/styles/src/style_tree/titlebar.ts b/styles/src/style_tree/titlebar.ts index 686f814a5d..109db8db20 100644 --- a/styles/src/style_tree/titlebar.ts +++ b/styles/src/style_tree/titlebar.ts @@ -173,9 +173,14 @@ export function titlebar(theme: ColorScheme): any { }, // Project - title: text(theme.lowest, "sans", "active"), project_name_divider: text(theme.lowest, "sans", "variant"), - git_branch: text(theme.lowest, "sans", "variant"), + + project_menu_button: toggleable_text_button(theme, { + color: 'base', + }), + git_menu_button: toggleable_text_button(theme, { + color: 'variant', + }), // Collaborators leader_avatar: { From b80281e556577c03c72027a45078aeaa0e5435c9 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 18:57:06 +0200 Subject: [PATCH 079/104] cargo fmt --- crates/collab_ui/src/collab_titlebar_item.rs | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index c8f1d7cf30..73450e7c7d 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -230,7 +230,9 @@ impl CollabTitlebarItem { Stack::new() .with_child( MouseEventHandler::::new(0, cx, |mouse_state, _| { - let style = project_style.in_state(self.project_popover.is_some()).style_for(mouse_state); + let style = project_style + .in_state(self.project_popover.is_some()) + .style_for(mouse_state); Label::new(name, style.text.clone()) .contained() .with_style(style.container) @@ -242,7 +244,7 @@ impl CollabTitlebarItem { .on_down(MouseButton::Left, move |_, this, cx| { this.toggle_project_menu(&Default::default(), cx) }) - .on_click(MouseButton::Left, move |_, _, _| {}) + .on_click(MouseButton::Left, move |_, _, _| {}), ) .with_children(self.render_project_popover_host(&theme.titlebar, cx)), ); @@ -259,16 +261,22 @@ impl CollabTitlebarItem { .with_child( Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |mouse_state, _| { - let style = git_style.in_state(self.branch_popover.is_some()).style_for(mouse_state); - Label::new(git_branch, style.text.clone()) - .contained() - .with_style(style.container.clone()) - .with_margin_right(item_spacing) - .aligned() - .left() - .into_any_named("title-project-branch") - }) + MouseEventHandler::::new( + 0, + cx, + |mouse_state, _| { + let style = git_style + .in_state(self.branch_popover.is_some()) + .style_for(mouse_state); + Label::new(git_branch, style.text.clone()) + .contained() + .with_style(style.container.clone()) + .with_margin_right(item_spacing) + .aligned() + .left() + .into_any_named("title-project-branch") + }, + ) .with_cursor_style(CursorStyle::PointingHand) .on_down(MouseButton::Left, move |_, this, cx| { this.toggle_vcs_menu(&Default::default(), cx) From 6a15ae9c01dcc771c2ed71b9eb14dfe05cc2a98f Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 5 Jul 2023 14:17:37 -0400 Subject: [PATCH 080/104] v0.95.x dev --- Cargo.lock | 2 +- crates/zed/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e1407f2c0..a4fd323fe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9339,7 +9339,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.94.0" +version = "0.95.0" dependencies = [ "activity_indicator", "ai", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 97d7f717ce..d016525af4 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2021" name = "zed" -version = "0.94.0" +version = "0.95.0" publish = false [lib] From 594b6e8d64b9019a42dbca7083a211fd65911b5f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 5 Jul 2023 11:47:17 -0700 Subject: [PATCH 081/104] collab 0.16.0 --- Cargo.lock | 2 +- crates/collab/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4fd323fe0..ac089cee18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1401,7 +1401,7 @@ dependencies = [ [[package]] name = "collab" -version = "0.15.0" +version = "0.16.0" dependencies = [ "anyhow", "async-tungstenite", diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index cc7263aa97..cee5fd0989 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] default-run = "collab" edition = "2021" name = "collab" -version = "0.15.0" +version = "0.16.0" publish = false [[bin]] From 8b8bafef228842d56e0b9c257ec975e24889a040 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 5 Jul 2023 12:05:16 -0700 Subject: [PATCH 082/104] Remove spurious audio depedency --- Cargo.lock | 1 - crates/collab/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac089cee18..c6a67d47ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,7 +1405,6 @@ version = "0.16.0" dependencies = [ "anyhow", "async-tungstenite", - "audio", "axum", "axum-extra", "base64 0.13.1", diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index cee5fd0989..8bd86ed9ec 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -14,7 +14,6 @@ name = "seed" required-features = ["seed-support"] [dependencies] -audio = { path = "../audio" } collections = { path = "../collections" } live_kit_server = { path = "../live_kit_server" } rpc = { path = "../rpc" } From 801f41e68e79e47e2c05e75d0b17c9b3734644fd Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 5 Jul 2023 12:15:56 -0700 Subject: [PATCH 083/104] Move audio dependency to dev --- Cargo.lock | 1 + crates/collab/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index c6a67d47ef..ac089cee18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,6 +1405,7 @@ version = "0.16.0" dependencies = [ "anyhow", "async-tungstenite", + "audio", "axum", "axum-extra", "base64 0.13.1", diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 8bd86ed9ec..c61fdeebfb 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -57,6 +57,7 @@ tracing-log = "0.1.3" tracing-subscriber = { version = "0.3.11", features = ["env-filter", "json"] } [dev-dependencies] +audio = { path = "../audio" } collections = { path = "../collections", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } call = { path = "../call", features = ["test-support"] } From f6c96ec8920b529d298691eac151db90c33c959e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 6 Jul 2023 09:53:34 +0200 Subject: [PATCH 084/104] Fix panic when saved conversations directory changes We were updating the view's state but missed a `notify`, which caused the `UniformList` responsible for rendering the saved conversations to panic when some files were deleted. --- crates/ai/src/assistant.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/ai/src/assistant.rs b/crates/ai/src/assistant.rs index 2b4f733c80..4d300230e1 100644 --- a/crates/ai/src/assistant.rs +++ b/crates/ai/src/assistant.rs @@ -147,8 +147,9 @@ impl AssistantPanel { .await .log_err() .unwrap_or_default(); - this.update(&mut cx, |this, _| { - this.saved_conversations = saved_conversations + this.update(&mut cx, |this, cx| { + this.saved_conversations = saved_conversations; + cx.notify(); }) .ok(); } From 1936bdebb36b1c4c00abbb9930287449ca0202b3 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 6 Jul 2023 11:16:39 +0300 Subject: [PATCH 085/104] Use less padding for typescript parameter hints --- crates/project/src/lsp_command.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index a3c6302e29..eec64beb5a 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1822,11 +1822,21 @@ impl LspCommand for InlayHints { async fn response_from_lsp( self, message: Option>, - _: ModelHandle, + project: ModelHandle, buffer: ModelHandle, - _: LanguageServerId, - cx: AsyncAppContext, + server_id: LanguageServerId, + mut cx: AsyncAppContext, ) -> Result> { + let (lsp_adapter, _) = language_server_for_buffer(&project, &buffer, server_id, &mut cx)?; + // `typescript-language-server` adds padding to the left for type hints, turning + // `const foo: boolean` into `const foo : boolean` which looks odd. + // `rust-analyzer` does not have the padding for this case, and we have to accomodate both. + // + // We could trim the whole string, but being pessimistic on par with the situation above, + // there might be a hint with multiple whitespaces at the end(s) which we need to display properly. + // Hence let's use a heuristic first to handle the most awkward case and look for more. + let force_no_type_left_padding = + lsp_adapter.name.0.as_ref() == "typescript-language-server"; cx.read(|cx| { let origin_buffer = buffer.read(cx); Ok(message @@ -1840,6 +1850,12 @@ impl LspCommand for InlayHints { }); let position = origin_buffer .clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left); + let padding_left = + if force_no_type_left_padding && kind == Some(InlayHintKind::Type) { + false + } else { + lsp_hint.padding_left.unwrap_or(false) + }; InlayHint { buffer_id: origin_buffer.remote_id(), position: if kind == Some(InlayHintKind::Parameter) { @@ -1847,7 +1863,7 @@ impl LspCommand for InlayHints { } else { origin_buffer.anchor_after(position) }, - padding_left: lsp_hint.padding_left.unwrap_or(false), + padding_left, padding_right: lsp_hint.padding_right.unwrap_or(false), label: match lsp_hint.label { lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s), From 492b849ea1cec2285ac466f31dde26084021b3f6 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:09:33 +0200 Subject: [PATCH 086/104] Do not render multiple hunks for the same line --- crates/editor/src/element.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 0a462b1e5d..2f69781aa1 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1057,6 +1057,7 @@ impl EditorElement { if layout.is_singleton && scrollbar_settings.selections { let start_anchor = Anchor::min(); let end_anchor = Anchor::max(); + let mut last_rendered_row_range = (-1., -1.); for (row, _) in &editor.background_highlights_in_range( start_anchor..end_anchor, &layout.position_map.snapshot, @@ -1069,6 +1070,11 @@ impl EditorElement { if end_y - start_y < 1. { end_y = start_y + 1.; } + if (start_y, end_y) == last_rendered_row_range { + skipped += 1; + continue; + } + last_rendered_row_range = (start_y, end_y); let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); let color = scrollbar_theme.selections; From 0b0a161626d4d58f2afefaf24ceb9b38e1fbf8c8 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 6 Jul 2023 11:45:17 +0300 Subject: [PATCH 087/104] Show inlay hints on startup for every language server with work events Language servers such as typescript-language-servers report a single work event, ending right after server's startup. Other servers might send more similar event, also during startup. The rest of the events are diagnostic-related and we filter them out. React on such events with /refresh-like hint update, that will check only the visible part of the editor for hints and might be replaced by other /refresh requests, if needed. --- crates/editor/src/inlay_hint_cache.rs | 111 ++++++++++++++++++++++++++ crates/project/src/project.rs | 1 + 2 files changed, 112 insertions(+) diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index a6ea3962d2..9ca94665c2 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -974,6 +974,117 @@ mod tests { }); } + #[gpui::test] + async fn test_cache_update_on_lsp_completion_tasks(cx: &mut gpui::TestAppContext) { + init_test(cx, |settings| { + settings.defaults.inlay_hints = Some(InlayHintSettings { + enabled: true, + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, + }) + }); + + let (file_with_hints, editor, fake_server) = prepare_test_objects(cx).await; + let lsp_request_count = Arc::new(AtomicU32::new(0)); + fake_server + .handle_request::(move |params, _| { + let task_lsp_request_count = Arc::clone(&lsp_request_count); + async move { + assert_eq!( + params.text_document.uri, + lsp::Url::from_file_path(file_with_hints).unwrap(), + ); + let current_call_id = + Arc::clone(&task_lsp_request_count).fetch_add(1, Ordering::SeqCst); + Ok(Some(vec![lsp::InlayHint { + position: lsp::Position::new(0, current_call_id), + label: lsp::InlayHintLabel::String(current_call_id.to_string()), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }])) + } + }) + .next() + .await; + cx.foreground().run_until_parked(); + + let mut edits_made = 1; + editor.update(cx, |editor, cx| { + let expected_layers = vec!["0".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Should get its first hints when opening the editor" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!( + inlay_cache.version, edits_made, + "The editor update the cache version after every cache/view change" + ); + }); + + let progress_token = "test_progress_token"; + fake_server + .request::(lsp::WorkDoneProgressCreateParams { + token: lsp::ProgressToken::String(progress_token.to_string()), + }) + .await + .expect("work done progress create request failed"); + cx.foreground().run_until_parked(); + fake_server.notify::(lsp::ProgressParams { + token: lsp::ProgressToken::String(progress_token.to_string()), + value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Begin( + lsp::WorkDoneProgressBegin::default(), + )), + }); + cx.foreground().run_until_parked(); + + editor.update(cx, |editor, cx| { + let expected_layers = vec!["0".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "Should not update hints while the work task is running" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!( + inlay_cache.version, edits_made, + "Should not update the cache while the work task is running" + ); + }); + + fake_server.notify::(lsp::ProgressParams { + token: lsp::ProgressToken::String(progress_token.to_string()), + value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::End( + lsp::WorkDoneProgressEnd::default(), + )), + }); + cx.foreground().run_until_parked(); + + edits_made += 1; + editor.update(cx, |editor, cx| { + let expected_layers = vec!["1".to_string()]; + assert_eq!( + expected_layers, + cached_hint_labels(editor), + "New hints should be queried after the work task is done" + ); + assert_eq!(expected_layers, visible_hint_labels(editor, cx)); + let inlay_cache = editor.inlay_hint_cache(); + assert_eq!( + inlay_cache.version, edits_made, + "Cache version should udpate once after the work task is done" + ); + }); + } + #[gpui::test] async fn test_no_hint_updates_for_unrelated_language_files(cx: &mut gpui::TestAppContext) { let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index bbb2064da2..d69e5cf21e 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -3397,6 +3397,7 @@ impl Project { cx: &mut ModelContext, ) { if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) { + cx.emit(Event::RefreshInlays); status.pending_work.remove(&token); cx.notify(); } From b66453e771e0a10d467016d23704c2f0d0cd7013 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:11:08 +0200 Subject: [PATCH 088/104] fixup! Do not render multiple hunks for the same line --- crates/editor/src/element.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 2f69781aa1..e884f4b356 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1071,7 +1071,6 @@ impl EditorElement { end_y = start_y + 1.; } if (start_y, end_y) == last_rendered_row_range { - skipped += 1; continue; } last_rendered_row_range = (start_y, end_y); From 5e7d9dc718522674053f3faa3878e655595b8cf4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 6 Jul 2023 13:31:45 +0200 Subject: [PATCH 089/104] Add hunk merging --- crates/editor/src/element.rs | 76 +++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index e884f4b356..82fbd194db 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1057,7 +1057,35 @@ impl EditorElement { if layout.is_singleton && scrollbar_settings.selections { let start_anchor = Anchor::min(); let end_anchor = Anchor::max(); - let mut last_rendered_row_range = (-1., -1.); + let mut start_row = None; + let mut end_row = None; + let color = scrollbar_theme.selections; + let border = Border { + width: 1., + color: style.thumb.border.color, + overlay: false, + top: false, + right: true, + bottom: false, + left: true, + }; + let mut push_region = |start, end| { + if let (Some(start_display), Some(end_display)) = (start, end) { + let start_y = y_for_row(start_display as f32); + let mut end_y = y_for_row(end_display as f32); + if end_y - start_y < 1. { + end_y = start_y + 1.; + } + let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); + + scene.push_quad(Quad { + bounds, + background: Some(color), + border, + corner_radius: style.thumb.corner_radius, + }) + } + }; for (row, _) in &editor.background_highlights_in_range( start_anchor..end_anchor, &layout.position_map.snapshot, @@ -1065,36 +1093,28 @@ impl EditorElement { ) { let start_display = row.start; let end_display = row.end; - let start_y = y_for_row(start_display.row() as f32); - let mut end_y = y_for_row((end_display.row()) as f32); - if end_y - start_y < 1. { - end_y = start_y + 1.; - } - if (start_y, end_y) == last_rendered_row_range { + + if start_row.is_none() { + assert_eq!(end_row, None); + start_row = Some(start_display.row()); + end_row = Some(end_display.row()); continue; } - last_rendered_row_range = (start_y, end_y); - let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); - - let color = scrollbar_theme.selections; - - let border = Border { - width: 1., - color: style.thumb.border.color, - overlay: false, - top: false, - right: true, - bottom: false, - left: true, - }; - - scene.push_quad(Quad { - bounds, - background: Some(color), - border, - corner_radius: style.thumb.corner_radius, - }) + if let Some(current_end) = end_row.as_mut() { + if start_display.row() > *current_end + 1 { + push_region(start_row, end_row); + start_row = None; + end_row = None; + } else { + // Merge two hunks. + *current_end = end_display.row(); + } + } else { + unreachable!(); + } } + // We might still have a hunk that was not rendered (if there was a search hit on the last line) + push_region(start_row, end_row); } if layout.is_singleton && scrollbar_settings.git_diff { From 3e245fec9033331034cd054c26291c2a4c06136e Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 6 Jul 2023 13:52:03 +0200 Subject: [PATCH 090/104] Save a flushing line instead of discarding it --- crates/editor/src/element.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 82fbd194db..e96f1efe92 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1103,8 +1103,8 @@ impl EditorElement { if let Some(current_end) = end_row.as_mut() { if start_display.row() > *current_end + 1 { push_region(start_row, end_row); - start_row = None; - end_row = None; + start_row = Some(start_display.row()); + end_row = Some(end_display.row()); } else { // Merge two hunks. *current_end = end_display.row(); From 5408275c7af8429e58bfc0b4113726e14b58ecc3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 6 Jul 2023 14:38:05 +0200 Subject: [PATCH 091/104] Filter out non-json files when loading conversations --- crates/ai/src/ai.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/ai/src/ai.rs b/crates/ai/src/ai.rs index 812fb05121..7cc5f08f7c 100644 --- a/crates/ai/src/ai.rs +++ b/crates/ai/src/ai.rs @@ -12,6 +12,7 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use std::{ cmp::Reverse, + ffi::OsStr, fmt::{self, Display}, path::PathBuf, sync::Arc, @@ -80,6 +81,9 @@ impl SavedConversationMetadata { let mut conversations = Vec::::new(); while let Some(path) = paths.next().await { let path = path?; + if path.extension() != Some(OsStr::new("json")) { + continue; + } let pattern = r" - \d+.zed.json$"; let re = Regex::new(pattern).unwrap(); From 708852aa000963780f678c7189b681039a8bfcbf Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 6 Jul 2023 14:11:18 +0200 Subject: [PATCH 092/104] Clip left when finding preceding (line) boundary This fixes an issue that was causing `alt-left` to not move the cursor when it was located right after an inlay hint with a `Left` bias. --- crates/editor/src/movement.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 523a0af964..e589337979 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -263,13 +263,13 @@ pub fn find_preceding_boundary( if let Some((prev_ch, prev_point)) = prev { if is_boundary(ch, prev_ch) { - return prev_point; + return map.clip_point(prev_point, Bias::Left); } } prev = Some((ch, point)); } - DisplayPoint::zero() + map.clip_point(DisplayPoint::zero(), Bias::Left) } /// Scans for a boundary preceding the given start point `from` until a boundary is found, indicated by the @@ -292,7 +292,7 @@ pub fn find_preceding_boundary_in_line( for (ch, point) in map.reverse_chars_at(from) { if let Some((prev_ch, prev_point)) = prev { if is_boundary(ch, prev_ch) { - return prev_point; + return map.clip_point(prev_point, Bias::Left); } } @@ -303,7 +303,7 @@ pub fn find_preceding_boundary_in_line( prev = Some((ch, point)); } - prev.map(|(_, point)| point).unwrap_or(from) + map.clip_point(prev.map(|(_, point)| point).unwrap_or(from), Bias::Left) } /// Scans for a boundary following the given start point until a boundary is found, indicated by the From 11ae99fbd6d953d9e89ee3821ef7be64ac8e9219 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 6 Jul 2023 17:12:26 +0300 Subject: [PATCH 093/104] Add a test --- crates/editor/src/movement.rs | 80 ++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index e589337979..e50d7d8306 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -406,8 +406,12 @@ pub fn split_display_range_by_lines( #[cfg(test)] mod tests { use super::*; - use crate::{test::marked_display_snapshot, Buffer, DisplayMap, ExcerptRange, MultiBuffer}; + use crate::{ + display_map::Inlay, test::marked_display_snapshot, Buffer, DisplayMap, ExcerptRange, + InlayId, MultiBuffer, + }; use settings::SettingsStore; + use util::post_inc; #[gpui::test] fn test_previous_word_start(cx: &mut gpui::AppContext) { @@ -505,6 +509,80 @@ mod tests { }); } + #[gpui::test] + fn test_find_preceding_boundary_with_inlays(cx: &mut gpui::AppContext) { + init_test(cx); + + let input_text = "abcdefghijklmnopqrstuvwxys"; + let family_id = cx + .font_cache() + .load_family(&["Helvetica"], &Default::default()) + .unwrap(); + let font_id = cx + .font_cache() + .select_font(family_id, &Default::default()) + .unwrap(); + let font_size = 14.0; + let buffer = MultiBuffer::build_simple(input_text, cx); + let buffer_snapshot = buffer.read(cx).snapshot(cx); + let display_map = + cx.add_model(|cx| DisplayMap::new(buffer, font_id, font_size, None, 1, 1, cx)); + + // add all kinds of inlays between two word boundaries: we should be able to cross them all, when looking for another boundary + let mut id = 0; + let inlays = (0..buffer_snapshot.len()) + .map(|offset| { + [ + Inlay { + id: InlayId::Suggestion(post_inc(&mut id)), + position: buffer_snapshot.anchor_at(offset, Bias::Left), + text: format!("test").into(), + }, + Inlay { + id: InlayId::Suggestion(post_inc(&mut id)), + position: buffer_snapshot.anchor_at(offset, Bias::Right), + text: format!("test").into(), + }, + Inlay { + id: InlayId::Hint(post_inc(&mut id)), + position: buffer_snapshot.anchor_at(offset, Bias::Left), + text: format!("test").into(), + }, + Inlay { + id: InlayId::Hint(post_inc(&mut id)), + position: buffer_snapshot.anchor_at(offset, Bias::Right), + text: format!("test").into(), + }, + ] + }) + .flatten() + .collect(); + let snapshot = display_map.update(cx, |map, cx| { + map.splice_inlays(Vec::new(), inlays, cx); + map.snapshot(cx) + }); + + assert_eq!( + find_preceding_boundary( + &snapshot, + buffer_snapshot.len().to_display_point(&snapshot), + |left, _| left == 'a', + ), + 0.to_display_point(&snapshot), + "Should not stop at inlays when looking for boundaries" + ); + + assert_eq!( + find_preceding_boundary_in_line( + &snapshot, + buffer_snapshot.len().to_display_point(&snapshot), + |left, _| left == 'a', + ), + 0.to_display_point(&snapshot), + "Should not stop at inlays when looking for boundaries in line" + ); + } + #[gpui::test] fn test_next_word_end(cx: &mut gpui::AppContext) { init_test(cx); From 793eff16957b5b20e7f98bd098c096887ed79f9c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 6 Jul 2023 10:54:47 -0400 Subject: [PATCH 094/104] Update scrollbar selection style --- styles/src/style_tree/editor.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index a1ba0be43d..48a2fd33e2 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -304,9 +304,7 @@ export default function editor(): any { ? with_opacity(theme.ramps.green(0.5).hex(), 0.8) : with_opacity(theme.ramps.green(0.4).hex(), 0.8), }, - selections: is_light - ? with_opacity(theme.ramps.blue(0.5).hex(), 0.8) - : with_opacity(theme.ramps.blue(0.4).hex(), 0.8) + selections: foreground(layer, "accent") }, composition_mark: { underline: { From fff65968bfb30bda31321a832ef2cd67d474cc8f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 6 Jul 2023 23:08:04 +0300 Subject: [PATCH 095/104] Restart LSP server on initialization options change --- crates/project/src/project.rs | 27 ++++++++++++++++++++++----- crates/workspace/src/workspace.rs | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index d69e5cf21e..81db0c7ed7 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -777,20 +777,32 @@ impl Project { } let mut language_servers_to_stop = Vec::new(); + let mut language_servers_to_restart = Vec::new(); let languages = self.languages.to_vec(); + let project_settings = settings::get::(cx).clone(); for (worktree_id, started_lsp_name) in self.language_server_ids.keys() { - let language = languages.iter().find(|l| { - l.lsp_adapters() + let language = languages.iter().find_map(|l| { + let adapter = l + .lsp_adapters() .iter() - .any(|adapter| &adapter.name == started_lsp_name) + .find(|adapter| &adapter.name == started_lsp_name)?; + Some((l, adapter)) }); - if let Some(language) = language { + if let Some((language, adapter)) = language { let worktree = self.worktree_for_id(*worktree_id, cx); - let file = worktree.and_then(|tree| { + let file = worktree.as_ref().and_then(|tree| { tree.update(cx, |tree, cx| tree.root_file(cx).map(|f| f as _)) }); if !language_settings(Some(language), file.as_ref(), cx).enable_language_server { language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); + } else if let Some(worktree) = worktree { + let new_lsp_settings = project_settings + .lsp + .get(&adapter.name.0) + .and_then(|s| s.initialization_options.as_ref()); + if adapter.initialization_options.as_ref() != new_lsp_settings { + language_servers_to_restart.push((worktree, Arc::clone(language))); + } } } } @@ -807,6 +819,11 @@ impl Project { self.start_language_servers(&worktree, worktree_path, language, cx); } + // Restart all language servers with changed initialization options. + for (worktree, language) in language_servers_to_restart { + self.restart_language_servers(worktree, language, cx); + } + if !self.copilot_enabled && Copilot::global(cx).is_some() { self.copilot_enabled = true; for buffer in self.opened_buffers.values() { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 60aefe4213..01d80d141c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -4809,6 +4809,7 @@ mod tests { theme::init((), cx); language::init(cx); crate::init_settings(cx); + Project::init_settings(cx); }); } } From e6ec0af74355020bf9017f8c90a043866adf7bad Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 6 Jul 2023 23:13:29 +0300 Subject: [PATCH 096/104] Remove redundant hint kind checks in tests --- crates/collab/src/tests/integration_tests.rs | 55 ++------------------ crates/editor/src/inlay_hint_cache.rs | 51 +++++------------- 2 files changed, 17 insertions(+), 89 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index b20844a065..66dc19d690 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -18,7 +18,7 @@ use gpui::{ }; use indoc::indoc; use language::{ - language_settings::{AllLanguageSettings, Formatter, InlayHintKind, InlayHintSettings}, + language_settings::{AllLanguageSettings, Formatter, InlayHintSettings}, tree_sitter_rust, Anchor, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig, OffsetRangeExt, Point, Rope, }; @@ -7843,7 +7843,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( }); }); }); - let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); let mut language = Language::new( LanguageConfig { @@ -7955,10 +7954,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Host should get its first hints when opens an editor" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Cache should use editor settings to get the allowed hint kinds" - ); assert_eq!( inlay_cache.version, edits_made, "Host editor update the cache version after every cache/view change", @@ -7982,10 +7977,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Client should get its first hints when opens an editor" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Cache should use editor settings to get the allowed hint kinds" - ); assert_eq!( inlay_cache.version, edits_made, "Guest editor update the cache version after every cache/view change" @@ -8007,10 +7998,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Host should get hints from the 1st edit and 1st LSP query" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!(inlay_cache.version, edits_made); }); editor_b.update(cx_b, |editor, _| { @@ -8025,10 +8012,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Guest should get hints the 1st edit and 2nd LSP query" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!(inlay_cache.version, edits_made); }); @@ -8054,10 +8037,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( 4th query was made by guest (but not applied) due to cache invalidation logic" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!(inlay_cache.version, edits_made); }); editor_b.update(cx_b, |editor, _| { @@ -8074,10 +8053,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Guest should get hints from 3rd edit, 6th LSP query" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!(inlay_cache.version, edits_made); }); @@ -8103,10 +8078,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Host should react to /refresh LSP request and get new hints from 7th LSP query" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!( inlay_cache.version, edits_made, "Host should accepted all edits and bump its cache version every time" @@ -8128,10 +8099,6 @@ async fn test_mutual_editor_inlay_hint_cache_update( "Guest should get a /refresh LSP request propagated by host and get new hints from 8th LSP query" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!( inlay_cache.version, edits_made, @@ -8164,9 +8131,9 @@ async fn test_inlay_hint_refresh_is_forwarded( store.update_user_settings::(cx, |settings| { settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: false, - show_type_hints: true, + show_type_hints: false, show_parameter_hints: false, - show_other_hints: true, + show_other_hints: false, }) }); }); @@ -8177,13 +8144,12 @@ async fn test_inlay_hint_refresh_is_forwarded( settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: true, show_type_hints: true, - show_parameter_hints: false, + show_parameter_hints: true, show_other_hints: true, }) }); }); }); - let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); let mut language = Language::new( LanguageConfig { @@ -8299,10 +8265,6 @@ async fn test_inlay_hint_refresh_is_forwarded( "Host should get no hints due to them turned off" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Host should have allowed hint kinds set despite hints are off" - ); assert_eq!( inlay_cache.version, 0, "Host should not increment its cache version due to no changes", @@ -8318,10 +8280,6 @@ async fn test_inlay_hint_refresh_is_forwarded( "Client should get its first hints when opens an editor" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Cache should use editor settings to get the allowed hint kinds" - ); assert_eq!( inlay_cache.version, edits_made, "Guest editor update the cache version after every cache/view change" @@ -8339,7 +8297,6 @@ async fn test_inlay_hint_refresh_is_forwarded( "Host should get nop hints due to them turned off, even after the /refresh" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!( inlay_cache.version, 0, "Host should not increment its cache version due to no changes", @@ -8355,10 +8312,6 @@ async fn test_inlay_hint_refresh_is_forwarded( "Guest should get a /refresh LSP request propagated by host despite host hints are off" ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Inlay kinds settings never change during the test" - ); assert_eq!( inlay_cache.version, edits_made, "Guest should accepted all edits and bump its cache version every time" diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 9ca94665c2..70fb372504 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -833,7 +833,7 @@ mod tests { use crate::{ scroll::{autoscroll::Autoscroll, scroll_amount::ScrollAmount}, serde_json::json, - ExcerptRange, InlayHintSettings, + ExcerptRange, }; use futures::StreamExt; use gpui::{executor::Deterministic, TestAppContext, ViewHandle}; @@ -1087,13 +1087,12 @@ mod tests { #[gpui::test] async fn test_no_hint_updates_for_unrelated_language_files(cx: &mut gpui::TestAppContext) { - let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); init_test(cx, |settings| { settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: true, - show_type_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Type)), - show_parameter_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Parameter)), - show_other_hints: allowed_hint_kinds.contains(&None), + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, }) }); @@ -1196,10 +1195,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.allowed_hint_kinds, allowed_hint_kinds, - "Cache should use editor settings to get the allowed hint kinds" - ); assert_eq!( inlay_cache.version, 1, "Rust editor update the cache version after every cache/view change" @@ -1258,7 +1253,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 1); }); @@ -1276,7 +1270,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!( inlay_cache.version, 2, "Every time hint cache changes, cache version should be incremented" @@ -1291,7 +1284,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 1); }); @@ -1309,7 +1301,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 2); }); rs_editor.update(cx, |editor, cx| { @@ -1321,7 +1312,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 2); }); } @@ -1444,7 +1434,6 @@ mod tests { visible_hint_labels(editor, cx) ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!( inlay_cache.version, edits_made, "Should not update cache version due to new loaded hints being the same" @@ -1580,7 +1569,6 @@ mod tests { assert!(cached_hint_labels(editor).is_empty()); assert!(visible_hint_labels(editor, cx).is_empty()); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, another_allowed_hint_kinds); assert_eq!( inlay_cache.version, edits_made, "The editor should not update the cache version after /refresh query without updates" @@ -1654,20 +1642,18 @@ mod tests { visible_hint_labels(editor, cx), ); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, final_allowed_hint_kinds); assert_eq!(inlay_cache.version, edits_made); }); } #[gpui::test] async fn test_hint_request_cancellation(cx: &mut gpui::TestAppContext) { - let allowed_hint_kinds = HashSet::from_iter([None]); init_test(cx, |settings| { settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: true, - show_type_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Type)), - show_parameter_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Parameter)), - show_other_hints: allowed_hint_kinds.contains(&None), + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, }) }); @@ -1735,7 +1721,6 @@ mod tests { ); assert_eq!(expected_hints, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!( inlay_cache.version, 1, "Only one update should be registered in the cache after all cancellations" @@ -1782,7 +1767,6 @@ mod tests { ); assert_eq!(expected_hints, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!( inlay_cache.version, 2, "Should update the cache version once more, for the new change" @@ -1792,13 +1776,12 @@ mod tests { #[gpui::test] async fn test_large_buffer_inlay_requests_split(cx: &mut gpui::TestAppContext) { - let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); init_test(cx, |settings| { settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: true, - show_type_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Type)), - show_parameter_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Parameter)), - show_other_hints: allowed_hint_kinds.contains(&None), + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, }) }); @@ -1904,7 +1887,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!( inlay_cache.version, 2, "Both LSP queries should've bumped the cache version" @@ -1937,7 +1919,6 @@ mod tests { "Should have hints from the new LSP response after edit"); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 5, "Should update the cache for every LSP response with hints added"); }); } @@ -1947,13 +1928,12 @@ mod tests { deterministic: Arc, cx: &mut gpui::TestAppContext, ) { - let allowed_hint_kinds = HashSet::from_iter([None, Some(InlayHintKind::Type)]); init_test(cx, |settings| { settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: true, - show_type_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Type)), - show_parameter_hints: allowed_hint_kinds.contains(&Some(InlayHintKind::Parameter)), - show_other_hints: allowed_hint_kinds.contains(&None), + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, }) }); @@ -2159,7 +2139,6 @@ mod tests { ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 4, "Every visible excerpt hints should bump the verison"); }); @@ -2191,7 +2170,6 @@ mod tests { "With more scrolls of the multibuffer, more hints should be added into the cache and nothing invalidated without edits"); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 9); }); @@ -2220,7 +2198,6 @@ mod tests { "After multibuffer was scrolled to the end, all hints for all excerpts should be fetched"); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 12); }); @@ -2249,7 +2226,6 @@ mod tests { "After multibuffer was scrolled to the end, further scrolls up should not bring more hints"); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 12, "No updates should happen during scrolling already scolled buffer"); }); @@ -2276,7 +2252,6 @@ mod tests { unedited (2nd) buffer should have the same hint"); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.allowed_hint_kinds, allowed_hint_kinds); assert_eq!(inlay_cache.version, 16); }); } From 318deed25b4bad1c0d0cfc29749a50a06a87590b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 7 Jul 2023 12:02:08 +0200 Subject: [PATCH 097/104] Skip key down event if preceded by its key equivalent version Previously, we would only track whether the previous key down event was a key equivalent. However, this could cause issues when pressing certain keystrokes in rapid succession, e.g.: - Pressing `shift-right` (to select a character) - Pressing a character (with or without `shift` held down) This would cause GPUI to ignore the second event because it was preceded by a key equivalent event. With this commit, we track the last key equivalent event, and skip the key down event only if it matches the last key equivalent event. --- crates/gpui/src/platform/event.rs | 2 +- crates/gpui/src/platform/mac/window.rs | 59 ++++++++++---------------- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/crates/gpui/src/platform/event.rs b/crates/gpui/src/platform/event.rs index c39c76dc34..4456db9a51 100644 --- a/crates/gpui/src/platform/event.rs +++ b/crates/gpui/src/platform/event.rs @@ -4,7 +4,7 @@ use pathfinder_geometry::vector::vec2f; use crate::{geometry::vector::Vector2F, keymap_matcher::Keystroke}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct KeyDownEvent { pub keystroke: Keystroke, pub is_held: bool, diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 3c82538611..381a4fbaaa 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -232,10 +232,6 @@ unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const C sel!(canBecomeKeyWindow), yes as extern "C" fn(&Object, Sel) -> BOOL, ); - decl.add_method( - sel!(sendEvent:), - send_event as extern "C" fn(&Object, Sel, id), - ); decl.add_method( sel!(windowDidResize:), window_did_resize as extern "C" fn(&Object, Sel, id), @@ -299,7 +295,7 @@ struct WindowState { appearance_changed_callback: Option>, input_handler: Option>, pending_key_down: Option<(KeyDownEvent, Option)>, - performed_key_equivalent: bool, + last_key_equivalent: Option, synthetic_drag_counter: usize, executor: Rc, scene_to_render: Option, @@ -521,7 +517,7 @@ impl Window { appearance_changed_callback: None, input_handler: None, pending_key_down: None, - performed_key_equivalent: false, + last_key_equivalent: None, synthetic_drag_counter: 0, executor, scene_to_render: Default::default(), @@ -965,36 +961,34 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: let window_height = window_state_borrow.content_size().y(); let event = unsafe { Event::from_native(native_event, Some(window_height)) }; - if let Some(event) = event { + if let Some(Event::KeyDown(event)) = event { + // For certain keystrokes, macOS will first dispatch a "key equivalent" event. + // If that event isn't handled, it will then dispatch a "key down" event. GPUI + // makes no distinction between these two types of events, so we need to ignore + // the "key down" event if we've already just processed its "key equivalent" version. if key_equivalent { - window_state_borrow.performed_key_equivalent = true; - } else if window_state_borrow.performed_key_equivalent { + window_state_borrow.last_key_equivalent = Some(event.clone()); + } else if window_state_borrow.last_key_equivalent.take().as_ref() == Some(&event) { return NO; } - let function_is_held; - window_state_borrow.pending_key_down = match event { - Event::KeyDown(event) => { - let keydown = event.keystroke.clone(); - // Ignore events from held-down keys after some of the initially-pressed keys - // were released. - if event.is_held { - if window_state_borrow.last_fresh_keydown.as_ref() != Some(&keydown) { - return YES; - } - } else { - window_state_borrow.last_fresh_keydown = Some(keydown); - } - function_is_held = event.keystroke.function; - Some((event, None)) + let keydown = event.keystroke.clone(); + let fn_modifier = keydown.function; + // Ignore events from held-down keys after some of the initially-pressed keys + // were released. + if event.is_held { + if window_state_borrow.last_fresh_keydown.as_ref() != Some(&keydown) { + return YES; } - - _ => return NO, - }; - + } else { + window_state_borrow.last_fresh_keydown = Some(keydown); + } + window_state_borrow.pending_key_down = Some((event, None)); drop(window_state_borrow); - if !function_is_held { + // Send the event to the input context for IME handling, unless the `fn` modifier is + // being pressed. + if !fn_modifier { unsafe { let input_context: id = msg_send![this, inputContext]; let _: BOOL = msg_send![input_context, handleEvent: native_event]; @@ -1143,13 +1137,6 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) { } } -extern "C" fn send_event(this: &Object, _: Sel, native_event: id) { - unsafe { - let _: () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event]; - get_window_state(this).borrow_mut().performed_key_equivalent = false; - } -} - extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) { let window_state = unsafe { get_window_state(this) }; window_state.as_ref().borrow().move_traffic_light(); From abf3b4a54e66e0a67cc39c2b6454d89ab7295534 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 7 Jul 2023 15:07:12 +0200 Subject: [PATCH 098/104] chore: Replace lazy_static Mutex with const. (#2693) Mutex::new() is const-stable as of Rust 1.63. Release Notes: - N/A --- Cargo.lock | 2 -- crates/collab/src/db.rs | 5 +---- crates/collab/src/tests/randomized_integration_tests.rs | 4 ++-- crates/db/src/db.rs | 2 +- crates/language/src/syntax_map.rs | 5 +---- crates/live_kit_client/Cargo.toml | 3 --- crates/live_kit_client/src/test.rs | 7 ++----- crates/vim/Cargo.toml | 1 - crates/vim/src/test/neovim_connection.rs | 6 +----- 9 files changed, 8 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac089cee18..60ed830683 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4004,7 +4004,6 @@ dependencies = [ "gpui", "hmac 0.12.1", "jwt", - "lazy_static", "live_kit_server", "log", "media", @@ -8398,7 +8397,6 @@ dependencies = [ "indoc", "itertools", "language", - "lazy_static", "log", "nvim-rs", "parking_lot 0.11.2", diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index 208da22efe..e16fa9edb1 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -3517,7 +3517,6 @@ pub use test::*; mod test { use super::*; use gpui::executor::Background; - use lazy_static::lazy_static; use parking_lot::Mutex; use sea_orm::ConnectionTrait; use sqlx::migrate::MigrateDatabase; @@ -3566,9 +3565,7 @@ mod test { } pub fn postgres(background: Arc) -> Self { - lazy_static! { - static ref LOCK: Mutex<()> = Mutex::new(()); - } + static LOCK: Mutex<()> = Mutex::new(()); let _guard = LOCK.lock(); let mut rng = StdRng::from_entropy(); diff --git a/crates/collab/src/tests/randomized_integration_tests.rs b/crates/collab/src/tests/randomized_integration_tests.rs index a95938f6b8..f5dfe17d6f 100644 --- a/crates/collab/src/tests/randomized_integration_tests.rs +++ b/crates/collab/src/tests/randomized_integration_tests.rs @@ -37,9 +37,9 @@ use util::ResultExt; lazy_static::lazy_static! { static ref PLAN_LOAD_PATH: Option = path_env_var("LOAD_PLAN"); static ref PLAN_SAVE_PATH: Option = path_env_var("SAVE_PLAN"); - static ref LOADED_PLAN_JSON: Mutex>> = Default::default(); - static ref PLAN: Mutex>>> = Default::default(); } +static LOADED_PLAN_JSON: Mutex>> = Mutex::new(None); +static PLAN: Mutex>>> = Mutex::new(None); #[gpui::test(iterations = 100, on_failure = "on_failure")] async fn test_random_collaboration( diff --git a/crates/db/src/db.rs b/crates/db/src/db.rs index 5b8aca07e0..798dfbc17f 100644 --- a/crates/db/src/db.rs +++ b/crates/db/src/db.rs @@ -43,10 +43,10 @@ const DB_FILE_NAME: &'static str = "db.sqlite"; lazy_static::lazy_static! { // !!!!!!! CHANGE BACK TO DEFAULT FALSE BEFORE SHIPPING static ref ZED_STATELESS: bool = std::env::var("ZED_STATELESS").map_or(false, |v| !v.is_empty()); - static ref DB_FILE_OPERATIONS: Mutex<()> = Mutex::new(()); pub static ref BACKUP_DB_PATH: RwLock> = RwLock::new(None); pub static ref ALL_FILE_DB_FAILED: AtomicBool = AtomicBool::new(false); } +static DB_FILE_OPERATIONS: Mutex<()> = Mutex::new(()); /// Open or create a database at the given directory path. /// This will retry a couple times if there are failures. If opening fails once, the db directory diff --git a/crates/language/src/syntax_map.rs b/crates/language/src/syntax_map.rs index 1570baf185..b6431c2286 100644 --- a/crates/language/src/syntax_map.rs +++ b/crates/language/src/syntax_map.rs @@ -4,7 +4,6 @@ mod syntax_map_tests; use crate::{Grammar, InjectionConfig, Language, LanguageRegistry}; use collections::HashMap; use futures::FutureExt; -use lazy_static::lazy_static; use parking_lot::Mutex; use std::{ borrow::Cow, @@ -25,9 +24,7 @@ thread_local! { static PARSER: RefCell = RefCell::new(Parser::new()); } -lazy_static! { - static ref QUERY_CURSORS: Mutex> = Default::default(); -} +static QUERY_CURSORS: Mutex> = Mutex::new(vec![]); #[derive(Default)] pub struct SyntaxMap { diff --git a/crates/live_kit_client/Cargo.toml b/crates/live_kit_client/Cargo.toml index 36087a42a3..78f435906b 100644 --- a/crates/live_kit_client/Cargo.toml +++ b/crates/live_kit_client/Cargo.toml @@ -17,7 +17,6 @@ test-support = [ "async-trait", "collections/test-support", "gpui/test-support", - "lazy_static", "live_kit_server", "nanoid", ] @@ -38,7 +37,6 @@ parking_lot.workspace = true postage.workspace = true async-trait = { workspace = true, optional = true } -lazy_static = { workspace = true, optional = true } nanoid = { version ="0.4", optional = true} [dev-dependencies] @@ -60,7 +58,6 @@ foreign-types = "0.3" futures.workspace = true hmac = "0.12" jwt = "0.16" -lazy_static.workspace = true objc = "0.2" parking_lot.workspace = true serde.workspace = true diff --git a/crates/live_kit_client/src/test.rs b/crates/live_kit_client/src/test.rs index 3fc046c5a2..ada864fc44 100644 --- a/crates/live_kit_client/src/test.rs +++ b/crates/live_kit_client/src/test.rs @@ -1,18 +1,15 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; -use collections::HashMap; +use collections::{BTreeMap, HashMap}; use futures::Stream; use gpui::executor::Background; -use lazy_static::lazy_static; use live_kit_server::token; use media::core_video::CVImageBuffer; use parking_lot::Mutex; use postage::watch; use std::{future::Future, mem, sync::Arc}; -lazy_static! { - static ref SERVERS: Mutex>> = Default::default(); -} +static SERVERS: Mutex>> = Mutex::new(BTreeMap::new()); pub struct TestServer { pub url: String, diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index 57d3821379..47a85f4ed3 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -36,7 +36,6 @@ workspace = { path = "../workspace" } [dev-dependencies] indoc.workspace = true parking_lot.workspace = true -lazy_static.workspace = true editor = { path = "../editor", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } diff --git a/crates/vim/src/test/neovim_connection.rs b/crates/vim/src/test/neovim_connection.rs index c3916722dd..aa14e4a065 100644 --- a/crates/vim/src/test/neovim_connection.rs +++ b/crates/vim/src/test/neovim_connection.rs @@ -11,8 +11,6 @@ use gpui::keymap_matcher::Keystroke; use language::Point; -#[cfg(feature = "neovim")] -use lazy_static::lazy_static; #[cfg(feature = "neovim")] use nvim_rs::{ create::tokio::new_child_cmd, error::LoopError, Handler, Neovim, UiAttachOptions, Value, @@ -32,9 +30,7 @@ use collections::VecDeque; // Neovim doesn't like to be started simultaneously from multiple threads. We use this lock // to ensure we are only constructing one neovim connection at a time. #[cfg(feature = "neovim")] -lazy_static! { - static ref NEOVIM_LOCK: ReentrantMutex<()> = ReentrantMutex::new(()); -} +static NEOVIM_LOCK: ReentrantMutex<()> = ReentrantMutex::new(()); #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum NeovimData { From 66bf56fc4f571c94486c5e2a1552aebf66f5f797 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 6 Jul 2023 17:18:45 -0400 Subject: [PATCH 099/104] Prevent duplicate instances by coordinating via a socket --- crates/cli/src/main.rs | 1 + crates/zed/src/main.rs | 9 +++- crates/zed/src/only_instance.rs | 82 +++++++++++++++++++++++++++++++++ crates/zed/src/zed.rs | 1 + 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 crates/zed/src/only_instance.rs diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index bdf677512c..2f742814a8 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -201,6 +201,7 @@ impl Bundle { self.zed_version_string() ); } + Self::LocalPath { executable, .. } => { let executable_parent = executable .parent() diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 3da8c24617..5eed301367 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -57,8 +57,9 @@ use staff_mode::StaffMode; use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt}; use workspace::{item::ItemHandle, notifications::NotifyResultExt, AppState, Workspace}; use zed::{ - assets::Assets, build_window_options, handle_keymap_file_changes, initialize_workspace, - languages, menus, + assets::Assets, + build_window_options, handle_keymap_file_changes, initialize_workspace, languages, menus, + only_instance::{ensure_only_instance, IsOnlyInstance}, }; fn main() { @@ -66,6 +67,10 @@ fn main() { init_paths(); init_logger(); + if ensure_only_instance() != IsOnlyInstance::Yes { + return; + } + log::info!("========== starting zed =========="); let mut app = gpui::App::new(Assets).unwrap(); diff --git a/crates/zed/src/only_instance.rs b/crates/zed/src/only_instance.rs new file mode 100644 index 0000000000..c1358f7a33 --- /dev/null +++ b/crates/zed/src/only_instance.rs @@ -0,0 +1,82 @@ +use std::{ + io::{Read, Write}, + net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener, TcpStream}, + thread, + time::Duration, +}; + +const PORT: u16 = 43739; +const LOCALHOST: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); +const ADDRESS: SocketAddr = SocketAddr::V4(SocketAddrV4::new(LOCALHOST, PORT)); +const INSTANCE_HANDSHAKE: &str = "Zed Editor Instance Running"; +const CONNECT_TIMEOUT: Duration = Duration::from_millis(10); +const RECEIVE_TIMEOUT: Duration = Duration::from_millis(35); +const SEND_TIMEOUT: Duration = Duration::from_millis(20); + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum IsOnlyInstance { + Yes, + No, +} + +pub fn ensure_only_instance() -> IsOnlyInstance { + if check_got_handshake() { + return IsOnlyInstance::No; + } + + let listener = match TcpListener::bind(ADDRESS) { + Ok(listener) => listener, + + Err(err) => { + log::warn!("Error binding to single instance port: {err}"); + if check_got_handshake() { + return IsOnlyInstance::No; + } + + // Avoid failing to start when some other application by chance already has + // a claim on the port. This is sub-par as any other instance that gets launched + // will be unable to communicate with this instance and will duplicate + log::warn!("Backup handshake request failed, continuing without handshake"); + return IsOnlyInstance::Yes; + } + }; + + thread::spawn(move || { + for stream in listener.incoming() { + let mut stream = match stream { + Ok(stream) => stream, + Err(_) => return, + }; + + _ = stream.set_nodelay(true); + _ = stream.set_read_timeout(Some(SEND_TIMEOUT)); + _ = stream.write_all(INSTANCE_HANDSHAKE.as_bytes()); + } + }); + + IsOnlyInstance::Yes +} + +fn check_got_handshake() -> bool { + match TcpStream::connect_timeout(&ADDRESS, CONNECT_TIMEOUT) { + Ok(mut stream) => { + let mut buf = vec![0u8; INSTANCE_HANDSHAKE.len()]; + + stream.set_read_timeout(Some(RECEIVE_TIMEOUT)).unwrap(); + if let Err(err) = stream.read_exact(&mut buf) { + log::warn!("Connected to single instance port but failed to read: {err}"); + return false; + } + + if buf == INSTANCE_HANDSHAKE.as_bytes() { + log::info!("Got instance handshake"); + return true; + } + + log::warn!("Got wrong instance handshake value"); + false + } + + Err(_) => false, + } +} diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 0df16f4bab..09bdbf65be 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,6 +1,7 @@ pub mod assets; pub mod languages; pub mod menus; +pub mod only_instance; #[cfg(any(test, feature = "test-support"))] pub mod test; From b70b76029e17e1cb96d9d008755bb48fd682df5c Mon Sep 17 00:00:00 2001 From: Julia Date: Fri, 7 Jul 2023 14:18:43 -0400 Subject: [PATCH 100/104] Use different port and handshake for different release channels --- crates/db/src/db.rs | 3 +-- crates/zed/src/only_instance.rs | 33 +++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/crates/db/src/db.rs b/crates/db/src/db.rs index 798dfbc17f..7b4aa74a80 100644 --- a/crates/db/src/db.rs +++ b/crates/db/src/db.rs @@ -41,8 +41,7 @@ const FALLBACK_DB_NAME: &'static str = "FALLBACK_MEMORY_DB"; const DB_FILE_NAME: &'static str = "db.sqlite"; lazy_static::lazy_static! { - // !!!!!!! CHANGE BACK TO DEFAULT FALSE BEFORE SHIPPING - static ref ZED_STATELESS: bool = std::env::var("ZED_STATELESS").map_or(false, |v| !v.is_empty()); + pub static ref ZED_STATELESS: bool = std::env::var("ZED_STATELESS").map_or(false, |v| !v.is_empty()); pub static ref BACKUP_DB_PATH: RwLock> = RwLock::new(None); pub static ref ALL_FILE_DB_FAILED: AtomicBool = AtomicBool::new(false); } diff --git a/crates/zed/src/only_instance.rs b/crates/zed/src/only_instance.rs index c1358f7a33..0450b5908b 100644 --- a/crates/zed/src/only_instance.rs +++ b/crates/zed/src/only_instance.rs @@ -5,14 +5,31 @@ use std::{ time::Duration, }; -const PORT: u16 = 43739; +use util::channel::ReleaseChannel; + const LOCALHOST: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); -const ADDRESS: SocketAddr = SocketAddr::V4(SocketAddrV4::new(LOCALHOST, PORT)); -const INSTANCE_HANDSHAKE: &str = "Zed Editor Instance Running"; const CONNECT_TIMEOUT: Duration = Duration::from_millis(10); const RECEIVE_TIMEOUT: Duration = Duration::from_millis(35); const SEND_TIMEOUT: Duration = Duration::from_millis(20); +fn address() -> SocketAddr { + let port = match *util::channel::RELEASE_CHANNEL { + ReleaseChannel::Dev => 43737, + ReleaseChannel::Preview => 43738, + ReleaseChannel::Stable => 43739, + }; + + SocketAddr::V4(SocketAddrV4::new(LOCALHOST, port)) +} + +fn instance_handshake() -> &'static str { + match *util::channel::RELEASE_CHANNEL { + ReleaseChannel::Dev => "Zed Editor Dev Instance Running", + ReleaseChannel::Preview => "Zed Editor Preview Instance Running", + ReleaseChannel::Stable => "Zed Editor Stable Instance Running", + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum IsOnlyInstance { Yes, @@ -24,7 +41,7 @@ pub fn ensure_only_instance() -> IsOnlyInstance { return IsOnlyInstance::No; } - let listener = match TcpListener::bind(ADDRESS) { + let listener = match TcpListener::bind(address()) { Ok(listener) => listener, Err(err) => { @@ -50,7 +67,7 @@ pub fn ensure_only_instance() -> IsOnlyInstance { _ = stream.set_nodelay(true); _ = stream.set_read_timeout(Some(SEND_TIMEOUT)); - _ = stream.write_all(INSTANCE_HANDSHAKE.as_bytes()); + _ = stream.write_all(instance_handshake().as_bytes()); } }); @@ -58,9 +75,9 @@ pub fn ensure_only_instance() -> IsOnlyInstance { } fn check_got_handshake() -> bool { - match TcpStream::connect_timeout(&ADDRESS, CONNECT_TIMEOUT) { + match TcpStream::connect_timeout(&address(), CONNECT_TIMEOUT) { Ok(mut stream) => { - let mut buf = vec![0u8; INSTANCE_HANDSHAKE.len()]; + let mut buf = vec![0u8; instance_handshake().len()]; stream.set_read_timeout(Some(RECEIVE_TIMEOUT)).unwrap(); if let Err(err) = stream.read_exact(&mut buf) { @@ -68,7 +85,7 @@ fn check_got_handshake() -> bool { return false; } - if buf == INSTANCE_HANDSHAKE.as_bytes() { + if buf == instance_handshake().as_bytes() { log::info!("Got instance handshake"); return true; } From caa29d57c2d82fbbcdc2f7d7ef6ec1d39969767c Mon Sep 17 00:00:00 2001 From: Julia Date: Fri, 7 Jul 2023 14:19:13 -0400 Subject: [PATCH 101/104] Avoid checking for duplicate instance when local DB is disabled --- crates/zed/src/only_instance.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/zed/src/only_instance.rs b/crates/zed/src/only_instance.rs index 0450b5908b..a8c4b30816 100644 --- a/crates/zed/src/only_instance.rs +++ b/crates/zed/src/only_instance.rs @@ -37,6 +37,10 @@ pub enum IsOnlyInstance { } pub fn ensure_only_instance() -> IsOnlyInstance { + if *db::ZED_STATELESS { + return IsOnlyInstance::Yes; + } + if check_got_handshake() { return IsOnlyInstance::No; } From 52a497be21d9a19ae9136d13ab524847d3b84daf Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Sat, 8 Jul 2023 18:03:18 -0400 Subject: [PATCH 102/104] Remove code block for GitHub release notes Discord can directly render the Markdown now. --- .github/workflows/release_actions.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/release_actions.yml b/.github/workflows/release_actions.yml index 4ccab09cbe..71909ae177 100644 --- a/.github/workflows/release_actions.yml +++ b/.github/workflows/release_actions.yml @@ -16,8 +16,4 @@ jobs: Restart your Zed or head to https://zed.dev/releases/stable/latest to grab it. - ```md - # Changelog - ${{ github.event.release.body }} - ``` From 6e24ded2bcbab2b0798c8c1ed3b88165a30c5c47 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:20:12 +0200 Subject: [PATCH 103/104] collab_ui: Add tooltip to branches popover (#2695) Z-2554 Release Notes: - N/A --- crates/collab_ui/src/collab_titlebar_item.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 73450e7c7d..ed3315ab5a 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -264,7 +264,8 @@ impl CollabTitlebarItem { MouseEventHandler::::new( 0, cx, - |mouse_state, _| { + |mouse_state, cx| { + enum BranchPopoverTooltip {} let style = git_style .in_state(self.branch_popover.is_some()) .style_for(mouse_state); @@ -274,6 +275,13 @@ impl CollabTitlebarItem { .with_margin_right(item_spacing) .aligned() .left() + .with_tooltip::( + 0, + "Recent branches".into(), + None, + theme.tooltip.clone(), + cx, + ) .into_any_named("title-project-branch") }, ) From 6c8cb6b2a9f8dbebb7e31df9035940b5ffd7659f Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 5 Jul 2023 10:54:28 +0200 Subject: [PATCH 104/104] project_search: display result count on cmd-enter It also focuses the first result (just like a normal enter). --- crates/search/src/project_search.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 135194df6a..ebd504d02c 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -675,6 +675,9 @@ impl ProjectSearchView { if match_ranges.is_empty() { self.active_match_index = None; } else { + self.active_match_index = Some(0); + self.select_match(Direction::Next, cx); + self.update_match_index(cx); let prev_search_id = mem::replace(&mut self.search_id, self.model.read(cx).search_id); let is_new_search = self.search_id != prev_search_id; self.results_editor.update(cx, |editor, cx| {