unified-video-framework 1.0.0

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.
Files changed (129) hide show
  1. package/.github/workflows/ci.yml +253 -0
  2. package/ANDROID_TV_IMPLEMENTATION.md +313 -0
  3. package/COMPLETION_STATUS.md +165 -0
  4. package/CONTRIBUTING.md +376 -0
  5. package/FINAL_STATUS_REPORT.md +170 -0
  6. package/FRAMEWORK_REVIEW.md +247 -0
  7. package/IMPROVEMENTS_SUMMARY.md +168 -0
  8. package/LICENSE +21 -0
  9. package/NATIVE_APP_INTEGRATION_GUIDE.md +903 -0
  10. package/PAYWALL_RENTAL_FLOW.md +499 -0
  11. package/PLATFORM_SETUP_GUIDE.md +1636 -0
  12. package/README.md +315 -0
  13. package/RUN_LOCALLY.md +151 -0
  14. package/apps/demo/cast-sender-min.html +173 -0
  15. package/apps/demo/custom-player.html +883 -0
  16. package/apps/demo/demo.html +990 -0
  17. package/apps/demo/enhanced-player.html +3556 -0
  18. package/apps/demo/index.html +159 -0
  19. package/apps/rental-api/.env.example +24 -0
  20. package/apps/rental-api/README.md +23 -0
  21. package/apps/rental-api/migrations/001_init.sql +35 -0
  22. package/apps/rental-api/migrations/002_videos.sql +10 -0
  23. package/apps/rental-api/migrations/003_add_gateway_subref.sql +4 -0
  24. package/apps/rental-api/migrations/004_update_gateways.sql +4 -0
  25. package/apps/rental-api/migrations/005_seed_demo_video.sql +5 -0
  26. package/apps/rental-api/package-lock.json +2045 -0
  27. package/apps/rental-api/package.json +33 -0
  28. package/apps/rental-api/scripts/run-migration.js +42 -0
  29. package/apps/rental-api/scripts/update-video-currency.js +21 -0
  30. package/apps/rental-api/scripts/update-video-price.js +19 -0
  31. package/apps/rental-api/src/config.ts +14 -0
  32. package/apps/rental-api/src/db.ts +10 -0
  33. package/apps/rental-api/src/routes/cashfree.ts +167 -0
  34. package/apps/rental-api/src/routes/pesapal.ts +92 -0
  35. package/apps/rental-api/src/routes/rentals.ts +242 -0
  36. package/apps/rental-api/src/routes/webhooks.ts +73 -0
  37. package/apps/rental-api/src/server.ts +41 -0
  38. package/apps/rental-api/src/services/entitlements.ts +45 -0
  39. package/apps/rental-api/src/services/payments.ts +22 -0
  40. package/apps/rental-api/tsconfig.json +17 -0
  41. package/check-urls.ps1 +74 -0
  42. package/comparison-report.md +181 -0
  43. package/docs/PAYWALL.md +95 -0
  44. package/docs/PLAYER_UI_VISIBILITY.md +431 -0
  45. package/docs/README.md +7 -0
  46. package/docs/SYSTEM_ARCHITECTURE.md +612 -0
  47. package/docs/VDOCIPHER_CLONE_REQUIREMENTS.md +403 -0
  48. package/examples/android/JavaSampleApp/MainActivity.java +641 -0
  49. package/examples/android/JavaSampleApp/activity_main.xml +226 -0
  50. package/examples/android/SampleApp/MainActivity.kt +430 -0
  51. package/examples/ios/SampleApp/ViewController.swift +337 -0
  52. package/examples/ios/SwiftUISampleApp/ContentView.swift +304 -0
  53. package/iOS_IMPLEMENTATION_OPTIONS.md +470 -0
  54. package/ios/UnifiedVideoPlayer/UnifiedVideoPlayer.podspec +33 -0
  55. package/jest.config.js +33 -0
  56. package/jitpack.yml +5 -0
  57. package/lerna.json +35 -0
  58. package/package.json +69 -0
  59. package/packages/PLATFORM_STATUS.md +163 -0
  60. package/packages/android/build.gradle +135 -0
  61. package/packages/android/src/main/AndroidManifest.xml +36 -0
  62. package/packages/android/src/main/java/com/unifiedvideo/player/PlayerConfiguration.java +221 -0
  63. package/packages/android/src/main/java/com/unifiedvideo/player/UnifiedVideoPlayer.java +1037 -0
  64. package/packages/android/src/main/java/com/unifiedvideo/player/UnifiedVideoPlayer.kt +707 -0
  65. package/packages/android/src/main/java/com/unifiedvideo/player/analytics/AnalyticsProvider.java +9 -0
  66. package/packages/android/src/main/java/com/unifiedvideo/player/cast/CastManager.java +141 -0
  67. package/packages/android/src/main/java/com/unifiedvideo/player/cast/CastOptionsProvider.java +29 -0
  68. package/packages/android/src/main/java/com/unifiedvideo/player/overlay/WatermarkOverlayView.java +88 -0
  69. package/packages/android/src/main/java/com/unifiedvideo/player/pip/PipActionReceiver.java +33 -0
  70. package/packages/android/src/main/java/com/unifiedvideo/player/services/PlaybackService.java +110 -0
  71. package/packages/android/src/main/java/com/unifiedvideo/player/services/PlayerHolder.java +19 -0
  72. package/packages/core/package.json +34 -0
  73. package/packages/core/src/BasePlayer.ts +250 -0
  74. package/packages/core/src/VideoPlayer.ts +237 -0
  75. package/packages/core/src/VideoPlayerFactory.ts +145 -0
  76. package/packages/core/src/index.ts +20 -0
  77. package/packages/core/src/interfaces/IVideoPlayer.ts +184 -0
  78. package/packages/core/src/interfaces.ts +240 -0
  79. package/packages/core/src/utils/EventEmitter.ts +66 -0
  80. package/packages/core/src/utils/PlatformDetector.ts +300 -0
  81. package/packages/core/tsconfig.json +20 -0
  82. package/packages/enact/package.json +51 -0
  83. package/packages/enact/src/VideoPlayer.js +365 -0
  84. package/packages/enact/src/adapters/TizenAdapter.js +354 -0
  85. package/packages/enact/src/index.js +82 -0
  86. package/packages/ios/BUILD_INSTRUCTIONS.md +108 -0
  87. package/packages/ios/FIX_EMBED_ISSUE.md +142 -0
  88. package/packages/ios/GETTING_STARTED.md +100 -0
  89. package/packages/ios/Package.swift +35 -0
  90. package/packages/ios/README.md +84 -0
  91. package/packages/ios/Sources/UnifiedVideoPlayer/Analytics/AnalyticsEmitter.swift +26 -0
  92. package/packages/ios/Sources/UnifiedVideoPlayer/DRM/FairPlayDRMManager.swift +102 -0
  93. package/packages/ios/Sources/UnifiedVideoPlayer/Info.plist +24 -0
  94. package/packages/ios/Sources/UnifiedVideoPlayer/Remote/RemoteCommandCenter.swift +109 -0
  95. package/packages/ios/Sources/UnifiedVideoPlayer/UnifiedVideoPlayer.swift +811 -0
  96. package/packages/ios/Sources/UnifiedVideoPlayer/UnifiedVideoPlayerView.swift +640 -0
  97. package/packages/ios/Sources/UnifiedVideoPlayer/Utilities/Color+Hex.swift +36 -0
  98. package/packages/ios/UnifiedVideoPlayer.podspec +27 -0
  99. package/packages/ios/UnifiedVideoPlayer.xcodeproj/project.pbxproj +385 -0
  100. package/packages/ios/build_framework.sh +55 -0
  101. package/packages/react-native/android/src/main/java/com/unifiedvideo/UnifiedVideoPlayerModule.kt +482 -0
  102. package/packages/react-native/ios/UnifiedVideoPlayer.swift +436 -0
  103. package/packages/react-native/package.json +51 -0
  104. package/packages/react-native/src/ReactNativePlayer.tsx +423 -0
  105. package/packages/react-native/src/VideoPlayer.tsx +224 -0
  106. package/packages/react-native/src/index.ts +28 -0
  107. package/packages/react-native/src/utils/EventEmitter.ts +66 -0
  108. package/packages/react-native/tsconfig.json +31 -0
  109. package/packages/roku/components/UnifiedVideoPlayer.brs +400 -0
  110. package/packages/roku/package.json +44 -0
  111. package/packages/roku/source/VideoPlayer.brs +231 -0
  112. package/packages/roku/source/main.brs +28 -0
  113. package/packages/web/GETTING_STARTED.md +292 -0
  114. package/packages/web/jest.config.js +28 -0
  115. package/packages/web/jest.setup.ts +110 -0
  116. package/packages/web/package.json +50 -0
  117. package/packages/web/src/SecureVideoPlayer.ts +1164 -0
  118. package/packages/web/src/WebPlayer.ts +3110 -0
  119. package/packages/web/src/__tests__/WebPlayer.test.ts +314 -0
  120. package/packages/web/src/index.ts +14 -0
  121. package/packages/web/src/paywall/PaywallController.ts +215 -0
  122. package/packages/web/src/react/WebPlayerView.tsx +177 -0
  123. package/packages/web/tsconfig.json +23 -0
  124. package/packages/web/webpack.config.js +45 -0
  125. package/server.js +131 -0
  126. package/server.py +84 -0
  127. package/test-urls.ps1 +97 -0
  128. package/test-video-urls.ps1 +87 -0
  129. package/tsconfig.json +39 -0
@@ -0,0 +1,300 @@
1
+ import { PlatformType, PlatformInfo } from '../interfaces';
2
+
3
+ export class PlatformDetector {
4
+ private cachedPlatform: PlatformInfo | null = null;
5
+
6
+ detect(): PlatformInfo {
7
+ if (this.cachedPlatform) {
8
+ return this.cachedPlatform;
9
+ }
10
+
11
+ this.cachedPlatform = this.detectPlatform();
12
+ return this.cachedPlatform;
13
+ }
14
+
15
+ private detectPlatform(): PlatformInfo {
16
+ // Check if we're in React Native environment
17
+ if (typeof window === 'undefined' || (global as any).nativeCallSyncHook) {
18
+ return this.detectReactNativePlatform();
19
+ }
20
+
21
+ // Web environment detection
22
+ if (typeof window !== 'undefined' && typeof navigator !== 'undefined') {
23
+ return this.detectWebPlatform();
24
+ }
25
+
26
+ // Default fallback
27
+ return {
28
+ type: PlatformType.WEB,
29
+ os: 'unknown',
30
+ version: 'unknown',
31
+ isTV: false,
32
+ isMobile: false,
33
+ isDesktop: true
34
+ };
35
+ }
36
+
37
+ private detectReactNativePlatform(): PlatformInfo {
38
+ try {
39
+ // This would be available in React Native environment
40
+ const { Platform } = require('react-native');
41
+
42
+ if (Platform.isTV) {
43
+ return {
44
+ type: Platform.OS === 'ios' ? PlatformType.APPLE_TV : PlatformType.ANDROID_TV,
45
+ os: Platform.OS,
46
+ version: Platform.Version?.toString() || 'unknown',
47
+ isTV: true,
48
+ isMobile: false,
49
+ isDesktop: false
50
+ };
51
+ }
52
+
53
+ return {
54
+ type: Platform.OS === 'ios' ? PlatformType.IOS : PlatformType.ANDROID,
55
+ os: Platform.OS,
56
+ version: Platform.Version?.toString() || 'unknown',
57
+ isTV: false,
58
+ isMobile: true,
59
+ isDesktop: false
60
+ };
61
+ } catch (e) {
62
+ // If React Native is not available, fall back to web detection
63
+ return this.detectWebPlatform();
64
+ }
65
+ }
66
+
67
+ private detectWebPlatform(): PlatformInfo {
68
+ const userAgent = navigator.userAgent.toLowerCase();
69
+ const platform = navigator.platform?.toLowerCase() || '';
70
+
71
+ // Tizen (Samsung TV)
72
+ if (userAgent.includes('tizen') || (window as any).tizen) {
73
+ return {
74
+ type: PlatformType.TIZEN,
75
+ os: 'tizen',
76
+ version: this.getTizenVersion(),
77
+ isTV: true,
78
+ isMobile: false,
79
+ isDesktop: false,
80
+ screenSize: this.getScreenSize()
81
+ };
82
+ }
83
+
84
+ // WebOS (LG TV)
85
+ if (userAgent.includes('webos') || userAgent.includes('web0s') || (window as any).webOS) {
86
+ return {
87
+ type: PlatformType.WEBOS,
88
+ os: 'webos',
89
+ version: this.getWebOSVersion(),
90
+ isTV: true,
91
+ isMobile: false,
92
+ isDesktop: false,
93
+ screenSize: this.getScreenSize()
94
+ };
95
+ }
96
+
97
+ // Roku
98
+ if (userAgent.includes('roku')) {
99
+ return {
100
+ type: PlatformType.ROKU,
101
+ os: 'roku',
102
+ version: this.getRokuVersion(userAgent),
103
+ isTV: true,
104
+ isMobile: false,
105
+ isDesktop: false
106
+ };
107
+ }
108
+
109
+ // Windows/UWP
110
+ if (platform.includes('win') || userAgent.includes('windows')) {
111
+ return {
112
+ type: PlatformType.WINDOWS,
113
+ os: 'windows',
114
+ version: this.getWindowsVersion(userAgent),
115
+ isTV: false,
116
+ isMobile: false,
117
+ isDesktop: true,
118
+ hasTouch: this.hasTouchSupport(),
119
+ screenSize: this.getScreenSize()
120
+ };
121
+ }
122
+
123
+ // iOS (Safari on iPhone/iPad)
124
+ if (/iphone|ipad|ipod/.test(userAgent) ||
125
+ (platform === 'macintel' && navigator.maxTouchPoints > 1)) {
126
+ return {
127
+ type: PlatformType.IOS,
128
+ os: 'ios',
129
+ version: this.getIOSVersion(userAgent),
130
+ isTV: false,
131
+ isMobile: true,
132
+ isDesktop: false,
133
+ hasTouch: true,
134
+ screenSize: this.getScreenSize()
135
+ };
136
+ }
137
+
138
+ // Android
139
+ if (userAgent.includes('android')) {
140
+ const isTV = userAgent.includes('tv') || userAgent.includes('aft');
141
+ return {
142
+ type: isTV ? PlatformType.ANDROID_TV : PlatformType.ANDROID,
143
+ os: 'android',
144
+ version: this.getAndroidVersion(userAgent),
145
+ isTV: isTV,
146
+ isMobile: !isTV,
147
+ isDesktop: false,
148
+ hasTouch: !isTV,
149
+ screenSize: this.getScreenSize()
150
+ };
151
+ }
152
+
153
+ // Apple TV (tvOS browser)
154
+ if (userAgent.includes('appletv')) {
155
+ return {
156
+ type: PlatformType.APPLE_TV,
157
+ os: 'tvos',
158
+ version: 'unknown',
159
+ isTV: true,
160
+ isMobile: false,
161
+ isDesktop: false
162
+ };
163
+ }
164
+
165
+ // Default to web
166
+ return {
167
+ type: PlatformType.WEB,
168
+ os: this.getOS(),
169
+ version: 'unknown',
170
+ isTV: false,
171
+ isMobile: this.isMobileWeb(),
172
+ isDesktop: !this.isMobileWeb(),
173
+ hasTouch: this.hasTouchSupport(),
174
+ screenSize: this.getScreenSize()
175
+ };
176
+ }
177
+
178
+ private getTizenVersion(): string {
179
+ try {
180
+ if ((window as any).tizen && (window as any).tizen.systeminfo) {
181
+ return (window as any).tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version');
182
+ }
183
+ } catch (e) {
184
+ console.error('Failed to get Tizen version:', e);
185
+ }
186
+ return 'unknown';
187
+ }
188
+
189
+ private getWebOSVersion(): string {
190
+ try {
191
+ if ((window as any).webOS && (window as any).webOS.systemInfo) {
192
+ return (window as any).webOS.systemInfo.version;
193
+ }
194
+ } catch (e) {
195
+ console.error('Failed to get webOS version:', e);
196
+ }
197
+ return 'unknown';
198
+ }
199
+
200
+ private getRokuVersion(userAgent: string): string {
201
+ const match = userAgent.match(/roku\/dvp-(\d+\.\d+)/);
202
+ return match ? match[1] : 'unknown';
203
+ }
204
+
205
+ private getWindowsVersion(userAgent: string): string {
206
+ if (userAgent.includes('windows nt 10.0')) return '10';
207
+ if (userAgent.includes('windows nt 6.3')) return '8.1';
208
+ if (userAgent.includes('windows nt 6.2')) return '8';
209
+ if (userAgent.includes('windows nt 6.1')) return '7';
210
+ return 'unknown';
211
+ }
212
+
213
+ private getIOSVersion(userAgent: string): string {
214
+ const match = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/);
215
+ if (match) {
216
+ return `${match[1]}.${match[2]}${match[3] ? `.${match[3]}` : ''}`;
217
+ }
218
+ return 'unknown';
219
+ }
220
+
221
+ private getAndroidVersion(userAgent: string): string {
222
+ const match = userAgent.match(/android (\d+\.?\d*)/);
223
+ return match ? match[1] : 'unknown';
224
+ }
225
+
226
+ private getOS(): string {
227
+ const platform = navigator.platform?.toLowerCase() || '';
228
+ const userAgent = navigator.userAgent.toLowerCase();
229
+
230
+ if (platform.includes('mac')) return 'macos';
231
+ if (platform.includes('win')) return 'windows';
232
+ if (platform.includes('linux')) return 'linux';
233
+ if (userAgent.includes('cros')) return 'chromeos';
234
+
235
+ return 'unknown';
236
+ }
237
+
238
+ private isMobileWeb(): boolean {
239
+ const userAgent = navigator.userAgent.toLowerCase();
240
+ const mobileRegex = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i;
241
+ return mobileRegex.test(userAgent) || this.isSmallScreen();
242
+ }
243
+
244
+ private isSmallScreen(): boolean {
245
+ return window.innerWidth <= 768 && window.innerHeight <= 1024;
246
+ }
247
+
248
+ private hasTouchSupport(): boolean {
249
+ return 'ontouchstart' in window ||
250
+ navigator.maxTouchPoints > 0 ||
251
+ (navigator as any).msMaxTouchPoints > 0;
252
+ }
253
+
254
+ private getScreenSize(): { width: number; height: number } {
255
+ return {
256
+ width: window.screen?.width || window.innerWidth,
257
+ height: window.screen?.height || window.innerHeight
258
+ };
259
+ }
260
+
261
+ // Utility methods for specific platform checks
262
+ isTV(): boolean {
263
+ return this.detect().isTV;
264
+ }
265
+
266
+ isMobile(): boolean {
267
+ return this.detect().isMobile;
268
+ }
269
+
270
+ isDesktop(): boolean {
271
+ return this.detect().isDesktop || false;
272
+ }
273
+
274
+ isApple(): boolean {
275
+ const platform = this.detect().type;
276
+ return [PlatformType.IOS, PlatformType.APPLE_TV].includes(platform);
277
+ }
278
+
279
+ isAndroid(): boolean {
280
+ const platform = this.detect().type;
281
+ return [PlatformType.ANDROID, PlatformType.ANDROID_TV].includes(platform);
282
+ }
283
+
284
+ isSamsung(): boolean {
285
+ return this.detect().type === PlatformType.TIZEN;
286
+ }
287
+
288
+ isLG(): boolean {
289
+ return this.detect().type === PlatformType.WEBOS;
290
+ }
291
+
292
+ isRoku(): boolean {
293
+ return this.detect().type === PlatformType.ROKU;
294
+ }
295
+
296
+ // Clear cached platform info (useful for testing)
297
+ clearCache(): void {
298
+ this.cachedPlatform = null;
299
+ }
300
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./dist",
6
+ "composite": true,
7
+ "isolatedModules": false,
8
+ "skipLibCheck": true,
9
+ "moduleResolution": "node"
10
+ },
11
+ "include": [
12
+ "src/**/*"
13
+ ],
14
+ "exclude": [
15
+ "node_modules",
16
+ "dist",
17
+ "**/*.test.ts",
18
+ "**/*.spec.ts"
19
+ ]
20
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@unified-video/enact",
3
+ "version": "1.0.0",
4
+ "description": "Enact TV implementation of Unified Video Framework for Samsung Tizen and LG webOS",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "src"
10
+ ],
11
+ "scripts": {
12
+ "build": "webpack --mode production",
13
+ "dev": "webpack --mode development --watch",
14
+ "clean": "rm -rf dist",
15
+ "test": "jest",
16
+ "lint": "eslint src --ext .js,.jsx",
17
+ "build:tizen": "npm run build && tizen package -t wgt -o dist/tizen",
18
+ "build:webos": "npm run build && ares-package dist -o dist/webos"
19
+ },
20
+ "dependencies": {
21
+ "@unified-video/core": "^1.0.0",
22
+ "@unified-video/web": "^1.0.0",
23
+ "@enact/core": "^4.0.0",
24
+ "@enact/ui": "^4.0.0",
25
+ "@enact/moonstone": "^4.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^18.0.0",
29
+ "webpack": "^5.75.0",
30
+ "webpack-cli": "^5.0.0",
31
+ "babel-loader": "^9.0.0",
32
+ "@babel/core": "^7.0.0",
33
+ "@babel/preset-env": "^7.0.0"
34
+ },
35
+ "keywords": [
36
+ "video",
37
+ "player",
38
+ "tv",
39
+ "smart-tv",
40
+ "tizen",
41
+ "webos",
42
+ "samsung",
43
+ "lg",
44
+ "enact"
45
+ ],
46
+ "author": "Your Company",
47
+ "license": "MIT",
48
+ "publishConfig": {
49
+ "access": "public"
50
+ }
51
+ }