@applicaster/quick-brick-player 15.1.10 → 15.1.11-alpha.1439851164
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "15.1.
|
|
3
|
+
"version": "15.1.11-alpha.1439851164",
|
|
4
4
|
"description": "Quick Brick Player",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@applicaster/quick-brick-mobile-transport-controls": "15.1.9",
|
|
39
39
|
"@applicaster/quick-brick-tv-transport-controls": "15.1.9",
|
|
40
|
-
"@applicaster/zapp-react-native-tvos-app": "15.1.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "15.1.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "15.1.
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "15.1.11-alpha.1439851164",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "15.1.11-alpha.1439851164",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "15.1.11-alpha.1439851164",
|
|
43
43
|
"query-string": "7.1.3",
|
|
44
44
|
"shaka-player": "4.3.5",
|
|
45
45
|
"typeface-montserrat": "^0.0.54",
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
VIDEO_TRANSITION_THRESHOLD,
|
|
13
13
|
} from "./consts";
|
|
14
14
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
15
|
+
import { useIsTabletLandscape } from "@applicaster/zapp-react-native-utils/reactHooks/device/useMemoizedIsTablet";
|
|
15
16
|
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
16
17
|
import {
|
|
17
18
|
SafeAreaView,
|
|
@@ -100,7 +101,23 @@ export function VideoPlayerModal({
|
|
|
100
101
|
fullscreen || pip
|
|
101
102
|
);
|
|
102
103
|
|
|
104
|
+
/* Landscape is a tablet's regular orientation, so rotating it says nothing
|
|
105
|
+
about the modal mode. useOrientationEffect skips its orientation effects
|
|
106
|
+
for the same reason, via the same predicate. */
|
|
107
|
+
const skipOrientationEffects = useIsTabletLandscape();
|
|
108
|
+
|
|
109
|
+
/* Props are the only reconciliation left once the listener below is skipped,
|
|
110
|
+
and even where it runs, the mount value goes stale: remounting during
|
|
111
|
+
native fullscreen would otherwise strand the modal in that layout. Rotating
|
|
112
|
+
a tablet flips the predicate itself, so reconcile then too — the last
|
|
113
|
+
orientation event may have left the state behind. */
|
|
114
|
+
React.useEffect(() => {
|
|
115
|
+
setFullScreenMode(fullscreen || pip);
|
|
116
|
+
}, [fullscreen, pip, skipOrientationEffects]);
|
|
117
|
+
|
|
103
118
|
React.useEffect(() => {
|
|
119
|
+
if (skipOrientationEffects) return;
|
|
120
|
+
|
|
104
121
|
const listener = addOrientationChangeListener(({ toOrientation }) => {
|
|
105
122
|
/* ignored in collapsed mode non-PiP player */
|
|
106
123
|
if (collapsed && !pip) return;
|
|
@@ -110,7 +127,7 @@ export function VideoPlayerModal({
|
|
|
110
127
|
return () => {
|
|
111
128
|
listener.remove();
|
|
112
129
|
};
|
|
113
|
-
}, [collapsed, pip]);
|
|
130
|
+
}, [collapsed, pip, skipOrientationEffects]);
|
|
114
131
|
|
|
115
132
|
const isFullScreenOrPIP = isFullScreenMode;
|
|
116
133
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import { act, render, screen } from "@testing-library/react-native";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The modal's fullscreen layout is not directly observable, but the collapsed
|
|
7
|
+
* bar is: it renders only while the modal is NOT in that layout. Every case
|
|
8
|
+
* below therefore reads `collapsedBarWrapper` as the proxy for the state under
|
|
9
|
+
* test.
|
|
10
|
+
*
|
|
11
|
+
* Why it matters: while the modal sits in the fullscreen layout, a drag still
|
|
12
|
+
* drives navigation to MINIMIZED, which docks the player and hides the native
|
|
13
|
+
* controls (see Player/index.tsx `shouldUseNativeControls`). If the layout
|
|
14
|
+
* cannot follow the mode back out, the modal is stranded on top of the tab bar
|
|
15
|
+
* with no controls and no way to restore them.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
let mockIsTabletLandscape = false;
|
|
19
|
+
let orientationListener: ((event: any) => void) | null = null;
|
|
20
|
+
const mockRemove = jest.fn();
|
|
21
|
+
|
|
22
|
+
const mockAddOrientationChangeListener = jest.fn((cb) => {
|
|
23
|
+
orientationListener = cb;
|
|
24
|
+
|
|
25
|
+
return { remove: mockRemove };
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
jest.mock(
|
|
29
|
+
"@applicaster/zapp-react-native-utils/appUtils/orientationHelper",
|
|
30
|
+
() => ({
|
|
31
|
+
addOrientationChangeListener: (cb) => mockAddOrientationChangeListener(cb),
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
jest.mock(
|
|
36
|
+
"@applicaster/zapp-react-native-utils/reactHooks/device/useMemoizedIsTablet",
|
|
37
|
+
() => ({ useIsTabletLandscape: () => mockIsTabletLandscape })
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
|
|
41
|
+
useIsTablet: () => mockIsTabletLandscape,
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
jest.mock(
|
|
45
|
+
"@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils",
|
|
46
|
+
() => ({ useConfiguration: () => ({ minimised_height: 60 }) })
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
jest.mock(
|
|
50
|
+
"@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils",
|
|
51
|
+
() => ({ PROGRESS_BAR_HEIGHT: 3 })
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
jest.mock("react-native-safe-area-context", () => {
|
|
55
|
+
const { View } = require("react-native");
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
SafeAreaView: View,
|
|
59
|
+
useSafeAreaFrame: () => ({ x: 0, y: 0, width: 1024, height: 768 }),
|
|
60
|
+
useSafeAreaInsets: () => ({ top: 24, bottom: 34, left: 0, right: 0 }),
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
jest.mock("../GestureAnimatedScrollView", () => {
|
|
65
|
+
const { ScrollView } = require("react-native");
|
|
66
|
+
|
|
67
|
+
return { GestureAnimatedScrollView: ScrollView };
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
jest.mock("../styles", () => ({
|
|
71
|
+
useStyles: () => ({
|
|
72
|
+
modal: {},
|
|
73
|
+
modalWrapper: {},
|
|
74
|
+
collapsedModalBg: {},
|
|
75
|
+
modalContent: {},
|
|
76
|
+
modalContentPiP: {},
|
|
77
|
+
expandedContentContainer: {},
|
|
78
|
+
extraContentScrollView: {},
|
|
79
|
+
collapsedBarContainer: {},
|
|
80
|
+
collapsedBarWrapper: {},
|
|
81
|
+
flexNone: {},
|
|
82
|
+
}),
|
|
83
|
+
}));
|
|
84
|
+
|
|
85
|
+
jest.mock("../hooks", () => ({
|
|
86
|
+
useVideoModalState: () => ({
|
|
87
|
+
collapsed: false,
|
|
88
|
+
offset: { current: 700 },
|
|
89
|
+
gestureHandlerProps: {},
|
|
90
|
+
translateY: new (require("react-native").Animated.Value)(0),
|
|
91
|
+
expand: jest.fn(),
|
|
92
|
+
}),
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
// eslint-disable-next-line import/first
|
|
96
|
+
import { VideoPlayerModal } from "../VideoPlayerModal";
|
|
97
|
+
|
|
98
|
+
const renderModal = (props = {}) =>
|
|
99
|
+
render(
|
|
100
|
+
<VideoPlayerModal
|
|
101
|
+
modal
|
|
102
|
+
content={<Text>content</Text>}
|
|
103
|
+
collapsedContent={<Text>collapsed</Text>}
|
|
104
|
+
style={{ width: 1024, height: 768, tabletLandscapeWidth: 600 }}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const collapsedBar = () => screen.queryByTestId("collapsedBarWrapper");
|
|
110
|
+
|
|
111
|
+
beforeEach(() => {
|
|
112
|
+
jest.clearAllMocks();
|
|
113
|
+
orientationListener = null;
|
|
114
|
+
mockIsTabletLandscape = false;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe("VideoPlayerModal fullscreen layout", () => {
|
|
118
|
+
describe("on a tablet in landscape", () => {
|
|
119
|
+
beforeEach(() => {
|
|
120
|
+
mockIsTabletLandscape = true;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("leaves the orientation listener alone, since landscape is its regular orientation", () => {
|
|
124
|
+
renderModal();
|
|
125
|
+
|
|
126
|
+
expect(mockAddOrientationChangeListener).not.toHaveBeenCalled();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("follows the mode back out of fullscreen", () => {
|
|
130
|
+
const { rerender } = renderModal({ fullscreen: true });
|
|
131
|
+
|
|
132
|
+
expect(collapsedBar()).toBeNull();
|
|
133
|
+
|
|
134
|
+
rerender(
|
|
135
|
+
<VideoPlayerModal
|
|
136
|
+
modal
|
|
137
|
+
fullscreen={false}
|
|
138
|
+
content={<Text>content</Text>}
|
|
139
|
+
collapsedContent={<Text>collapsed</Text>}
|
|
140
|
+
style={{ width: 1024, height: 768, tabletLandscapeWidth: 600 }}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(collapsedBar()).not.toBeNull();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe("on a phone", () => {
|
|
149
|
+
it("still lets orientation drive the layout", () => {
|
|
150
|
+
renderModal();
|
|
151
|
+
|
|
152
|
+
expect(mockAddOrientationChangeListener).toHaveBeenCalled();
|
|
153
|
+
expect(collapsedBar()).not.toBeNull();
|
|
154
|
+
|
|
155
|
+
act(() => orientationListener?.({ toOrientation: 4 }));
|
|
156
|
+
|
|
157
|
+
expect(collapsedBar()).toBeNull();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|