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) + '
' + (x.variants.length > 1 ? '
Variant' + esc(st.known ? v.label + (st.byPin ? ' · pinned' : '') : 'Not known: the builds share one package') + '
' : '') + '
' + '
'; - 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; }