Skip to content

Commit

Permalink
settings
Browse files Browse the repository at this point in the history
  • Loading branch information
ClanEver committed Jan 14, 2025
1 parent 85acbe5 commit 38d5613
Show file tree
Hide file tree
Showing 14 changed files with 538 additions and 252 deletions.
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"semi": false,
"singleQuote": true,
"jsxSingleQuote": true,
"tabWidth": 4
}
18 changes: 0 additions & 18 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/* :root {
--background: #ffffff;
--foreground: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
color: var(--foreground);
background: var(--background);
font-family: Arial, Helvetica, sans-serif;
} */
29 changes: 16 additions & 13 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
import { ThemeProvider } from 'next-themes'
import { FloatingMenu } from '@/components/FloatingMenu'
import type { Metadata } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
import './globals.css'

const geistSans = Geist({
variable: '--font-geist-sans',
subsets: ['latin']
subsets: ['latin'],
})

const geistMono = Geist_Mono({
variable: '--font-geist-mono',
subsets: ['latin']
subsets: ['latin'],
})

export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app'
title: 'co-coding',
description: 'Co-coding with your friends...?',
}

export default function RootLayout({
children
children,
}: Readonly<{
children: React.ReactNode;
children: React.ReactNode
}>) {
return (
<html lang='en'>
<body
className={ `${ geistSans.variable } ${ geistMono.variable } antialiased` }
>
{ children }
<FloatingMenu />
</body>
<html lang="en" suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<ThemeProvider>
{children}
<FloatingMenu />
</ThemeProvider>
</body>
</html>
)
}
40 changes: 28 additions & 12 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,50 @@

import { useState } from 'react'
import { useRouter } from 'next/navigation'
import SettingPanel from '@/components/SettingPanel'
import { SettingDialog } from '@/components/SettingDialog'
import { Button, Input } from 'react-daisyui'

export default function Home() {
const [roomId, setRoomId] = useState('')
const [isSettingDialogOpen, setIsSettingDialogOpen] = useState(false)
const [isJoining, setIsJoining] = useState(false)
const router = useRouter()

const handleJoinRoom = () => {
if (roomId) {
router.push(`/room/${roomId}`)
setIsJoining(true)
}
}

return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<h1 className="text-4xl font-bold mb-8">co-coding</h1>
<div className="flex flex-col items-center space-y-4">
<input
type="text"
<main className='flex min-h-screen flex-col items-center justify-center p-24'>
<div className='flex flex-col items-center space-y-6'>
<h1 className='text-4xl font-bold'>co-coding</h1>
<Input
type='text'
value={roomId}
onChange={(e) => setRoomId(e.target.value)}
placeholder="Enter room id"
className="input input-bordered w-64"
placeholder='Enter room id'
className='w-64'
/>
<SettingPanel />
<button onClick={handleJoinRoom} className="btn btn-primary">
Join Room
</button>
<div className='flex space-x-4'>
<Button onClick={() => setIsSettingDialogOpen(true)}>
Settings
</Button>
<Button
onClick={handleJoinRoom}
className='btn-primary'
loading={isJoining}
>
Join Room
</Button>
</div>
</div>
<SettingDialog
isOpen={isSettingDialogOpen}
onClose={() => setIsSettingDialogOpen(false)}
/>
</main>
)
}
20 changes: 3 additions & 17 deletions common/icons.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
import { FaPalette, FaGear } from 'react-icons/fa6'
export const Icons = {
Settings: (props: React.ComponentProps<'svg'>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
className="h-5 w-5"
{...props}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
),
Settings: FaGear,
Theme: FaPalette,
}
89 changes: 37 additions & 52 deletions components/CollaborativeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import CodeMirror, {
Extension,
keymap,
ReactCodeMirrorRef,
ViewUpdate
ViewUpdate,
} from '@uiw/react-codemirror'
// import { vscodeDark } from '@uiw/codemirror-theme-vscode'
import { insertNewlineAndIndent } from '@codemirror/commands'
import { Button, Select } from 'react-daisyui'
import { useSettingsStore } from './SettingPanel' // 引入 useSettingsStore

const BACKEND_URL =
process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:3001'
Expand All @@ -20,17 +22,16 @@ interface CollaborativeEditorProps {
roomId: string | undefined
}


export default function CollaborativeEditor({
roomId
roomId,
}: CollaborativeEditorProps) {
const [editorContent, setEditorContent] = useState('')
const [isReadOnly, setIsReadOnly] = useState(false)
const [userId, setUserId] = useState<number | null>(null)
const [editingUser, setEditingUser] = useState<number | null>(null)
const [isJoined, setIsJoined] = useState(false)
const [error, setError] = useState<string | null>(null)
const [selectedLanguage, setSelectedLanguage] = useState(languages[0])
const { settings } = useSettingsStore() // 使用 useSettingsStore 获取语言设置
const [languageExtension, setLanguageExtension] = useState<Extension>(null)
const socketRef = useRef<Socket>(null)
const editorRef = useRef<ReactCodeMirrorRef>(null)
Expand Down Expand Up @@ -76,10 +77,13 @@ export default function CollaborativeEditor({
}, [roomId, userId])

useEffect(() => {
selectedLanguage.extension().then((ext) => {
setLanguageExtension(ext)
})
}, [selectedLanguage])
languages
.find((lang) => lang['name'] === settings.language) // 使用 settings.language
?.extension()
.then((ext) => {
setLanguageExtension(ext)
})
}, [settings.language]) // 依赖 settings.language

const handleEditorChange = (value: string) => {
if (roomId && !isReadOnly) {
Expand All @@ -88,7 +92,7 @@ export default function CollaborativeEditor({
socketRef.current?.emit('contentChange', {
roomId,
content: value,
lastChar
lastChar,
})
}
}
Expand All @@ -110,15 +114,15 @@ export default function CollaborativeEditor({
if (!isJoined) {
return (
<div className='flex items-center justify-center h-screen'>
<p className='text-xl'>Joining room { roomId }...</p>
<p className='text-xl'>Joining room {roomId}...</p>
</div>
)
}

if (error) {
return (
<div className='flex items-center justify-center h-screen'>
<p className='text-xl text-red-500'>{ error }</p>
<p className='text-xl text-red-500'>{error}</p>
</div>
)
}
Expand All @@ -131,7 +135,7 @@ export default function CollaborativeEditor({

if (head !== docLength || anchor !== docLength) {
view.dispatch({
selection: { anchor: docLength, head: docLength }
selection: { anchor: docLength, head: docLength },
})
}
}
Expand All @@ -146,39 +150,20 @@ export default function CollaborativeEditor({
// 禁止粘贴
EditorView.domEventHandlers({ paste: () => true }),
// 快捷键仅保留换行
keymap.of([{ key: 'Enter', run: insertNewlineAndIndent }])
keymap.of([{ key: 'Enter', run: insertNewlineAndIndent }]),
]

return (
<div className='w-full h-[600px]' onPaste={ (e) => e.preventDefault() }>
<div className='mb-4'>
<select
value={ selectedLanguage.name }
onChange={ (e) =>
setSelectedLanguage(
languages.find(
(lang) => lang.name === e.target.value
) || languages[0]
)
}
className='px-4 py-2 border rounded'
>
{ languages.map((lang) => (
<option key={ lang.name } value={ lang.name }>
{ lang.name }
</option>
)) }
</select>
</div>
<div className='w-full h-[600px]' onPaste={(e) => e.preventDefault()}>
<CodeMirror
ref={ editorRef }
value={ editorContent }
ref={editorRef}
value={editorContent}
height='50vh'
// theme={vscodeDark}
extensions={ extensions }
onChange={ handleEditorChange }
editable={ !isReadOnly }
basicSetup={ {
extensions={extensions}
onChange={handleEditorChange}
editable={!isReadOnly}
basicSetup={{
history: false,
drawSelection: false,
defaultKeymap: false,
Expand All @@ -194,25 +179,25 @@ export default function CollaborativeEditor({
searchKeymap: false,
foldKeymap: false,
lintKeymap: false,
tabSize: 4
} }
onUpdate={ handleUpdate }
tabSize: 4,
}}
onUpdate={handleUpdate}
/>
<div className='mt-4 flex justify-between items-center'>
<p>
You are User { userId } in Room { roomId }.
{ isReadOnly
? `User ${ editingUser } is currently editing.`
: 'You can edit now. Press Enter to switch control.' }
You are User {userId} in Room {roomId}.
{isReadOnly
? `User ${editingUser} is currently editing.`
: 'You can edit now. Press Enter to switch control.'}
</p>
{ isReadOnly && (
<button
onClick={ requestEditPermission }
className='px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600'
{isReadOnly && (
<Button
onClick={requestEditPermission}
className='px-4 py-2 rounded btn-primary'
>
Request Edit Permission
</button>
) }
</Button>
)}
</div>
</div>
)
Expand Down
Loading

0 comments on commit 38d5613

Please sign in to comment.