diff --git a/README.md b/README.md
index c6b7b2a..1eaa1fc 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ Install the `.wgt` with Apps2Samsung like any package. A `vX.Y.Z` tag (matching
| Install through the TV's own `sdbd` | proven on a retail set |
| Signing on the TV | done, identical output to the Apps2Samsung signer |
| Arming from Apps2Samsung (phone, PC, CLI) | done |
-| The screens above | built (0.3.4); pins, developer search, your own .wgt or .tpk (0.3.10); finds itself under a renamed package id (0.3.11) |
+| The screens above | built (0.3.4); pins, developer search, your own .wgt or .tpk (0.3.10); finds itself under a renamed package id and sends you to Apps2Samsung to update it (0.3.11) |
| First real install from the TV | done, 2019 Tizen 5.0 set (0.3.4) |
| Tizen 3.0 and 4.0 sets (2017, 2018) | untested |
| Tizen 10 sets (2025) | done, retail set (0.3.9) |
diff --git a/tizen-app/js/app.js b/tizen-app/js/app.js
index 8d58f1b..45f9d43 100644
--- a/tizen-app/js/app.js
+++ b/tizen-app/js/app.js
@@ -460,6 +460,11 @@
var me = self(), info = selfInfo();
return !!(me && info && info.packageId && !me.variants.some(function (v) { return v.packageId === info.packageId; }));
}
+ // TV-Store cannot replace itself from here: the installer stops every process of the package
+ // it updates, and that includes the service driving the install, so the install never lands
+ // (#41). A head on a phone or PC is outside the package and updates it fine.
+ function isSelf(x) { return !!x && x === self(); }
+ var SELF_HOW = 'TV-Store cannot replace itself while it runs: the installer stops the service that drives the install. Update it from Apps2Samsung on a phone or PC (On the TV, Update).';
function updates() { return catalogApps.filter(function (x) { return state(x).update; }); }
function onTv() { return catalogApps.filter(function (x) { return state(x).installed; }); }
function byKey(k) { for (var i = 0; i < catalogApps.length; i++) if (catalogApps[i].key === k) return catalogApps[i]; return null; }
@@ -582,11 +587,10 @@
}
// TV-Store is in its own catalog: say so when a newer one is there (like Moonfin's update
- // popup, but from the signed catalog instead of the GitHub API, and installable from here).
+ // popup, but from the signed catalog instead of the GitHub API). Not installable from here
+ // (#41): the installer would stop the service doing it.
var me = self(), ms = me ? state(me) : null;
- if (ms && ms.update) h += '
TV-Store v' + esc(ms.latest)
- + ' is out (this is v' + esc(ms.version) + '). TV-Store closes while it updates itself; open it again after a minute.'
- + '
';
+ if (ms && ms.update) h += '
TV-Store v' + esc(ms.latest) + ' is out (this is v' + esc(ms.version) + '). ' + SELF_HOW + '
';
else if (me && selfRenamed()) {
// Installed under another package id: the platform lists this copy under that id, so
// state() cannot see it. Compare the catalog's version with our own and send the user to
@@ -635,11 +639,12 @@
function renderTv() {
var all = onTv(), ups = all.filter(function (x) { return state(x).update; }), ok = all.filter(function (x) { return !state(x).update; });
+ var doable = ups.filter(function (x) { return !isSelf(x); }); // TV-Store itself updates from a head (#41)
if (!tvSel || all.indexOf(tvSel) < 0) tvSel = ups[0] || ok[0] || null;
var h = '
Your apps
' + (all.length
? all.length + (all.length === 1 ? ' catalog app is' : ' catalog apps are') + ' on this TV. ' + (ups.length ? (ups.length === 1 ? 'One has' : ups.length + ' have') + ' a newer version in the catalog.' : 'All up to date.')
: 'No apps from the catalog on this TV yet.') + '
';
- if (ups.length && armed()) h += '';
+ if (doable.length && armed()) h += '';
h += '
';
if (!all.length) { pageEl.innerHTML = h + '
Install something from the store and it shows up here, with its updates.
'; return; }
h += '
';
@@ -657,11 +662,12 @@
+ '
In the catalogv' + esc(st.latest || v.version) + '
';
- if (st.update && st.known && !v.needsHead && armed()) h += '';
+ if (st.update && st.known && !v.needsHead && !isSelf(x) && armed()) h += '';
else h += '';
if (v.appId) h += '';
h += '
';
- if (st.update && v.needsHead) h += '
' + esc(x.name + ' ' + v.needsHead + ': update it with Apps2Samsung on a phone or PC.') + '
';
+ if (st.update && isSelf(x)) h += '
' + SELF_HOW + '
';
+ else if (st.update && v.needsHead) h += '
' + esc(x.name + ' ' + v.needsHead + ': update it with Apps2Samsung on a phone or PC.') + '
';
else if (!st.known && x.variants.length > 1) h += '
' + esc('TV-Store cannot tell which build of ' + x.name + ' this is: the builds share one package. Open Details, pick your build and pin it; the pinned build is the one that gets updated.') + '
';
return h + '
';
}
@@ -731,11 +737,13 @@
}
var label = st.installed && st.known && st.variant === sheet.v ? (st.update ? 'Update to v' + v.version : 'Reinstall') : (st.installed ? 'Install this variant' : 'Install on this TV');
- if (v.needsHead) h += '
' + esc(x.name + ' ' + v.needsHead + ', which this TV cannot do yet. Install it with Apps2Samsung on a phone or PC.') + '
';
+ var me = isSelf(x);
+ if (me) h += '
' + SELF_HOW + '
';
+ else if (v.needsHead) h += '
' + esc(x.name + ' ' + v.needsHead + ', which this TV cannot do yet. Install it with Apps2Samsung on a phone or PC.') + '
';
else if (!armed()) h += '
Not armed yet. Open this TV’s Toolbox in Apps2Samsung 3.0 or newer on your phone or PC and press Arm TV-Store once; after that every install runs here.
';
- var can = !v.needsHead && armed() && !(job && job.running);
+ var can = !v.needsHead && !me && armed() && !(job && job.running);
h += '
';
+ + esc(me ? (st.update ? 'Update' : 'Reinstall') + ' from a phone or PC' : v.needsHead ? 'Install from a phone or PC' : job && job.running ? 'Another install is running' : label) + '';
if (st.installed && x.variants[st.variant].appId) h += '';
// Pin this build to the top of the store (#29); for a one-build app the button pins the app.
h += '';
@@ -848,7 +856,7 @@
}
function startInstall(x, vIdx) {
- if (job && job.running) return;
+ if ((job && job.running) || isSelf(x)) return;
var v = x.variants[vIdx], st = state(x);
job = { app: x, v: v, vIdx: vIdx, update: st.installed && st.known && st.variant === vIdx, running: true, finished: false, ok: false, step: 0, bytes: 0, line: '', error: null, started: Date.now() };
if (sheet) { sheet = { mode: 'job' }; renderSheet(true); } else openSheet({ mode: 'job' });
@@ -951,10 +959,9 @@
case 'adultno': confirmingAdult = false; renderSheet(); focusKey('opt:showAdult'); return;
case 'tvupd': startInstall(tvSel, state(tvSel).variant); return;
case 'tvsheet': openApp(tvSel); return;
- case 'selfupd': openApp(self()); return;
case 'tvopen': launch(tvSel.variants[state(tvSel).variant].appId); return;
case 'updall':
- queue = updates().filter(function (x) { var st = state(x), v = x.variants[st.variant]; return st.known && !v.needsHead; });
+ queue = updates().filter(function (x) { var st = state(x), v = x.variants[st.variant]; return st.known && !v.needsHead && !isSelf(x); });
if (queue.length) { var first = queue.shift(); startInstall(first, state(first).variant); }
return;
}