mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-11-25 05:22:52 +00:00
dev: move preview actor (#378)
This commit is contained in:
parent
8852109b10
commit
ad79b29fd2
3 changed files with 101 additions and 76 deletions
|
|
@ -3,6 +3,7 @@
|
|||
pub mod editor;
|
||||
pub mod export;
|
||||
pub mod format;
|
||||
pub mod preview;
|
||||
pub mod typ_client;
|
||||
pub mod typ_server;
|
||||
pub mod user_action;
|
||||
|
|
|
|||
93
crates/tinymist/src/actor/preview.rs
Normal file
93
crates/tinymist/src/actor/preview.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use lsp_types::notification::Notification;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use sync_lsp::{internal_error, LspClient, LspResult};
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
use typst_preview::{ControlPlaneMessage, Previewer};
|
||||
|
||||
use super::typ_client::CompileHandler;
|
||||
|
||||
pub struct PreviewTab {
|
||||
/// Task ID
|
||||
pub task_id: String,
|
||||
/// Previewer
|
||||
pub previewer: Previewer,
|
||||
/// Static server killer
|
||||
pub ss_killer: oneshot::Sender<()>,
|
||||
/// Static server handle
|
||||
pub ss_handle: tokio::task::JoinHandle<()>,
|
||||
/// Control plane message sender
|
||||
pub ctl_tx: mpsc::UnboundedSender<ControlPlaneMessage>,
|
||||
/// Compile handler
|
||||
pub compile_handler: Arc<CompileHandler>,
|
||||
}
|
||||
|
||||
pub enum PreviewRequest {
|
||||
Started(PreviewTab),
|
||||
Kill(String, oneshot::Sender<LspResult<JsonValue>>),
|
||||
Scroll(String, ControlPlaneMessage),
|
||||
}
|
||||
|
||||
pub struct PreviewActor {
|
||||
pub client: LspClient,
|
||||
pub tabs: HashMap<String, PreviewTab>,
|
||||
pub preview_rx: mpsc::UnboundedReceiver<PreviewRequest>,
|
||||
}
|
||||
|
||||
impl PreviewActor {
|
||||
pub async fn run(mut self) {
|
||||
while let Some(req) = self.preview_rx.recv().await {
|
||||
match req {
|
||||
PreviewRequest::Started(tab) => {
|
||||
self.tabs.insert(tab.task_id.clone(), tab);
|
||||
}
|
||||
PreviewRequest::Kill(task_id, tx) => {
|
||||
log::info!("PreviewTask({task_id}): killing");
|
||||
let Some(mut tab) = self.tabs.remove(&task_id) else {
|
||||
let _ = tx.send(Err(internal_error("task not found")));
|
||||
continue;
|
||||
};
|
||||
|
||||
let client = self.client.clone();
|
||||
self.client.handle.spawn(async move {
|
||||
tab.previewer.stop().await;
|
||||
let _ = tab.ss_killer.send(());
|
||||
|
||||
// Wait for previewer to stop
|
||||
log::info!("PreviewTask({task_id}): wait for previewer to stop");
|
||||
tab.previewer.join().await;
|
||||
log::info!("PreviewTask({task_id}): wait for static server to stop");
|
||||
let _ = tab.ss_handle.await;
|
||||
|
||||
log::info!("PreviewTask({task_id}): killed");
|
||||
// Unregister preview
|
||||
tab.compile_handler.unregister_preview(&tab.task_id);
|
||||
// Send response
|
||||
let _ = tx.send(Ok(JsonValue::Null));
|
||||
// Send global notification
|
||||
client.send_notification::<DisposePreview>(DisposePreview { task_id });
|
||||
});
|
||||
}
|
||||
PreviewRequest::Scroll(task_id, req) => {
|
||||
self.scroll(task_id, req).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn scroll(&mut self, task_id: String, req: ControlPlaneMessage) -> Option<()> {
|
||||
self.tabs.get(&task_id)?.ctl_tx.send(req).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct DisposePreview {
|
||||
task_id: String,
|
||||
}
|
||||
|
||||
impl Notification for DisposePreview {
|
||||
type Params = Self;
|
||||
const METHOD: &'static str = "tinymist/preview/dispose";
|
||||
}
|
||||
|
|
@ -23,7 +23,11 @@ use typst_ts_core::config::{compiler::EntryOpts, CompileOpts};
|
|||
|
||||
use super::*;
|
||||
use crate::{compile_init::CompileOnceArgs, LspUniverse};
|
||||
use actor::{typ_client::CompileHandler, typ_server::CompileServerActor};
|
||||
use actor::{
|
||||
preview::{PreviewActor, PreviewRequest, PreviewTab},
|
||||
typ_client::CompileHandler,
|
||||
typ_server::CompileServerActor,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, clap::Parser)]
|
||||
pub struct PreviewCliArgs {
|
||||
|
|
@ -51,60 +55,8 @@ pub struct PreviewCliArgs {
|
|||
pub dont_open_in_browser: bool,
|
||||
}
|
||||
|
||||
pub struct PreviewActor {
|
||||
client: TypedLspClient<PreviewState>,
|
||||
tabs: HashMap<String, PreviewTab>,
|
||||
preview_rx: mpsc::UnboundedReceiver<PreviewRequest>,
|
||||
}
|
||||
|
||||
impl PreviewActor {
|
||||
pub async fn run(mut self) {
|
||||
while let Some(req) = self.preview_rx.recv().await {
|
||||
match req {
|
||||
PreviewRequest::Started(tab) => {
|
||||
self.tabs.insert(tab.task_id.clone(), tab);
|
||||
}
|
||||
PreviewRequest::Kill(task_id, tx) => {
|
||||
log::info!("PreviewTask({task_id}): killing");
|
||||
let Some(mut tab) = self.tabs.remove(&task_id) else {
|
||||
let _ = tx.send(Err(internal_error("task not found")));
|
||||
continue;
|
||||
};
|
||||
|
||||
let client = self.client.clone();
|
||||
self.client.handle.spawn(async move {
|
||||
tab.previewer.stop().await;
|
||||
let _ = tab.ss_killer.send(());
|
||||
|
||||
// Wait for previewer to stop
|
||||
log::info!("PreviewTask({task_id}): wait for previewer to stop");
|
||||
tab.previewer.join().await;
|
||||
log::info!("PreviewTask({task_id}): wait for static server to stop");
|
||||
let _ = tab.ss_handle.await;
|
||||
|
||||
log::info!("PreviewTask({task_id}): killed");
|
||||
// Unregister preview
|
||||
tab.compile_handler.unregister_preview(&tab.task_id);
|
||||
// Send response
|
||||
let _ = tx.send(Ok(JsonValue::Null));
|
||||
// Send global notification
|
||||
client.send_notification::<DisposePreview>(DisposePreview { task_id });
|
||||
});
|
||||
}
|
||||
PreviewRequest::Scroll(task_id, req) => {
|
||||
self.scroll(task_id, req).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn scroll(&mut self, task_id: String, req: ControlPlaneMessage) -> Option<()> {
|
||||
self.tabs.get(&task_id)?.ctl_tx.send(req).ok()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PreviewState {
|
||||
client: TypedLspClient<PreviewState>,
|
||||
pub client: TypedLspClient<PreviewState>,
|
||||
|
||||
preview_tx: mpsc::UnboundedSender<PreviewRequest>,
|
||||
}
|
||||
|
|
@ -115,7 +67,7 @@ impl PreviewState {
|
|||
|
||||
client.handle.spawn(
|
||||
PreviewActor {
|
||||
client: client.clone(),
|
||||
client: client.clone().to_untyped(),
|
||||
tabs: HashMap::default(),
|
||||
preview_rx,
|
||||
}
|
||||
|
|
@ -126,27 +78,6 @@ impl PreviewState {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct PreviewTab {
|
||||
/// Task ID
|
||||
pub task_id: String,
|
||||
/// Previewer
|
||||
pub previewer: Previewer,
|
||||
/// Static server killer
|
||||
pub ss_killer: oneshot::Sender<()>,
|
||||
/// Static server handle
|
||||
pub ss_handle: tokio::task::JoinHandle<()>,
|
||||
/// Control plane message sender
|
||||
pub ctl_tx: mpsc::UnboundedSender<ControlPlaneMessage>,
|
||||
/// Compile handler
|
||||
pub compile_handler: Arc<CompileHandler>,
|
||||
}
|
||||
|
||||
enum PreviewRequest {
|
||||
Started(PreviewTab),
|
||||
Kill(String, oneshot::Sender<LspResult<JsonValue>>),
|
||||
Scroll(String, ControlPlaneMessage),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct StartPreviewResponse {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue