mirror of https://github.com/logseq/logseq
Feat (Whiteboards): Pen mode (palm rejection) (#10222)
* introduce pen mode * add isPrimary checkpull/10298/head
parent
7c0e5edb8d
commit
bdba1ff86f
|
@ -524,7 +524,7 @@ html[data-theme='dark'] {
|
|||
}
|
||||
|
||||
&-btn {
|
||||
@apply fixed bottom-4 right-8;
|
||||
@apply fixed bottom-4 right-4 sm:right-8;
|
||||
|
||||
> .inner {
|
||||
@apply font-bold
|
||||
|
|
|
@ -205,7 +205,7 @@ input.tl-text-input {
|
|||
|
||||
.tl-action-bar {
|
||||
left: 0.5rem;
|
||||
bottom: 0.5rem;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.tl-primary-tools {
|
||||
|
|
|
@ -465,6 +465,7 @@
|
|||
:whiteboard/dashboard-card-edited "Edited "
|
||||
:whiteboard/toggle-grid "Toggle grid"
|
||||
:whiteboard/snap-to-grid "Snap to grid"
|
||||
:whiteboard/toggle-pen-mode "Toggle pen mode"
|
||||
:flashcards/modal-welcome-title "Time to create a card!"
|
||||
:flashcards/modal-welcome-desc-1 "You can add \"#card\" to any block to turn it into a card or trigger \"/cloze\" to add some clozes."
|
||||
:flashcards/modal-welcome-desc-2 "You can "
|
||||
|
|
|
@ -41,10 +41,14 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
|
|||
app.api.toggleSnapToGrid()
|
||||
}, [app])
|
||||
|
||||
const togglePenMode = React.useCallback(() => {
|
||||
app.api.togglePenMode()
|
||||
}, [app])
|
||||
|
||||
return (
|
||||
<div className="tl-action-bar" data-html2canvas-ignore="true">
|
||||
{!app.readOnly && (
|
||||
<div className="tl-toolbar tl-history-bar">
|
||||
<div className="tl-toolbar tl-history-bar mr-2 mb-2">
|
||||
<Button tooltip={t('whiteboard/undo')} onClick={undo}>
|
||||
<TablerIcon name="arrow-back-up" />
|
||||
</Button>
|
||||
|
@ -54,7 +58,7 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className={`tl-toolbar tl-zoom-bar ${app.readOnly ? '' : 'ml-4'}`}>
|
||||
<div className={'tl-toolbar tl-zoom-bar mr-2 mb-2'}>
|
||||
<Button tooltip={t('whiteboard/zoom-in')} onClick={zoomIn} id="tl-zoom-in">
|
||||
<TablerIcon name="plus" />
|
||||
</Button>
|
||||
|
@ -65,7 +69,7 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
|
|||
<ZoomMenu />
|
||||
</div>
|
||||
|
||||
<div className={'tl-toolbar tl-grid-bar ml-4'}>
|
||||
<div className={'tl-toolbar tl-grid-bar mr-2 mb-2'}>
|
||||
<ToggleInput
|
||||
tooltip={t('whiteboard/toggle-grid')}
|
||||
className="tl-button"
|
||||
|
@ -88,6 +92,20 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
|
|||
</ToggleInput>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!app.readOnly && (
|
||||
<div className="tl-toolbar tl-pen-mode-bar mb-2">
|
||||
<ToggleInput
|
||||
tooltip={t('whiteboard/toggle-pen-mode')}
|
||||
className="tl-button"
|
||||
pressed={app.settings.penMode}
|
||||
id="tl-toggle-pen-mode"
|
||||
onPressedChange={togglePenMode}
|
||||
>
|
||||
<TablerIcon name={app.settings.penMode ? "pencil" : "pencil-off"} />
|
||||
</ToggleInput>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
|
@ -166,7 +166,7 @@ html[data-theme='light'] {
|
|||
}
|
||||
|
||||
.tl-action-bar {
|
||||
@apply absolute bottom-0 flex items-center border-0 left-10 bottom-10;
|
||||
@apply absolute flex items-center border-0 left-10 bottom-8 flex-wrap-reverse pr-12;
|
||||
|
||||
z-index: 100000;
|
||||
user-select: none;
|
||||
|
|
|
@ -178,6 +178,13 @@ export class TLApi<S extends TLShape = TLShape, K extends TLEventMap = TLEventMa
|
|||
return this
|
||||
}
|
||||
|
||||
|
||||
togglePenMode = (): this => {
|
||||
const { settings } = this.app
|
||||
settings.update({ penMode: !settings.penMode })
|
||||
return this
|
||||
}
|
||||
|
||||
setColor = (color: string): this => {
|
||||
const { settings } = this.app
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { observable, makeObservable, action } from 'mobx'
|
|||
export interface TLSettingsProps {
|
||||
mode: 'light' | 'dark'
|
||||
showGrid: boolean
|
||||
penMode: boolean
|
||||
snapToGrid: boolean
|
||||
color: string
|
||||
scaleLevel: string
|
||||
|
@ -17,6 +18,7 @@ export class TLSettings implements TLSettingsProps {
|
|||
@observable mode: 'dark' | 'light' = 'light'
|
||||
@observable showGrid = true
|
||||
@observable snapToGrid = true
|
||||
@observable penMode = false
|
||||
@observable scaleLevel = 'md'
|
||||
@observable color = ''
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ export const AppCanvas = observer(function InnerApp<S extends TLReactShape>(
|
|||
shapes={app.shapes} // TODO: use shapes in viewport later?
|
||||
assets={app.assets}
|
||||
showGrid={app.settings.showGrid}
|
||||
penMode={app.settings.penMode}
|
||||
showSelection={app.showSelection}
|
||||
showSelectionRotation={app.showSelectionRotation}
|
||||
showResizeHandles={app.showResizeHandles}
|
||||
|
|
|
@ -58,6 +58,7 @@ export interface TLCanvasProps<S extends TLReactShape> {
|
|||
cursorRotation: number
|
||||
selectionRotation: number
|
||||
onEditingEnd: () => void
|
||||
penMode: boolean
|
||||
showGrid: boolean
|
||||
showSelection: boolean
|
||||
showHandles: boolean
|
||||
|
|
|
@ -13,11 +13,19 @@ export function useCanvasEvents() {
|
|||
|
||||
const events = React.useMemo(() => {
|
||||
const onPointerMove: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
callbacks.onPointerMove?.({ type: TLTargetType.Canvas, order }, e)
|
||||
}
|
||||
|
||||
const onPointerDown: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
|
||||
|
||||
|
@ -41,17 +49,29 @@ export function useCanvasEvents() {
|
|||
}
|
||||
|
||||
const onPointerUp: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
|
||||
callbacks.onPointerUp?.({ type: TLTargetType.Canvas, order }, e)
|
||||
}
|
||||
|
||||
const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
callbacks.onPointerEnter?.({ type: TLTargetType.Canvas, order }, e)
|
||||
}
|
||||
|
||||
const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
callbacks.onPointerLeave?.({ type: TLTargetType.Canvas, order }, e)
|
||||
}
|
||||
|
|
|
@ -1,23 +1,33 @@
|
|||
import * as React from 'react'
|
||||
import { TLTargetType } from '@tldraw/core'
|
||||
import { useApp } from './useApp'
|
||||
import { useRendererContext } from '.'
|
||||
import { DOUBLE_CLICK_DURATION } from '../constants'
|
||||
import type { TLReactShape } from '../lib'
|
||||
import type { TLReactCustomEvents } from '../types'
|
||||
|
||||
export function useShapeEvents<S extends TLReactShape>(shape: S) {
|
||||
const app = useApp()
|
||||
const { inputs, callbacks } = useRendererContext()
|
||||
|
||||
const rDoubleClickTimer = React.useRef<number>(-1)
|
||||
|
||||
const events = React.useMemo(() => {
|
||||
const onPointerMove: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
callbacks.onPointerMove?.({ type: TLTargetType.Shape, shape, order }, e)
|
||||
e.order = order + 1
|
||||
}
|
||||
|
||||
const onPointerDown: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
|
||||
callbacks.onPointerDown?.({ type: TLTargetType.Shape, shape, order }, e)
|
||||
|
@ -25,6 +35,10 @@ export function useShapeEvents<S extends TLReactShape>(shape: S) {
|
|||
}
|
||||
|
||||
const onPointerUp: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
|
||||
callbacks.onPointerUp?.({ type: TLTargetType.Shape, shape, order }, e)
|
||||
|
@ -42,12 +56,20 @@ export function useShapeEvents<S extends TLReactShape>(shape: S) {
|
|||
}
|
||||
|
||||
const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
callbacks.onPointerEnter?.({ type: TLTargetType.Shape, shape, order }, e)
|
||||
e.order = order + 1
|
||||
}
|
||||
|
||||
const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
|
||||
if (app.settings.penMode && (e.pointerType !== 'pen' || !e.isPrimary)) {
|
||||
return
|
||||
}
|
||||
|
||||
const { order = 0 } = e
|
||||
callbacks.onPointerLeave?.({ type: TLTargetType.Shape, shape, order }, e)
|
||||
e.order = order + 1
|
||||
|
|
Loading…
Reference in New Issue