Compare commits
12 Commits
telemetry-
...
v0.72.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f753a83eb1 | ||
|
|
f877d26c3a | ||
|
|
37ad025ccd | ||
|
|
e8ebd6d7a2 | ||
|
|
bcc38a60bf | ||
|
|
8944ca9236 | ||
|
|
6ae297832f | ||
|
|
a7f788746c | ||
|
|
7ff55087f3 | ||
|
|
41102751ef | ||
|
|
a25580fb7f | ||
|
|
bc7bccf5f5 |
19
.github/workflows/release_actions.yml
vendored
19
.github/workflows/release_actions.yml
vendored
@@ -13,23 +13,28 @@ jobs:
|
||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
content: |
|
||||
📣 Zed ${{ github.event.release.tag_name }} was just released!
|
||||
|
||||
|
||||
Restart your Zed or head to https://zed.dev/releases/latest to grab it.
|
||||
|
||||
|
||||
```md
|
||||
# Changelog
|
||||
|
||||
|
||||
${{ github.event.release.body }}
|
||||
```
|
||||
discourse_release:
|
||||
if: ${{ ! github.event.release.prerelease }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v2
|
||||
if: ${{ ! github.event.release.prerelease }}
|
||||
with:
|
||||
node-version: '16'
|
||||
- run: script/discourse_release ${{ secrets.DISCOURSE_RELEASES_API_KEY }} ${{ github.event.release.tag_name }} ${{ github.event.release.body }}
|
||||
node-version: "19"
|
||||
- run: >
|
||||
node "./script/discourse_release"
|
||||
${{ secrets.DISCOURSE_RELEASES_API_KEY }}
|
||||
${{ github.event.release.tag_name }}
|
||||
${{ github.event.release.body }}
|
||||
mixpanel_release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -40,7 +45,7 @@ jobs:
|
||||
architecture: "x64"
|
||||
cache: "pip"
|
||||
- run: pip install -r script/mixpanel_release/requirements.txt
|
||||
- run: >
|
||||
- run: >
|
||||
python script/mixpanel_release/main.py
|
||||
${{ github.event.release.tag_name }}
|
||||
${{ secrets.MIXPANEL_PROJECT_ID }}
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -8228,7 +8228,7 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.72.0"
|
||||
version = "0.72.2"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
||||
@@ -31,7 +31,7 @@ use workspace::{
|
||||
use crate::system_specs::SystemSpecs;
|
||||
|
||||
const FEEDBACK_CHAR_LIMIT: RangeInclusive<usize> = 10..=5000;
|
||||
const FEEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here as Markdown. Save the tab to submit your feedback.";
|
||||
const FEEDBACK_PLACEHOLDER_TEXT: &str = "Save to submit feedback as Markdown.";
|
||||
const FEEDBACK_SUBMISSION_ERROR_TEXT: &str =
|
||||
"Feedback failed to submit, see error log for details.";
|
||||
|
||||
@@ -125,7 +125,9 @@ impl FeedbackEditor {
|
||||
_: ModelHandle<Project>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let feedback_char_count = self.editor.read(cx).text(cx).chars().count();
|
||||
let feedback_text = self.editor.read(cx).text(cx);
|
||||
let feedback_char_count = feedback_text.chars().count();
|
||||
let feedback_text = feedback_text.trim().to_string();
|
||||
|
||||
let error = if feedback_char_count < *FEEDBACK_CHAR_LIMIT.start() {
|
||||
Some(format!(
|
||||
@@ -154,7 +156,6 @@ impl FeedbackEditor {
|
||||
|
||||
let this = cx.handle();
|
||||
let client = cx.global::<Arc<Client>>().clone();
|
||||
let feedback_text = self.editor.read(cx).text(cx);
|
||||
let specs = self.system_specs.clone();
|
||||
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
|
||||
@@ -910,15 +910,14 @@ impl MutableAppContext {
|
||||
.map_or(false, |window| window.is_fullscreen)
|
||||
}
|
||||
|
||||
pub fn window_bounds(&self, window_id: usize) -> WindowBounds {
|
||||
self.presenters_and_platform_windows[&window_id].1.bounds()
|
||||
pub fn window_bounds(&self, window_id: usize) -> Option<WindowBounds> {
|
||||
let (_, window) = self.presenters_and_platform_windows.get(&window_id)?;
|
||||
Some(window.bounds())
|
||||
}
|
||||
|
||||
pub fn window_display_uuid(&self, window_id: usize) -> Uuid {
|
||||
self.presenters_and_platform_windows[&window_id]
|
||||
.1
|
||||
.screen()
|
||||
.display_uuid()
|
||||
pub fn window_display_uuid(&self, window_id: usize) -> Option<Uuid> {
|
||||
let (_, window) = self.presenters_and_platform_windows.get(&window_id)?;
|
||||
window.screen().display_uuid()
|
||||
}
|
||||
|
||||
pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox> {
|
||||
@@ -2375,12 +2374,15 @@ impl MutableAppContext {
|
||||
callback(is_fullscreen, this)
|
||||
});
|
||||
|
||||
let bounds = this.window_bounds(window_id);
|
||||
let uuid = this.window_display_uuid(window_id);
|
||||
let mut bounds_observations = this.window_bounds_observations.clone();
|
||||
bounds_observations.emit(window_id, this, |callback, this| {
|
||||
callback(bounds, uuid, this)
|
||||
});
|
||||
if let Some((uuid, bounds)) = this
|
||||
.window_display_uuid(window_id)
|
||||
.zip(this.window_bounds(window_id))
|
||||
{
|
||||
let mut bounds_observations = this.window_bounds_observations.clone();
|
||||
bounds_observations.emit(window_id, this, |callback, this| {
|
||||
callback(bounds, uuid, this)
|
||||
});
|
||||
}
|
||||
|
||||
Some(())
|
||||
});
|
||||
@@ -2559,14 +2561,17 @@ impl MutableAppContext {
|
||||
}
|
||||
|
||||
fn handle_window_moved(&mut self, window_id: usize) {
|
||||
let bounds = self.window_bounds(window_id);
|
||||
let display = self.window_display_uuid(window_id);
|
||||
self.window_bounds_observations
|
||||
.clone()
|
||||
.emit(window_id, self, move |callback, this| {
|
||||
callback(bounds, display, this);
|
||||
true
|
||||
});
|
||||
if let Some((display, bounds)) = self
|
||||
.window_display_uuid(window_id)
|
||||
.zip(self.window_bounds(window_id))
|
||||
{
|
||||
self.window_bounds_observations
|
||||
.clone()
|
||||
.emit(window_id, self, move |callback, this| {
|
||||
callback(bounds, display, this);
|
||||
true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
|
||||
@@ -3731,10 +3736,6 @@ impl<'a, T: View> ViewContext<'a, T> {
|
||||
self.app.toggle_window_full_screen(self.window_id)
|
||||
}
|
||||
|
||||
pub fn window_bounds(&self) -> WindowBounds {
|
||||
self.app.window_bounds(self.window_id)
|
||||
}
|
||||
|
||||
pub fn prompt(
|
||||
&self,
|
||||
level: PromptLevel,
|
||||
|
||||
@@ -124,7 +124,7 @@ pub trait InputHandler {
|
||||
pub trait Screen: Debug {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn bounds(&self) -> RectF;
|
||||
fn display_uuid(&self) -> Uuid;
|
||||
fn display_uuid(&self) -> Option<Uuid>;
|
||||
}
|
||||
|
||||
pub trait Window {
|
||||
|
||||
@@ -35,7 +35,7 @@ impl Screen {
|
||||
.map(|ix| Screen {
|
||||
native_screen: native_screens.objectAtIndex(ix),
|
||||
})
|
||||
.find(|screen| platform::Screen::display_uuid(screen) == uuid)
|
||||
.find(|screen| platform::Screen::display_uuid(screen) == Some(uuid))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ impl platform::Screen for Screen {
|
||||
self
|
||||
}
|
||||
|
||||
fn display_uuid(&self) -> uuid::Uuid {
|
||||
fn display_uuid(&self) -> Option<uuid::Uuid> {
|
||||
unsafe {
|
||||
// Screen ids are not stable. Further, the default device id is also unstable across restarts.
|
||||
// CGDisplayCreateUUIDFromDisplayID is stable but not exposed in the bindings we use.
|
||||
@@ -74,8 +74,12 @@ impl platform::Screen for Screen {
|
||||
(&mut device_id) as *mut _ as *mut c_void,
|
||||
);
|
||||
let cfuuid = CGDisplayCreateUUIDFromDisplayID(device_id as CGDirectDisplayID);
|
||||
if cfuuid.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let bytes = CFUUIDGetUUIDBytes(cfuuid);
|
||||
Uuid::from_bytes([
|
||||
Some(Uuid::from_bytes([
|
||||
bytes.byte0,
|
||||
bytes.byte1,
|
||||
bytes.byte2,
|
||||
@@ -92,7 +96,7 @@ impl platform::Screen for Screen {
|
||||
bytes.byte13,
|
||||
bytes.byte14,
|
||||
bytes.byte15,
|
||||
])
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,8 +238,8 @@ impl super::Screen for Screen {
|
||||
RectF::new(Vector2F::zero(), Vector2F::new(1920., 1080.))
|
||||
}
|
||||
|
||||
fn display_uuid(&self) -> uuid::Uuid {
|
||||
uuid::Uuid::new_v4()
|
||||
fn display_uuid(&self) -> Option<uuid::Uuid> {
|
||||
Some(uuid::Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@ use highlighted_workspace_location::HighlightedWorkspaceLocation;
|
||||
use ordered_float::OrderedFloat;
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use settings::Settings;
|
||||
use workspace::{OpenPaths, Workspace, WorkspaceLocation, WORKSPACE_DB};
|
||||
use workspace::{
|
||||
notifications::simple_message_notification::MessageNotification, OpenPaths, Workspace,
|
||||
WorkspaceLocation, WORKSPACE_DB,
|
||||
};
|
||||
|
||||
actions!(projects, [OpenRecent]);
|
||||
|
||||
@@ -42,7 +45,7 @@ impl RecentProjectsView {
|
||||
|
||||
fn toggle(_: &mut Workspace, _: &OpenRecent, cx: &mut ViewContext<Workspace>) {
|
||||
cx.spawn(|workspace, mut cx| async move {
|
||||
let workspace_locations = cx
|
||||
let workspace_locations: Vec<_> = cx
|
||||
.background()
|
||||
.spawn(async {
|
||||
WORKSPACE_DB
|
||||
@@ -56,12 +59,20 @@ impl RecentProjectsView {
|
||||
.await;
|
||||
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
workspace.toggle_modal(cx, |_, cx| {
|
||||
let view = cx.add_view(|cx| Self::new(workspace_locations, cx));
|
||||
cx.subscribe(&view, Self::on_event).detach();
|
||||
view
|
||||
});
|
||||
})
|
||||
if !workspace_locations.is_empty() {
|
||||
workspace.toggle_modal(cx, |_, cx| {
|
||||
let view = cx.add_view(|cx| Self::new(workspace_locations, cx));
|
||||
cx.subscribe(&view, Self::on_event).detach();
|
||||
view
|
||||
});
|
||||
} else {
|
||||
workspace.show_notification(0, cx, |cx| {
|
||||
cx.add_view(|_| {
|
||||
MessageNotification::new_message("No recent projects to open.")
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
@@ -259,11 +259,7 @@ impl Item for ProjectSearchView {
|
||||
.boxed(),
|
||||
)
|
||||
.with_children(self.model.read(cx).active_query.as_ref().map(|query| {
|
||||
let query_text = if query.as_str().len() > MAX_TAB_TITLE_LEN {
|
||||
query.as_str()[..MAX_TAB_TITLE_LEN].to_string() + "…"
|
||||
} else {
|
||||
query.as_str().to_string()
|
||||
};
|
||||
let query_text = util::truncate_and_trailoff(query.as_str(), MAX_TAB_TITLE_LEN);
|
||||
|
||||
Label::new(query_text, tab_theme.label.clone())
|
||||
.aligned()
|
||||
@@ -575,9 +571,9 @@ impl ProjectSearchView {
|
||||
self.active_match_index = None;
|
||||
} else {
|
||||
let prev_search_id = mem::replace(&mut self.search_id, self.model.read(cx).search_id);
|
||||
let reset_selections = self.search_id != prev_search_id;
|
||||
let is_new_search = self.search_id != prev_search_id;
|
||||
self.results_editor.update(cx, |editor, cx| {
|
||||
if reset_selections {
|
||||
if is_new_search {
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.select_ranges(match_ranges.first().cloned())
|
||||
});
|
||||
@@ -588,7 +584,7 @@ impl ProjectSearchView {
|
||||
cx,
|
||||
);
|
||||
});
|
||||
if self.query_editor.is_focused(cx) {
|
||||
if is_new_search && self.query_editor.is_focused(cx) {
|
||||
self.focus_results_editor(cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,10 @@ pub fn truncate(s: &str, max_chars: usize) -> &str {
|
||||
pub fn truncate_and_trailoff(s: &str, max_chars: usize) -> String {
|
||||
debug_assert!(max_chars >= 5);
|
||||
|
||||
if s.len() > max_chars {
|
||||
format!("{}…", truncate(s, max_chars.saturating_sub(3)))
|
||||
} else {
|
||||
s.to_string()
|
||||
let truncation_ix = s.char_indices().map(|(i, _)| i).nth(max_chars);
|
||||
match truncation_ix {
|
||||
Some(length) => s[..length].to_string() + "…",
|
||||
None => s.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,4 +276,12 @@ mod tests {
|
||||
|
||||
assert_eq!(foo, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trancate_and_trailoff() {
|
||||
assert_eq!(truncate_and_trailoff("", 5), "");
|
||||
assert_eq!(truncate_and_trailoff("èèèèèè", 7), "èèèèèè");
|
||||
assert_eq!(truncate_and_trailoff("èèèèèè", 6), "èèèèèè");
|
||||
assert_eq!(truncate_and_trailoff("èèèèèè", 5), "èèèèè…");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ pub mod simple_message_notification {
|
||||
}
|
||||
|
||||
impl MessageNotification {
|
||||
pub fn new_messsage<S: AsRef<str>>(message: S) -> MessageNotification {
|
||||
pub fn new_message<S: AsRef<str>>(message: S) -> MessageNotification {
|
||||
Self {
|
||||
message: message.as_ref().to_string(),
|
||||
click_action: None,
|
||||
@@ -320,7 +320,7 @@ where
|
||||
Err(err) => {
|
||||
workspace.show_notification(0, cx, |cx| {
|
||||
cx.add_view(|_cx| {
|
||||
simple_message_notification::MessageNotification::new_messsage(format!(
|
||||
simple_message_notification::MessageNotification::new_message(format!(
|
||||
"Error: {:?}",
|
||||
err,
|
||||
))
|
||||
|
||||
@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.72.0"
|
||||
version = "0.72.2"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
stable
|
||||
Reference in New Issue
Block a user