@tivio/sdk-react 3.0.0-alpha3 → 3.1.1

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