Skip to content

Commit

Permalink
✨ feat: add awareness data change
Browse files Browse the repository at this point in the history
  • Loading branch information
jiangchu committed May 7, 2024
1 parent 1fcb4c1 commit 034d953
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 9 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"y-webrtc": "^10.3.0",
"yjs": "^13",
"zustand": "^4.4.1",
"zustand-middleware-yjs": "^1.3.1",
"zustand-utils": "^1.3.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/Awareness/Awareness.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { memo } from 'react';
import type { WebrtcProvider } from 'y-webrtc';
import Avatars from './Avatars';
// import Cursors from './Cursors';
import Cursors from './Cursors';
import { StoreContext, User, useCreateStore } from './store';

export interface AwarenessProps {
provider: WebrtcProvider;
avatars?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/Awareness/Cursors/Cursor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Color from 'color';

Check failure on line 1 in src/Awareness/Cursors/Cursor.tsx

View workflow job for this annotation

GitHub Actions / test

Could not find a declaration file for module 'color'. '/home/runner/work/pro-flow/pro-flow/node_modules/.pnpm/[email protected]/node_modules/color/index.js' implicitly has an 'any' type.
import { memo } from 'react';

import { createStyles } from '@/theme';
// import { createStyles } from '@/theme';
import CursorSvg from './CursorSvg';

const useStyles = createStyles(({ css }) => ({

Check failure on line 7 in src/Awareness/Cursors/Cursor.tsx

View workflow job for this annotation

GitHub Actions / test

Cannot find name 'createStyles'.

Check failure on line 7 in src/Awareness/Cursors/Cursor.tsx

View workflow job for this annotation

GitHub Actions / test

Binding element 'css' implicitly has an 'any' type.
Expand Down
16 changes: 10 additions & 6 deletions src/Awareness/Cursors/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { memo, useContext } from 'react';

import { Awareness } from '@ant-design/pro-editor';
import { StoreContext } from '../store';
import Cursor from './Cursor';

// import { useStore } from '../store';

Expand All @@ -11,14 +11,18 @@ const Cursors = memo(() => {
// isEqual,
// );

const { awarenessStates } = useContext(StoreContext)!;
const { awarenessStates, currentUser } = useContext(StoreContext)!;
return (
<>
{awarenessStates?.map((a) => {
const { cursor, user } = a;
{awarenessStates
.filter((a) => a.active && a.user.id !== currentUser.id)
?.map((a) => {
const { cursor, user } = a;

return <Cursor key={user.id} position={cursor} color={user.color} name={user.name} />;
})}
return (
<Awareness.Cursor key={user.id} position={cursor} color={user.color} name={user.name} />
);
})}
</>
);
});
Expand Down
54 changes: 54 additions & 0 deletions src/Awareness/demos/SessionForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ColorPicker, Form, Input, Modal } from 'antd';
import React from 'react';

interface Values {
name: string;
color: string;
}

interface SessionFormProps {
open: boolean;
onCreate: (values: Values) => void;
onCancel: () => void;
}

export const SessionForm: React.FC<SessionFormProps> = ({ open, onCreate, onCancel }) => {
const [form] = Form.useForm();
return (
<Modal
open={open}
title="Join Session"
okText="Join"
onCancel={onCancel}
onOk={() => {
form
.validateFields()
.then(({ color, name }) => {
form.resetFields();
const colorHex = typeof color === 'string' ? color : color?.toHexString();
onCreate({ color: colorHex, name });
})
.catch((info) => {
console.log('Validate Failed:', info);
});
}}
>
<Form form={form} layout="vertical" name="form_in_modal" initialValues={{ color: '#1677FF' }}>
<Form.Item
name="name"
label="Name"
rules={[{ required: true, message: 'Please input your name' }]}
>
<Input />
</Form.Item>
<Form.Item
name="color"
label="Color"
rules={[{ required: true, message: 'Please select your color' }]}
>
<ColorPicker format="hex" />
</Form.Item>
</Form>
</Modal>
);
};
86 changes: 86 additions & 0 deletions src/Awareness/demos/demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* title: 实时协同
* description: 打开多个窗口,点击 "Join" 加入协作
*/

import { Button, Divider, Input } from 'antd';
import { memo, useContext, useMemo, useState } from 'react';
import { WebrtcProvider } from 'y-webrtc';
// import { SessionForm } from './SessionForm';
import Awareness from '../Awareness';
import { SessionForm } from './SessionForm';
import { StoreContext, doc } from './store';

const App = memo(() => {
// const store = useStore((state) => ({
// count: state.count,
// increment: state.increment,
// updateText: state.updateText,
// text: state.text,
// }));
const { count, increment, updateText, text } = useContext(StoreContext)!;

return (
<>
<Divider />
<Input
value={text}
onChange={(e) => {
updateText(e.target.value);
}}
/>
<Divider />
<p>Count: {count}</p>
<Button onClick={increment}>To the Moon!</Button>
</>
);
});

const Container = () => {
const [user, setUser] = useState(null);
const [open, setOpen] = useState(false);
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const p = useMemo(() => {
console.log(doc);
return new WebrtcProvider('test1-room', doc);
}, []);

const onCreate = (values) => {

Check failure on line 49 in src/Awareness/demos/demo.tsx

View workflow job for this annotation

GitHub Actions / test

Parameter 'values' implicitly has an 'any' type.
setUser(values);
setOpen(false);
};

return (
<StoreContext.Provider
value={{
count,
text,
increment: () => setCount(count + 1),
updateText: (text) => setText(text),
}}
>
{user ? null : (
<Button
type="primary"
onClick={() => {
setOpen(true);
}}
>
Join
</Button>
)}
<SessionForm
open={open}
onCreate={onCreate}
onCancel={() => {
setOpen(false);
}}
/>
{user ? <Awareness provider={p} user={user} /> : null}
<App />
</StoreContext.Provider>
);
};

export default memo(Container);
14 changes: 14 additions & 0 deletions src/Awareness/demos/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createContext } from 'react';
import * as Y from 'yjs';
export { default as yjsMiddleware } from 'zustand-middleware-yjs';

interface Store {
count: number;
text: string;
increment: () => void;
updateText: (text: string) => void;
}

export const doc = new Y.Doc();

export const StoreContext = createContext<Store | null>(null);
3 changes: 2 additions & 1 deletion src/Awareness/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Awareness 代表着用户在应用内的运动和行为。用户能够实时看

## 代码演示

<!-- <code src="./demos/Cursor.tsx" title="Awareness.Cursor" description="协同角色的指针"></code> -->
<code src="./demos/demo.tsx" title="Awareness.Cursor" description="协同角色的指针"></code>

<!-- <code src="./demos/Avatar.tsx" title="Awareness.Avatar" description="协同用户"></code> -->

## API
Expand Down

0 comments on commit 034d953

Please sign in to comment.