tizenbrew-module 1.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.
Files changed (3) hide show
  1. package/index.js +230 -0
  2. package/package.json +20 -0
  3. package/style.css +31 -0
package/index.js ADDED
@@ -0,0 +1,230 @@
1
+ (function() {
2
+ // CRITICAL FIX: Launch the website!
3
+ // If the module is executed while in the TizenBrew menu (not on net22.cc),
4
+ // it needs to redirect the browser to the actual streaming site.
5
+ if (window.location.href.indexOf('net22.cc') === -1) {
6
+ window.location.href = 'https://net22.cc';
7
+ return; // Stop script execution here so we don't break the TizenBrew UI!
8
+ }
9
+
10
+ // Wrapped in an IIFE to prevent variable collisions in TizenBrew's global scope
11
+ var KEY_ENTER = 13;
12
+ var KEY_UP = 38;
13
+ var KEY_DOWN = 40;
14
+ var KEY_LEFT = 37;
15
+ var KEY_RIGHT = 39;
16
+ var KEY_RETURN = 10009;
17
+
18
+ var FOCUSABLE_SELECTORS = 'a, button, input, [tabindex="0"], .movie-poster, .play-btn, .search-bar, .focusable';
19
+
20
+ var focusableElements = [];
21
+ var currentFocusIndex = -1;
22
+
23
+ function updateFocusableElements() {
24
+ try {
25
+ var nodeList = document.querySelectorAll(FOCUSABLE_SELECTORS);
26
+ var allElements = Array.prototype.slice.call(nodeList);
27
+
28
+ focusableElements = allElements.filter(function(el) {
29
+ if (!el || !el.getBoundingClientRect) return false;
30
+ var rect = el.getBoundingClientRect();
31
+
32
+ // Fallback for getting style if window.getComputedStyle throws
33
+ var style;
34
+ try {
35
+ style = window.getComputedStyle(el);
36
+ } catch(e) {
37
+ return false;
38
+ }
39
+
40
+ return (
41
+ rect.width > 0 &&
42
+ rect.height > 0 &&
43
+ style &&
44
+ style.display !== 'none' &&
45
+ style.visibility !== 'hidden' &&
46
+ style.opacity !== '0'
47
+ );
48
+ });
49
+
50
+ for (var i = 0; i < focusableElements.length; i++) {
51
+ var el = focusableElements[i];
52
+ if (el && el.setAttribute && !el.hasAttribute('tabindex')) {
53
+ el.setAttribute('tabindex', '0');
54
+ }
55
+ if (el && el.classList && !el.classList.contains('focusable')) {
56
+ el.classList.add('focusable');
57
+ }
58
+ }
59
+
60
+ if (focusableElements.length > 0 && (!document.activeElement || (document.activeElement.classList && !document.activeElement.classList.contains('focusable')))) {
61
+ if (currentFocusIndex === -1 || currentFocusIndex >= focusableElements.length) {
62
+ focusElement(0);
63
+ }
64
+ }
65
+ } catch(err) {
66
+ console.error("TizenBrew Net22 Module Error in updateFocusableElements:", err);
67
+ }
68
+ }
69
+
70
+ function focusElement(index) {
71
+ try {
72
+ if (index >= 0 && index < focusableElements.length) {
73
+ if (currentFocusIndex !== -1 && focusableElements[currentFocusIndex] && focusableElements[currentFocusIndex].classList) {
74
+ focusableElements[currentFocusIndex].classList.remove('tizen-focus');
75
+ }
76
+
77
+ currentFocusIndex = index;
78
+ var el = focusableElements[currentFocusIndex];
79
+
80
+ if (el && el.focus) {
81
+ el.focus();
82
+ }
83
+ if (el && el.classList) {
84
+ el.classList.add('tizen-focus');
85
+ }
86
+
87
+ if (el && typeof el.scrollIntoView === 'function') {
88
+ try {
89
+ el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
90
+ } catch(e) {
91
+ el.scrollIntoView();
92
+ }
93
+ }
94
+ }
95
+ } catch(err) {
96
+ console.error("TizenBrew Net22 Module Error in focusElement:", err);
97
+ }
98
+ }
99
+
100
+ document.addEventListener('focusout', function(e) {
101
+ try {
102
+ if (e.target && e.target.classList) {
103
+ e.target.classList.remove('tizen-focus');
104
+ }
105
+ } catch(err) {}
106
+ });
107
+
108
+ function navigate(directionKeyCode) {
109
+ try {
110
+ if (focusableElements.length === 0) return;
111
+
112
+ if (currentFocusIndex === -1) {
113
+ focusElement(0);
114
+ return;
115
+ }
116
+
117
+ var currentEl = focusableElements[currentFocusIndex];
118
+ if (!currentEl || !currentEl.getBoundingClientRect) return;
119
+
120
+ var currentRect = currentEl.getBoundingClientRect();
121
+ var currentCenterX = currentRect.left + (currentRect.width / 2);
122
+ var currentCenterY = currentRect.top + (currentRect.height / 2);
123
+
124
+ var bestMatchIndex = -1;
125
+ var minDistance = Infinity;
126
+
127
+ for (var i = 0; i < focusableElements.length; i++) {
128
+ if (i === currentFocusIndex) continue;
129
+
130
+ var targetEl = focusableElements[i];
131
+ if (!targetEl || !targetEl.getBoundingClientRect) continue;
132
+
133
+ var targetRect = targetEl.getBoundingClientRect();
134
+ var targetCenterX = targetRect.left + (targetRect.width / 2);
135
+ var targetCenterY = targetRect.top + (targetRect.height / 2);
136
+
137
+ var dx = targetCenterX - currentCenterX;
138
+ var dy = targetCenterY - currentCenterY;
139
+
140
+ var absDx = Math.abs(dx);
141
+ var absDy = Math.abs(dy);
142
+
143
+ var isValidDirection = false;
144
+
145
+ if (directionKeyCode === KEY_UP && dy < 0 && absDy > absDx) {
146
+ isValidDirection = true;
147
+ } else if (directionKeyCode === KEY_DOWN && dy > 0 && absDy > absDx) {
148
+ isValidDirection = true;
149
+ } else if (directionKeyCode === KEY_LEFT && dx < 0 && absDx > absDy) {
150
+ isValidDirection = true;
151
+ } else if (directionKeyCode === KEY_RIGHT && dx > 0 && absDx > absDy) {
152
+ isValidDirection = true;
153
+ }
154
+
155
+ if (isValidDirection) {
156
+ var distance = Math.sqrt(dx * dx + dy * dy);
157
+
158
+ if (distance < minDistance) {
159
+ minDistance = distance;
160
+ bestMatchIndex = i;
161
+ }
162
+ }
163
+ }
164
+
165
+ if (bestMatchIndex !== -1) {
166
+ focusElement(bestMatchIndex);
167
+ }
168
+ } catch(err) {
169
+ console.error("TizenBrew Net22 Module Error in navigate:", err);
170
+ }
171
+ }
172
+
173
+ window.addEventListener('keydown', function(e) {
174
+ try {
175
+ var keyCode = e.keyCode || e.which;
176
+ switch (keyCode) {
177
+ case KEY_UP:
178
+ case KEY_DOWN:
179
+ case KEY_LEFT:
180
+ case KEY_RIGHT:
181
+ e.preventDefault();
182
+ navigate(keyCode);
183
+ break;
184
+
185
+ case KEY_ENTER:
186
+ e.preventDefault();
187
+ if (currentFocusIndex !== -1 && focusableElements[currentFocusIndex]) {
188
+ // Try clicking the element natively
189
+ if (typeof focusableElements[currentFocusIndex].click === 'function') {
190
+ focusableElements[currentFocusIndex].click();
191
+ } else {
192
+ // Fallback for some links
193
+ var event = document.createEvent('MouseEvents');
194
+ event.initEvent('click', true, true);
195
+ focusableElements[currentFocusIndex].dispatchEvent(event);
196
+ }
197
+ }
198
+ break;
199
+
200
+ case KEY_RETURN:
201
+ e.preventDefault();
202
+ var closeButton = document.querySelector('.modal-close, .close-btn, .video-close');
203
+ if (closeButton && window.getComputedStyle(closeButton).display !== 'none') {
204
+ closeButton.click();
205
+ } else {
206
+ window.history.back();
207
+ }
208
+ break;
209
+ }
210
+ } catch(err) {
211
+ console.error("TizenBrew Net22 Module Error in keydown handler:", err);
212
+ }
213
+ });
214
+
215
+ // Replace MutationObserver completely with a safe setInterval
216
+ // This is incredibly robust for older TVs, prevents any infinite DOM loops,
217
+ // and doesn't rely on the MutationObserver API existing.
218
+ setInterval(function() {
219
+ updateFocusableElements();
220
+ }, 1500);
221
+
222
+ // Initial check
223
+ window.addEventListener('load', function() {
224
+ updateFocusableElements();
225
+ });
226
+
227
+ // Failsafe execution
228
+ updateFocusableElements();
229
+
230
+ })();
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "tizenbrew-module",
3
+ "version": "1.0.1",
4
+ "description": "Custom TV remote mapping for net22.cc",
5
+ "main": "index.js",
6
+ "style": "style.css",
7
+ "author": "Netmirror",
8
+ "packageType": "mods",
9
+ "appName": "Net22 Player",
10
+ "title": "Net22 Player",
11
+ "websiteURL": "*://*.net22.cc/*",
12
+ "keys": [
13
+ "ArrowUp",
14
+ "ArrowDown",
15
+ "ArrowLeft",
16
+ "ArrowRight",
17
+ "Enter",
18
+ "Return"
19
+ ]
20
+ }
package/style.css ADDED
@@ -0,0 +1,31 @@
1
+ /* Hide mouse cursor completely */
2
+ * {
3
+ cursor: none !important;
4
+ }
5
+
6
+ /* Hide all web scrollbars */
7
+ ::-webkit-scrollbar {
8
+ display: none !important;
9
+ }
10
+
11
+ html, body {
12
+ -ms-overflow-style: none !important; /* IE and Edge */
13
+ scrollbar-width: none !important; /* Firefox */
14
+ }
15
+
16
+ /* Very obvious, high-contrast focus state */
17
+ :focus, .tizen-focus {
18
+ outline: none !important;
19
+ border: 5px solid #00ffcc !important;
20
+ transform: scale(1.1) !important;
21
+ box-shadow: 0 0 20px 5px rgba(0, 255, 204, 0.8) !important;
22
+ transition: transform 0.2s ease, box-shadow 0.2s ease, border 0.2s ease !important;
23
+ z-index: 9999 !important;
24
+ border-radius: 8px; /* Smooth corners */
25
+ background-color: rgba(0, 255, 204, 0.1) !important;
26
+ }
27
+
28
+ /* Base style for elements that will be scaled to ensure smooth transition */
29
+ .focusable {
30
+ transition: transform 0.2s ease, box-shadow 0.2s ease, border 0.2s ease;
31
+ }