mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-16 17:07:14 +03:00
gpui: Add Global marker trait (#7095)
This should prevent a class of bugs where one queries the wrong type of global, which results in oddities at runtime. Release Notes: - N/A --------- Co-authored-by: Marshall <marshall@zed.dev> Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
7bfa584eb6
commit
e6ebe7974d
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -661,6 +661,7 @@ dependencies = [
|
||||
"log",
|
||||
"menu",
|
||||
"project",
|
||||
"release_channel",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@ -1188,6 +1189,7 @@ dependencies = [
|
||||
"parking_lot 0.11.2",
|
||||
"postage",
|
||||
"rand 0.8.5",
|
||||
"release_channel",
|
||||
"rpc",
|
||||
"schemars",
|
||||
"serde",
|
||||
@ -1361,6 +1363,7 @@ dependencies = [
|
||||
"parking_lot 0.11.2",
|
||||
"postage",
|
||||
"rand 0.8.5",
|
||||
"release_channel",
|
||||
"rpc",
|
||||
"schemars",
|
||||
"serde",
|
||||
@ -1596,6 +1599,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"client",
|
||||
"collections",
|
||||
"copilot",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger",
|
||||
@ -1606,6 +1610,7 @@ dependencies = [
|
||||
"menu",
|
||||
"picker",
|
||||
"project",
|
||||
"release_channel",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"settings",
|
||||
@ -2040,6 +2045,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"parking_lot 0.11.2",
|
||||
"release_channel",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"smol",
|
||||
@ -2512,6 +2518,7 @@ dependencies = [
|
||||
"postage",
|
||||
"project",
|
||||
"regex",
|
||||
"release_channel",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
@ -4907,9 +4914,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
@ -6108,6 +6115,14 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "release_channel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gpui",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rend"
|
||||
version = "0.4.0"
|
||||
@ -6849,6 +6864,7 @@ dependencies = [
|
||||
"pretty_assertions",
|
||||
"project",
|
||||
"rand 0.8.5",
|
||||
"release_channel",
|
||||
"rpc",
|
||||
"rusqlite",
|
||||
"rust-embed",
|
||||
@ -6988,6 +7004,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"postage",
|
||||
"pretty_assertions",
|
||||
"release_channel",
|
||||
"rust-embed",
|
||||
"schemars",
|
||||
"serde",
|
||||
@ -9139,6 +9156,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"collections",
|
||||
"command_palette",
|
||||
"copilot",
|
||||
"diagnostics",
|
||||
"editor",
|
||||
"futures 0.3.28",
|
||||
@ -9687,6 +9705,7 @@ dependencies = [
|
||||
"client",
|
||||
"collections",
|
||||
"db",
|
||||
"derive_more",
|
||||
"env_logger",
|
||||
"fs",
|
||||
"futures 0.3.28",
|
||||
@ -9840,6 +9859,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"recent_projects",
|
||||
"regex",
|
||||
"release_channel",
|
||||
"rope",
|
||||
"rpc",
|
||||
"rsa 0.4.0",
|
||||
|
@ -59,6 +59,7 @@ members = [
|
||||
"crates/project_symbols",
|
||||
"crates/quick_action_bar",
|
||||
"crates/recent_projects",
|
||||
"crates/release_channel",
|
||||
"crates/rope",
|
||||
"crates/rpc",
|
||||
"crates/search",
|
||||
|
@ -2,7 +2,7 @@ use std::{io::Cursor, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use collections::HashMap;
|
||||
use gpui::{AppContext, AssetSource};
|
||||
use gpui::{AppContext, AssetSource, Global};
|
||||
use rodio::{
|
||||
source::{Buffered, SamplesConverter},
|
||||
Decoder, Source,
|
||||
@ -15,6 +15,10 @@ pub struct SoundRegistry {
|
||||
assets: Box<dyn AssetSource>,
|
||||
}
|
||||
|
||||
struct GlobalSoundRegistry(Arc<SoundRegistry>);
|
||||
|
||||
impl Global for GlobalSoundRegistry {}
|
||||
|
||||
impl SoundRegistry {
|
||||
pub fn new(source: impl AssetSource) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
@ -24,7 +28,11 @@ impl SoundRegistry {
|
||||
}
|
||||
|
||||
pub fn global(cx: &AppContext) -> Arc<Self> {
|
||||
cx.global::<Arc<Self>>().clone()
|
||||
cx.global::<GlobalSoundRegistry>().0.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn set_global(source: impl AssetSource, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalSoundRegistry(SoundRegistry::new(source)));
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Result<impl Source<Item = f32>> {
|
||||
|
@ -1,12 +1,12 @@
|
||||
use assets::SoundRegistry;
|
||||
use gpui::{AppContext, AssetSource};
|
||||
use gpui::{AppContext, AssetSource, Global};
|
||||
use rodio::{OutputStream, OutputStreamHandle};
|
||||
use util::ResultExt;
|
||||
|
||||
mod assets;
|
||||
|
||||
pub fn init(source: impl AssetSource, cx: &mut AppContext) {
|
||||
cx.set_global(SoundRegistry::new(source));
|
||||
SoundRegistry::set_global(source, cx);
|
||||
cx.set_global(Audio::new());
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@ pub struct Audio {
|
||||
output_handle: Option<OutputStreamHandle>,
|
||||
}
|
||||
|
||||
impl Global for Audio {}
|
||||
|
||||
impl Audio {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
@ -15,6 +15,7 @@ client = { path = "../client" }
|
||||
gpui = { path = "../gpui" }
|
||||
menu = { path = "../menu" }
|
||||
project = { path = "../project" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
settings = { path = "../settings" }
|
||||
theme = { path = "../theme" }
|
||||
workspace = { path = "../workspace" }
|
||||
|
@ -5,8 +5,8 @@ use client::{Client, TelemetrySettings, ZED_APP_PATH, ZED_APP_VERSION};
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use db::RELEASE_CHANNEL;
|
||||
use gpui::{
|
||||
actions, AppContext, AsyncAppContext, Context as _, Model, ModelContext, SemanticVersion, Task,
|
||||
ViewContext, VisualContext, WindowContext,
|
||||
actions, AppContext, AsyncAppContext, Context as _, Global, Model, ModelContext,
|
||||
SemanticVersion, Task, ViewContext, VisualContext, WindowContext,
|
||||
};
|
||||
use isahc::AsyncBody;
|
||||
|
||||
@ -18,6 +18,7 @@ use smol::io::AsyncReadExt;
|
||||
use settings::{Settings, SettingsStore};
|
||||
use smol::{fs::File, process::Command};
|
||||
|
||||
use release_channel::{AppCommitSha, ReleaseChannel};
|
||||
use std::{
|
||||
env::consts::{ARCH, OS},
|
||||
ffi::OsString,
|
||||
@ -25,11 +26,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
use update_notification::UpdateNotification;
|
||||
use util::http::HttpClient;
|
||||
use util::{
|
||||
channel::{AppCommitSha, ReleaseChannel},
|
||||
http::ZedHttpClient,
|
||||
};
|
||||
use util::http::{HttpClient, ZedHttpClient};
|
||||
use workspace::Workspace;
|
||||
|
||||
const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification";
|
||||
@ -94,6 +91,11 @@ impl Settings for AutoUpdateSetting {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct GlobalAutoUpdate(Option<Model<AutoUpdater>>);
|
||||
|
||||
impl Global for GlobalAutoUpdate {}
|
||||
|
||||
pub fn init(http_client: Arc<ZedHttpClient>, cx: &mut AppContext) {
|
||||
AutoUpdateSetting::register(cx);
|
||||
|
||||
@ -127,7 +129,7 @@ pub fn init(http_client: Arc<ZedHttpClient>, cx: &mut AppContext) {
|
||||
|
||||
updater
|
||||
});
|
||||
cx.set_global(Some(auto_updater));
|
||||
cx.set_global(GlobalAutoUpdate(Some(auto_updater)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +148,7 @@ pub fn check(_: &Check, cx: &mut WindowContext) {
|
||||
|
||||
pub fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) -> Option<()> {
|
||||
let auto_updater = AutoUpdater::get(cx)?;
|
||||
let release_channel = cx.try_global::<ReleaseChannel>()?;
|
||||
let release_channel = ReleaseChannel::try_global(cx)?;
|
||||
|
||||
if matches!(
|
||||
release_channel,
|
||||
@ -191,7 +193,7 @@ pub fn notify_of_any_new_update(cx: &mut ViewContext<Workspace>) -> Option<()> {
|
||||
|
||||
impl AutoUpdater {
|
||||
pub fn get(cx: &mut AppContext) -> Option<Model<Self>> {
|
||||
cx.default_global::<Option<Model<Self>>>().clone()
|
||||
cx.default_global::<GlobalAutoUpdate>().0.clone()
|
||||
}
|
||||
|
||||
fn new(current_version: SemanticVersion, http_client: Arc<ZedHttpClient>) -> Self {
|
||||
@ -253,8 +255,7 @@ impl AutoUpdater {
|
||||
OS, ARCH
|
||||
));
|
||||
cx.update(|cx| {
|
||||
if let Some(param) = cx
|
||||
.try_global::<ReleaseChannel>()
|
||||
if let Some(param) = ReleaseChannel::try_global(cx)
|
||||
.map(|release_channel| release_channel.release_query_param())
|
||||
.flatten()
|
||||
{
|
||||
@ -276,7 +277,9 @@ impl AutoUpdater {
|
||||
|
||||
let should_download = match *RELEASE_CHANNEL {
|
||||
ReleaseChannel::Nightly => cx
|
||||
.try_read_global::<AppCommitSha, _>(|sha, _| release.version != sha.0)
|
||||
.update(|cx| AppCommitSha::try_global(cx).map(|sha| release.version != sha.0))
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or(true),
|
||||
_ => release.version.parse::<SemanticVersion>()? > current_version,
|
||||
};
|
||||
@ -311,9 +314,8 @@ impl AutoUpdater {
|
||||
let mut dmg_file = File::create(&dmg_path).await?;
|
||||
|
||||
let (installation_id, release_channel, telemetry) = cx.update(|cx| {
|
||||
let installation_id = cx.global::<Arc<Client>>().telemetry().installation_id();
|
||||
let release_channel = cx
|
||||
.try_global::<ReleaseChannel>()
|
||||
let installation_id = Client::global(cx).telemetry().installation_id();
|
||||
let release_channel = ReleaseChannel::try_global(cx)
|
||||
.map(|release_channel| release_channel.display_name());
|
||||
let telemetry = TelemetrySettings::get_global(cx).metrics;
|
||||
|
||||
|
@ -3,7 +3,7 @@ use gpui::{
|
||||
SemanticVersion, StatefulInteractiveElement, Styled, ViewContext,
|
||||
};
|
||||
use menu::Cancel;
|
||||
use util::channel::ReleaseChannel;
|
||||
use release_channel::ReleaseChannel;
|
||||
use workspace::ui::{h_flex, v_flex, Icon, IconName, Label, StyledExt};
|
||||
|
||||
pub struct UpdateNotification {
|
||||
@ -14,7 +14,7 @@ impl EventEmitter<DismissEvent> for UpdateNotification {}
|
||||
|
||||
impl Render for UpdateNotification {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
let app_name = ReleaseChannel::global(cx).display_name();
|
||||
|
||||
v_flex()
|
||||
.on_action(cx.listener(UpdateNotification::dismiss))
|
||||
|
@ -9,8 +9,8 @@ use client::{proto, Client, TypedEnvelope, User, UserStore, ZED_ALWAYS_ACTIVE};
|
||||
use collections::HashSet;
|
||||
use futures::{channel::oneshot, future::Shared, Future, FutureExt};
|
||||
use gpui::{
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Subscription, Task,
|
||||
WeakModel,
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, Subscription,
|
||||
Task, WeakModel,
|
||||
};
|
||||
use postage::watch;
|
||||
use project::Project;
|
||||
@ -21,11 +21,15 @@ use std::sync::Arc;
|
||||
pub use participant::ParticipantLocation;
|
||||
pub use room::Room;
|
||||
|
||||
struct GlobalActiveCall(Model<ActiveCall>);
|
||||
|
||||
impl Global for GlobalActiveCall {}
|
||||
|
||||
pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
|
||||
CallSettings::register(cx);
|
||||
|
||||
let active_call = cx.new_model(|cx| ActiveCall::new(client, user_store, cx));
|
||||
cx.set_global(active_call);
|
||||
cx.set_global(GlobalActiveCall(active_call));
|
||||
}
|
||||
|
||||
pub struct OneAtATime {
|
||||
@ -154,7 +158,12 @@ impl ActiveCall {
|
||||
}
|
||||
|
||||
pub fn global(cx: &AppContext) -> Model<Self> {
|
||||
cx.global::<Model<Self>>().clone()
|
||||
cx.global::<GlobalActiveCall>().0.clone()
|
||||
}
|
||||
|
||||
pub fn try_global(cx: &AppContext) -> Option<Model<Self>> {
|
||||
cx.try_global::<GlobalActiveCall>()
|
||||
.map(|call| call.0.clone())
|
||||
}
|
||||
|
||||
pub fn invite(
|
||||
|
@ -21,6 +21,7 @@ util = { path = "../util" }
|
||||
rpc = { path = "../rpc" }
|
||||
text = { path = "../text" }
|
||||
language = { path = "../language" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
settings = { path = "../settings" }
|
||||
feature_flags = { path = "../feature_flags" }
|
||||
sum_tree = { path = "../sum_tree" }
|
||||
|
@ -5,13 +5,13 @@ use anyhow::{anyhow, Result};
|
||||
use channel_index::ChannelIndex;
|
||||
use client::{Client, Subscription, User, UserId, UserStore};
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
use db::RELEASE_CHANNEL;
|
||||
use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt};
|
||||
use gpui::{
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, SharedString, Task,
|
||||
WeakModel,
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, SharedString,
|
||||
Task, WeakModel,
|
||||
};
|
||||
use language::Capability;
|
||||
use release_channel::RELEASE_CHANNEL;
|
||||
use rpc::{
|
||||
proto::{self, ChannelRole, ChannelVisibility},
|
||||
TypedEnvelope,
|
||||
@ -22,7 +22,7 @@ use util::{async_maybe, maybe, ResultExt};
|
||||
pub fn init(client: &Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
|
||||
let channel_store =
|
||||
cx.new_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx));
|
||||
cx.set_global(channel_store);
|
||||
cx.set_global(GlobalChannelStore(channel_store));
|
||||
}
|
||||
|
||||
pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
@ -143,9 +143,13 @@ enum OpenedModelHandle<E> {
|
||||
Loading(Shared<Task<Result<Model<E>, Arc<anyhow::Error>>>>),
|
||||
}
|
||||
|
||||
struct GlobalChannelStore(Model<ChannelStore>);
|
||||
|
||||
impl Global for GlobalChannelStore {}
|
||||
|
||||
impl ChannelStore {
|
||||
pub fn global(cx: &AppContext) -> Model<Self> {
|
||||
cx.global::<Model<Self>>().clone()
|
||||
cx.global::<GlobalChannelStore>().0.clone()
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
|
@ -18,6 +18,7 @@ collections = { path = "../collections" }
|
||||
db = { path = "../db" }
|
||||
gpui = { path = "../gpui" }
|
||||
util = { path = "../util" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
rpc = { path = "../rpc" }
|
||||
text = { path = "../text" }
|
||||
settings = { path = "../settings" }
|
||||
|
@ -15,13 +15,14 @@ use futures::{
|
||||
TryFutureExt as _, TryStreamExt,
|
||||
};
|
||||
use gpui::{
|
||||
actions, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, Model, SemanticVersion, Task,
|
||||
WeakModel,
|
||||
actions, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, Global, Model, SemanticVersion,
|
||||
Task, WeakModel,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::RwLock;
|
||||
use postage::watch;
|
||||
use rand::prelude::*;
|
||||
use release_channel::ReleaseChannel;
|
||||
use rpc::proto::{AnyTypedEnvelope, EntityMessage, EnvelopedMessage, PeerId, RequestMessage};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -41,8 +42,7 @@ use std::{
|
||||
use telemetry::Telemetry;
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
use util::http::HttpClient;
|
||||
use util::{channel::ReleaseChannel, http::ZedHttpClient};
|
||||
use util::http::{HttpClient, ZedHttpClient};
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
|
||||
pub use rpc::*;
|
||||
@ -149,6 +149,10 @@ pub fn init(client: &Arc<Client>, cx: &mut AppContext) {
|
||||
});
|
||||
}
|
||||
|
||||
struct GlobalClient(Arc<Client>);
|
||||
|
||||
impl Global for GlobalClient {}
|
||||
|
||||
pub struct Client {
|
||||
id: AtomicU64,
|
||||
peer: Arc<Peer>,
|
||||
@ -483,6 +487,13 @@ impl Client {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn global(cx: &AppContext) -> Arc<Self> {
|
||||
cx.global::<GlobalClient>().0.clone()
|
||||
}
|
||||
pub fn set_global(client: Arc<Client>, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalClient(client))
|
||||
}
|
||||
|
||||
pub fn user_id(&self) -> Option<u64> {
|
||||
self.state
|
||||
.read()
|
||||
@ -996,7 +1007,10 @@ impl Client {
|
||||
credentials: &Credentials,
|
||||
cx: &AsyncAppContext,
|
||||
) -> Task<Result<Connection, EstablishConnectionError>> {
|
||||
let release_channel = cx.try_read_global(|channel: &ReleaseChannel, _| *channel);
|
||||
let release_channel = cx
|
||||
.update(|cx| ReleaseChannel::try_global(cx))
|
||||
.ok()
|
||||
.flatten();
|
||||
|
||||
let request = Request::builder()
|
||||
.header(
|
||||
|
@ -5,6 +5,7 @@ use chrono::{DateTime, Utc};
|
||||
use futures::Future;
|
||||
use gpui::{AppContext, AppMetadata, BackgroundExecutor, Task};
|
||||
use parking_lot::Mutex;
|
||||
use release_channel::ReleaseChannel;
|
||||
use serde::Serialize;
|
||||
use settings::{Settings, SettingsStore};
|
||||
use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration};
|
||||
@ -15,7 +16,7 @@ use tempfile::NamedTempFile;
|
||||
use util::http::{HttpClient, ZedHttpClient};
|
||||
#[cfg(not(debug_assertions))]
|
||||
use util::ResultExt;
|
||||
use util::{channel::ReleaseChannel, TryFutureExt};
|
||||
use util::TryFutureExt;
|
||||
|
||||
use self::event_coalescer::EventCoalescer;
|
||||
|
||||
@ -143,9 +144,8 @@ const FLUSH_INTERVAL: Duration = Duration::from_secs(60 * 5);
|
||||
|
||||
impl Telemetry {
|
||||
pub fn new(client: Arc<ZedHttpClient>, cx: &mut AppContext) -> Arc<Self> {
|
||||
let release_channel = cx
|
||||
.try_global::<ReleaseChannel>()
|
||||
.map(|release_channel| release_channel.display_name());
|
||||
let release_channel =
|
||||
ReleaseChannel::try_global(cx).map(|release_channel| release_channel.display_name());
|
||||
|
||||
TelemetrySettings::register(cx);
|
||||
|
||||
|
@ -11,13 +11,4 @@ pub type HashMap<K, V> = std::collections::HashMap<K, V>;
|
||||
pub type HashSet<T> = std::collections::HashSet<T>;
|
||||
|
||||
pub use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::any::TypeId;
|
||||
pub use std::collections::*;
|
||||
|
||||
// NEW TYPES
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CommandPaletteFilter {
|
||||
pub hidden_namespaces: HashSet<&'static str>,
|
||||
pub hidden_action_types: HashSet<TypeId>,
|
||||
}
|
||||
|
@ -12,11 +12,14 @@ doctest = false
|
||||
[dependencies]
|
||||
client = { path = "../client" }
|
||||
collections = { path = "../collections" }
|
||||
# HACK: We're only depending on `copilot` here for `CommandPaletteFilter`. See the attached comment on that type.
|
||||
copilot = { path = "../copilot" }
|
||||
editor = { path = "../editor" }
|
||||
fuzzy = { path = "../fuzzy" }
|
||||
gpui = { path = "../gpui" }
|
||||
picker = { path = "../picker" }
|
||||
project = { path = "../project" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
settings = { path = "../settings" }
|
||||
theme = { path = "../theme" }
|
||||
ui = { path = "../ui" }
|
||||
|
@ -4,19 +4,18 @@ use std::{
|
||||
};
|
||||
|
||||
use client::telemetry::Telemetry;
|
||||
use collections::{CommandPaletteFilter, HashMap};
|
||||
use collections::HashMap;
|
||||
use copilot::CommandPaletteFilter;
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{
|
||||
actions, Action, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
|
||||
actions, Action, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Global,
|
||||
ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
|
||||
use release_channel::{parse_zed_link, ReleaseChannel};
|
||||
use ui::{h_flex, prelude::*, v_flex, HighlightedLabel, KeyBinding, ListItem, ListItemSpacing};
|
||||
use util::{
|
||||
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
||||
ResultExt,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::{ModalView, Workspace};
|
||||
use zed_actions::OpenZedUrl;
|
||||
|
||||
@ -100,8 +99,11 @@ impl Render for CommandPalette {
|
||||
}
|
||||
}
|
||||
|
||||
pub type CommandPaletteInterceptor =
|
||||
Box<dyn Fn(&str, &AppContext) -> Option<CommandInterceptResult>>;
|
||||
pub struct CommandPaletteInterceptor(
|
||||
pub Box<dyn Fn(&str, &AppContext) -> Option<CommandInterceptResult>>,
|
||||
);
|
||||
|
||||
impl Global for CommandPaletteInterceptor {}
|
||||
|
||||
pub struct CommandInterceptResult {
|
||||
pub action: Box<dyn Action>,
|
||||
@ -139,6 +141,8 @@ impl Clone for Command {
|
||||
#[derive(Default)]
|
||||
struct HitCounts(HashMap<String, usize>);
|
||||
|
||||
impl Global for HitCounts {}
|
||||
|
||||
impl CommandPaletteDelegate {
|
||||
fn new(
|
||||
command_palette: WeakView<CommandPalette>,
|
||||
@ -229,11 +233,14 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||
|
||||
let mut intercept_result = cx
|
||||
.try_read_global(|interceptor: &CommandPaletteInterceptor, cx| {
|
||||
(interceptor)(&query, cx)
|
||||
(interceptor.0)(&query, cx)
|
||||
})
|
||||
.flatten();
|
||||
|
||||
if *RELEASE_CHANNEL == ReleaseChannel::Dev {
|
||||
let release_channel = cx
|
||||
.update(|cx| ReleaseChannel::try_global(cx))
|
||||
.ok()
|
||||
.flatten();
|
||||
if release_channel == Some(ReleaseChannel::Dev) {
|
||||
if parse_zed_link(&query).is_some() {
|
||||
intercept_result = Some(CommandInterceptResult {
|
||||
action: OpenZedUrl { url: query.clone() }.boxed_clone(),
|
||||
|
@ -5,7 +5,7 @@ use async_tar::Archive;
|
||||
use collections::{HashMap, HashSet};
|
||||
use futures::{channel::oneshot, future::Shared, Future, FutureExt, TryFutureExt};
|
||||
use gpui::{
|
||||
actions, AppContext, AsyncAppContext, Context, Entity, EntityId, EventEmitter, Model,
|
||||
actions, AppContext, AsyncAppContext, Context, Entity, EntityId, EventEmitter, Global, Model,
|
||||
ModelContext, Task, WeakModel,
|
||||
};
|
||||
use language::{
|
||||
@ -32,6 +32,17 @@ use util::{
|
||||
ResultExt,
|
||||
};
|
||||
|
||||
// HACK: This type is only defined in `copilot` since it is the earliest ancestor
|
||||
// of the crates that use it.
|
||||
//
|
||||
// This is not great. Let's find a better place for it to live.
|
||||
#[derive(Default)]
|
||||
pub struct CommandPaletteFilter {
|
||||
pub hidden_namespaces: HashSet<&'static str>,
|
||||
pub hidden_action_types: HashSet<TypeId>,
|
||||
}
|
||||
|
||||
impl Global for CommandPaletteFilter {}
|
||||
actions!(
|
||||
copilot,
|
||||
[
|
||||
@ -54,7 +65,7 @@ pub fn init(
|
||||
let node_runtime = node_runtime.clone();
|
||||
move |cx| Copilot::start(new_server_id, http, node_runtime, cx)
|
||||
});
|
||||
cx.set_global(copilot.clone());
|
||||
Copilot::set_global(copilot.clone(), cx);
|
||||
cx.observe(&copilot, |handle, cx| {
|
||||
let copilot_action_types = [
|
||||
TypeId::of::<Suggest>(),
|
||||
@ -65,7 +76,7 @@ pub fn init(
|
||||
let copilot_auth_action_types = [TypeId::of::<SignOut>()];
|
||||
let copilot_no_auth_action_types = [TypeId::of::<SignIn>()];
|
||||
let status = handle.read(cx).status();
|
||||
let filter = cx.default_global::<collections::CommandPaletteFilter>();
|
||||
let filter = cx.default_global::<CommandPaletteFilter>();
|
||||
|
||||
match status {
|
||||
Status::Disabled => {
|
||||
@ -307,9 +318,18 @@ pub enum Event {
|
||||
|
||||
impl EventEmitter<Event> for Copilot {}
|
||||
|
||||
struct GlobalCopilot(Model<Copilot>);
|
||||
|
||||
impl Global for GlobalCopilot {}
|
||||
|
||||
impl Copilot {
|
||||
pub fn global(cx: &AppContext) -> Option<Model<Self>> {
|
||||
cx.try_global::<Model<Self>>().map(|model| model.clone())
|
||||
cx.try_global::<GlobalCopilot>()
|
||||
.map(|model| model.0.clone())
|
||||
}
|
||||
|
||||
pub fn set_global(copilot: Model<Self>, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalCopilot(copilot));
|
||||
}
|
||||
|
||||
fn start(
|
||||
|
@ -15,6 +15,7 @@ test-support = []
|
||||
[dependencies]
|
||||
collections = { path = "../collections" }
|
||||
gpui = { path = "../gpui" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
sqlez = { path = "../sqlez" }
|
||||
sqlez_macros = { path = "../sqlez_macros" }
|
||||
util = { path = "../util" }
|
||||
|
@ -10,16 +10,16 @@ pub use lazy_static;
|
||||
pub use smol;
|
||||
pub use sqlez;
|
||||
pub use sqlez_macros;
|
||||
pub use util::channel::{RELEASE_CHANNEL, RELEASE_CHANNEL_NAME};
|
||||
pub use util::paths::DB_DIR;
|
||||
|
||||
use release_channel::ReleaseChannel;
|
||||
pub use release_channel::RELEASE_CHANNEL;
|
||||
use sqlez::domain::Migrator;
|
||||
use sqlez::thread_safe_connection::ThreadSafeConnection;
|
||||
use sqlez_macros::sql;
|
||||
use std::future::Future;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use util::channel::ReleaseChannel;
|
||||
use util::{async_maybe, ResultExt};
|
||||
|
||||
const CONNECTION_INITIALIZE_QUERY: &'static str = sql!(
|
||||
@ -223,7 +223,7 @@ mod tests {
|
||||
.prefix("DbTests")
|
||||
.tempdir()
|
||||
.unwrap();
|
||||
let _bad_db = open_db::<BadDB>(tempdir.path(), &util::channel::ReleaseChannel::Dev).await;
|
||||
let _bad_db = open_db::<BadDB>(tempdir.path(), &release_channel::ReleaseChannel::Dev).await;
|
||||
}
|
||||
|
||||
/// Test that DB exists but corrupted (causing recreate)
|
||||
@ -261,11 +261,12 @@ mod tests {
|
||||
.unwrap();
|
||||
{
|
||||
let corrupt_db =
|
||||
open_db::<CorruptedDB>(tempdir.path(), &util::channel::ReleaseChannel::Dev).await;
|
||||
open_db::<CorruptedDB>(tempdir.path(), &release_channel::ReleaseChannel::Dev).await;
|
||||
assert!(corrupt_db.persistent());
|
||||
}
|
||||
|
||||
let good_db = open_db::<GoodDB>(tempdir.path(), &util::channel::ReleaseChannel::Dev).await;
|
||||
let good_db =
|
||||
open_db::<GoodDB>(tempdir.path(), &release_channel::ReleaseChannel::Dev).await;
|
||||
assert!(
|
||||
good_db.select_row::<usize>("SELECT * FROM test2").unwrap()()
|
||||
.unwrap()
|
||||
@ -309,7 +310,7 @@ mod tests {
|
||||
{
|
||||
// Setup the bad database
|
||||
let corrupt_db =
|
||||
open_db::<CorruptedDB>(tempdir.path(), &util::channel::ReleaseChannel::Dev).await;
|
||||
open_db::<CorruptedDB>(tempdir.path(), &release_channel::ReleaseChannel::Dev).await;
|
||||
assert!(corrupt_db.persistent());
|
||||
}
|
||||
|
||||
@ -320,7 +321,7 @@ mod tests {
|
||||
let guard = thread::spawn(move || {
|
||||
let good_db = smol::block_on(open_db::<GoodDB>(
|
||||
tmp_path.as_path(),
|
||||
&util::channel::ReleaseChannel::Dev,
|
||||
&release_channel::ReleaseChannel::Dev,
|
||||
));
|
||||
assert!(
|
||||
good_db.select_row::<usize>("SELECT * FROM test2").unwrap()()
|
||||
|
@ -104,7 +104,6 @@ use std::{
|
||||
ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
sync::Weak,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
pub use sum_tree::Bias;
|
||||
@ -241,7 +240,7 @@ pub fn init(cx: &mut AppContext) {
|
||||
.detach();
|
||||
|
||||
cx.on_action(move |_: &workspace::NewFile, cx| {
|
||||
let app_state = cx.global::<Weak<workspace::AppState>>();
|
||||
let app_state = workspace::AppState::global(cx);
|
||||
if let Some(app_state) = app_state.upgrade() {
|
||||
workspace::open_new(&app_state, cx, |workspace, cx| {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
@ -250,7 +249,7 @@ pub fn init(cx: &mut AppContext) {
|
||||
}
|
||||
});
|
||||
cx.on_action(move |_: &workspace::NewWindow, cx| {
|
||||
let app_state = cx.global::<Weak<workspace::AppState>>();
|
||||
let app_state = workspace::AppState::global(cx);
|
||||
if let Some(app_state) = app_state.upgrade() {
|
||||
workspace::open_new(&app_state, cx, |workspace, cx| {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
|
@ -7226,7 +7226,7 @@ async fn test_copilot(executor: BackgroundExecutor, cx: &mut gpui::TestAppContex
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||
_ = cx.update(|cx| cx.set_global(copilot));
|
||||
_ = cx.update(|cx| Copilot::set_global(copilot, cx));
|
||||
let mut cx = EditorLspTestContext::new_rust(
|
||||
lsp::ServerCapabilities {
|
||||
completion_provider: Some(lsp::CompletionOptions {
|
||||
@ -7479,7 +7479,7 @@ async fn test_copilot_completion_invalidation(
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||
_ = cx.update(|cx| cx.set_global(copilot));
|
||||
_ = cx.update(|cx| Copilot::set_global(copilot, cx));
|
||||
let mut cx = EditorLspTestContext::new_rust(
|
||||
lsp::ServerCapabilities {
|
||||
completion_provider: Some(lsp::CompletionOptions {
|
||||
@ -7543,7 +7543,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||
_ = cx.update(|cx| cx.set_global(copilot));
|
||||
_ = cx.update(|cx| Copilot::set_global(copilot, cx));
|
||||
|
||||
let buffer_1 = cx.new_model(|cx| {
|
||||
Buffer::new(
|
||||
@ -7660,7 +7660,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui
|
||||
});
|
||||
|
||||
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||
_ = cx.update(|cx| cx.set_global(copilot));
|
||||
_ = cx.update(|cx| Copilot::set_global(copilot, cx));
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
MultiBufferSnapshot, ToPoint,
|
||||
};
|
||||
pub use autoscroll::{Autoscroll, AutoscrollStrategy};
|
||||
use gpui::{point, px, AppContext, Entity, Pixels, Task, ViewContext};
|
||||
use gpui::{point, px, AppContext, Entity, Global, Pixels, Task, ViewContext};
|
||||
use language::{Bias, Point};
|
||||
pub use scroll_amount::ScrollAmount;
|
||||
use std::{
|
||||
@ -27,6 +27,8 @@ const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
|
||||
#[derive(Default)]
|
||||
pub struct ScrollbarAutoHide(pub bool);
|
||||
|
||||
impl Global for ScrollbarAutoHide {}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct ScrollAnchor {
|
||||
pub offset: gpui::Point<f32>,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use gpui::{AppContext, Subscription, ViewContext};
|
||||
use gpui::{AppContext, Global, Subscription, ViewContext};
|
||||
|
||||
#[derive(Default)]
|
||||
struct FeatureFlags {
|
||||
@ -12,6 +12,8 @@ impl FeatureFlags {
|
||||
}
|
||||
}
|
||||
|
||||
impl Global for FeatureFlags {}
|
||||
|
||||
pub trait FeatureFlag {
|
||||
const NAME: &'static str;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ gpui = { path = "../gpui" }
|
||||
language = { path = "../language" }
|
||||
menu = { path = "../menu" }
|
||||
project = { path = "../project" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
settings = { path = "../settings" }
|
||||
theme = { path = "../theme" }
|
||||
ui = { path = "../ui" }
|
||||
|
@ -225,7 +225,7 @@ impl FeedbackModal {
|
||||
None,
|
||||
&["Yes, Submit!", "No"],
|
||||
);
|
||||
let client = cx.global::<Arc<Client>>().clone();
|
||||
let client = Client::global(cx).clone();
|
||||
let specs = self.system_specs.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let answer = answer.await.ok();
|
||||
|
@ -1,10 +1,10 @@
|
||||
use client::ZED_APP_VERSION;
|
||||
use gpui::AppContext;
|
||||
use human_bytes::human_bytes;
|
||||
use release_channel::ReleaseChannel;
|
||||
use serde::Serialize;
|
||||
use std::{env, fmt::Display};
|
||||
use sysinfo::{RefreshKind, System, SystemExt};
|
||||
use util::channel::ReleaseChannel;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct SystemSpecs {
|
||||
@ -21,7 +21,7 @@ impl SystemSpecs {
|
||||
let app_version = ZED_APP_VERSION
|
||||
.or_else(|| cx.app_metadata().app_version)
|
||||
.map(|v| v.to_string());
|
||||
let release_channel = cx.global::<ReleaseChannel>().display_name();
|
||||
let release_channel = ReleaseChannel::global(cx).display_name();
|
||||
let os_name = cx.app_metadata().os_name;
|
||||
let system = System::new_with_specifics(RefreshKind::new().with_memory());
|
||||
let memory = system.total_memory();
|
||||
|
@ -17,7 +17,7 @@ use time::UtcOffset;
|
||||
use crate::{
|
||||
current_platform, image_cache::ImageCache, init_app_menus, Action, ActionRegistry, Any,
|
||||
AnyView, AnyWindowHandle, AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context,
|
||||
DispatchPhase, DisplayId, Entity, EventEmitter, ForegroundExecutor, KeyBinding, Keymap,
|
||||
DispatchPhase, DisplayId, Entity, EventEmitter, ForegroundExecutor, Global, KeyBinding, Keymap,
|
||||
Keystroke, LayoutId, Menu, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render,
|
||||
SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement,
|
||||
TextSystem, View, ViewContext, Window, WindowContext, WindowHandle, WindowId,
|
||||
@ -823,13 +823,13 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Check whether a global of the given type has been assigned.
|
||||
pub fn has_global<G: 'static>(&self) -> bool {
|
||||
pub fn has_global<G: Global>(&self) -> bool {
|
||||
self.globals_by_type.contains_key(&TypeId::of::<G>())
|
||||
}
|
||||
|
||||
/// Access the global of the given type. Panics if a global for that type has not been assigned.
|
||||
#[track_caller]
|
||||
pub fn global<G: 'static>(&self) -> &G {
|
||||
pub fn global<G: Global>(&self) -> &G {
|
||||
self.globals_by_type
|
||||
.get(&TypeId::of::<G>())
|
||||
.map(|any_state| any_state.downcast_ref::<G>().unwrap())
|
||||
@ -838,7 +838,7 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Access the global of the given type if a value has been assigned.
|
||||
pub fn try_global<G: 'static>(&self) -> Option<&G> {
|
||||
pub fn try_global<G: Global>(&self) -> Option<&G> {
|
||||
self.globals_by_type
|
||||
.get(&TypeId::of::<G>())
|
||||
.map(|any_state| any_state.downcast_ref::<G>().unwrap())
|
||||
@ -846,7 +846,7 @@ impl AppContext {
|
||||
|
||||
/// Access the global of the given type mutably. Panics if a global for that type has not been assigned.
|
||||
#[track_caller]
|
||||
pub fn global_mut<G: 'static>(&mut self) -> &mut G {
|
||||
pub fn global_mut<G: Global>(&mut self) -> &mut G {
|
||||
let global_type = TypeId::of::<G>();
|
||||
self.push_effect(Effect::NotifyGlobalObservers { global_type });
|
||||
self.globals_by_type
|
||||
@ -858,7 +858,7 @@ impl AppContext {
|
||||
|
||||
/// Access the global of the given type mutably. A default value is assigned if a global of this type has not
|
||||
/// yet been assigned.
|
||||
pub fn default_global<G: 'static + Default>(&mut self) -> &mut G {
|
||||
pub fn default_global<G: Global + Default>(&mut self) -> &mut G {
|
||||
let global_type = TypeId::of::<G>();
|
||||
self.push_effect(Effect::NotifyGlobalObservers { global_type });
|
||||
self.globals_by_type
|
||||
@ -869,7 +869,7 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Sets the value of the global of the given type.
|
||||
pub fn set_global<G: Any>(&mut self, global: G) {
|
||||
pub fn set_global<G: Global>(&mut self, global: G) {
|
||||
let global_type = TypeId::of::<G>();
|
||||
self.push_effect(Effect::NotifyGlobalObservers { global_type });
|
||||
self.globals_by_type.insert(global_type, Box::new(global));
|
||||
@ -882,7 +882,7 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Remove the global of the given type from the app context. Does not notify global observers.
|
||||
pub fn remove_global<G: Any>(&mut self) -> G {
|
||||
pub fn remove_global<G: Global>(&mut self) -> G {
|
||||
let global_type = TypeId::of::<G>();
|
||||
self.push_effect(Effect::NotifyGlobalObservers { global_type });
|
||||
*self
|
||||
@ -895,7 +895,7 @@ impl AppContext {
|
||||
|
||||
/// Updates the global of the given type with a closure. Unlike `global_mut`, this method provides
|
||||
/// your closure with mutable access to the `AppContext` and the global simultaneously.
|
||||
pub fn update_global<G: 'static, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
|
||||
pub fn update_global<G: Global, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
|
||||
self.update(|cx| {
|
||||
let mut global = cx.lease_global::<G>();
|
||||
let result = f(&mut global, cx);
|
||||
@ -905,7 +905,7 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Register a callback to be invoked when a global of the given type is updated.
|
||||
pub fn observe_global<G: 'static>(
|
||||
pub fn observe_global<G: Global>(
|
||||
&mut self,
|
||||
mut f: impl FnMut(&mut Self) + 'static,
|
||||
) -> Subscription {
|
||||
@ -921,7 +921,7 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Move the global of the given type to the stack.
|
||||
pub(crate) fn lease_global<G: 'static>(&mut self) -> GlobalLease<G> {
|
||||
pub(crate) fn lease_global<G: Global>(&mut self) -> GlobalLease<G> {
|
||||
GlobalLease::new(
|
||||
self.globals_by_type
|
||||
.remove(&TypeId::of::<G>())
|
||||
@ -931,7 +931,7 @@ impl AppContext {
|
||||
}
|
||||
|
||||
/// Restore the global of the given type after it is moved to the stack.
|
||||
pub(crate) fn end_global_lease<G: 'static>(&mut self, lease: GlobalLease<G>) {
|
||||
pub(crate) fn end_global_lease<G: Global>(&mut self, lease: GlobalLease<G>) {
|
||||
let global_type = TypeId::of::<G>();
|
||||
self.push_effect(Effect::NotifyGlobalObservers { global_type });
|
||||
self.globals_by_type.insert(global_type, lease.global);
|
||||
@ -1293,12 +1293,12 @@ pub(crate) enum Effect {
|
||||
}
|
||||
|
||||
/// Wraps a global variable value during `update_global` while the value has been moved to the stack.
|
||||
pub(crate) struct GlobalLease<G: 'static> {
|
||||
pub(crate) struct GlobalLease<G: Global> {
|
||||
global: Box<dyn Any>,
|
||||
global_type: PhantomData<G>,
|
||||
}
|
||||
|
||||
impl<G: 'static> GlobalLease<G> {
|
||||
impl<G: Global> GlobalLease<G> {
|
||||
fn new(global: Box<dyn Any>) -> Self {
|
||||
GlobalLease {
|
||||
global,
|
||||
@ -1307,7 +1307,7 @@ impl<G: 'static> GlobalLease<G> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: 'static> Deref for GlobalLease<G> {
|
||||
impl<G: Global> Deref for GlobalLease<G> {
|
||||
type Target = G;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -1315,7 +1315,7 @@ impl<G: 'static> Deref for GlobalLease<G> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: 'static> DerefMut for GlobalLease<G> {
|
||||
impl<G: Global> DerefMut for GlobalLease<G> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.global.downcast_mut().unwrap()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, DismissEvent,
|
||||
FocusableView, ForegroundExecutor, Model, ModelContext, Render, Result, Task, View,
|
||||
FocusableView, ForegroundExecutor, Global, Model, ModelContext, Render, Result, Task, View,
|
||||
ViewContext, VisualContext, WindowContext, WindowHandle,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _};
|
||||
@ -144,7 +144,7 @@ impl AsyncAppContext {
|
||||
|
||||
/// Determine whether global state of the specified type has been assigned.
|
||||
/// Returns an error if the `AppContext` has been dropped.
|
||||
pub fn has_global<G: 'static>(&self) -> Result<bool> {
|
||||
pub fn has_global<G: Global>(&self) -> Result<bool> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
@ -157,7 +157,7 @@ impl AsyncAppContext {
|
||||
///
|
||||
/// Panics if no global state of the specified type has been assigned.
|
||||
/// Returns an error if the `AppContext` has been dropped.
|
||||
pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
|
||||
pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
@ -172,7 +172,7 @@ impl AsyncAppContext {
|
||||
/// if no state of the specified type has been assigned.
|
||||
///
|
||||
/// Returns an error if no state of the specified type has been assigned the `AppContext` has been dropped.
|
||||
pub fn try_read_global<G: 'static, R>(
|
||||
pub fn try_read_global<G: Global, R>(
|
||||
&self,
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Option<R> {
|
||||
@ -183,7 +183,7 @@ impl AsyncAppContext {
|
||||
|
||||
/// A convenience method for [AppContext::update_global]
|
||||
/// for updating the global state of the specified type.
|
||||
pub fn update_global<G: 'static, R>(
|
||||
pub fn update_global<G: Global, R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(&mut G, &mut AppContext) -> R,
|
||||
) -> Result<R> {
|
||||
@ -235,7 +235,7 @@ impl AsyncWindowContext {
|
||||
}
|
||||
|
||||
/// A convenience method for [`AppContext::global`].
|
||||
pub fn read_global<G: 'static, R>(
|
||||
pub fn read_global<G: Global, R>(
|
||||
&mut self,
|
||||
read: impl FnOnce(&G, &WindowContext) -> R,
|
||||
) -> Result<R> {
|
||||
@ -249,7 +249,7 @@ impl AsyncWindowContext {
|
||||
update: impl FnOnce(&mut G, &mut WindowContext) -> R,
|
||||
) -> Result<R>
|
||||
where
|
||||
G: 'static,
|
||||
G: Global,
|
||||
{
|
||||
self.window.update(self, |_, cx| cx.update_global(update))
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
AnyView, AnyWindowHandle, AppContext, AsyncAppContext, Context, Effect, Entity, EntityId,
|
||||
EventEmitter, Model, Subscription, Task, View, WeakModel, WindowContext, WindowHandle,
|
||||
EventEmitter, Global, Model, Subscription, Task, View, WeakModel, WindowContext, WindowHandle,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
@ -193,7 +193,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
||||
/// Updates the given global
|
||||
pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
|
||||
where
|
||||
G: 'static,
|
||||
G: Global,
|
||||
{
|
||||
let mut global = self.app.lease_global::<G>();
|
||||
let result = f(&mut global, self);
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
Action, AnyElement, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
|
||||
AvailableSpace, BackgroundExecutor, Bounds, ClipboardItem, Context, Entity, EventEmitter,
|
||||
ForegroundExecutor, InputEvent, Keystroke, Model, ModelContext, Pixels, Platform, Point,
|
||||
Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow, TextSystem, View,
|
||||
ForegroundExecutor, Global, InputEvent, Keystroke, Model, ModelContext, Pixels, Platform,
|
||||
Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow, TextSystem, View,
|
||||
ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use anyhow::{anyhow, bail};
|
||||
@ -256,20 +256,20 @@ impl TestAppContext {
|
||||
}
|
||||
|
||||
/// true if the given global is defined
|
||||
pub fn has_global<G: 'static>(&self) -> bool {
|
||||
pub fn has_global<G: Global>(&self) -> bool {
|
||||
let app = self.app.borrow();
|
||||
app.has_global::<G>()
|
||||
}
|
||||
|
||||
/// runs the given closure with a reference to the global
|
||||
/// panics if `has_global` would return false.
|
||||
pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> R {
|
||||
pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> R {
|
||||
let app = self.app.borrow();
|
||||
read(app.global(), &app)
|
||||
}
|
||||
|
||||
/// runs the given closure with a reference to the global (if set)
|
||||
pub fn try_read_global<G: 'static, R>(
|
||||
pub fn try_read_global<G: Global, R>(
|
||||
&self,
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Option<R> {
|
||||
@ -278,13 +278,13 @@ impl TestAppContext {
|
||||
}
|
||||
|
||||
/// sets the global in this context.
|
||||
pub fn set_global<G: 'static>(&mut self, global: G) {
|
||||
pub fn set_global<G: Global>(&mut self, global: G) {
|
||||
let mut lock = self.app.borrow_mut();
|
||||
lock.set_global(global);
|
||||
}
|
||||
|
||||
/// updates the global in this context. (panics if `has_global` would return false)
|
||||
pub fn update_global<G: 'static, R>(
|
||||
pub fn update_global<G: Global, R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(&mut G, &mut AppContext) -> R,
|
||||
) -> R {
|
||||
|
@ -17,11 +17,11 @@
|
||||
|
||||
use crate::{
|
||||
point, px, size, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Bounds,
|
||||
ClickEvent, DispatchPhase, Element, ElementContext, ElementId, FocusHandle, IntoElement,
|
||||
IsZero, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent,
|
||||
MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent,
|
||||
SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility,
|
||||
WindowContext,
|
||||
ClickEvent, DispatchPhase, Element, ElementContext, ElementId, FocusHandle, Global,
|
||||
IntoElement, IsZero, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton,
|
||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render,
|
||||
ScrollWheelEvent, SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task,
|
||||
View, Visibility, WindowContext,
|
||||
};
|
||||
|
||||
use collections::HashMap;
|
||||
@ -2070,6 +2070,8 @@ impl ElementClickedState {
|
||||
#[derive(Default)]
|
||||
pub(crate) struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
|
||||
|
||||
impl Global for GroupBounds {}
|
||||
|
||||
impl GroupBounds {
|
||||
pub fn get(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
|
||||
cx.default_global::<Self>()
|
||||
|
@ -258,14 +258,14 @@ pub trait EventEmitter<E: Any>: 'static {}
|
||||
/// can be used interchangeably.
|
||||
pub trait BorrowAppContext {
|
||||
/// Set a global value on the context.
|
||||
fn set_global<T: 'static>(&mut self, global: T);
|
||||
fn set_global<T: Global>(&mut self, global: T);
|
||||
}
|
||||
|
||||
impl<C> BorrowAppContext for C
|
||||
where
|
||||
C: BorrowMut<AppContext>,
|
||||
{
|
||||
fn set_global<G: 'static>(&mut self, global: G) {
|
||||
fn set_global<G: Global>(&mut self, global: G) {
|
||||
self.borrow_mut().set_global(global)
|
||||
}
|
||||
}
|
||||
@ -287,3 +287,8 @@ impl<T> Flatten<T> for Result<T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A marker trait for types that can be stored in GPUI's global state.
|
||||
///
|
||||
/// Implement this on types you want to store in the context as a global.
|
||||
pub trait Global: 'static {}
|
||||
|
@ -3,8 +3,8 @@ use std::{iter, mem, ops::Range};
|
||||
use crate::{
|
||||
black, phi, point, quad, rems, AbsoluteLength, Bounds, ContentMask, Corners, CornersRefinement,
|
||||
CursorStyle, DefiniteLength, Edges, EdgesRefinement, ElementContext, Font, FontFeatures,
|
||||
FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba, SharedString, Size,
|
||||
SizeRefinement, Styled, TextRun,
|
||||
FontStyle, FontWeight, Global, Hsla, Length, Pixels, Point, PointRefinement, Rgba,
|
||||
SharedString, Size, SizeRefinement, Styled, TextRun,
|
||||
};
|
||||
use collections::HashSet;
|
||||
use refineable::Refineable;
|
||||
@ -20,6 +20,8 @@ pub use taffy::style::{
|
||||
/// GPUI.
|
||||
pub struct DebugBelow;
|
||||
|
||||
impl Global for DebugBelow {}
|
||||
|
||||
/// The CSS styling that can be applied to an element via the `Styled` trait
|
||||
#[derive(Clone, Refineable, Debug)]
|
||||
#[refineable(Debug)]
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
px, size, transparent_black, Action, AnyDrag, AnyView, AppContext, Arena, AsyncWindowContext,
|
||||
AvailableSpace, Bounds, Context, Corners, CursorStyle, DispatchActionListener, DispatchNodeId,
|
||||
DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten,
|
||||
GlobalElementId, Hsla, KeyBinding, KeyContext, KeyDownEvent, KeyMatch, KeymatchMode,
|
||||
Global, GlobalElementId, Hsla, KeyBinding, KeyContext, KeyDownEvent, KeyMatch, KeymatchMode,
|
||||
KeymatchResult, Keystroke, KeystrokeEvent, Model, ModelContext, Modifiers, MouseButton,
|
||||
MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
||||
PlatformWindow, Point, PromptLevel, Render, ScaledPixels, SharedString, Size, SubscriberSet,
|
||||
@ -708,7 +708,7 @@ impl<'a> WindowContext<'a> {
|
||||
/// access both to the global and the context.
|
||||
pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
|
||||
where
|
||||
G: 'static,
|
||||
G: Global,
|
||||
{
|
||||
let mut global = self.app.lease_global::<G>();
|
||||
let result = f(&mut global, self);
|
||||
@ -1441,7 +1441,7 @@ impl<'a> WindowContext<'a> {
|
||||
|
||||
/// Register the given handler to be invoked whenever the global of the given type
|
||||
/// is updated.
|
||||
pub fn observe_global<G: 'static>(
|
||||
pub fn observe_global<G: Global>(
|
||||
&mut self,
|
||||
f: impl Fn(&mut WindowContext<'_>) + 'static,
|
||||
) -> Subscription {
|
||||
@ -2198,7 +2198,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
/// Updates the global state of the given type.
|
||||
pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
|
||||
where
|
||||
G: 'static,
|
||||
G: Global,
|
||||
{
|
||||
let mut global = self.app.lease_global::<G>();
|
||||
let result = f(&mut global, self);
|
||||
@ -2207,7 +2207,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
}
|
||||
|
||||
/// Register a callback to be invoked when the given global state changes.
|
||||
pub fn observe_global<G: 'static>(
|
||||
pub fn observe_global<G: Global>(
|
||||
&mut self,
|
||||
mut f: impl FnMut(&mut V, &mut ViewContext<'_, V>) + 'static,
|
||||
) -> Subscription {
|
||||
|
@ -3,7 +3,9 @@ use channel::{ChannelMessage, ChannelMessageId, ChannelStore};
|
||||
use client::{Client, UserStore};
|
||||
use collections::HashMap;
|
||||
use db::smol::stream::StreamExt;
|
||||
use gpui::{AppContext, AsyncAppContext, Context as _, EventEmitter, Model, ModelContext, Task};
|
||||
use gpui::{
|
||||
AppContext, AsyncAppContext, Context as _, EventEmitter, Global, Model, ModelContext, Task,
|
||||
};
|
||||
use rpc::{proto, Notification, TypedEnvelope};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
use sum_tree::{Bias, SumTree};
|
||||
@ -12,9 +14,13 @@ use util::ResultExt;
|
||||
|
||||
pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
|
||||
let notification_store = cx.new_model(|cx| NotificationStore::new(client, user_store, cx));
|
||||
cx.set_global(notification_store);
|
||||
cx.set_global(GlobalNotificationStore(notification_store));
|
||||
}
|
||||
|
||||
struct GlobalNotificationStore(Model<NotificationStore>);
|
||||
|
||||
impl Global for GlobalNotificationStore {}
|
||||
|
||||
pub struct NotificationStore {
|
||||
client: Arc<Client>,
|
||||
user_store: Model<UserStore>,
|
||||
@ -70,7 +76,7 @@ struct NotificationId(u64);
|
||||
|
||||
impl NotificationStore {
|
||||
pub fn global(cx: &AppContext) -> Model<Self> {
|
||||
cx.global::<Model<Self>>().clone()
|
||||
cx.global::<GlobalNotificationStore>().0.clone()
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
|
@ -2,7 +2,7 @@ use std::{path::Path, str, sync::Arc};
|
||||
|
||||
use collections::HashMap;
|
||||
|
||||
use gpui::{AppContext, AssetSource};
|
||||
use gpui::{AppContext, AssetSource, Global};
|
||||
use serde_derive::Deserialize;
|
||||
use util::{maybe, paths::PathExt};
|
||||
|
||||
@ -17,6 +17,8 @@ pub struct FileAssociations {
|
||||
types: HashMap<String, TypeConfig>,
|
||||
}
|
||||
|
||||
impl Global for FileAssociations {}
|
||||
|
||||
const COLLAPSED_DIRECTORY_TYPE: &'static str = "collapsed_folder";
|
||||
const EXPANDED_DIRECTORY_TYPE: &'static str = "expanded_folder";
|
||||
const COLLAPSED_CHEVRON_TYPE: &'static str = "collapsed_chevron";
|
||||
|
10
crates/release_channel/Cargo.toml
Normal file
10
crates/release_channel/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "release_channel"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[dependencies]
|
||||
gpui = { path = "../gpui" }
|
||||
once_cell = "1.19.0"
|
1
crates/release_channel/LICENSE-GPL
Symbolic link
1
crates/release_channel/LICENSE-GPL
Symbolic link
@ -0,0 +1 @@
|
||||
../../LICENSE-GPL
|
@ -1,24 +1,44 @@
|
||||
use lazy_static::lazy_static;
|
||||
use gpui::{AppContext, Global};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::env;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref RELEASE_CHANNEL_NAME: String = if cfg!(debug_assertions) {
|
||||
#[doc(hidden)]
|
||||
pub static RELEASE_CHANNEL_NAME: Lazy<String> = if cfg!(debug_assertions) {
|
||||
Lazy::new(|| {
|
||||
env::var("ZED_RELEASE_CHANNEL")
|
||||
.unwrap_or_else(|_| include_str!("../../zed/RELEASE_CHANNEL").to_string())
|
||||
} else {
|
||||
include_str!("../../zed/RELEASE_CHANNEL").to_string()
|
||||
};
|
||||
pub static ref RELEASE_CHANNEL: ReleaseChannel = match RELEASE_CHANNEL_NAME.as_str().trim() {
|
||||
})
|
||||
} else {
|
||||
Lazy::new(|| include_str!("../../zed/RELEASE_CHANNEL").to_string())
|
||||
};
|
||||
#[doc(hidden)]
|
||||
pub static RELEASE_CHANNEL: Lazy<ReleaseChannel> =
|
||||
Lazy::new(|| match RELEASE_CHANNEL_NAME.as_str().trim() {
|
||||
"dev" => ReleaseChannel::Dev,
|
||||
"nightly" => ReleaseChannel::Nightly,
|
||||
"preview" => ReleaseChannel::Preview,
|
||||
"stable" => ReleaseChannel::Stable,
|
||||
_ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppCommitSha(pub String);
|
||||
|
||||
struct GlobalAppCommitSha(AppCommitSha);
|
||||
|
||||
impl Global for GlobalAppCommitSha {}
|
||||
|
||||
impl AppCommitSha {
|
||||
pub fn try_global(cx: &AppContext) -> Option<AppCommitSha> {
|
||||
cx.try_global::<GlobalAppCommitSha>()
|
||||
.map(|sha| sha.0.clone())
|
||||
}
|
||||
|
||||
pub fn set_global(sha: AppCommitSha, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalAppCommitSha(sha))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
||||
pub enum ReleaseChannel {
|
||||
#[default]
|
||||
@ -28,7 +48,24 @@ pub enum ReleaseChannel {
|
||||
Stable,
|
||||
}
|
||||
|
||||
struct GlobalReleaseChannel(ReleaseChannel);
|
||||
|
||||
impl Global for GlobalReleaseChannel {}
|
||||
|
||||
impl ReleaseChannel {
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.set_global(GlobalReleaseChannel(*RELEASE_CHANNEL))
|
||||
}
|
||||
|
||||
pub fn global(cx: &AppContext) -> Self {
|
||||
cx.global::<GlobalReleaseChannel>().0
|
||||
}
|
||||
|
||||
pub fn try_global(cx: &AppContext) -> Option<Self> {
|
||||
cx.try_global::<GlobalReleaseChannel>()
|
||||
.map(|channel| channel.0)
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
ReleaseChannel::Dev => "Zed Dev",
|
@ -13,10 +13,10 @@ use editor::{
|
||||
use editor::{EditorElement, EditorStyle};
|
||||
use gpui::{
|
||||
actions, div, Action, AnyElement, AnyView, AppContext, Context as _, Element, EntityId,
|
||||
EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, Hsla, InteractiveElement,
|
||||
IntoElement, KeyContext, Model, ModelContext, ParentElement, PromptLevel, Render, SharedString,
|
||||
Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakModel, WeakView,
|
||||
WhiteSpace, WindowContext,
|
||||
EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, Global, Hsla,
|
||||
InteractiveElement, IntoElement, KeyContext, Model, ModelContext, ParentElement, PromptLevel,
|
||||
Render, SharedString, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext,
|
||||
WeakModel, WeakView, WhiteSpace, WindowContext,
|
||||
};
|
||||
use menu::Confirm;
|
||||
use project::{
|
||||
@ -58,6 +58,8 @@ actions!(
|
||||
#[derive(Default)]
|
||||
struct ActiveSettings(HashMap<WeakModel<Project>, ProjectSearchSettings>);
|
||||
|
||||
impl Global for ActiveSettings {}
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.set_global(ActiveSettings::default());
|
||||
cx.observe_new_views(|workspace: &mut Workspace, _cx| {
|
||||
|
@ -17,6 +17,7 @@ language = { path = "../language" }
|
||||
project = { path = "../project" }
|
||||
workspace = { path = "../workspace" }
|
||||
util = { path = "../util" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
rpc = { path = "../rpc" }
|
||||
settings = { path = "../settings" }
|
||||
anyhow.workspace = true
|
||||
|
@ -15,8 +15,8 @@ use db::VectorDatabase;
|
||||
use embedding_queue::{EmbeddingQueue, FileToEmbed};
|
||||
use futures::{future, FutureExt, StreamExt};
|
||||
use gpui::{
|
||||
AppContext, AsyncAppContext, BorrowWindow, Context, Model, ModelContext, Task, ViewContext,
|
||||
WeakModel,
|
||||
AppContext, AsyncAppContext, BorrowWindow, Context, Global, Model, ModelContext, Task,
|
||||
ViewContext, WeakModel,
|
||||
};
|
||||
use language::{Anchor, Bias, Buffer, Language, LanguageRegistry};
|
||||
use lazy_static::lazy_static;
|
||||
@ -25,6 +25,7 @@ use parking_lot::Mutex;
|
||||
use parsing::{CodeContextRetriever, Span, SpanDigest, PARSEABLE_ENTIRE_FILE_TYPES};
|
||||
use postage::watch;
|
||||
use project::{Fs, PathChange, Project, ProjectEntryId, Worktree, WorktreeId};
|
||||
use release_channel::ReleaseChannel;
|
||||
use settings::Settings;
|
||||
use smol::channel;
|
||||
use std::{
|
||||
@ -38,7 +39,7 @@ use std::{
|
||||
time::{Duration, Instant, SystemTime},
|
||||
};
|
||||
use util::paths::PathMatcher;
|
||||
use util::{channel::RELEASE_CHANNEL_NAME, http::HttpClient, paths::EMBEDDINGS_DIR, ResultExt};
|
||||
use util::{http::HttpClient, paths::EMBEDDINGS_DIR, ResultExt};
|
||||
use workspace::Workspace;
|
||||
|
||||
const SEMANTIC_INDEX_VERSION: usize = 11;
|
||||
@ -58,7 +59,7 @@ pub fn init(
|
||||
SemanticIndexSettings::register(cx);
|
||||
|
||||
let db_file_path = EMBEDDINGS_DIR
|
||||
.join(Path::new(RELEASE_CHANNEL_NAME.as_str()))
|
||||
.join(Path::new(ReleaseChannel::global(cx).dev_name()))
|
||||
.join("embeddings_db");
|
||||
|
||||
cx.observe_new_views(
|
||||
@ -101,7 +102,7 @@ pub fn init(
|
||||
)
|
||||
.await?;
|
||||
|
||||
cx.update(|cx| cx.set_global(semantic_index.clone()))?;
|
||||
cx.update(|cx| cx.set_global(GlobalSemanticIndex(semantic_index.clone())))?;
|
||||
|
||||
anyhow::Ok(())
|
||||
})
|
||||
@ -130,6 +131,10 @@ pub struct SemanticIndex {
|
||||
projects: HashMap<WeakModel<Project>, ProjectState>,
|
||||
}
|
||||
|
||||
struct GlobalSemanticIndex(Model<SemanticIndex>);
|
||||
|
||||
impl Global for GlobalSemanticIndex {}
|
||||
|
||||
struct ProjectState {
|
||||
worktrees: HashMap<WorktreeId, WorktreeState>,
|
||||
pending_file_count_rx: watch::Receiver<usize>,
|
||||
@ -274,8 +279,8 @@ pub struct SearchResult {
|
||||
|
||||
impl SemanticIndex {
|
||||
pub fn global(cx: &mut AppContext) -> Option<Model<SemanticIndex>> {
|
||||
cx.try_global::<Model<Self>>()
|
||||
.map(|semantic_index| semantic_index.clone())
|
||||
cx.try_global::<GlobalSemanticIndex>()
|
||||
.map(|semantic_index| semantic_index.0.clone())
|
||||
}
|
||||
|
||||
pub fn authenticate(&mut self, cx: &mut AppContext) -> Task<bool> {
|
||||
|
@ -17,6 +17,7 @@ collections = { path = "../collections" }
|
||||
gpui = { path = "../gpui" }
|
||||
fs = { path = "../fs" }
|
||||
feature_flags = { path = "../feature_flags" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
util = { path = "../util" }
|
||||
|
||||
anyhow.workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use collections::{btree_map, hash_map, BTreeMap, HashMap};
|
||||
use gpui::{AppContext, AsyncAppContext};
|
||||
use gpui::{AppContext, AsyncAppContext, Global};
|
||||
use lazy_static::lazy_static;
|
||||
use schemars::{gen::SchemaGenerator, schema::RootSchema, JsonSchema};
|
||||
use serde::{de::DeserializeOwned, Deserialize as _, Serialize};
|
||||
@ -13,9 +13,7 @@ use std::{
|
||||
str,
|
||||
sync::Arc,
|
||||
};
|
||||
use util::{
|
||||
channel::RELEASE_CHANNEL_NAME, merge_non_null_json_value_into, RangeExt, ResultExt as _,
|
||||
};
|
||||
use util::{merge_non_null_json_value_into, RangeExt, ResultExt as _};
|
||||
|
||||
/// A value that can be defined as a user setting.
|
||||
///
|
||||
@ -139,6 +137,8 @@ pub struct SettingsStore {
|
||||
)>,
|
||||
}
|
||||
|
||||
impl Global for SettingsStore {}
|
||||
|
||||
impl Default for SettingsStore {
|
||||
fn default() -> Self {
|
||||
SettingsStore {
|
||||
@ -207,7 +207,10 @@ impl SettingsStore {
|
||||
user_values_stack = vec![user_settings];
|
||||
}
|
||||
|
||||
if let Some(release_settings) = &self.raw_user_settings.get(&*RELEASE_CHANNEL_NAME) {
|
||||
if let Some(release_settings) = &self
|
||||
.raw_user_settings
|
||||
.get(&*release_channel::RELEASE_CHANNEL_NAME)
|
||||
{
|
||||
if let Some(release_settings) = setting_value
|
||||
.deserialize_setting(&release_settings)
|
||||
.log_err()
|
||||
@ -537,7 +540,10 @@ impl SettingsStore {
|
||||
paths_stack.push(None);
|
||||
}
|
||||
|
||||
if let Some(release_settings) = &self.raw_user_settings.get(&*RELEASE_CHANNEL_NAME) {
|
||||
if let Some(release_settings) = &self
|
||||
.raw_user_settings
|
||||
.get(&*release_channel::RELEASE_CHANNEL_NAME)
|
||||
{
|
||||
if let Some(release_settings) = setting_value
|
||||
.deserialize_setting(&release_settings)
|
||||
.log_err()
|
||||
|
@ -6,7 +6,7 @@ use anyhow::{anyhow, Context, Result};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use fs::Fs;
|
||||
use futures::StreamExt;
|
||||
use gpui::{AppContext, AssetSource, HighlightStyle, SharedString};
|
||||
use gpui::{AppContext, AssetSource, Global, HighlightStyle, SharedString};
|
||||
use parking_lot::RwLock;
|
||||
use refineable::Refineable;
|
||||
use util::ResultExt;
|
||||
@ -32,10 +32,7 @@ pub struct ThemeMeta {
|
||||
#[derive(Default, Deref, DerefMut)]
|
||||
struct GlobalThemeRegistry(Arc<ThemeRegistry>);
|
||||
|
||||
/// Initializes the theme registry.
|
||||
pub fn init(assets: Box<dyn AssetSource>, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalThemeRegistry(Arc::new(ThemeRegistry::new(assets))));
|
||||
}
|
||||
impl Global for GlobalThemeRegistry {}
|
||||
|
||||
struct ThemeRegistryState {
|
||||
themes: HashMap<SharedString, Arc<Theme>>,
|
||||
@ -59,6 +56,11 @@ impl ThemeRegistry {
|
||||
cx.default_global::<GlobalThemeRegistry>().0.clone()
|
||||
}
|
||||
|
||||
/// Sets the global [`ThemeRegistry`].
|
||||
pub(crate) fn set_global(assets: Box<dyn AssetSource>, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalThemeRegistry(Arc::new(ThemeRegistry::new(assets))));
|
||||
}
|
||||
|
||||
pub fn new(assets: Box<dyn AssetSource>) -> Self {
|
||||
let registry = Self {
|
||||
state: RwLock::new(ThemeRegistryState {
|
||||
|
@ -2,7 +2,8 @@ use crate::one_themes::one_dark;
|
||||
use crate::{SyntaxTheme, Theme, ThemeRegistry, ThemeStyleContent};
|
||||
use anyhow::Result;
|
||||
use gpui::{
|
||||
px, AppContext, Font, FontFeatures, FontStyle, FontWeight, Pixels, Subscription, ViewContext,
|
||||
px, AppContext, Font, FontFeatures, FontStyle, FontWeight, Global, Pixels, Subscription,
|
||||
ViewContext,
|
||||
};
|
||||
use refineable::Refineable;
|
||||
use schemars::{
|
||||
@ -34,6 +35,8 @@ pub struct ThemeSettings {
|
||||
#[derive(Default)]
|
||||
pub(crate) struct AdjustedBufferFontSize(Pixels);
|
||||
|
||||
impl Global for AdjustedBufferFontSize {}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct ThemeSettingsContent {
|
||||
#[serde(default)]
|
||||
|
@ -60,7 +60,7 @@ pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) {
|
||||
LoadThemes::JustBase => (Box::new(()) as Box<dyn AssetSource>, false),
|
||||
LoadThemes::All(assets) => (assets, true),
|
||||
};
|
||||
registry::init(assets, cx);
|
||||
ThemeRegistry::set_global(assets, cx);
|
||||
|
||||
if load_user_themes {
|
||||
ThemeRegistry::global(cx).load_bundled_themes();
|
||||
|
@ -36,24 +36,6 @@ pub fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Worksp
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn reload(cx: &mut AppContext) {
|
||||
let current_theme_name = cx.theme().name.clone();
|
||||
let current_theme = cx.update_global(|registry: &mut ThemeRegistry, _cx| {
|
||||
registry.clear();
|
||||
registry.get(¤t_theme_name)
|
||||
});
|
||||
match current_theme {
|
||||
Ok(theme) => {
|
||||
ThemeSelectorDelegate::set_theme(theme, cx);
|
||||
log::info!("reloaded theme {}", current_theme_name);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!("failed to load theme {}: {:?}", current_theme_name, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModalView for ThemeSelector {}
|
||||
|
||||
pub struct ThemeSelector {
|
||||
|
@ -1,5 +1,4 @@
|
||||
pub mod arc_cow;
|
||||
pub mod channel;
|
||||
pub mod fs;
|
||||
pub mod github;
|
||||
pub mod http;
|
||||
|
@ -28,6 +28,8 @@ regex.workspace = true
|
||||
|
||||
collections = { path = "../collections" }
|
||||
command_palette = { path = "../command_palette" }
|
||||
# HACK: We're only depending on `copilot` here for `CommandPaletteFilter`. See the attached comment on that type.
|
||||
copilot = { path = "../copilot" }
|
||||
editor = { path = "../editor" }
|
||||
gpui = { path = "../gpui" }
|
||||
language = { path = "../language" }
|
||||
|
@ -15,11 +15,12 @@ mod utils;
|
||||
mod visual;
|
||||
|
||||
use anyhow::Result;
|
||||
use collections::{CommandPaletteFilter, HashMap};
|
||||
use collections::HashMap;
|
||||
use command_palette::CommandPaletteInterceptor;
|
||||
use copilot::CommandPaletteFilter;
|
||||
use editor::{movement, Editor, EditorEvent, EditorMode};
|
||||
use gpui::{
|
||||
actions, impl_actions, Action, AppContext, EntityId, KeyContext, Subscription, View,
|
||||
actions, impl_actions, Action, AppContext, EntityId, Global, KeyContext, Subscription, View,
|
||||
ViewContext, WeakView, WindowContext,
|
||||
};
|
||||
use language::{CursorShape, Point, Selection, SelectionGoal};
|
||||
@ -171,9 +172,9 @@ pub fn observe_keystrokes(cx: &mut WindowContext) {
|
||||
.detach()
|
||||
}
|
||||
|
||||
/// The state pertaining to Vim mode. Stored as a global.
|
||||
/// The state pertaining to Vim mode.
|
||||
#[derive(Default)]
|
||||
pub struct Vim {
|
||||
struct Vim {
|
||||
active_editor: Option<WeakView<Editor>>,
|
||||
editor_subscription: Option<Subscription>,
|
||||
enabled: bool,
|
||||
@ -182,6 +183,8 @@ pub struct Vim {
|
||||
default_state: EditorState,
|
||||
}
|
||||
|
||||
impl Global for Vim {}
|
||||
|
||||
impl Vim {
|
||||
fn read(cx: &mut AppContext) -> &Self {
|
||||
cx.global::<Self>()
|
||||
@ -512,7 +515,9 @@ impl Vim {
|
||||
});
|
||||
|
||||
if self.enabled {
|
||||
cx.set_global::<CommandPaletteInterceptor>(Box::new(command::command_interceptor));
|
||||
cx.set_global::<CommandPaletteInterceptor>(CommandPaletteInterceptor(Box::new(
|
||||
command::command_interceptor,
|
||||
)));
|
||||
} else if cx.has_global::<CommandPaletteInterceptor>() {
|
||||
let _ = cx.remove_global::<CommandPaletteInterceptor>();
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ async-recursion = "1.0.0"
|
||||
itertools = "0.10"
|
||||
bincode = "1.2.1"
|
||||
anyhow.workspace = true
|
||||
derive_more.workspace = true
|
||||
futures.workspace = true
|
||||
lazy_static.workspace = true
|
||||
log.workspace = true
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{Toast, Workspace};
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
AnyView, AppContext, AsyncWindowContext, DismissEvent, Entity, EntityId, EventEmitter,
|
||||
AnyView, AppContext, AsyncWindowContext, DismissEvent, Entity, EntityId, EventEmitter, Global,
|
||||
PromptLevel, Render, Task, View, ViewContext, VisualContext, WindowContext,
|
||||
};
|
||||
use std::{any::TypeId, ops::DerefMut};
|
||||
@ -39,6 +39,8 @@ pub(crate) struct NotificationTracker {
|
||||
notifications_sent: HashMap<TypeId, Vec<usize>>,
|
||||
}
|
||||
|
||||
impl Global for NotificationTracker {}
|
||||
|
||||
impl std::ops::Deref for NotificationTracker {
|
||||
type Target = HashMap<TypeId, Vec<usize>>;
|
||||
|
||||
|
@ -18,6 +18,7 @@ use client::{
|
||||
Client, ErrorExt, Status, TypedEnvelope, UserStore,
|
||||
};
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle};
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
@ -28,7 +29,7 @@ use gpui::{
|
||||
actions, canvas, div, impl_actions, point, px, size, Action, AnyElement, AnyModel, AnyView,
|
||||
AnyWeakView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div,
|
||||
DragMoveEvent, Element, ElementContext, Entity, EntityId, EventEmitter, FocusHandle,
|
||||
FocusableView, GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId,
|
||||
FocusableView, Global, GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId,
|
||||
ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point, PromptLevel,
|
||||
Render, SharedString, Size, Styled, Subscription, Task, View, ViewContext, VisualContext,
|
||||
WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
@ -59,6 +60,7 @@ use std::{
|
||||
borrow::Cow,
|
||||
cmp, env,
|
||||
path::{Path, PathBuf},
|
||||
sync::Weak,
|
||||
sync::{atomic::AtomicUsize, Arc},
|
||||
time::Duration,
|
||||
};
|
||||
@ -256,8 +258,13 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
});
|
||||
}
|
||||
|
||||
type ProjectItemBuilders =
|
||||
HashMap<TypeId, fn(Model<Project>, AnyModel, &mut ViewContext<Pane>) -> Box<dyn ItemHandle>>;
|
||||
#[derive(Clone, Default, Deref, DerefMut)]
|
||||
struct ProjectItemBuilders(
|
||||
HashMap<TypeId, fn(Model<Project>, AnyModel, &mut ViewContext<Pane>) -> Box<dyn ItemHandle>>,
|
||||
);
|
||||
|
||||
impl Global for ProjectItemBuilders {}
|
||||
|
||||
pub fn register_project_item<I: ProjectItem>(cx: &mut AppContext) {
|
||||
let builders = cx.default_global::<ProjectItemBuilders>();
|
||||
builders.insert(TypeId::of::<I::Item>(), |project, model, cx| {
|
||||
@ -273,13 +280,20 @@ type FollowableItemBuilder = fn(
|
||||
&mut Option<proto::view::Variant>,
|
||||
&mut WindowContext,
|
||||
) -> Option<Task<Result<Box<dyn FollowableItemHandle>>>>;
|
||||
type FollowableItemBuilders = HashMap<
|
||||
TypeId,
|
||||
(
|
||||
FollowableItemBuilder,
|
||||
fn(&AnyView) -> Box<dyn FollowableItemHandle>,
|
||||
),
|
||||
>;
|
||||
|
||||
#[derive(Default, Deref, DerefMut)]
|
||||
struct FollowableItemBuilders(
|
||||
HashMap<
|
||||
TypeId,
|
||||
(
|
||||
FollowableItemBuilder,
|
||||
fn(&AnyView) -> Box<dyn FollowableItemHandle>,
|
||||
),
|
||||
>,
|
||||
);
|
||||
|
||||
impl Global for FollowableItemBuilders {}
|
||||
|
||||
pub fn register_followable_item<I: FollowableItem>(cx: &mut AppContext) {
|
||||
let builders = cx.default_global::<FollowableItemBuilders>();
|
||||
builders.insert(
|
||||
@ -296,16 +310,22 @@ pub fn register_followable_item<I: FollowableItem>(cx: &mut AppContext) {
|
||||
);
|
||||
}
|
||||
|
||||
type ItemDeserializers = HashMap<
|
||||
Arc<str>,
|
||||
fn(
|
||||
Model<Project>,
|
||||
WeakView<Workspace>,
|
||||
WorkspaceId,
|
||||
ItemId,
|
||||
&mut ViewContext<Pane>,
|
||||
) -> Task<Result<Box<dyn ItemHandle>>>,
|
||||
>;
|
||||
#[derive(Default, Deref, DerefMut)]
|
||||
struct ItemDeserializers(
|
||||
HashMap<
|
||||
Arc<str>,
|
||||
fn(
|
||||
Model<Project>,
|
||||
WeakView<Workspace>,
|
||||
WorkspaceId,
|
||||
ItemId,
|
||||
&mut ViewContext<Pane>,
|
||||
) -> Task<Result<Box<dyn ItemHandle>>>,
|
||||
>,
|
||||
);
|
||||
|
||||
impl Global for ItemDeserializers {}
|
||||
|
||||
pub fn register_deserializable_item<I: Item>(cx: &mut AppContext) {
|
||||
if let Some(serialized_item_kind) = I::serialized_item_kind() {
|
||||
let deserializers = cx.default_global::<ItemDeserializers>();
|
||||
@ -331,6 +351,10 @@ pub struct AppState {
|
||||
pub node_runtime: Arc<dyn NodeRuntime>,
|
||||
}
|
||||
|
||||
struct GlobalAppState(Weak<AppState>);
|
||||
|
||||
impl Global for GlobalAppState {}
|
||||
|
||||
pub struct WorkspaceStore {
|
||||
workspaces: HashSet<WindowHandle<Workspace>>,
|
||||
followers: Vec<Follower>,
|
||||
@ -345,6 +369,17 @@ struct Follower {
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn global(cx: &AppContext) -> Weak<Self> {
|
||||
cx.global::<GlobalAppState>().0.clone()
|
||||
}
|
||||
pub fn try_global(cx: &AppContext) -> Option<Weak<Self>> {
|
||||
cx.try_global::<GlobalAppState>()
|
||||
.map(|state| state.0.clone())
|
||||
}
|
||||
pub fn set_global(state: Weak<AppState>, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalAppState(state));
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn test(cx: &mut AppContext) -> Arc<Self> {
|
||||
use node_runtime::FakeNodeRuntime;
|
||||
@ -616,7 +651,7 @@ impl Workspace {
|
||||
let modal_layer = cx.new_view(|_| ModalLayer::new());
|
||||
|
||||
let mut active_call = None;
|
||||
if let Some(call) = cx.try_global::<Model<ActiveCall>>() {
|
||||
if let Some(call) = ActiveCall::try_global(cx) {
|
||||
let call = call.clone();
|
||||
let mut subscriptions = Vec::new();
|
||||
subscriptions.push(cx.subscribe(&call, Self::on_active_call_event));
|
||||
@ -3657,7 +3692,7 @@ impl WorkspaceStore {
|
||||
update: proto::update_followers::Variant,
|
||||
cx: &AppContext,
|
||||
) -> Option<()> {
|
||||
let active_call = cx.try_global::<Model<ActiveCall>>()?;
|
||||
let active_call = ActiveCall::try_global(cx)?;
|
||||
let room_id = active_call.read(cx).room()?.read(cx).id();
|
||||
let follower_ids: Vec<_> = self
|
||||
.followers
|
||||
|
@ -59,6 +59,7 @@ project_panel = { path = "../project_panel" }
|
||||
project_symbols = { path = "../project_symbols" }
|
||||
quick_action_bar = { path = "../quick_action_bar" }
|
||||
recent_projects = { path = "../recent_projects" }
|
||||
release_channel = { path = "../release_channel" }
|
||||
rope = { path = "../rope"}
|
||||
rpc = { path = "../rpc" }
|
||||
settings = { path = "../settings" }
|
||||
|
@ -19,6 +19,7 @@ use log::LevelFilter;
|
||||
use assets::Assets;
|
||||
use node_runtime::RealNodeRuntime;
|
||||
use parking_lot::Mutex;
|
||||
use release_channel::{parse_zed_link, AppCommitSha, ReleaseChannel, RELEASE_CHANNEL};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{
|
||||
default_settings, handle_settings_file_changes, watch_config_file, Settings, SettingsStore,
|
||||
@ -34,14 +35,13 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
atomic::{AtomicU32, Ordering},
|
||||
Arc, Weak,
|
||||
Arc,
|
||||
},
|
||||
thread,
|
||||
};
|
||||
use theme::{ActiveTheme, ThemeRegistry, ThemeSettings};
|
||||
use util::{
|
||||
async_maybe,
|
||||
channel::{parse_zed_link, AppCommitSha, ReleaseChannel, RELEASE_CHANNEL},
|
||||
http::{self, HttpClient, ZedHttpClient},
|
||||
paths::{self, CRASHES_DIR, CRASHES_RETIRED_DIR},
|
||||
ResultExt,
|
||||
@ -102,8 +102,7 @@ fn main() {
|
||||
let open_listener = listener.clone();
|
||||
app.on_open_urls(move |urls, _| open_listener.open_urls(&urls));
|
||||
app.on_reopen(move |cx| {
|
||||
if let Some(app_state) = cx
|
||||
.try_global::<Weak<AppState>>()
|
||||
if let Some(app_state) = AppState::try_global(cx)
|
||||
.map(|app_state| app_state.upgrade())
|
||||
.flatten()
|
||||
{
|
||||
@ -115,12 +114,12 @@ fn main() {
|
||||
});
|
||||
|
||||
app.run(move |cx| {
|
||||
cx.set_global(*RELEASE_CHANNEL);
|
||||
ReleaseChannel::init(cx);
|
||||
if let Some(build_sha) = option_env!("ZED_COMMIT_SHA") {
|
||||
cx.set_global(AppCommitSha(build_sha.into()))
|
||||
AppCommitSha::set_global(AppCommitSha(build_sha.into()), cx);
|
||||
}
|
||||
|
||||
cx.set_global(listener.clone());
|
||||
OpenListener::set_global(listener.clone(), cx);
|
||||
|
||||
load_embedded_fonts(cx);
|
||||
|
||||
@ -148,7 +147,7 @@ fn main() {
|
||||
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
|
||||
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||
|
||||
cx.set_global(client.clone());
|
||||
Client::set_global(client.clone(), cx);
|
||||
|
||||
zed::init(cx);
|
||||
theme::init(theme::LoadThemes::All(Box::new(Assets)), cx);
|
||||
@ -242,7 +241,7 @@ fn main() {
|
||||
workspace_store,
|
||||
node_runtime,
|
||||
});
|
||||
cx.set_global(Arc::downgrade(&app_state));
|
||||
AppState::set_global(Arc::downgrade(&app_state), cx);
|
||||
|
||||
audio::init(Assets, cx);
|
||||
auto_update::init(http.clone(), cx);
|
||||
@ -565,7 +564,7 @@ fn init_panic_hook(app: &App, installation_id: Option<String>, session_id: Strin
|
||||
.or_else(|| info.payload().downcast_ref::<String>().map(|s| s.clone()))
|
||||
.unwrap_or_else(|| "Box<Any>".to_string());
|
||||
|
||||
if *util::channel::RELEASE_CHANNEL == ReleaseChannel::Dev {
|
||||
if *release_channel::RELEASE_CHANNEL == ReleaseChannel::Dev {
|
||||
let location = info.location().unwrap();
|
||||
let backtrace = Backtrace::new();
|
||||
eprintln!(
|
||||
|
@ -5,7 +5,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use util::channel::ReleaseChannel;
|
||||
use release_channel::ReleaseChannel;
|
||||
|
||||
const LOCALHOST: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
|
||||
const CONNECT_TIMEOUT: Duration = Duration::from_millis(10);
|
||||
@ -13,7 +13,7 @@ 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 {
|
||||
let port = match *release_channel::RELEASE_CHANNEL {
|
||||
ReleaseChannel::Dev => 43737,
|
||||
ReleaseChannel::Preview => 43738,
|
||||
ReleaseChannel::Stable => 43739,
|
||||
@ -24,7 +24,7 @@ fn address() -> SocketAddr {
|
||||
}
|
||||
|
||||
fn instance_handshake() -> &'static str {
|
||||
match *util::channel::RELEASE_CHANNEL {
|
||||
match *release_channel::RELEASE_CHANNEL {
|
||||
ReleaseChannel::Dev => "Zed Editor Dev Instance Running",
|
||||
ReleaseChannel::Nightly => "Zed Editor Nightly Instance Running",
|
||||
ReleaseChannel::Preview => "Zed Editor Preview Instance Running",
|
||||
@ -39,7 +39,7 @@ pub enum IsOnlyInstance {
|
||||
}
|
||||
|
||||
pub fn ensure_only_instance() -> IsOnlyInstance {
|
||||
if *db::ZED_STATELESS || *util::channel::RELEASE_CHANNEL == ReleaseChannel::Dev {
|
||||
if *db::ZED_STATELESS || *release_channel::RELEASE_CHANNEL == ReleaseChannel::Dev {
|
||||
return IsOnlyInstance::Yes;
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,9 @@ use editor::Editor;
|
||||
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use futures::{FutureExt, SinkExt, StreamExt};
|
||||
use gpui::AsyncAppContext;
|
||||
use gpui::{AppContext, AsyncAppContext, Global};
|
||||
use language::{Bias, Point};
|
||||
use release_channel::parse_zed_link;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::prelude::OsStrExt;
|
||||
@ -17,7 +18,6 @@ use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::{path::PathBuf, sync::atomic::AtomicBool};
|
||||
use util::channel::parse_zed_link;
|
||||
use util::paths::PathLikeWithPosition;
|
||||
use util::ResultExt;
|
||||
use workspace::AppState;
|
||||
@ -42,7 +42,19 @@ pub struct OpenListener {
|
||||
pub triggered: AtomicBool,
|
||||
}
|
||||
|
||||
struct GlobalOpenListener(Arc<OpenListener>);
|
||||
|
||||
impl Global for GlobalOpenListener {}
|
||||
|
||||
impl OpenListener {
|
||||
pub fn global(cx: &AppContext) -> Arc<Self> {
|
||||
cx.global::<GlobalOpenListener>().0.clone()
|
||||
}
|
||||
|
||||
pub fn set_global(listener: Arc<OpenListener>, cx: &mut AppContext) {
|
||||
cx.set_global(GlobalOpenListener(listener))
|
||||
}
|
||||
|
||||
pub fn new() -> (Self, UnboundedReceiver<OpenRequest>) {
|
||||
let (tx, rx) = mpsc::unbounded();
|
||||
(
|
||||
|
@ -20,6 +20,7 @@ use assets::Assets;
|
||||
use futures::{channel::mpsc, select_biased, StreamExt};
|
||||
use project_panel::ProjectPanel;
|
||||
use quick_action_bar::QuickActionBar;
|
||||
use release_channel::{AppCommitSha, ReleaseChannel};
|
||||
use rope::Rope;
|
||||
use search::project_search::ProjectSearchBar;
|
||||
use settings::{initial_local_settings_content, KeymapFile, Settings, SettingsStore};
|
||||
@ -27,7 +28,6 @@ use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc};
|
||||
use terminal_view::terminal_panel::{self, TerminalPanel};
|
||||
use util::{
|
||||
asset_str,
|
||||
channel::{AppCommitSha, ReleaseChannel},
|
||||
paths::{self, LOCAL_SETTINGS_RELATIVE_PATH},
|
||||
ResultExt,
|
||||
};
|
||||
@ -202,8 +202,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
cx.toggle_full_screen();
|
||||
})
|
||||
.register_action(|_, action: &OpenZedUrl, cx| {
|
||||
cx.global::<Arc<OpenListener>>()
|
||||
.open_urls(&[action.url.clone()])
|
||||
OpenListener::global(cx).open_urls(&[action.url.clone()])
|
||||
})
|
||||
.register_action(|_, action: &OpenBrowser, cx| cx.open_url(&action.url))
|
||||
.register_action(move |_, _: &IncreaseBufferFontSize, cx| {
|
||||
@ -370,12 +369,12 @@ fn initialize_pane(workspace: &mut Workspace, pane: &View<Pane>, cx: &mut ViewCo
|
||||
}
|
||||
|
||||
fn about(_: &mut Workspace, _: &About, cx: &mut gpui::ViewContext<Workspace>) {
|
||||
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
let app_name = ReleaseChannel::global(cx).display_name();
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let message = format!("{app_name} {version}");
|
||||
let detail = cx.try_global::<AppCommitSha>().map(|sha| sha.0.as_ref());
|
||||
let detail = AppCommitSha::try_global(cx).map(|sha| sha.0.clone());
|
||||
|
||||
let prompt = cx.prompt(PromptLevel::Info, &message, detail, &["OK"]);
|
||||
let prompt = cx.prompt(PromptLevel::Info, &message, detail.as_deref(), &["OK"]);
|
||||
cx.foreground_executor()
|
||||
.spawn(async {
|
||||
prompt.await.ok();
|
||||
|
Loading…
Reference in New Issue
Block a user