diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index b0f791d..37ea879 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,6 +1,7 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use serde_json::json; use tokio::sync::Mutex; use std::collections::HashMap; @@ -94,7 +95,8 @@ impl AppState { } // Return cell_id - async fn create_cell(&self, window_id: &str, cell_type: Option<&str>) -> Option { + async fn create_cell(&self, window: Window, cell_type: Option<&str>) -> Option { + let window_id = window.label(); debug!("Creating a new cell in window with ID: {}", window_id); let cell_type = cell_type.unwrap_or("code"); @@ -111,7 +113,8 @@ impl AppState { } // Update a specific cell within the specified notebook - async fn update_cell(&self, window_id: &str, cell_id: &str, new_content: &str) -> bool { + async fn update_cell(&self, window: Window, cell_id: &str, new_content: &str) -> bool { + let window_id = window.label(); debug!( "Updating cell with ID: {} in window with ID: {} with new content: {}", cell_id, window_id, new_content @@ -121,6 +124,13 @@ impl AppState { if let Some(notebook) = notebooks.get_mut(window_id) { if let Some(cell) = notebook.get_mut_cell(cell_id) { cell.set_source(new_content); + + window.emit( + format!("cell-{}", cell_id).as_str(), + Some(json!({ + "source": new_content + })) + ).unwrap(); } true } else { @@ -131,8 +141,7 @@ impl AppState { #[tauri::command] async fn create_cell(state: State<'_, AppState>, window: Window, cell_type: &str) -> Result, String> { - let window_id = window.label(); // Use the window label as a unique identifier - Ok(state.create_cell(window_id, Some(cell_type)).await) + Ok(state.create_cell(window, Some(cell_type)).await) } #[tauri::command] @@ -151,8 +160,7 @@ async fn update_cell( cell_id: &str, new_content: &str, ) -> Result { - let window_id = window.label(); // Use the window label as a unique identifier - Ok(state.update_cell(window_id, cell_id, new_content).await) + Ok(state.update_cell(window, cell_id, new_content).await) } // The main entry point for the Tauri application diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index db41662..bf655b8 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -6,7 +6,7 @@ import { lightTheme } from "@/codemirror-themes"; import { StateField } from "@codemirror/state"; import { EditorView, keymap } from "@codemirror/view"; -import { useCodeCell } from "@/hooks/useCell"; +import { useCell } from "@/hooks/useCell"; import { invoke } from "@tauri-apps/api/tauri"; @@ -82,7 +82,7 @@ const baseExtensions = [ export const Editor = ({ cellId, className, language }: { cellId: string, className?: string, language: string }) => { const ref = useRef(null); - const { content, updateCell } = useCodeCell(cellId); + const { content, updateCell } = useCell(cellId); // We need to compute a derived extensions state based on the language of the editor const extensions = useMemo(() => { diff --git a/src/components/markdown-cell.tsx b/src/components/markdown-cell.tsx index 115ee61..483b610 100644 --- a/src/components/markdown-cell.tsx +++ b/src/components/markdown-cell.tsx @@ -3,6 +3,8 @@ import { useRemark } from "react-remark"; import { useMarkdownCell } from "@/hooks/useCell"; +import { Editor } from "@/components//Editor"; + export const MarkdownCell = ({ cellId }: { cellId: string }) => { const { content } = useMarkdownCell(cellId); @@ -12,6 +14,8 @@ export const MarkdownCell = ({ cellId }: { cellId: string }) => { setMarkdownSource(content); }, [content]); + console.log(content) + return (
@@ -19,6 +23,12 @@ export const MarkdownCell = ({ cellId }: { cellId: string }) => { {/* placeholder */}
+ +
{reactContent}
); diff --git a/src/hooks/useCell.ts b/src/hooks/useCell.ts index 03b88d1..206c8cc 100644 --- a/src/hooks/useCell.ts +++ b/src/hooks/useCell.ts @@ -35,18 +35,43 @@ function cellReducer(state: CellState, action: Action) { } } -export function useMarkdownCell(cellId: string) { +export function useCell(cellId: string) { const [content, setContent] = useState(""); const updateCell = useCallback(async (newContent: string) => { try { - await invoke("update_cell", { cellId, newContent }); setContent(newContent); + await invoke("update_cell", { cellId, newContent }); } catch (error) { console.error(error); // Handle error } - }, [cellId]); + }, [cellId]); + + + useEffect(() => { + const setupListener = async () => { + const unlisten = await listen(`cell-${cellId}`, (event) => { + const cellUpdate = event.payload as any; + + setContent(cellUpdate.source) + }); + + return () => { + unlisten(); + }; + }; + + setupListener(); + }, [cellId]); + + + + return { content, setContent, updateCell } +} + +export function useMarkdownCell(cellId: string) { + const { content, updateCell } = useCell(cellId); // TODO: Push/pull this from cell metadata const metadata = { }; @@ -55,7 +80,8 @@ export function useMarkdownCell(cellId: string) { } export function useCodeCell(cellId: string) { - const [content, setContent] = useState(""); + const { content, updateCell } = useCell(cellId); + const [state, dispatch] = useReducer(cellReducer, initialState); const executeCell = useCallback(async () => { @@ -69,16 +95,6 @@ export function useCodeCell(cellId: string) { dispatch({ type: 'reset' }); }, [cellId]); - const updateCell = useCallback(async (newContent: string) => { - try { - await invoke("update_cell", { cellId, newContent }); - setContent(newContent); - } catch (error) { - console.error(error); - // Handle error - } - }, [cellId]); - useEffect(() => { const setupListener = async () => { const unlisten = await listen(`cell-outputs-${cellId}`, (event) => {