diff --git a/src/components/grid/grid.ts b/src/components/grid/grid.ts index 206c5e71a4..153a7af991 100644 --- a/src/components/grid/grid.ts +++ b/src/components/grid/grid.ts @@ -911,4 +911,12 @@ export class Grid extends Component { get displaySelectionHandler() { return this.env.isMobile() && this.composerFocusStore.activeComposer.editionMode === "inactive"; } + + get displayTableResizer() { + return ( + this.env.model.getters.isGridSelectionActive() && + !this.env.model.getters.isReadonly() && + !this.env.model.getters.isSheetLocked(this.env.model.getters.getActiveSheetId()) + ); + } } diff --git a/src/components/grid/grid.xml b/src/components/grid/grid.xml index 1d4660462f..f6436da904 100644 --- a/src/components/grid/grid.xml +++ b/src/components/grid/grid.xml @@ -58,7 +58,7 @@ onClose="() => this.closeMenu()" /> diff --git a/src/components/tables/table_resizer/table_resizer.ts b/src/components/tables/table_resizer/table_resizer.ts index 680167ac23..ff3ff9bbd5 100644 --- a/src/components/tables/table_resizer/table_resizer.ts +++ b/src/components/tables/table_resizer/table_resizer.ts @@ -32,11 +32,6 @@ export class TableResizer extends Component { get containerStyle(): string { const tableZone = this.props.table.range.zone; - const sheetId = this.props.table.range.sheetId; - - if (this.env.model.getters.isReadonly() || this.env.model.getters.isSheetLocked(sheetId)) { - return cssPropertiesToCss({ display: "none" }); - } const bottomRight = { ...tableZone, left: tableZone.right, top: tableZone.bottom }; const rect = this.env.model.getters.getVisibleRect(bottomRight); if (rect.height === 0 || rect.width === 0) { diff --git a/src/model.ts b/src/model.ts index 3b4b72ba63..82c0b0a320 100644 --- a/src/model.ts +++ b/src/model.ts @@ -24,7 +24,10 @@ import { statefulUIPluginRegistry, } from "./plugins/plugin_registries"; import { UIPlugin, UIPluginConfig, UIPluginConstructor } from "./plugins/ui_plugin"; -import { SelectionStreamProcessorImpl } from "./selection_stream/selection_stream_processor"; +import { + selectionModifiers, + SelectionStreamProcessorImpl, +} from "./selection_stream/selection_stream_processor"; import { StateObserver } from "./state_observer"; import { _t, setDefaultTranslationMethod } from "./translation"; import { StateUpdateMessage } from "./types/collaborative/transport_service"; @@ -121,6 +124,7 @@ export class Model extends EventBus implements CommandDispatcher { private state: StateObserver; readonly selection: SelectionStreamProcessor; + readonly pluginSelection: SelectionStreamProcessor; /** * Getters are the main way the rest of the UI read data from the model. Also, @@ -187,6 +191,21 @@ export class Model extends EventBus implements CommandDispatcher { // Initiate stream processor this.selection = new SelectionStreamProcessorImpl(this.getters); + this.pluginSelection = new Proxy(this.selection, { + observable: false, + get: (target, prop, receiver) => { + const value = Reflect.get(target, prop, receiver); + if (typeof value !== "function" || !selectionModifiers.has(prop)) { + return value; + } + return (...args: unknown[]) => { + if (!this.getters.isGridSelectionActive()) { + this.selection.getBackToDefault(); + } + return (value as Function).apply(target, args); + }; + }, + } as ProxyHandler); this.coreHandlers.push(this.range); this.handlers.push(this.range); @@ -433,7 +452,7 @@ export class Model extends EventBus implements CommandDispatcher { stateObserver: this.state, dispatch: this.dispatch, canDispatch: this.canDispatch, - selection: this.selection, + selection: this.pluginSelection, moveClient: this.session.move.bind(this.session), custom: this.config.custom, uiActions: this.config, diff --git a/src/selection_stream/selection_stream_processor.ts b/src/selection_stream/selection_stream_processor.ts index 00f0aaf763..010fa3b48b 100644 --- a/src/selection_stream/selection_stream_processor.ts +++ b/src/selection_stream/selection_stream_processor.ts @@ -677,3 +677,19 @@ export class SelectionStreamProcessorImpl implements SelectionStreamProcessor { ); } } + +export const selectionModifiers: Set = new Set([ + "selectZone", + "selectCell", + "moveAnchorCell", + "updateAnchorCell", + "setAnchorCorner", + "addCellToSelection", + "resizeAnchorZone", + "selectColumn", + "selectRow", + "selectAll", + "loopSelection", + "selectTableAroundSelection", + "commitSelection", +]); diff --git a/tests/model/model.test.ts b/tests/model/model.test.ts index 498759b3ff..2d89b1b420 100644 --- a/tests/model/model.test.ts +++ b/tests/model/model.test.ts @@ -420,4 +420,41 @@ describe("Model", () => { type: "SNAPSHOT", }); }); + + test("Selection Processor falls back to gridSelection when invoked from the plugins", () => { + class MyUIPlugin extends UIPlugin { + handle(cmd: Command) { + // @ts-ignore + if (cmd.type === "CAPTURE") { + this.selection.capture( + this, + { + cell: { col: 0, row: 0 }, + zone: toZone("A1"), + }, + { + handleEvent: () => { + throw new Error("Should not be called"); + }, + } + ); + } + // @ts-ignore + else if (cmd.type === "MOVE") { + this.selection.selectCell(0, 1); + } + } + } + addTestPlugin(featurePluginRegistry, MyUIPlugin); + const model = new Model(); + expect(model.getters.isGridSelectionActive()).toBe(true); + expect(model.getters.getSelectedZone()).toEqual(toZone("A1")); + // @ts-ignore + model.dispatch("CAPTURE"); + expect(model.getters.isGridSelectionActive()).toBe(false); + // @ts-ignore + model.dispatch("MOVE"); + expect(model.getters.isGridSelectionActive()).toBe(true); + expect(model.getters.getSelectedZone()).toEqual(toZone("A2")); + }); }); diff --git a/tests/table/table_resizer_component.test.ts b/tests/table/table_resizer_component.test.ts index 5e55c12edb..4990d7ef95 100644 --- a/tests/table/table_resizer_component.test.ts +++ b/tests/table/table_resizer_component.test.ts @@ -1,4 +1,5 @@ import { Model, UID } from "../../src"; +import { CellComposerStore } from "../../src/components/composer/composer/cell_composer_store"; import { Grid } from "../../src/components/grid/grid"; import { DEFAULT_CELL_HEIGHT, DEFAULT_CELL_WIDTH } from "../../src/constants"; import { toZone, zoneToXc } from "../../src/helpers/zones"; @@ -114,4 +115,14 @@ describe("Table resizer component", () => { await nextTick(); expect(".o-table-resizer").toHaveCount(0); }); + + test("table resizer is not loaded when the grid selection is not active", async () => { + createTable(model, "A1:B2"); + await nextTick(); + expect(".o-table-resizer").toHaveCount(1); + // start the edition and steal the selection from the grid + env.getStore(CellComposerStore).startEdition(); + await nextTick(); + expect(".o-table-resizer").toHaveCount(0); + }); });