106 lines · 3.3 KB · Rust
RawDownload
use db::kvp::KEY_VALUE_STORE;use gpui::{SharedString, Window};use project::{Project, WorktreeId};use std::sync::LazyLock;use ui::prelude::*;use util::rel_path::RelPath;use workspace::Workspace;use workspace::notifications::NotificationId;use workspace::notifications::simple_message_notification::MessageNotification;use worktree::UpdatedEntriesSet; const DEV_CONTAINER_SUGGEST_KEY: &str = "dev_container_suggest_dismissed"; fn devcontainer_path() -> &'static RelPath {    static PATH: LazyLock<&'static RelPath> =        LazyLock::new(|| RelPath::unix(".devcontainer").expect("valid path"));    *PATH} fn project_devcontainer_key(project_path: &str) -> String {    format!("{}_{}", DEV_CONTAINER_SUGGEST_KEY, project_path)} pub fn suggest_on_worktree_updated(    worktree_id: WorktreeId,    updated_entries: &UpdatedEntriesSet,    project: &gpui::Entity<Project>,    window: &mut Window,    cx: &mut Context<Workspace>,) {    let devcontainer_updated = updated_entries        .iter()        .any(|(path, _, _)| path.as_ref() == devcontainer_path());     if !devcontainer_updated {        return;    }     let Some(worktree) = project.read(cx).worktree_for_id(worktree_id, cx) else {        return;    };     let worktree = worktree.read(cx);     if !worktree.is_local() {        return;    }     let has_devcontainer = worktree        .entry_for_path(devcontainer_path())        .is_some_and(|entry| entry.is_dir());     if !has_devcontainer {        return;    }     let abs_path = worktree.abs_path();    let project_path = abs_path.to_string_lossy().to_string();    let key_for_dismiss = project_devcontainer_key(&project_path);     let already_dismissed = KEY_VALUE_STORE        .read_kvp(&key_for_dismiss)        .ok()        .flatten()        .is_some();     if already_dismissed {        return;    }     cx.on_next_frame(window, move |workspace, _window, cx| {        struct DevContainerSuggestionNotification;         let notification_id = NotificationId::composite::<DevContainerSuggestionNotification>(            SharedString::from(project_path.clone()),        );         workspace.show_notification(notification_id, cx, |cx| {            cx.new(move |cx| {                MessageNotification::new(                    "This project contains a Dev Container configuration file. Would you like to re-open it in a container?",                    cx,                )                .primary_message("Yes, Open in Container")                .primary_icon(IconName::Check)                .primary_icon_color(Color::Success)                .primary_on_click({                    move |window, cx| {                        window.dispatch_action(Box::new(zed_actions::OpenDevContainer), cx);                    }                })                .secondary_message("Don't Show Again")                .secondary_icon(IconName::Close)                .secondary_icon_color(Color::Error)                .secondary_on_click({                    move |_window, cx| {                        let key = key_for_dismiss.clone();                        db::write_and_log(cx, move || {                            KEY_VALUE_STORE.write_kvp(key, "dismissed".to_string())                        });                    }                })            })        });    });}