nuvio-tizen 1.8.9 → 1.8.12
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/config.xml +1 -1
- package/css/style.css +8 -0
- package/index.html +9 -9
- package/js/focus.js +31 -12
- package/js/views.js +51 -3
- package/package.json +1 -1
package/config.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets"
|
|
3
|
-
id="http://nuvio.tizen/NuvioTizen" version="1.
|
|
3
|
+
id="http://nuvio.tizen/NuvioTizen" version="1.8.12" viewmodes="maximized">
|
|
4
4
|
<tizen:application id="Nuvio00001.Nuvio" package="Nuvio00001" required_version="2.4"/>
|
|
5
5
|
<content src="index.html"/>
|
|
6
6
|
<feature name="http://tizen.org/feature/screen.size.all"/>
|
package/css/style.css
CHANGED
|
@@ -191,6 +191,14 @@ html, body {
|
|
|
191
191
|
.modal-msg { font-size: 30px; line-height: 1.4; color: #e6e9ef; margin-bottom: 36px; }
|
|
192
192
|
.modal-row { display: flex; justify-content: center; }
|
|
193
193
|
.modal-btn { min-width: 200px; text-align: center; }
|
|
194
|
+
/* list picker (single choice) */
|
|
195
|
+
.pick-box { width: 720px; text-align: left; }
|
|
196
|
+
.pick-box .modal-msg { text-align: left; margin-bottom: 20px; }
|
|
197
|
+
.pick-list { max-height: 620px; overflow: hidden; }
|
|
198
|
+
.pick-item { padding: 14px 20px; margin-bottom: 8px; border-radius: 8px; background: #0e1117; border: 4px solid transparent; font-size: 24px; }
|
|
199
|
+
.pick-item.sel { background: #2a3346; }
|
|
200
|
+
.pick-item.focusable.focused { background: #818cf8; color: #0e1117; border-color: #fff; }
|
|
201
|
+
|
|
194
202
|
.pill.danger { background: #3a2130; }
|
|
195
203
|
.pill.danger.focusable.focused { background: #ef4444; color: #fff; }
|
|
196
204
|
.reset-item .a-name { color: #f0a5a5; }
|
package/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=1920, height=1080, user-scalable=no">
|
|
6
6
|
<title>Nuvio</title>
|
|
7
|
-
<link rel="stylesheet" href="css/style.css?v=1.8.
|
|
7
|
+
<link rel="stylesheet" href="css/style.css?v=1.8.12">
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<!-- CSS-applied sentinel (kept off-screen); app.js waits for its width before rendering -->
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
|
|
48
48
|
<!-- Load order matters: polyfills -> util -> data -> input -> player -> views -> app -->
|
|
49
49
|
<!-- ?v= busts the TV webview cache on every release (keep in sync with package.json) -->
|
|
50
|
-
<script src="js/polyfills.js?v=1.8.
|
|
51
|
-
<script src="js/util.js?v=1.8.
|
|
52
|
-
<script src="js/stremio.js?v=1.8.
|
|
53
|
-
<script src="js/keys.js?v=1.8.
|
|
54
|
-
<script src="js/focus.js?v=1.8.
|
|
55
|
-
<script src="js/player.js?v=1.8.
|
|
56
|
-
<script src="js/views.js?v=1.8.
|
|
57
|
-
<script src="js/app.js?v=1.8.
|
|
50
|
+
<script src="js/polyfills.js?v=1.8.12"></script>
|
|
51
|
+
<script src="js/util.js?v=1.8.12"></script>
|
|
52
|
+
<script src="js/stremio.js?v=1.8.12"></script>
|
|
53
|
+
<script src="js/keys.js?v=1.8.12"></script>
|
|
54
|
+
<script src="js/focus.js?v=1.8.12"></script>
|
|
55
|
+
<script src="js/player.js?v=1.8.12"></script>
|
|
56
|
+
<script src="js/views.js?v=1.8.12"></script>
|
|
57
|
+
<script src="js/app.js?v=1.8.12"></script>
|
|
58
58
|
</body>
|
|
59
59
|
</html>
|
package/js/focus.js
CHANGED
|
@@ -85,18 +85,37 @@ var Focus = (function () {
|
|
|
85
85
|
}
|
|
86
86
|
if (!cands.length) { return; }
|
|
87
87
|
|
|
88
|
-
// Two-phase:
|
|
89
|
-
//
|
|
90
|
-
// then pick the closest
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
// Two-phase, direction-aware:
|
|
89
|
+
// - Vertical (UP/DOWN): first restrict to the NEAREST row (min primary =
|
|
90
|
+
// vertical distance), then pick the horizontally closest (min cross).
|
|
91
|
+
// - Horizontal (LEFT/RIGHT): first restrict to the SAME row (min cross =
|
|
92
|
+
// vertical offset), then pick the horizontally closest (min primary).
|
|
93
|
+
// This stops vertical moves skipping a short row, and stops horizontal moves
|
|
94
|
+
// jumping into another row (e.g. Settings -> LEFT should land on Search).
|
|
95
|
+
var vertical = (dir === 'UP' || dir === 'DOWN');
|
|
96
|
+
var best = null, bestSel = Infinity, bestTie = Infinity;
|
|
97
|
+
|
|
98
|
+
if (vertical) {
|
|
99
|
+
// nearest row first (min primary band), then closest horizontally
|
|
100
|
+
var BAND = 120, minP = Infinity;
|
|
101
|
+
for (var j = 0; j < cands.length; j++) { if (cands[j].primary < minP) { minP = cands[j].primary; } }
|
|
102
|
+
for (var k = 0; k < cands.length; k++) {
|
|
103
|
+
var c = cands[k];
|
|
104
|
+
if (c.primary > minP + BAND) { continue; }
|
|
105
|
+
if (c.cross < bestSel || (c.cross === bestSel && c.primary < bestTie)) {
|
|
106
|
+
best = c.node; bestSel = c.cross; bestTie = c.primary;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
// same row only (absolute vertical tolerance), then nearest horizontally.
|
|
111
|
+
// No jump to another row/header at a row end — just don't move.
|
|
112
|
+
var ROW_TOL = 140;
|
|
113
|
+
for (var m = 0; m < cands.length; m++) {
|
|
114
|
+
var d = cands[m];
|
|
115
|
+
if (d.cross > ROW_TOL) { continue; }
|
|
116
|
+
if (d.primary < bestSel || (d.primary === bestSel && d.cross < bestTie)) {
|
|
117
|
+
best = d.node; bestSel = d.primary; bestTie = d.cross;
|
|
118
|
+
}
|
|
100
119
|
}
|
|
101
120
|
}
|
|
102
121
|
if (best) { setFocus(best); }
|
package/js/views.js
CHANGED
|
@@ -42,6 +42,31 @@ var Views = (function () {
|
|
|
42
42
|
_modalScope = null; _modalPrevFocus = null;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
// A scrollable single-choice list overlay (D-pad). options = [[value,label],...]
|
|
46
|
+
function pickList(title, options, current, onPick) {
|
|
47
|
+
var existing = document.querySelector('.modal-overlay');
|
|
48
|
+
if (existing) { existing.parentNode.removeChild(existing); }
|
|
49
|
+
var overlay = U.el('div', 'modal-overlay');
|
|
50
|
+
var box = U.el('div', 'modal-box pick-box');
|
|
51
|
+
box.appendChild(U.el('div', 'modal-msg', title));
|
|
52
|
+
var listEl = U.el('div', 'pick-list');
|
|
53
|
+
var pref = null;
|
|
54
|
+
options.forEach(function (opt) {
|
|
55
|
+
var it = U.el('div', 'pick-item focusable' + (opt[0] === current ? ' sel' : ''), opt[1]);
|
|
56
|
+
it.__onselect = function () { closeModal(); onPick(opt[0]); };
|
|
57
|
+
if (opt[0] === current) { pref = it; }
|
|
58
|
+
listEl.appendChild(it);
|
|
59
|
+
});
|
|
60
|
+
box.appendChild(listEl);
|
|
61
|
+
overlay.appendChild(box);
|
|
62
|
+
document.body.appendChild(overlay);
|
|
63
|
+
|
|
64
|
+
_modalPrevFocus = Focus.current();
|
|
65
|
+
_modalScope = _current();
|
|
66
|
+
_modalOpen = true;
|
|
67
|
+
Focus.setScope(overlay, pref);
|
|
68
|
+
}
|
|
69
|
+
|
|
45
70
|
function _current() {
|
|
46
71
|
var names = ['home', 'detail', 'search', 'settings', 'addaddon'];
|
|
47
72
|
for (var i = 0; i < names.length; i++) {
|
|
@@ -630,9 +655,11 @@ var Views = (function () {
|
|
|
630
655
|
var cancelBtn = U.el('div', 'pill focusable', 'Cancel');
|
|
631
656
|
confirmBtn.__onselect = doConfirm;
|
|
632
657
|
cancelBtn.__onselect = function () { App.back(); };
|
|
633
|
-
|
|
658
|
+
|
|
659
|
+
// Order: Validate · Confirm · Cancel
|
|
660
|
+
var valBtn = null;
|
|
634
661
|
if (cfg.validator) {
|
|
635
|
-
|
|
662
|
+
valBtn = U.el('div', 'pill focusable', 'Validate');
|
|
636
663
|
valBtn.__onselect = function () {
|
|
637
664
|
var v = ('' + input.value).trim();
|
|
638
665
|
if (!v) { U.toast('Enter a key first'); return; }
|
|
@@ -643,9 +670,13 @@ var Views = (function () {
|
|
|
643
670
|
};
|
|
644
671
|
row.appendChild(valBtn);
|
|
645
672
|
}
|
|
673
|
+
row.appendChild(confirmBtn);
|
|
646
674
|
row.appendChild(cancelBtn);
|
|
647
675
|
wrap.appendChild(row);
|
|
648
676
|
|
|
677
|
+
// DOWN from the field lands on Validate (or Confirm when there's no validator)
|
|
678
|
+
input.__navDOWN = function () { Focus.setFocus(valBtn || confirmBtn); return true; };
|
|
679
|
+
|
|
649
680
|
s.appendChild(wrap);
|
|
650
681
|
Focus.setScope(s, input);
|
|
651
682
|
|
|
@@ -690,6 +721,23 @@ var Views = (function () {
|
|
|
690
721
|
return row;
|
|
691
722
|
}
|
|
692
723
|
|
|
724
|
+
// Like subCycleRow but OK opens a scrollable list picker.
|
|
725
|
+
function subPickRow(caption, list, key) {
|
|
726
|
+
var row = U.el('div', 'addon-item focusable cfg-row');
|
|
727
|
+
var name = U.el('div', 'a-name');
|
|
728
|
+
function render() { name.textContent = caption + ': ' + labelFor(list, Player.getSubCfg()[key]); }
|
|
729
|
+
render();
|
|
730
|
+
row.appendChild(name);
|
|
731
|
+
row.appendChild(U.el('div', 'a-url', 'Press OK to choose'));
|
|
732
|
+
row.__onselect = function () {
|
|
733
|
+
pickList(caption, list, Player.getSubCfg()[key], function (v) {
|
|
734
|
+
var cfg = Player.getSubCfg(); cfg[key] = v; Player.setSubCfg(cfg);
|
|
735
|
+
render();
|
|
736
|
+
});
|
|
737
|
+
};
|
|
738
|
+
return row;
|
|
739
|
+
}
|
|
740
|
+
|
|
693
741
|
// ================= SETTINGS (sectioned) =================
|
|
694
742
|
var _settingsSection = 'menu';
|
|
695
743
|
|
|
@@ -825,7 +873,7 @@ var Views = (function () {
|
|
|
825
873
|
|
|
826
874
|
function settingsSubtitles(wrap) {
|
|
827
875
|
wrap.appendChild(U.el('h2', null, 'Subtitle Options'));
|
|
828
|
-
wrap.appendChild(
|
|
876
|
+
wrap.appendChild(subPickRow('Default language', SUB_LANGS, 'lang'));
|
|
829
877
|
wrap.appendChild(subCycleRow('Size', SUB_SIZES, 'size'));
|
|
830
878
|
wrap.appendChild(subCycleRow('Style', SUB_STYLES, 'style'));
|
|
831
879
|
wrap.appendChild(backRow());
|