Skip to content

Commit

Permalink
Content Model: Allow clear cache from formatContentModel (#2186)
Browse files Browse the repository at this point in the history
* Move formatWithContentModel to be a core API

* Content Model: Allow clear cache from formatContentModel
  • Loading branch information
JiuqingSong authored Nov 6, 2023
1 parent 77b891b commit 095249e
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChangeSource } from '../../publicTypes/event/ContentModelContentChangedEvent';
import { ColorTransformDirection, EntityOperation, PluginEventType } from 'roosterjs-editor-types';
import type ContentModelContentChangedEvent from '../../publicTypes/event/ContentModelContentChangedEvent';
import { ChangeSource } from '../../publicTypes/event/ContentModelContentChangedEvent';
import type {
ContentModelEditorCore,
FormatContentModel,
Expand Down Expand Up @@ -62,15 +62,18 @@ export const formatContentModel: FormatContentModel = (core, formatter, options)

const eventData: ContentModelContentChangedEvent = {
eventType: PluginEventType.ContentChanged,
contentModel: model,
selection: selection,
contentModel: context.clearModelCache ? undefined : model,
selection: context.clearModelCache ? undefined : selection,
source: changeSource || ChangeSource.Format,
data: getChangeData?.(),
additionalData: {
formatApiName: apiName,
},
};
core.api.triggerEvent(core, eventData, true /*broadcast*/);
} else if (context.clearModelCache) {
core.cache.cachedModel = undefined;
core.cache.cachedSelection = undefined;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ export function handleKeyboardEventResult(
context: FormatWithContentModelContext
): boolean {
context.skipUndoSnapshot = true;
context.clearModelCache = false;

switch (result) {
case DeleteResult.NotDeleted:
// We have not delete anything, we will let browser handle this event
// We have not delete anything, we will let browser handle this event, so that current cached model may be invalid
context.clearModelCache = true;

// Return false here since we didn't do any change to Content Model, so no need to rewrite with Content Model
return false;

case DeleteResult.NothingToDelete:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export interface ContentModelContentChangedEventData extends ContentChangedEvent
/**
* The content model that is applied which causes this content changed event
*/
contentModel: ContentModelDocument;
contentModel?: ContentModelDocument;

/**
* Selection range applied to the document
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ export interface FormatWithContentModelContext {
* Need to be set by the formatter function
*/
skipUndoSnapshot?: boolean;

/**
* @optional
* When set to true, formatWithContentModel API will not keep cached Content Model. Next time when we need a Content Model, a new one will be created
*/
clearModelCache?: boolean;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('formatContentModel', () => {
triggerEvent,
},
lifecycle: {},
cache: {},
getVisibleViewport,
} as any) as ContentModelEditorCore;
});
Expand Down Expand Up @@ -459,4 +460,60 @@ describe('formatContentModel', () => {
true
);
});

it('Has shouldClearCachedModel', () => {
formatContentModel(
core,
(model, context) => {
context.clearModelCache = true;
return true;
},
{
apiName,
}
);

expect(addUndoSnapshot).toHaveBeenCalled();
expect(setContentModel).toHaveBeenCalledTimes(1);
expect(setContentModel).toHaveBeenCalledWith(core, mockedModel, undefined, undefined);
expect(triggerEvent).toHaveBeenCalledTimes(1);
expect(triggerEvent).toHaveBeenCalledWith(
core,
{
eventType: PluginEventType.ContentChanged,
contentModel: undefined,
selection: undefined,
source: ChangeSource.Format,
data: undefined,
additionalData: {
formatApiName: apiName,
},
},
true
);
});

it('Has shouldClearCachedModel, and callback return false', () => {
core.cache.cachedModel = 'Model' as any;
core.cache.cachedSelection = 'Selection' as any;

formatContentModel(
core,
(model, context) => {
context.clearModelCache = true;
return false;
},
{
apiName,
}
);

expect(addUndoSnapshot).not.toHaveBeenCalled();
expect(setContentModel).not.toHaveBeenCalled();
expect(triggerEvent).not.toHaveBeenCalled();
expect(core.cache).toEqual({
cachedModel: undefined,
cachedSelection: undefined,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ describe('handleKeyboardEventResult', () => {
rawEvent: mockedEvent,
});
expect(context.skipUndoSnapshot).toBeTrue();
expect(context.clearModelCache).toBeFalsy();
});

it('DeleteResult.NotDeleted', () => {
Expand All @@ -88,6 +89,7 @@ describe('handleKeyboardEventResult', () => {
expect(cacheContentModel).not.toHaveBeenCalledWith(null);
expect(triggerPluginEvent).not.toHaveBeenCalled();
expect(context.skipUndoSnapshot).toBeTrue();
expect(context.clearModelCache).toBeTruthy();
});

it('DeleteResult.Range', () => {
Expand All @@ -114,6 +116,7 @@ describe('handleKeyboardEventResult', () => {
rawEvent: mockedEvent,
});
expect(context.skipUndoSnapshot).toBeFalse();
expect(context.clearModelCache).toBeFalsy();
});

it('DeleteResult.NothingToDelete', () => {
Expand All @@ -138,6 +141,7 @@ describe('handleKeyboardEventResult', () => {
expect(cacheContentModel).not.toHaveBeenCalled();
expect(triggerPluginEvent).not.toHaveBeenCalled();
expect(context.skipUndoSnapshot).toBeTrue();
expect(context.clearModelCache).toBeFalsy();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('keyboardDelete', () => {
expectedResult: ContentModelDocument,
expectedSteps: DeleteSelectionStep[],
expectedDelete: DeleteResult,
expectedClearModelCache: boolean,
calledTimes: number
) {
deleteSelectionSpy.and.returnValue({
Expand Down Expand Up @@ -73,6 +74,7 @@ describe('keyboardDelete', () => {
rawEvent: mockedEvent,
newImages: [],
skipUndoSnapshot: true,
clearModelCache: expectedClearModelCache,
});
}

Expand All @@ -89,6 +91,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, forwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand All @@ -106,6 +109,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, backwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand All @@ -125,6 +129,7 @@ describe('keyboardDelete', () => {
},
[null!, forwardDeleteWordSelection, forwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand All @@ -144,6 +149,7 @@ describe('keyboardDelete', () => {
},
[null!, backwardDeleteWordSelection, backwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand All @@ -163,6 +169,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, forwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand All @@ -182,6 +189,7 @@ describe('keyboardDelete', () => {
},
[deleteAllSegmentBefore, null!, backwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand Down Expand Up @@ -223,6 +231,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, forwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand Down Expand Up @@ -264,6 +273,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, backwardDeleteCollapsedSelection],
DeleteResult.NotDeleted,
true,
0
);
});
Expand Down Expand Up @@ -315,6 +325,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, forwardDeleteCollapsedSelection],
DeleteResult.SingleChar,
false,
1
);
});
Expand Down Expand Up @@ -366,6 +377,7 @@ describe('keyboardDelete', () => {
},
[null!, null!, backwardDeleteCollapsedSelection],
DeleteResult.SingleChar,
false,
1
);
});
Expand Down

0 comments on commit 095249e

Please sign in to comment.