Compare commits

...

4 Commits

Author SHA1 Message Date
Dirk Hohndel
6fb41eae0c mobile: add option to merge local cloud cache data
The UI is ugly, and of course this is hidden in the developer options that have
to first be enabled in the advanced settings. As I mentioned in the previous
commit, I believe the actual risk that something gets damaged here is very low,
but still, explaining this so it makes sense to the casual user may be a bit...
difficult.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-06-06 10:08:39 -07:00
Dirk Hohndel
db965cf86a mobile: add helper to import data from local cloud cache
If you pass in the repo name, it isn't treated as cloud storage, but simply as
local git storage and imported (i.e., added) to the current dive list.

This allows the user to work around failed no-cloud->cloud transitions, merge
different accounts, and most importantly deal with situations were conflicts on
the server caused us to move a cache out of the way and potentially make dives
that were on the mobile device inaccessible to the user.

Once a UI is added, this allows the user to recover those dives (realistically
this is not really all that potentially 'dangerous' to do, but it's definitely
something that would best be done after talking to someone who understands the
cloud storage and can guide the user...).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-06-06 09:55:52 -07:00
Dirk Hohndel
4339192fa0 mobile: make list of local cloud cache directories available
This way QML can show those to the user.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-06-06 09:52:12 -07:00
Dirk Hohndel
56f554e551 mobile: tiny whitespace update
Every time I edit main.qml, QtCreator fixes this for me. And then I filter it
from the commit to not mix white space and actual changes. So let's just get
this fixed and move on.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-06-06 09:47:53 -07:00
6 changed files with 136 additions and 4 deletions

View File

@ -1,3 +1,4 @@
Mobile: add advanved option to import dives from local cloud cache directories
Mobile: fix broken editing of location, suit, buddy, and dive master
Mobile: fix missing translations on Android
CSV export: support for multiple cylinders

View File

@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0
import QtQuick 2.6
import org.kde.kirigami 2.4 as Kirigami
import org.subsurfacedivelog.mobile 1.0
Kirigami.ScrollablePage {
id: recoverCache
title: qsTr("Cloud Cache Import")
objectName: "recoverCache"
background: Rectangle { color: subsurfaceTheme.backgroundColor }
width: parent.width
height: parent.height
Item {
TemplateLabel {
id: header
text: qsTr("Cloud Cache Import")
color: subsurfaceTheme.lightPrimaryTextColor
background: Rectangle { color: subsurfaceTheme.lightPrimaryColor }
font.pointSize: subsurfaceTheme.regularPointSize * 1.5
padding: Kirigami.Units.gridUnit
width: recoverCache.width - 5 * Kirigami.Units.largeSpacing
height: 3.5 * Kirigami.Units.gridUnit
}
Rectangle {
id: subheader
z: 5
width: recoverCache.width - 5 * Kirigami.Units.largeSpacing
height: 3 * Kirigami.Units.gridUnit
color: subsurfaceTheme.backgroundColor
anchors {
left: header.left
top: header.bottom
right: parent.right
}
TemplateLabel {
height: 2 * Kirigami.Units.gridUnit
text: qsTr("import data from the given cache repo")
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
}
Rectangle {
id: spacer
anchors.top: subheader.bottom
height: Kirigami.Units.largeSpacing
width: recoverCache.width
color: subsurfaceTheme.backgroundColor
}
Rectangle {
anchors {
left: header.left
right: parent.right
top: spacer.bottom
}
z: -5
ListView {
height: recoverCache.height - 9 * Kirigami.Units.gridUnit
width: recoverCache.width
model: manager.cloudCacheList
delegate: TemplateButton {
height: 3 * Kirigami.Units.gridUnit
width: parent.width - 2 * Kirigami.Units.gridUnit
text: modelData
onClicked: {
console.log("import " + modelData)
manager.importCacheRepo(modelData)
}
}
}
}
}
}

View File

@ -162,7 +162,7 @@ Kirigami.ApplicationWindow {
height: rootItem.height
rightPadding: 0
enabled: (Backend.cloud_verification_status === Enums.CS_NOCLOUD ||
Backend.cloud_verification_status === Enums.CS_VERIFIED)
Backend.cloud_verification_status === Enums.CS_VERIFIED)
topContent: Image {
source: "qrc:/qml/icons/dive.jpg"
Layout.fillWidth: true
@ -534,6 +534,14 @@ if you have network connectivity and want to sync your data to cloud storage."),
}
}
Kirigami.Action {
text: qsTr("Access local cloud cache dirs")
onTriggered: {
globalDrawer.close()
showPage(recoverCache)
}
}
/* disable for now
Kirigami.Action {
text: qsTr("Dive planner")
@ -681,8 +689,8 @@ if you have network connectivity and want to sync your data to cloud storage."),
manager.appendTextToLog("pageStack forced back to map")
}
} else if (pageStack.currentItem.objectName !== mapPage.objectName &&
pageStack.lastItem.objectName === mapPage.objectName &&
hackToOpenMap === 1 /* MapSelected */) {
pageStack.lastItem.objectName === mapPage.objectName &&
hackToOpenMap === 1 /* MapSelected */) {
// if we just picked the mapPage and are suddenly back on a different page
// force things back to the mapPage
manager.appendTextToLog("pageStack wrong page, switching back to map")
@ -822,6 +830,12 @@ if you have network connectivity and want to sync your data to cloud storage."),
id: mapPage
visible: false
}
RecoverCache {
id: recoverCache
visible: false
}
/* this shouldn't be exposed unless someone will finish the work
DivePlannerSetup {
id: divePlannerSetupWindow

View File

@ -41,6 +41,8 @@
<file>ThemeTest.qml</file>
<file>TripDetails.qml</file>
<file>StartPage.qml</file>
<file>RecoverCache.qml</file>
<file>SsrfCheckBox.qml</file>
<file>SsrfSwitch.qml</file>
<file>SsrfTextField.qml</file>

View File

@ -403,6 +403,8 @@ void QMLManager::openLocalThenRemote(QString url)
updateAllGlobalLists();
setDiveListProcessing(false);
// this could have added a new local cache directory
emit cloudCacheListChanged();
}
// Convenience function to accesss dive directly via its row.
@ -534,6 +536,9 @@ void QMLManager::finishSetup()
}
m_initialized = true;
emit initializedChanged();
// this could have brought in new cache directories, so make sure QML
// calls our getter function again and doesn't show us outdated information
emit cloudCacheListChanged();
}
QMLManager::~QMLManager()
@ -2201,3 +2206,34 @@ void QMLManager::setDiveListProcessing(bool value)
}
}
void QMLManager::importCacheRepo(QString repo)
{
struct dive_table table = empty_dive_table;
struct trip_table trips = empty_trip_table;
struct dive_site_table sites = empty_dive_site_table;
QString repoPath = QString("%1/cloudstorage/%2").arg(system_default_directory()).arg(repo);
appendTextToLog(QString("importing %1").arg(repoPath));
parse_file(qPrintable(repoPath), &table, &trips, &sites);
add_imported_dives(&table, &trips, &sites, IMPORT_MERGE_ALL_TRIPS);
changesNeedSaving();
}
QStringList QMLManager::cloudCacheList() const
{
QDir localCacheDir(QString("%1/cloudstorage/").arg(system_default_directory()));
QStringList dirs = localCacheDir.entryList().filter(QRegExp("...+"));
QStringList result;
foreach(QString dir, dirs) {
QString originsDir = QString("%1/cloudstorage/%2/.git/refs/remotes/origin/").arg(system_default_directory()).arg(dir);
QDir remote(originsDir);
if (dir == "localrepo") {
result << QString("localrepo[master]");
} else {
foreach(QString branch, remote.entryList().filter(QRegExp("...+"))) {
result << QString("%1[%2]").arg(dir).arg(branch);
}
}
}
return result;
}

View File

@ -40,6 +40,7 @@ class QMLManager : public QObject {
Q_PROPERTY(QStringList divemasterList READ divemasterList NOTIFY divemasterListChanged)
Q_PROPERTY(QStringList locationList READ locationList NOTIFY locationListChanged)
Q_PROPERTY(QStringList cylinderInit READ cylinderInit CONSTANT)
Q_PROPERTY(QStringList cloudCacheList READ cloudCacheList NOTIFY cloudCacheListChanged)
Q_PROPERTY(QString progressMessage MEMBER m_progressMessage WRITE setProgressMessage NOTIFY progressMessageChanged)
Q_PROPERTY(bool btEnabled MEMBER m_btEnabled WRITE setBtEnabled NOTIFY btEnabledChanged)
@ -118,6 +119,7 @@ public:
Q_INVOKABLE void setFilter(const QString filterText, int mode);
Q_INVOKABLE void selectRow(int row);
Q_INVOKABLE void selectSwipeRow(int row);
Q_INVOKABLE void importCacheRepo(QString repo);
static QMLManager *instance();
Q_INVOKABLE void registerError(QString error);
@ -161,6 +163,7 @@ public:
QStringList divemasterList() const;
QStringList locationList() const;
QStringList cylinderInit() const;
QStringList cloudCacheList() const;
Q_INVOKABLE void setStatusbarColor(QColor color);
void btHostModeChange(QBluetoothLocalDevice::HostMode state);
QObject *qmlWindow;
@ -303,6 +306,7 @@ signals:
void buddyListChanged();
void divemasterListChanged();
void locationListChanged();
void cloudCacheListChanged();
void waitingForPositionChanged();
void pluggedInDeviceNameChanged();
void showNonDiveComputersChanged();
@ -316,7 +320,6 @@ signals:
void uploadFinish(bool success, const QString &text);
void uploadProgress(qreal percentage);
private slots:
void uploadFinishSlot(bool success, const QString &text, const QByteArray &html);
};