Made login flow usable again

This commit is contained in:
scharel 2021-06-20 21:02:10 +02:00
parent a99e30aeea
commit 79ed971afe
14 changed files with 212 additions and 211 deletions

View file

@ -2,13 +2,22 @@ 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 Nemo.Notifications 1.0 import Nemo.Notifications 1.0
import NextcloudApi 1.0 import harbour.nextcloudapi 1.0
import harbour.nextcloudapi.notes 1.0
import "pages" import "pages"
ApplicationWindow ApplicationWindow
{ {
id: appWindow id: appWindow
property var nextcloudApi: Nextcloud
property var notesApp: Notes
property NotesModel notesModel: notesApp.model()
Component.onCompleted: {
//console.log("Current account: ", appSettings.currentAccount)
}
// General settings of the app // General settings of the app
ConfigurationGroup { ConfigurationGroup {
id: appSettings id: appSettings
@ -30,10 +39,10 @@ ApplicationWindow
} }
onSortByChanged: { onSortByChanged: {
if (sortBy == "none") notesModel.invalidate() if (sortBy == "none") Notes.model.invalidate()
} }
onFavoritesOnTopChanged: { onFavoritesOnTopChanged: {
notesModel.favoritesOnTop = favoritesOnTop Notes.model.favoritesOnTop = favoritesOnTop
} }
function createAccount(username, password, url, name) { function createAccount(username, password, url, name) {
@ -52,7 +61,7 @@ ApplicationWindow
return hash return hash
} }
function removeAccount(hash) { function removeAccount(hash) {
notesApi.deleteAppPassword(appSettings.value("accounts/" + hash + "/password"), Nextcloud.deleteAppPassword(appSettings.value("accounts/" + hash + "/password"),
appSettings.value("accounts/" + hash + "/username"), appSettings.value("accounts/" + hash + "/username"),
appSettings.value("accounts/" + hash + "/url")) appSettings.value("accounts/" + hash + "/url"))
var tmpaccounts = accounts var tmpaccounts = accounts
@ -77,6 +86,10 @@ ApplicationWindow
property string passowrd: value("password", "", String) property string passowrd: value("password", "", String)
property string name: value("name", "", String) property string name: value("name", "", String)
property var update: value("update", new Date(0), Date) property var update: value("update", new Date(0), Date)
onUrlChanged: Nextcloud.server = url
onUsernameChanged: Nextcloud.username = username
onPassowrdChanged: Nextcloud.password = passowrd
} }
ConfigurationGroup { ConfigurationGroup {
@ -119,10 +132,10 @@ ApplicationWindow
id: autoSyncTimer id: autoSyncTimer
interval: appSettings.autoSyncInterval * 1000 interval: appSettings.autoSyncInterval * 1000
repeat: true repeat: true
running: interval > 0 && notesApi.networkAccessible && appWindow.visible running: interval > 0 && appSettings.currentAccount !== "" && Nextcloud.networkAccessible && appWindow.visible
triggeredOnStart: true triggeredOnStart: true
onTriggered: { onTriggered: {
notesApi.getAllNotes() Notes.getAllNotes()
} }
onIntervalChanged: { onIntervalChanged: {
if (interval > 0) { if (interval > 0) {
@ -134,16 +147,6 @@ ApplicationWindow
} }
} }
Nextcloud {
id: notesApi
server: account.url
username: account.username
password: account.passowrd
}
Component.onCompleted: {
}
Component.onDestruction: { Component.onDestruction: {
offlineNotification.close() offlineNotification.close()
storeErrorNotification.close() storeErrorNotification.close()

View file

@ -113,7 +113,7 @@ Dialog {
Repeater { Repeater {
id: categoryRepeater id: categoryRepeater
model: notesApi.categories model: Nextcloud.categories
BackgroundItem { BackgroundItem {
id: categoryBackground id: categoryBackground
width: categoryRectangle.width width: categoryRectangle.width

View file

@ -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 NextcloudApi 1.0 import harbour.nextcloudapi 1.0
Dialog { Dialog {
id: loginDialog id: loginDialog
@ -18,31 +18,31 @@ Dialog {
property bool allowUnecrypted: false property bool allowUnecrypted: false
Component.onCompleted: { Component.onCompleted: {
appSettings.currentAccount = null appSettings.currentAccount = ""
} }
onRejected: { onRejected: {
notesApi.abortFlowV2Login() Nextcloud.abortFlowV2Login()
appSettings.currentAccount = peviousAccount appSettings.currentAccount = peviousAccount
} }
onAccepted: { onAccepted: {
appSettings.createAccount(notesApi.username, notesApi.password, notesApi.server, notesApi.statusProductName) appSettings.currentAccount = appSettings.createAccount(Nextcloud.username, Nextcloud.password, Nextcloud.server, Nextcloud.statusProductName)
} }
Timer { Timer {
id: verifyServerTimer id: verifyServerTimer
onTriggered: notesApi.getNcStatus() onTriggered: Nextcloud.getStatus()
} }
Connections { Connections {
target: notesApi target: Nextcloud
onStatusInstalledChanged: { onStatusInstalledChanged: {
if (notesApi.statusInstalled) if (Nextcloud.statusInstalled)
serverField.focus = false serverField.focus = false
} }
onStatusVersionChanged: { onStatusVersionChanged: {
if (notesApi.statusVersion) { if (Nextcloud.statusVersion) {
if (notesApi.statusVersion.split('.')[0] >= 16) { if (Nextcloud.statusVersion.split('.')[0] >= 16) {
legacyLoginPossible = false legacyLoginPossible = false
flowLoginV2Possible = true flowLoginV2Possible = true
console.log("Using Flow Login v2") console.log("Using Flow Login v2")
@ -58,48 +58,39 @@ Dialog {
flowLoginV2Possible = false flowLoginV2Possible = false
} }
} }
onStatusProductNameChanged: {
if (notesApi.statusProductName) {
productName = notesApi.statusProductName
console.log(productName)
}
else {
productName = null
}
}
onLoginStatusChanged: { onLoginStatusChanged: {
loginDialog.canAccept = false loginDialog.canAccept = false
apiProgressBar.indeterminate = false apiProgressBar.indeterminate = false
switch(notesApi.loginStatus) { switch(Nextcloud.loginStatus) {
case NotesApi.LoginLegacyReady: case Nextcloud.LoginLegacyReady:
console.log("LoginLegacyReady") console.log("LoginLegacyReady")
apiProgressBar.label = qsTr("Enter your credentials") apiProgressBar.label = qsTr("Enter your credentials")
break; break;
case NotesApi.LoginFlowV2Initiating: case Nextcloud.LoginFlowV2Initiating:
console.log("LoginFlowV2Initiating") console.log("LoginFlowV2Initiating")
apiProgressBar.indeterminate = true apiProgressBar.indeterminate = true
break; break;
case NotesApi.LoginFlowV2Polling: case Nextcloud.LoginFlowV2Polling:
console.log("LoginFlowV2Polling") console.log("LoginFlowV2Polling")
apiProgressBar.label = qsTr("Follow the instructions in the browser") apiProgressBar.label = qsTr("Follow the instructions in the browser")
apiProgressBar.indeterminate = true apiProgressBar.indeterminate = true
break; break;
case NotesApi.LoginFlowV2Success: case Nextcloud.LoginFlowV2Success:
console.log("LoginFlowV2Success") console.log("LoginFlowV2Success")
notesApi.verifyLogin() Nextcloud.verifyLogin()
break; break;
case NotesApi.LoginFlowV2Failed: case Nextcloud.LoginFlowV2Failed:
console.log("LoginFlowV2Failed") console.log("LoginFlowV2Failed")
apiProgressBar.label = qsTr("Login failed!") apiProgressBar.label = qsTr("Login failed!")
break break
case NotesApi.LoginSuccess: case Nextcloud.LoginSuccess:
console.log("LoginSuccess") console.log("LoginSuccess")
apiProgressBar.label = qsTr("Login successfull!") apiProgressBar.label = qsTr("Login successfull!")
if (legacyLoginPossible || forceLegacyButton.checked) if (legacyLoginPossible || forceLegacyButton.checked)
notesApi.convertToAppPassword(); Nextcloud.convertToAppPassword();
loginDialog.canAccept = true loginDialog.canAccept = true
break; break;
case NotesApi.LoginFailed: case Nextcloud.LoginFailed:
console.log("LoginFailed") console.log("LoginFailed")
apiProgressBar.label = qsTr("Login failed!") apiProgressBar.label = qsTr("Login failed!")
break; break;
@ -109,8 +100,8 @@ Dialog {
} }
} }
onLoginUrlChanged: { onLoginUrlChanged: {
if (notesApi.loginUrl) { if (Nextcloud.loginUrl) {
Qt.openUrlExternally(notesApi.loginUrl) Qt.openUrlExternally(Nextcloud.loginUrl)
} }
} }
} }
@ -142,9 +133,9 @@ Dialog {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: parent.width width: parent.width
label: verifyServerTimer.running ? qsTr("Verifying address") : " " label: verifyServerTimer.running ? qsTr("Verifying address") : " "
indeterminate: notesApi.loginStatus === NotesApi.LoginFlowV2Initiating || indeterminate: Nextcloud.loginStatus === Nextcloud.LoginFlowV2Initiating ||
notesApi.loginStatus === NotesApi.LoginFlowV2Polling || Nextcloud.loginStatus === Nextcloud.LoginFlowV2Polling ||
notesApi.ncStatusStatus === NotesApi.NextcloudBusy || Nextcloud.statusStatus === Nextcloud.NextcloudBusy ||
verifyServerTimer.running verifyServerTimer.running
} }
@ -153,16 +144,16 @@ Dialog {
TextField { TextField {
id: serverField id: serverField
width: parent.width - statusIcon.width - Theme.horizontalPageMargin width: parent.width - statusIcon.width - Theme.horizontalPageMargin
text: notesApi.server text: Nextcloud.server
placeholderText: qsTr("Enter Nextcloud address") placeholderText: qsTr("Enter Nextcloud address")
label: notesApi.statusProductName ? notesApi.statusProductName : qsTr("Nextcloud address") label: Nextcloud.statusProductName ? Nextcloud.statusProductName : qsTr("Nextcloud address")
validator: RegExpValidator { regExp: allowUnecrypted ? /^https?:\/\/([-a-zA-Z0-9@:%._\+~#=].*)/: /^https:\/\/([-a-zA-Z0-9@:%._\+~#=].*)/ } validator: RegExpValidator { regExp: allowUnecrypted ? /^https?:\/\/([-a-zA-Z0-9@:%._\+~#=].*)/: /^https:\/\/([-a-zA-Z0-9@:%._\+~#=].*)/ }
inputMethodHints: Qt.ImhUrlCharactersOnly inputMethodHints: Qt.ImhUrlCharactersOnly
onClicked: if (text === "") text = allowUnecrypted ? "http://" : "https://" onClicked: if (text === "") text = allowUnecrypted ? "http://" : "https://"
onTextChanged: { onTextChanged: {
loginDialog.canAccept = false loginDialog.canAccept = false
if (acceptableInput) { if (acceptableInput) {
notesApi.server = text Nextcloud.server = text
verifyServerTimer.restart() verifyServerTimer.restart()
} }
} }
@ -171,27 +162,15 @@ Dialog {
EnterKey.onClicked: { EnterKey.onClicked: {
if (legacyLoginPossible) if (legacyLoginPossible)
usernameField.focus = true usernameField.focus = true
else if (flowLoginV2Possible && notesApi.loginStatus !== notesApi.LoginFlowV2Polling) else if (flowLoginV2Possible && Nextcloud.loginStatus !== Nextcloud.LoginFlowV2Polling)
notesApi.initiateFlowV2Login() Nextcloud.initiateFlowV2Login()
focus = false focus = false
} }
} }
Icon { Icon {
id: statusIcon id: statusIcon
source: notesApi.statusInstalled ? "image://theme/icon-m-accept" : "image://theme/icon-m-cancel" source: Nextcloud.statusInstalled ? "image://theme/icon-m-accept" : "image://theme/icon-m-cancel"
color: notesApi.statusInstalled ? "green" : Theme.errorColor color: Nextcloud.statusInstalled ? "green" : Theme.errorColor
}
}
TextSwitch {
id: forceLegacyButton
visible: debug || !notesApi.statusInstalled
text: qsTr("Enforce legacy login")
automaticCheck: true
onCheckedChanged: {
if (!checked) {
notesApi.getNcStatus()
}
} }
} }
@ -204,8 +183,20 @@ Dialog {
Behavior on opacity { FadeAnimator {} } Behavior on opacity { FadeAnimator {} }
Button { Button {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: notesApi.loginStatus === NotesApi.LoginFlowV2Polling ? qsTr("Abort") : notesApi.loginStatus === NotesApi.LoginSuccess ? qsTr("Re-Login") : qsTr("Login") text: Nextcloud.loginStatus === Nextcloud.LoginFlowV2Polling ? qsTr("Abort") : Nextcloud.loginStatus === Nextcloud.LoginSuccess ? qsTr("Re-Login") : qsTr("Login")
onClicked: notesApi.loginStatus === NotesApi.LoginFlowV2Polling ? notesApi.abortFlowV2Login() : notesApi.initiateFlowV2Login() onClicked: Nextcloud.loginStatus === Nextcloud.LoginFlowV2Polling ? Nextcloud.abortFlowV2Login() : Nextcloud.initiateFlowV2Login()
}
}
TextSwitch {
id: forceLegacyButton
visible: debug || !Nextcloud.statusInstalled
text: qsTr("Enforce legacy login")
automaticCheck: true
onCheckedChanged: {
if (!checked) {
Nextcloud.getNcStatus()
}
} }
} }
@ -218,14 +209,14 @@ Dialog {
TextField { TextField {
id: usernameField id: usernameField
width: parent.width width: parent.width
text: notesApi.username text: Nextcloud.username
placeholderText: qsTr("Enter Username") placeholderText: qsTr("Enter Username")
label: qsTr("Username") label: qsTr("Username")
inputMethodHints: Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase inputMethodHints: Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase
errorHighlight: text.length === 0// && focus === true errorHighlight: text.length === 0// && focus === true
onTextChanged: { onTextChanged: {
loginDialog.canAccept = false loginDialog.canAccept = false
notesApi.username = text Nextcloud.username = text
} }
EnterKey.enabled: text.length > 0 EnterKey.enabled: text.length > 0
EnterKey.iconSource: "image://theme/icon-m-enter-next" EnterKey.iconSource: "image://theme/icon-m-enter-next"
@ -234,22 +225,22 @@ Dialog {
PasswordField { PasswordField {
id: passwordField id: passwordField
width: parent.width width: parent.width
text: notesApi.password text: Nextcloud.password
placeholderText: qsTr("Enter Password") placeholderText: qsTr("Enter Password")
label: qsTr("Password") label: qsTr("Password")
errorHighlight: text.length === 0// && focus === true errorHighlight: text.length === 0// && focus === true
onTextChanged: { onTextChanged: {
loginDialog.canAccept = false loginDialog.canAccept = false
notesApi.password = text Nextcloud.password = text
} }
EnterKey.enabled: text.length > 0 EnterKey.enabled: text.length > 0
EnterKey.iconSource: "image://theme/icon-m-enter-accept" EnterKey.iconSource: "image://theme/icon-m-enter-accept"
EnterKey.onClicked: notesApi.verifyLogin() EnterKey.onClicked: Nextcloud.verifyLogin()
} }
Button { Button {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Test Login") text: qsTr("Test Login")
onClicked: notesApi.verifyLogin(passwordField.text, usernameField.text, serverField.text) onClicked: Nextcloud.verifyLogin(passwordField.text, usernameField.text, serverField.text)
} }
} }
@ -262,7 +253,7 @@ Dialog {
wrapMode: Text.Wrap wrapMode: Text.Wrap
color: Theme.secondaryColor color: Theme.secondaryColor
linkColor: Theme.secondaryHighlightColor linkColor: Theme.secondaryHighlightColor
text: qsTr("The <a href=\"https://apps.nextcloud.com/apps/notes\">Notes</a> app needs to be installed on the Nextcloud server for this app to work.") text: qsTr("The <a href=\"https://apps.Nextcloud.com/apps/notes\">Notes</a> app needs to be installed on the Nextcloud server for this app to work.")
} }
SectionHeader { SectionHeader {
@ -281,7 +272,7 @@ Dialog {
text: qsTr("Do not check certificates") text: qsTr("Do not check certificates")
description: qsTr("Enable this option to allow selfsigned certificates") description: qsTr("Enable this option to allow selfsigned certificates")
onCheckedChanged: { onCheckedChanged: {
notesApi.verifySsl = !checked Nextcloud.verifySsl = !checked
} }
} }
TextSwitch { TextSwitch {

View file

@ -95,7 +95,7 @@ Dialog {
onTriggered: pageStack.pop() onTriggered: pageStack.pop()
} }
PullDownMenu { PullDownMenu {
busy: notesApi.busy busy: Nextcloud.busy
MenuItem { MenuItem {
text: qsTr("Delete") text: qsTr("Delete")
@ -103,7 +103,7 @@ Dialog {
} }
MenuItem { MenuItem {
text: enabled ? qsTr("Reload") : qsTr("Updating...") text: enabled ? qsTr("Reload") : qsTr("Updating...")
enabled: !notesApi.busy enabled: !Nextcloud.busy
onClicked: notesModel.note(note["id"]) onClicked: notesModel.note(note["id"])
} }
/*MenuItem { /*MenuItem {
@ -130,7 +130,7 @@ Dialog {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
size: BusyIndicatorSize.Medium size: BusyIndicatorSize.Medium
running: notesApi.busy running: Nextcloud.busy
} }
Column { Column {
@ -194,7 +194,7 @@ Dialog {
Repeater { Repeater {
id: categoryRepeater id: categoryRepeater
model: notesApi.categories model: Nextcloud.categories
BackgroundItem { BackgroundItem {
id: categoryBackground id: categoryBackground
width: categoryRectangle.width width: categoryRectangle.width

View file

@ -1,5 +1,6 @@
import QtQuick 2.2 import QtQuick 2.2
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import harbour.nextcloudapi 1.0
Page { Page {
id: page id: page
@ -24,7 +25,7 @@ Page {
spacing: Theme.paddingLarge spacing: Theme.paddingLarge
PullDownMenu { PullDownMenu {
busy: notesApi.busy busy: Nextcloud.busy
MenuItem { MenuItem {
text: qsTr("Settings") text: qsTr("Settings")
@ -32,16 +33,18 @@ Page {
} }
MenuItem { MenuItem {
text: qsTr("Add note") text: qsTr("Add note")
enabled: account !== null && notesApi.networkAccessible visible: appSettings.currentAccount !== ""
onClicked: notesApi.createNote( { 'content': "", 'modified': new Date().valueOf() / 1000 } ) enabled: Nextcloud.networkAccessible
onClicked: Nextcloud.createNote( { 'content': "", 'modified': new Date().valueOf() / 1000 } )
} }
MenuItem { MenuItem {
text: notesApi.networkAccessible && !notesApi.busy ? qsTr("Reload") : qsTr("Updating...") text: Nextcloud.networkAccessible && !Nextcloud.busy ? qsTr("Reload") : qsTr("Updating...")
enabled: account !== null && notesApi.networkAccessible && !notesApi.busy visible: appSettings.currentAccount !== ""
onClicked: notesApi.getAllNotes() enabled: Nextcloud.networkAccessible && !Nextcloud.busy
onClicked: Nextcloud.getAllNotes()
} }
MenuLabel { MenuLabel {
visible: account !== null visible: appSettings.currentAccount !== ""
text: qsTr("Last update") + ": " + ( text: qsTr("Last update") + ": " + (
new Date(account.update).valueOf() !== 0 ? new Date(account.update).valueOf() !== 0 ?
new Date(account.update).toLocaleString(Qt.locale(), Locale.ShortFormat) : new Date(account.update).toLocaleString(Qt.locale(), Locale.ShortFormat) :
@ -55,11 +58,11 @@ Page {
id: searchField id: searchField
width: parent.width width: parent.width
enabled: !busyIndicator.running && !noLoginPlaceholder.enabled && !errorPlaceholder.enabled && !noNotesPlaceholder.enabled enabled: !busyIndicator.running && !noLoginPlaceholder.enabled && !errorPlaceholder.enabled && !noNotesPlaceholder.enabled
placeholderText: notesApi.statusProductName.length > 0 ? notesApi.statusProductName : account.name.length > 0 ? account.name : qsTr("Nextcloud Notes") placeholderText: Nextcloud.statusProductName.length > 0 ? Nextcloud.statusProductName : account.name.length > 0 ? account.name : qsTr("Nextcloud Notes")
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: {
notesModel.searchFilter = text Notes.model.searchFilter = text
} }
} }
Label { Label {
@ -71,14 +74,14 @@ Page {
anchors.bottomMargin: Theme.paddingMedium anchors.bottomMargin: Theme.paddingMedium
color: Theme.secondaryHighlightColor color: Theme.secondaryHighlightColor
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
text: notesApi.username + "@" + notesApi.host text: Nextcloud.username + "@" + Nextcloud.host
} }
BusyIndicator { BusyIndicator {
anchors.verticalCenter: searchField.verticalCenter anchors.verticalCenter: searchField.verticalCenter
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Theme.horizontalPageMargin anchors.rightMargin: Theme.horizontalPageMargin
size: BusyIndicatorSize.Medium size: BusyIndicatorSize.Medium
running: notesApi.busy && !busyIndicator.running running: Nextcloud.busy && !busyIndicator.running
} }
} }
@ -120,7 +123,7 @@ Page {
icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") + icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") +
(note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor) (note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
onClicked: { onClicked: {
notesModel.setNote({ 'favorite': !favorite }) Notes.model.setNote({ 'favorite': !favorite })
} }
} }
@ -190,7 +193,7 @@ Page {
text: qsTr("Delete") text: qsTr("Delete")
onClicked: { onClicked: {
remorse.execute(note, qsTr("Deleting note"), function() { remorse.execute(note, qsTr("Deleting note"), function() {
notesModel.deleteNote(id) Notes.model.deleteNote(id)
}) })
} }
} }
@ -208,7 +211,7 @@ Page {
id: busyIndicator id: busyIndicator
anchors.centerIn: parent anchors.centerIn: parent
size: BusyIndicatorSize.Large size: BusyIndicatorSize.Large
running: notesList.count === 0 && notesApi.busy running: notesList.count === 0 && Nextcloud.busy
} }
Label { Label {
id: busyLabel id: busyLabel
@ -231,14 +234,14 @@ Page {
ViewPlaceholder { ViewPlaceholder {
id: noNotesPlaceholder id: noNotesPlaceholder
enabled: notesApi.status === 204 && !busyIndicator.running && !noLoginPlaceholder.enabled enabled: Nextcloud.status === 204 && !busyIndicator.running && !noLoginPlaceholder.enabled
text: qsTr("No notes yet") text: qsTr("No notes yet")
hintText: qsTr("Pull down to add a note") hintText: qsTr("Pull down to add a note")
} }
ViewPlaceholder { ViewPlaceholder {
id: noSearchPlaceholder id: noSearchPlaceholder
enabled: notesList.count === 0 && notesModel.searchFilter !== "" //notesModel.filterRegExp !== "" enabled: notesList.count === 0 && notesModel.searchFilter !== "" //Notes.model.filterRegExp !== ""
text: qsTr("No result") text: qsTr("No result")
hintText: qsTr("Try another query") hintText: qsTr("Try another query")
} }
@ -247,7 +250,7 @@ Page {
id: errorPlaceholder id: errorPlaceholder
enabled: notesList.count === 0 && !busyIndicator.running && !noSearchPlaceholder.enabled && !noNotesPlaceholder.enabled && !noLoginPlaceholder.enabled enabled: notesList.count === 0 && !busyIndicator.running && !noSearchPlaceholder.enabled && !noNotesPlaceholder.enabled && !noLoginPlaceholder.enabled
text: qsTr("An error occurred") text: qsTr("An error occurred")
//hintText: notesApi.statusText //hintText: Nextcloud.statusText
} }
TouchInteractionHint { TouchInteractionHint {

View file

@ -123,7 +123,9 @@ Page {
} }
} }
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (autoSyncIntervalRepeater.model[currentIndex] !== appSettings.autoSyncInterval) {
appSettings.autoSyncInterval = autoSyncIntervalRepeater.model[currentIndex] appSettings.autoSyncInterval = autoSyncIntervalRepeater.model[currentIndex]
}
if (autoSyncIntervalRepeater.model[currentIndex] === 42 && theAnswer.enabled) { if (autoSyncIntervalRepeater.model[currentIndex] === 42 && theAnswer.enabled) {
console.log(theAnswer.body) console.log(theAnswer.body)
theAnswer.publish() theAnswer.publish()

View file

@ -13,10 +13,10 @@ class AbstractNextcloudApp : public QObject {
public: public:
AbstractNextcloudApp(QObject *parent = nullptr, QString name = QString(), NextcloudApi* api = nullptr) : QObject(parent), m_appName(name), m_api(api) { AbstractNextcloudApp(QObject *parent = nullptr, QString name = QString(), NextcloudApi* api = nullptr) : QObject(parent), m_appName(name), m_api(api) {
connect(this, SIGNAL(capabilitiesChanged), this, SLOT(updateCapabilities)); connect(this, SIGNAL(capabilitiesChanged(QJsonObject*)), this, SLOT(updateCapabilities(QJsonObject*)));
connect(m_api, SIGNAL(capabilitiesChanged), this, SLOT(updateApiCapabilities)); connect(m_api, SIGNAL(capabilitiesChanged(QJsonObject*)), this, SLOT(updateApiCapabilities(QJsonObject*)));
connect(this, SIGNAL(replyReceived), this, SLOT(updateReply)); connect(this, SIGNAL(replyReceived(QNetworkReply*)), this, SLOT(updateReply(QNetworkReply*)));
connect(m_api, SIGNAL(replyReceived), this, SLOT(updateApiReply)); connect(m_api, SIGNAL(apiFinished(QNetworkReply*)), this, SLOT(updateApiReply(QNetworkReply*)));
} }
virtual ~AbstractNextcloudApp() { virtual ~AbstractNextcloudApp() {

View file

@ -32,7 +32,7 @@ public:
static AbstractNextcloudApp & getInstance(); static AbstractNextcloudApp & getInstance();
static QObject * provider(QQmlEngine *, QJSEngine *); static QObject * provider(QQmlEngine *, QJSEngine *);
const QSortFilterProxyModel* model() { return &m_notesProxy; } Q_INVOKABLE NotesProxyModel* model() { return &m_notesProxy; }
Q_INVOKABLE QVersionNumber serverVersion() const; Q_INVOKABLE QVersionNumber serverVersion() const;
Q_INVOKABLE QList<QVersionNumber> apiVersions() const; Q_INVOKABLE QList<QVersionNumber> apiVersions() const;
@ -47,7 +47,7 @@ public slots:
//Q_INVOKABLE bool changeSettings(const QJsonObject& settings); //Q_INVOKABLE bool changeSettings(const QJsonObject& settings);
protected slots: protected slots:
void updateCapabilities(QJsonObject* json) { } void updateCapabilities(QJsonObject*) { }
void updateReply(QNetworkReply* reply); void updateReply(QNetworkReply* reply);
signals: signals:

View file

@ -302,7 +302,7 @@ Qt::ItemFlags NotesModel::flags(const QModelIndex &index) const {
} }
} }
int NotesModel::rowCount(const QModelIndex &parent) const { int NotesModel::rowCount(const QModelIndex &) const {
if (m_fileDir.exists() && !account().isEmpty()) { if (m_fileDir.exists() && !account().isEmpty()) {
return static_cast<int>(m_fileDir.count()); return static_cast<int>(m_fileDir.count());
} }

View file

@ -20,9 +20,10 @@ int main(int argc, char *argv[])
AccountHash* accountHash = new AccountHash; AccountHash* accountHash = new AccountHash;
NextcloudApi::instantiate(app); NextcloudApi::instantiate(app);
qmlRegisterSingletonType<NextcloudApi>("harbour.nextcloudnotes.nextcloudapi", 1, 0, "Nextcloud", NextcloudApi::provider); qmlRegisterSingletonType<NextcloudApi>("harbour.nextcloudapi", 1, 0, "Nextcloud", NextcloudApi::provider);
NotesApp::instantiate(&NextcloudApi::getInstance(), &NextcloudApi::getInstance()); NotesApp::instantiate(&NextcloudApi::getInstance(), &NextcloudApi::getInstance());
qmlRegisterSingletonType<NotesApp>("harbour.nextcloudnotes.nextcloudapi", 1, 0, "Notes", NotesApp::provider); qmlRegisterSingletonType<NotesApp>("harbour.nextcloudapi.notes", 1, 0, "Notes", NotesApp::provider);
qmlRegisterType<NotesProxyModel>("harbour.nextcloudapi.notes", 1, 0, "NotesModel");
//qmlRegisterType<NextcloudApi>("NextcloudApi", 1, 0, "Nextcloud"); //qmlRegisterType<NextcloudApi>("NextcloudApi", 1, 0, "Nextcloud");
//qmlRegisterType<NotesApp>("NextcloudApi", 1, 0, "Notes"); //qmlRegisterType<NotesApp>("NextcloudApi", 1, 0, "Notes");

View file

@ -12,7 +12,7 @@ NextcloudApi::NextcloudApi(QObject *parent) : QObject(parent)
setUserMetaStatus(ApiCallStatus::ApiUnknown); setUserMetaStatus(ApiCallStatus::ApiUnknown);
// Verify URL // Verify URL
connect(this, SIGNAL(urlChanged(QUrl)), this, SLOT(verifyUrl(QUrl))); connect(this, SIGNAL(urlChanged(QUrl*)), this, SLOT(verifyUrl(QUrl*)));
// Login Flow V2 poll timer // Login Flow V2 poll timer
m_loginPollTimer.setInterval(LOGIN_FLOWV2_POLL_INTERVALL); m_loginPollTimer.setInterval(LOGIN_FLOWV2_POLL_INTERVALL);
@ -259,7 +259,7 @@ bool NextcloudApi::initiateFlowV2Login() {
if (m_loginStatus == LoginStatus::LoginFlowV2Initiating || m_loginStatus == LoginStatus::LoginFlowV2Polling) { if (m_loginStatus == LoginStatus::LoginFlowV2Initiating || m_loginStatus == LoginStatus::LoginFlowV2Polling) {
abortFlowV2Login(); abortFlowV2Login();
} }
if (post(LOGIN_FLOWV2_ENDPOINT, QByteArray(), false)) { if (post(LOGIN_FLOWV2_ENDPOINT, QByteArray(), ReplyJSON, false)) {
setLoginStatus(LoginStatus::LoginFlowV2Initiating); setLoginStatus(LoginStatus::LoginFlowV2Initiating);
return true; return true;
} }
@ -327,7 +327,7 @@ void NextcloudApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAcce
} }
bool NextcloudApi::pollLoginUrl() { bool NextcloudApi::pollLoginUrl() {
if (post(m_pollUrl.path(), QByteArray("token=").append(m_pollToken), false)) { if (post(m_pollUrl.path(), QByteArray("token=").append(m_pollToken), ReplyJSON, false)) {
setLoginStatus(LoginStatus::LoginFlowV2Polling); setLoginStatus(LoginStatus::LoginFlowV2Polling);
return true; return true;
} }
@ -350,6 +350,7 @@ void NextcloudApi::replyFinished(QNetworkReply* reply) {
if (reply->error() != QNetworkReply::NoError) if (reply->error() != QNetworkReply::NoError)
qDebug() << reply->error() << reply->errorString(); qDebug() << reply->error() << reply->errorString();
qDebug() << reply->url().toDisplayString();
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
QJsonDocument json = QJsonDocument::fromJson(data); QJsonDocument json = QJsonDocument::fromJson(data);
//qDebug() << data; //qDebug() << data;
@ -367,7 +368,7 @@ void NextcloudApi::replyFinished(QNetworkReply* reply) {
qDebug() << "App password received"; qDebug() << "App password received";
updateAppPassword(json.object()); updateAppPassword(json.object());
} }
else if (reply->url().toString().contains(USER_METADATA_ENDPOINT)) { else if (reply->url().toString().contains(QString(USER_METADATA_ENDPOINT).remove(QRegExp("/%[0-9]")))) {
qDebug() << "User metadata for" << reply->url().toString().split('/').last() << "received"; qDebug() << "User metadata for" << reply->url().toString().split('/').last() << "received";
updateUserMeta(json.object()); updateUserMeta(json.object());
} }
@ -545,7 +546,7 @@ bool NextcloudApi::updateAppPassword(const QJsonObject &json) {
return false; return false;
} }
bool NextcloudApi::deleteAppPassword(const QJsonObject &json) { bool NextcloudApi::deleteAppPassword(const QJsonObject &) {
setPassword(QString()); setPassword(QString());
return true; return true;
} }

View file

@ -182,10 +182,6 @@
<source>Note</source> <source>Note</source>
<translation>Achtung</translation> <translation>Achtung</translation>
</message> </message>
<message>
<source>The &lt;a href=&quot;https://apps.nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; app needs to be installed on the Nextcloud server for this app to work.</source>
<translation>Die &lt;a href=&quot;https://apps.nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; Applikation muss auf dem Nextcloud-Server installiert sein, damit diese App funktioniert.</translation>
</message>
<message> <message>
<source>Re-Login</source> <source>Re-Login</source>
<translation>Neu einloggen</translation> <translation>Neu einloggen</translation>
@ -214,6 +210,10 @@
<source>Enter Password</source> <source>Enter Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>The &lt;a href=&quot;https://apps.Nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; app needs to be installed on the Nextcloud server for this app to work.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>MITLicense</name> <name>MITLicense</name>

View file

@ -182,10 +182,6 @@
<source>Note</source> <source>Note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>The &lt;a href=&quot;https://apps.nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; app needs to be installed on the Nextcloud server for this app to work.</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Re-Login</source> <source>Re-Login</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -214,6 +210,10 @@
<source>Enter Password</source> <source>Enter Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>The &lt;a href=&quot;https://apps.Nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; app needs to be installed on the Nextcloud server for this app to work.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>MITLicense</name> <name>MITLicense</name>

View file

@ -138,123 +138,123 @@
<context> <context>
<name>LoginPage</name> <name>LoginPage</name>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="129"/> <location filename="../qml/pages/LoginPage.qml" line="120"/>
<source>Nextcloud Login</source> <source>Nextcloud Login</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="223"/> <location filename="../qml/pages/LoginPage.qml" line="214"/>
<source>Username</source> <source>Username</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="239"/> <location filename="../qml/pages/LoginPage.qml" line="230"/>
<source>Password</source> <source>Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="207"/> <location filename="../qml/pages/LoginPage.qml" line="186"/>
<source>Abort</source> <source>Abort</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="84"/> <location filename="../qml/pages/LoginPage.qml" line="75"/>
<source>Follow the instructions in the browser</source> <source>Follow the instructions in the browser</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="97"/> <location filename="../qml/pages/LoginPage.qml" line="88"/>
<source>Login successfull!</source> <source>Login successfull!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="93"/> <location filename="../qml/pages/LoginPage.qml" line="84"/>
<location filename="../qml/pages/LoginPage.qml" line="104"/> <location filename="../qml/pages/LoginPage.qml" line="95"/>
<source>Login failed!</source> <source>Login failed!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="76"/> <location filename="../qml/pages/LoginPage.qml" line="67"/>
<source>Enter your credentials</source> <source>Enter your credentials</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="158"/> <location filename="../qml/pages/LoginPage.qml" line="149"/>
<source>Nextcloud address</source> <source>Nextcloud address</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="144"/> <location filename="../qml/pages/LoginPage.qml" line="135"/>
<source>Verifying address</source> <source>Verifying address</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="157"/> <location filename="../qml/pages/LoginPage.qml" line="148"/>
<source>Enter Nextcloud address</source> <source>Enter Nextcloud address</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="189"/> <location filename="../qml/pages/LoginPage.qml" line="194"/>
<source>Enforce legacy login</source> <source>Enforce legacy login</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="207"/> <location filename="../qml/pages/LoginPage.qml" line="186"/>
<source>Login</source> <source>Login</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="207"/> <location filename="../qml/pages/LoginPage.qml" line="186"/>
<source>Re-Login</source> <source>Re-Login</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="222"/> <location filename="../qml/pages/LoginPage.qml" line="213"/>
<source>Enter Username</source> <source>Enter Username</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="238"/> <location filename="../qml/pages/LoginPage.qml" line="229"/>
<source>Enter Password</source> <source>Enter Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="251"/> <location filename="../qml/pages/LoginPage.qml" line="242"/>
<source>Test Login</source> <source>Test Login</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="257"/> <location filename="../qml/pages/LoginPage.qml" line="248"/>
<source>Note</source> <source>Note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="265"/> <location filename="../qml/pages/LoginPage.qml" line="256"/>
<source>The &lt;a href=&quot;https://apps.nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; app needs to be installed on the Nextcloud server for this app to work.</source> <source>The &lt;a href=&quot;https://apps.Nextcloud.com/apps/notes&quot;&gt;Notes&lt;/a&gt; app needs to be installed on the Nextcloud server for this app to work.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="269"/> <location filename="../qml/pages/LoginPage.qml" line="260"/>
<source>Security</source> <source>Security</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="276"/> <location filename="../qml/pages/LoginPage.qml" line="267"/>
<source>&lt;strong&gt;CAUTION: Your password will be saved without any encryption on the device!&lt;/strong&gt;&lt;br&gt;Please consider creating a dedicated app password! Open your Nextcloud in a browser and go to &lt;i&gt;Settings&lt;/i&gt; &lt;i&gt;Security&lt;/i&gt;.</source> <source>&lt;strong&gt;CAUTION: Your password will be saved without any encryption on the device!&lt;/strong&gt;&lt;br&gt;Please consider creating a dedicated app password! Open your Nextcloud in a browser and go to &lt;i&gt;Settings&lt;/i&gt; &lt;i&gt;Security&lt;/i&gt;.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/LoginPage.qml" line="281"/> <location filename="../qml/pages/LoginPage.qml" line="272"/>
<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/LoginPage.qml" line="282"/> <location filename="../qml/pages/LoginPage.qml" line="273"/>
<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/LoginPage.qml" line="291"/> <location filename="../qml/pages/LoginPage.qml" line="282"/>
<source>Allow unencrypted connections</source> <source>Allow unencrypted connections</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -275,32 +275,32 @@
<context> <context>
<name>NextcloudApi</name> <name>NextcloudApi</name>
<message> <message>
<location filename="../src/nextcloudapi.cpp" line="180"/> <location filename="../src/nextcloudapi.cpp" line="178"/>
<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="183"/> <location filename="../src/nextcloudapi.cpp" line="181"/>
<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="186"/> <location filename="../src/nextcloudapi.cpp" line="184"/>
<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="189"/> <location filename="../src/nextcloudapi.cpp" line="187"/>
<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="192"/> <location filename="../src/nextcloudapi.cpp" line="190"/>
<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="195"/> <location filename="../src/nextcloudapi.cpp" line="193"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -308,12 +308,12 @@
<context> <context>
<name>Note</name> <name>Note</name>
<message> <message>
<location filename="../src/note.cpp" line="357"/> <location filename="../src/apps/notes/note.cpp" line="357"/>
<source>Today</source> <source>Today</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/note.cpp" line="359"/> <location filename="../src/apps/notes/note.cpp" line="359"/>
<source>Yesterday</source> <source>Yesterday</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -374,32 +374,32 @@
<context> <context>
<name>NotesApi</name> <name>NotesApi</name>
<message> <message>
<location filename="../src/notesapi.cpp" line="371"/> <location filename="../src/apps/notes/notesapi.cpp" line="371"/>
<source>No error</source> <source>No error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/notesapi.cpp" line="374"/> <location filename="../src/apps/notes/notesapi.cpp" line="374"/>
<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="377"/> <location filename="../src/apps/notes/notesapi.cpp" line="377"/>
<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="380"/> <location filename="../src/apps/notes/notesapi.cpp" line="380"/>
<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="383"/> <location filename="../src/apps/notes/notesapi.cpp" line="383"/>
<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="386"/> <location filename="../src/apps/notes/notesapi.cpp" line="386"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -407,97 +407,97 @@
<context> <context>
<name>NotesPage</name> <name>NotesPage</name>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="30"/> <location filename="../qml/pages/NotesPage.qml" line="31"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="34"/> <location filename="../qml/pages/NotesPage.qml" line="35"/>
<source>Add note</source> <source>Add note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="39"/> <location filename="../qml/pages/NotesPage.qml" line="41"/>
<source>Reload</source> <source>Reload</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="39"/> <location filename="../qml/pages/NotesPage.qml" line="41"/>
<source>Updating...</source> <source>Updating...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="45"/> <location filename="../qml/pages/NotesPage.qml" line="48"/>
<source>Last update</source> <source>Last update</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="48"/> <location filename="../qml/pages/NotesPage.qml" line="51"/>
<source>never</source> <source>never</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="58"/> <location filename="../qml/pages/NotesPage.qml" line="61"/>
<source>Nextcloud Notes</source> <source>Nextcloud Notes</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="187"/> <location filename="../qml/pages/NotesPage.qml" line="190"/>
<source>Modified</source> <source>Modified</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="190"/> <location filename="../qml/pages/NotesPage.qml" line="193"/>
<source>Delete</source> <source>Delete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="192"/> <location filename="../qml/pages/NotesPage.qml" line="195"/>
<source>Deleting note</source> <source>Deleting note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="222"/> <location filename="../qml/pages/NotesPage.qml" line="225"/>
<source>Loading notes...</source> <source>Loading notes...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="228"/> <location filename="../qml/pages/NotesPage.qml" line="231"/>
<source>No account yet</source> <source>No account yet</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="229"/> <location filename="../qml/pages/NotesPage.qml" line="232"/>
<source>Got to the settings to add an account</source> <source>Got to the settings to add an account</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="235"/> <location filename="../qml/pages/NotesPage.qml" line="238"/>
<source>No notes yet</source> <source>No notes yet</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="236"/> <location filename="../qml/pages/NotesPage.qml" line="239"/>
<source>Pull down to add a note</source> <source>Pull down to add a note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="242"/> <location filename="../qml/pages/NotesPage.qml" line="245"/>
<source>No result</source> <source>No result</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="243"/> <location filename="../qml/pages/NotesPage.qml" line="246"/>
<source>Try another query</source> <source>Try another query</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="249"/> <location filename="../qml/pages/NotesPage.qml" line="252"/>
<source>An error occurred</source> <source>An error occurred</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/NotesPage.qml" line="260"/> <location filename="../qml/pages/NotesPage.qml" line="263"/>
<source>Open the settings to configure your Nextcloud accounts</source> <source>Open the settings to configure your Nextcloud accounts</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -585,122 +585,122 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="136"/> <location filename="../qml/pages/SettingsPage.qml" line="138"/>
<source>The Answer is 42</source> <source>The Answer is 42</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="137"/> <location filename="../qml/pages/SettingsPage.qml" line="139"/>
<source>Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything!</source> <source>Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="145"/> <location filename="../qml/pages/SettingsPage.qml" line="147"/>
<source>Appearance</source> <source>Appearance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="153"/> <location filename="../qml/pages/SettingsPage.qml" line="155"/>
<source>No sorting</source> <source>No sorting</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="177"/> <location filename="../qml/pages/SettingsPage.qml" line="179"/>
<source>Favorites on top</source> <source>Favorites on top</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="178"/> <location filename="../qml/pages/SettingsPage.qml" line="180"/>
<source>Show notes marked as favorite above the others</source> <source>Show notes marked as favorite above the others</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="216"/> <location filename="../qml/pages/SettingsPage.qml" line="218"/>
<source>Reset</source> <source>Reset</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="219"/> <location filename="../qml/pages/SettingsPage.qml" line="221"/>
<source>Reset app settings</source> <source>Reset app settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="221"/> <location filename="../qml/pages/SettingsPage.qml" line="223"/>
<source>Cleared app data</source> <source>Cleared app data</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="224"/> <location filename="../qml/pages/SettingsPage.qml" line="226"/>
<source>Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts.</source> <source>Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="150"/> <location filename="../qml/pages/SettingsPage.qml" line="152"/>
<source>Last edited</source> <source>Last edited</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="151"/> <location filename="../qml/pages/SettingsPage.qml" line="153"/>
<source>Category</source> <source>Category</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="152"/> <location filename="../qml/pages/SettingsPage.qml" line="154"/>
<source>Title alphabetically</source> <source>Title alphabetically</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="155"/> <location filename="../qml/pages/SettingsPage.qml" line="157"/>
<source>Sort notes by</source> <source>Sort notes by</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="156"/> <location filename="../qml/pages/SettingsPage.qml" line="158"/>
<source>This will also change how the notes are grouped</source> <source>This will also change how the notes are grouped</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="183"/> <location filename="../qml/pages/SettingsPage.qml" line="185"/>
<source>Show separator</source> <source>Show separator</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="184"/> <location filename="../qml/pages/SettingsPage.qml" line="186"/>
<source>Show a separator line between the notes</source> <source>Show a separator line between the notes</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="194"/> <location filename="../qml/pages/SettingsPage.qml" line="196"/>
<source>lines</source> <source>lines</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="195"/> <location filename="../qml/pages/SettingsPage.qml" line="197"/>
<source>Number of lines in the preview</source> <source>Number of lines in the preview</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="200"/> <location filename="../qml/pages/SettingsPage.qml" line="202"/>
<source>Editing</source> <source>Editing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="203"/> <location filename="../qml/pages/SettingsPage.qml" line="205"/>
<source>Monospaced font</source> <source>Monospaced font</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="204"/> <location filename="../qml/pages/SettingsPage.qml" line="206"/>
<source>Use a monospeced font to edit a note</source> <source>Use a monospeced font to edit a note</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="209"/> <location filename="../qml/pages/SettingsPage.qml" line="211"/>
<source>Capital &apos;X&apos; in checkboxes</source> <source>Capital &apos;X&apos; in checkboxes</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../qml/pages/SettingsPage.qml" line="210"/> <location filename="../qml/pages/SettingsPage.qml" line="212"/>
<source>For interoperability with other apps such as Joplin</source> <source>For interoperability with other apps such as Joplin</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="98"/> <location filename="../qml/harbour-nextcloudnotes.qml" line="111"/>
<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="99"/> <location filename="../qml/harbour-nextcloudnotes.qml" line="112"/>
<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="100"/> <location filename="../qml/harbour-nextcloudnotes.qml" line="113"/>
<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="114"/> <location filename="../qml/harbour-nextcloudnotes.qml" line="127"/>
<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="107"/> <location filename="../qml/harbour-nextcloudnotes.qml" line="120"/>
<source>File error</source> <source>File error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>