diff --git a/components/BleedThroughImage.tsx b/components/BleedThroughImage.tsx index 1d55a40b..933243b7 100644 --- a/components/BleedThroughImage.tsx +++ b/components/BleedThroughImage.tsx @@ -12,6 +12,7 @@ export function BleedThroughImage({ dimensions, lqip, className, + alt, ...props }: BleedThroughImageProps) { return ( @@ -22,6 +23,7 @@ export function BleedThroughImage({ height={dimensions.height} unoptimized {...props} + alt="" /> {alt ) diff --git a/components/LiveAvatars.tsx b/components/LiveAvatars.tsx index c4b24a5e..8b7e91b1 100644 --- a/components/LiveAvatars.tsx +++ b/components/LiveAvatars.tsx @@ -1,92 +1,92 @@ -import { AnimatePresence, motion } from 'framer-motion' -import Image from 'next/image' -import React from 'react' -import Balancer from 'react-wrap-balancer' - -import { Tooltip } from '~/components/ui/Tooltip' -import { usePostStore } from '~/lib/store' - -const MAX_OTHERS = 7 -const MAX_AVATARS = 8 - -const animationProps = { - initial: { width: 0, transformOrigin: 'left', opacity: 0 }, - animate: { width: 'auto', height: 'auto', opacity: 1 }, - exit: { width: 0, opacity: 0 }, - transition: { - type: 'spring', - damping: 18, - mass: 1, - stiffness: 200, - restSpeed: 0.01, - }, -} -export function LiveAvatars() { - const others = usePostStore((state) => state.liveblocks.others) - const hasMore = others.length > MAX_OTHERS - const shownOthers = hasMore ? others.slice(0, MAX_OTHERS) : others - - const [tooltipOpen, setTooltipOpen] = React.useState(false) - - return ( - - - -
- - {hasMore && ( - - - - +{others.length - MAX_OTHERS} - - - - )} - {shownOthers.map((other) => ( - - - - ))} - -
-
- - {tooltipOpen && ( - - - - - 其他 {others.length} 个小伙伴也在阅读 - - - - - )} - -
-
- ) -} +// import { AnimatePresence, motion } from 'framer-motion' +// import Image from 'next/image' +// import React from 'react' +// import Balancer from 'react-wrap-balancer' +// +// import { Tooltip } from '~/components/ui/Tooltip' +// import { usePostStore } from '~/lib/store' +// +// const MAX_OTHERS = 7 +// const MAX_AVATARS = 8 +// +// const animationProps = { +// initial: { width: 0, transformOrigin: 'left', opacity: 0 }, +// animate: { width: 'auto', height: 'auto', opacity: 1 }, +// exit: { width: 0, opacity: 0 }, +// transition: { +// type: 'spring', +// damping: 18, +// mass: 1, +// stiffness: 200, +// restSpeed: 0.01, +// }, +// } +// export function LiveAvatars() { +// const others = usePostStore((state) => state.liveblocks.others) +// const hasMore = others.length > MAX_OTHERS +// const shownOthers = hasMore ? others.slice(0, MAX_OTHERS) : others +// +// const [tooltipOpen, setTooltipOpen] = React.useState(false) +// +// return ( +// +// +// +//
+// +// {hasMore && ( +// +// +// +// +{others.length - MAX_OTHERS} +// +// +// +// )} +// {shownOthers.map((other) => ( +// +// +// +// ))} +// +//
+//
+// +// {tooltipOpen && ( +// +// +// +// +// 其他 {others.length} 个小伙伴也在阅读 +// +// +// +// +// )} +// +//
+//
+// ) +// } diff --git a/components/Multiplayer.tsx b/components/Multiplayer.tsx index c9737cd8..a83d9f40 100644 --- a/components/Multiplayer.tsx +++ b/components/Multiplayer.tsx @@ -1,288 +1,288 @@ -'use client' - -import { Portal } from '@headlessui/react' -import { clsxm } from '@zolplay/utils' -import { AnimatePresence, motion } from 'framer-motion' -import { useAtom } from 'jotai/index' -import { atomWithStorage } from 'jotai/utils' -import React, { Fragment } from 'react' -import Balancer from 'react-wrap-balancer' - -import { CloudIcon, CursorClickIcon, CursorIcon, UFOIcon } from '~/assets' -import { Tooltip } from '~/components/ui/Tooltip' -import { usePresenceStore } from '~/lib/store' - -const enabledMultiplayerAtom = atomWithStorage( - '__cali_so.enabled_multiplayer', - false -) - -export function Multiplayer() { - const [enabledMultiplayer, setEnabledMultiplayer] = useAtom( - enabledMultiplayerAtom - ) - const { - liveblocks: { enterRoom, leaveRoom, connection }, - roomId, - } = usePresenceStore() - React.useEffect(() => { - if (roomId && enabledMultiplayer) { - enterRoom(roomId) - } - - return () => { - if (roomId) { - leaveRoom(roomId) - } - } - }, [enabledMultiplayer, enterRoom, leaveRoom, roomId]) - - const [tooltipOpen, setTooltipOpen] = React.useState(false) - - return ( - <> - - - {roomId && ( - - - - )} - - {tooltipOpen && ( - - - - - {connection === 'open' && '已显示多人光标'} - {connection === 'closed' && '点击显示多人光标'} - {connection === 'connecting' && '连接中...'} - {connection === 'failed' && '连接失败'} - - - - - )} - - - - - {enabledMultiplayer && } - - ) -} - -function useLiveCursors() { - const setCursor = usePresenceStore((state) => state.setCursor) - - React.useEffect(() => { - const scroll = { - x: window.scrollX, - y: window.scrollY, - } - - let lastPosition: { x: number; y: number } | null = null - - function transformPosition( - cursor: { x: number; y: number }, - down?: boolean - ) { - return { - x: cursor.x / window.innerWidth, - y: cursor.y, - isDown: down, - } - } - - function onPointerMove(event: PointerEvent) { - const position = { - x: event.pageX, - y: event.pageY, - } - lastPosition = position - setCursor(transformPosition(position)) - } - - function onPointerLeave() { - lastPosition = null - setCursor(null) - } - - function onPointerDown(event: PointerEvent) { - const position = { - x: event.pageX, - y: event.pageY, - } - lastPosition = position - setCursor(transformPosition(position, true)) - } - - function onPointerUp() { - if (lastPosition) { - setCursor(transformPosition(lastPosition)) - } - } - - function onDocumentScroll() { - if (lastPosition) { - const offsetX = window.scrollX - scroll.x - const offsetY = window.scrollY - scroll.y - const position = { - x: lastPosition.x + offsetX, - y: lastPosition.y + offsetY, - } - lastPosition = position - setCursor(transformPosition(position)) - } - scroll.x = window.scrollX - scroll.y = window.scrollY - } - - document.addEventListener('scroll', onDocumentScroll) - document.addEventListener('pointermove', onPointerMove) - document.addEventListener('pointerleave', onPointerLeave) - document.addEventListener('pointerdown', onPointerDown) - document.addEventListener('pointerup', onPointerUp) - - return () => { - document.removeEventListener('scroll', onDocumentScroll) - document.removeEventListener('pointermove', onPointerMove) - document.removeEventListener('pointerleave', onPointerLeave) - document.removeEventListener('pointerdown', onPointerDown) - document.removeEventListener('pointerup', onPointerUp) - } - }, [setCursor]) - - const others = usePresenceStore((state) => state.liveblocks.others) - - const cursors = [] - - for (const { connectionId, presence } of others) { - if (presence.cursor) { - const { x, y, isDown } = presence.cursor as { - x: number - y: number - isDown?: boolean - } - cursors.push({ - x: x * window.innerWidth, - y, - isDown, - connectionId, - }) - } - } - - return cursors -} - -const COLORS = [ - '#64748b', - '#ef4444', - '#f97316', - '#f59e0b', - '#eab308', - '#84cc16', - '#22c55e', - '#10b981', - '#14b8a6', - '#06b6d4', - '#0ea5e9', - '#3b82f6', - '#6366f1', - '#8b5cf6', - '#a855f7', - '#d946ef', - '#ec4899', - '#f43f5e', -] -function Cursors() { - const cursors = useLiveCursors() - - return ( - - {cursors.map(({ x, y, isDown, connectionId }) => ( - - ))} - - ) -} - -type CursorProps = { - color: string - x: number - y: number - isDown?: boolean -} - -function Cursor({ color, x, y, isDown }: CursorProps) { - return ( - <> - - - - {isDown && ( - - )} - - - - - ) -} +// 'use client' +// +// import { Portal } from '@headlessui/react' +// import { clsxm } from '@zolplay/utils' +// import { AnimatePresence, motion } from 'framer-motion' +// import { useAtom } from 'jotai/index' +// import { atomWithStorage } from 'jotai/utils' +// import React, { Fragment } from 'react' +// import Balancer from 'react-wrap-balancer' +// +// import { CloudIcon, CursorClickIcon, CursorIcon, UFOIcon } from '~/assets' +// import { Tooltip } from '~/components/ui/Tooltip' +// import { usePresenceStore } from '~/lib/store' +// +// const enabledMultiplayerAtom = atomWithStorage( +// '__cali_so.enabled_multiplayer', +// false +// ) +// +// export function Multiplayer() { +// const [enabledMultiplayer, setEnabledMultiplayer] = useAtom( +// enabledMultiplayerAtom +// ) +// const { +// liveblocks: { enterRoom, leaveRoom, connection }, +// roomId, +// } = usePresenceStore() +// React.useEffect(() => { +// if (roomId && enabledMultiplayer) { +// enterRoom(roomId) +// } +// +// return () => { +// if (roomId) { +// leaveRoom(roomId) +// } +// } +// }, [enabledMultiplayer, enterRoom, leaveRoom, roomId]) +// +// const [tooltipOpen, setTooltipOpen] = React.useState(false) +// +// return ( +// <> +// +// +// {roomId && ( +// +// +// +// )} +// +// {tooltipOpen && ( +// +// +// +// +// {connection === 'open' && '已显示多人光标'} +// {connection === 'closed' && '点击显示多人光标'} +// {connection === 'connecting' && '连接中...'} +// {connection === 'failed' && '连接失败'} +// +// +// +// +// )} +// +// +// +// +// {enabledMultiplayer && } +// +// ) +// } +// +// function useLiveCursors() { +// const setCursor = usePresenceStore((state) => state.setCursor) +// +// React.useEffect(() => { +// const scroll = { +// x: window.scrollX, +// y: window.scrollY, +// } +// +// let lastPosition: { x: number; y: number } | null = null +// +// function transformPosition( +// cursor: { x: number; y: number }, +// down?: boolean +// ) { +// return { +// x: cursor.x / window.innerWidth, +// y: cursor.y, +// isDown: down, +// } +// } +// +// function onPointerMove(event: PointerEvent) { +// const position = { +// x: event.pageX, +// y: event.pageY, +// } +// lastPosition = position +// setCursor(transformPosition(position)) +// } +// +// function onPointerLeave() { +// lastPosition = null +// setCursor(null) +// } +// +// function onPointerDown(event: PointerEvent) { +// const position = { +// x: event.pageX, +// y: event.pageY, +// } +// lastPosition = position +// setCursor(transformPosition(position, true)) +// } +// +// function onPointerUp() { +// if (lastPosition) { +// setCursor(transformPosition(lastPosition)) +// } +// } +// +// function onDocumentScroll() { +// if (lastPosition) { +// const offsetX = window.scrollX - scroll.x +// const offsetY = window.scrollY - scroll.y +// const position = { +// x: lastPosition.x + offsetX, +// y: lastPosition.y + offsetY, +// } +// lastPosition = position +// setCursor(transformPosition(position)) +// } +// scroll.x = window.scrollX +// scroll.y = window.scrollY +// } +// +// document.addEventListener('scroll', onDocumentScroll) +// document.addEventListener('pointermove', onPointerMove) +// document.addEventListener('pointerleave', onPointerLeave) +// document.addEventListener('pointerdown', onPointerDown) +// document.addEventListener('pointerup', onPointerUp) +// +// return () => { +// document.removeEventListener('scroll', onDocumentScroll) +// document.removeEventListener('pointermove', onPointerMove) +// document.removeEventListener('pointerleave', onPointerLeave) +// document.removeEventListener('pointerdown', onPointerDown) +// document.removeEventListener('pointerup', onPointerUp) +// } +// }, [setCursor]) +// +// const others = usePresenceStore((state) => state.liveblocks.others) +// +// const cursors = [] +// +// for (const { connectionId, presence } of others) { +// if (presence.cursor) { +// const { x, y, isDown } = presence.cursor as { +// x: number +// y: number +// isDown?: boolean +// } +// cursors.push({ +// x: x * window.innerWidth, +// y, +// isDown, +// connectionId, +// }) +// } +// } +// +// return cursors +// } +// +// const COLORS = [ +// '#64748b', +// '#ef4444', +// '#f97316', +// '#f59e0b', +// '#eab308', +// '#84cc16', +// '#22c55e', +// '#10b981', +// '#14b8a6', +// '#06b6d4', +// '#0ea5e9', +// '#3b82f6', +// '#6366f1', +// '#8b5cf6', +// '#a855f7', +// '#d946ef', +// '#ec4899', +// '#f43f5e', +// ] +// function Cursors() { +// const cursors = useLiveCursors() +// +// return ( +// +// {cursors.map(({ x, y, isDown, connectionId }) => ( +// +// ))} +// +// ) +// } +// +// type CursorProps = { +// color: string +// x: number +// y: number +// isDown?: boolean +// } +// +// function Cursor({ color, x, y, isDown }: CursorProps) { +// return ( +// <> +// +// +// +// {isDown && ( +// +// )} +// +// +// +// +// ) +// }