diff --git a/frontend/app/onboarding/onboarding-command.tsx b/frontend/app/onboarding/onboarding-command.tsx index 783f544e51..d98065dbf6 100644 --- a/frontend/app/onboarding/onboarding-command.tsx +++ b/frontend/app/onboarding/onboarding-command.tsx @@ -1,7 +1,7 @@ // Copyright 2025, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { useCallback, useLayoutEffect, useState } from "react"; +import { useCallback, useLayoutEffect, useRef, useState } from "react"; import { FakeBlock } from "./onboarding-layout"; import waveLogo from "/logos/wave-logo.png"; @@ -114,6 +114,7 @@ export const ViewLogoCommand = ({ onComplete }: { onComplete?: () => void }) => }; export const EditBashrcCommand = ({ onComplete }: { onComplete?: () => void }) => { + const fileNameRef = useRef(`${crypto.randomUUID()}/.bashrc`); const bashrcContent = `# Aliases alias ll="ls -lah" alias gst="git status" @@ -127,7 +128,13 @@ export PATH="$HOME/.local/bin:$PATH"`; return ( - + ); }; diff --git a/frontend/app/onboarding/onboarding-layout.tsx b/frontend/app/onboarding/onboarding-layout.tsx index 057aef0fc2..bbe2aece5f 100644 --- a/frontend/app/onboarding/onboarding-layout.tsx +++ b/frontend/app/onboarding/onboarding-layout.tsx @@ -15,9 +15,21 @@ export type FakeBlockProps = { markdown?: string; imgsrc?: string; editorText?: string; + editorFileName?: string; + editorLanguage?: string; }; -export const FakeBlock = ({ icon, name, highlighted, className, markdown, imgsrc, editorText }: FakeBlockProps) => { +export const FakeBlock = ({ + icon, + name, + highlighted, + className, + markdown, + imgsrc, + editorText, + editorFileName, + editorLanguage, +}: FakeBlockProps) => { return (
{editorText ? (
- +
) : imgsrc ? ( {name} diff --git a/frontend/app/view/codeeditor/codeeditor.tsx b/frontend/app/view/codeeditor/codeeditor.tsx index 3f278a6825..13c810d6a0 100644 --- a/frontend/app/view/codeeditor/codeeditor.tsx +++ b/frontend/app/view/codeeditor/codeeditor.tsx @@ -108,11 +108,12 @@ interface CodeEditorProps { text: string; readonly: boolean; language?: string; + fileName?: string; onChange?: (text: string) => void; onMount?: (monacoPtr: MonacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco) => () => void; } -export function CodeEditor({ blockId, text, language, readonly, onChange, onMount }: CodeEditorProps) { +export function CodeEditor({ blockId, text, language, fileName, readonly, onChange, onMount }: CodeEditorProps) { const divRef = useRef(null); const unmountRef = useRef<() => void>(null); const minimapEnabled = useOverrideConfigAtom(blockId, "editor:minimapenabled") ?? false; @@ -120,7 +121,14 @@ export function CodeEditor({ blockId, text, language, readonly, onChange, onMoun const wordWrap = useOverrideConfigAtom(blockId, "editor:wordwrap") ?? false; const fontSize = boundNumber(useOverrideConfigAtom(blockId, "editor:fontsize"), 6, 64); const theme = "wave-theme-dark"; - const editorPath = useRef(crypto.randomUUID()).current; + const uuidRef = useRef(crypto.randomUUID()).current; + let editorPath: string; + if (fileName) { + const separator = fileName.startsWith("/") ? "" : "/"; + editorPath = blockId + separator + fileName; + } else { + editorPath = uuidRef; + } React.useEffect(() => { return () => { diff --git a/frontend/app/view/preview/preview-edit.tsx b/frontend/app/view/preview/preview-edit.tsx index f249f7ee7f..a7ec656cc2 100644 --- a/frontend/app/view/preview/preview-edit.tsx +++ b/frontend/app/view/preview/preview-edit.tsx @@ -12,10 +12,35 @@ import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api"; import { useEffect } from "react"; import type { SpecializedViewProps } from "./preview"; +export const shellFileMap: Record = { + ".bashrc": "shell", + ".bash_profile": "shell", + ".bash_login": "shell", + ".bash_logout": "shell", + ".profile": "shell", + ".zshrc": "shell", + ".zprofile": "shell", + ".zlogin": "shell", + ".zlogout": "shell", + ".kshrc": "shell", + ".cshrc": "shell", + ".tcshrc": "shell", + ".xonshrc": "python", + ".shrc": "shell", + ".aliases": "shell", + ".functions": "shell", + ".exports": "shell", + ".direnvrc": "shell", +}; + function CodeEditPreview({ model }: SpecializedViewProps) { const fileContent = useAtomValue(model.fileContent); const setNewFileContent = useSetAtom(model.newFileContent); const fileInfo = useAtomValue(model.statFile); + const fileName = fileInfo?.path || fileInfo?.name; + + const baseName = fileName ? fileName.split("/").pop() : null; + const language = baseName && shellFileMap[baseName] ? shellFileMap[baseName] : undefined; function codeEditKeyDownHandler(e: WaveKeyboardEvent): boolean { if (checkKeyPressed(e, "Cmd:e")) { @@ -65,6 +90,8 @@ function CodeEditPreview({ model }: SpecializedViewProps) { setNewFileContent(text)} onMount={onMount}