@tivio/sdk-react 3.0.0-alpha2 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,7 +1,17 @@
1
1
  # @tivio/sdk-react
2
2
 
3
3
  ## Changelog
4
- * v3.0.0-alpha1
4
+
5
+ * UNRELEASED
6
+ * v3.1.0
7
+ * patch: internal refactored `useAd`, `useAdSegment`
8
+ * patch: `useAdSegment()` now returns null if no monetization is configured, ad segments are not managed in that situation
9
+ * patch: internal: fixed refactored `setUser()`
10
+ * minor: enriched `AdSegment` type from `useAdSegment()`
11
+ * minor: Added `setUser()` function for login and logout
12
+ * v3.0.0
13
+ * minor: Added hook useWatchWithoutAdsOffer to trigger purchase dialog to "watch without ads", if available
14
+ * patch: fix peerDependency declaration for react, react-dom
5
15
  * major: TivioProvider requires deviceCapabilities
6
16
  * major: TivioProvider requires currency
7
17
  * minor: add voucher support (see usePurchaseSubscription and useTransactionPayment hooks)
@@ -10,6 +20,15 @@
10
20
  * minor: watermarking support
11
21
  * minor: add useSearch hook
12
22
  * patch: price on video is 0 when purchased
23
+ * v2.4.2
24
+ * patch: added back changelog
25
+ * v2.4.1
26
+ * patch: improved doc about player wrapper
27
+ * v2.4.0
28
+ * patch: improved Player wrapper types
29
+ * minor: added Tivio DOM events `tivio_key_input_handling_change`, `tivio_context_switch` and `tivio_request_goto`
30
+ * patch: added support for remote code on browsers that do not implement [indexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
31
+ * patch: added support for browsers that do not implement [indexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
13
32
  * v2.3.4
14
33
  * patch: fix of usePurchaseSubscription not reactive
15
34
  * v2.3.3
@@ -29,7 +48,7 @@
29
48
  * v2.1.5
30
49
  * patch fix of `useVideosInSection` hook (fetching video's monetizations)
31
50
  * v2.1.4
32
- * patch: fix re-rendering of `useAd` during non-skippable ads (requires core-react@2.1.9)
51
+ * patch: fix re-rendering of `useAd` during non-skippable ads (requires core-react-dom@2.1.9)
33
52
  * v2.1.3
34
53
  * patch: fix changelog
35
54
  * v2.1.2
@@ -61,16 +80,14 @@
61
80
  * v1.3.4
62
81
  * ...
63
82
 
64
- ## Installation
65
83
 
66
- Check/install peer dependencies
67
- ``` sh
68
- npm install --save mobx@6.0.4 styled-components@5.2.1 firebase@8.2.3 react@17.0.2 react-dom@17.0.2
69
- ```
84
+ ## Installation
70
85
 
71
- Install SDK itself
72
- ``` sh
73
- npm install --save @tivio/sdk-react
86
+ Install @tivio/sdk-react along with its peer dependencies
87
+ ```sh
88
+ npm i react@17 react-dom@17 @tivio/sdk-react
89
+ # or
90
+ yarn add react@17 react-dom@17 @tivio/sdk-react
74
91
  ```
75
92
 
76
93
  ## Initialization
@@ -80,42 +97,42 @@ Put Tivio Provider at the top level of your application:
80
97
  ``` javascript
81
98
  import { TivioProvider } from '@tivio/sdk-react'
82
99
 
83
- const tivioConf = {
100
+ const config = {
84
101
  secret: 'XXXXXXXXXX',
85
102
  }
86
103
 
87
104
  function App({children}) {
88
105
  return (
89
- <TivioProvider conf={tivioConf}>
106
+ <TivioProvider conf={config}>
90
107
  {children}
91
108
  </TivioProvider>
92
109
  )
93
110
  }
94
111
  ```
95
112
 
96
- ### Usage with authorization
113
+ ## Authentication
97
114
 
98
- ``` javascript
99
- import { TivioProvider, setUser } from '@tivio/sdk-react'
115
+ A logged-in user can access more features, such as making purchases. In order to authenticate a user with Tivio, use the `setUser()` method.
100
116
 
101
- const tivioConf = {
102
- secret: 'XXXXXXXXXX',
103
- }
117
+ Verification of the user against 3rd party auth servers is implemented per customer.
104
118
 
105
- setUser('user-id', { some: 'payload' })
119
+ ```typescript
120
+ import { setUser } from '@tivio/sdk-react'
106
121
 
107
- function App({children}) {
108
- return (
109
- <TivioProvider conf={tivioConf}>
110
- {children}
111
- </TivioProvider>
112
- )
113
- }
122
+ // Log in
123
+
124
+ // Payload is specific per customer
125
+ // A common use-case is sending an auth token inside the payload, which Tivio can use to verify the user
126
+ await setUser('userId', { token: 'xxx'})
127
+
128
+ // Log out
129
+ await setUser('userId', null)
114
130
  ```
131
+
115
132
  ## Tivio widget
116
133
 
117
134
  Tivio widget is the main Tivio component which shows the widget and provides access to its channels, sections and videos.
118
- Usage is very simple (be sure to set `id` to the widget ID you have configured in Tivio Studio):
135
+ Usage is very simple (be sure to set `id` to the widget ID you have configured in [Tivio Studio](https://studio.tiv.io/)):
119
136
 
120
137
  ``` javascript
121
138
  import { TivioWidget } from '@tivio/sdk-react'
@@ -144,48 +161,146 @@ function Screen() {
144
161
  )
145
162
  }
146
163
  ```
164
+
147
165
  ## Player wrapper
148
166
 
149
- Player wrapper is the way how you can enhance your video player with Tivio features (e.g. inserting of ads).
167
+ Player wrapper is the way how you can enhance your video player with Tivio features, such Tivio Ads. In order to start using Tivio player wrapper, wrap your player methods with PlayerWrapper, start using PlayerWrapper's methods instead of them to control your playback and start sending player events to Tivio PlayerWrapper.
168
+
169
+ ### Wrap your player methods with Tivio player wrapper
150
170
 
151
171
  ``` javascript
152
- import { useTivioData } from '@tivio/sdk-react'
172
+ import { useTivioReadyData } from '@tivio/sdk-react'
153
173
 
154
174
  function CustomPlayer() {
155
- const tivio = useTivioData()
156
- const [isPlaying, setIsPlaying] = useState()
175
+ const tivioData = useTivioReadyData()
157
176
 
158
177
  useEffect(() => {
159
- (async () => {
160
- if (tivio.getPlayerWrapper) {
161
- const playerWrapper = await tivio.getPlayerWrapper(
162
- { playerWrapperId: 'default' }
163
- )
164
-
165
- playerWrapper.register({
166
- play: () => {
167
- setIsPlaying(true)
168
- // start playback using your player here
169
- },
170
- pause: () => {
171
- setIsPlaying(false)
172
- // pause playback using your player here
173
- },
174
- seekTo: (ms: number) => {
175
- // seek using your player here
176
- },
177
- setSource: (videoSource: InputSource) => {
178
- // play videoSource using your player here
179
- },
180
- })
181
- }
182
- })()
183
- }, [])
184
-
185
- return (<div>Example is {isPlaying ? null : 'not '}playing.</div>)
178
+ if (tivioData) {
179
+ // If your app uses multiple player instances, use different Tivio player wrapper for each
180
+ // distinguished by playerWrapperId
181
+ const playerWrapper = tivio.getPlayerWrapper({ playerWrapperId: 'PLAYER_1' })
182
+
183
+ // Pass your player methods to Tivio player wrapper
184
+ playerWrapper.register({
185
+ play: () => {
186
+ // Un-pause your player
187
+ },
188
+ pause: () => {
189
+ // Pause your player
190
+ },
191
+ seekTo: (ms: number) => {
192
+ // Seek to position in milliseconds using your player
193
+ },
194
+ setSource: (videoSource: InputSource) => {
195
+ // Send this video source to your player to load it
196
+ },
197
+ })
198
+ }
199
+ }, [tivioData])
200
+ }
201
+ ```
202
+
203
+ ### Start using Tivio player wrapper methods to control playback
204
+
205
+ ``` javascript
206
+ // Channel source metadata, such as channel name, epg start and epg end are necessary
207
+ // for TV ad segment detection and application of ad strategies
208
+ const source = new ChannelSource(
209
+ 'https://channel_prima_hd.m3u8',
210
+ {
211
+ // here put any additional metadata, for your use.
212
+ // This object will not be touched by Tivio
213
+ },
214
+ // channel name
215
+ // can also be prima hd, prima_hd, prima, Prima, PRIMA, etc.
216
+ // we will normalize it to snake case and add '_hd' if necessary
217
+ 'Prima HD',
218
+ // program name
219
+ 'Dr. House',
220
+ // description (optional)
221
+ 'Episode about Dr. House being awesome',
222
+ // EPG start
223
+ new Date('2021-12-10T12:00:00'),
224
+ // EPG end
225
+ new Date('2021-12-10T13:40:00'),
226
+ )
227
+
228
+ // Send source to player
229
+ playerWrapper.onSourceChanged(source)
230
+
231
+ // Un-pause player
232
+ playerWrapper.play()
233
+
234
+ // Pause player
235
+ playerWrapper.pause()
236
+ }
237
+ ```
238
+
239
+ ### Start reporting player events to Tivio
240
+
241
+ ``` javascript
242
+ // Report that source is playing
243
+ playerWrapper.onStateChanged('playing')
244
+
245
+ // Report that source is paused
246
+ playerWrapper.onStateChanged('paused')
247
+
248
+ // Report that source stopped playing
249
+ playerWrapper.onPlaybackEnded()
250
+ playerWrapper.onStateChanged('idle')
251
+
252
+ // Report video progress
253
+ playerWrapper.onTimeChanged(ms)
254
+ }
255
+ ```
256
+
257
+ ### Start reporting playback-related errors to Tivio
258
+
259
+ ``` javascript
260
+ // Report that video failed to load (e.g. due to a wrong URI)
261
+ playerWrapper.onLoadError(new Error('video failed to load'))
262
+
263
+ // Report that video failed during playback (e.g. due to bad connection, corrupted chunks of stream video etc.)
264
+ // This type of error may be auto-recoverable
265
+ playerWrapper.onError(new Error('playback error'))
186
266
  }
187
267
  ```
188
268
 
269
+ ## Tivio DOM events
270
+
271
+ `TivioWidget` triggers these events on `window.document`.
272
+
273
+ 1. To instruct the parent app to navigate to and focus a specific TivioWidget (e.g. after going back from a Tivio screen)
274
+
275
+ ```typescript
276
+ document.addEventListener("tivio_request_goto", e => {
277
+ e.detail.widgetId; // string - Tivio widget ID to go navigate to in UI
278
+ });
279
+ ```
280
+ 2. To notify the parent app about context switch, i.e. where is the user located or what is he focusing
281
+
282
+ ```typescript
283
+ document.addEventListener("tivio_context_switch", e => {
284
+ e.detail.context; // 'tivio' | 'parent' - where is the user located? - in Tivio or in parent app
285
+
286
+ // For context Tivio there are additional fields
287
+ e.detail.context; // 'tivio'
288
+ e.detail.contextLocation; // 'route' | 'overlay' | 'widget' - where in Tivio is the user located?
289
+ // - on a Tivio route, in parent app but looking at a full screen Tivio overlay,
290
+ // or in parent app and focus is on a Tivio widget
291
+
292
+ // For context Tivio contextLocation 'widget' there is an additional field of widget ID
293
+ e.detail.widgetId; // string - which Tivio widget is focused right now
294
+ });
295
+ ```
296
+ 3. To notify the parent app about whether it should be handling key input from RC (TV remote) or not. When inputHandler is 'tivio', the parent app should stop reacting to key input, when inputHandler is 'parent' the parent app should start reacting again.
297
+
298
+ ```typescript
299
+ document.addEventListener("tivio_key_input_handling_change", e => {
300
+ e.detail.inputHandler; // 'tivio' | 'parent' - who should be handling RC input? - Tivio or parent app
301
+ });
302
+ ```
303
+
189
304
  ## Data hooks
190
305
 
191
306
  If you don't want to use TivioWidget, you can implement your own UI using React data hooks.
@@ -3,11 +3,17 @@
3
3
  * nangu.TV, a.s PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4
4
  */
5
5
  import React, { FunctionComponentElement } from 'react';
6
+ import type { PlayerWrapper } from '../types/customPlayer.types';
6
7
  export declare type PlayerProviderProps = {
7
8
  children: React.ReactNode;
8
9
  playerWrapperId?: string;
9
10
  };
10
- export declare type Player = any;
11
- export declare const PlayerContext: React.Context<any>;
11
+ /**
12
+ * value
13
+ * - undefined - you are trying to access this context but are not inside <PlayerContext /> that is a bug
14
+ * - null - we are waiting for remote code
15
+ * - Player - player is ready
16
+ */
17
+ export declare const PlayerContext: React.Context<PlayerWrapper | null | undefined>;
12
18
  export declare const PlayerProvider: ({ children, playerWrapperId, }: PlayerProviderProps) => FunctionComponentElement<PlayerProviderProps>;
13
19
  export declare function withPlayerContext(id: string): <P>(WrappedComponent: React.ComponentType<P>) => (props: P) => JSX.Element;
@@ -13,4 +13,7 @@ export * from './useOrganizationSubscriptions';
13
13
  export * from './usePurchasesWithVideos';
14
14
  export * from './useFreePurchase';
15
15
  export * from './useRowsInScreen';
16
+ export * from './useVoucher';
16
17
  export * from './useTivio';
18
+ export * from './useLastVideoByWidgetId';
19
+ export * from './useWatchWithoutAdsOffer';
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) 2021, nangu.TV, a.s. All rights reserved.
3
3
  * nangu.TV, a.s PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4
4
  */
5
- import type { AdSource, UsePlayerEvent } from '../../types/customPlayer.types';
5
+ import type { UsePlayerEvent } from '../../types/customPlayer.types';
6
6
  import type { BetOffer, Marker } from '../../types/types';
7
7
  export declare const usePlayerEvent: UsePlayerEvent;
8
8
  export declare const useMarkers: () => Marker[] | null;
@@ -12,12 +12,17 @@ interface IntroMarker {
12
12
  skip: () => void;
13
13
  }
14
14
  export declare const useIntro: () => IntroMarker | null;
15
- export declare const useAd: () => AdSource | null;
15
+ export declare const useAd: () => import("../../types/customPlayer.types").AdSource | null;
16
16
  export declare const useCurrentMarker: () => Marker | null;
17
17
  export declare const useSeekState: () => boolean | null;
18
- interface AdSegment {
18
+ export declare const useAdSegment: () => {
19
+ id: string;
19
20
  remainingMs: number;
21
+ secondsToEnd: number;
22
+ secondsToSkippable: number | null;
20
23
  canSeek: boolean;
21
- }
22
- export declare const useAdSegment: () => AdSegment | null;
24
+ canSkip: boolean;
25
+ isSkippable: boolean;
26
+ skip: () => any;
27
+ } | null;
23
28
  export {};
@@ -1,11 +1,11 @@
1
- import { PaginationInterface, SubscribeToItemsInRowOptions, Tag, Video } from '@tivio/common';
1
+ import { ItemsInRow, PaginationInterface, SubscribeToItemsInRowOptions } from '@tivio/common';
2
2
  /**
3
3
  * Use row items
4
4
  * @param rowId - row ID
5
5
  * @param options - subscription options
6
6
  */
7
7
  declare const useItemsInRow: (rowId: string, options?: SubscribeToItemsInRowOptions) => {
8
- pagination: PaginationInterface<Video | Tag> | null;
8
+ pagination: PaginationInterface<ItemsInRow> | null;
9
9
  error: Error | null;
10
10
  };
11
11
  export { useItemsInRow, };
@@ -0,0 +1,2 @@
1
+ import { Video } from '@tivio/common';
2
+ export declare function useLastVideoByWidgetId(widgetId: string): Video | null;
@@ -1,4 +1,4 @@
1
1
  import { QerkoTransaction } from '@tivio/common';
2
- import { Voucher } from './useTransactionPayment';
3
- declare const usePurchaseSubscription: (monetizationId: string, voucher?: Voucher | undefined) => QerkoTransaction;
2
+ import { NewVoucher } from './useTransactionPayment';
3
+ declare const usePurchaseSubscription: (monetizationId: string, voucher?: NewVoucher | undefined) => QerkoTransaction;
4
4
  export { usePurchaseSubscription, };
@@ -1,10 +1,10 @@
1
1
  import { QerkoTransaction } from '@tivio/common';
2
- declare type Voucher = {
3
- /**
4
- * Voucher expiration date as a Date object or timestamp in ms.
5
- */
2
+ /**
3
+ * TODO: Duplicate, because we can't import types from core-js.
4
+ */
5
+ declare type NewVoucher = {
6
6
  expirationDate: Date | number;
7
7
  };
8
- declare const useTransactionPayment: (videoId: string, monetizationId: string, voucher?: Voucher | undefined) => QerkoTransaction;
8
+ declare const useTransactionPayment: (videoId: string, monetizationId: string, voucher?: NewVoucher | undefined) => QerkoTransaction;
9
9
  export { useTransactionPayment, };
10
- export type { Voucher, };
10
+ export type { NewVoucher, };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * TODO: Should be in core-js, we can't import types from it, though.
3
+ */
4
+ declare type Voucher = {
5
+ activate: () => void;
6
+ isUsed: boolean;
7
+ isExpired: boolean;
8
+ status: 'NEW' | 'USED';
9
+ voucherInfo: any;
10
+ };
11
+ declare const useVoucher: (voucherId: string) => {
12
+ activate: (() => Promise<void>) | null;
13
+ voucher: Voucher | null;
14
+ error: Error | null;
15
+ };
16
+ export { useVoucher, };
@@ -0,0 +1,4 @@
1
+ export declare const useWatchWithoutAdsOffer: () => {
2
+ canPurchaseWatchWithoutAds: boolean;
3
+ showPurchaseDialog: () => void;
4
+ };
package/dist/index.d.ts CHANGED
@@ -23,3 +23,4 @@ export { TivioGetters } from './types/bundle.types';
23
23
  export { TivioSubscriptions } from './types/bundle.types';
24
24
  export { PlayerCapability } from './types/bundle.types';
25
25
  export { Currency } from './types/bundle.types';
26
+ export { setUser } from './services/login';