Implemented Nextcloud Login Flow v2
This commit is contained in:
parent
ecebd90dcb
commit
2be8a2675d
9 changed files with 312 additions and 210 deletions
|
@ -28,7 +28,6 @@ SOURCES += src/harbour-nextcloudnotes.cpp \
|
||||||
|
|
||||||
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
||||||
qml/cover/CoverPage.qml \
|
qml/cover/CoverPage.qml \
|
||||||
qml/pages/LoginWebView.qml \
|
|
||||||
rpm/harbour-nextcloudnotes.changes.run.in \
|
rpm/harbour-nextcloudnotes.changes.run.in \
|
||||||
rpm/harbour-nextcloudnotes.changes \
|
rpm/harbour-nextcloudnotes.changes \
|
||||||
rpm/harbour-nextcloudnotes.spec \
|
rpm/harbour-nextcloudnotes.spec \
|
||||||
|
|
|
@ -131,7 +131,6 @@ ApplicationWindow
|
||||||
id: notesApi
|
id: notesApi
|
||||||
scheme: account.allowUnecrypted ? "http" : "https"
|
scheme: account.allowUnecrypted ? "http" : "https"
|
||||||
host: account.server
|
host: account.server
|
||||||
path: "/index.php/apps/notes/api/" + account.version
|
|
||||||
username: account.username
|
username: account.username
|
||||||
password: account.password
|
password: account.password
|
||||||
sslVerify: !account.doNotVerifySsl
|
sslVerify: !account.doNotVerifySsl
|
||||||
|
|
|
@ -31,15 +31,39 @@ Dialog {
|
||||||
account.setValue("unsecureConnection", unsecureConnectionTextSwitch.checked)
|
account.setValue("unsecureConnection", unsecureConnectionTextSwitch.checked)
|
||||||
account.setValue("unencryptedConnection", unencryptedConnectionTextSwitch.checked)
|
account.setValue("unencryptedConnection", unencryptedConnectionTextSwitch.checked)
|
||||||
account.sync()
|
account.sync()
|
||||||
api.uuid = accountId
|
|
||||||
}
|
}
|
||||||
onRejected: {
|
onRejected: {
|
||||||
if (addingNew) appSettings.removeAccount(accountId)
|
if (addingNew) appSettings.removeAccount(accountId)
|
||||||
notesApi.host = value("server", "", String)
|
notesApi.host = account.value("server", "", String)
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Connections {
|
||||||
id: loginPollTimer
|
target: notesApi
|
||||||
|
onStatusVersionChanged: {
|
||||||
|
for (var i = 0; i < notesApi.version.length; ++i) {
|
||||||
|
console.log(notesApi.version[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onLoginUrlChanged: {
|
||||||
|
if (notesApi.loginUrl)
|
||||||
|
Qt.openUrlExternally(notesApi.loginUrl)
|
||||||
|
else {
|
||||||
|
pushed = true
|
||||||
|
//console.log("Login successfull")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onServerChanged: {
|
||||||
|
console.log("Login server: " + notesApi.server)
|
||||||
|
serverField.text = notesApi.server
|
||||||
|
}
|
||||||
|
onUsernameChanged: {
|
||||||
|
console.log("Login username: " + notesApi.username)
|
||||||
|
usernameField.text = notesApi.username
|
||||||
|
}
|
||||||
|
onPasswordChanged: {
|
||||||
|
console.log("Login password: " + notesApi.password)
|
||||||
|
passwordField.text = notesApi.password
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SilicaFlickable {
|
SilicaFlickable {
|
||||||
|
@ -62,6 +86,30 @@ Dialog {
|
||||||
source: "../img/nextcloud-logo-transparent.png"
|
source: "../img/nextcloud-logo-transparent.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: flowv2LoginColumn
|
||||||
|
width: parent.width
|
||||||
|
visible: notesApi.statusVersion.split('.')[0] >= 16
|
||||||
|
|
||||||
|
Label {
|
||||||
|
x: Theme.horizontalPageMargin
|
||||||
|
width: parent.width - 2*x
|
||||||
|
text: qsTr("Login Flow v2") + " " + notesApi.statusVersionString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: legacyLoginColumn
|
||||||
|
width: parent.width
|
||||||
|
visible: !flowv2LoginColumn.visible
|
||||||
|
|
||||||
|
Label {
|
||||||
|
x: Theme.horizontalPageMargin
|
||||||
|
width: parent.width - 2*x
|
||||||
|
text: qsTr("Legacy Login") + " " + notesApi.statusVersionString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: nameField
|
id: nameField
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -121,10 +169,23 @@ Dialog {
|
||||||
Button {
|
Button {
|
||||||
id: loginButton
|
id: loginButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
property bool pushed: false
|
||||||
text: qsTr("Login")
|
text: qsTr("Login")
|
||||||
|
enabled: !pushed
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
pushed = true
|
||||||
//pageStack.push(Qt.resolvedUrl("LoginWebView.qml"), { loginUrl: serverField.text })
|
loginTimeout.start()
|
||||||
|
notesApi.initiateFlowV2Login()
|
||||||
|
}
|
||||||
|
BusyIndicator {
|
||||||
|
id: loginBusyIndicator
|
||||||
|
anchors.centerIn: parent
|
||||||
|
running: loginButton.pushed
|
||||||
|
}
|
||||||
|
Timer {
|
||||||
|
id: loginTimeout
|
||||||
|
interval: 60000
|
||||||
|
onTriggered: loginButton.pushed = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import Sailfish.Silica 1.0
|
|
||||||
|
|
||||||
Page {
|
|
||||||
id: loginWebView
|
|
||||||
property url loginUrl
|
|
||||||
|
|
||||||
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: ncFlow2WebView
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
url: loginUrl
|
|
||||||
|
|
||||||
header: PageHeader {
|
|
||||||
title: ncFlow2WebView.title
|
|
||||||
description: url
|
|
||||||
BusyIndicator {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Theme.horizontalPageMargin
|
|
||||||
size: BusyIndicatorSize.Medium
|
|
||||||
running: ncFlow2WebView.loading
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
200
src/notesapi.cpp
200
src/notesapi.cpp
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
NotesApi::NotesApi(QObject *parent) : QObject(parent)
|
NotesApi::NotesApi(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
m_loginPollTimer.setInterval(1000);
|
||||||
|
connect(&m_loginPollTimer, SIGNAL(timeout()), this, SLOT(pollLoginUrl()));
|
||||||
m_online = m_manager.networkAccessible() == QNetworkAccessManager::Accessible;
|
m_online = m_manager.networkAccessible() == QNetworkAccessManager::Accessible;
|
||||||
mp_model = new NotesModel(this);
|
mp_model = new NotesModel(this);
|
||||||
mp_modelProxy = new NotesProxyModel(this);
|
mp_modelProxy = new NotesProxyModel(this);
|
||||||
|
@ -20,7 +22,7 @@ NotesApi::NotesApi(QObject *parent) : QObject(parent)
|
||||||
connect(&m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
|
connect(&m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
|
||||||
connect(&m_manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(sslError(QNetworkReply*,QList<QSslError>)));
|
connect(&m_manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(sslError(QNetworkReply*,QList<QSslError>)));
|
||||||
m_request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
|
m_request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
|
||||||
m_request.setHeader(QNetworkRequest::UserAgentHeader, QGuiApplication::applicationDisplayName() + " / " + QGuiApplication::applicationVersion());
|
m_request.setHeader(QNetworkRequest::UserAgentHeader, QGuiApplication::applicationDisplayName() + " " + QGuiApplication::applicationVersion() + " - " + QSysInfo::machineHostName());
|
||||||
m_request.setRawHeader("OCS-APIREQUEST", "true");
|
m_request.setRawHeader("OCS-APIREQUEST", "true");
|
||||||
m_request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json").toUtf8());
|
m_request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json").toUtf8());
|
||||||
connect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector<int>)));
|
connect(mp_model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(saveToFile(QModelIndex,QModelIndex,QVector<int>)));
|
||||||
|
@ -50,9 +52,11 @@ void NotesApi::setSslVerify(bool verify) {
|
||||||
void NotesApi::setUrl(QUrl url) {
|
void NotesApi::setUrl(QUrl url) {
|
||||||
if (url != m_url) {
|
if (url != m_url) {
|
||||||
QUrl oldUrl = m_url;
|
QUrl oldUrl = m_url;
|
||||||
bool oldReady = ready();
|
QString oldServer = server();
|
||||||
m_url = url;
|
m_url = url;
|
||||||
emit urlChanged(m_url);
|
emit urlChanged(m_url);
|
||||||
|
if (server() != oldServer)
|
||||||
|
emit serverChanged(server());
|
||||||
if (m_url.scheme() != oldUrl.scheme())
|
if (m_url.scheme() != oldUrl.scheme())
|
||||||
emit schemeChanged(m_url.scheme());
|
emit schemeChanged(m_url.scheme());
|
||||||
if (m_url.host() != oldUrl.host())
|
if (m_url.host() != oldUrl.host())
|
||||||
|
@ -65,13 +69,31 @@ void NotesApi::setUrl(QUrl url) {
|
||||||
emit passwordChanged(m_url.password());
|
emit passwordChanged(m_url.password());
|
||||||
if (m_url.path() != oldUrl.path())
|
if (m_url.path() != oldUrl.path())
|
||||||
emit pathChanged(m_url.path());
|
emit pathChanged(m_url.path());
|
||||||
if (ready() != oldReady)
|
|
||||||
emit readyChanged(ready());
|
|
||||||
if (m_url.isValid())
|
if (m_url.isValid())
|
||||||
qDebug() << "API URL:" << m_url.toDisplayString();
|
qDebug() << "API URL:" << m_url.toDisplayString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString NotesApi::server() const {
|
||||||
|
QUrl server;
|
||||||
|
server.setScheme(m_url.scheme());
|
||||||
|
server.setHost(m_url.host());
|
||||||
|
if (m_url.port() > 0)
|
||||||
|
server.setPort(m_url.port());
|
||||||
|
server.setPath(m_url.path());
|
||||||
|
return server.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesApi::setServer(QString serverUrl) {
|
||||||
|
QUrl url(serverUrl);
|
||||||
|
if (serverUrl != server()) {
|
||||||
|
setScheme(url.scheme());
|
||||||
|
setHost(url.host());
|
||||||
|
setPort(url.port());
|
||||||
|
setPath(url.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NotesApi::setScheme(QString scheme) {
|
void NotesApi::setScheme(QString scheme) {
|
||||||
if (scheme == "http" || scheme == "https") {
|
if (scheme == "http" || scheme == "https") {
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
|
@ -89,18 +111,18 @@ void NotesApi::setHost(QString host) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::setPort(int port) {
|
void NotesApi::setPort(int port) {
|
||||||
if (port >= -1 && port <= 65535) {
|
if (port >= 1 && port <= 65535) {
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
url.setPort(port);
|
url.setPort(port);
|
||||||
setUrl(url);
|
setUrl(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::setUsername(QString username) {
|
void NotesApi::setUsername(QString user) {
|
||||||
if (!username.isEmpty()) {
|
if (!user.isEmpty()) {
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
url.setUserName(username);
|
url.setUserName(user);
|
||||||
QString concatenated = username + ":" + password();
|
QString concatenated = user + ":" + password();
|
||||||
QByteArray data = concatenated.toLocal8Bit().toBase64();
|
QByteArray data = concatenated.toLocal8Bit().toBase64();
|
||||||
QString headerData = "Basic " + data;
|
QString headerData = "Basic " + data;
|
||||||
m_request.setRawHeader("Authorization", headerData.toLocal8Bit());
|
m_request.setRawHeader("Authorization", headerData.toLocal8Bit());
|
||||||
|
@ -138,18 +160,10 @@ void NotesApi::setDataFile(QString dataFile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesApi::ready() const {
|
|
||||||
return !m_url.scheme().isEmpty() &&
|
|
||||||
!m_url.userName().isEmpty() &&
|
|
||||||
!m_url.host().isEmpty() &&
|
|
||||||
!m_url.path().isEmpty() &&
|
|
||||||
!m_url.query().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NotesApi::busy() const {
|
bool NotesApi::busy() const {
|
||||||
bool busy = false;
|
bool busy = false;
|
||||||
QVector<QNetworkReply*> replies;
|
QVector<QNetworkReply*> replies;
|
||||||
replies << m_replies << m_status_replies << m_login_replies;
|
replies << m_replies << m_status_replies << m_login_replies << m_poll_replies;
|
||||||
for (int i = 0; i < replies.size(); ++i) {
|
for (int i = 0; i < replies.size(); ++i) {
|
||||||
busy |= replies[i]->isRunning();
|
busy |= replies[i]->isRunning();
|
||||||
}
|
}
|
||||||
|
@ -157,33 +171,46 @@ bool NotesApi::busy() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::getStatus() {
|
void NotesApi::getStatus() {
|
||||||
QUrl url = m_url;
|
QUrl url = server();
|
||||||
url.setPath("/index.php/login/v2");
|
QNetworkRequest request;
|
||||||
|
url.setPath(url.path() + "/status.php");
|
||||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "POST" << url.toDisplayString();
|
qDebug() << "POST" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
request.setUrl(url);
|
||||||
m_login_replies << m_manager.post(m_request, QByteArray());
|
m_status_replies << m_manager.post(request, QByteArray());
|
||||||
emit busyChanged(busy());
|
emit busyChanged(busy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::initiateFlowV2Login() {
|
void NotesApi::initiateFlowV2Login() {
|
||||||
QUrl url = m_url;
|
QUrl url = server();
|
||||||
url.setPath("/status.php");
|
url.setPath(url.path() + "/index.php/login/v2");
|
||||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "POST" << url.toDisplayString();
|
qDebug() << "POST" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
m_request.setUrl(url);
|
||||||
m_status_replies << m_manager.post(m_request, QByteArray());
|
m_login_replies << m_manager.post(m_request, QByteArray());
|
||||||
|
m_loginPollTimer.start();
|
||||||
|
emit busyChanged(busy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotesApi::pollLoginUrl() {
|
||||||
|
//QNetworkRequest request;
|
||||||
|
//request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded").toUtf8());
|
||||||
|
if (m_pollUrl.isValid() && !m_pollUrl.scheme().isEmpty() && !m_pollUrl.host().isEmpty() && !m_pollToken.isEmpty()) {
|
||||||
|
//qDebug() << "POST" << m_pollUrl.toDisplayString();
|
||||||
|
m_request.setUrl(m_pollUrl);
|
||||||
|
m_poll_replies << m_manager.post(m_request, QByteArray("token=").append(m_pollToken));
|
||||||
emit busyChanged(busy());
|
emit busyChanged(busy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::getAllNotes(QStringList excludeFields) {
|
void NotesApi::getAllNotes(QStringList excludeFields) {
|
||||||
QUrl url = m_url;
|
QUrl url = server();
|
||||||
url.setPath(url.path() + "/notes");
|
url.setPath(url.path() + "/index.php/apps/notes/api/v0.2" + "/notes");
|
||||||
if (!excludeFields.isEmpty())
|
if (!excludeFields.isEmpty())
|
||||||
url.setQuery(QString("exclude=").append(excludeFields.join(",")));
|
url.setQuery(QString("exclude=").append(excludeFields.join(",")));
|
||||||
if (url.isValid()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "GET" << url.toDisplayString();
|
qDebug() << "GET" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
m_request.setUrl(url);
|
||||||
m_replies << m_manager.get(m_request);
|
m_replies << m_manager.get(m_request);
|
||||||
|
@ -193,10 +220,10 @@ void NotesApi::getAllNotes(QStringList excludeFields) {
|
||||||
|
|
||||||
void NotesApi::getNote(double noteId, QStringList excludeFields) {
|
void NotesApi::getNote(double noteId, QStringList excludeFields) {
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
url.setPath(url.path() + QString("/notes/%1").arg(noteId));
|
url.setPath(url.path() + "/index.php/apps/notes/api/v0.2" + QString("/notes/%1").arg(noteId));
|
||||||
if (!excludeFields.isEmpty())
|
if (!excludeFields.isEmpty())
|
||||||
url.setQuery(QString("exclude=").append(excludeFields.join(",")));
|
url.setQuery(QString("exclude=").append(excludeFields.join(",")));
|
||||||
if (url.isValid()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "GET" << url.toDisplayString();
|
qDebug() << "GET" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
m_request.setUrl(url);
|
||||||
m_replies << m_manager.get(m_request);
|
m_replies << m_manager.get(m_request);
|
||||||
|
@ -211,8 +238,8 @@ void NotesApi::createNote(QVariantMap fields) {
|
||||||
|
|
||||||
// Create note via the API
|
// Create note via the API
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
url.setPath(url.path() + "/notes");
|
url.setPath(url.path() + "/index.php/apps/notes/api/v0.2" + "/notes");
|
||||||
if (url.isValid()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "POST" << url.toDisplayString();
|
qDebug() << "POST" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
m_request.setUrl(url);
|
||||||
m_replies << m_manager.post(m_request, note.toJsonDocument().toJson());
|
m_replies << m_manager.post(m_request, note.toJsonDocument().toJson());
|
||||||
|
@ -227,8 +254,8 @@ void NotesApi::updateNote(double noteId, QVariantMap fields) {
|
||||||
|
|
||||||
// Update note on the server
|
// Update note on the server
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
url.setPath(url.path() + QString("/notes/%1").arg(noteId));
|
url.setPath(url.path() + "/index.php/apps/notes/api/v0.2" + QString("/notes/%1").arg(noteId));
|
||||||
if (url.isValid()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "PUT" << url.toDisplayString();
|
qDebug() << "PUT" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
m_request.setUrl(url);
|
||||||
m_replies << m_manager.put(m_request, note.toJsonDocument().toJson());
|
m_replies << m_manager.put(m_request, note.toJsonDocument().toJson());
|
||||||
|
@ -242,8 +269,8 @@ void NotesApi::deleteNote(double noteId) {
|
||||||
|
|
||||||
// Remove note from the server
|
// Remove note from the server
|
||||||
QUrl url = m_url;
|
QUrl url = m_url;
|
||||||
url.setPath(url.path() + QString("/notes/%1").arg(noteId));
|
url.setPath(url.path() + "/index.php/apps/notes/api/v0.2" + QString("/notes/%1").arg(noteId));
|
||||||
if (url.isValid()) {
|
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||||
qDebug() << "DELETE" << url.toDisplayString();
|
qDebug() << "DELETE" << url.toDisplayString();
|
||||||
m_request.setUrl(url);
|
m_request.setUrl(url);
|
||||||
m_replies << m_manager.deleteResource(m_request);
|
m_replies << m_manager.deleteResource(m_request);
|
||||||
|
@ -254,7 +281,7 @@ void NotesApi::deleteNote(double noteId) {
|
||||||
|
|
||||||
void NotesApi::verifyUrl(QUrl url) {
|
void NotesApi::verifyUrl(QUrl url) {
|
||||||
emit urlValidChanged(url.isValid());
|
emit urlValidChanged(url.isValid());
|
||||||
if (url.isValid()) {
|
if (m_url.isValid() && !m_url.scheme().isEmpty() && !m_url.host().isEmpty()) {
|
||||||
getStatus();
|
getStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,20 +301,28 @@ void NotesApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessib
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::replyFinished(QNetworkReply *reply) {
|
void NotesApi::replyFinished(QNetworkReply *reply) {
|
||||||
qDebug() << reply->error() << reply->errorString();
|
//qDebug() << reply->error() << reply->errorString();
|
||||||
|
bool deleteReply = false;
|
||||||
if (reply->error() == QNetworkReply::NoError) {
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
emit error(NoError);
|
emit error(NoError);
|
||||||
QByteArray data = reply->readAll();
|
QByteArray data = reply->readAll();
|
||||||
QJsonDocument json = QJsonDocument::fromJson(data);
|
QJsonDocument json = QJsonDocument::fromJson(data);
|
||||||
if (m_login_replies.contains(reply)) {
|
if (m_login_replies.contains(reply)) {
|
||||||
if (json.isObject()) {
|
if (json.isObject())
|
||||||
updateLogin(json.object());
|
updateLoginFlow(json.object());
|
||||||
}
|
m_login_replies.removeAll(reply);
|
||||||
}
|
}
|
||||||
if (m_status_replies.contains(reply)) {
|
else if (m_poll_replies.contains(reply)) {
|
||||||
if (json.isObject()) {
|
if (json.isObject())
|
||||||
|
updateLoginCredentials(json.object());
|
||||||
|
m_poll_replies.removeAll(reply);
|
||||||
|
m_loginPollTimer.stop();
|
||||||
|
m_loginUrl.clear();
|
||||||
|
}
|
||||||
|
else if (m_status_replies.contains(reply)) {
|
||||||
|
if (json.isObject())
|
||||||
updateStatus(json.object());
|
updateStatus(json.object());
|
||||||
}
|
m_status_replies.removeAll(reply);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (mp_model) {
|
if (mp_model) {
|
||||||
|
@ -296,18 +331,26 @@ void NotesApi::replyFinished(QNetworkReply *reply) {
|
||||||
emit lastSyncChanged(m_lastSync);
|
emit lastSyncChanged(m_lastSync);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_replies.removeAll(reply);
|
||||||
}
|
}
|
||||||
//qDebug() << data;
|
//qDebug() << data;
|
||||||
|
deleteReply = true;
|
||||||
}
|
}
|
||||||
else if (reply->error() == QNetworkReply::AuthenticationRequiredError)
|
else if (reply->error() == QNetworkReply::AuthenticationRequiredError) {
|
||||||
emit error(AuthenticationError);
|
emit error(AuthenticationError);
|
||||||
else
|
deleteReply = true;
|
||||||
emit error(CommunicationError);
|
}
|
||||||
m_login_replies.removeAll(reply);
|
else {
|
||||||
m_status_replies.removeAll(reply);
|
if (!m_poll_replies.contains(reply)) {
|
||||||
m_replies.removeAll(reply);
|
emit error(CommunicationError);
|
||||||
reply->deleteLater();
|
deleteReply = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//qDebug() << "Polling not finished yet" << m_pollUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
emit busyChanged(busy());
|
emit busyChanged(busy());
|
||||||
|
//if (deleteReply) reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::sslError(QNetworkReply *reply, const QList<QSslError> &errors) {
|
void NotesApi::sslError(QNetworkReply *reply, const QList<QSslError> &errors) {
|
||||||
|
@ -344,12 +387,8 @@ void NotesApi::updateStatus(const QJsonObject &status) {
|
||||||
m_status_needsDbUpgrade = status.value("needsDbUpgrade").toBool();
|
m_status_needsDbUpgrade = status.value("needsDbUpgrade").toBool();
|
||||||
emit statusNeedsDbUpgradeChanged(m_status_needsDbUpgrade);
|
emit statusNeedsDbUpgradeChanged(m_status_needsDbUpgrade);
|
||||||
}
|
}
|
||||||
QStringList versionStr = status.value("version").toString().split('.');
|
if (m_status_version != status.value("version").toString()) {
|
||||||
QVector<int> version;
|
m_status_version = status.value("version").toString();
|
||||||
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);
|
emit statusVersionChanged(m_status_version);
|
||||||
}
|
}
|
||||||
if (m_status_versionstring != status.value("versionstring").toString()) {
|
if (m_status_versionstring != status.value("versionstring").toString()) {
|
||||||
|
@ -362,7 +401,6 @@ void NotesApi::updateStatus(const QJsonObject &status) {
|
||||||
}
|
}
|
||||||
if (m_status_productname != status.value("productname").toString()) {
|
if (m_status_productname != status.value("productname").toString()) {
|
||||||
m_status_productname = status.value("productname").toString();
|
m_status_productname = status.value("productname").toString();
|
||||||
qDebug() << m_status_productname;
|
|
||||||
emit statusProductNameChanged(m_status_productname);
|
emit statusProductNameChanged(m_status_productname);
|
||||||
}
|
}
|
||||||
if (m_status_extendedSupport != status.value("extendedSupport").toBool()) {
|
if (m_status_extendedSupport != status.value("extendedSupport").toBool()) {
|
||||||
|
@ -372,31 +410,51 @@ void NotesApi::updateStatus(const QJsonObject &status) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotesApi::updateLogin(const QJsonObject &login) {
|
void NotesApi::updateLoginFlow(const QJsonObject &login) {
|
||||||
QUrl url;
|
QUrl url;
|
||||||
QString token;
|
QString token;
|
||||||
if (!login.isEmpty()) {
|
if (!login.isEmpty()) {
|
||||||
url = login.value("login").toString();
|
|
||||||
if (m_login_loginUrl != url && url.isValid()) {
|
|
||||||
m_login_loginUrl = url;
|
|
||||||
emit loginLoginUrlChanged(m_login_loginUrl);
|
|
||||||
}
|
|
||||||
QJsonObject poll = login.value("poll").toObject();
|
QJsonObject poll = login.value("poll").toObject();
|
||||||
if (!poll.isEmpty()) {
|
if (!poll.isEmpty()) {
|
||||||
url = poll.value("endpoint").toString() ;
|
url = poll.value("endpoint").toString() ;
|
||||||
if (m_login_pollUrl != url && urlValid()) {
|
|
||||||
m_login_pollUrl = url;
|
|
||||||
emit loginPollUrlChanged(m_login_pollUrl);
|
|
||||||
}
|
|
||||||
token = poll.value("token").toString();
|
token = poll.value("token").toString();
|
||||||
if (m_login_pollToken != token) {
|
if (url.isValid() && !token.isEmpty()) {
|
||||||
m_login_pollToken = token;
|
m_pollUrl = url;
|
||||||
emit loginPollTokenChanged(m_login_pollToken);
|
qDebug() << "Poll URL: " << m_pollUrl;
|
||||||
|
m_pollToken = token;
|
||||||
|
qDebug() << "Poll Token: " << m_pollToken;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "Invalid Poll URL:" << url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
url = login.value("login").toString();
|
||||||
|
if (m_loginUrl != url && url.isValid()) {
|
||||||
|
m_loginUrl = url;
|
||||||
|
qDebug() << "Login URL: " << m_loginUrl;
|
||||||
|
emit loginUrlChanged(m_loginUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NotesApi::updateLoginCredentials(const QJsonObject &credentials) {
|
||||||
|
QString serverAddr;
|
||||||
|
QString loginName;
|
||||||
|
QString appPassword;
|
||||||
|
if (!credentials.isEmpty()) {
|
||||||
|
serverAddr = credentials.value("server").toString();
|
||||||
|
if (serverAddr != server())
|
||||||
|
setServer(serverAddr);
|
||||||
|
loginName = credentials.value("loginName").toString();
|
||||||
|
if (loginName != username())
|
||||||
|
setUsername(loginName);
|
||||||
|
appPassword = credentials.value("appPassword").toString();
|
||||||
|
if (appPassword != password())
|
||||||
|
setPassword(appPassword);
|
||||||
|
}
|
||||||
|
qDebug() << "Login successfull for user" << loginName << "on" << serverAddr;
|
||||||
|
}
|
||||||
|
|
||||||
const QString NotesApi::errorMessage(int error) const {
|
const QString NotesApi::errorMessage(int error) const {
|
||||||
QString message;
|
QString message;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QTimer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "notesmodel.h"
|
#include "notesmodel.h"
|
||||||
|
|
||||||
|
@ -27,6 +28,10 @@ public:
|
||||||
Q_PROPERTY(bool urlValid READ urlValid NOTIFY urlValidChanged)
|
Q_PROPERTY(bool urlValid READ urlValid NOTIFY urlValidChanged)
|
||||||
bool urlValid() const { return m_url.isValid(); }
|
bool urlValid() const { return m_url.isValid(); }
|
||||||
|
|
||||||
|
Q_PROPERTY(QString server READ server WRITE setServer NOTIFY serverChanged)
|
||||||
|
QString server() const;
|
||||||
|
void setServer(QString server);
|
||||||
|
|
||||||
Q_PROPERTY(QString scheme READ scheme WRITE setScheme NOTIFY schemeChanged)
|
Q_PROPERTY(QString scheme READ scheme WRITE setScheme NOTIFY schemeChanged)
|
||||||
QString scheme() const { return m_url.scheme(); }
|
QString scheme() const { return m_url.scheme(); }
|
||||||
void setScheme(QString scheme);
|
void setScheme(QString scheme);
|
||||||
|
@ -61,9 +66,6 @@ public:
|
||||||
Q_PROPERTY(QDateTime lastSync READ lastSync NOTIFY lastSyncChanged)
|
Q_PROPERTY(QDateTime lastSync READ lastSync NOTIFY lastSyncChanged)
|
||||||
QDateTime lastSync() const { return m_lastSync; }
|
QDateTime lastSync() const { return m_lastSync; }
|
||||||
|
|
||||||
Q_PROPERTY(bool ready READ ready NOTIFY readyChanged)
|
|
||||||
bool ready() const;
|
|
||||||
|
|
||||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||||
bool busy() const;
|
bool busy() const;
|
||||||
|
|
||||||
|
@ -73,8 +75,8 @@ public:
|
||||||
bool statusMaintenance() const { return m_status_maintenance; }
|
bool statusMaintenance() const { return m_status_maintenance; }
|
||||||
Q_PROPERTY(bool statusNeedsDbUpgrade READ statusNeedsDbUpgrade NOTIFY statusNeedsDbUpgradeChanged)
|
Q_PROPERTY(bool statusNeedsDbUpgrade READ statusNeedsDbUpgrade NOTIFY statusNeedsDbUpgradeChanged)
|
||||||
bool statusNeedsDbUpgrade() const { return m_status_needsDbUpgrade; }
|
bool statusNeedsDbUpgrade() const { return m_status_needsDbUpgrade; }
|
||||||
Q_PROPERTY(QVector<int> statusVersion READ statusVersion NOTIFY statusVersionChanged)
|
Q_PROPERTY(QString statusVersion READ statusVersion NOTIFY statusVersionChanged)
|
||||||
QVector<int> statusVersion() const { return m_status_version; }
|
QString statusVersion() const { return m_status_version; }
|
||||||
Q_PROPERTY(QString statusVersionString READ statusVersionString NOTIFY statusVersionStringChanged)
|
Q_PROPERTY(QString statusVersionString READ statusVersionString NOTIFY statusVersionStringChanged)
|
||||||
QString statusVersionString() const { return m_status_versionstring; }
|
QString statusVersionString() const { return m_status_versionstring; }
|
||||||
Q_PROPERTY(QString statusEdition READ statusEdition NOTIFY statusEditionChanged)
|
Q_PROPERTY(QString statusEdition READ statusEdition NOTIFY statusEditionChanged)
|
||||||
|
@ -83,12 +85,8 @@ public:
|
||||||
QString statusProductName() const { return m_status_productname; }
|
QString statusProductName() const { return m_status_productname; }
|
||||||
Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged)
|
Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged)
|
||||||
bool statusExtendedSupport() const { return m_status_extendedSupport; }
|
bool statusExtendedSupport() const { return m_status_extendedSupport; }
|
||||||
Q_PROPERTY(QUrl loginPollUrl READ loginPollUrl NOTIFY loginPollUrlChanged)
|
Q_PROPERTY(QUrl loginUrl READ loginUrl NOTIFY loginUrlChanged)
|
||||||
QUrl loginPollUrl() const { return m_login_pollUrl; }
|
QUrl loginUrl() const { return m_loginUrl; }
|
||||||
Q_PROPERTY(QString loginPollToken READ loginPollToken NOTIFY loginPollTokenChanged)
|
|
||||||
QString loginPollToken() const { return m_login_pollToken; }
|
|
||||||
Q_PROPERTY(QUrl loginLoginUrl READ loginLoginUrl NOTIFY loginLoginUrlChanged)
|
|
||||||
QUrl loginLoginUrl() const { return m_login_loginUrl; }
|
|
||||||
|
|
||||||
Q_INVOKABLE void getStatus();
|
Q_INVOKABLE void getStatus();
|
||||||
Q_INVOKABLE void initiateFlowV2Login();
|
Q_INVOKABLE void initiateFlowV2Login();
|
||||||
|
@ -114,6 +112,7 @@ signals:
|
||||||
void sslVerifyChanged(bool verify);
|
void sslVerifyChanged(bool verify);
|
||||||
void urlChanged(QUrl url);
|
void urlChanged(QUrl url);
|
||||||
void urlValidChanged(bool valid);
|
void urlValidChanged(bool valid);
|
||||||
|
void serverChanged(QString server);
|
||||||
void schemeChanged(QString scheme);
|
void schemeChanged(QString scheme);
|
||||||
void hostChanged(QString host);
|
void hostChanged(QString host);
|
||||||
void portChanged(int port);
|
void portChanged(int port);
|
||||||
|
@ -123,19 +122,16 @@ signals:
|
||||||
void dataFileChanged(QString dataFile);
|
void dataFileChanged(QString dataFile);
|
||||||
void networkAccessibleChanged(bool accessible);
|
void networkAccessibleChanged(bool accessible);
|
||||||
void lastSyncChanged(QDateTime lastSync);
|
void lastSyncChanged(QDateTime lastSync);
|
||||||
void readyChanged(bool ready);
|
|
||||||
void busyChanged(bool busy);
|
void busyChanged(bool busy);
|
||||||
void statusInstalledChanged(bool installed);
|
void statusInstalledChanged(bool installed);
|
||||||
void statusMaintenanceChanged(bool maintenance);
|
void statusMaintenanceChanged(bool maintenance);
|
||||||
void statusNeedsDbUpgradeChanged(bool needsDbUpgrade);
|
void statusNeedsDbUpgradeChanged(bool needsDbUpgrade);
|
||||||
void statusVersionChanged(QVector<int> version);
|
void statusVersionChanged(QString version);
|
||||||
void statusVersionStringChanged(QString versionString);
|
void statusVersionStringChanged(QString versionString);
|
||||||
void statusEditionChanged(QString edition);
|
void statusEditionChanged(QString edition);
|
||||||
void statusProductNameChanged(QString productName);
|
void statusProductNameChanged(QString productName);
|
||||||
void statusExtendedSupportChanged(bool extendedSupport);
|
void statusExtendedSupportChanged(bool extendedSupport);
|
||||||
void loginPollUrlChanged(QUrl url);
|
void loginUrlChanged(QUrl url);
|
||||||
void loginPollTokenChanged(QString token);
|
|
||||||
void loginLoginUrlChanged(QUrl url);
|
|
||||||
void error(int error);
|
void error(int error);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -145,6 +141,7 @@ private slots:
|
||||||
void requireAuthentication(QNetworkReply * reply, QAuthenticator * authenticator);
|
void requireAuthentication(QNetworkReply * reply, QAuthenticator * authenticator);
|
||||||
void onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
|
void onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
|
||||||
void replyFinished(QNetworkReply* reply);
|
void replyFinished(QNetworkReply* reply);
|
||||||
|
void pollLoginUrl();
|
||||||
void sslError(QNetworkReply* reply, const QList<QSslError> &errors);
|
void sslError(QNetworkReply* reply, const QList<QSslError> &errors);
|
||||||
void saveToFile(QModelIndex,QModelIndex,QVector<int>);
|
void saveToFile(QModelIndex,QModelIndex,QVector<int>);
|
||||||
|
|
||||||
|
@ -164,17 +161,20 @@ private:
|
||||||
bool m_status_installed;
|
bool m_status_installed;
|
||||||
bool m_status_maintenance;
|
bool m_status_maintenance;
|
||||||
bool m_status_needsDbUpgrade;
|
bool m_status_needsDbUpgrade;
|
||||||
QVector<int> m_status_version;
|
QString m_status_version;
|
||||||
QString m_status_versionstring;
|
QString m_status_versionstring;
|
||||||
QString m_status_edition;
|
QString m_status_edition;
|
||||||
QString m_status_productname;
|
QString m_status_productname;
|
||||||
bool m_status_extendedSupport;
|
bool m_status_extendedSupport;
|
||||||
|
|
||||||
void updateLogin(const QJsonObject &login);
|
void updateLoginFlow(const QJsonObject &login);
|
||||||
|
void updateLoginCredentials(const QJsonObject &credentials);
|
||||||
QVector<QNetworkReply*> m_login_replies;
|
QVector<QNetworkReply*> m_login_replies;
|
||||||
QUrl m_login_pollUrl;
|
QVector<QNetworkReply*> m_poll_replies;
|
||||||
QString m_login_pollToken;
|
QTimer m_loginPollTimer;
|
||||||
QUrl m_login_loginUrl;
|
QUrl m_loginUrl;
|
||||||
|
QUrl m_pollUrl;
|
||||||
|
QString m_pollToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NOTESAPI_H
|
#endif // NOTESAPI_H
|
||||||
|
|
|
@ -103,45 +103,49 @@
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>LoginDialog</name>
|
<name>LoginDialog</name>
|
||||||
|
<message>
|
||||||
|
<source></source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Login</source>
|
<source>Login</source>
|
||||||
<translation>Verbinden</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>Speichern</translation>
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Login Flow v2</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Legacy Login</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Account name</source>
|
<source>Account name</source>
|
||||||
<translation>Kontoname</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Nextcloud server</source>
|
<source>Nextcloud server</source>
|
||||||
<translation>Nextcloud Server URL</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Benutzername</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
<translation>Passwort</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Security</source>
|
<source>Security</source>
|
||||||
<translation>Sicherheit</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<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>
|
<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><strong>ACHTUNG: Dein Password wird unverschlüsselt auf dem Gerät gespeichert!</strong><br>Erwäge ein eigenes App-Passwort zu erstellen! Öffne deine Nextcloud in einem Webbrowser und gehe zu <i>Einstellungen</i> --> <i>Sicherheit</i>.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Allow unencrypted connections</source>
|
|
||||||
<translation>Unverschlüsselte Verbindungen zulassen</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source></source>
|
|
||||||
<translation></translation>
|
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Do not check certificates</source>
|
<source>Do not check certificates</source>
|
||||||
|
@ -151,6 +155,10 @@
|
||||||
<source>Enable this option to allow selfsigned certificates</source>
|
<source>Enable this option to allow selfsigned certificates</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Allow unencrypted connections</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MITLicense</name>
|
<name>MITLicense</name>
|
||||||
|
|
|
@ -103,45 +103,49 @@
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>LoginDialog</name>
|
<name>LoginDialog</name>
|
||||||
<message>
|
|
||||||
<source>Login</source>
|
|
||||||
<translation>Logga in</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Username</source>
|
|
||||||
<translation>Användarnamn</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Nextcloud server</source>
|
|
||||||
<translation>Nextcloud server</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Account name</source>
|
|
||||||
<translation>Kontonamn</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Security</source>
|
|
||||||
<translation>Säkerhet</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source></source>
|
<source></source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<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>
|
<source>Login</source>
|
||||||
<translation><strong>OBS! Ditt lösenord kommer att sparas okrypterat på enheten!</strong><br>Överväg att skapa ett dedikerat app-lösenord! Öppna din Nextcloud i en webbläsare och gå till <i>Inställningar</i> → <i>Säkerhet</i>.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Password</source>
|
|
||||||
<translation>Lösenord</translation>
|
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>Spara</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Allow unencrypted connections</source>
|
<source>Login Flow v2</source>
|
||||||
<translation>Tillåt okrypterade anslutningar</translation>
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Legacy Login</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Account name</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Nextcloud server</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Username</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Password</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Security</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<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>
|
||||||
<message>
|
<message>
|
||||||
<source>Do not check certificates</source>
|
<source>Do not check certificates</source>
|
||||||
|
@ -151,6 +155,10 @@
|
||||||
<source>Enable this option to allow selfsigned certificates</source>
|
<source>Enable this option to allow selfsigned certificates</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Allow unencrypted connections</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MITLicense</name>
|
<name>MITLicense</name>
|
||||||
|
|
|
@ -125,66 +125,76 @@
|
||||||
<context>
|
<context>
|
||||||
<name>LoginDialog</name>
|
<name>LoginDialog</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="55"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="133"/>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="124"/>
|
<source></source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/pages/LoginDialog.qml" line="79"/>
|
||||||
|
<location filename="../qml/pages/LoginDialog.qml" line="175"/>
|
||||||
<source>Login</source>
|
<source>Login</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="55"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="79"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="71"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="97"/>
|
||||||
|
<source>Login Flow v2</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/pages/LoginDialog.qml" line="111"/>
|
||||||
|
<source>Legacy Login</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/pages/LoginDialog.qml" line="121"/>
|
||||||
<source>Account name</source>
|
<source>Account name</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="86"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="136"/>
|
||||||
<source>Nextcloud server</source>
|
<source>Nextcloud server</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="101"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="151"/>
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="114"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="164"/>
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="132"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="195"/>
|
||||||
<source>Security</source>
|
<source>Security</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="139"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="202"/>
|
||||||
<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>
|
<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>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="143"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="206"/>
|
||||||
<source>Do not check certificates</source>
|
<source>Do not check certificates</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="144"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="207"/>
|
||||||
<source>Enable this option to allow selfsigned certificates</source>
|
<source>Enable this option to allow selfsigned certificates</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="150"/>
|
<location filename="../qml/pages/LoginDialog.qml" line="213"/>
|
||||||
<source>Allow unencrypted connections</source>
|
<source>Allow unencrypted connections</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../qml/pages/LoginDialog.qml" line="133"/>
|
|
||||||
<source></source>
|
|
||||||
<translation></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MITLicense</name>
|
<name>MITLicense</name>
|
||||||
|
@ -263,37 +273,37 @@
|
||||||
<context>
|
<context>
|
||||||
<name>NotesApi</name>
|
<name>NotesApi</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="406"/>
|
<location filename="../src/notesapi.cpp" line="464"/>
|
||||||
<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/notesapi.cpp" line="409"/>
|
<location filename="../src/notesapi.cpp" line="467"/>
|
||||||
<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/notesapi.cpp" line="412"/>
|
<location filename="../src/notesapi.cpp" line="470"/>
|
||||||
<source>An error happened while reading from the local storage</source>
|
<source>An error happened while reading from the local storage</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="415"/>
|
<location filename="../src/notesapi.cpp" line="473"/>
|
||||||
<source>An error happened while writing to the local storage</source>
|
<source>An error happened while writing to the local storage</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/notesapi.cpp" line="418"/>
|
<location filename="../src/notesapi.cpp" line="476"/>
|
||||||
<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/notesapi.cpp" line="421"/>
|
<location filename="../src/notesapi.cpp" line="479"/>
|
||||||
<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/notesapi.cpp" line="424"/>
|
<location filename="../src/notesapi.cpp" line="482"/>
|
||||||
<source>Unknown error</source>
|
<source>Unknown error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
Loading…
Reference in a new issue