From d425bd5d05f0b29642e8c75c5dea17023f7be90b Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Thu, 12 Oct 2023 22:59:21 +0530 Subject: [PATCH 1/4] debounced updateWindow --- lib/useKWindowDimensions.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/useKWindowDimensions.js b/lib/useKWindowDimensions.js index 244c87fd8..63b55b93f 100644 --- a/lib/useKWindowDimensions.js +++ b/lib/useKWindowDimensions.js @@ -1,5 +1,6 @@ import './composition-api'; //Due to @vue/composition-api shortcomings, add plugin prior to use in kolibri, studio and tests import { onMounted, onUnmounted, ref } from '@vue/composition-api'; +import debounce from 'lodash/debounce'; /** Global variables */ export const windowWidth = ref(null); @@ -16,6 +17,8 @@ const updateWindow = () => { windowHeight.value = metrics.height; }; +const debouncedUpdateWindow = debounce(updateWindow, 200); + /** * Returns window inner width and height * @returns {Object} The window's inner width and height @@ -73,12 +76,12 @@ function isUseKWindowDimensionsActiveElsewhere() { export default function useKWindowDimensions() { onMounted(() => { usageCount.value++; - addWindowListener(updateWindow); + addWindowListener(debouncedUpdateWindow); }); onUnmounted(() => { usageCount.value--; - removeWindowListener(updateWindow); + removeWindowListener(debouncedUpdateWindow); }); return { From 5a569c64c63b26db86fe0d1fe9afed133675a53d Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Sat, 14 Oct 2023 23:50:30 +0530 Subject: [PATCH 2/4] use throttle to optimize updateWindow --- lib/__tests__/useKWindowDimensions.spec.js | 14 ++- .../__tests__/useKResponsiveWindow.spec.js | 90 ++++++++++++++----- lib/useKWindowDimensions.js | 8 +- 3 files changed, 80 insertions(+), 32 deletions(-) diff --git a/lib/__tests__/useKWindowDimensions.spec.js b/lib/__tests__/useKWindowDimensions.spec.js index 80ff266d2..b33a9204b 100644 --- a/lib/__tests__/useKWindowDimensions.spec.js +++ b/lib/__tests__/useKWindowDimensions.spec.js @@ -22,8 +22,11 @@ describe('useKWindowDimensions composable', () => { it('check if windowWidth and windowHeight properties are initialized on mount', () => { const wrapper = mount(TestComponent); - expect(wrapper.vm.windowWidth).toEqual(expect.any(Number)); - expect(wrapper.vm.windowHeight).toEqual(expect.any(Number)); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowWidth).toEqual(expect.any(Number)); + expect(wrapper.vm.windowHeight).toEqual(expect.any(Number)); + }, 20); }); it('check if windowWidth and windowHeight change when window is resized', () => { @@ -31,7 +34,10 @@ describe('useKWindowDimensions composable', () => { expect(wrapper.vm.windowWidth).not.toEqual(600); expect(wrapper.vm.windowHeight).not.toEqual(400); resizeWindow(600, 400); - expect(wrapper.vm.windowWidth).toEqual(600); - expect(wrapper.vm.windowHeight).toEqual(400); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowWidth).toEqual(600); + expect(wrapper.vm.windowHeight).toEqual(400); + }, 20); }); }); diff --git a/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js b/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js index 146a4882f..fd498288e 100644 --- a/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js +++ b/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js @@ -36,16 +36,19 @@ describe('useKResponsiveWindow composable', () => { resizeWindow(1700); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowWidth).toEqual(1700); - expect(wrapper.vm.windowHeight).toEqual(768); - expect(wrapper.vm.windowBreakpoint).toEqual(7); - expect(wrapper.vm.windowIsPortrait).toEqual(false); - expect(wrapper.vm.windowIsLandscape).toEqual(true); - expect(wrapper.vm.windowGutter).toEqual(24); - expect(wrapper.vm.windowIsShort).toEqual(false); - expect(wrapper.vm.windowIsLarge).toEqual(true); - expect(wrapper.vm.windowIsMedium).toEqual(false); - expect(wrapper.vm.windowIsSmall).toEqual(false); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowWidth).toEqual(1700); + expect(wrapper.vm.windowHeight).toEqual(768); + expect(wrapper.vm.windowBreakpoint).toEqual(7); + expect(wrapper.vm.windowIsPortrait).toEqual(false); + expect(wrapper.vm.windowIsLandscape).toEqual(true); + expect(wrapper.vm.windowGutter).toEqual(24); + expect(wrapper.vm.windowIsShort).toEqual(false); + expect(wrapper.vm.windowIsLarge).toEqual(true); + expect(wrapper.vm.windowIsMedium).toEqual(false); + expect(wrapper.vm.windowIsSmall).toEqual(false); + }, 20); }); describe('check if windowBreakpoint is set on width change', () => { @@ -53,56 +56,80 @@ describe('useKResponsiveWindow composable', () => { resizeWindow(400); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(0); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(0); + }, 20); }); it('windowBreakpoint is 1 if 480px < width <= 600px', async () => { resizeWindow(540); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(1); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(1); + }, 20); }); it('windowBreakpoint is 2 if 600px < width <= 840px', async () => { resizeWindow(800); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(2); + // Wait for the throttling delay + setInterval(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(2); + }, 20); }); it('windowBreakpoint is 3 if 840px < width <= 944px', async () => { resizeWindow(944); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(3); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(3); + }, 20); }); it('windowBreakpoint is 4 if 944px < width <= 1264px', async () => { resizeWindow(1264); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(4); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(4); + }, 20); }); it('windowBreakpoint is 5 if 1264px < width <= 1424px', async () => { resizeWindow(1424); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(5); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(5); + }, 20); }); it('windowBreakpoint is 6 if 1424px < width <= 1584px', async () => { resizeWindow(1584); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(6); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(6); + }, 20); }); it('windowBreakpoint is 7 if width >= 1601px', async () => { resizeWindow(1800); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(7); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(7); + }, 20); }); }); @@ -111,7 +138,10 @@ describe('useKResponsiveWindow composable', () => { resizeWindow(601); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowIsSmall).toEqual(false); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowIsSmall).toEqual(false); + }, 20); }); it('windowIsSmall is true if width <= 600px', async () => { @@ -134,7 +164,10 @@ describe('useKResponsiveWindow composable', () => { resizeWindow(700); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowIsMedium).toEqual(true); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowIsMedium).toEqual(true); + }, 20); }); }); @@ -150,7 +183,10 @@ describe('useKResponsiveWindow composable', () => { resizeWindow(841); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowIsLarge).toEqual(true); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowIsLarge).toEqual(true); + }, 20); }); }); @@ -193,14 +229,20 @@ describe('useKResponsiveWindow composable', () => { resizeWindow(500, 500); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowBreakpoint).toEqual(1); - expect(wrapper.vm.windowGutter).toEqual(16); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowBreakpoint).toEqual(1); + expect(wrapper.vm.windowGutter).toEqual(16); + }, 20); }); it('windowGutter is 24px if windowIsSmall is false(width > 600px)', async () => { resizeWindow(841); const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); - expect(wrapper.vm.windowGutter).toEqual(24); + // Wait for the throttling delay + setTimeout(() => { + expect(wrapper.vm.windowGutter).toEqual(24); + }, 20); }); }); }); diff --git a/lib/useKWindowDimensions.js b/lib/useKWindowDimensions.js index 63b55b93f..d0e54bbdf 100644 --- a/lib/useKWindowDimensions.js +++ b/lib/useKWindowDimensions.js @@ -1,6 +1,6 @@ import './composition-api'; //Due to @vue/composition-api shortcomings, add plugin prior to use in kolibri, studio and tests import { onMounted, onUnmounted, ref } from '@vue/composition-api'; -import debounce from 'lodash/debounce'; +import { throttle } from 'frame-throttle'; /** Global variables */ export const windowWidth = ref(null); @@ -17,7 +17,7 @@ const updateWindow = () => { windowHeight.value = metrics.height; }; -const debouncedUpdateWindow = debounce(updateWindow, 200); +const throttledUpdateWindow = throttle(updateWindow); /** * Returns window inner width and height @@ -76,12 +76,12 @@ function isUseKWindowDimensionsActiveElsewhere() { export default function useKWindowDimensions() { onMounted(() => { usageCount.value++; - addWindowListener(debouncedUpdateWindow); + addWindowListener(throttledUpdateWindow); }); onUnmounted(() => { usageCount.value--; - removeWindowListener(debouncedUpdateWindow); + removeWindowListener(throttledUpdateWindow); }); return { From 9f4785b676ad68dbea7e0f6d6f6bdad862f727c5 Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Mon, 16 Oct 2023 22:17:02 +0530 Subject: [PATCH 3/4] fix lint issue --- lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js b/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js index fd498288e..702ddd009 100644 --- a/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js +++ b/lib/useKResponsiveWindow/__tests__/useKResponsiveWindow.spec.js @@ -67,7 +67,7 @@ describe('useKResponsiveWindow composable', () => { const wrapper = mount(TestComponent()); await wrapper.vm.$nextTick(); // Wait for the throttling delay - setTimeout(() => { + setTimeout(() => { expect(wrapper.vm.windowBreakpoint).toEqual(1); }, 20); }); From 17c0e6ed605210b8a3cd6b0f748525d54edba47a Mon Sep 17 00:00:00 2001 From: MisRob Date: Tue, 17 Oct 2023 12:27:51 +0200 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42e8ada00..1ab7177c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,17 @@ Changelog is rather internal in nature. See release notes for the public overvie +- [#469] + - **Description:** Throttle the resize listener handler + - **Products impact:** updated API + - **Addresses:** https://github.com/learningequality/kolibri-design-system/issues/461 + - **Components:** useKResponsiveWindow + - **Breaking:** no + - **Impacts a11y:** no + - **Guidance:** - + +[#469]: https://github.com/learningequality/kolibri-design-system/pull/469 + - [#463] - **Description:** Add deprecation warning for KResponsiveWindowMixin - **Products impact:** updated API