From e827affd97f4cd3dbff4296c8686b77fab4a06b4 Mon Sep 17 00:00:00 2001 From: Danny Budzinski Date: Fri, 19 Jan 2024 11:28:23 +0100 Subject: [PATCH 1/5] fix: prevent slider from getting stuck in non-anmiated mode --- src/components/TileDock/TileDock.tsx | 56 ++++++++++++++++------------ 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/components/TileDock/TileDock.tsx b/src/components/TileDock/TileDock.tsx index 6375ea0a2..ff44868fe 100644 --- a/src/components/TileDock/TileDock.tsx +++ b/src/components/TileDock/TileDock.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; +import React, { type ReactNode, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import styles from './TileDock.module.scss'; @@ -19,10 +19,10 @@ export type TileDockProps = { animated?: boolean; wrapWithEmptyTiles?: boolean; transitionTime?: string; - renderTile: (item: T, isInView: boolean) => JSX.Element; - renderLeftControl?: (handleClick: () => void) => JSX.Element; - renderRightControl?: (handleClick: () => void) => JSX.Element; - renderPaginationDots?: (index: number, pageIndex: number) => JSX.Element; + renderTile: (item: T, isInView: boolean) => ReactNode; + renderLeftControl?: (handleClick: () => void) => ReactNode; + renderRightControl?: (handleClick: () => void) => ReactNode; + renderPaginationDots?: (index: number, pageIndex: number) => ReactNode; }; type Tile = { @@ -75,11 +75,11 @@ function TileDock({ renderRightControl, renderPaginationDots, }: TileDockProps) { - const [index, setIndex] = useState(0); - const [slideToIndex, setSlideToIndex] = useState(0); - const [transform, setTransform] = useState(-100); - const [doAnimationReset, setDoAnimationReset] = useState(false); - const [hasTransition, setHasTransition] = useState(false); + const [index, setIndex] = useState(0); + const [slideToIndex, setSlideToIndex] = useState(0); + const [transform, setTransform] = useState(-100); + const [animationDone, setAnimationDone] = useState(false); + const [isAnimationRunning, setIsAnimationRunning] = useState(false); const frameRef = useRef() as React.MutableRefObject; const tileWidth: number = 100 / tilesToShow; @@ -90,7 +90,7 @@ function TileDock({ return sliceItems(items, isMultiPage, index, tilesToShow, cycleMode); }, [items, isMultiPage, index, tilesToShow, cycleMode]); - const transitionBasis: string = isMultiPage && animated && hasTransition ? `transform ${transitionTime} ease` : ''; + const transitionBasis: string = isMultiPage && animated && isAnimationRunning ? `transform ${transitionTime} ease` : ''; const needControls: boolean = showControls && isMultiPage; const showLeftControl: boolean = needControls && !(cycleMode === 'stop' && index === 0); @@ -98,7 +98,8 @@ function TileDock({ const slide = useCallback( (direction: Direction): void => { - if (hasTransition) { + // Debounce slide events based on if the animation is running + if (isAnimationRunning) { return; } @@ -120,11 +121,17 @@ function TileDock({ setSlideToIndex(nextIndex); setTransform(-100 + movement); - setHasTransition(true); - if (!animated) setDoAnimationReset(true); + // If this is an animated slider, start the animation 'slide' + if (animated) { + setIsAnimationRunning(true); + } + // If not anmiated, trigger the post animation code right away + else { + setAnimationDone(true); + } }, - [animated, cycleMode, index, items.length, tileWidth, tilesToShow, hasTransition], + [animated, cycleMode, index, items.length, tileWidth, tilesToShow, isAnimationRunning], ); const handleTouchStart = useCallback( @@ -134,7 +141,7 @@ function TileDock({ y: event.touches[0].clientY, }; - function handleTouchMove(this: HTMLDocument, event: TouchEvent): void { + function handleTouchMove(this: Document, event: TouchEvent): void { const newPosition: Position = { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY, @@ -148,7 +155,7 @@ function TileDock({ } } - function handleTouchEnd(this: HTMLDocument, event: TouchEvent): void { + function handleTouchEnd(this: Document, event: TouchEvent): void { const newPosition = { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY, @@ -182,8 +189,9 @@ function TileDock({ [minimalTouchMovement, slide], ); + // Run code after the slide animation to set the new index useLayoutEffect(() => { - const resetAnimation = (): void => { + const postAnimationCleanup = (): void => { let resetIndex: number = slideToIndex; resetIndex = resetIndex >= items.length ? slideToIndex - items.length : resetIndex; @@ -195,16 +203,18 @@ function TileDock({ setIndex(resetIndex); setTransform(-100); - setDoAnimationReset(false); + setIsAnimationRunning(false); + setAnimationDone(false); }; - if (doAnimationReset) resetAnimation(); - }, [doAnimationReset, index, items.length, slideToIndex, tileWidth, tilesToShow, transitionBasis]); + if (animationDone) { + postAnimationCleanup(); + } + }, [animationDone, index, items.length, slideToIndex, tileWidth, tilesToShow, transitionBasis]); const handleTransitionEnd = (event: React.TransitionEvent) => { if (event.target === frameRef.current) { - setDoAnimationReset(true); - setHasTransition(false); + setAnimationDone(true); } }; From 1b36ae0e391d9ec977fdd6e8b0ef3befa43ddc5a Mon Sep 17 00:00:00 2001 From: Danny Budzinski Date: Fri, 19 Jan 2024 11:57:19 +0100 Subject: [PATCH 2/5] fix: lock animation mode on first load --- src/components/TileDock/TileDock.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/TileDock/TileDock.tsx b/src/components/TileDock/TileDock.tsx index ff44868fe..a95ea47df 100644 --- a/src/components/TileDock/TileDock.tsx +++ b/src/components/TileDock/TileDock.tsx @@ -16,7 +16,7 @@ export type TileDockProps = { minimalTouchMovement?: number; showControls?: boolean; showDots?: boolean; - animated?: boolean; + animatedOverride?: boolean; wrapWithEmptyTiles?: boolean; transitionTime?: string; renderTile: (item: T, isInView: boolean) => ReactNode; @@ -66,7 +66,7 @@ function TileDock({ spacing = 12, minimalTouchMovement = 30, showControls = true, - animated = !window.matchMedia('(prefers-reduced-motion)').matches, + animatedOverride, transitionTime = '0.6s', wrapWithEmptyTiles = false, showDots = false, @@ -78,6 +78,8 @@ function TileDock({ const [index, setIndex] = useState(0); const [slideToIndex, setSlideToIndex] = useState(0); const [transform, setTransform] = useState(-100); + // Prevent animation mode from changing after first load + const [isAnimated] = useState(animatedOverride ?? !window.matchMedia('(prefers-reduced-motion)').matches); const [animationDone, setAnimationDone] = useState(false); const [isAnimationRunning, setIsAnimationRunning] = useState(false); @@ -90,7 +92,7 @@ function TileDock({ return sliceItems(items, isMultiPage, index, tilesToShow, cycleMode); }, [items, isMultiPage, index, tilesToShow, cycleMode]); - const transitionBasis: string = isMultiPage && animated && isAnimationRunning ? `transform ${transitionTime} ease` : ''; + const transitionBasis: string = isMultiPage && isAnimated && isAnimationRunning ? `transform ${transitionTime} ease` : ''; const needControls: boolean = showControls && isMultiPage; const showLeftControl: boolean = needControls && !(cycleMode === 'stop' && index === 0); @@ -123,7 +125,7 @@ function TileDock({ setTransform(-100 + movement); // If this is an animated slider, start the animation 'slide' - if (animated) { + if (isAnimated) { setIsAnimationRunning(true); } // If not anmiated, trigger the post animation code right away @@ -131,7 +133,7 @@ function TileDock({ setAnimationDone(true); } }, - [animated, cycleMode, index, items.length, tileWidth, tilesToShow, isAnimationRunning], + [isAnimated, cycleMode, index, items.length, tileWidth, tilesToShow, isAnimationRunning], ); const handleTouchStart = useCallback( From 9bed444a3ce66daad52789243fa1acd3303996ce Mon Sep 17 00:00:00 2001 From: Danny Budzinski Date: Fri, 19 Jan 2024 12:02:36 +0100 Subject: [PATCH 3/5] chore: rename variables for consistency --- src/components/TileDock/TileDock.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/TileDock/TileDock.tsx b/src/components/TileDock/TileDock.tsx index a95ea47df..885501148 100644 --- a/src/components/TileDock/TileDock.tsx +++ b/src/components/TileDock/TileDock.tsx @@ -16,7 +16,7 @@ export type TileDockProps = { minimalTouchMovement?: number; showControls?: boolean; showDots?: boolean; - animatedOverride?: boolean; + animationModeOverride?: boolean; wrapWithEmptyTiles?: boolean; transitionTime?: string; renderTile: (item: T, isInView: boolean) => ReactNode; @@ -66,7 +66,7 @@ function TileDock({ spacing = 12, minimalTouchMovement = 30, showControls = true, - animatedOverride, + animationModeOverride, transitionTime = '0.6s', wrapWithEmptyTiles = false, showDots = false, @@ -79,8 +79,8 @@ function TileDock({ const [slideToIndex, setSlideToIndex] = useState(0); const [transform, setTransform] = useState(-100); // Prevent animation mode from changing after first load - const [isAnimated] = useState(animatedOverride ?? !window.matchMedia('(prefers-reduced-motion)').matches); - const [animationDone, setAnimationDone] = useState(false); + const [isAnimated] = useState(animationModeOverride ?? !window.matchMedia('(prefers-reduced-motion)').matches); + const [isAnimationDone, setIsAnimationDone] = useState(false); const [isAnimationRunning, setIsAnimationRunning] = useState(false); const frameRef = useRef() as React.MutableRefObject; @@ -130,7 +130,7 @@ function TileDock({ } // If not anmiated, trigger the post animation code right away else { - setAnimationDone(true); + setIsAnimationDone(true); } }, [isAnimated, cycleMode, index, items.length, tileWidth, tilesToShow, isAnimationRunning], @@ -206,17 +206,17 @@ function TileDock({ setIndex(resetIndex); setTransform(-100); setIsAnimationRunning(false); - setAnimationDone(false); + setIsAnimationDone(false); }; - if (animationDone) { + if (isAnimationDone) { postAnimationCleanup(); } - }, [animationDone, index, items.length, slideToIndex, tileWidth, tilesToShow, transitionBasis]); + }, [isAnimationDone, index, items.length, slideToIndex, tileWidth, tilesToShow, transitionBasis]); const handleTransitionEnd = (event: React.TransitionEvent) => { if (event.target === frameRef.current) { - setAnimationDone(true); + setIsAnimationDone(true); } }; From 4f6e4b0af50c26b523c1fc8f12469baa5280f5a1 Mon Sep 17 00:00:00 2001 From: Anton Lantukh Date: Wed, 24 Jan 2024 10:38:21 +0100 Subject: [PATCH 4/5] fix(project): fix dfault schemas --- scripts/content-types/content-types.json | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/scripts/content-types/content-types.json b/scripts/content-types/content-types.json index 328ad4f80..c086bc2ab 100644 --- a/scripts/content-types/content-types.json +++ b/scripts/content-types/content-types.json @@ -161,7 +161,7 @@ "hosting_type": "hosted", "is_active": true, "is_series": false, - "sections": [] + "sections": ["access"] }, { "name": "liveChannel", @@ -261,7 +261,22 @@ "hosting_type": "hosted", "is_active": true, "is_series": false, - "sections": [] + "sections": [ + { + "title": "Access", + "fields": [ + { + "param": "free", + "label": "Free", + "description": "If this item can be watched for free and doesn't require a login or subscription, you can set this value to true. Otherwise, if you leave this setting false, the application level subscription and authentication level rules will apply.", + "details": { + "field_type": "toggle", + "default": true + } + } + ] + } + ] }, { "name": "hub", From 472ad06b638d1358851f36a25c8f6819f7598b29 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 24 Jan 2024 10:20:09 +0000 Subject: [PATCH 5/5] chore(release): v5.1.1 --- CHANGELOG.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a226dd35c..5402f754e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [5.1.1](https://github.com/jwplayer/ott-web-app/compare/v5.1.0...v5.1.1) (2024-01-24) + + +### Bug Fixes + +* lock animation mode on first load ([1b36ae0](https://github.com/jwplayer/ott-web-app/commit/1b36ae0e391d9ec977fdd6e8b0ef3befa43ddc5a)) +* prevent slider from getting stuck in non-anmiated mode ([e827aff](https://github.com/jwplayer/ott-web-app/commit/e827affd97f4cd3dbff4296c8686b77fab4a06b4)) +* **project:** fix dfault schemas ([4f6e4b0](https://github.com/jwplayer/ott-web-app/commit/4f6e4b0af50c26b523c1fc8f12469baa5280f5a1)) + ## [5.1.0](https://github.com/jwplayer/ott-web-app/compare/v5.0.0...v5.1.0) (2024-01-18) diff --git a/package.json b/package.json index 73deb7e56..9ae97447c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jw-ott-webapp", - "version": "5.1.0", + "version": "5.1.1", "main": "index.js", "repository": "https://github.com/jwplayer/ott-web-app.git", "author": "JW Player",