diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aa3cd486..b0d6194d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [6.1.2](https://github.com/jwplayer/ott-web-app/compare/v6.1.1...v6.1.2) (2024-05-21) + + +### Bug Fixes + +* **a11y:** improve accessibility of offers modal ([af654ec](https://github.com/jwplayer/ott-web-app/commit/af654ecc9b481353522b8e08a2d8078a7b91aa2a)) +* **home:** broken home skeleton ([#523](https://github.com/jwplayer/ott-web-app/issues/523)) ([35cd2db](https://github.com/jwplayer/ott-web-app/commit/35cd2db26ed3ffee65a6e2edf38447bce7957c7f)) +* **menu:** reintroduce profile menu styling ([39fd840](https://github.com/jwplayer/ott-web-app/commit/39fd840019405797069e84f7dbfd9d10a746b534)) +* **project:** alignment of password toggle button ([642068d](https://github.com/jwplayer/ott-web-app/commit/642068dc4babba8e9660e9bfee6acf16931aa8aa)) +* **project:** favicon paths ([7acf234](https://github.com/jwplayer/ott-web-app/commit/7acf234446d8dc62e3f43b13f49c3b2ad3c72a8a)) +* remove simultaneous logins ([9aa4a71](https://github.com/jwplayer/ott-web-app/commit/9aa4a71d8c12865bdf13fadf3d93b420343bd672)) + ## [6.1.1](https://github.com/jwplayer/ott-web-app/compare/v6.1.0...v6.1.1) (2024-04-23) diff --git a/package.json b/package.json index b13af62b3..4fb840f26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jwp/ott", - "version": "6.1.1", + "version": "6.1.2", "private": true, "license": "Apache-2.0", "repository": "https://github.com/jwplayer/ott-web-app.git", diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts index bfaf1d4b8..953face35 100644 --- a/packages/common/src/constants.ts +++ b/packages/common/src/constants.ts @@ -75,8 +75,6 @@ export const DEFAULT_FEATURES = { watchListSizeLimit: MAX_WATCHLIST_ITEMS_COUNT, }; -export const simultaneousLoginWarningKey = 'simultaneous_logins'; - export const EPG_TYPE = { jwp: 'jwp', viewNexa: 'viewnexa', diff --git a/packages/common/src/controllers/AccountController.ts b/packages/common/src/controllers/AccountController.ts index 5ee095675..af9cd99ee 100644 --- a/packages/common/src/controllers/AccountController.ts +++ b/packages/common/src/controllers/AccountController.ts @@ -334,7 +334,7 @@ export default class AccountController { if (response.errors.length > 0) throw new Error(response.errors[0]); - await this.reloadSubscriptions({ delay: 2000 }); + await this.reloadSubscriptions({ retry: 10 }); return response?.responseData; }; @@ -386,7 +386,7 @@ export default class AccountController { return !!responseData?.accessGranted; }; - reloadSubscriptions = async ({ delay }: { delay: number } = { delay: 0 }): Promise => { + reloadSubscriptions = async ({ delay, retry }: { delay?: number; retry?: number } = { delay: 0, retry: 0 }): Promise => { useAccountStore.setState({ loading: true }); const { getAccountInfo } = useAccountStore.getState(); @@ -395,10 +395,10 @@ export default class AccountController { // The subscription data takes a few seconds to load after it's purchased, // so here's a delay mechanism to give it time to process - if (delay > 0) { + if (delay && delay > 0) { return new Promise((resolve: (value?: unknown) => void) => { setTimeout(() => { - this.reloadSubscriptions().finally(resolve); + this.reloadSubscriptions({ retry }).finally(resolve); }, delay); }); } @@ -418,6 +418,12 @@ export default class AccountController { let pendingOffer: Offer | null = null; + if (!activeSubscription && !!retry && retry > 0) { + const retryDelay = 1500; // Any initial delay has already occured, so we can set this to a fixed value + + return await this.reloadSubscriptions({ delay: retryDelay, retry: retry - 1 }); + } + // resolve and fetch the pending offer after upgrade/downgrade try { if (activeSubscription?.pendingSwitchId) { diff --git a/packages/common/src/stores/UIStore.ts b/packages/common/src/stores/UIStore.ts index af33c22b4..a328ae7ed 100644 --- a/packages/common/src/stores/UIStore.ts +++ b/packages/common/src/stores/UIStore.ts @@ -4,6 +4,7 @@ type UIState = { searchQuery: string; searchActive: boolean; userMenuOpen: boolean; + sideBarOpen: boolean; languageMenuOpen: boolean; preSearchPage?: string; }; @@ -12,5 +13,6 @@ export const useUIStore = createStore('UIStore', () => ({ searchQuery: '', searchActive: false, userMenuOpen: false, + sideBarOpen: false, languageMenuOpen: false, })); diff --git a/packages/common/types/form.d.ts b/packages/common/types/form.d.ts index f4616910b..336d1270f 100644 --- a/packages/common/types/form.d.ts +++ b/packages/common/types/form.d.ts @@ -1,5 +1,5 @@ -export type UseFormChangeHandler = React.ChangeEventHandler; -export type UseFormBlurHandler = React.FocusEventHandler; +export type UseFormChangeHandler = React.ChangeEventHandler; +export type UseFormBlurHandler = React.FocusEventHandler; export type UseFormSubmitHandler = React.FormEventHandler; export type GenericFormErrors = { form: string }; diff --git a/packages/hooks-react/src/useCheckAccess.ts b/packages/hooks-react/src/useCheckAccess.ts index 4c55dca48..de50537e4 100644 --- a/packages/hooks-react/src/useCheckAccess.ts +++ b/packages/hooks-react/src/useCheckAccess.ts @@ -31,7 +31,7 @@ const useCheckAccess = () => { const hasAccess = await accountController.checkEntitlements(offerId); if (hasAccess) { - await accountController.reloadSubscriptions({ delay: 2000 }); // Delay needed for backend processing (Cleeng API returns empty subscription, even after accessGranted from entitlements call + await accountController.reloadSubscriptions({ retry: 10, delay: 2000 }); callback?.(true); } else if (--iterations === 0) { window.clearInterval(intervalRef.current); diff --git a/packages/hooks-react/src/useCheckout.ts b/packages/hooks-react/src/useCheckout.ts index 29614f08b..59a6c3966 100644 --- a/packages/hooks-react/src/useCheckout.ts +++ b/packages/hooks-react/src/useCheckout.ts @@ -47,7 +47,7 @@ const useCheckout = ({ onUpdateOrderSuccess, onSubmitPaymentWithoutDetailsSucces mutationKey: ['submitPaymentWithoutDetails'], mutationFn: checkoutController.paymentWithoutDetails, onSuccess: async () => { - await accountController.reloadSubscriptions({ delay: 1000 }); + await accountController.reloadSubscriptions({ retry: 10 }); onSubmitPaymentWithoutDetailsSuccess(); }, }); diff --git a/packages/hooks-react/src/useOffers.ts b/packages/hooks-react/src/useOffers.ts index b62ef8865..06663c495 100644 --- a/packages/hooks-react/src/useOffers.ts +++ b/packages/hooks-react/src/useOffers.ts @@ -1,5 +1,4 @@ -import { useMutation } from 'react-query'; -import { useEffect } from 'react'; +import { useMutation, useQuery } from 'react-query'; import { shallow } from '@jwp/ott-common/src/utils/compare'; import { getModule } from '@jwp/ott-common/src/modules/container'; import { useCheckoutStore } from '@jwp/ott-common/src/stores/CheckoutStore'; @@ -21,9 +20,9 @@ const useOffers = () => { shallow, ); - const { mutate: initialise, isLoading: isInitialisationLoading } = useMutation({ - mutationKey: ['initialiseOffers', requestedMediaOffers], - mutationFn: checkoutController.initialiseOffers, + const { isLoading: isInitialisationLoading } = useQuery({ + queryKey: ['initialiseOffers', requestedMediaOffers], + queryFn: checkoutController.initialiseOffers, }); const chooseOffer = useMutation({ @@ -34,13 +33,9 @@ const useOffers = () => { const switchSubscription = useMutation({ mutationKey: ['switchSubscription'], mutationFn: checkoutController.switchSubscription, - onSuccess: () => accountController.reloadSubscriptions({ delay: 7500 }), // @todo: Is there a better way to wait? + onSuccess: () => accountController.reloadSubscriptions({ delay: 3000, retry: 10 }), // A subscription switch usually takes at least 3 secs }); - useEffect(() => { - initialise(); - }, [requestedMediaOffers, initialise]); - const hasMediaOffers = mediaOffers.length > 0; const hasSubscriptionOffers = subscriptionOffers.length > 0; const hasPremierOffers = requestedMediaOffers.some((mediaOffer) => mediaOffer.premier); diff --git a/packages/hooks-react/src/usePlaylists.ts b/packages/hooks-react/src/usePlaylists.ts index c430e816f..b67945f46 100644 --- a/packages/hooks-react/src/usePlaylists.ts +++ b/packages/hooks-react/src/usePlaylists.ts @@ -14,9 +14,9 @@ const placeholderData = generatePlaylistPlaceholder(30); type UsePlaylistResult = { data: Playlist | undefined; - isLoading: boolean; isSuccess?: boolean; error?: unknown; + isPlaceholderData?: boolean; }[]; const usePlaylists = (content: Content[], rowsToLoad: number | undefined = undefined) => { @@ -57,13 +57,13 @@ const usePlaylists = (content: Content[], rowsToLoad: number | undefined = undef if (type === PersonalShelf.Favorites) return { data: favorites, isLoading: false, isSuccess: true }; if (type === PersonalShelf.ContinueWatching) return { data: watchHistory, isLoading: false, isSuccess: true }; - const { data, isLoading, isSuccess, error } = playlistQueries[index]; + const { data, isSuccess, error, isPlaceholderData } = playlistQueries[index]; return { data, - isLoading, isSuccess, error, + isPlaceholderData, }; }); diff --git a/packages/hooks-react/src/useProfiles.ts b/packages/hooks-react/src/useProfiles.ts index aef289e6f..ebda26e9a 100644 --- a/packages/hooks-react/src/useProfiles.ts +++ b/packages/hooks-react/src/useProfiles.ts @@ -10,6 +10,7 @@ import { useAccountStore } from '@jwp/ott-common/src/stores/AccountStore'; import ProfileController from '@jwp/ott-common/src/controllers/ProfileController'; import AccountController from '@jwp/ott-common/src/controllers/AccountController'; import { logDev } from '@jwp/ott-common/src/utils/common'; +import { useConfigStore } from '@jwp/ott-common/src/stores/ConfigStore'; export const useSelectProfile = (options?: { onSuccess: () => void; onError: () => void }) => { const accountController = getModule(AccountController, false); @@ -94,7 +95,9 @@ export const useProfileErrorHandler = () => { }; export const useProfiles = (options?: UseQueryOptions) => { - const { user } = useAccountStore(); + const user = useAccountStore((state) => state.user); + const accessModel = useConfigStore((state) => state.accessModel); + const { profile } = useProfileStore(); const isLoggedIn = !!user; const profileController = getModule(ProfileController); @@ -106,8 +109,11 @@ export const useProfiles = (options?: UseQueryOptions ))} diff --git a/packages/ui-react/src/components/Account/__snapshots__/Account.test.tsx.snap b/packages/ui-react/src/components/Account/__snapshots__/Account.test.tsx.snap index 624a6df72..25c330d33 100644 --- a/packages/ui-react/src/components/Account/__snapshots__/Account.test.tsx.snap +++ b/packages/ui-react/src/components/Account/__snapshots__/Account.test.tsx.snap @@ -25,10 +25,10 @@ exports[` > renders and matches snapshot 1`] = ` novalidate="" >