The logic to support it was not implemented. This is not the prettiest way to solve it in the world but it does work. Some more refactoring here is probably warranted.
Fixes#1039
* Don't reset cache while zooming using a gesture
This reuses the cached canvas while the gesture is happening. Once it has stop updating, then recompute the cache with the proper zoom.
This should massively improve performance when panning on big scenes on mobile
Fixes#1056
* update snapshot tests
This wasn't taking into account zoom properly.
The logic should probably get refactored a bit, it's not ideal that we're passing canvas, state and scale as different arguments. Also it's weird that the function that returns the center is computing the viewport translation. But I'm not motivated enough to fix it right now...
Fixes#1100
* load scene from localStorage in collaboration if user is first in room
* load scene from localStorage in collaboration prior to syncing with server
* fix merge
Co-authored-by: dwelle <luzar.david@gmail.com>
* Update shortcuts.md for Lock
* Add 'Q' as a shortcut for toggling shape lock
* Add shortcut to LockIcon title
* use event.key instead
Co-authored-by: Faustino Kialungila <Faustino.kialungila@gmail.com>
* Restyle the bottom bar on mobile as an Island
* Shorter label for collaboration button, truncate too-long button labels
* Refactor safe area things to global vars
* Fix scroll bar positioning, don’t block scrollbars with menu island
* Update text
* cmd+d to duplicate selection
* use duplicateElement instead
* use duplicateElement instead
* Update actionDuplicateSelection.ts
* select the new duplicated element
* add locale
* use event.key instead of event.code
Co-authored-by: David Luzar <luzar.david@gmail.com>
* New translations en.json (Korean)
* New translations en.json (Korean)
* New translations en.json (Korean)
* New translations en.json (Korean)
* New translations en.json (Korean)
* New translations en.json (Portuguese)
* New translations en.json (Portuguese)
* [WIP] Add names next to pointers
This implements the rendering and messaging across. Still need to do the UI to set the name.
Also, not really sure what's the best place to send the name and store it.
* Add randomized names
Co-authored-by: Christopher Chedeau <vjeux@fb.com>
* Fix hit testing threshold
- The bounding box was not correctly extended to take into account the threshold. It was only for y axis but not x.
- The bezier threshold was using 20 instead of 10 and not taking into account zoom level.
Both those issues are fixed and now the behavior looks good on all the shapes I can test.
* fix_tests
My original hack to put the scale when we create the canvas element doesn't make much sense. It should be done when we are rendering the scene. I moved it there in this PR.
The rest was all about forwarding the scale to where it's needed.
* Stop using getTransform
Fixes#861
The original motivation behind this is to make it work with Firefox. But it also helped make the code more intentional.
Test Plan:
- Create one square, select it, zoom in repeatedly, make sure that it zooms centered in the screen and everything looks good
- Scroll at various zoom levels, things look good
- Export a small scene at 1x and 3x, make sure the background is properly set and look good
* fix selection element
I'm using the client id as a random number to index on the color array. So far it's been working better than using a sequential increment as the colors in the array are sorted by proximity. Also, it has the advantage that everyone in the room will see the same color for the same person.
* support ToolIcon className and fix label padding
* factor some ExportDialog classes out to Modal
* initial RoomDialog prototype
* change label for another-session button
* remove unused css
* add color comments
* Move the collaboration button to the main menu, add support for mobile
* remove button for creating another session
* add locks
* Fix alignment issue
* Reorder button
* reuse current scene for collab session
* keep collaboration state on restore
Co-authored-by: Jed Fox <git@twopointzero.us>
* Enable collaborative syncing for elements
* Don't fall back to local storage if using a room, as that is confusing
* Use remote socket server
* Send updates to new users when they join
* ~
* add mouse tracking
* enable collaboration, rooms, and mouse tracking
* fix syncing bugs and add a button to start syncing mid session
* enable collaboration, rooms, and mouse tracking
* fix syncing bugs and add a button to start syncing mid session
* Add Live button and app state to support tracking collaborator counts
* Enable collaborative syncing for elements
* add mouse tracking
* enable collaboration, rooms, and mouse tracking
* fix syncing bugs and add a button to start syncing mid session
* fix syncing bugs and add a button to start syncing mid session
* Add Live button and app state to support tracking collaborator counts
* prettier
* Fix bug with remote pointers not changing on scroll
* Enable collaborative syncing for elements
* add mouse tracking
* enable collaboration, rooms, and mouse tracking
* fix syncing bugs and add a button to start syncing mid session
* enable collaboration, rooms, and mouse tracking
* fix syncing bugs and add a button to start syncing mid session
* Add Live button and app state to support tracking collaborator counts
* enable collaboration, rooms, and mouse tracking
* fix syncing bugs and add a button to start syncing mid session
* fix syncing bugs and add a button to start syncing mid session
* Fix bug with remote pointers not changing on scroll
* remove UI for collaboration
* remove link
* clean up lingering unused UI
* set random IV passed per encrypted message, reduce room id length, refactored socket broadcasting API, rename room_id to room, removed throttling of pointer movement
* fix package.json conflict
* Get rid of isSelected, canvas, canvasZoom, canvasOffsetX and canvasOffsetY on ExcalidrawElement.
* Fix most unit tests. Fix cmd a. Fix alt drag
* Focus on paste
* shift select should include previously selected items
* Fix last test
* Move this.shape out of ExcalidrawElement and into a WeakMap
* Initial factoring out of parts of the LayerUI component
2360 → 2224 LOC
* Create a Section component
* Break up src/index.tsx
* Refactor actions to reduce duplication, fix CSS
Also consolidate icons
* Move scene/data.ts to its own directory
* Fix accidental reverts, banish further single-character variables
* ACTIVE_ELEM_COLOR → ACTIVE_ELEMENT_COLOR
* Further refactoring the icons file
* Log all errors
* Pointer Event polyfill to make the tests work
* add test hooks & fix tests
Co-authored-by: dwelle <luzar.david@gmail.com>
* fix scrollbar detection on high devicePixelRatio devices
* don't create a new element on pointerdown over a scrollbar
* Return scrollbars from renderScene and use it in isOverScrollBars
* remove unneeded setState
* show default cursor when hovering or dragging a scrollbar
* disable scrollbars when in multielement mode
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Make Undo & Redo and the menu buttons into actions; add undo/redo buttons
* Create variables for the ToolIcon colors
* Darken the menu buttons when they’re active
* Put the more intensive test in `perform`
* Fix & restyle hint viewer
* Add pinch zoom for macOS Safari
* Chrome/Firefox trackpad pinch zoom
* openedMenu → openMenu
* needsShapeEditor.ts → showSelectedShapeActions.ts
* Call showSelectedShapeActions
* Change the extension to .excalidra
* Support opening as well
* support .excalidraw extension on canvas DranAndDrop
Co-authored-by: Faustino Kialungila <Faustino.kialungila@gmail.com>
* New translations en.json (French)
* New translations en.json (German)
* New translations en.json (Norwegian)
* New translations en.json (Polish)
* New translations en.json (Portuguese)
* New translations en.json (Russian)
* New translations en.json (Spanish)
* New translations en.json (Turkish)
* New translations en.json (Polish)
* feat: add reset zoom button
Add zoom reset button.
Button is shown only when zoom scale is different from 1
* change reset zoom icon
* always show zoom reset
* fix typo
* don't render bounding box for multi-point lines during creation
* force LayerUI rerender after creating a new point
Force LayerUI rerender after creating a new point so that the mobile UI
updates and the Done button is visible.
* don't select multiElement on confirm is locked
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Disable text selection
* Set content-editable=plaintext-only to disable Touch Bar formatting buttons
* Enlarge resize handle tap targets for pen/touch
* Make the lock button a button in mobile mode
* Use icons instead of Unicode characters; add an alternate toolbar for creating multipoint lines
* Allow buttons to hide themselves
* Fix heuristic for showing shape actions
* Refactor icons
* Fix label for edit button
* Switch edit button icon
* Remove lock button on mobile
* Add language selector on mobile
* Fix showing edit button on mobile
* Fix showing edit button on mobile, part 2
* Fix handle touch regions
* Fix scroll-back button position
* Allow using the text tool on a text object to start editing it
* Fix deletion of last point in line
* Add touch support
* Mock media query
* Mock media query pt 2
* Fix tests
* Allow installing as an app on iOS
* Fix type error
* Math.hypot
* delete and finalize buttons, hint viewer
* skip failing tests
* skip the rest of the failing tests
* Hide the selected shape actions when nothing is selected
* Don’t go into mobile view on short-but-wide viewports
* lol
* Initial support for mobile devices
No editing yet, but UI looks nice and you can open the canvas menu
* Add support for editing shape color, etc
* Allow the mobile menus to cover the shape selector
* Hopefully fix test error
* Fix touch on canvas
* Fix safe area handling & remove unused Island
* Shortcuts to zoom in/out and to reset zoom
* add support for numerical keys
* Fixed Firefox compatibility
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Zoom icons.
* Actions.
* Min zoom of 0 does not make sense.
* Zoom logic.
* Modify how zoom affects selection rendering.
* More precise scrollbar dimensions.
* Adjust elements visibility and scrollbars.
* Normalized canvas width and height.
* Apply zoom to resize test.
* [WIP] Zoom using canvas center as an origin.
* Undo zoom on `getScrollBars`.
* WIP: center zoom origin via scroll
* This was wrong for sure.
* Finish scaling using center as origin.
* Almost there.
* Scroll offset should be not part of zoom transforms.
* Better naming.
* Wheel movement should be the same no matter the zoom level.
* Panning movement should be the same no matter the zoom level.
* Fix elements pasting.
* Fix text WYSIWGT.
* Fix scrollbars and visibility.
* Scaffold a simple test case for debugging
* Set up Jest environment that works with React
- Install and set up react-testing-library
- "Unignore" roughjs and browser-nativejs transformations
- Separate App component from ReactDOM
* Write first passing test
- Mock canvas
- Remove App file and mount/unmount ReactDOM on import
* Add tests for drag create behavior
* Fix comments in dragCreate
* Pin jest-mock-canvas dependency
* Remove dependency range for testing library
* Add tests for multi point mode and selection element
* Fix all tests due to decrease in updates to canvas when changing tools
* Disable state updates if component is unmounted
- Remove all event listeners
- Disable storing scene in state if component is unmounted
* Add tests for move and element selection
* Merge branch 'master' into add-integration-tests
* Add tests for resizing rectangle
* move unmounted check to syncActionResult method
* Use a custom test renderer instead of default testing-library functions
* Add custom query for selecting tools
* move files around
Co-authored-by: David Luzar <luzar.david@gmail.com>
* keep arrows and lines selected if locked
* keep element type selected if locked after inserting text
* ensure clicking outside doesn't create new text
* esc should switch to selection even if locked
* reset cursor when creating text via doubleClick
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Add z-index options back to panel
* Add formatting for z-index panel buttons
* make z-index buttons all the same width
* make z-index button spacing even
* use svg icons & translations
* add ui legend
Co-authored-by: David Luzar <luzar.david@gmail.com>
The computation was not correct. I'm not really sure how it used to work but it was not taking into account the dimensions of the scene so it was wrong.
The new algorithm is computing the scrollbar such that it's the position of the viewport in relationship to the bounding box of the viewport and all the elements.
Fixes#680
* End to end encryption description
This PR updates the url upload description to mention that it is end to end encrypted. I used a very similar message as whatsapp so that it is familar to people.
I also removed the automatic copying and turned the alert into prompt. This should be less awkward than the current implementation.
* capitalize excalidraw
Co-authored-by: David Luzar <luzar.david@gmail.com>
* switch to selection tool on paste
* align pasting via contextMenu with pasting from event
* ensure only plaintext can be pasted
* fix findShapeByKey regression
* simplify wysiwyg pasting
* improve wysiwyg blurriness
* Separate UI from Canvas
* Explicitly define history recording
* ActionManager: Set syncActionState during construction instead of in every call
* Add commit to history flag to necessary actions
* Disable undoing during multiElement
* Write custom equality function for UI component to render it only when specific props and elements change
* Remove stale comments about history skipping
* Stop undo/redoing when in resizing element mode
* wip
* correctly reset resizingElement & add undo check
* Separate selection element from the rest of the array and stop redrawing the UI when dragging the selection
* Remove selectionElement from local storage
* Remove unnecessary readonly type casting in actionFinalize
* Fix undo / redo for multi points
* Fix an issue that did not update history when elements were locked
* Disable committing to history for noops
- deleteSelected without deleting anything
- Basic selection
* Use generateEntry only inside history and pass elements and appstate to history
* Update component after every history resume
* Remove last item from the history only if in multi mode
* Resume recording when element type is not selection
* ensure we prevent hotkeys only on writable elements
* Remove selection clearing from history
* Remove one point arrows as they are invisibly small
* Remove shape of elements from local storage
* Fix removing invisible element from the array
* add missing history resuming cases & simplify slice
* fix lint
* don't regenerate elements if no elements deselected
* regenerate elements array on selection
* reset state.selectionElement unconditionally
* Use getter instead of passing appState and scene data through functions to actions
* fix import
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Add encryption
In order to avoid the server being able to read the content of the scene, this PR implements local encryption and decryption. This implements the algorithm described in #610.
Right now the server doesn't support uploading binary files. I mocked the server with comments. @lipis, could you add support on the server and update this PR? I added a bunch of TODO: that tell you where to comment/uncomment in order to get the server flow going.
To test locally right now:
- Import: Open http://localhost:3000/#json=1234,5oYVOnGpWYPPTz19-PMYYw and see a square
- Export: Click the export link and see the right url with the private key + the encrypted binary in the console
Fixes#610
* backend_v2
* v2
* Enable multi points in lines
* Stop retrieving arrow points for lines
* Migrate lines to new spec during load
* Clean up and refactor some code
- Normalize shape dimensions during load
- Rename getArrowAbsoluteBounds
* Fix linter issues
* Add Hint viewer
- Add hints for arrows and lines
- Add hints for resizing elements
* Swap priority of multi mode and resize mode in Hint Viewer
* Remove dangling locales from public
* Add shortcut to hide hints
* Change hint texts and show resize hint ONLY during resizing
* Remove hints toggling
* Add keybindings for shapes
I'm not 100% sure about this one. I feel like it's going to help people be a lot more productive to display the key bindings at all time. But it also clutters the UI...
* increase font-size
* fix shape keybindings for non-qwerty keyboards
* tweak position and color
Co-authored-by: David Luzar <luzar.david@gmail.com>
With the infinite scroll behavior, it's easy to scroll super far away from where the content is and have a hard time getting back. This PR adds a button to refocus on the center of the scene when no elements are visible anymore.
* support undo/redo for azerty keyboards
* migrate to event.key
* remove unnecessary shiftKey check
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Add keybindings for color picker
This adds the ability to navigate using left/right/bottom/up keys and shows key bindings for all the different colors. This is only optimized for the qwerty keyboard layout, but unfortunately it's not possible to detect other keyboard layouts :(
* add aria-keyshortcuts and keybinding in title
* make focus select color, confirm on enter
Co-authored-by: David Luzar <luzar.david@gmail.com>
* Revert "Revert "Feature: Multi Point Arrows (#338)" (#634)"
This reverts commit 3d2e59bfed.
* Convert old arrow spec to new one
* Remove unnecessary failchecks and fix context transform issue in retina displays
* Remove old points failcheck from getArrowAbsoluteBounds
* Remove all failchecks for old arrow
* remove the rest of unnecessary checks
* Set default values for the arrow during import
* Add translations
* fix restore using unmigrated elements for state computation
* don't use width/height when migrating from new arrow spec
Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>