Worked on Nextcloud API capabilities (not tested\!)
This commit is contained in:
parent
7e1cc5cf1e
commit
e44af7ec7a
15 changed files with 164 additions and 73 deletions
|
@ -30,13 +30,10 @@ ApplicationWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
onSortByChanged: {
|
onSortByChanged: {
|
||||||
if (sortBy == "none")
|
if (sortBy == "none") notesModel.invalidate()
|
||||||
notesProxyModel.invalidate()
|
|
||||||
else
|
|
||||||
notesProxyModel.sortRole = notesModel.roleFromName(sortBy)
|
|
||||||
}
|
}
|
||||||
onFavoritesOnTopChanged: {
|
onFavoritesOnTopChanged: {
|
||||||
notesProxyModel.favoritesOnTop = favoritesOnTop
|
notesModel.favoritesOnTop = favoritesOnTop
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccount(username, password, url, name) {
|
function createAccount(username, password, url, name) {
|
||||||
|
@ -138,7 +135,7 @@ ApplicationWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
Nextcloud {
|
Nextcloud {
|
||||||
id: nextcloud
|
id: notesApi
|
||||||
server: account.url
|
server: account.url
|
||||||
username: account.username
|
username: account.username
|
||||||
password: account.passowrd
|
password: account.passowrd
|
||||||
|
@ -155,5 +152,6 @@ ApplicationWindow
|
||||||
|
|
||||||
initialPage: Component { NotesPage { } }
|
initialPage: Component { NotesPage { } }
|
||||||
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
||||||
allowedOrientations: defaultAllowedOrientations
|
|
||||||
|
allowedOrientations: debug ? Orientation.All : defaultAllowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,5 +89,5 @@ Page {
|
||||||
VerticalScrollDecorator {}
|
VerticalScrollDecorator {}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,5 +179,5 @@ Dialog {
|
||||||
VerticalScrollDecorator {}
|
VerticalScrollDecorator {}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,5 +111,5 @@ NO WARRANTY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
import Nemo.Configuration 1.0
|
import Nemo.Configuration 1.0
|
||||||
import NextcloudNotes 1.0
|
import NextcloudApi 1.0
|
||||||
|
|
||||||
Dialog {
|
Dialog {
|
||||||
id: loginDialog
|
id: loginDialog
|
||||||
|
@ -308,5 +308,5 @@ Dialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,5 +44,5 @@ SOFTWARE.</p>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,5 +261,5 @@ Dialog {
|
||||||
VerticalScrollDecorator {}
|
VerticalScrollDecorator {}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ Page {
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: notesApi.networkAccessible && !notesApi.busy ? qsTr("Reload") : qsTr("Updating...")
|
text: notesApi.networkAccessible && !notesApi.busy ? qsTr("Reload") : qsTr("Updating...")
|
||||||
enabled: account !== null && notesApi.networkAccessible && !notesApi.busy
|
enabled: account !== null && notesApi.networkAccessible && !notesApi.busy
|
||||||
onClicked: notes.getAllNotes()
|
onClicked: notesApi.getAllNotes()
|
||||||
}
|
}
|
||||||
MenuLabel {
|
MenuLabel {
|
||||||
visible: account !== null
|
visible: account !== null
|
||||||
|
@ -59,7 +59,7 @@ Page {
|
||||||
EnterKey.iconSource: "image://theme/icon-m-enter-close"
|
EnterKey.iconSource: "image://theme/icon-m-enter-close"
|
||||||
EnterKey.onClicked: focus = false
|
EnterKey.onClicked: focus = false
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
notesProxyModel.searchFilter = text
|
notesModel.searchFilter = text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
|
@ -84,7 +84,7 @@ Page {
|
||||||
|
|
||||||
currentIndex: -1
|
currentIndex: -1
|
||||||
|
|
||||||
model: notesProxyModel
|
model: notesModel
|
||||||
|
|
||||||
delegate: BackgroundItem {
|
delegate: BackgroundItem {
|
||||||
id: note
|
id: note
|
||||||
|
@ -238,7 +238,7 @@ Page {
|
||||||
|
|
||||||
ViewPlaceholder {
|
ViewPlaceholder {
|
||||||
id: noSearchPlaceholder
|
id: noSearchPlaceholder
|
||||||
enabled: notesList.count === 0 && notesProxyModel.searchFilter !== "" //notesProxyModel.filterRegExp !== ""
|
enabled: notesList.count === 0 && notesModel.searchFilter !== "" //notesModel.filterRegExp !== ""
|
||||||
text: qsTr("No result")
|
text: qsTr("No result")
|
||||||
hintText: qsTr("Try another query")
|
hintText: qsTr("Try another query")
|
||||||
}
|
}
|
||||||
|
@ -266,5 +266,5 @@ Page {
|
||||||
VerticalScrollDecorator { flickable: notesList }
|
VerticalScrollDecorator { flickable: notesList }
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,5 +231,5 @@ Page {
|
||||||
VerticalScrollDecorator {}
|
VerticalScrollDecorator {}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,5 +394,5 @@ Use <b>HTML</b> <i>Tags</i> to format your text."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,5 +39,5 @@ Dialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: appWindow.allowedOrientations
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
qDebug() << app->applicationDisplayName() << app->applicationVersion();
|
qDebug() << app->applicationDisplayName() << app->applicationVersion();
|
||||||
|
|
||||||
|
NotesProxyModel* notesProxyModel = new NotesProxyModel;
|
||||||
AccountHash* accountHash = new AccountHash;
|
AccountHash* accountHash = new AccountHash;
|
||||||
qmlRegisterType<NextcloudApi>("NextcloudApi", 1, 0, "Nextcloud");
|
qmlRegisterType<NextcloudApi>("NextcloudApi", 1, 0, "Nextcloud");
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ int main(int argc, char *argv[])
|
||||||
#else
|
#else
|
||||||
view->rootContext()->setContextProperty("debug", QVariant(false));
|
view->rootContext()->setContextProperty("debug", QVariant(false));
|
||||||
#endif
|
#endif
|
||||||
|
view->rootContext()->setContextProperty("notesModel", notesProxyModel);
|
||||||
view->rootContext()->setContextProperty("accountHash", accountHash);
|
view->rootContext()->setContextProperty("accountHash", accountHash);
|
||||||
|
|
||||||
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
|
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
|
||||||
|
|
|
@ -15,6 +15,9 @@ NextcloudApi::NextcloudApi(QObject *parent) : QObject(parent)
|
||||||
m_status_needsDbUpgrade = false;
|
m_status_needsDbUpgrade = false;
|
||||||
m_status_extendedSupport = false;
|
m_status_extendedSupport = false;
|
||||||
|
|
||||||
|
// Add capabilities functions for server apps
|
||||||
|
m_appCapabilities["notes"] = &NextcloudApi::updateNoteCapabilities;
|
||||||
|
|
||||||
// Login Flow V2 poll timer
|
// Login Flow V2 poll timer
|
||||||
m_loginPollTimer.setInterval(LOGIN_FLOWV2_POLL_INTERVALL);
|
m_loginPollTimer.setInterval(LOGIN_FLOWV2_POLL_INTERVALL);
|
||||||
connect(&m_loginPollTimer, SIGNAL(timeout()), this, SLOT(pollLoginUrl()));
|
connect(&m_loginPollTimer, SIGNAL(timeout()), this, SLOT(pollLoginUrl()));
|
||||||
|
@ -118,6 +121,15 @@ void NextcloudApi::setPort(int port) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NextcloudApi::setPath(QString path) {
|
||||||
|
if (path != m_url.path()) {
|
||||||
|
m_url.setPath(path);
|
||||||
|
emit pathChanged(m_url.path());
|
||||||
|
emit serverChanged(server());
|
||||||
|
emit urlChanged(m_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NextcloudApi::setUsername(QString username) {
|
void NextcloudApi::setUsername(QString username) {
|
||||||
if (username != m_url.userName()) {
|
if (username != m_url.userName()) {
|
||||||
m_url.setUserName(username);
|
m_url.setUserName(username);
|
||||||
|
@ -142,13 +154,23 @@ void NextcloudApi::setPassword(QString password) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NextcloudApi::setPath(QString path) {
|
bool NextcloudApi::notesAppInstalled() const {
|
||||||
if (path != m_url.path()) {
|
QJsonObject notes = m_capabilities.value("notes").toObject();
|
||||||
m_url.setPath(path);
|
return !notes.isEmpty();
|
||||||
emit pathChanged(m_url.path());
|
}
|
||||||
emit serverChanged(server());
|
|
||||||
emit urlChanged(m_url);
|
QStringList NextcloudApi::notesAppApiVersions() const {
|
||||||
|
QStringList versions;
|
||||||
|
QJsonObject notes = m_capabilities.value("notes").toObject();
|
||||||
|
if (!notes.isEmpty()) {
|
||||||
|
QJsonArray apiVersion = notes.value("api_version").toArray();
|
||||||
|
QJsonArray::const_iterator i;
|
||||||
|
for (i = apiVersion.constBegin(); i != apiVersion.constEnd(); ++i) {
|
||||||
|
if (i->isString())
|
||||||
|
versions << i->toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return versions;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString NextcloudApi::errorMessage(int error) const {
|
const QString NextcloudApi::errorMessage(int error) const {
|
||||||
|
@ -288,6 +310,18 @@ bool NextcloudApi::deleteAppPassword() {
|
||||||
return del(DEL_APPPASSWORD_ENDPOINT, true);
|
return del(DEL_APPPASSWORD_ENDPOINT, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NextcloudApi::getUserList() {
|
||||||
|
return false; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NextcloudApi::getUserMetaData(const QString& user) {
|
||||||
|
return false; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NextcloudApi::getCapabilities() {
|
||||||
|
return false; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
void NextcloudApi::verifyUrl(QUrl url) {
|
void NextcloudApi::verifyUrl(QUrl url) {
|
||||||
emit urlValidChanged(
|
emit urlValidChanged(
|
||||||
url.isValid()&&
|
url.isValid()&&
|
||||||
|
@ -608,9 +642,53 @@ void NextcloudApi::setUserMetaStatus(ApiCallStatus status, bool *changed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NextcloudApi::updateCapabilities(const QJsonObject &json) {
|
bool NextcloudApi::updateCapabilities(const QJsonObject &json) {
|
||||||
|
QJsonObject ocs = json.value("ocs").toObject();
|
||||||
|
QJsonObject data = ocs.value("data").toObject();
|
||||||
|
QJsonObject preCapabilities = m_capabilities;
|
||||||
|
QJsonObject newCapabilities = data.value("capabilities").toObject();
|
||||||
|
if (!newCapabilities.isEmpty()) {
|
||||||
|
setCababilitiesStatus(ApiSuccess);
|
||||||
|
if (newCapabilities != preCapabilities) {
|
||||||
|
m_capabilities = newCapabilities;
|
||||||
|
|
||||||
|
QStringList apps = newCapabilities.keys();
|
||||||
|
QStringList::const_iterator app;
|
||||||
|
for (app = apps.constBegin(); app != apps.constEnd(); ++app) {
|
||||||
|
if (m_appCapabilities.contains(*app)) {
|
||||||
|
qDebug() << "Updating \"" << *app << "\" capabilities";
|
||||||
|
(this->*m_appCapabilities[*app])(newCapabilities.value(*app).toObject(), preCapabilities.value(*app).toObject());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "Capabilities for " << *app << " not implemented!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
setCababilitiesStatus(ApiFailed);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextcloudApi::updateNoteCapabilities(const QJsonObject &newObject, const QJsonObject &preObject) {
|
||||||
|
qDebug() << "Updating \"notes\" capabilities";
|
||||||
|
if (newObject.isEmpty() != preObject.isEmpty())
|
||||||
|
emit notesAppInstalledChanged(notesAppInstalled());
|
||||||
|
|
||||||
|
QStringList preVersions;
|
||||||
|
QJsonArray preApiVersion = preObject.value("api_version").toArray();
|
||||||
|
QJsonArray::const_iterator i;
|
||||||
|
for (i = preApiVersion.constBegin(); i != preApiVersion.constEnd(); ++i) {
|
||||||
|
if (i->isString())
|
||||||
|
preVersions << i->toString();
|
||||||
|
}
|
||||||
|
if (preVersions != notesAppApiVersions())
|
||||||
|
emit notesAppApiVersionsChanged(notesAppApiVersions());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NextcloudApi::setCababilitiesStatus(ApiCallStatus status, bool *changed) {
|
void NextcloudApi::setCababilitiesStatus(ApiCallStatus status, bool *changed) {
|
||||||
|
if (status != m_capabilitiesStatus) {
|
||||||
|
m_capabilitiesStatus = status;
|
||||||
|
if (changed) *changed = true;
|
||||||
|
emit capabilitiesStatusChanged(m_capabilitiesStatus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,24 @@
|
||||||
// Nextcloud instance information
|
// Nextcloud instance information
|
||||||
const QString STATUS_ENDPOINT("/status.php");
|
const QString STATUS_ENDPOINT("/status.php");
|
||||||
|
|
||||||
// Capabilites and users
|
// OCS APIs endpoints
|
||||||
|
// https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html
|
||||||
const QString CAPABILITIES_ENDPOINT("/ocs/v2.php/cloud/capabilities");
|
const QString CAPABILITIES_ENDPOINT("/ocs/v2.php/cloud/capabilities");
|
||||||
const QString LIST_USERS_ENDPOINT("/ocs/v2.php/cloud/users");
|
const QString LIST_USERS_ENDPOINT("/ocs/v2.php/cloud/users");
|
||||||
const QString USER_METADATA_ENDPOINT("/ocs/v2.php/cloud/users/%1");
|
const QString USER_METADATA_ENDPOINT("/ocs/v2.php/cloud/users/%1");
|
||||||
const QString USER_NOTIFICATION_ENDPOINT("/ocs/v2.php/cloud/capabilities");
|
const QString USER_NOTIFICATION_ENDPOINT("/ocs/v2.php/apps/notifications/api/v2/notifications");
|
||||||
|
const QString DIRECT_DOWNLOAD_ENDPOINT("/ocs/v2.php/apps/dav/api/v1/direct");
|
||||||
|
|
||||||
// Login and authentication
|
// Login Flow endpoints
|
||||||
|
// https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html
|
||||||
const QString GET_APPPASSWORD_ENDPOINT("/ocs/v2.php/core/getapppassword");
|
const QString GET_APPPASSWORD_ENDPOINT("/ocs/v2.php/core/getapppassword");
|
||||||
const QString DEL_APPPASSWORD_ENDPOINT("/ocs/v2.php/core/apppassword");
|
const QString DEL_APPPASSWORD_ENDPOINT("/ocs/v2.php/core/apppassword");
|
||||||
const QString LOGIN_FLOWV2_ENDPOINT("/index.php/login/v2");
|
const QString LOGIN_FLOWV2_ENDPOINT("/index.php/login/v2");
|
||||||
const int LOGIN_FLOWV2_MIN_VERSION = 16;
|
const int LOGIN_FLOWV2_MIN_VERSION = 16;
|
||||||
const int LOGIN_FLOWV2_POLL_INTERVALL = 5000;
|
const int LOGIN_FLOWV2_POLL_INTERVALL = 5000;
|
||||||
|
|
||||||
// Diredct Download
|
class NextcloudApi;
|
||||||
const QString DIRECT_DOWNLOAD_ENDPOINT("/ocs/v2.php/apps/dav/api/v1/direct");
|
typedef void (NextcloudApi::*updateAppCapabilities)(const QJsonObject &newObject, const QJsonObject &preObject);
|
||||||
|
|
||||||
class NextcloudApi : public QObject
|
class NextcloudApi : public QObject
|
||||||
{
|
{
|
||||||
|
@ -38,9 +41,9 @@ class NextcloudApi : public QObject
|
||||||
|
|
||||||
// Generic API properties
|
// Generic API properties
|
||||||
Q_PROPERTY(bool verifySsl READ verifySsl WRITE setVerifySsl NOTIFY verifySslChanged) // to allow selfsigned certificates
|
Q_PROPERTY(bool verifySsl READ verifySsl WRITE setVerifySsl NOTIFY verifySslChanged) // to allow selfsigned certificates
|
||||||
Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) // complete API URL = <scheme>://<username>:<password>@<host>[:<port>]/<path>
|
Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) // complete nextcloud URL = <scheme>://<username>:<password>@<host>[:<port>]/<path>
|
||||||
Q_PROPERTY(QString server READ server WRITE setServer NOTIFY serverChanged) // url without username and password = <scheme>://<host>[:<port>]/<path>
|
Q_PROPERTY(QString server READ server WRITE setServer NOTIFY serverChanged) // url without username and password = <scheme>://<host>[:<port>]/<path>
|
||||||
// the following six properties will update the url and server properties and vice versa
|
// the following properties will update the url and server properties and vice versa
|
||||||
Q_PROPERTY(QString scheme READ scheme WRITE setScheme NOTIFY schemeChanged)
|
Q_PROPERTY(QString scheme READ scheme WRITE setScheme NOTIFY schemeChanged)
|
||||||
Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged)
|
Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged)
|
||||||
Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged)
|
Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged)
|
||||||
|
@ -49,10 +52,10 @@ class NextcloudApi : public QObject
|
||||||
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
|
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
|
||||||
|
|
||||||
// Networking status information
|
// Networking status information
|
||||||
Q_PROPERTY(bool ready READ ready NOTIFY readyChanged)
|
Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) // when all needed properties are set
|
||||||
Q_PROPERTY(bool urlValid READ urlValid NOTIFY urlValidChanged)
|
Q_PROPERTY(bool urlValid READ urlValid NOTIFY urlValidChanged) // if the property url is valid
|
||||||
Q_PROPERTY(bool networkAccessible READ networkAccessible NOTIFY networkAccessibleChanged)
|
Q_PROPERTY(bool networkAccessible READ networkAccessible NOTIFY networkAccessibleChanged) // when the device has connectivity
|
||||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) // when an API call is currently running
|
||||||
|
|
||||||
// Nextcloud status (status.php), these properties will be automatically updated on changes of the generic properties
|
// Nextcloud status (status.php), these properties will be automatically updated on changes of the generic properties
|
||||||
Q_PROPERTY(ApiCallStatus statusStatus READ statusStatus NOTIFY statusStatusChanged)
|
Q_PROPERTY(ApiCallStatus statusStatus READ statusStatus NOTIFY statusStatusChanged)
|
||||||
|
@ -66,17 +69,21 @@ class NextcloudApi : public QObject
|
||||||
Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged)
|
Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged)
|
||||||
|
|
||||||
// Login status
|
// Login status
|
||||||
|
Q_PROPERTY(LoginStatus loginStatus READ loginStatus NOTIFY loginStatusChanged)
|
||||||
Q_PROPERTY(bool loginFlowV2Possible READ loginFlowV2Possible NOTIFY loginFlowV2PossibleChanged)
|
Q_PROPERTY(bool loginFlowV2Possible READ loginFlowV2Possible NOTIFY loginFlowV2PossibleChanged)
|
||||||
Q_PROPERTY(QUrl loginUrl READ loginUrl NOTIFY loginUrlChanged)
|
Q_PROPERTY(QUrl loginUrl READ loginUrl NOTIFY loginUrlChanged) // will be set after initiateFlowV2Login() has been called. The URL needs to be opened in a browser or webview
|
||||||
Q_PROPERTY(ApiCallStatus loginStatus READ loginStatus NOTIFY loginStatusChanged)
|
|
||||||
|
|
||||||
// User(s) status
|
// User(s) status
|
||||||
Q_PROPERTY(ApiCallStatus userListStatus READ userListStatus NOTIFY userListStatusChanged)
|
Q_PROPERTY(ApiCallStatus userListStatus READ userListStatus NOTIFY userListStatusChanged)
|
||||||
Q_PROPERTY(QStringList userList READ userList NOTIFY userListChanged)
|
|
||||||
Q_PROPERTY(ApiCallStatus userMetaStatus READ userMetaStatus NOTIFY userMetaStatusChanged)
|
Q_PROPERTY(ApiCallStatus userMetaStatus READ userMetaStatus NOTIFY userMetaStatusChanged)
|
||||||
|
Q_PROPERTY(QStringList userList READ userList NOTIFY userListChanged)
|
||||||
|
// TODO property for user metadata
|
||||||
|
|
||||||
// Nextcloud capabilities
|
// Nextcloud capabilities
|
||||||
Q_PROPERTY(ApiCallStatus capabilitiesStatus READ capabilitiesStatus NOTIFY capabilitiesStatusChanged)
|
Q_PROPERTY(ApiCallStatus capabilitiesStatus READ capabilitiesStatus NOTIFY capabilitiesStatusChanged)
|
||||||
|
Q_PROPERTY(bool notesAppInstalled READ notesAppInstalled NOTIFY notesAppInstalledChanged)
|
||||||
|
Q_PROPERTY(QStringList notesAppApiVersions READ notesAppApiVersions NOTIFY notesAppApiVersionsChanged)
|
||||||
|
// TODO other property for server capabilities
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit NextcloudApi(QObject *parent = nullptr);
|
explicit NextcloudApi(QObject *parent = nullptr);
|
||||||
|
@ -148,17 +155,19 @@ public:
|
||||||
bool statusExtendedSupport() const { return m_status_extendedSupport; }
|
bool statusExtendedSupport() const { return m_status_extendedSupport; }
|
||||||
|
|
||||||
// Login status
|
// Login status
|
||||||
|
LoginStatus loginStatus() const { return m_loginStatus; }
|
||||||
bool loginFlowV2Possible() const { return QVersionNumber::fromString(statusVersion()) >= QVersionNumber(LOGIN_FLOWV2_MIN_VERSION); }
|
bool loginFlowV2Possible() const { return QVersionNumber::fromString(statusVersion()) >= QVersionNumber(LOGIN_FLOWV2_MIN_VERSION); }
|
||||||
QUrl loginUrl() const { return m_loginUrl; }
|
QUrl loginUrl() const { return m_loginUrl; }
|
||||||
LoginStatus loginStatus() const { return m_loginStatus; }
|
|
||||||
|
|
||||||
// User(s) status
|
// User(s) status
|
||||||
ApiCallStatus userListStatus() const { return m_userListStatus; }
|
ApiCallStatus userListStatus() const { return m_userListStatus; }
|
||||||
QStringList userList() const { return m_userList; }
|
|
||||||
ApiCallStatus userMetaStatus() const { return m_userMetaStatus; }
|
ApiCallStatus userMetaStatus() const { return m_userMetaStatus; }
|
||||||
|
QStringList userList() const { return m_userList; }
|
||||||
|
|
||||||
// Nextcloud capabilities
|
// Nextcloud capabilities
|
||||||
ApiCallStatus capabilitiesStatus() const { return m_capabilitiesStatus; }
|
ApiCallStatus capabilitiesStatus() const { return m_capabilitiesStatus; }
|
||||||
|
bool notesAppInstalled() const;
|
||||||
|
QStringList notesAppApiVersions() const;
|
||||||
|
|
||||||
enum ErrorCodes {
|
enum ErrorCodes {
|
||||||
NoError,
|
NoError,
|
||||||
|
@ -229,6 +238,8 @@ signals:
|
||||||
|
|
||||||
// Nextcloud capabilities
|
// Nextcloud capabilities
|
||||||
void capabilitiesStatusChanged(ApiCallStatus status);
|
void capabilitiesStatusChanged(ApiCallStatus status);
|
||||||
|
void notesAppInstalledChanged(bool installed);
|
||||||
|
void notesAppApiVersionsChanged(QStringList versions);
|
||||||
|
|
||||||
// API helper updates
|
// API helper updates
|
||||||
void getFinished(QNetworkReply* reply);
|
void getFinished(QNetworkReply* reply);
|
||||||
|
@ -265,11 +276,18 @@ private:
|
||||||
QString m_status_productname;
|
QString m_status_productname;
|
||||||
bool m_status_extendedSupport;
|
bool m_status_extendedSupport;
|
||||||
|
|
||||||
// Nextcloud capabilities
|
// Nextcloud Login Flow v2
|
||||||
bool updateCapabilities(const QJsonObject &json);
|
// https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2
|
||||||
void setCababilitiesStatus(ApiCallStatus status, bool *changed = NULL);
|
bool updateLoginFlow(const QJsonObject &json);
|
||||||
ApiCallStatus m_capabilitiesStatus;
|
bool updateLoginCredentials(const QJsonObject &json);
|
||||||
QJsonObject m_capabilities;
|
bool updateAppPassword(const QJsonObject &json);
|
||||||
|
bool deleteAppPassword(const QJsonObject &json);
|
||||||
|
void setLoginStatus(LoginStatus status, bool *changed = NULL);
|
||||||
|
LoginStatus m_loginStatus;
|
||||||
|
QTimer m_loginPollTimer;
|
||||||
|
QUrl m_loginUrl;
|
||||||
|
QUrl m_pollUrl;
|
||||||
|
QString m_pollToken;
|
||||||
|
|
||||||
// Nextcloud users list
|
// Nextcloud users list
|
||||||
bool updateUserList(const QJsonObject &json);
|
bool updateUserList(const QJsonObject &json);
|
||||||
|
@ -283,18 +301,13 @@ private:
|
||||||
ApiCallStatus m_userMetaStatus;
|
ApiCallStatus m_userMetaStatus;
|
||||||
QHash<QString, QJsonObject> m_userMeta;
|
QHash<QString, QJsonObject> m_userMeta;
|
||||||
|
|
||||||
// Nextcloud Login Flow v2
|
// Nextcloud capabilities
|
||||||
// https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2
|
bool updateCapabilities(const QJsonObject &json);
|
||||||
bool updateLoginFlow(const QJsonObject &json);
|
QMap<QString, updateAppCapabilities> m_appCapabilities;
|
||||||
bool updateLoginCredentials(const QJsonObject &json);
|
void updateNoteCapabilities(const QJsonObject &newObject, const QJsonObject &preObject = QJsonObject());
|
||||||
bool updateAppPassword(const QJsonObject &json);
|
void setCababilitiesStatus(ApiCallStatus status, bool *changed = NULL);
|
||||||
bool deleteAppPassword(const QJsonObject &json);
|
ApiCallStatus m_capabilitiesStatus;
|
||||||
void setLoginStatus(LoginStatus status, bool *changed = NULL);
|
QJsonObject m_capabilities;
|
||||||
LoginStatus m_loginStatus;
|
|
||||||
QTimer m_loginPollTimer;
|
|
||||||
QUrl m_loginUrl;
|
|
||||||
QUrl m_pollUrl;
|
|
||||||
QString m_pollToken;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NEXTCLOUDAPI_H
|
#endif // NEXTCLOUDAPI_H
|
||||||
|
|
|
@ -275,32 +275,32 @@
|
||||||
<context>
|
<context>
|
||||||
<name>NextcloudApi</name>
|
<name>NextcloudApi</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/nextcloudapi.cpp" line="157"/>
|
<location filename="../src/nextcloudapi.cpp" line="158"/>
|
||||||
<source>No error</source>
|
<source>No error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/nextcloudapi.cpp" line="160"/>
|
<location filename="../src/nextcloudapi.cpp" line="161"/>
|
||||||
<source>No network connection available</source>
|
<source>No network connection available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/nextcloudapi.cpp" line="163"/>
|
<location filename="../src/nextcloudapi.cpp" line="164"/>
|
||||||
<source>Failed to communicate with the Nextcloud server</source>
|
<source>Failed to communicate with the Nextcloud server</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/nextcloudapi.cpp" line="166"/>
|
<location filename="../src/nextcloudapi.cpp" line="167"/>
|
||||||
<source>An error occured while establishing an encrypted connection</source>
|
<source>An error occured while establishing an encrypted connection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/nextcloudapi.cpp" line="169"/>
|
<location filename="../src/nextcloudapi.cpp" line="170"/>
|
||||||
<source>Could not authenticate to the Nextcloud instance</source>
|
<source>Could not authenticate to the Nextcloud instance</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/nextcloudapi.cpp" line="172"/>
|
<location filename="../src/nextcloudapi.cpp" line="173"/>
|
||||||
<source>Unknown error</source>
|
<source>Unknown error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -912,27 +912,27 @@ You can also use other markdown syntax inside them.</source>
|
||||||
<context>
|
<context>
|
||||||
<name>harbour-nextcloudnotes</name>
|
<name>harbour-nextcloudnotes</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="101"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="98"/>
|
||||||
<source>Notes</source>
|
<source>Notes</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="102"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="99"/>
|
||||||
<source>Offline</source>
|
<source>Offline</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="103"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="100"/>
|
||||||
<source>Synced</source>
|
<source>Synced</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="117"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="114"/>
|
||||||
<source>API error</source>
|
<source>API error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="110"/>
|
<location filename="../qml/harbour-nextcloudnotes.qml" line="107"/>
|
||||||
<source>File error</source>
|
<source>File error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
Loading…
Reference in a new issue