Skip to content
This repository has been archived by the owner on Feb 18, 2022. It is now read-only.

Commit

Permalink
Convert canvas components to TS
Browse files Browse the repository at this point in the history
  • Loading branch information
Reselim committed Nov 19, 2021
1 parent 6798e7c commit 7787201
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 36 deletions.
5 changes: 2 additions & 3 deletions src/components/viewer/ViewerCanvas/core/Canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class Collector extends EventEmitter2 {
}

class Canvas extends EventEmitter2 {
public camera: Camera
public camera?: Camera
public collectors: Collector[] = []

public readonly app: PIXI.Application = new PIXI.Application({
Expand All @@ -267,10 +267,9 @@ class Canvas extends EventEmitter2 {

private maid: Maid = new Maid()

constructor(camera: Camera) {
constructor() {
super()

this.camera = camera
this.element = this.app.view

const updateSize = () => {
Expand Down
4 changes: 1 addition & 3 deletions src/components/viewer/ViewerCanvas/core/Input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EventEmitter2 } from "eventemitter2"

import Maid from "../../../../class/Maid"

function getEventPosition(event: MouseEvent) {
function getEventPosition(event: MouseEvent): Vector2 {
return new Vector2(event.offsetX, event.offsetY)
}

Expand Down Expand Up @@ -38,8 +38,6 @@ class Pointer extends EventEmitter2 {
}
}

type EventListener = (event: Event) => void

class Input extends EventEmitter2 {
public pointers: Record<string, Pointer> = {}
public maid: Maid = new Maid()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ import styled from "styled-components"
import Canvas from "./core/Canvas"
import Camera from "./core/Camera"
import Input from "./core/Input"
import useStaticValue from "/src/util/useStaticValue"
import useStaticValue from "../../../util/useStaticValue"
import ViewerContext from "../ViewerContext"
import { Snapshot } from "@free-draw/moderation-client"

const ViewerCanvasElement = styled.div`
position: relative;
overflow: hidden;
`

function ViewerCanvas({ data, className, children }) {
const ref = React.useRef()
function ViewerCanvas({ data, className, children }: {
data: Snapshot["canvas"],
className?: string,
children?: React.ReactNode[],
}) {
const ref = React.useRef() as React.RefObject<HTMLDivElement>

const canvas = useStaticValue(() => new Canvas())
const input = useStaticValue(() => new Input(canvas.element))
Expand Down
5 changes: 0 additions & 5 deletions src/components/viewer/ViewerContext.js

This file was deleted.

14 changes: 14 additions & 0 deletions src/components/viewer/ViewerContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react"
import Camera from "./ViewerCanvas/core/Camera"
import Canvas from "./ViewerCanvas/core/Canvas"
import Input from "./ViewerCanvas/core/Input"

type ViewerContextData = {
canvas: Canvas,
input: Input,
camera: Camera,
}

const ViewerContext = React.createContext<ViewerContextData | null>(null)

export default ViewerContext
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Vector2 } from "@free-draw/moderation-client"
import React from "react"
import styled from "styled-components"

import { Pointer } from "./ViewerCanvas/core/Input"
import ViewerContext from "./ViewerContext"

const ViewerHoverDetailsElement = styled.div`
const ViewerHoverDetailsElement = styled.div<{
enabled: boolean,
}>`
position: absolute;
top: 0;
left: 0;
Expand All @@ -21,16 +24,19 @@ const ViewerHoverDetailsNameElement = styled.span`
font-size: 16px;
`

function ViewerHoverDetails() {
const [ enabled, setEnabled ] = React.useState(false)
const [ name, setName ] = React.useState(null)
const ViewerHoverDetails = () => {
const ref = React.useRef() as React.RefObject<HTMLDivElement>

const context = React.useContext(ViewerContext)
if (!context) throw new Error("ViewerHoverDetails must be inside of a ViewerCanvas")
const { canvas, input } = context

const ref = React.useRef()
const { canvas, input } = React.useContext(ViewerContext)
const [ enabled, setEnabled ] = React.useState<boolean>(false)
const [ name, setName ] = React.useState<string | null>(null)

React.useEffect(() => {
const listener = input.on("move", (_, screenPosition) => {
const position = canvas.camera.getRelativePosition(screenPosition)
const onMove = (_pointer: Pointer, screenPosition: Vector2) => {
const position = canvas.camera!.getRelativePosition(screenPosition)
const line = canvas.getLineAt(position)

const shouldBeEnabled = !!line
Expand All @@ -43,14 +49,17 @@ function ViewerHoverDetails() {
const owner = collector.owner

if (name !== owner.name) {
setName(owner.name)
setName(owner.name!)
}
}

ref.current.style.transform = `translate(${screenPosition.x}px, ${screenPosition.y}px)`
}, { objectify: true })
ref.current!.style.transform = `translate(${screenPosition.x}px, ${screenPosition.y}px)`
}

return () => listener.off()
input.on("move", onMove)
return () => {
input.off("move", onMove)
}
}, [ enabled, name ])

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react"
import styled from "styled-components"
import { getRobloxThumbnail, RobloxThumbnailType } from "@free-draw/moderation-client"
import API from "/src/API"
import useAsync from "/src/util/useAsync"
import { getRobloxThumbnail, RobloxThumbnailType, SnapshotPlayer, Vector2 } from "@free-draw/moderation-client"
import API from "../../API"
import useAsync from "../../util/useAsync"
import ViewerPositionalOverlay from "./ViewerPositionalOverlay"

const size = 64
Expand Down Expand Up @@ -35,8 +35,10 @@ const ViewerPlayerBubbleNameElement = styled.span`
margin-top: 12px;
`

function ViewerPlayerBubble(props) {
const { player, position } = props
function ViewerPlayerBubble({ player, position }: {
player: SnapshotPlayer,
position: Vector2,
}) {
const avatar = useAsync(getRobloxThumbnail, [ player.id ])(API, {
id: player.id,
type: RobloxThumbnailType.AVATAR_HEADSHOT,
Expand All @@ -46,7 +48,7 @@ function ViewerPlayerBubble(props) {
return (
<ViewerPositionalOverlay position={position} ignoreScale>
<ViewerPlayerBubbleElement href={`https://www.roblox.com/users/${player.id}/profile`}>
<ViewerPlayerBubbleAvatarElement src={avatar} />
<ViewerPlayerBubbleAvatarElement src={avatar ?? ""} />
<ViewerPlayerBubbleNameElement>{player.name}</ViewerPlayerBubbleNameElement>
</ViewerPlayerBubbleElement>
</ViewerPositionalOverlay>
Expand All @@ -55,11 +57,13 @@ function ViewerPlayerBubble(props) {

const ViewerPlayerBubblesElement = styled.div``

function ViewerPlayerBubbles(props) {
function ViewerPlayerBubbles({ players }: {
players: SnapshotPlayer[],
}) {
return (
<ViewerPlayerBubblesElement>
{
Object.values(props.players).map((player) => {
Object.values(players).map((player) => {
return (
<ViewerPlayerBubble
key={player.id}
Expand Down
1 change: 1 addition & 0 deletions src/components/viewer/ViewerPositionalOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const ViewerPositionalOverlayElement = styled.div`
function ViewerPositionalOverlay(props: {
position: Vector2,
ignoreScale?: boolean,
children: React.ReactNode[],
}) {
const context = React.useContext(ViewerContext)
if (!context) throw new Error("ViewerPositionalOverlay must be inside of a ViewerCanvas")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ViewerPlayerBubbles from "./ViewerPlayerBubbles"

export {
ViewerContext,

ViewerCanvas,
ViewerHoverDetails,
ViewerPositionalOverlay,
Expand Down

0 comments on commit 7787201

Please sign in to comment.