From 385302d81cfd1abf79a1d1ae750351ce3f19ee5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Lef=C3=A8vre=20=28lul=29?= Date: Mon, 16 Sep 2024 16:55:42 +0200 Subject: [PATCH] [FIX] auto-complete: hide auto-complete when selecting a cell Steps to reproduce: - Insert a pivot - type in a composer =PIVOT( (the auto-complete should show up with the pivot id) - click on a cell to fill in the reference: you end up with =PIVOT(B3 - press Enter => you get =PIVOT(1B3 instead of the composer being closed Task: 4022927 --- .../autocomplete_dropdown_store.ts | 9 +++++++++ src/selection_stream/event_stream.ts | 4 ++++ .../selection_stream_processor.ts | 5 +++++ .../composer_integration_component.test.ts | 20 +++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/src/components/composer/autocomplete_dropdown/autocomplete_dropdown_store.ts b/src/components/composer/autocomplete_dropdown/autocomplete_dropdown_store.ts index 41cd6c68f9..16c50ede37 100644 --- a/src/components/composer/autocomplete_dropdown/autocomplete_dropdown_store.ts +++ b/src/components/composer/autocomplete_dropdown/autocomplete_dropdown_store.ts @@ -1,4 +1,5 @@ import { AutoCompleteProposal, AutoCompleteProvider } from "../../../registries"; +import { Get } from "../../../store_engine"; import { SpreadsheetStore } from "../../../stores"; export class AutoCompleteStore extends SpreadsheetStore { @@ -6,6 +7,14 @@ export class AutoCompleteStore extends SpreadsheetStore { selectedIndex: number | undefined = undefined; provider: AutoCompleteProvider | undefined; + constructor(get: Get) { + super(get); + this.model.selection.observe(this, { + handleEvent: () => this.hide(), + }); + this.onDispose(() => this.model.selection.stopWatching(this)); + } + get selectedProposal(): AutoCompleteProposal | undefined { if (this.selectedIndex === undefined || this.provider === undefined) { return undefined; diff --git a/src/selection_stream/event_stream.ts b/src/selection_stream/event_stream.ts index 46675ac97f..54dcf8f856 100644 --- a/src/selection_stream/event_stream.ts +++ b/src/selection_stream/event_stream.ts @@ -65,6 +65,10 @@ export class EventStream { this.observers.set(owner, { owner, callbacks }); } + stopWatching(owner: Owner) { + this.observers.delete(owner); + } + /** * Capture the stream for yourself */ diff --git a/src/selection_stream/selection_stream_processor.ts b/src/selection_stream/selection_stream_processor.ts index 001e5444af..834d144b54 100644 --- a/src/selection_stream/selection_stream_processor.ts +++ b/src/selection_stream/selection_stream_processor.ts @@ -31,6 +31,7 @@ type StatefulStream = { resetDefaultAnchor: (owner: unknown, state: State) => void; resetAnchor: (owner: unknown, state: State) => void; observe: (owner: unknown, callbacks: StreamCallbacks) => void; + stopWatching: (owner: unknown) => void; release: (owner: unknown) => void; getBackToDefault(): void; }; @@ -114,6 +115,10 @@ export class SelectionStreamProcessorImpl implements SelectionStreamProcessor { this.stream.observe(owner, callbacks); } + stopWatching(owner: unknown) { + this.stream.stopWatching(owner); + } + release(owner: unknown) { if (this.stream.isListening(owner)) { this.stream.release(owner); diff --git a/tests/composer/composer_integration_component.test.ts b/tests/composer/composer_integration_component.test.ts index d542279d30..1e5c07a147 100644 --- a/tests/composer/composer_integration_component.test.ts +++ b/tests/composer/composer_integration_component.test.ts @@ -37,6 +37,7 @@ import { import { getActivePosition, getActiveSheetFullScrollInfo, + getCell, getCellContent, getCellText, getSelectionAnchorCellXc, @@ -50,6 +51,7 @@ import { typeInComposerGrid as typeInComposerGridHelper, typeInComposerTopBar as typeInComposerTopBarHelper, } from "../test_helpers/helpers"; +import { addPivot } from "../test_helpers/pivot_helpers"; jest.mock("../../src/components/composer/content_editable_helper.ts", () => require("../__mocks__/content_editable_helper") @@ -154,6 +156,24 @@ describe("Composer interactions", () => { expect(fixture.querySelector(".o-grid .o-autocomplete-dropdown")).toBeNull(); }); + test("autocomplete disappear when selecting a cell in the grid", async () => { + setCellContent(model, "B1", "Customer"); + setCellContent(model, "B2", "Alice"); + + addPivot(model, "B1:B2", { + columns: [], + rows: [], + measures: [{ name: "Customer", aggregator: "count" }], + }); + await keyDown({ key: "Enter" }); + await typeInComposerGrid("=PIVOT("); + expect(fixture.querySelector(".o-grid .o-autocomplete-dropdown")).not.toBeNull(); + await clickCell(model, "B3"); + expect(fixture.querySelector(".o-grid .o-autocomplete-dropdown")).toBeNull(); + await keyDown({ key: "Enter" }); + expect(getCell(model, "A1")?.content).toBe("=PIVOT(B3)"); + }); + test("focus top bar composer does not resize grid composer when autocomplete is displayed", async () => { await keyDown({ key: "Enter" }); const topBarComposer = document.querySelector(".o-spreadsheet-topbar .o-composer")!;