diff options
author | Egor Nemtsev <enemtsev@luxoft.com> | 2020-02-21 19:21:45 +0300 |
---|---|---|
committer | Egor Nemtsev <enemtsev@luxoft.com> | 2020-04-06 13:11:34 +0000 |
commit | ec183828f827220527266cf64d2d73b46cdb4d24 (patch) | |
tree | da781a393262163116720180c6eb4b35ed2defa0 | |
parent | 35f65a9ff013d51f057f458ceb5467ca5dafdd4b (diff) |
[downloads] move to state observer/controller
Task-number: AUTOSUITE-1486
Change-Id: I9ac110f93691e9345f31ac791f21581293169e8b
Reviewed-by: Grigorii Zimin <gzimin@luxoft.com>
-rw-r--r-- | apps/com.pelagicore.downloads/controls/DownloadAppList.qml | 58 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/controls/DownloadsToolsColumn.qml | 9 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/stores/DownloadsStates.qml | 311 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/stores/DownloadsStore.qml | 82 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/stores/JSONBackend.js | 29 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/stores/JSONModel.qml | 6 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/stores/ServerConfig.qml | 70 | ||||
-rw-r--r-- | apps/com.pelagicore.downloads/views/DownloadsView.qml | 331 | ||||
-rw-r--r-- | imports_shared/assets/translations/ar_MA.ts | 33 | ||||
-rw-r--r-- | imports_shared/assets/translations/cs_CZ.ts | 33 | ||||
-rw-r--r-- | imports_shared/assets/translations/de_DE.ts | 33 | ||||
-rw-r--r-- | imports_shared/assets/translations/en_GB.ts | 35 | ||||
-rw-r--r-- | imports_shared/assets/translations/en_US.ts | 35 | ||||
-rw-r--r-- | imports_shared/assets/translations/ja_JP.ts | 33 | ||||
-rw-r--r-- | imports_shared/assets/translations/ko_KR.ts | 33 | ||||
-rw-r--r-- | imports_shared/assets/translations/zh_CN.ts | 33 |
16 files changed, 960 insertions, 204 deletions
diff --git a/apps/com.pelagicore.downloads/controls/DownloadAppList.qml b/apps/com.pelagicore.downloads/controls/DownloadAppList.qml index 59ea9742..f082f3e5 100644 --- a/apps/com.pelagicore.downloads/controls/DownloadAppList.qml +++ b/apps/com.pelagicore.downloads/controls/DownloadAppList.qml @@ -41,49 +41,75 @@ import shared.Sizes 1.0 ListView { id: root - property var store + property string appServerUrl + property string cpuArch + property var applicationModel + property real currentInstallationProgress signal toolClicked(string appId, string appName) + signal appClicked(string appId) - model: root.store.applicationModel + function refreshAppsInfo(isPackageInstalledByPackageControllerFunc, + isPackageBuiltInFunc, getInstalledPackageSizeTextFunc) { + d.installedPackagesChanged(isPackageInstalledByPackageControllerFunc, + isPackageBuiltInFunc, getInstalledPackageSizeTextFunc); + } + + QtObject { + id: d + + signal installedPackagesChanged(var isPackageInstalledByPackageControllerFunc, + var isPackageBuiltInFunc, + var getInstalledPackageSizeTextFunc) + } + + model: root.applicationModel currentIndex: -1 delegate: ListItemProgress { id: delegatedItem objectName: "itemDownloadApp_" + model.id - property bool isInstalled: root.store.isPackageInstalledByPackageController(model.id) - width: Sizes.dp(720) - height: Sizes.dp(100) - icon.source: root.store.appServerUrl - + "/app/icon?id=" + model.id - + "&architecture=" + store.cpuArch + property bool isInstalled: model.isInstalled + property string packageSizeText: model.packageSizeText + property bool packageBuiltIn: model.packageBuiltIn + + width: Sizes.dp(720); height: Sizes.dp(100) + icon.source: root.appServerUrl + "/app/icon?id=" + model.id + + "&architecture=" + root.cpuArch text: model.name subText: model.id - secondaryText: delegatedItem.isInstalled ? root.store.getInstalledPackageSizeText(model.id) - : ( root.store.isPackageBuiltIn(model.id) ? + secondaryText: delegatedItem.isInstalled ? delegatedItem.packageSizeText + : ( delegatedItem.packageBuiltIn ? qsTr("update") : "" ) cancelSymbol: delegatedItem.isInstalled ? "ic-close" : "ic-download_OFF" - value: root.store.currentInstallationProgress + value: root.currentInstallationProgress onValueChanged: { if (value === 1.0) { root.currentIndex = -1; } } - progressVisible: root.currentIndex === index && root.store.currentInstallationProgress < 1.0 + progressVisible: root.currentIndex === index && root.currentInstallationProgress < 1.0 onProgressCanceled: { if (!delegatedItem.isInstalled) { root.currentIndex = index; } root.toolClicked(model.id, model.name); } - onClicked: root.store.tryStartApp(model.id) + onClicked: root.appClicked(model.id) Connections { - target: root.store + target: d onInstalledPackagesChanged: { - isInstalled = root.store.isPackageInstalledByPackageController(model.id) + // functions are passed as parameters to signal + model.isInstalled = isPackageInstalledByPackageControllerFunc(model.id); + if (isInstalled) { + model.packageBuiltIn = isPackageBuiltInFunc(model.id); + model.packageSizeText = getInstalledPackageSizeTextFunc(model.id); + } else { + model.packageBuiltIn = false; + model.packageSizeText = ""; + } } } - } } diff --git a/apps/com.pelagicore.downloads/controls/DownloadsToolsColumn.qml b/apps/com.pelagicore.downloads/controls/DownloadsToolsColumn.qml index 6795797b..95dea832 100644 --- a/apps/com.pelagicore.downloads/controls/DownloadsToolsColumn.qml +++ b/apps/com.pelagicore.downloads/controls/DownloadsToolsColumn.qml @@ -34,9 +34,6 @@ import QtQuick 2.10 import QtQuick.Controls 2.3 import shared.utils 1.0 import shared.Sizes 1.0 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.2 -import QtQml.Models 2.2 import shared.controls 1.0 @@ -44,8 +41,8 @@ Item { id: root property alias model: toolsColumn.model - property int currentIndex: 0 property string serverUrl + signal toolClicked(int index) ToolsColumn { @@ -55,8 +52,6 @@ Item { anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top anchors.topMargin: Sizes.dp(53) - onCurrentIndexChanged: { - root.toolClicked(currentIndex) - } + onClicked: root.toolClicked(currentIndex) } } diff --git a/apps/com.pelagicore.downloads/stores/DownloadsStates.qml b/apps/com.pelagicore.downloads/stores/DownloadsStates.qml new file mode 100644 index 00000000..69db4c7c --- /dev/null +++ b/apps/com.pelagicore.downloads/stores/DownloadsStates.qml @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Luxoft Sweden AB +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Neptune 3 UI. +** +** $QT_BEGIN_LICENSE:GPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: GPL-3.0 +** +****************************************************************************/ + +import QtQuick 2.8 +import QtQml.StateMachine 1.0 as DSM + +import "JSONBackend.js" as JSONBackend +import shared.com.pelagicore.systeminfo 1.0 +import shared.utils 1.0 + +DSM.StateMachine { + running: true + initialState: networkConnectedState + + property alias noNetwork: noNetworkState + property alias networkConnected: networkConnectedState + property alias connectingToServer: connectingToServerState + property alias connectedError: connectedErrorState + property alias connectedToServer: connectedToServerState + property alias fetchingApps: fetchingAppsState + property alias fetchingCategories: fetchingCategoriesState + property alias appsLoaded: appsLoadedState + property alias serverOnMaintance: serverOnMaintanceState + property alias serverNA: serverNAState + property alias loggingIn: loggingInState + property alias categoriesLoaded: categoriesLoadedState + property alias checkServerError: checkServerErrorState + + property SystemInfo sysinfo + property ServerConfig appStoreConfig + property JSONModel jsonCategoryModel + property JSONModel jsonAppModel + + DSM.State { + id: noNetworkState + + DSM.SignalTransition { + targetState: networkConnectedState + signal: sysinfo.onInternetAccessChanged + guard: sysinfo.internetAccess + } + + DSM.SignalTransition { + targetState: networkConnectedState + signal: sysinfo.onConnectedChanged + guard: sysinfo.connected + } + } + + DSM.State { + id: networkConnectedState + + initialState: connectingToServerState + onEntered: { appStoreConfig.reconnectionAttempt = 0; } + + DSM.SignalTransition { + targetState: noNetworkState + signal: sysinfo.onConnectedChanged + guard: !sysinfo.connected + } + + DSM.SignalTransition { + targetState: noNetworkState + signal: sysinfo.onInternetAccessChanged + guard: !sysinfo.internetAccess + } + + DSM.State { + id: connectingToServerState + + DSM.SignalTransition { + targetState: connectedToServerState + signal: appStoreConfig.connectionSuccessful + } + DSM.SignalTransition { + targetState: checkServerErrorState + signal: appStoreConfig.connectionFailed + } + DSM.SignalTransition { + targetState: serverOnMaintanceState + signal: appStoreConfig.serverOnMaintanceState + } + } + + DSM.State { + id: serverOnMaintanceState + + DSM.SignalTransition { + targetState: connectingToServerState + signal: appStoreConfig.tryConnectToServer + } + } + + DSM.State { + id: checkServerErrorState + + signal noMoreAttempts() + + onEntered: { + if (appStoreConfig.reconnectionAttempt < appStoreConfig.maxReconnectCount) { + appStoreConfig.reconnectionAttempt += 1; + retryTimer.start(); + } else { + noMoreAttempts(); + } + } + + Timer { + id: retryTimer + interval: 2000 + onTriggered: { + console.warn(Logging.apps, "Neptune 3 UI::DownloadsStates - Retry Connection", + appStoreConfig.reconnectionAttempt, "of", + appStoreConfig.maxReconnectCount); + appStoreConfig.checkServer(); + } + } + + DSM.SignalTransition { + targetState: connectingToServerState + signal: appStoreConfig.tryConnectToServer + } + + DSM.SignalTransition { + targetState: serverNAState + signal: checkServerErrorState.noMoreAttempts + } + } + + DSM.State { + id: serverNAState + + onEntered: { appStoreConfig.reconnectionAttempt = 0; } + + DSM.SignalTransition { + targetState: connectingToServerState + signal: appStoreConfig.tryConnectToServer + } + } + + DSM.State { + id: connectedToServerState + + initialState: loggingInState + onEntered: { appStoreConfig.reconnectionAttempt = 0; } + + DSM.SignalTransition { + targetState: checkServerErrorState + signal: appStoreConfig.connectionFailed + } + + DSM.State { + id: loggingInState + + onEntered: { appStoreConfig.login(); } + + Connections { + target: appStoreConfig + onLoginFailed: { + connectedErrorState.errorText = qsTr("Login Failed"); + } + } + + DSM.SignalTransition { + targetState: connectedErrorState + signal: appStoreConfig.loginFailed + } + + DSM.SignalTransition { + targetState: loggedInState + signal: appStoreConfig.loginSuccessful + } + } + + DSM.State { + id: connectedErrorState + + property string errorText: "" + + DSM.SignalTransition { + targetState: connectingToServerState + signal: appStoreConfig.tryConnectToServer + } + } + + DSM.State { + id: loggedInState + + initialState: fetchingCategoriesState + + DSM.State { + id: fetchingCategoriesState + + onEntered: { jsonCategoryModel.refresh(); } + + Connections { + target: jsonCategoryModel + onStatusChanged: { + if (jsonCategoryModel.status === "error") + connectedErrorState.errorText = qsTr("Fetching categories error"); + } + } + + DSM.SignalTransition { + targetState: categoriesLoadedState + signal: jsonCategoryModel.onStatusChanged + guard: jsonCategoryModel.status === "ready" + } + + DSM.SignalTransition { + targetState: connectedErrorState + signal: jsonCategoryModel.onStatusChanged + guard: jsonCategoryModel.status === "error" + } + } + + DSM.State { + id: categoriesLoadedState + + onEntered: { + if (jsonCategoryModel.count > 0) { + jsonAppModel.categoryId = jsonCategoryModel.get(0).id; + jsonAppModel.refresh() + } else { + jsonCategoryModel.emptyCategoriesList() + } + } + + DSM.SignalTransition { + targetState: fetchingAppsState + signal: jsonAppModel.onStatusChanged + guard: jsonAppModel.status === "loading" + } + + DSM.SignalTransition { + targetState: appsLoadedState + signal: jsonAppModel.onStatusChanged + guard: jsonAppModel.status === "ready" + } + + DSM.SignalTransition { + targetState: appsLoadedState + signal: jsonCategoryModel.onEmptyCategoriesList + } + } + + DSM.State { + id: fetchingAppsState + + Connections { + target: jsonAppModel + onStatusChanged: { + if (jsonAppModel.status === "error") + connectedErrorState.errorText = qsTr("Fetching apps error"); + } + } + + DSM.SignalTransition { + targetState: appsLoadedState + signal: jsonAppModel.onStatusChanged + guard: jsonAppModel.status === "ready" + } + + DSM.SignalTransition { + targetState: connectedErrorState + signal: jsonAppModel.onStatusChanged + guard: jsonAppModel.status === "error" + } + } + + DSM.State { + id: appsLoadedState + + DSM.SignalTransition { + targetState: fetchingAppsState + signal: jsonAppModel.onStatusChanged + guard: jsonAppModel.status === "loading" + } + } + } + } + } +} diff --git a/apps/com.pelagicore.downloads/stores/DownloadsStore.qml b/apps/com.pelagicore.downloads/stores/DownloadsStore.qml index af76482b..98728495 100644 --- a/apps/com.pelagicore.downloads/stores/DownloadsStore.qml +++ b/apps/com.pelagicore.downloads/stores/DownloadsStore.qml @@ -46,13 +46,9 @@ Item { property alias appStoreConfig: appStoreConfig property string appServerUrl: appStoreConfig.serverUrl property alias cpuArch: appStoreConfig.cpuArch - property int categoryid: 0 property string filter: "" property real currentInstallationProgress: 0.0 readonly property var installedPackages: PackageManager.packageIds() - readonly property bool isOnline: appStoreConfig.serverOnline - readonly property bool isReconnecting: appStoreConfig.isReconnecting - property bool isBusy: false// appModel.count == 0 && isOnline readonly property IntentHandler intentHandler: IntentHandler { intentIds: "activate-app" onRequestReceived: { @@ -60,9 +56,14 @@ Item { request.sendReply({ "done": true }) } } + property DownloadsStates downloadsStates: DownloadsStates { + sysinfo: sysinfo + appStoreConfig: appStoreConfig + jsonCategoryModel: jsonCategoryModel + jsonAppModel: jsonAppModel + } signal requestRaiseAppReceived() - signal categoryListReady() function formatBytes(bytes) { if (bytes < 1024) return qsTr("%1 Bytes").arg(bytes); @@ -78,23 +79,26 @@ Item { var url = appStoreConfig.serverUrl + "/app/purchase"; var data = {"id": packageId, "device_id" : "00-11-22-33-44-55" }; + var icon = root.appServerUrl + + "/app/icon?id=" + packageId + + "&architecture=" + root.cpuArch; JSONBackend.serverCall(url, data, function(data) { if (data !== 0) { if (data.status === "ok") { console.log(Logging.apps, "start downloading"); - var icon = root.appServerUrl - + "/app/icon?id=" + packageId - + "&architecture=" + root.cpuArch; var installID = PackageManager.startPackageInstallation(data.url); PackageManager.acknowledgePackageInstallation(installID); } else if (data.status === "fail" && data.error === "not-logged-in"){ - console.log(Logging.apps, ":::AppStoreServer::: not logged in"); + console.warn(Logging.apps, ":::AppStoreServer::: not logged in"); showNotification(qsTr("System is not logged in"), qsTr("System is not logged in"), icon); } else { - console.log(Logging.apps, ":::AppStoreServer::: download failed: " + data.error); + console.warn(Logging.apps, ":::AppStoreServer::: download failed: " + data.error); showNotification(qsTr("%1 Download Failed").arg(name), qsTr("%1 download failed").arg(name), icon); } + } else { + console.warn(Logging.apps, ":::AppStoreServer::: download failed"); + showNotification(qsTr("%1 Download Failed").arg(name), qsTr("%1 download failed").arg(name), icon); } }) } @@ -106,7 +110,7 @@ Item { function isPackageBuiltIn(packageId) { var pkg = PackageManager.package(packageId); - return pkg && pkg.builtIn; + return !!pkg && pkg.builtIn; } function isPackageBusy(packageId) { @@ -140,12 +144,12 @@ Item { function selectCategory(index) { var category = categoryListModel.get(index); if (category) { - root.categoryid = category.id; + jsonAppModel.categoryId = category.id; } else { - root.categoryid = 1; + jsonAppModel.categoryId = 1; } - appModel.refresh(); + jsonAppModel.refresh(); } function showNotification(summary, body, icon) { @@ -162,7 +166,7 @@ Item { if (isPackageBuiltIn(packageId)) { return qsTr("built-in"); } else { - console.warn("Uknown app package size: -1", id); + console.warn("Uknown app package size: -1", packageId); return qsTr("Unknown size"); } } @@ -290,21 +294,10 @@ Item { ServerConfig { id: appStoreConfig cpuArch: sysinfo.cpu + "-" + sysinfo.kernel - property bool initialized: false - onLoginSuccessful: { - if (!initialized) { - categoryListModel.refresh(); - initialized = true; - } - } } ListModel { id: categoryListModel - - function refresh() { - jsonCategoryModel.refresh(); - } } JSONModel { @@ -312,6 +305,11 @@ Item { url: appStoreConfig.serverUrl + "/category/list" onStatusChanged: { + if (status === "loading" && categoryListModel.count > 0) { + categoryListModel.clear(); + jsonAppModel.categoryId = 0; + } + if (status === "ready") { categoryListModel.clear(); for (let i = 0; i < jsonCategoryModel.count; ++i) { @@ -322,14 +320,40 @@ Item { "sourceOff": root.appServerUrl + "/category/icon?id=" + cat.id, }); } - root.categoryListReady(); } } } - JSONModel { + ListModel { id: appModel + } + + JSONModel { + id: jsonAppModel + + property int categoryId: 0 url: appStoreConfig.serverUrl + "/app/list" - data: root.categoryid >= 0 ? ({ "filter" : root.filter , "category_id" : root.categoryid}) : ({ "filter" : root.filter}) + data: jsonAppModel.categoryId >= 0 ? ({ "filter" : root.filter , + "category_id" : jsonAppModel.categoryId}) + : ({ "filter" : root.filter}) + onStatusChanged: { + appModel.clear(); + + if (status === "ready") { + let appList = []; + for (let i = 0; i < jsonAppModel.count; ++i) { + let app = jsonAppModel.get(i); + let isInstalled = isPackageInstalledByPackageController(app.id) + appList.push({ + "id": app.id, + "name": app.name, + "isInstalled": isInstalled, + "packageSizeText": isInstalled ? getInstalledPackageSizeText(app.id) : "", + "packageBuiltIn": isInstalled ? isPackageBuiltIn(app.id) : false + }); + } + appModel.append(appList) + } + } } } diff --git a/apps/com.pelagicore.downloads/stores/JSONBackend.js b/apps/com.pelagicore.downloads/stores/JSONBackend.js index bd08c54c..1aa58ee3 100644 --- a/apps/com.pelagicore.downloads/stores/JSONBackend.js +++ b/apps/com.pelagicore.downloads/stores/JSONBackend.js @@ -42,7 +42,7 @@ function setErrorFunction(func) { } function serverCall(url, data, dataReadyFunction) { - var i = 0 + var i = 0; for (var key in data) { if (i === 0) { @@ -50,26 +50,35 @@ function serverCall(url, data, dataReadyFunction) { } else { url += "&" + key+ "=" + data[key]; } - i++ + i++; } var xhr = new XMLHttpRequest(); - console.log(Utils.Logging.sysui, "HTTP GET to " + url); + console.log(Utils.Logging.apps, "HTTP GET to " + url); xhr.open("GET", url); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.responseText !== "") { - errorCounter = 0 - var data = JSON.parse(xhr.responseText); - return dataReadyFunction(data) + errorCounter = 0; + var data = 0; + + try { + data = JSON.parse(xhr.responseText); + } catch(e) { + console.warn(Utils.Logging.apps, "JSONBackend error parsing answer:", + xhr.responseText); + } + + return dataReadyFunction(data); } else { - console.log(Utils.Logging.sysui, "JSONBackend: " + xhr.status + xhr.statusText) - errorCounter++ + console.warn(Utils.Logging.apps, "JSONBackend: status:", xhr.status, + xhr.statusText); + errorCounter++; if (errorCounter >= 3 && errorFunc) { - errorFunc() + errorFunc(); } - return dataReadyFunction(0) + return dataReadyFunction(0); } } } diff --git a/apps/com.pelagicore.downloads/stores/JSONModel.qml b/apps/com.pelagicore.downloads/stores/JSONModel.qml index 2b3cb842..e18cf4ef 100644 --- a/apps/com.pelagicore.downloads/stores/JSONModel.qml +++ b/apps/com.pelagicore.downloads/stores/JSONModel.qml @@ -45,6 +45,12 @@ ListModel { status = "loading" clear(); JSONBackend.serverCall(url, data, function(data) { + if (data === 0) { + status = "error"; + + return; + } + for (var i = 0; i < data.length; i++) { var entry = data[i]; append(entry); diff --git a/apps/com.pelagicore.downloads/stores/ServerConfig.qml b/apps/com.pelagicore.downloads/stores/ServerConfig.qml index 46c527f4..666b215b 100644 --- a/apps/com.pelagicore.downloads/stores/ServerConfig.qml +++ b/apps/com.pelagicore.downloads/stores/ServerConfig.qml @@ -39,88 +39,72 @@ import shared.utils 1.0 QtObject { id: root - property bool serverOnline: false - property string serverReason property string cpuArch property string serverUrl: ApplicationManager.systemProperties.appStoreServerUrl property string userName: ApplicationManager.systemProperties.userName property string userPassword: ApplicationManager.systemProperties.userPassword readonly property string imei: ApplicationManager.systemProperties.imei - property bool isReconnecting: false + + readonly property int maxReconnectCount: 5 + property int reconnectionAttempt: 0 signal loginSuccessful() + signal connectionSuccessful() + signal connectionFailed() + signal tryConnectToServer() + signal loginFailed() + signal serverOnMaintance() property var d: QtObject { - - property int attempt: 0 - property Timer retryTimer: Timer { - interval: 2000 - onTriggered: { - d.checkServerPrivate() - } - } - - function retry() { - console.log(Logging.apps, "Neptune-UI::Application Store - Retry Connection"); - if (attempt < 5) { - attempt += 1; - retryTimer.start(); - } else { - root.isReconnecting = false; - } - } - function checkServerPrivate() { - root.isReconnecting = true; console.log(Logging.apps, "Neptune-UI::Application Store - Check Server"); + root.tryConnectToServer(); var url = root.serverUrl + "/hello"; var data = {"platform" : "NEPTUNE3", "version" : "1", "architecture": root.cpuArch}; - JSONBackend.setErrorFunction(function () { - root.serverOnline = false; - root.serverReason = "unknown"; - root.d.retry() - }) + JSONBackend.setErrorFunction(0); JSONBackend.serverCall(url, data, function(data) { if (data !== 0) { if (data.status === "ok") { - root.d.attempt = 0 - root.serverOnline = true; - root.isReconnecting = false; - root.login(); + root.reconnectionAttempt = 0 + root.connectionSuccessful(); } else if (data.status === "maintenance") { - console.log(Logging.apps, "Server Call: maintenance"); - root.serverOnline = false; - root.serverReason = "maintenance"; + console.warn(Logging.apps, "Server Call: maintenance"); + root.serverOnMaintance(); } else { - console.log(Logging.apps, "Server Call Err: " + data.error); - root.serverOnline = false; - root.d.retry() + console.warn(Logging.apps, "Server Call Err: " + data.error, + "Status: " + data.status); + root.connectionFailed(); } } else { - root.serverOnline = false; - root.serverReason = "unknown"; - root.d.retry(); + console.warn(Logging.apps, "Server Check Error: zero data error") + root.connectionFailed(); } }) } } function checkServer() { - root.d.attempt = 0 root.d.checkServerPrivate() } function login() { var url = serverUrl + "/login" var data = { "username" : userName, "password" : userPassword, "imei" : imei } + + JSONBackend.setErrorFunction(0); JSONBackend.serverCall(url, data, function(data) { if (data !== 0) { if (data.status === "ok") { console.log(Logging.apps, "Login Succeeded"); loginSuccessful(); } else { - console.log(Logging.apps, "Login Err: " + data.error); + console.warn(Logging.apps, "Login Error: " + data.error, + "Status: " + data.status); + root.loginFailed(); } + } else { + console.warn(Logging.apps, "Login Error: zero data error"); + root.loginFailed(); } }) } diff --git a/apps/com.pelagicore.downloads/views/DownloadsView.qml b/apps/com.pelagicore.downloads/views/DownloadsView.qml index 29424f11..ca7fa916 100644 --- a/apps/com.pelagicore.downloads/views/DownloadsView.qml +++ b/apps/com.pelagicore.downloads/views/DownloadsView.qml @@ -46,109 +46,137 @@ Item { property DownloadsStore store - Connections { - target: store - onCategoryListReady: { - if (toolsColumn.model && toolsColumn.model.count > 0) { - toolsColumn.toolClicked(0); + states: [ + State { + when: store.downloadsStates.noNetwork.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 0.0 } + PropertyChanges { + target: busyIndicator + opacity: store.downloadsStates.connectingToServer.active ? 1.0 : 0.0 } - } - } - - BusyIndicator { - id: busyIndicator - - width: Sizes.dp(225) - height: Sizes.dp(440) - anchors.centerIn: parent - running: visible - opacity: root.store.isBusy ? 1.0 : 0.0 - visible: opacity > 0.0 - Behavior on opacity { - PauseAnimation { duration: 1000 } - DefaultNumberAnimation { } - } - } - - Loader { - anchors.top: root.store.isBusy ? busyIndicator.bottom : undefined - anchors.centerIn: busyIndicator.visible ? undefined : root - anchors.topMargin: Sizes.dp(8) - anchors.horizontalCenter: parent.horizontalCenter - sourceComponent: root.store.isOnline ? fetchingLabel : noInternetLabel - visible: opacity > 0 - opacity: root.store.isOnline ? busyIndicator.opacity : 1.0 - Behavior on opacity { DefaultNumberAnimation { } } - } - - Component { - id: fetchingLabel - - Label { - color: Style.contrastColor - font.pixelSize: Sizes.fontSizeM - text: qsTr("Fetching data from Neptune Server") - } - } - - Component { - id: noInternetLabel - - Column { - id: column - anchors.centerIn: parent - spacing: Sizes.dp(50) - Label { - color: Style.contrastColor - font.pixelSize: Sizes.fontSizeM - horizontalAlignment: Text.AlignHCenter + PropertyChanges { + target: topMessageText text: qsTr("Cannot Connect to the Server") + "\n" + qsTr("A Network connection is required") } - Label { - color: Style.contrastColor - font.pixelSize: Sizes.fontSizeM - horizontalAlignment: Text.AlignHCenter + PropertyChanges { + target: bottomMessageText text: qsTr("Reconnecting...") - visible: store.isReconnecting - anchors.horizontalCenter: parent.horizontalCenter + opacity: store.downloadsStates.connectingToServer.active ? 1.0 : 0.0 } - Button { - text: qsTr("Retry") - implicitHeight: Sizes.dp(70) - implicitWidth: Sizes.dp(315) - font.pixelSize: Sizes.fontSizeS - anchors.horizontalCenter: column.horizontalCenter - visible: !store.isReconnecting - onClicked: { - store.appStoreConfig.checkServer() - } + PropertyChanges { + target: retryButton + visible: !store.downloadsStates.connectingToServer.active + } + }, + State { + when: store.downloadsStates.networkConnected.active + && store.downloadsStates.connectingToServer.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 0.0 } + PropertyChanges { target: busyIndicator; opacity: 1.0 } + PropertyChanges { + target: topMessageText + text: qsTr("Connecting to server...") + } + PropertyChanges { target: bottomMessageText; opacity: 0.0 } + PropertyChanges { target: retryButton; visible: false } + }, + State { + when: store.downloadsStates.networkConnected.active + && store.downloadsStates.checkServerError.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 0.0 } + PropertyChanges { target: busyIndicator; opacity: 1.0 } + PropertyChanges { + target: topMessageText + text: qsTr("Connecting to server...") + } + PropertyChanges { target: bottomMessageText; opacity: 0.0 } + PropertyChanges { target: retryButton; visible: false } + }, + State { + when: store.downloadsStates.serverNA.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 0.0 } + PropertyChanges { target: busyIndicator; opacity: 0.0 } + PropertyChanges { + target: topMessageText + text: qsTr("Server is not available") + } + PropertyChanges { target: retryButton; visible: true } + }, + State { + when: store.downloadsStates.serverOnMaintance.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 0.0 } + PropertyChanges { target: busyIndicator; opacity: 0.0 } + PropertyChanges { + target: topMessageText + text: qsTr("Server is on Maintance") + } + PropertyChanges { target: retryButton; visible: true } + }, + State { + when: store.downloadsStates.connectedError.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 0.0 } + PropertyChanges { target: busyIndicator; opacity: 0.0 } + PropertyChanges { + target: topMessageText + text: store.downloadsStates.connectedError.errorText + } + PropertyChanges { target: retryButton; visible: true } + }, + State { + when: store.downloadsStates.fetchingApps.active + || store.downloadsStates.fetchingCategories.active + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 1.0 } + PropertyChanges { target: appList; opacity: 0.0 } + PropertyChanges { target: busyIndicator; opacity: 1.0 } + PropertyChanges { + target: topMessageText + text: qsTr("Fetching data from Neptune Server") + } + PropertyChanges { target: bottomMessageText; text: "" } + PropertyChanges { target: retryButton; visible: false } + }, + State { + when: store.downloadsStates.appsLoaded.active && appList.count === 0 + PropertyChanges { target: busyMessage; opacity: 1.0 } + PropertyChanges { target: downloadsContent; opacity: 1.0 } + PropertyChanges { target: busyIndicator; opacity: 0.0 } + PropertyChanges { + target: topMessageText + text: qsTr("No apps") } + PropertyChanges { target: bottomMessageText; text: "" } + PropertyChanges { target: retryButton; visible: false } + }, + State { + when: store.downloadsStates.appsLoaded.active && appList.count > 0 + PropertyChanges { target: busyMessage; opacity: 0.0 } + PropertyChanges { target: downloadsContent; opacity: 1.0 } + PropertyChanges { target: appList; opacity: 1.0 } } - } - - Label { - anchors.centerIn: parent - color: Style.contrastColor - font.pixelSize: Sizes.fontSizeM - text: qsTr("No apps found!") - opacity: 1.0 - busyIndicator.opacity - visible: root.store.isBusy - } + ] RowLayout { id: downloadsContent + anchors.left: parent.left anchors.top: parent.top anchors.topMargin: Sizes.dp(500) anchors.bottom: parent.bottom anchors.bottomMargin: Sizes.dp(20) + opacity: 0.0 visible: opacity > 0 - opacity: root.store.isOnline ? 1.0 : 0.0 - Behavior on opacity { DefaultNumberAnimation { } } DownloadsToolsColumn { id: toolsColumn + objectName: "downloadsAppColumn" Layout.preferredWidth: Sizes.dp(264) Layout.fillHeight: true @@ -159,13 +187,16 @@ Item { DownloadAppList { id: appList + objectName: "downloadAppList" Layout.preferredHeight: Sizes.dp(800) Layout.preferredWidth: Sizes.dp(675) Layout.alignment: Qt.AlignTop Layout.topMargin: Sizes.dp(16) - store: root.store - + appServerUrl: root.store.appServerUrl + cpuArch: root.store.cpuArch + applicationModel: root.store.applicationModel + currentInstallationProgress: root.store.currentInstallationProgress onToolClicked: { if (root.store.isPackageBusy(appId)) { console.warn("Package busy... Aborting", appId) @@ -177,6 +208,136 @@ Item { root.store.download(appId, appName); } } + onAppClicked: { root.store.tryStartApp(appId); } + + Behavior on opacity { DefaultNumberAnimation { duration: 200 } } + + Connections { + target: root.store + onInstalledPackagesChanged: { + // update states of app items, pass functions to update function + appList.refreshAppsInfo(root.store.isPackageInstalledByPackageController, + root.store.isPackageBuiltIn, + root.store.getInstalledPackageSizeText) + } + } + } + } + + Item { + id: busyMessage + + anchors.fill: parent + Behavior on opacity { + SequentialAnimation{ + // keep invisible and only show if nothing happens not to blink + PauseAnimation { duration: 400 } + DefaultNumberAnimation { } + } + } + + ColumnLayout { + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + anchors.topMargin: Sizes.dp(400) + + BusyIndicator { + id: busyIndicator + + implicitWidth: Sizes.dp(225) + implicitHeight: Sizes.dp(440) + opacity: 0.0 + Layout.alignment: Qt.AlignHCenter + Behavior on opacity { + SequentialAnimation{ + PauseAnimation { duration: 1000 } + DefaultNumberAnimation { } + } + } + } + + Label { + id: topMessageText + + color: Style.contrastColor + font.pixelSize: Sizes.fontSizeM + horizontalAlignment: Text.AlignHCenter + Layout.alignment: Qt.AlignHCenter + } + + Label { + id: bottomMessageText + + color: Style.contrastColor + font.pixelSize: Sizes.fontSizeM + horizontalAlignment: Text.AlignHCenter + Layout.alignment: Qt.AlignHCenter + } + + Button { + id: retryButton + + text: qsTr("Retry") + implicitHeight: Sizes.dp(70) + implicitWidth: Sizes.dp(315) + font.pixelSize: Sizes.fontSizeS + visible: false + Layout.alignment: Qt.AlignHCenter + onClicked: { store.appStoreConfig.checkServer() } + } + } + } + + /* + + // Debug visual output for states changes + + Loader { + active: true + sourceComponent: Component { + id: debugStatesComponent + + ListView { + width: parent.width; height: Sizes.dp(600) + model: statesModel + delegate: Row { + Rectangle { + width: Sizes.dp(20); height: Sizes.dp(30); + color: model.stateValue ? "green" : "red" + } + Label { text: model.stateName } + } + + function updateStatesList() { + statesModel.clear(); + statesModel.append({"stateName": "noNetwork", "stateValue": store.downloadsStates.noNetwork.active }); + statesModel.append({"stateName": "networkConnected", "stateValue": store.downloadsStates.networkConnected.active }); + statesModel.append({"stateName": "connectingToServer", "stateValue": store.downloadsStates.connectingToServer.active }); + statesModel.append({"stateName": "connectedError", "stateValue": store.downloadsStates.connectedError.active }); + statesModel.append({"stateName": "connectedToServer", "stateValue": store.downloadsStates.connectedToServer.active }); + statesModel.append({"stateName": "fetchingApps", "stateValue": store.downloadsStates.fetchingApps.active }); + statesModel.append({"stateName": "fetchingCategories", "stateValue": store.downloadsStates.fetchingCategories.active }); + statesModel.append({"stateName": "appsLoaded", "stateValue": store.downloadsStates.appsLoaded.active }); + statesModel.append({"stateName": "serverOnMaintance", "stateValue": store.downloadsStates.serverOnMaintance.active }); + statesModel.append({"stateName": "serverNA", "stateValue": store.downloadsStates.serverNA.active }); + statesModel.append({"stateName": "loggingIn", "stateValue": store.downloadsStates.loggingIn.active }); + statesModel.append({"stateName": "categoriesLoaded", "stateValue": store.downloadsStates.categoriesLoaded.active }); + statesModel.append({"stateName": "checkServerError", "stateValue": store.downloadsStates.checkServerError.active }); + } + + ListModel { + id: statesModel + Component.onCompleted: { updateStatesList(); } + } + + Connections { + target: root + onStateChanged: { updateStatesList(); } + } + } + } } + + */ } diff --git a/imports_shared/assets/translations/ar_MA.ts b/imports_shared/assets/translations/ar_MA.ts index 869fd934..1d573ccc 100644 --- a/imports_shared/assets/translations/ar_MA.ts +++ b/imports_shared/assets/translations/ar_MA.ts @@ -301,6 +301,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Bytes</source> @@ -399,7 +414,7 @@ temperatures between 14° and 18°.</source> </message> <message> <source>No apps found!</source> - <translation>لا وجود لتطبيقات!</translation> + <translation type="vanished">لا وجود لتطبيقات!</translation> </message> <message> <source>A Network connection is required</source> @@ -413,6 +428,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/cs_CZ.ts b/imports_shared/assets/translations/cs_CZ.ts index db2abfaf..a58ebb29 100644 --- a/imports_shared/assets/translations/cs_CZ.ts +++ b/imports_shared/assets/translations/cs_CZ.ts @@ -613,6 +613,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -711,7 +726,7 @@ temperatures between 14° and 18°.</source> </message> <message> <source>No apps found!</source> - <translation type="unfinished">Žádné aplikace nenalezeny!</translation> + <translation type="obsolete">Žádné aplikace nenalezeny!</translation> </message> <message> <source>A Network connection is required</source> @@ -725,6 +740,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/de_DE.ts b/imports_shared/assets/translations/de_DE.ts index 9d790ae4..bbe6cbd7 100644 --- a/imports_shared/assets/translations/de_DE.ts +++ b/imports_shared/assets/translations/de_DE.ts @@ -454,6 +454,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -548,7 +563,7 @@ temperatures between 14° and 18°.</source> </message> <message> <source>No apps found!</source> - <translation>Keine Apps gefunden!</translation> + <translation type="vanished">Keine Apps gefunden!</translation> </message> <message> <source>A Network connection is required</source> @@ -562,6 +577,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation>Wiederholung</translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/en_GB.ts b/imports_shared/assets/translations/en_GB.ts index 0b4d0391..b24b4b62 100644 --- a/imports_shared/assets/translations/en_GB.ts +++ b/imports_shared/assets/translations/en_GB.ts @@ -278,6 +278,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -371,10 +386,6 @@ temperatures between 14° and 18°.</source> <translation type="unfinished"></translation> </message> <message> - <source>No apps found!</source> - <translation></translation> - </message> - <message> <source>A Network connection is required</source> <translation type="unfinished"></translation> </message> @@ -386,6 +397,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/en_US.ts b/imports_shared/assets/translations/en_US.ts index 4390cd37..b0c7b4a1 100644 --- a/imports_shared/assets/translations/en_US.ts +++ b/imports_shared/assets/translations/en_US.ts @@ -278,6 +278,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -371,10 +386,6 @@ temperatures between 14° and 18°.</source> <translation type="unfinished"></translation> </message> <message> - <source>No apps found!</source> - <translation></translation> - </message> - <message> <source>A Network connection is required</source> <translation type="unfinished"></translation> </message> @@ -386,6 +397,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/ja_JP.ts b/imports_shared/assets/translations/ja_JP.ts index 852ce7d2..cf03eb90 100644 --- a/imports_shared/assets/translations/ja_JP.ts +++ b/imports_shared/assets/translations/ja_JP.ts @@ -440,6 +440,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -534,7 +549,7 @@ temperatures between 14° and 18°.</source> </message> <message> <source>No apps found!</source> - <translation type="unfinished">アプリが見つかりません!</translation> + <translation type="obsolete">アプリが見つかりません!</translation> </message> <message> <source>A Network connection is required</source> @@ -548,6 +563,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/ko_KR.ts b/imports_shared/assets/translations/ko_KR.ts index f46cb8fe..e714754d 100644 --- a/imports_shared/assets/translations/ko_KR.ts +++ b/imports_shared/assets/translations/ko_KR.ts @@ -447,6 +447,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -541,7 +556,7 @@ temperatures between 14° and 18°.</source> </message> <message> <source>No apps found!</source> - <translation type="unfinished">앱을 찾을 수 없습니다!</translation> + <translation type="obsolete">앱을 찾을 수 없습니다!</translation> </message> <message> <source>A Network connection is required</source> @@ -555,6 +570,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> diff --git a/imports_shared/assets/translations/zh_CN.ts b/imports_shared/assets/translations/zh_CN.ts index 42b48cad..28c835e7 100644 --- a/imports_shared/assets/translations/zh_CN.ts +++ b/imports_shared/assets/translations/zh_CN.ts @@ -447,6 +447,21 @@ temperatures between 14° and 18°.</source> </message> </context> <context> + <name>DownloadsStates</name> + <message> + <source>Login Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching categories error</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Fetching apps error</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>DownloadsStore</name> <message> <source>%1 Successfully Installed</source> @@ -541,7 +556,7 @@ temperatures between 14° and 18°.</source> </message> <message> <source>No apps found!</source> - <translation type="unfinished">未找到app!</translation> + <translation type="obsolete">未找到app!</translation> </message> <message> <source>A Network connection is required</source> @@ -555,6 +570,22 @@ temperatures between 14° and 18°.</source> <source>Retry</source> <translation type="unfinished"></translation> </message> + <message> + <source>Connecting to server...</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is not available</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Server is on Maintance</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>No apps</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>DrivingModeRange</name> |