working basic live collab
This commit is contained in:
parent
a18bcf9c14
commit
17af48fe2c
3
backend/server/dist/index.js
vendored
3
backend/server/dist/index.js
vendored
@ -57,7 +57,8 @@ io.use((socket, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
return;
|
||||
}
|
||||
const sandbox = dbUserJSON.sandbox.find((s) => s.id === sandboxId);
|
||||
if (!sandbox) {
|
||||
const sharedSandboxes = dbUserJSON.usersToSandboxes.find((uts) => uts.sandboxId === sandboxId);
|
||||
if (!sandbox && !sharedSandboxes) {
|
||||
console.log("Invalid credentials.");
|
||||
next(new Error("Invalid credentials."));
|
||||
return;
|
||||
|
@ -63,8 +63,11 @@ io.use(async (socket, next) => {
|
||||
}
|
||||
|
||||
const sandbox = dbUserJSON.sandbox.find((s) => s.id === sandboxId)
|
||||
const sharedSandboxes = dbUserJSON.usersToSandboxes.find(
|
||||
(uts) => uts.sandboxId === sandboxId
|
||||
)
|
||||
|
||||
if (!sandbox) {
|
||||
if (!sandbox && !sharedSandboxes) {
|
||||
console.log("Invalid credentials.")
|
||||
next(new Error("Invalid credentials."))
|
||||
return
|
||||
|
@ -107,3 +107,38 @@
|
||||
border-radius: 4px;
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.yRemoteSelection {
|
||||
opacity: 0.5;
|
||||
background-color: var(--user-color);
|
||||
margin-right: -1px;
|
||||
}
|
||||
|
||||
/* Cursor caret */
|
||||
.yRemoteSelectionHead {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
border-left: 2px solid var(--user-color);
|
||||
}
|
||||
|
||||
/* Cursor name */
|
||||
.yRemoteSelectionHead::after {
|
||||
position: absolute;
|
||||
top: -1.4em;
|
||||
left: -2px;
|
||||
padding: 2px 6px;
|
||||
background: var(--user-color);
|
||||
color: #fff;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
border-bottom-left-radius: 0;
|
||||
line-height: normal;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
z-index: 1000;
|
||||
}
|
@ -42,7 +42,6 @@ import { TFile, TFileData, TFolder, TTab } from "./sidebar/types"
|
||||
import { User } from "@/lib/types"
|
||||
import { processFileType, validateName } from "@/lib/utils"
|
||||
import { Cursors } from "./live/cursors"
|
||||
import { Avatars } from "./live/avatars"
|
||||
|
||||
export default function CodeEditor({
|
||||
userData,
|
||||
@ -271,26 +270,31 @@ export default function CodeEditor({
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!editorRef.current) return
|
||||
let yProvider: any
|
||||
let yDoc: Y.Doc
|
||||
let binding: MonacoBinding
|
||||
|
||||
const yDoc = new Y.Doc()
|
||||
const yText = yDoc.getText("monaco")
|
||||
const yProvider: any = new LiveblocksProvider(room, yDoc)
|
||||
setProvider(yProvider)
|
||||
if (editorRef.current) {
|
||||
yDoc = new Y.Doc()
|
||||
const yText = yDoc.getText("monaco")
|
||||
yProvider = new LiveblocksProvider(room, yDoc)
|
||||
setProvider(yProvider)
|
||||
|
||||
const binding = new MonacoBinding(
|
||||
yText,
|
||||
editorRef.current.getModel() as monaco.editor.ITextModel,
|
||||
new Set([editorRef.current]),
|
||||
yProvider.awareness as Awareness
|
||||
)
|
||||
// Attach Yjs to Monaco
|
||||
binding = new MonacoBinding(
|
||||
yText,
|
||||
editorRef.current.getModel() as monaco.editor.ITextModel,
|
||||
new Set([editorRef.current]),
|
||||
yProvider.awareness as Awareness
|
||||
)
|
||||
}
|
||||
|
||||
return () => {
|
||||
yDoc.destroy()
|
||||
yProvider.destroy()
|
||||
binding.destroy()
|
||||
yDoc?.destroy()
|
||||
yProvider?.destroy()
|
||||
binding?.destroy()
|
||||
}
|
||||
}, [editorRef, room])
|
||||
}, [editorRef.current, room])
|
||||
|
||||
// connection/disconnection effect + resizeobserver
|
||||
useEffect(() => {
|
||||
@ -490,7 +494,6 @@ export default function CodeEditor({
|
||||
{tab.name}
|
||||
</Tab>
|
||||
))}
|
||||
<Avatars />
|
||||
</div>
|
||||
<div
|
||||
ref={editorContainerRef}
|
||||
|
@ -19,6 +19,7 @@ export function Cursors({ yProvider }: { yProvider: TypedLiveblocksProvider }) {
|
||||
|
||||
// On changes, update `awarenessUsers`
|
||||
function setUsers() {
|
||||
console.log("SET USERS")
|
||||
setAwarenessUsers(
|
||||
Array.from(yProvider.awareness.getStates()) as AwarenessList
|
||||
)
|
||||
|
@ -10,6 +10,7 @@ import { Button } from "@/components/ui/button"
|
||||
import { useState } from "react"
|
||||
import EditSandboxModal from "./edit"
|
||||
import ShareSandboxModal from "./share"
|
||||
import { Avatars } from "../live/avatars"
|
||||
|
||||
export default function Navbar({
|
||||
userData,
|
||||
@ -58,6 +59,8 @@ export default function Navbar({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<Avatars />
|
||||
|
||||
<Button variant="outline" onClick={() => setIsShareOpen(true)}>
|
||||
<Users className="w-4 h-4 mr-2" />
|
||||
Share
|
||||
|
Loading…
x
Reference in New Issue
Block a user