Implemented status.php call in the API. Began implementing Nextcloud Login flow v2.
This commit is contained in:
parent
da29b4b0ff
commit
58ae28dbe6
16 changed files with 197 additions and 35 deletions
|
@ -28,6 +28,7 @@ SOURCES += src/harbour-nextcloudnotes.cpp \
|
|||
|
||||
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
||||
qml/cover/CoverPage.qml \
|
||||
qml/pages/LoginWebView.qml \
|
||||
rpm/harbour-nextcloudnotes.changes.run.in \
|
||||
rpm/harbour-nextcloudnotes.changes \
|
||||
rpm/harbour-nextcloudnotes.spec \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
CoverBackground {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Configuration 1.0
|
||||
import Nemo.Notifications 1.0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Page {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Notifications 1.0
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Page {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Configuration 1.0
|
||||
|
||||
|
@ -12,7 +12,7 @@ Dialog {
|
|||
id: account
|
||||
path: "/apps/harbour-nextcloudnotes/accounts/" + accountId
|
||||
Component.onCompleted: {
|
||||
nameField.text = value("name", "", String)
|
||||
//nameField.text = value("name", "", String)
|
||||
serverField.text = value("server", "", String)
|
||||
usernameField.text = value("username", "", String)
|
||||
passwordField.text = value("password", "", String)
|
||||
|
@ -35,6 +35,7 @@ Dialog {
|
|||
}
|
||||
onRejected: {
|
||||
if (addingNew) appSettings.removeAccount(accountId)
|
||||
notesApi.host = value("server", "", String)
|
||||
}
|
||||
|
||||
SilicaFlickable {
|
||||
|
@ -61,6 +62,8 @@ Dialog {
|
|||
id: nameField
|
||||
width: parent.width
|
||||
//text: account.value("name", "", String)
|
||||
text: notesApi.statusProductName
|
||||
enabled: false
|
||||
placeholderText: qsTr("Account name")
|
||||
label: placeholderText
|
||||
errorHighlight: text.length === 0// && focus === true
|
||||
|
@ -84,6 +87,7 @@ Dialog {
|
|||
EnterKey.enabled: acceptableInput
|
||||
EnterKey.iconSource: "image://theme/icon-m-enter-next"
|
||||
EnterKey.onClicked: usernameField.focus = true
|
||||
onTextChanged: notesApi.host = text
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
@ -110,6 +114,12 @@ Dialog {
|
|||
EnterKey.iconSource: "image://theme/icon-m-enter-accept"
|
||||
EnterKey.onClicked: loginDialog.accept()
|
||||
}
|
||||
Button {
|
||||
id: loginButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Login")
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("LoginWebView.qml"), { server: serverField.text })
|
||||
}
|
||||
|
||||
SectionHeader {
|
||||
text: qsTr("Security")
|
||||
|
|
50
qml/pages/LoginWebView.qml
Normal file
50
qml/pages/LoginWebView.qml
Normal file
|
@ -0,0 +1,50 @@
|
|||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Page {
|
||||
id: loginWebView
|
||||
property string server
|
||||
property url ncurl: (account.allowUnecrypted ? "http://" : "https://") + server + "/index.php/login/flow"
|
||||
|
||||
Component.onCompleted: {
|
||||
var req = new XMLHttpRequest()
|
||||
req.open("GET", endpoint, true)
|
||||
req.setRequestHeader('User-Agent', 'SailfishOS/harbour-nextcloudnotes')
|
||||
req.setRequestHeader("OCS-APIREQUEST", "true")
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState === XMLHttpRequest.DONE) {
|
||||
if (req.status === 200) {
|
||||
ncFlowWebView.data = req.responseText
|
||||
}
|
||||
}
|
||||
}
|
||||
req.send()
|
||||
}
|
||||
|
||||
SilicaWebView {
|
||||
id: ncFlowWebView
|
||||
anchors.fill: parent
|
||||
|
||||
//url: ncurl
|
||||
//experimental.userAgent: "SailfishBrowser 1 - Sailfish" //"Mozilla/5.0 (U; Linux; Maemo; Jolla; Sailfish; like Android 4.3) " + "AppleWebKit/" + wkversion + " (KHTML, like Gecko) WebPirate/" + version + " like Mobile Safari/" + wkversion + " (compatible)"
|
||||
onNavigationRequested: {
|
||||
console.log(url)
|
||||
if (url.toString().indexOf("nc://login") === 0) {
|
||||
var credentials = url.split("/", 1)
|
||||
console.log(credentials)
|
||||
}
|
||||
}
|
||||
|
||||
header: PageHeader {
|
||||
title: ncFlowWebView.title
|
||||
description: loginWebView.ncurl
|
||||
BusyIndicator {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.horizontalPageMargin
|
||||
size: BusyIndicatorSize.Medium
|
||||
running: ncFlowWebView.loading
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Page {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import harbour.nextcloudnotes.notesmodel 1.0
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Configuration 1.0
|
||||
import Nemo.Notifications 1.0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Page {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick 2.2
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Dialog {
|
||||
|
|
|
@ -154,6 +154,17 @@ bool NotesApi::busy() const {
|
|||
return busy;
|
||||
}
|
||||
|
||||
void NotesApi::getStatus() {
|
||||
QUrl url = m_url;
|
||||
url.setPath("/status.php");
|
||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||
qDebug() << "POST" << url.toDisplayString();
|
||||
m_request.setUrl(url);
|
||||
m_status_replies << m_manager.post(m_request, QByteArray());
|
||||
emit busyChanged(busy());
|
||||
}
|
||||
}
|
||||
|
||||
void NotesApi::getAllNotes(QStringList excludeFields) {
|
||||
QUrl url = m_url;
|
||||
url.setPath(url.path() + "/notes");
|
||||
|
@ -230,6 +241,9 @@ void NotesApi::deleteNote(double noteId) {
|
|||
|
||||
void NotesApi::verifyUrl(QUrl url) {
|
||||
emit urlValidChanged(url.isValid());
|
||||
if (url.isValid()) {
|
||||
getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void NotesApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authenticator) {
|
||||
|
@ -243,7 +257,6 @@ void NotesApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authe
|
|||
|
||||
void NotesApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible) {
|
||||
m_online = accessible == QNetworkAccessManager::Accessible;
|
||||
//qDebug() << m_online;
|
||||
emit networkAccessibleChanged(m_online);
|
||||
}
|
||||
|
||||
|
@ -253,10 +266,17 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
|||
emit error(NoError);
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonDocument json = QJsonDocument::fromJson(data);
|
||||
if (mp_model) {
|
||||
if (mp_model->fromJsonDocument(json)) {
|
||||
m_lastSync = QDateTime::currentDateTimeUtc();
|
||||
emit lastSyncChanged(m_lastSync);
|
||||
if (m_status_replies.contains(reply)) {
|
||||
if (json.isObject()) {
|
||||
updateStatus(json.object());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mp_model) {
|
||||
if (mp_model->fromJsonDocument(json)) {
|
||||
m_lastSync = QDateTime::currentDateTimeUtc();
|
||||
emit lastSyncChanged(m_lastSync);
|
||||
}
|
||||
}
|
||||
}
|
||||
//qDebug() << data;
|
||||
|
@ -266,6 +286,7 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
|||
else
|
||||
emit error(CommunicationError);
|
||||
m_replies.removeAll(reply);
|
||||
m_status_replies.removeAll(reply);
|
||||
reply->deleteLater();
|
||||
emit busyChanged(busy());
|
||||
}
|
||||
|
@ -290,6 +311,48 @@ void NotesApi::saveToFile(QModelIndex, QModelIndex, QVector<int>) {
|
|||
emit error(LocalFileWriteError);
|
||||
}
|
||||
|
||||
void NotesApi::updateStatus(const QJsonObject &status) {
|
||||
if (!status.isEmpty()) {
|
||||
if (m_status_installed != status.value("installed").toBool()) {
|
||||
m_status_installed = status.value("installed").toBool();
|
||||
emit statusInstalledChanged(m_status_installed);
|
||||
}
|
||||
if (m_status_maintenance != status.value("maintenance").toBool()) {
|
||||
m_status_maintenance = status.value("maintenance").toBool();
|
||||
emit statusMaintenanceChanged(m_status_maintenance);
|
||||
}
|
||||
if (m_status_needsDbUpgrade != status.value("needsDbUpgrade").toBool()) {
|
||||
m_status_needsDbUpgrade = status.value("needsDbUpgrade").toBool();
|
||||
emit statusNeedsDbUpgradeChanged(m_status_needsDbUpgrade);
|
||||
}
|
||||
QStringList versionStr = status.value("version").toString().split('.');
|
||||
QVector<int> version;
|
||||
for(int i = 0; i < versionStr.size(); ++i)
|
||||
version << versionStr[i].toInt();
|
||||
if (m_status_version != version) {
|
||||
m_status_version = version;
|
||||
emit statusVersionChanged(m_status_version);
|
||||
}
|
||||
if (m_status_versionstring != status.value("versionstring").toString()) {
|
||||
m_status_versionstring = status.value("versionstring").toString();
|
||||
emit statusVersionStringChanged(m_status_versionstring);
|
||||
}
|
||||
if (m_status_edition != status.value("edition").toString()) {
|
||||
m_status_edition = status.value("edition").toString();
|
||||
emit statusEditionChanged(m_status_edition);
|
||||
}
|
||||
if (m_status_productname != status.value("productname").toString()) {
|
||||
m_status_productname = status.value("productname").toString();
|
||||
qDebug() << m_status_productname;
|
||||
emit statusProductNameChanged(m_status_productname);
|
||||
}
|
||||
if (m_status_extendedSupport != status.value("extendedSupport").toBool()) {
|
||||
m_status_extendedSupport = status.value("extendedSupport").toBool();
|
||||
emit statusExtendedSupportChanged(m_status_extendedSupport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QString NotesApi::errorMessage(int error) const {
|
||||
QString message;
|
||||
switch (error) {
|
||||
|
|
|
@ -67,6 +67,24 @@ public:
|
|||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||
bool busy() const;
|
||||
|
||||
Q_PROPERTY(bool statusInstalled READ statusInstalled NOTIFY statusInstalledChanged)
|
||||
bool statusInstalled() const { return m_status_installed; }
|
||||
Q_PROPERTY(bool statusMaintenance READ statusMaintenance NOTIFY statusMaintenanceChanged)
|
||||
bool statusMaintenance() const { return m_status_maintenance; }
|
||||
Q_PROPERTY(bool statusNeedsDbUpgrade READ statusNeedsDbUpgrade NOTIFY statusNeedsDbUpgradeChanged)
|
||||
bool statusNeedsDbUpgrade() const { return m_status_needsDbUpgrade; }
|
||||
Q_PROPERTY(QVector<int> statusVersion READ statusVersion NOTIFY statusVersionChanged)
|
||||
QVector<int> statusVersion() const { return m_status_version; }
|
||||
Q_PROPERTY(QString statusVersionString READ statusVersionString NOTIFY statusVersionStringChanged)
|
||||
QString statusVersionString() const { return m_status_versionstring; }
|
||||
Q_PROPERTY(QString statusEdition READ statusEdition NOTIFY statusEditionChanged)
|
||||
QString statusEdition() const { return m_status_edition; }
|
||||
Q_PROPERTY(QString statusProductName READ statusProductName NOTIFY statusProductNameChanged)
|
||||
QString statusProductName() const { return m_status_productname; }
|
||||
Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged)
|
||||
bool statusExtendedSupport() const { return m_status_extendedSupport; }
|
||||
|
||||
Q_INVOKABLE void getStatus();
|
||||
Q_INVOKABLE void getAllNotes(QStringList excludeFields = QStringList());
|
||||
Q_INVOKABLE void getNote(double noteId, QStringList excludeFields = QStringList());
|
||||
Q_INVOKABLE void createNote(QVariantMap fields = QVariantMap());
|
||||
|
@ -100,6 +118,14 @@ signals:
|
|||
void lastSyncChanged(QDateTime lastSync);
|
||||
void readyChanged(bool ready);
|
||||
void busyChanged(bool busy);
|
||||
void statusInstalledChanged(bool installed);
|
||||
void statusMaintenanceChanged(bool maintenance);
|
||||
void statusNeedsDbUpgradeChanged(bool needsDbUpgrade);
|
||||
void statusVersionChanged(QVector<int> version);
|
||||
void statusVersionStringChanged(QString versionString);
|
||||
void statusEditionChanged(QString edition);
|
||||
void statusProductNameChanged(QString productName);
|
||||
void statusExtendedSupportChanged(bool extendedSupport);
|
||||
void error(int error);
|
||||
|
||||
public slots:
|
||||
|
@ -122,6 +148,17 @@ private:
|
|||
QFile m_jsonFile;
|
||||
NotesModel* mp_model;
|
||||
NotesProxyModel* mp_modelProxy;
|
||||
|
||||
void updateStatus(const QJsonObject &status);
|
||||
QVector<QNetworkReply*> m_status_replies;
|
||||
bool m_status_installed;
|
||||
bool m_status_maintenance;
|
||||
bool m_status_needsDbUpgrade;
|
||||
QVector<int> m_status_version;
|
||||
QString m_status_versionstring;
|
||||
QString m_status_edition;
|
||||
QString m_status_productname;
|
||||
bool m_status_extendedSupport;
|
||||
};
|
||||
|
||||
#endif // NOTESAPI_H
|
||||
|
|
|
@ -125,57 +125,58 @@
|
|||
<context>
|
||||
<name>LoginDialog</name>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="50"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="51"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="120"/>
|
||||
<source>Login</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="50"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="51"/>
|
||||
<source>Save</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="64"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="67"/>
|
||||
<source>Account name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="79"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="82"/>
|
||||
<source>Nextcloud server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="93"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="97"/>
|
||||
<source>Username</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="106"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="110"/>
|
||||
<source>Password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="115"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="125"/>
|
||||
<source>Security</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="122"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="132"/>
|
||||
<source><strong>CAUTION: Your password will be saved without any encryption on the device!</strong><br>Please consider creating a dedicated app password! Open your Nextcloud in a browser and go to <i>Settings</i> → <i>Security</i>.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="126"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="136"/>
|
||||
<source>Do not check certificates</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="127"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="137"/>
|
||||
<source>Enable this option to allow selfsigned certificates</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="133"/>
|
||||
<location filename="../qml/pages/LoginDialog.qml" line="143"/>
|
||||
<source>Allow unencrypted connections</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -262,37 +263,37 @@
|
|||
<context>
|
||||
<name>NotesApi</name>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="299"/>
|
||||
<location filename="../src/notesapi.cpp" line="362"/>
|
||||
<source>No network connection available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="302"/>
|
||||
<location filename="../src/notesapi.cpp" line="365"/>
|
||||
<source>Failed to communicate with the Nextcloud server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="305"/>
|
||||
<location filename="../src/notesapi.cpp" line="368"/>
|
||||
<source>An error happened while reading from the local storage</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="308"/>
|
||||
<location filename="../src/notesapi.cpp" line="371"/>
|
||||
<source>An error happened while writing to the local storage</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="311"/>
|
||||
<location filename="../src/notesapi.cpp" line="374"/>
|
||||
<source>An error occured while establishing an encrypted connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="314"/>
|
||||
<location filename="../src/notesapi.cpp" line="377"/>
|
||||
<source>Could not authenticate to the Nextcloud instance</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notesapi.cpp" line="317"/>
|
||||
<location filename="../src/notesapi.cpp" line="380"/>
|
||||
<source>Unknown error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
Loading…
Reference in a new issue