Cargo.lock 🔗
@@ -9207,6 +9207,7 @@ dependencies = [
"serde_json",
"settings",
"sysinfo 0.37.2",
+ "telemetry",
"theme",
"tree-sitter",
"ui",
zed-zippy[bot] , Katie Geer , Ben Kunkle , and Zed Zippy created
Cherry-pick of #48225 to preview
----
Closes #ISSUE
Release Notes:
- N/A *or* Added/Fixed/Improved ...
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Zed Zippy
<234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Katie Geer <katie@zed.dev>
Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Cargo.lock | 1
crates/edit_prediction_ui/src/edit_prediction_button.rs | 103 +++++++++++
crates/language_tools/Cargo.toml | 3
crates/language_tools/src/lsp_button.rs | 20 ++
4 files changed, 125 insertions(+), 2 deletions(-)
@@ -9207,6 +9207,7 @@ dependencies = [
"serde_json",
"settings",
"sysinfo 0.37.2",
+ "telemetry",
"theme",
"tree-sitter",
"ui",
@@ -26,6 +26,7 @@ use settings::{
EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME, Settings, SettingsStore, update_settings_file,
};
use std::{
+ rc::Rc,
sync::{Arc, LazyLock},
time::Duration,
};
@@ -35,6 +36,7 @@ use ui::{
Indicator, PopoverMenu, PopoverMenuHandle, ProgressBar, Tooltip, prelude::*,
};
use util::ResultExt as _;
+
use workspace::{
StatusItemView, Toast, Workspace, create_and_open_local_file, item::ItemHandle,
notifications::NotificationId,
@@ -147,8 +149,20 @@ impl Render for EditPredictionButton {
}
let this = cx.weak_entity();
let project = self.project.clone();
+ let file = self.file.clone();
+ let language = self.language.clone();
div().child(
PopoverMenu::new("copilot")
+ .on_open({
+ let file = file.clone();
+ let language = language;
+ let project = project.clone();
+ Rc::new(move |_window, cx| {
+ emit_edit_prediction_menu_opened(
+ "copilot", &file, &language, &project, cx,
+ );
+ })
+ })
.menu(move |window, cx| {
let current_status = EditPredictionStore::try_global(cx)
.and_then(|store| {
@@ -207,9 +221,26 @@ impl Render for EditPredictionButton {
let has_menu = status.has_menu();
let this = cx.weak_entity();
let fs = self.fs.clone();
+ let file = self.file.clone();
+ let language = self.language.clone();
+ let project = self.project.clone();
div().child(
PopoverMenu::new("supermaven")
+ .on_open({
+ let file = file.clone();
+ let language = language;
+ let project = project;
+ Rc::new(move |_window, cx| {
+ emit_edit_prediction_menu_opened(
+ "supermaven",
+ &file,
+ &language,
+ &project,
+ cx,
+ );
+ })
+ })
.menu(move |window, cx| match &status {
SupermavenButtonStatus::NeedsActivation(activate_url) => {
Some(ContextMenu::build(window, cx, |menu, _, _| {
@@ -258,6 +289,9 @@ impl Render for EditPredictionButton {
let enabled = self.editor_enabled.unwrap_or(true);
let has_api_key = CodestralEditPredictionDelegate::has_api_key(cx);
let this = cx.weak_entity();
+ let file = self.file.clone();
+ let language = self.language.clone();
+ let project = self.project.clone();
let tooltip_meta = if has_api_key {
"Powered by Codestral"
@@ -267,6 +301,20 @@ impl Render for EditPredictionButton {
div().child(
PopoverMenu::new("codestral")
+ .on_open({
+ let file = file.clone();
+ let language = language;
+ let project = project;
+ Rc::new(move |_window, cx| {
+ emit_edit_prediction_menu_opened(
+ "codestral",
+ &file,
+ &language,
+ &project,
+ cx,
+ );
+ })
+ })
.menu(move |window, cx| {
this.update(cx, |this, cx| {
this.build_codestral_context_menu(window, cx)
@@ -360,6 +408,14 @@ impl Render for EditPredictionButton {
| EditPredictionProvider::Sweep
| EditPredictionProvider::Mercury) => {
let enabled = self.editor_enabled.unwrap_or(true);
+ let file = self.file.clone();
+ let language = self.language.clone();
+ let project = self.project.clone();
+ let provider_name: &'static str = match provider {
+ EditPredictionProvider::Experimental(name) => name,
+ EditPredictionProvider::Zed => "zed",
+ _ => "unknown",
+ };
let icons = self
.edit_prediction_provider
.as_ref()
@@ -486,6 +542,20 @@ impl Render for EditPredictionButton {
let this = cx.weak_entity();
let mut popover_menu = PopoverMenu::new("edit-prediction")
+ .on_open({
+ let file = file.clone();
+ let language = language;
+ let project = project;
+ Rc::new(move |_window, cx| {
+ emit_edit_prediction_menu_opened(
+ provider_name,
+ &file,
+ &language,
+ &project,
+ cx,
+ );
+ })
+ })
.map(|popover_menu| {
let this = this.clone();
popover_menu.menu(move |window, cx| {
@@ -1498,6 +1568,39 @@ fn render_zeta_tab_animation(cx: &App) -> impl IntoElement {
.child(tab_sequence(false))
}
+fn emit_edit_prediction_menu_opened(
+ provider: &str,
+ file: &Option<Arc<dyn File>>,
+ language: &Option<Arc<Language>>,
+ project: &WeakEntity<Project>,
+ cx: &App,
+) {
+ let language_name = language.as_ref().map(|l| l.name());
+ let edit_predictions_enabled_for_language =
+ language_settings::language_settings(language_name, file.as_ref(), cx)
+ .show_edit_predictions;
+ let file_extension = file
+ .as_ref()
+ .and_then(|f| {
+ std::path::Path::new(f.file_name(cx))
+ .extension()
+ .and_then(|e| e.to_str())
+ })
+ .map(|s| s.to_string());
+ let is_via_ssh = project
+ .upgrade()
+ .map(|p| p.read(cx).is_via_remote_server())
+ .unwrap_or(false);
+ telemetry::event!(
+ "Toolbar Menu Opened",
+ name = "Edit Predictions",
+ provider,
+ file_extension,
+ edit_predictions_enabled_for_language,
+ is_via_ssh,
+ );
+}
+
fn copilot_settings_url(enterprise_uri: Option<&str>) -> String {
match enterprise_uri {
Some(uri) => {
@@ -28,6 +28,7 @@ project.workspace = true
proto.workspace = true
serde_json.workspace = true
settings.workspace = true
+telemetry.workspace = true
theme.workspace = true
tree-sitter.workspace = true
sysinfo.workspace = true
@@ -42,4 +43,4 @@ release_channel.workspace = true
gpui = { workspace = true, features = ["test-support"] }
semver.workspace = true
util = { workspace = true, features = ["test-support"] }
-zlog.workspace = true
+zlog.workspace = true
@@ -8,6 +8,8 @@ use std::{
use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System};
+use language::language_settings::{EditPredictionProvider, all_language_settings};
+
use client::proto;
use collections::HashSet;
use editor::{Editor, EditorEvent};
@@ -1296,10 +1298,16 @@ impl Render for LspButton {
return div().hidden();
}
+ let state = self.server_state.read(cx);
+ let is_via_ssh = state
+ .workspace
+ .upgrade()
+ .map(|workspace| workspace.read(cx).project().read(cx).is_via_remote_server())
+ .unwrap_or(false);
+
let mut has_errors = false;
let mut has_warnings = false;
let mut has_other_notifications = false;
- let state = self.server_state.read(cx);
for binary_status in state.language_servers.binary_statuses.values() {
has_errors |= matches!(binary_status.status, BinaryStatus::Failed { .. });
has_other_notifications |= binary_status.message.is_some();
@@ -1339,6 +1347,16 @@ impl Render for LspButton {
div().child(
PopoverMenu::new("lsp-tool")
+ .on_open(Rc::new(move |_window, cx| {
+ let copilot_enabled = all_language_settings(None, cx).edit_predictions.provider
+ == EditPredictionProvider::Copilot;
+ telemetry::event!(
+ "Toolbar Menu Opened",
+ name = "Language Servers",
+ copilot_enabled,
+ is_via_ssh,
+ );
+ }))
.menu(move |_, cx| {
lsp_button
.read_with(cx, |lsp_button, _| lsp_button.lsp_menu.clone())