diff --git a/src/components/appRouter.js b/src/components/appRouter.js index 8643e3f47f..7b36d01bdd 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -545,13 +545,18 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM page.back(); } + /** + * Pages of "no return" (when "Go back" should behave differently, probably quitting the application). + */ + var startPages = ['home', 'login', 'selectserver']; + function canGoBack() { var curr = current(); if (!curr) { return false; } - if (curr.type === 'home') { + if (!document.querySelector('.dialogContainer') && startPages.indexOf(curr.type) !== -1) { return false; } return page.canGoBack(); diff --git a/src/components/apphost.js b/src/components/apphost.js index c03ae0bce8..0c4d2a6dca 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -299,6 +299,52 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet return features; }(); + /** + * Do exit according to platform + */ + function doExit() { + try { + if (window.NativeShell) { + window.NativeShell.AppHost.exit(); + } else if (browser.tizen) { + tizen.application.getCurrentApplication().exit(); + } else if (browser.web0s) { + webOS.platformBack(); + } else { + window.close(); + } + } catch (err) { + console.log("error closing application: " + err); + } + } + + var exitPromise; + + /** + * Ask user for exit + */ + function askForExit() { + if (!!exitPromise) { + return; + } + + require(["actionsheet"], function (actionsheet) { + exitPromise = actionsheet.show({ + title: Globalize.translate("MessageConfirmAppExit"), + items: [ + {id: "yes", name: Globalize.translate("Yes")}, + {id: "no", name: Globalize.translate("No")} + ] + }).then(function (value) { + if (value === "yes") { + doExit(); + } + }).finally(function () { + exitPromise = null; + }); + }); + } + var deviceId; var deviceName; var appName = "Jellyfin Web"; @@ -314,16 +360,10 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet alert("setWindowState is not supported and should not be called"); }, exit: function () { - if (window.NativeShell) { - window.NativeShell.AppHost.exit(); - } else if (browser.tizen) { - try { - tizen.application.getCurrentApplication().exit(); - } catch (err) { - console.log("error closing application: " + err); - } + if (!!window.appMode && browser.tizen) { + askForExit(); } else { - window.close(); + doExit(); } }, supports: function (command) { diff --git a/src/scripts/inputManager.js b/src/scripts/inputManager.js index 6839b0b6f6..2db8aaa56a 100644 --- a/src/scripts/inputManager.js +++ b/src/scripts/inputManager.js @@ -1,4 +1,4 @@ -define(['playbackManager', 'focusManager', 'appRouter', 'dom'], function (playbackManager, focusManager, appRouter, dom) { +define(['playbackManager', 'focusManager', 'appRouter', 'dom', 'apphost'], function (playbackManager, focusManager, appRouter, dom, appHost) { 'use strict'; var lastInputTime = new Date().getTime(); @@ -96,7 +96,11 @@ define(['playbackManager', 'focusManager', 'appRouter', 'dom'], function (playba appRouter.showSettings(); break; case 'back': - appRouter.back(); + if (appRouter.canGoBack()) { + appRouter.back(); + } else if (appHost.supports('exit')) { + appHost.exit(); + } break; case 'forward': break; diff --git a/src/scripts/routes.js b/src/scripts/routes.js index a3427c6551..b726aaf872 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -226,7 +226,8 @@ define([ autoFocus: false, anonymous: true, startup: true, - controller: "auth/login" + controller: "auth/login", + type: "login" }); defineRoute({ path: "/metadataimages.html", @@ -312,7 +313,8 @@ define([ autoFocus: false, anonymous: true, startup: true, - controller: "auth/selectserver" + controller: "auth/selectserver", + type: "selectserver" }); defineRoute({ path: "/serveractivity.html", diff --git a/src/strings/en-us.json b/src/strings/en-us.json index e587090918..f90e436645 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -946,6 +946,7 @@ "MessageAlreadyInstalled": "This version is already installed.", "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?", + "MessageConfirmAppExit": "Do you want to exit?", "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", diff --git a/src/strings/ru.json b/src/strings/ru.json index 2e01ee9ff9..f8ede4ea8a 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -890,6 +890,7 @@ "MessageAlreadyInstalled": "Данная версия уже установлена.", "MessageAreYouSureDeleteSubtitles": "Вы действительно хотите удалить данный файл субитров?", "MessageAreYouSureYouWishToRemoveMediaFolder": "Вы действительно хотите изъять данную медиапапку?", + "MessageConfirmAppExit": "Вы хотите выйти?", "MessageConfirmDeleteGuideProvider": "Вы действительно хотите удалить данного поставщика телегида?", "MessageConfirmDeleteTunerDevice": "Вы действительно хотите удалить данное устройство?", "MessageConfirmProfileDeletion": "Вы действительно хотите удалить данный профиль?",