Compare commits

...

3 Commits

Author SHA1 Message Date
vel 370e056a2b
(doc): readme changes 2022-02-02 16:13:08 -08:00
vel 55e5136e88
Merge pull request #1 from QPixel/refactor/main
Refactor main so it works now
2022-02-02 16:04:12 -08:00
vel 2586e60f0c
finally fixed player 2022-02-01 17:07:56 -08:00
8 changed files with 84 additions and 47 deletions

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# watchtogether
This was a project that I created over 7 days of working while having covid :)
I probably won't do much with the codebase, but enjoy how I basically figured out how to sync video streams with multiple clients
## The Stack
- frontend
- next js
- websockets
- chakra-ui
- react-player
- backend
- go
- gorilla/websockets
## how 2 deploy?
you don't

View File

@ -6,7 +6,6 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="8a64704d-5500-41a6-aa4c-e275933fc58c" name="Changes" comment=""> <list default="true" id="8a64704d-5500-41a6-aa4c-e275933fc58c" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/components/Player.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/components/Player.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/pages/player.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/pages/player.tsx" afterDir="false" /> <change beforePath="$PROJECT_DIR$/../frontend/src/pages/player.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/pages/player.tsx" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />

1
backend/README.md Normal file
View File

@ -0,0 +1 @@
# backend

View File

@ -1,39 +1 @@
# Example app with [chakra-ui](https://github.com/chakra-ui/chakra-ui) and TypeScript # frontend
This example features how to use [chakra-ui](https://github.com/chakra-ui/chakra-ui) as the component library within a Next.js app with TypeScript.
Next.js and chakra-ui have built-in TypeScript declarations, so we'll get autocompletion for their modules straight away.
We are connecting the Next.js `_app.js` with `chakra-ui`'s Provider and theme so the pages can have app-wide dark/light mode. We are also creating some components which shows the usage of `chakra-ui`'s style props.
## Preview
Preview the example live on [StackBlitz](http://stackblitz.com/):
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-chakra-ui-typescript)
## Deploy your own
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-chakra-ui-typescript&project-name=with-chakra-ui-typescript&repository-name=with-chakra-ui-typescript)
## How to use
### Using `create-next-app`
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
```bash
npx create-next-app --example with-chakra-ui-typescript with-chakra-ui-typescript-app
# or
yarn create next-app --example with-chakra-ui-typescript with-chakra-ui-typescript-app
```
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
## Notes
Chakra has supported Gradients and RTL in `v1.1`. To utilize RTL, [add RTL direction and swap](https://chakra-ui.com/docs/features/rtl-support).
If you don't have multi-direction app, you should make `<Html lang="ar" dir="rtl">` inside `_document.ts`.

View File

@ -73,9 +73,7 @@ const Player = forwardRef<ReactPlayer, ReactPlayerProps>((props, ref) => {
width="100%" width="100%"
height="100%" height="100%"
config={config} config={config}
controls
ref={ref} ref={ref}
playing={false}
{...props} {...props}
/> />
</Box> </Box>

View File

@ -14,6 +14,9 @@ const useWS = ({ user }: useWSProps): PlayerSocket | null => {
// todo checkout usecallback // todo checkout usecallback
const [socket, setSocket] = useState<PlayerSocket>(null); const [socket, setSocket] = useState<PlayerSocket>(null);
useEffect(() => { useEffect(() => {
if (socket !== null) {
return;
}
let internalSocket = new PlayerSocket(user); let internalSocket = new PlayerSocket(user);
setSocket(internalSocket); setSocket(internalSocket);
return () => { return () => {

View File

@ -2,7 +2,7 @@ import IUser from "./IUser";
interface IdentityData { interface IdentityData {
admin?: boolean; admin?: boolean;
controller?: boolean; hasController?: boolean;
clientID?: string; clientID?: string;
playlist?: string; playlist?: string;
playhead?: number; playhead?: number;

View File

@ -8,10 +8,12 @@ import { Container } from "../components/Container";
import Player from "../components/Player"; import Player from "../components/Player";
import useWS from "../hooks/useWS"; import useWS from "../hooks/useWS";
import IdentityData from "../interfaces/Identity"; import IdentityData from "../interfaces/Identity";
import { MessageTypes } from "../interfaces/IMessage";
import SetPlayheadEvent from "../interfaces/Playhead"; import SetPlayheadEvent from "../interfaces/Playhead";
import SocketEvents from "../interfaces/SocketEvents"; import SocketEvents from "../interfaces/SocketEvents";
import { isBrowser } from "../util"; import { isBrowser } from "../util";
import PlayerSocket from "../ws/websocket"; import Message from "../util/Message";
import MessageUtil from "../util/MessageUtil";
interface PlayerPageProps { interface PlayerPageProps {
user: User; user: User;
@ -23,25 +25,74 @@ const PlayerPage: NextPage<PlayerPageProps> = ({ user }) => {
const playerRef = useRef<ReactPlayer>(); const playerRef = useRef<ReactPlayer>();
const [id, setID] = useState<string>(""); const [id, setID] = useState<string>("");
const [identity, setIdentity] = useState<IdentityData>(); const [identity, setIdentity] = useState<IdentityData>();
const [paused, setPaused] = useState<boolean>(true);
useEffect(() => { useEffect(() => {
if (isBrowser() && typeof socket !== "undefined") { if (isBrowser() && typeof socket !== "undefined") {
socket?.emitter.once(SocketEvents.Identify, (e: IdentityData) => { socket?.emitter.once(SocketEvents.Identify, (e: IdentityData) => {
setID(e.playlist); setID(e.playlist);
setIdentity(e); setIdentity(e);
playerRef?.current.seekTo(e.playhead);
setPaused(e.paused);
}); });
socket?.emitter.on(SocketEvents.SetPlayhead, (e: SetPlayheadEvent) => { socket?.emitter.on(SocketEvents.SetPlayhead, (e: SetPlayheadEvent) => {
console.log(e); console.log(e.paused);
setPaused(e.paused);
playerRef.current.seekTo(e.playhead);
}); });
} }
}, [socket]); }, [socket]);
const onSeek = () => {}; const onPlay = () => {
if (!identity.admin) return;
setPaused(false);
socket?.send(
MessageUtil.encode(
new Message(MessageTypes.SetPlayhead, {
playhead: playerRef.current.getCurrentTime(),
paused: false,
})
)
);
};
const onSeek = (playedSeconds: number) => {
if (!identity.admin) return;
socket.send(
MessageUtil.encode(
new Message(MessageTypes.SetPlayhead, {
playhead: playedSeconds,
paused: paused,
})
)
);
};
const onPause = () => {
console.log("running now");
if (!identity.admin) return;
setPaused(true);
socket?.send(
MessageUtil.encode(
new Message(MessageTypes.SetPlayhead, {
playhead: playerRef.current.getCurrentTime(),
paused: true,
})
)
);
};
return ( return (
<> <>
<Head> <Head>
<title>Watch Together</title> <title>Watch Together</title>
</Head> </Head>
<Container height="100vh" background={"#000"}> <Container height="100vh" background={"#000"}>
<Player ref={playerRef} /> <Player
url={id}
onPlay={onPlay}
onPause={onPause}
onSeek={onSeek}
controls={identity?.hasController}
playing={!paused}
ref={playerRef}
/>
</Container> </Container>
</> </>
); );