File size: 3,712 Bytes
c10f8f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4fb6d26
 
 
 
 
 
 
 
 
c10f8f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4fb6d26
e0eec0d
4fb6d26
 
 
e0eec0d
 
c10f8f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"use client";
import { useMemo, useRef, useState } from "react";
import { useCopyToClipboard } from "react-use";
import { CopyIcon } from "lucide-react";
import { toast } from "sonner";
import classNames from "classnames";
import { editor } from "monaco-editor";
import Editor from "@monaco-editor/react";

import { useEditor } from "@/hooks/useEditor";
import { Header } from "@/components/editor/header";
import { useAi } from "@/hooks/useAi";

import { ListPages } from "./pages";
import { AskAi } from "./ask-ai";
import { Preview } from "./preview";
import Loading from "../loading";

export const AppEditor = ({
  namespace,
  repoId,
  isNew = false,
}: {
  namespace?: string;
  repoId?: string;
  isNew?: boolean;
}) => {
  const {
    project,
    setPages,
    files,
    currentPageData,
    currentTab,
    currentCommit,
  } = useEditor(namespace, repoId);
  const { isAiWorking } = useAi();
  const [, copyToClipboard] = useCopyToClipboard();

  const monacoRef = useRef<any>(null);
  const editor = useRef<HTMLDivElement>(null);
  const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);

  return (
    <section className="h-screen w-full bg-neutral-950 flex flex-col">
      <Header />
      <main className="bg-neutral-950 flex-1 max-lg:flex-col flex w-full relative">
        <div
          ref={editor}
          className={classNames(
            "bg-neutral-900 relative flex h-full max-h-[calc(100dvh-47px)] w-full flex-col lg:max-w-[600px] transition-all duration-200",
            {
              "max-lg:hidden lg:!w-[0px] overflow-hidden":
                currentTab !== "chat",
            }
          )}
        >
          <ListPages />
          <CopyIcon
            className="size-4 absolute top-14 right-5 text-neutral-500 hover:text-neutral-300 z-2 cursor-pointer"
            onClick={() => {
              copyToClipboard(currentPageData.html);
              toast.success("HTML copied to clipboard!");
            }}
          />
          <Editor
            defaultLanguage="html"
            theme="vs-dark"
            loading={<Loading overlay={false} />}
            className="h-full absolute left-0 top-0 lg:min-w-[600px]"
            options={{
              colorDecorators: true,
              fontLigatures: true,
              theme: "vs-dark",
              minimap: { enabled: false },
              scrollbar: {
                horizontal: "hidden",
              },
              wordWrap: "on",
              readOnly: !!isAiWorking || !!currentCommit,
              readOnlyMessage: {
                value: currentCommit
                  ? "You can't edit the code, as this is an old version of the project."
                  : "Wait for DeepSite to finish working...",
                isTrusted: true,
              },
            }}
            value={currentPageData.html}
            onChange={(value) => {
              const newValue = value ?? "";
              setPages((prev) =>
                prev.map((page) =>
                  page.path === currentPageData.path
                    ? { ...page, html: newValue }
                    : page
                )
              );
            }}
            onMount={(editor, monaco) => {
              editorRef.current = editor;
              monacoRef.current = monaco;
            }}
          />
          <AskAi
            project={project}
            files={files}
            isNew={isNew}
            onScrollToBottom={() => {
              editorRef.current?.revealLine(
                editorRef.current?.getModel()?.getLineCount() ?? 0
              );
            }}
          />
        </div>
        <Preview isNew={isNew} />
      </main>
    </section>
  );
};