lsp: Send contents to preview for implicitly loaded slint files

This fixes the no preview in slintpad issue when retrieving the contents
of files is slow (e.g. when loaded from the web).

Fixes: #3855
This commit is contained in:
Tobias Hunger 2023-11-08 14:00:33 +01:00 committed by Tobias Hunger
parent aeb512686e
commit 0774d01a59
5 changed files with 73 additions and 59 deletions

View file

@ -123,7 +123,7 @@ pub struct Context {
pub document_cache: RefCell<DocumentCache>,
pub server_notifier: crate::ServerNotifier,
pub init_param: InitializeParams,
pub preview: Box<dyn PreviewApi>,
pub preview: Rc<dyn PreviewApi>,
}
#[derive(Default)]

View file

@ -311,25 +311,14 @@ pub fn run_lsp_server() -> Result<IoThreads> {
}
fn main_loop(connection: Connection, init_param: InitializeParams) -> Result<()> {
let mut compiler_config =
CompilerConfiguration::new(i_slint_compiler::generator::OutputFormat::Interpreter);
let cli_args = Cli::parse();
compiler_config.style =
Some(if cli_args.style.is_empty() { "fluent".into() } else { cli_args.style });
compiler_config.include_paths = cli_args.include_paths;
let mut rh = RequestHandler::default();
register_request_handlers(&mut rh);
let request_queue = OutgoingRequestQueue::default();
let server_notifier = ServerNotifier(connection.sender.clone(), request_queue.clone());
let ctx = Rc::new(Context {
document_cache: RefCell::new(DocumentCache::new(compiler_config)),
let preview = Rc::new(Previewer {
server_notifier: server_notifier.clone(),
init_param,
preview: Box::new(Previewer {
server_notifier,
#[cfg(all(not(feature = "preview-builtin"), not(feature = "preview-external")))]
use_external_previewer: RefCell::new(false), // No preview, pick any.
#[cfg(all(not(feature = "preview-builtin"), feature = "preview-external"))]
@ -339,7 +328,31 @@ fn main_loop(connection: Connection, init_param: InitializeParams) -> Result<()>
#[cfg(all(feature = "preview-builtin", feature = "preview-external"))]
use_external_previewer: RefCell::new(false), // prefer internal
to_show: RefCell::new(None),
}),
});
let mut compiler_config =
CompilerConfiguration::new(i_slint_compiler::generator::OutputFormat::Interpreter);
let cli_args = Cli::parse();
compiler_config.style =
Some(if cli_args.style.is_empty() { "fluent".into() } else { cli_args.style });
compiler_config.include_paths = cli_args.include_paths;
let preview_notifier = preview.clone();
compiler_config.open_import_fallback = Some(Rc::new(move |path| {
let preview_notifier = preview_notifier.clone();
Box::pin(async move {
let contents = std::fs::read_to_string(&path);
if let Ok(contents) = &contents {
preview_notifier.set_contents(&PathBuf::from(path), contents);
}
Some(contents)
})
}));
let ctx = Rc::new(Context {
document_cache: RefCell::new(DocumentCache::new(compiler_config)),
server_notifier: server_notifier,
init_param,
preview,
});
let mut futures = Vec::<Pin<Box<dyn Future<Output = Result<()>>>>>::new();

View file

@ -65,7 +65,8 @@ pub fn set_contents(path: &Path, content: String) {
let current = cache.current.clone();
let ui_is_visible = cache.ui_is_visible;
drop(cache);
if ui_is_visible {
if ui_is_visible && !current.path.as_os_str().is_empty() {
load_preview(current);
}
}
@ -79,11 +80,14 @@ fn set_design_mode(enable: bool) {
}
fn change_style() {
let component = {
let cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
cache.current.clone()
};
load_preview(component);
let ui_is_visible = cache.ui_is_visible;
let current = cache.current.clone();
drop(cache);
if ui_is_visible && !current.path.as_os_str().is_empty() {
load_preview(current);
}
}
pub fn start_parsing() {
@ -119,7 +123,8 @@ pub fn config_changed(
let current = cache.current.clone();
let ui_is_visible = cache.ui_is_visible;
drop(cache);
if ui_is_visible {
if ui_is_visible && !current.path.as_os_str().is_empty() {
load_preview(current);
}
}

View file

@ -65,6 +65,10 @@ impl PreviewApi for Previewer {
}
fn load_preview(&self, component: common::PreviewComponent) {
if component.path.as_os_str().is_empty() {
return;
}
self.to_show.replace(Some(component.clone()));
#[cfg(feature = "preview-external")]
@ -260,29 +264,38 @@ pub fn create(
) -> JsResult<SlintServer> {
console_error_panic_hook::set_once();
let send_request = Function::from(send_request.clone());
let server_notifier = ServerNotifier { send_notification, send_request };
let preview = Rc::new(Previewer {
server_notifier: server_notifier.clone(),
to_show: Default::default(),
});
let init_param = serde_wasm_bindgen::from_value(init_param)?;
let mut compiler_config =
CompilerConfiguration::new(i_slint_compiler::generator::OutputFormat::Interpreter);
let preview_notifier = preview.clone();
compiler_config.open_import_fallback = Some(Rc::new(move |path| {
let load_file = Function::from(load_file.clone());
Box::pin(async move { Some(self::load_file(path, &load_file).await) })
let preview_notifier = preview_notifier.clone();
Box::pin(async move {
let contents = self::load_file(path.clone(), &load_file).await;
if let Ok(contents) = &contents {
preview_notifier.set_contents(&PathBuf::from(path), contents);
}
Some(contents)
})
}));
let document_cache = RefCell::new(DocumentCache::new(compiler_config));
let send_request = Function::from(send_request.clone());
let reentry_guard = Rc::new(RefCell::new(ReentryGuard::default()));
let mut rh = RequestHandler::default();
language::register_request_handlers(&mut rh);
let server_notifier = ServerNotifier { send_notification, send_request };
Ok(SlintServer {
ctx: Rc::new(Context {
document_cache,
init_param,
server_notifier: server_notifier.clone(),
preview: Box::new(Previewer { server_notifier, to_show: Default::default() }),
}),
ctx: Rc::new(Context { document_cache, init_param, server_notifier, preview }),
reentry_guard,
rh: Rc::new(rh),
})

View file

@ -1,7 +1,7 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
// cSpell: ignore edcore lumino mimetypes printerdemo
// cSpell: ignore codingame lumino mimetypes printerdemo
import * as monaco from "monaco-editor";
@ -416,6 +416,10 @@ class EditorPaneWidget extends Widget {
if (monaco.editor.getModels().length === 1) {
this.#main_uri = uri;
this.set_model(uri);
this.language_client?.sendRequest("workspace/executeCommand", {
command: "slint/showPreview",
arguments: [this.#main_uri?.toString() ?? "", ""],
});
}
}
@ -797,7 +801,6 @@ export class EditorWidget extends Widget {
}
async set_demo(location: string) {
let result_uri: monaco.Uri | null = null;
if (location) {
const default_tag = "XXXX_DEFAULT_TAG_XXXX";
let tag = default_tag.startsWith("XXXX_DEFAULT_TAG_")
@ -813,32 +816,12 @@ export class EditorWidget extends Widget {
tag = "v" + found[1];
}
}
result_uri = await this.project_from_url(
await this.project_from_url(
`https://raw.githubusercontent.com/slint-ui/slint/${tag}/${location}`,
);
} else {
this.#editor.clear_models();
const model = await createModel(
this.#editor.internal_uuid,
hello_world,
);
if (model) {
result_uri = model.uri;
}
}
if (result_uri) {
setTimeout(
() =>
this.language_client?.sendRequest(
"workspace/executeCommand",
{
command: "slint/showPreview",
arguments: [result_uri?.toString() ?? "", ""],
},
),
1000,
);
await createModel(this.#editor.internal_uuid, hello_world);
}
}