No impure getters pt9 (#2222)

follow up to #2189 

### Change Type

- [x] `patch` — Bug fix
This commit is contained in:
David Sheldrick 2023-11-14 17:07:35 +00:00 committed by GitHub
parent dc0f6ae0f2
commit d683cc0943
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 516 additions and 111 deletions

View file

@ -47,7 +47,7 @@ export class CardShapeUtil extends ShapeUtil<ICardShape> {
// Render method — the React component that will be rendered for the shape
component(shape: ICardShape) {
const bounds = this.editor.getShapeGeometry(shape).bounds
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
// Unfortunately eslint will think this is a class components
// eslint-disable-next-line react-hooks/rules-of-hooks

View file

@ -56,7 +56,7 @@ export class CardShapeUtil extends BaseBoxShapeUtil<CardShape> {
component(shape: CardShape) {
const bounds = this.editor.getShapeGeometry(shape).bounds
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
return (
<HTMLContainer

View file

@ -12,9 +12,9 @@ export default function MetaExample() {
// all shapes created by the user.
editor.getInitialMetaForShape = (_shape) => {
return {
createdBy: editor.user.id,
createdBy: editor.user.getId(),
createdAt: Date.now(),
updatedBy: editor.user.id,
updatedBy: editor.user.getId(),
updatedAt: Date.now(),
}
}
@ -25,7 +25,7 @@ export default function MetaExample() {
if (source !== 'user') return record
record.meta = {
...record.meta,
updatedBy: editor.user.id,
updatedBy: editor.user.getId(),
updatedAt: Date.now(),
}
return record

View file

@ -1799,26 +1799,43 @@ export class SnapManager {
constructor(editor: Editor);
// (undocumented)
clear(): void;
// (undocumented)
// @deprecated (undocumented)
get currentCommonAncestor(): TLShapeId | undefined;
// (undocumented)
readonly editor: Editor;
// (undocumented)
getCurrentCommonAncestor(): TLShapeId | undefined;
// (undocumented)
getOutlinesInPageSpace(): Vec2d[][];
// (undocumented)
getSnappablePoints(): SnapPoint[];
// (undocumented)
getSnappableShapes(): GapNode[];
// (undocumented)
getSnappingHandleDelta({ handlePoint, additionalSegments, }: {
handlePoint: Vec2d;
additionalSegments: Vec2d[][];
}): null | Vec2d;
// (undocumented)
get lines(): SnapLine[];
getSnapPointsCache(): ComputedCache<SnapPoint[], TLShape>;
// (undocumented)
getSnapThreshold(): number;
// (undocumented)
getVisibleGaps(): {
horizontal: Gap[];
vertical: Gap[];
};
// (undocumented)
get lines(): SnapLine[];
// @deprecated (undocumented)
get outlinesInPageSpace(): Vec2d[][];
// (undocumented)
setLines(lines: SnapLine[]): void;
// (undocumented)
// @deprecated (undocumented)
get snappablePoints(): SnapPoint[];
// (undocumented)
// @deprecated (undocumented)
get snappableShapes(): GapNode[];
// (undocumented)
// @deprecated (undocumented)
get snapPointsCache(): ComputedCache<SnapPoint[], TLShape>;
// (undocumented)
snapResize({ initialSelectionPageBounds, dragDelta, handle: originalHandle, isAspectRatioLocked, isResizingFromCenter, }: {
@ -1828,7 +1845,7 @@ export class SnapManager {
isAspectRatioLocked: boolean;
isResizingFromCenter: boolean;
}): SnapData;
// (undocumented)
// @deprecated (undocumented)
get snapThreshold(): number;
// (undocumented)
snapTranslate({ lockedAxis, initialSelectionPageBounds, initialSelectionSnapPoints, dragDelta, }: {
@ -1837,7 +1854,7 @@ export class SnapManager {
initialSelectionPageBounds: Box2d;
dragDelta: Vec2d;
}): SnapData;
// (undocumented)
// @deprecated (undocumented)
get visibleGaps(): {
horizontal: Gap[];
vertical: Gap[];

View file

@ -33754,7 +33754,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#currentCommonAncestor:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getCurrentCommonAncestor` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -33817,6 +33817,150 @@
"isProtected": false,
"isAbstract": false
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getCurrentCommonAncestor:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getCurrentCommonAncestor(): "
},
{
"kind": "Reference",
"text": "TLShapeId",
"canonicalReference": "@tldraw/tlschema!TLShapeId:type"
},
{
"kind": "Content",
"text": " | undefined"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getCurrentCommonAncestor"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getOutlinesInPageSpace:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getOutlinesInPageSpace(): "
},
{
"kind": "Reference",
"text": "Vec2d",
"canonicalReference": "@tldraw/editor!Vec2d:class"
},
{
"kind": "Content",
"text": "[][]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getOutlinesInPageSpace"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getSnappablePoints:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getSnappablePoints(): "
},
{
"kind": "Reference",
"text": "SnapPoint",
"canonicalReference": "@tldraw/editor!SnapPoint:interface"
},
{
"kind": "Content",
"text": "[]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSnappablePoints"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getSnappableShapes:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getSnappableShapes(): "
},
{
"kind": "Reference",
"text": "GapNode",
"canonicalReference": "@tldraw/editor!~GapNode:type"
},
{
"kind": "Content",
"text": "[]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSnappableShapes"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getSnappingHandleDelta:member(1)",
@ -33888,6 +34032,144 @@
"isAbstract": false,
"name": "getSnappingHandleDelta"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getSnapPointsCache:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getSnapPointsCache(): "
},
{
"kind": "Content",
"text": "import(\"@tldraw/store\")."
},
{
"kind": "Reference",
"text": "ComputedCache",
"canonicalReference": "@tldraw/store!ComputedCache:type"
},
{
"kind": "Content",
"text": "<"
},
{
"kind": "Reference",
"text": "SnapPoint",
"canonicalReference": "@tldraw/editor!SnapPoint:interface"
},
{
"kind": "Content",
"text": "[], "
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": ">"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 8
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSnapPointsCache"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getSnapThreshold:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getSnapThreshold(): "
},
{
"kind": "Content",
"text": "number"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSnapThreshold"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!SnapManager#getVisibleGaps:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getVisibleGaps(): "
},
{
"kind": "Content",
"text": "{\n horizontal: "
},
{
"kind": "Reference",
"text": "Gap",
"canonicalReference": "@tldraw/editor!~Gap:type"
},
{
"kind": "Content",
"text": "[];\n vertical: "
},
{
"kind": "Reference",
"text": "Gap",
"canonicalReference": "@tldraw/editor!~Gap:type"
},
{
"kind": "Content",
"text": "[];\n }"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 6
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getVisibleGaps"
},
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#lines:member",
@ -33926,7 +34208,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#outlinesInPageSpace:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getOutlinesInPageSpace` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -34014,7 +34296,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#snappablePoints:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getSnappablePoints` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -34049,7 +34331,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#snappableShapes:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getSnappableShapes` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -34084,7 +34366,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#snapPointsCache:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getSnapPointsCache` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -34235,7 +34517,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#snapThreshold:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getSnapThreshold` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -34341,7 +34623,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!SnapManager#visibleGaps:member",
"docComment": "",
"docComment": "/**\n * @deprecated\n *\n * use `getVisibleGaps` instead\n */\n",
"excerptTokens": [
{
"kind": "Content",

View file

@ -49,7 +49,7 @@ const CollaboratorGuard = track(function CollaboratorGuard({
const { highlightedUserIds } = editor.getInstanceState()
// If they're idle and following us and unless they have a chat message or are highlighted, hide them
if (
presence.followingUserId === editor.user.id &&
presence.followingUserId === editor.user.getId() &&
!(presence.chatMessage || highlightedUserIds.includes(presence.userId))
) {
return null

View file

@ -31,7 +31,7 @@ export const DefaultErrorFallback: TLErrorFallbackComponent = ({ error, editor }
() => {
try {
if (editor) {
return editor.user.isDarkMode
return editor.user.getIsDarkMode()
}
} catch {
// we're in a funky error state so this might not work for spooky

View file

@ -2692,9 +2692,7 @@ export class Editor extends EventEmitter<TLEventMap> {
/** @internal */
private _animateToViewport(targetViewportPage: Box2d, opts = {} as TLAnimationOptions) {
const { duration = 0, easing = EASINGS.easeInOutCubic } = opts
const {
user: { animationSpeed },
} = this
const animationSpeed = this.user.getAnimationSpeed()
const viewportPageBounds = this.getViewportPageBounds()
// If we have an existing animation, then stop it; also stop following any user
@ -2745,7 +2743,7 @@ export class Editor extends EventEmitter<TLEventMap> {
this.stopCameraAnimation()
const { animationSpeed } = this.user
const animationSpeed = this.user.getAnimationSpeed()
if (animationSpeed === 0) return this
@ -3062,7 +3060,7 @@ export class Editor extends EventEmitter<TLEventMap> {
userId: { eq: userId },
}))
const thisUserId = this.user.id
const thisUserId = this.user.getId()
if (!thisUserId) {
console.warn('You should set the userId for the current instance before following a user')
@ -8398,7 +8396,7 @@ export class Editor extends EventEmitter<TLEventMap> {
} = opts
// todo: we shouldn't depend on the public theme here
const theme = getDefaultColorTheme({ isDarkMode: this.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.user.getIsDarkMode() })
// ---Figure out which shapes we need to include
const shapeIdsToInclude = this.getShapeAndDescendantIds(ids)

View file

@ -228,7 +228,7 @@ export class SnapManager {
constructor(public readonly editor: Editor) {}
@computed get snapPointsCache() {
@computed getSnapPointsCache() {
const { editor } = this
return editor.store.createComputedCache<SnapPoint[], TLShape>('snapPoints', (shape) => {
const pageTransfrorm = editor.getShapePageTransform(shape.id)
@ -241,12 +241,26 @@ export class SnapManager {
})
}
@computed get snapThreshold() {
/**
* @deprecated use `getSnapPointsCache` instead
*/
get snapPointsCache() {
return this.getSnapPointsCache()
}
@computed getSnapThreshold() {
return 8 / this.editor.getZoomLevel()
}
/**
* @deprecated use `getSnapThreshold` instead
*/
get snapThreshold() {
return this.getSnapThreshold()
}
// TODO: make this an incremental derivation
@computed get snappableShapes(): GapNode[] {
@computed getSnappableShapes(): GapNode[] {
const { editor } = this
const renderingBounds = editor.getRenderingBounds()
const selectedShapeIds = editor.getSelectedShapeIds()
@ -279,19 +293,35 @@ export class SnapManager {
}
}
collectSnappableShapesFromParent(this.currentCommonAncestor ?? editor.currentPageId)
collectSnappableShapesFromParent(this.getCurrentCommonAncestor() ?? editor.currentPageId)
return snappableShapes
}
/**
* @deprecated use `getSnappableShapes` instead
*/
get snappableShapes() {
return this.getSnappableShapes()
}
// This needs to be external from any expensive work
@computed get currentCommonAncestor() {
@computed getCurrentCommonAncestor() {
return this.editor.findCommonAncestor(this.editor.getSelectedShapes())
}
/**
* @deprecated use `getCurrentCommonAncestor` instead
*/
get currentCommonAncestor() {
return this.getCurrentCommonAncestor()
}
// Points which belong to snappable shapes
@computed get snappablePoints() {
const { snappableShapes, snapPointsCache } = this
@computed getSnappablePoints() {
const snapPointsCache = this.getSnapPointsCache()
const snappableShapes = this.getSnappableShapes()
const result: SnapPoint[] = []
snappableShapes.forEach((shape) => {
@ -304,13 +334,20 @@ export class SnapManager {
return result
}
@computed get visibleGaps(): { horizontal: Gap[]; vertical: Gap[] } {
/**
* @deprecated use `getSnappablePoints` instead
*/
get snappablePoints() {
return this.getSnappablePoints()
}
@computed getVisibleGaps(): { horizontal: Gap[]; vertical: Gap[] } {
const horizontal: Gap[] = []
const vertical: Gap[] = []
let startNode: GapNode, endNode: GapNode
const sortedShapesOnCurrentPageHorizontal = this.snappableShapes.sort((a, b) => {
const sortedShapesOnCurrentPageHorizontal = this.getSnappableShapes().sort((a, b) => {
return a.pageBounds.minX - b.pageBounds.minX
})
@ -401,6 +438,13 @@ export class SnapManager {
return { horizontal, vertical }
}
/**
* @deprecated use `getVisibleGaps` instead
*/
get visibleGaps() {
return this.getVisibleGaps()
}
snapTranslate({
lockedAxis,
initialSelectionPageBounds,
@ -412,7 +456,8 @@ export class SnapManager {
initialSelectionPageBounds: Box2d
dragDelta: Vec2d
}): SnapData {
const { snappablePoints: visibleSnapPointsNotInSelection, snapThreshold } = this
const snapThreshold = this.getSnapThreshold()
const visibleSnapPointsNotInSelection = this.getSnappablePoints()
const selectionPageBounds = initialSelectionPageBounds.clone().translate(dragDelta)
@ -493,8 +538,8 @@ export class SnapManager {
return { nudge }
}
@computed get outlinesInPageSpace() {
return this.snappableShapes.map(({ id, isClosed }) => {
@computed getOutlinesInPageSpace() {
return this.getSnappableShapes().map(({ id, isClosed }) => {
const outline = deepCopy(this.editor.getShapeGeometry(id).vertices)
if (isClosed) outline.push(outline[0])
const pageTransform = this.editor.getShapePageTransform(id)
@ -503,6 +548,13 @@ export class SnapManager {
})
}
/**
* @deprecated use `getOutlinesInPageSpace` instead
*/
get outlinesInPageSpace() {
return this.getOutlinesInPageSpace()
}
getSnappingHandleDelta({
handlePoint,
additionalSegments,
@ -510,7 +562,8 @@ export class SnapManager {
handlePoint: Vec2d
additionalSegments: Vec2d[][]
}): Vec2d | null {
const { outlinesInPageSpace, snapThreshold } = this
const snapThreshold = this.getSnapThreshold()
const outlinesInPageSpace = this.getOutlinesInPageSpace()
// Find the nearest point that is within the snap threshold
let minDistance = snapThreshold
@ -566,7 +619,7 @@ export class SnapManager {
isAspectRatioLocked: boolean
isResizingFromCenter: boolean
}): SnapData {
const { snapThreshold } = this
const snapThreshold = this.getSnapThreshold()
// first figure out the new bounds of the selection
const {
@ -600,7 +653,7 @@ export class SnapManager {
const selectionSnapPoints = getResizeSnapPointsForHandle(handle, unsnappedResizedPageBounds)
const otherNodeSnapPoints = this.snappablePoints
const otherNodeSnapPoints = this.getSnappablePoints()
const nearestSnapsX: NearestPointsSnap[] = []
const nearestSnapsY: NearestPointsSnap[] = []
@ -758,7 +811,7 @@ export class SnapManager {
nearestSnapsX: NearestSnap[]
nearestSnapsY: NearestSnap[]
}) {
const { horizontal, vertical } = this.visibleGaps
const { horizontal, vertical } = this.getVisibleGaps()
for (const gap of horizontal) {
// ignore this gap if the selection doesn't overlap with it in the y axis
@ -1092,7 +1145,7 @@ export class SnapManager {
nearestSnapsX: NearestSnap[]
nearestSnapsY: NearestSnap[]
}): GapsSnapLine[] {
const { vertical, horizontal } = this.visibleGaps
const { vertical, horizontal } = this.getVisibleGaps()
const selectionSides: Record<SelectionEdge, [Vec2d, Vec2d]> = {
top: selectionPageBounds.sides[0],

View file

@ -15,46 +15,101 @@ export class UserPreferencesManager {
...userPreferences,
})
}
@computed get userPreferences() {
@computed getUserPreferences() {
return {
id: this.id,
name: this.name,
locale: this.locale,
color: this.color,
isDarkMode: this.isDarkMode,
animationSpeed: this.animationSpeed,
isSnapMode: this.isSnapMode,
id: this.getId(),
name: this.getName(),
locale: this.getLocale(),
color: this.getColor(),
isDarkMode: this.getIsDarkMode(),
animationSpeed: this.getAnimationSpeed(),
isSnapMode: this.getIsSnapMode(),
}
}
/**
* @deprecated use `getUserPreferences` instead
*/
get userPreferences() {
return this.getUserPreferences()
}
@computed get isDarkMode() {
@computed getIsDarkMode() {
return (
this.user.userPreferences.get().isDarkMode ??
(this.inferDarkMode ? userPrefersDarkUI() : false)
)
}
@computed get animationSpeed() {
/**
* @deprecated use `getIsDarkMode` instead
*/
get isDarkMode() {
return this.getIsDarkMode()
}
@computed getAnimationSpeed() {
return this.user.userPreferences.get().animationSpeed ?? defaultUserPreferences.animationSpeed
}
@computed get id() {
/**
* @deprecated use `getAnimationSpeed` instead
*/
get animationSpeed() {
return this.getAnimationSpeed()
}
@computed getId() {
return this.user.userPreferences.get().id
}
@computed get name() {
/**
* @deprecated use `getId` instead
*/
get id() {
return this.getId()
}
@computed getName() {
return this.user.userPreferences.get().name ?? defaultUserPreferences.name
}
@computed get locale() {
/**
* @deprecated use `getName` instead
*/
get name() {
return this.getName()
}
@computed getLocale() {
return this.user.userPreferences.get().locale ?? defaultUserPreferences.locale
}
@computed get color() {
/**
* @deprecated use `getLocale` instead
*/
get locale() {
return this.getLocale()
}
@computed getColor() {
return this.user.userPreferences.get().color ?? defaultUserPreferences.color
}
@computed get isSnapMode() {
/**
* @deprecated use `getColor` instead
*/
get color() {
return this.getColor()
}
@computed getIsSnapMode() {
return this.user.userPreferences.get().isSnapMode ?? defaultUserPreferences.isSnapMode
}
/**
* @deprecated use `getIsSnapMode` instead
*/
get isSnapMode() {
return this.getIsSnapMode()
}
}

View file

@ -4,5 +4,5 @@ import { useEditor } from './useEditor'
/** @public */
export function useIsDarkMode() {
const editor = useEditor()
return useValue('isDarkMode', () => editor.user.isDarkMode, [editor])
return useValue('isDarkMode', () => editor.user.getIsDarkMode(), [editor])
}

View file

@ -12,7 +12,7 @@ export function usePeerIds() {
const editor = useEditor()
const $presences = useMemo(() => {
return editor.store.query.records('instance_presence', () => ({
userId: { neq: editor.user.id },
userId: { neq: editor.user.getId() },
}))
}, [editor])

View file

@ -14,11 +14,11 @@ beforeEach(() => {
describe('user', () => {
it('gets a user with the correct color', () => {
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
})
it('gets a user with the correct', () => {
editor.user.updateUserPreferences({ isDarkMode: true })
expect(editor.user.isDarkMode).toBe(true)
expect(editor.user.getIsDarkMode()).toBe(true)
})
})

View file

@ -803,7 +803,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
}
override toSvg(shape: TLArrowShape, ctx: SvgExportContext) {
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
ctx.addExportDef(getFillDefForExport(shape.props.fill, theme))
const color = theme[shape.props.color].solid

View file

@ -184,7 +184,7 @@ export class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
}
override toSvg(shape: TLDrawShape, ctx: SvgExportContext) {
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
ctx.addExportDef(getFillDefForExport(shape.props.fill, theme))
const { color } = shape.props

View file

@ -469,7 +469,7 @@ export class Drawing extends StateNode {
let didSnap = false
let snapSegment: TLDrawShapeSegment | undefined = undefined
const shouldSnap = this.editor.user.isSnapMode ? !ctrlKey : ctrlKey
const shouldSnap = this.editor.user.getIsSnapMode() ? !ctrlKey : ctrlKey
if (shouldSnap) {
if (newSegments.length > 2) {

View file

@ -76,7 +76,7 @@ export class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {
}
override toSvg(shape: TLFrameShape): SVGElement | Promise<SVGElement> {
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')

View file

@ -598,7 +598,7 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
override toSvg(shape: TLGeoShape, ctx: SvgExportContext) {
const { id, props } = shape
const strokeWidth = STROKE_SIZES[props.size]
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
ctx.addExportDef(getFillDefForExport(shape.props.fill, theme))
let svgElm: SVGElement

View file

@ -117,12 +117,12 @@ export class HighlightShapeUtil extends ShapeUtil<TLHighlightShape> {
}
override toSvg(shape: TLHighlightShape) {
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
return highlighterToSvg(getStrokeWidth(shape), shape, OVERLAY_OPACITY, theme)
}
override toBackgroundSvg(shape: TLHighlightShape) {
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
return highlighterToSvg(getStrokeWidth(shape), shape, UNDERLAY_OPACITY, theme)
}

View file

@ -330,7 +330,7 @@ export class LineShapeUtil extends ShapeUtil<TLLineShape> {
}
override toSvg(shape: TLLineShape) {
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
const color = theme[shape.props.color].solid
const spline = getGeometryForLineShape(shape)
const strokeWidth = STROKE_SIZES[shape.props.size]

View file

@ -112,7 +112,7 @@ export class NoteShapeUtil extends ShapeUtil<TLNoteShape> {
override toSvg(shape: TLNoteShape, ctx: SvgExportContext) {
ctx.addExportDef(getFontDefForExport(shape.props.font))
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
const bounds = this.editor.getShapeGeometry(shape).bounds
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')

View file

@ -71,7 +71,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
props: { text, color },
} = shape
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
const { width, height } = this.getMinDimensions(shape)
const {
@ -150,7 +150,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
override toSvg(shape: TLTextShape, ctx: SvgExportContext) {
ctx.addExportDef(getFontDefForExport(shape.props.font))
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() })
const bounds = this.editor.getShapeGeometry(shape).bounds
const text = shape.props.text

View file

@ -208,8 +208,8 @@ export class DraggingHandle extends StateNode {
const { editor, shapeId, initialPagePoint } = this
const { initialHandle, initialPageRotation, initialAdjacentHandle } = this
const hintingShapeIds = this.editor.getHintingShapeIds()
const isSnapMode = this.editor.user.getIsSnapMode()
const {
user: { isSnapMode },
snaps,
inputs: { currentPagePoint, shiftKey, ctrlKey, altKey, pointerVelocity },
} = editor

View file

@ -225,7 +225,7 @@ export class Resizing extends StateNode {
this.editor.snaps.clear()
const shouldSnap = this.editor.user.isSnapMode ? !ctrlKey : ctrlKey
const shouldSnap = this.editor.user.getIsSnapMode() ? !ctrlKey : ctrlKey
if (shouldSnap && selectionRotation % TAU === 0) {
const { nudge } = this.editor.snaps.snapResize({

View file

@ -308,7 +308,7 @@ function getTranslatingSnapshot(editor: Editor) {
let initialSnapPoints: SnapPoint[] = []
if (editor.getSelectedShapeIds().length === 1) {
initialSnapPoints = editor.snaps.snapPointsCache.get(editor.getSelectedShapeIds()[0])!
initialSnapPoints = editor.snaps.getSnapPointsCache().get(editor.getSelectedShapeIds()[0])!
} else {
const selectionPageBounds = editor.getSelectionPageBounds()
if (selectionPageBounds) {
@ -374,7 +374,7 @@ export function moveShapesToPoint({
editor.snaps.clear()
const shouldSnap =
(editor.user.isSnapMode ? !inputs.ctrlKey : inputs.ctrlKey) &&
(editor.user.getIsSnapMode() ? !inputs.ctrlKey : inputs.ctrlKey) &&
editor.inputs.pointerVelocity.len() < 0.5 // ...and if the user is not dragging fast
if (shouldSnap) {

View file

@ -19,7 +19,7 @@ export function MobileStylePanel() {
const relevantStyles = useRelevantStyles()
const color = relevantStyles?.styles.get(DefaultColorStyle)
const theme = getDefaultColorTheme({ isDarkMode: editor.user.isDarkMode })
const theme = getDefaultColorTheme({ isDarkMode: editor.user.getIsDarkMode() })
const currentColor = (
color?.type === 'shared' ? theme[color.value as TLDefaultColorStyle] : theme.black
).solid

View file

@ -92,7 +92,7 @@ function _ButtonPicker<T extends string>(props: ButtonPickerProps<T>) {
const theme = useValue(
'theme',
() => getDefaultColorTheme({ isDarkMode: editor.user.isDarkMode }),
() => getDefaultColorTheme({ isDarkMode: editor.user.getIsDarkMode() }),
[editor]
)

View file

@ -923,7 +923,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: false,
onSelect(source) {
trackEvent('toggle-snap-mode', { source })
editor.user.updateUserPreferences({ isSnapMode: !editor.user.isSnapMode })
editor.user.updateUserPreferences({ isSnapMode: !editor.user.getIsSnapMode() })
},
checkbox: true,
},
@ -935,7 +935,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('toggle-dark-mode', { source })
editor.user.updateUserPreferences({ isDarkMode: !editor.user.isDarkMode })
editor.user.updateUserPreferences({ isDarkMode: !editor.user.getIsDarkMode() })
},
checkbox: true,
},
@ -947,7 +947,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
onSelect(source) {
trackEvent('toggle-reduce-motion', { source })
editor.user.updateUserPreferences({
animationSpeed: editor.user.animationSpeed === 0 ? 1 : 0,
animationSpeed: editor.user.getAnimationSpeed() === 0 ? 1 : 0,
})
},
checkbox: true,

View file

@ -49,10 +49,10 @@ export function TLUiMenuSchemaProvider({ overrides, children }: TLUiMenuSchemaPr
const breakpoint = useBreakpoint()
const isMobile = breakpoint < 5
const isDarkMode = useValue('isDarkMode', () => editor.user.isDarkMode, [editor])
const animationSpeed = useValue('animationSpeed', () => editor.user.animationSpeed, [editor])
const isDarkMode = useValue('isDarkMode', () => editor.user.getIsDarkMode(), [editor])
const animationSpeed = useValue('animationSpeed', () => editor.user.getAnimationSpeed(), [editor])
const isGridMode = useValue('isGridMode', () => editor.getInstanceState().isGridMode, [editor])
const isSnapMode = useValue('isSnapMode', () => editor.user.isSnapMode, [editor])
const isSnapMode = useValue('isSnapMode', () => editor.user.getIsSnapMode(), [editor])
const isToolLock = useValue('isToolLock', () => editor.getInstanceState().isToolLocked, [editor])
const isFocusMode = useValue('isFocusMode', () => editor.getInstanceState().isFocusMode, [editor])
const isDebugMode = useValue('isDebugMode', () => editor.getInstanceState().isDebugMode, [editor])

View file

@ -5,6 +5,6 @@ export function useLanguages() {
const editor = useEditor()
return {
languages: LANGUAGES as readonly TLLanguage[],
currentLanguage: editor.user.locale,
currentLanguage: editor.user.getLocale(),
}
}

View file

@ -39,7 +39,7 @@ export const TranslationProvider = track(function TranslationProvider({
children,
}: TLUiTranslationProviderProps) {
const editor = useEditor()
const locale = editor.user.locale
const locale = editor.user.getLocale()
const getAssetUrl = useAssetUrls()
const [currentTranslation, setCurrentTranslation] = React.useState<TLUiTranslation>(() => {

View file

@ -607,15 +607,15 @@ describe('when the user prefers dark UI', () => {
})
it('isDarkMode should be false by default', () => {
editor = new TestEditor({})
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
})
it('isDarkMode should be false when inferDarkMode is false', () => {
editor = new TestEditor({ inferDarkMode: false })
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
})
it('should be true if the editor was instantiated with inferDarkMode', () => {
editor = new TestEditor({ inferDarkMode: true })
expect(editor.user.isDarkMode).toBe(true)
expect(editor.user.getIsDarkMode()).toBe(true)
})
})
@ -634,14 +634,14 @@ describe('when the user prefers light UI', () => {
})
it('isDarkMode should be false by default', () => {
editor = new TestEditor({})
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
})
it('isDarkMode should be false when inferDarkMode is false', () => {
editor = new TestEditor({ inferDarkMode: false })
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
})
it('should be false if the editor was instantiated with inferDarkMode', () => {
editor = new TestEditor({ inferDarkMode: true })
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
})
})

View file

@ -9,11 +9,11 @@ beforeEach(() => {
describe('TLUserPreferences', () => {
it('allows updating user preferences on the editor', () => {
expect(editor.user.isSnapMode).toBe(false)
expect(editor.user.getIsSnapMode()).toBe(false)
editor.user.updateUserPreferences({ isSnapMode: true })
expect(editor.user.isSnapMode).toBe(true)
expect(editor.user.getIsSnapMode()).toBe(true)
})
it('can be customized', () => {
@ -34,18 +34,18 @@ describe('TLUserPreferences', () => {
}),
})
expect(editor.user.isDarkMode).toBe(true)
expect(editor.user.getIsDarkMode()).toBe(true)
userPreferences.set({
...userPreferences.get(),
isDarkMode: false,
})
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.getIsDarkMode()).toBe(false)
editor.user.updateUserPreferences({ isDarkMode: true })
expect(editor.user.isDarkMode).toBe(true)
expect(editor.user.getIsDarkMode()).toBe(true)
expect(userPreferences.get().isDarkMode).toBe(true)
})
@ -68,11 +68,11 @@ describe('TLUserPreferences', () => {
}),
})
expect(editor.user.animationSpeed).toBe(1)
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.isSnapMode).toBe(false)
expect(editor.user.locale).toBe('en')
expect(editor.user.name).toBe('New User')
expect(editor.user.getAnimationSpeed()).toBe(1)
expect(editor.user.getIsDarkMode()).toBe(false)
expect(editor.user.getIsSnapMode()).toBe(false)
expect(editor.user.getLocale()).toBe('en')
expect(editor.user.getName()).toBe('New User')
})
it('can have unspecified values and it will use defaults', () => {
@ -89,11 +89,11 @@ describe('TLUserPreferences', () => {
}),
})
expect(editor.user.animationSpeed).toBe(1)
expect(editor.user.isDarkMode).toBe(false)
expect(editor.user.isSnapMode).toBe(false)
expect(editor.user.locale).toBe('en')
expect(editor.user.name).toBe('blah')
expect(editor.user.getAnimationSpeed()).toBe(1)
expect(editor.user.getIsDarkMode()).toBe(false)
expect(editor.user.getIsSnapMode()).toBe(false)
expect(editor.user.getLocale()).toBe('en')
expect(editor.user.getName()).toBe('blah')
})
it('allows setting values to null', () => {
@ -110,10 +110,10 @@ describe('TLUserPreferences', () => {
}),
})
expect(editor.user.name).toBe('blah')
expect(editor.user.getName()).toBe('blah')
editor.user.updateUserPreferences({ name: null })
expect(editor.user.name).toBe('New User')
expect(editor.user.getName()).toBe('New User')
expect(setUserPreferences).toHaveBeenCalledTimes(1)
expect(setUserPreferences).toHaveBeenLastCalledWith({
id: '123',