diff options
Diffstat (limited to 'mobile-widgets')
-rw-r--r-- | mobile-widgets/qml/CloudCredentials.qml | 11 | ||||
-rw-r--r-- | mobile-widgets/qml/DiveDetails.qml | 2 | ||||
-rw-r--r-- | mobile-widgets/qml/DiveList.qml | 28 | ||||
-rw-r--r-- | mobile-widgets/qml/StartPage.qml | 6 | ||||
-rw-r--r-- | mobile-widgets/qml/icons/nocloud.svg | 71 | ||||
-rw-r--r-- | mobile-widgets/qml/main.qml | 31 | ||||
-rw-r--r-- | mobile-widgets/qml/mobile-resources.qrc | 2 | ||||
-rw-r--r-- | mobile-widgets/qmlmanager.cpp | 162 | ||||
-rw-r--r-- | mobile-widgets/qmlmanager.h | 7 |
9 files changed, 270 insertions, 50 deletions
diff --git a/mobile-widgets/qml/CloudCredentials.qml b/mobile-widgets/qml/CloudCredentials.qml index d63227619..2bb42a6ed 100644 --- a/mobile-widgets/qml/CloudCredentials.qml +++ b/mobile-widgets/qml/CloudCredentials.qml @@ -23,6 +23,17 @@ Item { id: outerLayout width: loginWindow.width - loginWindow.leftPadding - loginWindow.rightPadding - 2 * Kirigami.Units.gridUnit + function goToNext() { + for (var i = 0; i < children.length; ++i) + if (children[i].focus) { + children[i].nextItemInFocusChain().forceActiveFocus() + break + } + } + + Keys.onReturnPressed: goToNext() + Keys.onTabPressed: goToNext() + onVisibleChanged: { if (visible && manager.accessingCloud < 0) { manager.appendTextToLog("Credential scrn: show kbd was: " + (Qt.inputMethod.isVisible ? "visible" : "invisible")) diff --git a/mobile-widgets/qml/DiveDetails.qml b/mobile-widgets/qml/DiveDetails.qml index 3f42a1ed5..5735266f6 100644 --- a/mobile-widgets/qml/DiveDetails.qml +++ b/mobile-widgets/qml/DiveDetails.qml @@ -30,8 +30,6 @@ Kirigami.Page { property alias gpsCheckbox: detailsEdit.gpsCheckbox property int updateCurrentIdx: manager.updateSelectedDive - property bool contentItem: true // HACK to work around Kirigami issue - remove once that's addressed upstream - title: diveDetailsListView.currentItem ? diveDetailsListView.currentItem.modelData.dive.location : "Dive details" state: "view" leftPadding: 0 diff --git a/mobile-widgets/qml/DiveList.qml b/mobile-widgets/qml/DiveList.qml index 6ad3161e1..9ffb2ee88 100644 --- a/mobile-widgets/qml/DiveList.qml +++ b/mobile-widgets/qml/DiveList.qml @@ -211,18 +211,24 @@ Kirigami.ScrollablePage { ScrollView { id: startPageWrapper anchors.fill: parent - opacity: (diveListView.count > 0 && (credentialStatus == QMLManager.VALID || credentialStatus == QMLManager.VALID_EMAIL)) ? 0 : 1 + opacity: credentialStatus === QMLManager.NOCLOUD || (diveListView.count > 0 && (credentialStatus === QMLManager.VALID || credentialStatus === QMLManager.VALID_EMAIL)) ? 0 : 1 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } } onVisibleChanged: { + print("startPageWrapper onVisibleChanged credentialStatus " + credentialStatus + " diveListView.count " + diveListView.count) if (visible) { page.actions.main = page.saveAction + page.actions.right = page.offlineAction title = "Cloud credentials" - } else if(manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL) { + } else if(manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL || manager.credentialStatus === QMLManager.NOCLOUD) { page.actions.main = page.addDiveAction + page.actions.right = null title = "Dive list" + if (diveListView.count === 0) + showPassiveNotification(qsTr("Please tap the '+' button to add a dive"), 3000) } else { page.actions.main = null + page.actions.right = null title = "Dive list" } } @@ -279,15 +285,25 @@ Kirigami.ScrollablePage { } } + property QtObject offlineAction: Action { + iconName: "qrc:/qml/nocloud.svg" + onTriggered: { + manager.syncToCloud = false + manager.credentialStatus = QMLManager.NOCLOUD + } + } + onBackRequested: { - if (startPageWrapper.visible && diveListView.count > 0 && manager.credentialStatus != QMLManager.INVALID) { + if (startPageWrapper.visible && diveListView.count > 0 && manager.credentialStatus !== QMLManager.INVALID) { manager.credentialStatus = oldStatus event.accepted = true; } if (!startPageWrapper.visible) { - manager.quit() - // we shouldn't come back from there, but just in case - event.accepted = true + if (Qt.platform.os != "ios") { + manager.quit() + // we shouldn't come back from there, but just in case + event.accepted = true + } } } } diff --git a/mobile-widgets/qml/StartPage.qml b/mobile-widgets/qml/StartPage.qml index 41fe469c2..e9c785672 100644 --- a/mobile-widgets/qml/StartPage.qml +++ b/mobile-widgets/qml/StartPage.qml @@ -16,8 +16,10 @@ ColumnLayout { Layout.fillWidth: true Layout.margins: Kirigami.Units.gridUnit Layout.topMargin: Kirigami.Units.gridUnit * 3 - text: "In order to use Subsurface-mobile you need to have a Subsurface cloud storage account " + - "(which can be created with the Subsurface desktop application)." + text: "To use Subsurface-mobile with Subsurface cloud storage, please enter " + + "your cloud credentials.\n\n" + + "To use Subsurface-mobile only with local data on this device, tap " + + "on the no cloud icon below." wrapMode: Text.WordWrap } Kirigami.Label { diff --git a/mobile-widgets/qml/icons/nocloud.svg b/mobile-widgets/qml/icons/nocloud.svg new file mode 100644 index 000000000..0661d32e6 --- /dev/null +++ b/mobile-widgets/qml/icons/nocloud.svg @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + viewBox="0 0 22 22" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="nocloud.svg"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1022" + inkscape:window-height="740" + id="namedview8" + showgrid="false" + inkscape:zoom="10.727273" + inkscape:cx="-2.8898305" + inkscape:cy="11" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:current-layer="svg2" /> + <defs + id="defs3051"> + <style + type="text/css" + id="current-color-scheme"> + .ColorScheme-Text { + color:#4d4d4d; + } + </style> + </defs> + <path + style="fill:currentColor;fill-opacity:1;stroke:none" + d="M 11 4 A 6 6 0 0 0 5 10 A 6 6 0 0 0 5.0039062 10.128906 A 4 4 0 0 0 2 14 A 4 4 0 0 0 6 18 L 15 18 A 5 5 0 0 0 20 13 A 5 5 0 0 0 16.757812 8.3242188 A 6 6 0 0 0 11 4 z M 11 5 A 5 5 0 0 1 15.919922 9.1113281 A 4.0000019 4.0000019 0 0 1 19 13 A 4.0000019 4.0000019 0 0 1 15 17 L 6 17 A 2.9999979 2.9999979 0 0 1 3 14 A 2.9999979 2.9999979 0 0 1 6 11 A 2.9999979 2.9999979 0 0 1 6.1074219 11.005859 A 5 5 0 0 1 6 10 A 5 5 0 0 1 11 5 z " + class="ColorScheme-Text" + id="path6" /> + <path + style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 4.0550844,20.042373 18.877119,4.0084751" + id="path3338-1" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#4d4d4d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:1" + d="M 3.8220339,19.855932 18.644068,3.8220339" + id="path3338" + inkscape:connector-curvature="0" /> +</svg> diff --git a/mobile-widgets/qml/main.qml b/mobile-widgets/qml/main.qml index e1a140635..b4ab897e9 100644 --- a/mobile-widgets/qml/main.qml +++ b/mobile-widgets/qml/main.qml @@ -124,7 +124,6 @@ Kirigami.ApplicationWindow { }, Kirigami.Action { text: "Manage dives" - enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL /* * disable for the beta to avoid confusion Action { @@ -137,6 +136,7 @@ Kirigami.ApplicationWindow { */ Kirigami.Action { text: "Add dive manually" + enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL || manager.credentialStatus === QMLManager.NOCLOUD onTriggered: { returnTopPage() // otherwise odd things happen with the page stack startAddDive() @@ -144,24 +144,34 @@ Kirigami.ApplicationWindow { } Kirigami.Action { text: "Manual sync with cloud" + enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL || manager.credentialStatus === QMLManager.NOCLOUD onTriggered: { - globalDrawer.close() - detailsWindow.endEditMode() - manager.saveChangesCloud(true); - globalDrawer.close() + if (manager.credentialStatus === QMLManager.NOCLOUD) { + returnTopPage() + oldStatus = manager.credentialStatus + manager.startPageText = "Enter valid cloud storage credentials" + manager.credentialStatus = QMLManager.UNKNOWN + globalDrawer.close() + } else { + globalDrawer.close() + detailsWindow.endEditMode() + manager.saveChangesCloud(true); + globalDrawer.close() + } } } Kirigami.Action { - text: syncToCloud ? "Disable auto cloud sync" : "Enable auto cloud sync" + text: syncToCloud ? "Offline mode" : "Enable auto cloud sync" + enabled: manager.credentialStatus !== QMLManager.NOCLOUD onTriggered: { syncToCloud = !syncToCloud if (!syncToCloud) { var alertText = "Turning off automatic sync to cloud causes all data\n" - alertText +=" to only be stored locally.\n" + alertText +="to only be stored locally.\n" alertText += "This can be very useful in situations with\n" - alertText += " limited or no network access.\n" + alertText += "limited or no network access.\n" alertText += "Please chose 'Manual sync with cloud' if you have network\n" - alertText += " connectivity and want to sync your data to cloud storage." + alertText += "connectivity and want to sync your data to cloud storage." showPassiveNotification(alertText, 10000) } } @@ -326,8 +336,7 @@ Kirigami.ApplicationWindow { DiveDetails { id: detailsWindow visible: false - width: parent.width - height: parent.height + anchors.fill: parent } DownloadFromDiveComputer { diff --git a/mobile-widgets/qml/mobile-resources.qrc b/mobile-widgets/qml/mobile-resources.qrc index 6157e3bf6..ab556789b 100644 --- a/mobile-widgets/qml/mobile-resources.qrc +++ b/mobile-widgets/qml/mobile-resources.qrc @@ -21,6 +21,7 @@ <file alias="context-menu.png">icons/context-menu.png</file> <file alias="menu-edit.png">icons/menu-edit.png</file> <file alias="menu-back.png">icons/menu-back.png</file> + <file alias="nocloud.svg">icons/nocloud.svg</file> </qresource> <qresource prefix="/imports"> <file alias="org/kde/kirigami/qmldir">kirigami/qmldir</file> @@ -48,6 +49,7 @@ <file alias="org/kde/kirigami/private/ActionButton.qml">kirigami/private/ActionButton.qml</file> <file alias="org/kde/kirigami/private/BackButton.qml">kirigami/private/BackButton.qml</file> <file alias="org/kde/kirigami/private/ContextIcon.qml">kirigami/private/ContextIcon.qml</file> + <file alias="org/kde/kirigami/private/DefaultListItemBackground.qml">kirigami/private/DefaultListItemBackground.qml</file> <file alias="org/kde/kirigami/private/EdgeShadow.qml">kirigami/private/EdgeShadow.qml</file> <file alias="org/kde/kirigami/private/MenuIcon.qml">kirigami/private/MenuIcon.qml</file> <file alias="org/kde/kirigami/private/DefaultListItemBackground.qml">kirigami/private/DefaultListItemBackground.qml</file> diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index c2c60ce5c..82ea319bb 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -19,12 +19,16 @@ #include "core/qt-gui.h" #include "core/git-access.h" #include "core/cloudstorage.h" +#include "core/subsurface-qt/SettingsObjectWrapper.h" +#include "core/membuffer.h" QMLManager *QMLManager::m_instance = NULL; #define RED_FONT QLatin1Literal("<font color=\"red\">") #define END_FONT QLatin1Literal("</font>") +#define NOCLOUD_LOCALSTORAGE format_string("%s/cloudstorage/localrepo[master]", system_default_directory()) + static void appendTextToLogStandalone(const char *text) { QMLManager *self = QMLManager::instance(); @@ -153,6 +157,11 @@ void QMLManager::openLocalThenRemote(QString url) DiveListModel::instance()->addAllDives(); appendTextToLog(QStringLiteral("%1 dives loaded from cache").arg(dive_table.nr)); } + if (oldStatus() == NOCLOUD) { + // if we switch to credentials from NOCLOUD, we take things online temporarily + prefs.git_local_only = false; + appendTextToLog(QStringLiteral("taking things online to be able to switch to cloud account")); + } set_filename(fileNamePrt.data(), true); if (prefs.git_local_only) { appendTextToLog(QStringLiteral("have cloud credentials, but user asked not to connect to network")); @@ -163,6 +172,13 @@ void QMLManager::openLocalThenRemote(QString url) } } +void QMLManager::mergeLocalRepo() +{ + char *filename = NOCLOUD_LOCALSTORAGE; + parse_file(filename); + process_dives(true, false); +} + void QMLManager::finishSetup() { // Initialize cloud credentials. @@ -178,9 +194,23 @@ void QMLManager::finishSetup() // but we need to make sure we stay the only ones accessing git storage alreadySaving = true; openLocalThenRemote(url); + } else if (!same_string(existing_filename, "")) { + setCredentialStatus(NOCLOUD); + appendTextToLog(tr("working in no-cloud mode")); + int error = parse_file(existing_filename); + if (error) { + // we got an error loading the local file + appendTextToLog(QString("got error %2 when parsing file %1").arg(existing_filename, get_error_string())); + set_filename(NULL, ""); + } else { + // successfully opened the local file, now add thigs to the dive list + consumeFinishedLoad(0); + setAccessingCloud(-1); + appendTextToLog(QString("working in no-cloud mode, finished loading %1 dives from %2").arg(dive_table.nr).arg(existing_filename)); + } } else { setCredentialStatus(INCOMPLETE); - appendTextToLog(QStringLiteral("no cloud credentials")); + appendTextToLog(tr("no cloud credentials")); setStartPageText(RED_FONT + tr("Please enter valid cloud credentials.") + END_FONT); } setDistanceThreshold(prefs.distance_threshold); @@ -231,6 +261,7 @@ void QMLManager::saveCloudCredentials() // just go back to the dive list setCredentialStatus(oldStatus()); } + if (!same_string(prefs.cloud_storage_password, qPrintable(cloudPassword()))) { free(prefs.cloud_storage_password); prefs.cloud_storage_password = strdup(qPrintable(cloudPassword())); @@ -238,6 +269,9 @@ void QMLManager::saveCloudCredentials() if (cloudUserName().isEmpty() || cloudPassword().isEmpty()) { setStartPageText(RED_FONT + tr("Please enter valid cloud credentials.") + END_FONT); } else if (cloudCredentialsChanged) { + // let's make sure there are no unsaved changes + saveChangesLocal(); + free(prefs.userid); prefs.userid = NULL; syncLoadFromCloud(); @@ -252,6 +286,10 @@ void QMLManager::saveCloudCredentials() // we therefore know that no one else is already accessing THIS git repo; // let's make sure we stay the only ones doing so alreadySaving = true; + // since we changed credentials, we need to try to connect to the cloud, regardless + // of whether we're in offline mode or not, to make sure the repository is synced + currentGitLocalOnly = prefs.git_local_only; + prefs.git_local_only = false; openLocalThenRemote(url); } } @@ -268,7 +306,6 @@ void QMLManager::checkCredentialsAndExecute(execute_function_type execute) CloudStorageAuthenticate *csa = new CloudStorageAuthenticate(this); csa->backend(prefs.cloud_storage_email, prefs.cloud_storage_password); connect(manager(), &QNetworkAccessManager::authenticationRequired, this, &QMLManager::provideAuth, Qt::UniqueConnection); - connect(manager(), &QNetworkAccessManager::finished, this, execute, Qt::UniqueConnection); QUrl url(CLOUDREDIRECTURL); request = QNetworkRequest(url); request.setRawHeader("User-Agent", getUserAgent().toUtf8()); @@ -276,6 +313,7 @@ void QMLManager::checkCredentialsAndExecute(execute_function_type execute) reply = manager()->get(request); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError(QNetworkReply::NetworkError))); connect(reply, &QNetworkReply::sslErrors, this, &QMLManager::handleSslErrors); + connect(reply, &QNetworkReply::finished, this, execute, Qt::UniqueConnection); } } @@ -325,10 +363,11 @@ void QMLManager::handleError(QNetworkReply::NetworkError nError) void QMLManager::retrieveUserid() { if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 302) { - appendTextToLog(QStringLiteral("Cloud storage connection not working correctly: %1").arg(QString(reply->readAll()))); + appendTextToLog(QStringLiteral("Cloud storage connection not working correctly: (%1) %2") + .arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()) + .arg(QString(reply->readAll()))); setStartPageText(RED_FONT + tr("Cannot connect to cloud storage") + END_FONT); - setAccessingCloud(-1); - alreadySaving = false; + revertToNoCloudIfNeeded(); return; } setCredentialStatus(VALID); @@ -336,8 +375,7 @@ void QMLManager::retrieveUserid() if (userid.isEmpty()) { if (same_string(prefs.cloud_storage_email, "") || same_string(prefs.cloud_storage_password, "")) { appendTextToLog("cloud user name or password are empty, can't retrieve web user id"); - setAccessingCloud(-1); - alreadySaving = false; + revertToNoCloudIfNeeded(); return; } appendTextToLog(QStringLiteral("calling getUserid with user %1").arg(prefs.cloud_storage_email)); @@ -366,12 +404,12 @@ void QMLManager::loadDiveProgress(int percent) void QMLManager::loadDivesWithValidCredentials() { QString url; + timestamp_t currentDiveTimestamp = selectedDiveTimestamp(); if (getCloudURL(url)) { QString errorString(get_error_string()); appendTextToLog(errorString); setStartPageText(RED_FONT + tr("Cloud storage error: %1").arg(errorString) + END_FONT); - setAccessingCloud(-1); - alreadySaving = false; + revertToNoCloudIfNeeded(); return; } QByteArray fileNamePrt = QFile::encodeName(url); @@ -381,13 +419,9 @@ void QMLManager::loadDivesWithValidCredentials() if (check_git_sha(fileNamePrt.data(), &git, &branch) == 0) { qDebug() << "local cache was current, no need to modify dive list"; appendTextToLog("Cloud sync shows local cache was current"); - setLoadFromCloud(true); - setAccessingCloud(-1); - alreadySaving = false; - return; + goto successful_exit; } appendTextToLog("Cloud sync brought newer data, reloading the dive list"); - timestamp_t currentDiveTimestamp = selectedDiveTimestamp(); clear_dive_file_data(); if (git != dummy_git_repository) { @@ -407,10 +441,71 @@ void QMLManager::loadDivesWithValidCredentials() report_error("failed to open file %s", fileNamePrt.data()); QString errorString(get_error_string()); appendTextToLog(errorString); - setStartPageText(RED_FONT + tr("Cloud storage error: %1").arg(errorString) + END_FONT); - alreadySaving = false; + revertToNoCloudIfNeeded(); return; } + consumeFinishedLoad(currentDiveTimestamp); + +successful_exit: + alreadySaving = false; + setLoadFromCloud(true); + // if we came from local storage mode, let's merge the local data into the local cache + // for the remote data - which then later gets merged with the remote data if necessary + if (oldStatus() == NOCLOUD) { + git_storage_update_progress(false, "import dives from nocloud local storage"); + dive_table.preexisting = dive_table.nr; + mergeLocalRepo(); + DiveListModel::instance()->clear(); + DiveListModel::instance()->addAllDives(); + appendTextToLog(QStringLiteral("%1 dives loaded after importing nocloud local storage").arg(dive_table.nr)); + saveChangesLocal(); + if (syncToCloud() == false) { + appendTextToLog(QStringLiteral("taking things back offline now that storage is synced")); + prefs.git_local_only = syncToCloud(); + } + } + setAccessingCloud(-1); + // if we got here just for an initial connection to the cloud, reset to offline + if (currentGitLocalOnly) { + currentGitLocalOnly = false; + prefs.git_local_only = true; + } + return; +} + +void QMLManager::revertToNoCloudIfNeeded() +{ + if (currentGitLocalOnly) { + // we tried to connect to the cloud for the first time and that failed + currentGitLocalOnly = false; + prefs.git_local_only = true; + } + if (oldStatus() == NOCLOUD) { + // we tried to switch to a cloud account and had previously used local data, + // but connecting to the cloud account (and subsequently merging the local + // and cloud data) failed - so let's delete the cloud credentials and go + // back to NOCLOUD mode in order to prevent us from losing the locally stored + // dives + if (syncToCloud() == false) { + appendTextToLog(QStringLiteral("taking things back offline since sync with cloud failed")); + prefs.git_local_only = syncToCloud(); + } + free(prefs.cloud_storage_email); + prefs.cloud_storage_email = NULL; + free(prefs.cloud_storage_password); + prefs.cloud_storage_password = NULL; + setCloudUserName(""); + setCloudPassword(""); + setCredentialStatus(INCOMPLETE); + set_filename(NOCLOUD_LOCALSTORAGE, true); + setStartPageText(RED_FONT + tr("Failed to connect to cloud server, reverting to no cloud status") + END_FONT); + } + setAccessingCloud(-1); + alreadySaving = false; +} + +void QMLManager::consumeFinishedLoad(timestamp_t currentDiveTimestamp) +{ prefs.unit_system = informational_prefs.unit_system; if (informational_prefs.unit_system == IMPERIAL) informational_prefs.units = IMPERIAL_units; @@ -420,12 +515,9 @@ void QMLManager::loadDivesWithValidCredentials() DiveListModel::instance()->addAllDives(); if (currentDiveTimestamp) setUpdateSelectedDive(dlSortModel->getIdxForId(get_dive_id_closest_to(currentDiveTimestamp))); - else - setUpdateSelectedDive(0); appendTextToLog(QStringLiteral("%1 dives loaded").arg(dive_table.nr)); if (dive_table.nr == 0) setStartPageText(tr("Cloud storage open successfully. No dives in dive list.")); - setLoadFromCloud(true); alreadySaving = false; } @@ -782,11 +874,10 @@ void QMLManager::changesNeedSaving() // to be reasonably fast), but don't save at all (and only remember that we need to save things // on iOS // on all other platforms we just save the changes and be done with it -#if defined(Q_OS_IOS) mark_divelist_changed(true); -#elif defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) saveChangesLocal(); -#else +#elif !defined(Q_OS_IOS) saveChangesCloud(false); #endif } @@ -794,7 +885,18 @@ void QMLManager::saveChangesLocal() { if (unsaved_changes()) { git_storage_update_progress(true, "saving dives locally"); // reset the timers - if (!loadFromCloud()) { + if (credentialStatus() == NOCLOUD) { + if (same_string(existing_filename, "")) { + char *filename = NOCLOUD_LOCALSTORAGE; + if (git_create_local_repo(filename)) + appendTextToLog(get_error_string()); + set_filename(filename, true); + GeneralSettingsObjectWrapper s(this); + s.setDefaultFilename(filename); + s.setDefaultFileBehavior(LOCAL_DEFAULT_FILE); + qDebug() << "setting default file to" << filename; + } + } else if (!loadFromCloud()) { // this seems silly, but you need a common ancestor in the repository in // order to be able to merge che changes later appendTextToLog("Don't save dives without loading from the cloud, first."); @@ -809,6 +911,7 @@ void QMLManager::saveChangesLocal() prefs.git_local_only = true; if (save_dives(existing_filename)) { appendTextToLog(get_error_string()); + set_filename(NULL, true); setAccessingCloud(-1); prefs.git_local_only = glo; alreadySaving = false; @@ -825,14 +928,10 @@ void QMLManager::saveChangesLocal() void QMLManager::saveChangesCloud(bool forceRemoteSync) { - if (!unsaved_changes()) { + if (!unsaved_changes() && !forceRemoteSync) { appendTextToLog("asked to save changes but no unsaved changes"); return; } - if (!loadFromCloud()) { - appendTextToLog("Don't save dives without loading from the cloud, first."); - return; - } if (alreadySaving) { appendTextToLog("save operation in progress already"); return; @@ -844,6 +943,11 @@ void QMLManager::saveChangesCloud(bool forceRemoteSync) if (prefs.git_local_only && !forceRemoteSync) return; + if (!loadFromCloud()) { + appendTextToLog("Don't save dives without loading from the cloud, first."); + return; + } + bool glo = prefs.git_local_only; git_storage_update_progress(false, "start save change to cloud"); prefs.git_local_only = false; @@ -1119,6 +1223,8 @@ QMLManager::credentialStatus_t QMLManager::credentialStatus() const void QMLManager::setCredentialStatus(const credentialStatus_t value) { if (m_credentialStatus != value) { + if (value == NOCLOUD) + appendTextToLog("Switching to no cloud mode"); m_credentialStatus = value; emit credentialStatusChanged(); } diff --git a/mobile-widgets/qmlmanager.h b/mobile-widgets/qmlmanager.h index ece2c7b59..906e7b0b2 100644 --- a/mobile-widgets/qmlmanager.h +++ b/mobile-widgets/qmlmanager.h @@ -39,7 +39,8 @@ public: UNKNOWN, INVALID, VALID_EMAIL, - VALID + VALID, + NOCLOUD }; static QMLManager *instance(); @@ -127,11 +128,14 @@ public slots: void clearGpsData(); void finishSetup(); void openLocalThenRemote(QString url); + void mergeLocalRepo(); QString getNumber(const QString& diveId); QString getDate(const QString& diveId); QString getCurrentPosition(); QString getVersion() const; void deleteGpsFix(quint64 when); + void revertToNoCloudIfNeeded(); + void consumeFinishedLoad(timestamp_t currentDiveTimestamp); void refreshDiveList(); void screenChanged(QScreen *screen); qreal lastDevicePixelRatio(); @@ -170,6 +174,7 @@ private: bool checkLocation(DiveObjectHelper *myDive, struct dive *d, QString location, QString gps); bool checkDuration(DiveObjectHelper *myDive, struct dive *d, QString duration); bool checkDepth(DiveObjectHelper *myDive, struct dive *d, QString depth); + bool currentGitLocalOnly; signals: void cloudUserNameChanged(); |