Display user-provided project name in the top bar (#7533)

Closes #7409

https://github.com/enso-org/enso/assets/6566674/d4cb6733-dc9f-454e-ba1b-e76260bda467

# Important Notes
A new config parameter was added, `startup.displayedProjectName`. When connecting IDE to the LS, it must be provided directly with the `rpcUrl` and `dataUrl` parameters. If not provided, `startup.project` will be displayed in the IDE instead. Remember that `startup.project` must be a valid Enso project name, so-called `normalized name`.
This commit is contained in:
Ilya Bogdanov 2023-08-11 16:32:46 +04:00 committed by GitHub
parent e035b2d50a
commit c2ca848d6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 15 deletions

View File

@ -46,6 +46,7 @@ pub enum BackendService {
binary_endpoint: String,
namespace: String,
project_name: String,
displayed_name: String,
},
}
@ -90,11 +91,19 @@ impl BackendService {
} else {
Ok(project_name.to_owned())
}?;
let displayed_name_option = &args.groups.startup.options.displayed_project_name;
let displayed_name = displayed_name_option.value.as_str();
let displayed_name = if displayed_name.is_empty() {
project_name.clone()
} else {
displayed_name.to_owned()
};
Ok(Self::LanguageServer {
json_endpoint,
binary_endpoint,
namespace,
project_name,
displayed_name,
})
}
}

View File

@ -11,6 +11,7 @@ use crate::model::project::synchronized::Properties;
use double_representation::name::project;
use engine_protocol::project_manager::ProjectName;
use engine_protocol::project_manager::ProjectNormalizedName;
use parser::Parser;
@ -60,7 +61,8 @@ impl Handle {
/// Create IDE Controller from Language Server endpoints, describing the opened project.
pub async fn from_ls_endpoints(
namespace: String,
project_name: ProjectName,
normalized_name: ProjectNormalizedName,
displayed_name: ProjectName,
version: semver::Version,
json_endpoint: String,
binary_endpoint: String,
@ -68,8 +70,9 @@ impl Handle {
let properties = Properties {
//TODO [ao]: this should be not the default; instead project model should not need the
// id. See https://github.com/enso-org/ide/issues/1572
id: default(),
name: project::QualifiedName::new(namespace, project_name),
id: default(),
project_name: project::QualifiedName::new(namespace, normalized_name),
displayed_name,
engine_version: version,
};
let project = model::project::Synchronized::new_connected(

View File

@ -129,10 +129,17 @@ impl Initializer {
let controller = controller::ide::Desktop::new(project_manager, project_to_open);
Ok(Rc::new(controller.await?))
}
LanguageServer { json_endpoint, binary_endpoint, namespace, project_name } => {
LanguageServer {
json_endpoint,
binary_endpoint,
namespace,
project_name,
displayed_name,
} => {
let json_endpoint = json_endpoint.clone();
let binary_endpoint = binary_endpoint.clone();
let namespace = namespace.clone();
let displayed_name = displayed_name.clone().into();
let project_name = project_name.clone().into();
// TODO[ao]: we should think how to handle engine's versions in cloud.
// https://github.com/enso-org/ide/issues/1195
@ -140,6 +147,7 @@ impl Initializer {
let controller = controller::ide::Plain::from_ls_endpoints(
namespace,
project_name,
displayed_name,
version,
json_endpoint,
binary_endpoint,

View File

@ -262,7 +262,7 @@ pub struct UnsupportedEngineVersion {
impl UnsupportedEngineVersion {
fn error_wrapper(properties: &Properties) -> impl Fn(failure::Error) -> failure::Error {
let engine_version = properties.engine_version.clone();
let project_name = properties.name.project.as_str().to_owned();
let project_name = properties.project_name.project.as_str().to_owned();
move |root_cause| {
if let Err(version_mismatch) = enso_config::check_engine_version(&engine_version) {
UnsupportedEngineVersion {
@ -300,7 +300,11 @@ impl Display for UnsupportedEngineVersion {
pub struct Properties {
/// ID of the project, as used by the Project Manager service.
pub id: Uuid,
pub name: project::QualifiedName,
/// Qualified name of the project's main module, it is used primarily in communication with the
/// language server.
pub project_name: project::QualifiedName,
/// A project name as displayed to the user, it can be different from the `project_name`.
pub displayed_name: ProjectName,
pub engine_version: semver::Version,
}
@ -338,7 +342,7 @@ impl Project {
properties: Properties,
) -> FallibleResult<Self> {
let wrap = UnsupportedEngineVersion::error_wrapper(&properties);
info!("Creating a model of project {}", properties.name);
info!("Creating a model of project {}", properties.project_name);
let binary_protocol_events = language_server_bin.event_stream();
let json_rpc_events = language_server_rpc.events();
let embedded_visualizations = default();
@ -422,13 +426,15 @@ impl Project {
let action = MissingComponentAction::Install;
let opened = project_manager.open_project(&id, &action).await?;
let namespace = opened.project_namespace;
let displayed_name = opened.project_name;
let normalized_name = opened.project_normalized_name;
let project_manager = Some(project_manager);
let json_endpoint = opened.language_server_json_address.to_string();
let binary_endpoint = opened.language_server_binary_address.to_string();
let properties = Properties {
id,
name: project::QualifiedName::new(namespace, normalized_name),
project_name: project::QualifiedName::new(namespace, normalized_name),
displayed_name,
engine_version: semver::Version::parse(&opened.engine_version)?,
};
Self::new_connected(project_manager, json_endpoint, binary_endpoint, properties).await
@ -676,11 +682,11 @@ impl Project {
impl model::project::API for Project {
fn name(&self) -> ImString {
self.properties.borrow().name.project.clone_ref()
self.properties.borrow().displayed_name.clone().into()
}
fn qualified_name(&self) -> project::QualifiedName {
self.properties.borrow().name.clone_ref()
self.properties.borrow().project_name.clone_ref()
}
fn json_rpc(&self) -> Rc<language_server::Connection> {
@ -749,7 +755,7 @@ impl model::project::API for Project {
std::future::ready(Err(RenameInReadOnly.into())).boxed_local()
} else {
async move {
let old_name = self.properties.borrow_mut().name.project.clone_ref();
let old_name = self.properties.borrow_mut().project_name.project.clone_ref();
let referent_name = name.to_im_string();
let project_manager =
self.project_manager.as_ref().ok_or(ProjectManagerUnavailable)?;
@ -763,7 +769,7 @@ impl model::project::API for Project {
error => error.into(),
},
)?;
self.properties.borrow_mut().name.project = referent_name.clone_ref();
self.properties.borrow_mut().project_name.project = referent_name.clone_ref();
self.execution_contexts.rename_project(old_name, referent_name);
Ok(())
}
@ -853,7 +859,8 @@ mod test {
let project_manager = Rc::new(project_manager);
let properties = Properties {
id: Uuid::new_v4(),
name: crate::test::mock::data::project_qualified_name(),
project_name: crate::test::mock::data::project_qualified_name(),
displayed_name: ProjectName::new_unchecked("Test Project"),
engine_version: semver::Version::new(0, 2, 1),
};
let project_fut =

View File

@ -42,6 +42,11 @@
"value": "",
"description": "The name of the project to open at startup. If the project does not exist, it will be created."
},
"displayedProjectName": {
"value": "",
"description": "The name of the project to be displayed to the user.",
"primary": false
},
"platform": {
"value": "web",
"defaultDescription": "'web' if run in the browser, operating system name otherwise`",
@ -60,12 +65,12 @@
},
"rpcUrl": {
"value": "",
"description": "The address of the Language Server RPC endpoint. This argument should be provided together with `dataUrl`, `namespace`, and `project` options. They enable Enso to connect directly to an already-spawned Language Server of some project.",
"description": "The address of the Language Server RPC endpoint. This argument should be provided together with `dataUrl`, `namespace`, `project` and `displayedProjectName` options. They enable Enso to connect directly to an already-spawned Language Server of some project.",
"primary": false
},
"dataUrl": {
"value": "",
"description": "The address of the Language Server Data endpoint. This argument should be provided together with `rpcUrl`, `namespace`, and `project` options. They enable Enso to connect directly to an already-spawned Language Server of some project.",
"description": "The address of the Language Server Data endpoint. This argument should be provided together with `rpcUrl`, `namespace`, `project` and `dislayedProjectName` options. They enable Enso to connect directly to an already-spawned Language Server of some project.",
"primary": false
},
"namespace": {