generated from arvinxx/npm-template
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
jiangchu
committed
May 6, 2024
1 parent
7194d19
commit e712842
Showing
9 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Avatar as A, Badge, Tooltip } from 'antd'; | ||
import Color from 'color'; | ||
Check failure on line 2 in src/Awareness/Avatars/Avatar.tsx GitHub Actions / test
|
||
import { memo } from 'react'; | ||
|
||
export interface AvatarProps { | ||
/** | ||
* 用户名 | ||
*/ | ||
name: string; | ||
/** | ||
* 颜色 | ||
*/ | ||
color: string; | ||
/** | ||
* 是否激活状态 | ||
* @default false | ||
*/ | ||
active?: boolean; | ||
/** | ||
* 是否当前用户 | ||
* @default false | ||
*/ | ||
current?: boolean; | ||
/** | ||
* 是否关注了当前用户 | ||
* @default false | ||
*/ | ||
following?: boolean; | ||
/** | ||
* 点击事件回调函数 | ||
*/ | ||
onClick?: () => void; | ||
} | ||
|
||
const Avatar = memo<AvatarProps>(({ name, color, onClick, active, current, following }) => { | ||
if (!name) return <A />; | ||
|
||
const colorModel = Color(color); | ||
|
||
return ( | ||
<Tooltip title={name} showArrow={false}> | ||
<A | ||
shape={'circle'} | ||
style={{ | ||
background: color, | ||
outline: following ? `2px solid ${color}` : '', | ||
color: colorModel.isLight() ? 'black' : 'inherit', | ||
zIndex: following ? 1000 : active ? 100 : 0, | ||
filter: active ? 'none' : 'grayscale(80%)', | ||
overflow: 'initial', | ||
cursor: current ? 'inherit' : 'pointer', | ||
}} | ||
onClick={onClick} | ||
> | ||
{name.slice(0, 1)} | ||
<Badge | ||
status={active ? 'success' : 'default'} | ||
color={active ? undefined : '#d9d9d9'} | ||
style={{ position: 'absolute', left: 11, top: 11 }} | ||
/> | ||
</A> | ||
</Tooltip> | ||
); | ||
}); | ||
|
||
export default Avatar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Avatar as A } from 'antd'; | ||
import { memo, useContext } from 'react'; | ||
import { StoreContext } from '../store'; | ||
import Avatar from './Avatar'; | ||
|
||
const AvatarWrapper = ({ id, name, color, active }) => { | ||
Check failure on line 6 in src/Awareness/Avatars/index.tsx GitHub Actions / test
Check failure on line 6 in src/Awareness/Avatars/index.tsx GitHub Actions / test
Check failure on line 6 in src/Awareness/Avatars/index.tsx GitHub Actions / test
|
||
const { currentUser, followUser, setFollowUser } = useContext(StoreContext)!; | ||
|
||
const current = currentUser === id!; | ||
const following = followUser && followUser === id! ? true : false; | ||
|
||
return ( | ||
<Avatar | ||
name={name} | ||
current={current} | ||
following={following} | ||
color={color} | ||
active={active} | ||
onClick={() => { | ||
if (current) return; | ||
|
||
if (following) { | ||
setFollowUser(''); | ||
} else { | ||
setFollowUser(id); | ||
} | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
const Avatars = memo(() => { | ||
const awarenessStates = useContext(StoreContext)?.awarenessStates; | ||
|
||
return ( | ||
<A.Group> | ||
{awarenessStates && | ||
awarenessStates | ||
.filter(Boolean) | ||
.map(({ user, active }, index) => ( | ||
<AvatarWrapper active={active} key={`${user?.id}-${index}`} {...user} /> | ||
))} | ||
</A.Group> | ||
); | ||
}); | ||
|
||
export default Avatars; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { memo } from 'react'; | ||
import type { WebrtcProvider } from 'y-webrtc'; | ||
import Avatars from './Avatars'; | ||
import Cursors from './Cursors'; | ||
import { StoreContext, User, useCreateStore } from './store'; | ||
|
||
export interface AwarenessProps { | ||
provider: WebrtcProvider; | ||
avatars?: boolean; | ||
cursors?: boolean; | ||
user: Pick<User, 'color' | 'name'>; | ||
} | ||
|
||
const Awareness = memo<AwarenessProps>(({ provider, avatars = true, cursors = true, user }) => { | ||
const value = useCreateStore(provider, user); | ||
|
||
return ( | ||
<StoreContext.Provider value={value}> | ||
{cursors && <Cursors />} | ||
{avatars && <Avatars />} | ||
</StoreContext.Provider> | ||
); | ||
}); | ||
|
||
export default Awareness; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import Color from 'color'; | ||
Check failure on line 1 in src/Awareness/Cursors/Cursor.tsx GitHub Actions / test
|
||
import { memo } from 'react'; | ||
|
||
import { createStyles } from '@/theme'; | ||
import CursorSvg from './CursorSvg'; | ||
|
||
const useStyles = createStyles(({ css }) => ({ | ||
container: css` | ||
position: fixed; | ||
z-index: 5000; | ||
`, | ||
name: css` | ||
position: absolute; | ||
top: 20px; | ||
left: 20px; | ||
font-size: 12px; | ||
max-width: 96px; | ||
padding: 2px 12px; | ||
border-radius: 4px; | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
white-space: nowrap; | ||
`, | ||
})); | ||
|
||
export interface CursorProps { | ||
position: { x: number; y: number }; | ||
color: string; | ||
name: string; | ||
} | ||
|
||
const Cursor = memo<CursorProps>(({ position, color, name }) => { | ||
const { styles } = useStyles(); | ||
|
||
return ( | ||
<div | ||
className={styles.container} | ||
style={{ | ||
top: position.y, | ||
left: position.x, | ||
}} | ||
> | ||
<CursorSvg color={color} /> | ||
<div | ||
className={styles.name} | ||
style={{ | ||
backgroundColor: color, | ||
color: Color(color).isLight() ? 'black' : 'white', | ||
}} | ||
> | ||
{name} | ||
</div> | ||
</div> | ||
); | ||
}); | ||
|
||
export default Cursor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { memo } from 'react'; | ||
|
||
interface CursorProps { | ||
color: string; | ||
} | ||
|
||
const Cursor = memo<CursorProps>(({ color }) => { | ||
return ( | ||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="24"> | ||
<g fill="none" fillRule="evenodd"> | ||
<path | ||
fill={color} | ||
d="M19.208 10.282 2.007 2.269l4.068 18.916.066-.1a29.368 29.368 0 0 1 13.067-10.803Z" | ||
/> | ||
<path | ||
stroke="#FFF" | ||
strokeWidth="1.5" | ||
d="m19.483 10.954.758-.32a.365.365 0 0 0 .013-.666l-.747-.347-18.246-8.5a.143.143 0 0 0-.2.16L5.375 21.34l.18.833a.357.357 0 0 0 .645.123l.469-.704 2.458-3.694a14.326 14.326 0 0 1 6.374-5.27l3.982-1.674Z" | ||
/> | ||
</g> | ||
</svg> | ||
); | ||
}); | ||
|
||
export default Cursor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import isEqual from 'fast-deep-equal'; | ||
import { memo } from 'react'; | ||
|
||
import Cursor from './Cursor'; | ||
|
||
import type { AwarenessState } from '../store'; | ||
import { useStore } from '../store'; | ||
|
||
const Cursors = memo(() => { | ||
const awarenessStates = useStore<AwarenessState[]>( | ||
(s) => s.awarenessStates?.filter((a) => a.active && a.user.id !== s.currentUser.id), | ||
isEqual, | ||
); | ||
|
||
return ( | ||
<> | ||
{awarenessStates?.map((a) => { | ||
const { cursor, user } = a; | ||
|
||
return <Cursor key={user.id} position={cursor} color={user.color} name={user.name} />; | ||
})} | ||
</> | ||
); | ||
}); | ||
|
||
export default Cursors; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
nav: | ||
title: 组件 | ||
order: 20 | ||
group: | ||
title: 辅助 | ||
order: 10 | ||
title: Awareness 协同感知套件 | ||
--- | ||
|
||
# Awareness 协同感知套件 | ||
|
||
Awareness 代表着用户在应用内的运动和行为。用户能够实时看到其他人正在做什么。 | ||
|
||
## 代码演示 | ||
|
||
<!-- <code src="./demos/Cursor.tsx" title="Awareness.Cursor" description="协同角色的指针"></code> --> | ||
<!-- <code src="./demos/Avatar.tsx" title="Awareness.Avatar" description="协同用户"></code> --> | ||
|
||
## API | ||
|
||
### Awareness.Cursor | ||
|
||
光标属性 | ||
|
||
| 属性 | 类型 | 描述 | | ||
| -------- | -------------------------- | -------- | | ||
| position | `{ x: number; y: number }` | 光标位置 | | ||
| color | `string` | 光标颜色 | | ||
| name | `string` | 光标名称 | | ||
|
||
### Awareness.Avatar | ||
|
||
头像组件的属性 | ||
|
||
| 属性名 | 类型 | 描述 | | ||
| --------- | ------------ | ---------------------------------- | | ||
| name | `string` | 用户名 | | ||
| color | `string` | 颜色 | | ||
| active | `boolean` | 是否激活状态,默认为 `false` | | ||
| current | `boolean` | 是否当前用户,默认为 `false` | | ||
| following | `boolean` | 是否关注了当前用户,默认为 `false` | | ||
| onClick | `() => void` | 点击事件回调函数 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { nanoid } from 'nanoid'; | ||
import { createContext, useState } from 'react'; | ||
import type { Awareness } from 'y-protocols/awareness'; | ||
import { WebrtcProvider } from 'y-webrtc'; | ||
|
||
export interface User { | ||
id: string; | ||
name: string; | ||
color: string; | ||
} | ||
|
||
export declare type Position = { | ||
x: number; | ||
y: number; | ||
}; | ||
|
||
export interface AwarenessState { | ||
user: User; | ||
cursor: Position; | ||
active: boolean; | ||
} | ||
|
||
interface ProviderStore { | ||
provider: WebrtcProvider; | ||
awareness?: Awareness; | ||
currentUser: User; | ||
awarenessStates: AwarenessState[]; | ||
followUser?: string; | ||
|
||
setFollowUser: (id: string) => void; | ||
} | ||
|
||
export const useCreateStore = (provider: WebrtcProvider, user: Pick<User, 'color' | 'name'>) => { | ||
const [followUser, setFollowUser] = useState<string | undefined>(undefined); | ||
|
||
return { | ||
provider, | ||
awareness: provider.awareness, | ||
currentUser: { | ||
id: nanoid(), | ||
name: user?.name ?? 'Anonymous', | ||
color: user?.color ?? 'black', | ||
}, | ||
awarenessStates: [], | ||
followUser, | ||
setFollowUser, | ||
}; | ||
}; | ||
|
||
export const StoreContext = createContext<ProviderStore | null>(null); |