@thestatic-tv/dcl-sdk 1.0.7 → 2.0.1

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/README.md CHANGED
@@ -1,51 +1,65 @@
1
- # @thestatic/dcl-sdk
1
+ # @thestatic-tv/dcl-sdk
2
2
 
3
3
  Connect your Decentraland scene to [thestatic.tv](https://thestatic.tv) - the decentralized streaming platform.
4
4
 
5
+ [![npm version](https://img.shields.io/npm/v/@thestatic-tv/dcl-sdk?color=00e5e5)](https://www.npmjs.com/package/@thestatic-tv/dcl-sdk)
6
+ [![DCL SDK](https://img.shields.io/badge/DCL%20SDK-7.x-blue)](https://docs.decentraland.org/)
7
+
5
8
  This SDK allows DCL scene builders to:
9
+ - Track visitors to your Decentraland scene
6
10
  - Display the full thestatic.tv channel lineup in their scenes
7
11
  - Track video watching metrics
8
12
  - Enable likes/follows from within DCL
9
13
  - Get referral credit for driving traffic to channels
10
14
 
11
- ## Two Modes
15
+ ## Pricing
16
+
17
+ | Mode | Price | Key Prefix | Features |
18
+ |------|-------|------------|----------|
19
+ | **Lite** | $5/mo | `dcls_` | Session/visitor tracking only |
20
+ | **Full** | $10/mo | `dclk_` | Guide, Heartbeat, Sessions, Interactions, **Guide UI**, **Chat UI** |
21
+
22
+ > **Free Trial**: All new scene keys include a 7-day free trial!
23
+ >
24
+ > **Expiry Warnings**: You'll receive dashboard notifications at 7, 3, and 1 days before your subscription expires.
25
+
26
+ Get your key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) → DCL Scenes tab.
27
+
28
+ ### Coordinate Locking
12
29
 
13
- | Mode | Key Prefix | Features | Get Key From |
14
- |------|------------|----------|--------------|
15
- | **Full** | `dclk_` | Guide, Heartbeat, Sessions, Interactions | Studio (channel owners) |
16
- | **Lite** | `dcls_` | Sessions only (visitor tracking) | Profile (all users) |
30
+ When you create a scene key, you'll be asked to confirm your parcel coordinates. **Once confirmed, coordinates are permanently locked** to prevent key reuse across different scenes. This ensures analytics accurately reflect a single scene.
17
31
 
18
- The SDK auto-detects your key type and enables/disables features accordingly.
32
+ ### Key Rotation
19
33
 
20
- > **Free Trial**: New accounts get 7 days of free visitor tracking!
34
+ If you need to rotate your API key (e.g., if compromised), you can do so from the dashboard without losing your subscription or analytics history. The old key is immediately invalidated.
21
35
 
22
36
  ## Example Scene
23
37
 
24
- Clone our example scene to get started quickly:
38
+ Clone our starter scene to get started quickly:
25
39
 
26
40
  ```bash
27
- git clone https://github.com/thestatic-tv/dcl-example.git
28
- cd dcl-example
41
+ git clone https://github.com/thestatic-tv/thestatic-dcl-starter.git
42
+ cd thestatic-dcl-starter
29
43
  npm install
30
44
  npm start
31
45
  ```
32
46
 
33
- See the [example repo](https://github.com/thestatic-tv/dcl-example) for a complete working scene.
47
+ See the [starter repo](https://github.com/thestatic-tv/thestatic-dcl-starter) for a complete working scene.
34
48
 
35
49
  ## Installation
36
50
 
37
51
  ```bash
38
- npm install @thestatic/dcl-sdk
52
+ npm install @thestatic-tv/dcl-sdk
39
53
  ```
40
54
 
41
55
  ## Quick Start
42
56
 
43
- 1. Get your API key from [thestatic.tv/studio](https://thestatic.tv/studio) (DCL Integration tab)
57
+ 1. Get your API key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) (DCL Scenes tab)
44
58
 
45
59
  2. Initialize the client in your scene:
46
60
 
47
61
  ```typescript
48
- import { StaticTVClient } from '@thestatic/dcl-sdk'
62
+ import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
49
63
 
50
64
  const staticTV = new StaticTVClient({
51
65
  apiKey: 'dclk_your_api_key_here',
@@ -96,12 +110,12 @@ await staticTV.destroy()
96
110
 
97
111
  If you don't have a channel but want to track visitors to your scene:
98
112
 
99
- 1. Get a scene key from [thestatic.tv/profile](https://thestatic.tv/profile) (DCL Scenes tab)
113
+ 1. Get a scene key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) (DCL Scenes tab)
100
114
 
101
115
  2. Initialize with your scene key:
102
116
 
103
117
  ```typescript
104
- import { StaticTVClient } from '@thestatic/dcl-sdk'
118
+ import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
105
119
 
106
120
  const staticTV = new StaticTVClient({
107
121
  apiKey: 'dcls_your_scene_key_here'
@@ -150,6 +164,8 @@ Main client class for interacting with thestatic.tv.
150
164
  | `session` | `SessionModule` | Session module (always available) |
151
165
  | `heartbeat` | `HeartbeatModule \| null` | Heartbeat module (null in lite mode) |
152
166
  | `interactions` | `InteractionsModule \| null` | Interactions module (null in lite mode) |
167
+ | `guideUI` | `GuideUIModule \| null` | Guide UI module (null in lite mode) |
168
+ | `chatUI` | `ChatUIModule \| null` | Chat UI module (null in lite mode) |
153
169
 
154
170
  ### Guide Module (Full Mode Only)
155
171
 
@@ -192,6 +208,91 @@ staticTV.interactions.like(channelSlug) // Like a channel
192
208
  staticTV.interactions.follow(channelSlug) // Follow a channel
193
209
  ```
194
210
 
211
+ ### Guide UI Module (Full Mode Only)
212
+
213
+ Built-in channel browser UI. You provide a callback to handle video selection.
214
+
215
+ ```typescript
216
+ // Configure in constructor
217
+ const staticTV = new StaticTVClient({
218
+ apiKey: 'dclk_your_api_key',
219
+ guideUI: {
220
+ onVideoSelect: (video) => {
221
+ // Handle video playback in your scene
222
+ console.log('Playing:', video.name, video.src)
223
+ }
224
+ }
225
+ })
226
+
227
+ // Initialize the UI (call once after client is created)
228
+ await staticTV.guideUI.init()
229
+
230
+ // Show/hide the guide
231
+ staticTV.guideUI.show()
232
+ staticTV.guideUI.hide()
233
+ staticTV.guideUI.toggle()
234
+
235
+ // Check visibility
236
+ if (staticTV.guideUI.isVisible) { ... }
237
+
238
+ // Update "PLAYING" indicator
239
+ staticTV.guideUI.currentVideoId = 'video-id'
240
+
241
+ // Refresh data
242
+ await staticTV.guideUI.refresh()
243
+ ```
244
+
245
+ ### Chat UI Module (Full Mode Only)
246
+
247
+ Real-time chat with Firebase authentication.
248
+
249
+ ```typescript
250
+ // Configure in constructor
251
+ const staticTV = new StaticTVClient({
252
+ apiKey: 'dclk_your_api_key',
253
+ chatUI: {
254
+ position: 'right', // 'left', 'center', or 'right'
255
+ fontScale: 1.0
256
+ }
257
+ })
258
+
259
+ // Initialize the chat (call once after client is created)
260
+ await staticTV.chatUI.init()
261
+
262
+ // Show/hide the chat
263
+ staticTV.chatUI.show()
264
+ staticTV.chatUI.hide()
265
+ staticTV.chatUI.toggle()
266
+
267
+ // Check visibility
268
+ if (staticTV.chatUI.isVisible) { ... }
269
+
270
+ // Get unread message count (for badge display)
271
+ const unread = staticTV.chatUI.unreadCount
272
+
273
+ // Switch channels
274
+ staticTV.chatUI.setChannel('channel-slug')
275
+ ```
276
+
277
+ ### Rendering UI Components
278
+
279
+ The UI modules provide `getComponent()` methods that return React-ECS elements. Call these in your UI renderer:
280
+
281
+ ```typescript
282
+ import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
283
+
284
+ // In your scene setup
285
+ ReactEcsRenderer.setUiRenderer(() => {
286
+ return (
287
+ <>
288
+ {/* Your other UI elements */}
289
+ {staticTV.guideUI?.getComponent()}
290
+ {staticTV.chatUI?.getComponent()}
291
+ </>
292
+ )
293
+ })
294
+ ```
295
+
195
296
  ## Metrics Attribution
196
297
 
197
298
  This SDK implements dual attribution:
package/dist/index.d.mts CHANGED
@@ -34,6 +34,14 @@ interface StaticTVConfig {
34
34
  * })
35
35
  */
36
36
  player?: PlayerData;
37
+ /**
38
+ * Guide UI configuration (channel keys only)
39
+ */
40
+ guideUI?: GuideUIConfig;
41
+ /**
42
+ * Chat UI configuration (channel keys only)
43
+ */
44
+ chatUI?: ChatUIConfig;
37
45
  }
38
46
  /**
39
47
  * Channel information from the guide
@@ -124,6 +132,75 @@ interface SceneStatsResponse {
124
132
  sceneName: string | null;
125
133
  version: string;
126
134
  }
135
+ /**
136
+ * Video data for the guide UI
137
+ */
138
+ interface GuideVideo {
139
+ id: string;
140
+ name: string;
141
+ src: string;
142
+ isLive?: boolean;
143
+ isCreator?: boolean;
144
+ channelId?: string;
145
+ duration?: number;
146
+ requiresAuth?: boolean;
147
+ }
148
+ /**
149
+ * Featured playlist for the guide UI
150
+ */
151
+ interface GuideFeaturedPlaylist {
152
+ name: string;
153
+ videos: GuideVideo[];
154
+ }
155
+ /**
156
+ * Configuration options for GuideUIModule
157
+ */
158
+ interface GuideUIConfig {
159
+ /**
160
+ * Callback when user selects a video
161
+ * Developer should handle playback
162
+ */
163
+ onVideoSelect?: (video: GuideVideo) => void;
164
+ /**
165
+ * Current video ID (for "PLAYING" indicator)
166
+ */
167
+ currentVideoId?: string;
168
+ /**
169
+ * UI scale multiplier (default: 1.0)
170
+ */
171
+ uiScale?: number;
172
+ }
173
+ /**
174
+ * Chat channel data
175
+ */
176
+ interface ChatChannel {
177
+ id: string;
178
+ name: string;
179
+ }
180
+ /**
181
+ * Chat message data
182
+ */
183
+ interface ChatMessage {
184
+ id: string;
185
+ username: string;
186
+ text: string;
187
+ uid: string;
188
+ createdAt: any;
189
+ isSystem?: boolean;
190
+ }
191
+ /**
192
+ * Configuration options for ChatUIModule
193
+ */
194
+ interface ChatUIConfig {
195
+ /**
196
+ * Chat panel position (default: 'right')
197
+ */
198
+ position?: 'left' | 'center' | 'right';
199
+ /**
200
+ * Font scale multiplier (default: 1.0)
201
+ */
202
+ fontScale?: number;
203
+ }
127
204
 
128
205
  /**
129
206
  * Guide module - fetch channel lineup from thestatic.tv
@@ -279,11 +356,176 @@ declare class InteractionsModule {
279
356
  follow(channelSlug: string): Promise<InteractionResponse | null>;
280
357
  }
281
358
 
359
+ /**
360
+ * Guide UI Module - provides channel/video browser
361
+ */
362
+ declare class GuideUIModule {
363
+ private client;
364
+ private config;
365
+ private _isVisible;
366
+ private videos;
367
+ private featuredPlaylists;
368
+ private liveVideos;
369
+ private activeTab;
370
+ private currentPage;
371
+ private itemsPerPage;
372
+ private searchQuery;
373
+ private uiScale;
374
+ private _currentVideoId;
375
+ constructor(client: StaticTVClient, config?: GuideUIConfig);
376
+ /**
377
+ * Initialize the guide - fetch channel data
378
+ */
379
+ init(): Promise<void>;
380
+ /**
381
+ * Show the guide UI
382
+ */
383
+ show(): void;
384
+ /**
385
+ * Hide the guide UI
386
+ */
387
+ hide(): void;
388
+ /**
389
+ * Toggle guide visibility
390
+ */
391
+ toggle(): void;
392
+ /**
393
+ * Check if guide is visible
394
+ */
395
+ get isVisible(): boolean;
396
+ /**
397
+ * Set the currently playing video ID (for "PLAYING" indicator)
398
+ */
399
+ set currentVideoId(id: string | null);
400
+ /**
401
+ * Get the currently playing video ID
402
+ */
403
+ get currentVideoId(): string | null;
404
+ /**
405
+ * Get all videos
406
+ */
407
+ getVideos(): GuideVideo[];
408
+ /**
409
+ * Get live videos only
410
+ */
411
+ getLiveVideos(): GuideVideo[];
412
+ /**
413
+ * Refresh guide data
414
+ */
415
+ refresh(): Promise<void>;
416
+ private getBaseUrl;
417
+ private fetchGuideData;
418
+ private s;
419
+ private handleVideoSelect;
420
+ private handleChannelClick;
421
+ /**
422
+ * Get the guide UI component for rendering
423
+ */
424
+ getComponent: () => any;
425
+ private renderLeftPanel;
426
+ private renderMenuButton;
427
+ private renderRightPanel;
428
+ private renderCardGrid;
429
+ private renderGuideCard;
430
+ private renderCloseButton;
431
+ }
432
+
433
+ /**
434
+ * Chat UI Module - provides real-time chat functionality
435
+ */
436
+ declare class ChatUIModule {
437
+ private client;
438
+ private config;
439
+ private _isVisible;
440
+ private _unreadCount;
441
+ private idToken;
442
+ private isSigningIn;
443
+ private isRegisteredUser;
444
+ private currentUsername;
445
+ private currentUserId;
446
+ private channels;
447
+ private currentChannelId;
448
+ private showChannelDropdown;
449
+ private channelPage;
450
+ private realMessages;
451
+ private systemMessages;
452
+ private inputText;
453
+ private chatScrollOffset;
454
+ private position;
455
+ private fontScale;
456
+ private chatTimerId;
457
+ private playerInfoTimerId;
458
+ private isInitialized;
459
+ constructor(client: StaticTVClient, config?: ChatUIConfig);
460
+ /**
461
+ * Initialize the chat system
462
+ */
463
+ init(): Promise<void>;
464
+ /**
465
+ * Show the chat UI
466
+ */
467
+ show(): void;
468
+ /**
469
+ * Hide the chat UI
470
+ */
471
+ hide(): void;
472
+ /**
473
+ * Toggle chat visibility
474
+ */
475
+ toggle(): void;
476
+ /**
477
+ * Check if chat is visible
478
+ */
479
+ get isVisible(): boolean;
480
+ /**
481
+ * Get unread message count
482
+ */
483
+ get unreadCount(): number;
484
+ /**
485
+ * Get current channel ID
486
+ */
487
+ get currentChannel(): string;
488
+ /**
489
+ * Switch to a different channel
490
+ */
491
+ setChannel(channelId: string): void;
492
+ /**
493
+ * Cleanup resources
494
+ */
495
+ destroy(): void;
496
+ private getBaseUrl;
497
+ private performAuth;
498
+ private fetchChannels;
499
+ private fetchMessages;
500
+ private handleSend;
501
+ private generateBootSequence;
502
+ private fetchPlayerInfo;
503
+ private switchChannel;
504
+ private startChatLoop;
505
+ private chatLoop;
506
+ private resetChatTimer;
507
+ private parseServerTime;
508
+ private formatTime;
509
+ /**
510
+ * Get the chat UI component for rendering
511
+ */
512
+ getComponent: () => any;
513
+ private getPositionStyle;
514
+ private renderHeader;
515
+ private renderChannelButton;
516
+ private renderMessagesArea;
517
+ private renderSystemMessage;
518
+ private renderChatMessage;
519
+ private renderUserInfoBar;
520
+ private renderInputArea;
521
+ private renderChannelDropdown;
522
+ }
523
+
282
524
  /**
283
525
  * StaticTVClient - Main client for connecting DCL scenes to thestatic.tv
284
526
  *
285
527
  * Supports two key types:
286
- * - dclk_* : Channel keys (full access - guide, heartbeat, interactions)
528
+ * - dclk_* : Channel keys (full access - guide, heartbeat, interactions, UI)
287
529
  * - dcls_* : Scene-only keys (lite - session tracking only)
288
530
  */
289
531
 
@@ -302,6 +544,10 @@ declare class StaticTVClient {
302
544
  readonly heartbeat: HeartbeatModule | null;
303
545
  /** Interactions module - like/follow channels (channel keys only) */
304
546
  readonly interactions: InteractionsModule | null;
547
+ /** Guide UI module - channel browser UI (channel keys only) */
548
+ readonly guideUI: GuideUIModule | null;
549
+ /** Chat UI module - real-time chat UI (channel keys only) */
550
+ readonly chatUI: ChatUIModule | null;
305
551
  /**
306
552
  * Create a new StaticTVClient
307
553
  *
@@ -375,4 +621,4 @@ declare function getPlayerWallet(): string | null;
375
621
  */
376
622
  declare function getPlayerDisplayName(): string | null;
377
623
 
378
- export { type Channel, GuideModule, type GuideResponse, HeartbeatModule, type HeartbeatResponse, type InteractionResponse, InteractionsModule, KEY_TYPE_CHANNEL, KEY_TYPE_SCENE, type PlayerData, type SceneStats, type SceneStatsResponse, SessionModule, type SessionResponse, StaticTVClient, type StaticTVConfig, type Vod, fetchUserData, getPlayerDisplayName, getPlayerWallet };
624
+ export { type Channel, type ChatChannel, type ChatMessage, type ChatUIConfig, ChatUIModule, type GuideFeaturedPlaylist, GuideModule, type GuideResponse, type GuideUIConfig, GuideUIModule, type GuideVideo, HeartbeatModule, type HeartbeatResponse, type InteractionResponse, InteractionsModule, KEY_TYPE_CHANNEL, KEY_TYPE_SCENE, type PlayerData, type SceneStats, type SceneStatsResponse, SessionModule, type SessionResponse, StaticTVClient, type StaticTVConfig, type Vod, fetchUserData, getPlayerDisplayName, getPlayerWallet };