Adds provisional keyboard panning

This commit is contained in:
Steve Ruiz 2021-06-30 21:56:42 +01:00
parent e5408219de
commit 7da573ffdb
10 changed files with 79 additions and 40 deletions

View file

@ -1,15 +1,16 @@
import Cursor from './cursor'
import { useCoopSelector } from 'state/coop/coop-state'
import { useSelector } from 'state'
export default function Presence(): JSX.Element {
const others = useCoopSelector((s) => s.data.others)
const currentPageId = useSelector((s) => s.data.currentPageId)
return (
<>
{Object.values(others).map(({ connectionId, presence }) => {
if (presence == null) {
return null
}
if (presence === null) return null
if (presence.pageId !== currentPageId) return null
return (
<Cursor

View file

@ -2,12 +2,6 @@ import React from 'react'
import styled from 'styles'
import { motion } from 'framer-motion'
// const transition = {
// type: 'spring',
// mass: 2,
// damping: 20,
// }
export default function Cursor({
color = 'dodgerblue',
duration = 0,

View file

@ -8,6 +8,7 @@ import {
fastTranslate,
} from 'state/hacks'
import inputs from 'state/inputs'
import Vec from 'utils/vec'
export default function useCanvasEvents(
rCanvas: MutableRefObject<SVGGElement>
@ -27,8 +28,14 @@ export default function useCanvasEvents(
const handlePointerMove = useCallback((e: React.PointerEvent) => {
if (!inputs.canAccept(e.pointerId)) return
const prev = inputs.pointer?.point
const info = inputs.pointerMove(e)
if (prev && state.isIn('selecting') && inputs.keys[' ']) {
state.send('KEYBOARD_PANNED_CAMERA', { delta: Vec.sub(prev, info.point) })
return
}
if (state.isIn('draw.editing')) {
fastDrawUpdate(info)
} else if (state.isIn('brushSelecting')) {

View file

@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { useEffect } from 'react'
import state from 'state'
import inputs from 'state/inputs'
import { MoveType } from 'types'
import { getKeyboardEventInfo, metaKey } from 'utils'
import { metaKey } from 'utils'
export default function useKeyboardEvents() {
useEffect(() => {
@ -24,7 +25,7 @@ export default function useKeyboardEvents() {
e.preventDefault()
}
const info = getKeyboardEventInfo(e)
const info = inputs.keydown(e)
switch (e.key) {
case 'ArrowUp': {
@ -269,7 +270,7 @@ export default function useKeyboardEvents() {
}
function handleKeyUp(e: KeyboardEvent) {
const info = getKeyboardEventInfo(e)
const info = inputs.keyup(e)
if (e.key === 'Shift') {
state.send('RELEASED_SHIFT_KEY', info)

View file

@ -2,6 +2,7 @@
import React, { MutableRefObject, useCallback } from 'react'
import state from 'state'
import inputs from 'state/inputs'
import Vec from 'utils/vec'
export default function useShapeEvents(
id: string,
@ -57,6 +58,20 @@ export default function useShapeEvents(
(e: React.PointerEvent) => {
if (!inputs.canAccept(e.pointerId)) return
const prev = inputs.pointer?.point
const info = inputs.pointerMove(e)
if (prev && state.isIn('selecting') && inputs.keys[' ']) {
if (!e.currentTarget.hasPointerCapture(e.pointerId)) {
e.currentTarget.setPointerCapture(e.pointerId)
}
state.send('KEYBOARD_PANNED_CAMERA', {
delta: Vec.sub(prev, info.point),
})
return
}
if (isParent) {
state.send('MOVED_OVER_GROUP', inputs.pointerEnter(e, id))
} else {

View file

@ -1,5 +1,3 @@
/* eslint-disable prefer-const */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Client, Room, createClient } from '@liveblocks/client'
import coopState from './coop-state'
import { CoopPresence } from 'types'
@ -108,6 +106,7 @@ class CoopClient {
bufferedYs: this.bufferedYs,
times,
duration,
pageId,
})
// Reset data for next update
@ -118,6 +117,7 @@ class CoopClient {
elapsed = 0
}
// Add the new point and time
this.bufferedXs.push(point[0])
this.bufferedYs.push(point[1])
this.bufferedTs.push(elapsed / 1000)

View file

@ -1,5 +1,5 @@
import React from 'react'
import { PointerInfo } from 'types'
import { KeyboardInfo, PointerInfo } from 'types'
import vec from 'utils/vec'
import { isDarwin, getPoint } from 'utils'
@ -8,8 +8,12 @@ const DOUBLE_CLICK_DURATION = 250
class Inputs {
activePointerId?: number
pointerUpTime = 0
points: Record<string, PointerInfo> = {}
pointer: PointerInfo
points: Record<string, PointerInfo> = {}
keyboard: KeyboardInfo
keys: Record<string, boolean> = {}
touchStart(e: TouchEvent | React.TouchEvent, target: string) {
const { shiftKey, ctrlKey, metaKey, altKey } = e
@ -190,6 +194,36 @@ class Inputs {
resetDoubleClick() {
this.pointerUpTime = 0
}
keydown = (e: KeyboardEvent | React.KeyboardEvent): KeyboardInfo => {
const { shiftKey, ctrlKey, metaKey, altKey } = e
this.keys[e.key] = true
return {
key: e.key,
keys: Object.keys(this.keys),
shiftKey,
ctrlKey,
metaKey: isDarwin() ? metaKey : ctrlKey,
altKey,
}
}
keyup = (e: KeyboardEvent | React.KeyboardEvent): KeyboardInfo => {
const { shiftKey, ctrlKey, metaKey, altKey } = e
delete this.keys[e.key]
return {
key: e.key,
keys: Object.keys(this.keys),
shiftKey,
ctrlKey,
metaKey: isDarwin() ? metaKey : ctrlKey,
altKey,
}
}
}
export default new Inputs()

View file

@ -173,8 +173,6 @@ const state = createState({
// RT_CHANGED_STATUS: 'setRtStatus',
// RT_DELETED_SHAPE: 'deleteRtShape',
// RT_EDITED_SHAPE: 'editRtShape',
// RT_MOVED_CURSOR: 'moveRtCursor',
// MOVED_POINTER: { secretlyDo: 'sendRtCursorMove' },
// Client
RESIZED_WINDOW: 'resetPageState',
RESET_DOCUMENT_STATE: 'resetDocumentState',
@ -334,6 +332,7 @@ const state = createState({
selecting: {
onEnter: ['setActiveToolSelect', 'clearInputs'],
on: {
KEYBOARD_PANNED_CAMERA: 'panCamera',
STARTED_PINCHING: {
unless: 'isInSession',
to: 'pinching.selectPinching',

View file

@ -44,6 +44,7 @@ export type CoopPresence = {
bufferedYs: number[]
times: number[]
duration: number
pageId: string
}
export interface TLDocument {
@ -286,6 +287,15 @@ export interface PointerInfo {
altKey: boolean
}
export interface KeyboardInfo {
key: string
keys: string[]
shiftKey: boolean
ctrlKey: boolean
metaKey: boolean
altKey: boolean
}
export enum Edge {
Top = 'top_edge',
Right = 'right_edge',

View file

@ -1564,28 +1564,6 @@ export function metaKey(e: KeyboardEvent | React.KeyboardEvent): boolean {
return isDarwin() ? e.metaKey : e.ctrlKey
}
/**
* Extract info about a keyboard event.
* @param e
*/
export function getKeyboardEventInfo(e: KeyboardEvent | React.KeyboardEvent): {
key: string
shiftKey: boolean
ctrlKey: boolean
metaKey: boolean
altKey: boolean
} {
const { shiftKey, ctrlKey, metaKey, altKey } = e
return {
key: e.key,
shiftKey,
ctrlKey,
metaKey: isDarwin() ? metaKey : ctrlKey,
altKey,
}
}
/**
* Find the closest point on a SVG path to an off-path point.
* @param pathNode