
resolves #24655 resolves #23945 I haven't yet added a default binding for the new command. #27797 added `:ls` and `:buffers` which in my opinion should use the global searchable version given that that matches the vim semantics of those commands better than just showing the tabs in the local pane. There's also a question of what to do when you select a tab from another pane, should the focus jump to that pane or should that tab move to the currently focused pane? For now I've implemented the former. Release Notes: - Added `tab_switcher::ToggleAll` to search open tabs from all panes and focus the selected one. --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
171 lines
6.6 KiB
Rust
171 lines
6.6 KiB
Rust
use auto_update::AutoUpdater;
|
|
use client::proto::UpdateNotification;
|
|
use editor::{Editor, MultiBuffer};
|
|
use gpui::{App, Context, DismissEvent, Entity, SharedString, Window, actions, prelude::*};
|
|
use http_client::HttpClient;
|
|
use markdown_preview::markdown_preview_view::{MarkdownPreviewMode, MarkdownPreviewView};
|
|
use release_channel::{AppVersion, ReleaseChannel};
|
|
use serde::Deserialize;
|
|
use smol::io::AsyncReadExt;
|
|
use util::ResultExt as _;
|
|
use workspace::Workspace;
|
|
use workspace::notifications::simple_message_notification::MessageNotification;
|
|
use workspace::notifications::{NotificationId, show_app_notification};
|
|
|
|
actions!(auto_update, [ViewReleaseNotesLocally]);
|
|
|
|
pub fn init(cx: &mut App) {
|
|
notify_if_app_was_updated(cx);
|
|
cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
|
|
workspace.register_action(|workspace, _: &ViewReleaseNotesLocally, window, cx| {
|
|
view_release_notes_locally(workspace, window, cx);
|
|
});
|
|
})
|
|
.detach();
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct ReleaseNotesBody {
|
|
title: String,
|
|
release_notes: String,
|
|
}
|
|
|
|
fn view_release_notes_locally(
|
|
workspace: &mut Workspace,
|
|
window: &mut Window,
|
|
cx: &mut Context<Workspace>,
|
|
) {
|
|
let release_channel = ReleaseChannel::global(cx);
|
|
|
|
let url = match release_channel {
|
|
ReleaseChannel::Nightly => Some("https://github.com/zed-industries/zed/commits/nightly/"),
|
|
ReleaseChannel::Dev => Some("https://github.com/zed-industries/zed/commits/main/"),
|
|
_ => None,
|
|
};
|
|
|
|
if let Some(url) = url {
|
|
cx.open_url(url);
|
|
return;
|
|
}
|
|
|
|
let version = AppVersion::global(cx).to_string();
|
|
|
|
let client = client::Client::global(cx).http_client();
|
|
let url = client.build_url(&format!(
|
|
"/api/release_notes/v2/{}/{}",
|
|
release_channel.dev_name(),
|
|
version
|
|
));
|
|
|
|
let markdown = workspace
|
|
.app_state()
|
|
.languages
|
|
.language_for_name("Markdown");
|
|
|
|
workspace
|
|
.with_local_workspace(window, cx, move |_, window, cx| {
|
|
cx.spawn_in(window, async move |workspace, cx| {
|
|
let markdown = markdown.await.log_err();
|
|
let response = client.get(&url, Default::default(), true).await;
|
|
let Some(mut response) = response.log_err() else {
|
|
return;
|
|
};
|
|
|
|
let mut body = Vec::new();
|
|
response.body_mut().read_to_end(&mut body).await.ok();
|
|
|
|
let body: serde_json::Result<ReleaseNotesBody> =
|
|
serde_json::from_slice(body.as_slice());
|
|
|
|
if let Ok(body) = body {
|
|
workspace
|
|
.update_in(cx, |workspace, window, cx| {
|
|
let project = workspace.project().clone();
|
|
let buffer = project.update(cx, |project, cx| {
|
|
project.create_local_buffer("", markdown, cx)
|
|
});
|
|
buffer.update(cx, |buffer, cx| {
|
|
buffer.edit([(0..0, body.release_notes)], None, cx)
|
|
});
|
|
let language_registry = project.read(cx).languages().clone();
|
|
|
|
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
|
|
|
|
let tab_content = SharedString::from(body.title.to_string());
|
|
let editor = cx.new(|cx| {
|
|
Editor::for_multibuffer(buffer, Some(project), window, cx)
|
|
});
|
|
let workspace_handle = workspace.weak_handle();
|
|
let markdown_preview: Entity<MarkdownPreviewView> =
|
|
MarkdownPreviewView::new(
|
|
MarkdownPreviewMode::Default,
|
|
editor,
|
|
workspace_handle,
|
|
language_registry,
|
|
tab_content,
|
|
window,
|
|
cx,
|
|
);
|
|
workspace.add_item_to_active_pane(
|
|
Box::new(markdown_preview.clone()),
|
|
None,
|
|
true,
|
|
window,
|
|
cx,
|
|
);
|
|
cx.notify();
|
|
})
|
|
.log_err();
|
|
}
|
|
})
|
|
.detach();
|
|
})
|
|
.detach();
|
|
}
|
|
|
|
/// Shows a notification across all workspaces if an update was previously automatically installed
|
|
/// and this notification had not yet been shown.
|
|
pub fn notify_if_app_was_updated(cx: &mut App) {
|
|
let Some(updater) = AutoUpdater::get(cx) else {
|
|
return;
|
|
};
|
|
let should_show_notification = updater.read(cx).should_show_update_notification(cx);
|
|
cx.spawn(async move |cx| {
|
|
let should_show_notification = should_show_notification.await?;
|
|
if should_show_notification {
|
|
cx.update(|cx| {
|
|
let version = updater.read(cx).current_version();
|
|
let app_name = ReleaseChannel::global(cx).display_name();
|
|
show_app_notification(
|
|
NotificationId::unique::<UpdateNotification>(),
|
|
cx,
|
|
move |cx| {
|
|
let workspace_handle = cx.entity().downgrade();
|
|
cx.new(|cx| {
|
|
MessageNotification::new(
|
|
format!("Updated to {app_name} {}", version),
|
|
cx,
|
|
)
|
|
.primary_message("View Release Notes")
|
|
.primary_on_click(move |window, cx| {
|
|
if let Some(workspace) = workspace_handle.upgrade() {
|
|
workspace.update(cx, |workspace, cx| {
|
|
crate::view_release_notes_locally(workspace, window, cx);
|
|
})
|
|
}
|
|
cx.emit(DismissEvent);
|
|
})
|
|
})
|
|
},
|
|
);
|
|
updater.update(cx, |updater, cx| {
|
|
updater
|
|
.set_should_show_update_notification(false, cx)
|
|
.detach_and_log_err(cx);
|
|
})
|
|
})?;
|
|
}
|
|
anyhow::Ok(())
|
|
})
|
|
.detach();
|
|
}
|