From 7bb225e95f05e8ab23b2bb08c9ea85eea1236b9c Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 14 Jun 2022 16:25:43 +0000 Subject: [PATCH 1/3] fix(picker-column-internal): quickly switching off an input mode column no longer resets scroll --- .../picker-column-internal.tsx | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/core/src/components/picker-column-internal/picker-column-internal.tsx b/core/src/components/picker-column-internal/picker-column-internal.tsx index 8110b2d0ab9..c4a4536af44 100644 --- a/core/src/components/picker-column-internal/picker-column-internal.tsx +++ b/core/src/components/picker-column-internal/picker-column-internal.tsx @@ -24,7 +24,8 @@ import type { PickerColumnItem } from './picker-column-internal-interfaces'; }) export class PickerColumnInternal implements ComponentInterface { private destroyScrollListener?: () => void; - private hapticsStarted = false; + private isScrolling = false; + private scrollEndCallback?: () => void; private isColumnVisible = false; @State() isActive = false; @@ -187,11 +188,30 @@ export class PickerColumnInternal implements ComponentInterface { const isColumnActive = inputModeColumn === undefined || inputModeColumn === this.el; if (!useInputMode || !isColumnActive) { - this.isActive = false; + this.setInputModeActive(false); return; } - this.isActive = true; + this.setInputModeActive(true); + }; + + /** + * Setting isActive will cause a re-render. + * As a result, we do not want to cause the + * re-render mid scroll as this will cause + * the picker column to jump back to + * whatever value was selected at the + * start of the scroll interaction. + */ + private setInputModeActive = (state: boolean) => { + if (this.isScrolling) { + this.scrollEndCallback = () => { + this.isActive = state; + }; + return; + } + + this.isActive = state; }; /** @@ -213,9 +233,9 @@ export class PickerColumnInternal implements ComponentInterface { timeout = undefined; } - if (!this.hapticsStarted) { + if (!this.isScrolling) { hapticSelectionStart(); - this.hapticsStarted = true; + this.isScrolling = true; } /** @@ -260,7 +280,19 @@ export class PickerColumnInternal implements ComponentInterface { if (selectedItem.value !== this.value) { this.setValue(selectedItem.value); hapticSelectionEnd(); - this.hapticsStarted = false; + this.isScrolling = false; + + /** + * Certain tasks (such as those that + * cause re-renders) should only be done + * once scrolling has finished, otherwise + * flickering may occur. + */ + const { scrollEndCallback } = this; + if (scrollEndCallback) { + scrollEndCallback(); + this.scrollEndCallback = undefined; + } } }, 250); }); From 9a125ab37a00da813be98f537d719ef7926cd51f Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 14 Jun 2022 16:46:34 +0000 Subject: [PATCH 2/3] fix(): ensure isScrolling is correctly reset --- .../picker-column-internal.tsx | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/core/src/components/picker-column-internal/picker-column-internal.tsx b/core/src/components/picker-column-internal/picker-column-internal.tsx index c4a4536af44..1afa4ac8ca3 100644 --- a/core/src/components/picker-column-internal/picker-column-internal.tsx +++ b/core/src/components/picker-column-internal/picker-column-internal.tsx @@ -263,6 +263,20 @@ export class PickerColumnInternal implements ComponentInterface { activeElement.classList.add(PICKER_COL_ACTIVE); timeout = setTimeout(() => { + this.isScrolling = false; + + /** + * Certain tasks (such as those that + * cause re-renders) should only be done + * once scrolling has finished, otherwise + * flickering may occur. + */ + const { scrollEndCallback } = this; + if (scrollEndCallback) { + scrollEndCallback(); + this.scrollEndCallback = undefined; + } + const dataIndex = activeElement.getAttribute('data-index'); /** @@ -280,19 +294,6 @@ export class PickerColumnInternal implements ComponentInterface { if (selectedItem.value !== this.value) { this.setValue(selectedItem.value); hapticSelectionEnd(); - this.isScrolling = false; - - /** - * Certain tasks (such as those that - * cause re-renders) should only be done - * once scrolling has finished, otherwise - * flickering may occur. - */ - const { scrollEndCallback } = this; - if (scrollEndCallback) { - scrollEndCallback(); - this.scrollEndCallback = undefined; - } } }, 250); }); From e732795677c5a88cdc5ae6fb1641371a8b759697 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 14 Jun 2022 16:47:55 +0000 Subject: [PATCH 3/3] chore(): clean up haptic resources --- .../picker-column-internal/picker-column-internal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/components/picker-column-internal/picker-column-internal.tsx b/core/src/components/picker-column-internal/picker-column-internal.tsx index 1afa4ac8ca3..77f473e146a 100644 --- a/core/src/components/picker-column-internal/picker-column-internal.tsx +++ b/core/src/components/picker-column-internal/picker-column-internal.tsx @@ -264,6 +264,7 @@ export class PickerColumnInternal implements ComponentInterface { timeout = setTimeout(() => { this.isScrolling = false; + hapticSelectionEnd(); /** * Certain tasks (such as those that @@ -293,7 +294,6 @@ export class PickerColumnInternal implements ComponentInterface { if (selectedItem.value !== this.value) { this.setValue(selectedItem.value); - hapticSelectionEnd(); } }, 250); });