From 9fc188dbe63996fd7d2212a7a85385ad56a8e23a Mon Sep 17 00:00:00 2001 From: scharel Date: Sun, 25 Jul 2021 18:28:58 +0200 Subject: [PATCH] Account handling --- qml/harbour-nextcloudnotes.qml | 30 ++-- qml/pages/NotesPage.qml | 4 +- qml/pages/SettingsPage.qml | 6 +- src/apps/notes/notesapp.cpp | 10 ++ src/apps/notes/notesapp.h | 4 +- src/apps/notes/notesmodel.cpp | 160 ++++++++++--------- src/apps/notes/notesmodel.h | 17 ++- src/harbour-nextcloudnotes.cpp | 3 - src/nextcloudapi.cpp | 6 + src/nextcloudapi.h | 2 + translations/harbour-nextcloudnotes-de.ts | 174 ++++++++++----------- translations/harbour-nextcloudnotes-sv.ts | 178 +++++++++++----------- translations/harbour-nextcloudnotes.ts | 92 +++++------ 13 files changed, 363 insertions(+), 323 deletions(-) diff --git a/qml/harbour-nextcloudnotes.qml b/qml/harbour-nextcloudnotes.qml index 7b565dd..50207b7 100644 --- a/qml/harbour-nextcloudnotes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -18,13 +18,20 @@ ApplicationWindow //console.log("Current account: ", appSettings.currentAccount) } + // Workaround as ConfigurationGroup does not store arrays + ConfigurationValue { + id: accountList + key: appSettings.path + "/accountList" + defaultValue: [] + } + // General settings of the app ConfigurationGroup { id: appSettings path: "/apps/harbour-nextcloudnotes" property bool initialized: false - property var accountList: value("accountList", [], Array) + //property var accountList: value("accountList", [], Array) property string currentAccount: value("currentAccount", "", String) property int autoSyncInterval: value("autoSyncInterval", 0, Number) property int previewLineCount: value("previewLineCount", 4, Number) @@ -42,10 +49,10 @@ ApplicationWindow } function createAccount(username, password, url, name) { - var hash = accountHash.hash(username, url) - var tmpaccounts = accountList - tmpaccounts.push(hash) - accountList = tmpaccounts + var hash = nextcloudApi.accountHash(username, url) + var tmpAccountList = accountList.value + tmpAccountList.push(hash) + accountList.value = tmpAccountList tmpAccount.path = appSettings.path + "/accounts/" + hash tmpAccount.url = url @@ -60,14 +67,14 @@ ApplicationWindow Nextcloud.deleteAppPassword(appSettings.value("accounts/" + hash + "/password"), appSettings.value("accounts/" + hash + "/username"), appSettings.value("accounts/" + hash + "/url")) - var tmpaccounts = accountList - tmpaccounts.pop(hash) - accountList = tmpaccounts + var tmpAccountList = accountList.value + tmpAccountList.pop(hash) + accountList.value = tmpAccountList tmpAccount.path = appSettings.path + "/accounts/" + hash tmpAccount.clear() - if (accountList[-1]) { - currentAccount = accountList[-1] + if (accountList.value[-1]) { + currentAccount = accountList.value[-1] } else { currentAccount = "" @@ -81,8 +88,7 @@ ApplicationWindow target: appSettings onCurrentAccountChanged: { account.path = appSettings.path + "/accounts/" + appSettings.currentAccount - console.log("Current account: " + account.username + "@" + account.url) - notesApp.model().account = appSettings.currentAccount + console.log("Current account: " + account.username + "@" + String(account.url).split('//')[1]) } } diff --git a/qml/pages/NotesPage.qml b/qml/pages/NotesPage.qml index 0523a1a..bae6c73 100644 --- a/qml/pages/NotesPage.qml +++ b/qml/pages/NotesPage.qml @@ -8,7 +8,7 @@ Page { onStatusChanged: { if (status === PageStatus.Activating) { - if (appSettings.accountList.length <= 0) { + if (accountList.value.length <= 0) { addAccountHint.restart() } else { @@ -228,7 +228,7 @@ Page { ViewPlaceholder { id: noLoginPlaceholder - enabled: appSettings.accountList.length <= 0 + enabled: accountList.value.length <= 0 text: qsTr("No account yet") hintText: qsTr("Got to the settings to add an account") } diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml index 34a9151..8b4d1f9 100644 --- a/qml/pages/SettingsPage.qml +++ b/qml/pages/SettingsPage.qml @@ -32,7 +32,7 @@ Page { } Label { id: noAccountsLabel - visible: appSettings.accountList.length <= 0 + visible: accountList.value.length <= 0 text: qsTr("No Nextcloud account yet") font.pixelSize: Theme.fontSizeLarge color: Theme.secondaryHighlightColor @@ -43,7 +43,7 @@ Page { } Repeater { id: accountRepeater - model: appSettings.accountList + model: accountList.value delegate: ListItem { id: accountListItem @@ -63,7 +63,7 @@ Page { TextSwitch { id: accountTextSwitch text: settingsAccount.name - description: settingsAccount.username + "@" + settingsAccount.url + description: settingsAccount.username + "@" + String(settingsAccount.url).split('//')[1] automaticCheck: false checked: modelData === appSettings.currentAccount onClicked: { diff --git a/src/apps/notes/notesapp.cpp b/src/apps/notes/notesapp.cpp index 03b64e3..9e985e5 100644 --- a/src/apps/notes/notesapp.cpp +++ b/src/apps/notes/notesapp.cpp @@ -3,6 +3,7 @@ NotesApp::NotesApp(QObject *parent, NextcloudApi* api) : AbstractNextcloudApp(parent, "notes", api) { m_notesProxy.setSourceModel(&m_notesModel); + connect(api, SIGNAL(readyChanged(bool)), this, SLOT(onApiReady(bool))); connect(this, SIGNAL(capabilitiesChanged(QJsonObject*)), this, SLOT(updateCapabilities(QJsonObject*))); connect(this, SIGNAL(replyReceived(QNetworkReply*)), this, SLOT(updateReply(QNetworkReply*))); } @@ -38,6 +39,15 @@ QList NotesApp::apiVersions() const { return versions; } +// FIXME +void NotesApp::updateUrl(QUrl* url) { + if (url->isValid() && m_api->ready()) { + QUrl myUrl = m_api->url(); + myUrl.setUserInfo(QString()); + m_notesModel.setAccount(m_api->accountHash(m_api->username(), myUrl.toString())); + } +} + bool NotesApp::getAllNotes(const QStringList& exclude) { qDebug() << "Getting all notes"; QUrlQuery query; diff --git a/src/apps/notes/notesapp.h b/src/apps/notes/notesapp.h index 1529f12..f4ca6f1 100644 --- a/src/apps/notes/notesapp.h +++ b/src/apps/notes/notesapp.h @@ -24,7 +24,6 @@ class NotesApp : public AbstractNextcloudApp { public: NotesApp(QObject *parent = nullptr, NextcloudApi* api = nullptr); - virtual ~NotesApp() {} // QML singleton @@ -32,8 +31,10 @@ public: static AbstractNextcloudApp & getInstance(); static QObject * provider(QQmlEngine *, QJSEngine *); + // Notes model Q_INVOKABLE NotesProxyModel* model() { return &m_notesProxy; } + // Properties Q_INVOKABLE QVersionNumber serverVersion() const; Q_INVOKABLE QList apiVersions() const; @@ -45,6 +46,7 @@ public slots: Q_INVOKABLE bool deleteNote(const int id, bool local = false); //Q_INVOKABLE bool getSettings(); //Q_INVOKABLE bool changeSettings(const QJsonObject& settings); + void updateUrl(QUrl* url); protected slots: void updateCapabilities(QJsonObject*) { } diff --git a/src/apps/notes/notesmodel.cpp b/src/apps/notes/notesmodel.cpp index 9dadc8f..83b006a 100644 --- a/src/apps/notes/notesmodel.cpp +++ b/src/apps/notes/notesmodel.cpp @@ -107,6 +107,7 @@ void NotesModel::setAccount(const QString& account) { } if (!account.isEmpty()) { m_fileDir.setPath(account); + qDebug() << m_fileDir.absolutePath(); if (m_fileDir.mkpath(".")) { m_fileDir.setFilter(QDir::Files | QDir::NoDotAndDotDot); m_fileDir.setSorting(QDir::Name | QDir::DirsLast); @@ -156,6 +157,84 @@ int NotesModel::noteModified(const int id) { } */ +void NotesModel::insert(int id, const QJsonObject& json) { + if (id < 0) { + id = json.value(m_roleNames[IdRole]).toInt(-1); + } + if (id >= 0) { + qDebug() << "Inserting note: " << id; + if (indexOfNoteById(id) >= 0) { + qDebug() << "Note already present"; + update(id, json); + } + else { + int newPosition = indexOfNoteById(id, true); + qDebug() << "New position: " << newPosition; + beginInsertRows(QModelIndex(), newPosition, newPosition); + setNoteFile(json.toVariantMap(), id); + endInsertRows(); + //emit noteInserted(id, note); + qDebug() << "Note inserted"; + } + } +} + +void NotesModel::update(int id, const QJsonObject &json) { + if (id < 0) { + id = json.value(m_roleNames[IdRole]).toInt(-1); + } + if (id >= 0) { + qDebug() << "Updating note: " << id; + if (indexOfNoteById(id) < 0) { + qDebug() << "Note is new"; + insert(id, json); + } + else { + int newPosition = indexOfNoteById(id); + setNoteFile(json.toVariantMap(), id); + emit dataChanged(index(newPosition), index(newPosition)); + qDebug() << "Note changed"; + } + } +} + +void NotesModel::remove(int id) { + qDebug() << "Removing note: " << id; + int newPosition = indexOfNoteById(id); + if (newPosition >= 0) { + beginRemoveRows(QModelIndex(), newPosition, newPosition); + deleteNoteFile(id); + endRemoveRows(); + qDebug() << "Note removed"; + } +} + +int NotesModel::indexOfNoteById(int id, bool nonexistant) const { + int index = -1; + if (m_fileDir.exists() && !account().isEmpty()) { + QStringList fileList = m_fileDir.entryList(); + if (nonexistant) { + fileList << QString("^%1.%2$").arg(id).arg(m_fileSuffix); + fileList.sort(Qt::CaseInsensitive); + } + qDebug() << fileList; + index = fileList.indexOf(QRegExp(QString("^%1.%2$").arg(id).arg(m_fileSuffix))); + } + return index; +} + +int NotesModel::idOfNoteByINdex(int index) const { + int id = -1; + if (m_fileDir.exists() && !account().isEmpty()) { + QFileInfo fileName = m_fileDir.entryInfoList().value(index); + bool ok; + id = fileName.baseName().toInt(&ok); + if (!ok) id = -1; + } + return id; +} + +/* int NotesModel::newNotePosition(const int id) const { if (m_fileDir.exists() && !account().isEmpty() && id >= 0) { QStringList fileList = m_fileDir.entryList(); @@ -167,8 +246,9 @@ int NotesModel::newNotePosition(const int id) const { } return -1; } +*/ -const QVariantMap NotesModel::note(const int id) const { +const QVariantMap NotesModel::getNoteFile(const int id) const { QVariantMap json; if (m_fileDir.exists() && !account().isEmpty() && id >= 0) { QFileInfo fileinfo(m_fileDir, QString("%1.%2").arg(id).arg(m_fileSuffix)); @@ -183,7 +263,7 @@ const QVariantMap NotesModel::note(const int id) const { return json; } -bool NotesModel::setNote(const QVariantMap ¬e, int id) { +bool NotesModel::setNoteFile(const QVariantMap ¬e, int id) { bool ok; if (id < 0) { id = note.value(m_roleNames[IdRole]).toInt(&ok); @@ -204,7 +284,7 @@ bool NotesModel::setNote(const QVariantMap ¬e, int id) { return ok; } -bool NotesModel::deleteNote(const int id) { +bool NotesModel::deleteNoteFile(const int id) { if (m_fileDir.exists() && !account().isEmpty() && id >= 0) { QFileInfo fileinfo(m_fileDir, QString("%1.%2").arg(id).arg(m_fileSuffix)); QFile file(fileinfo.filePath()); @@ -217,74 +297,6 @@ bool NotesModel::deleteNote(const int id) { return false; } -void NotesModel::insert(int id, const QJsonObject& json) { - if (id < 0) { - id = json.value(m_roleNames[IdRole]).toInt(-1); - } - if (id >= 0) { - qDebug() << "Inserting note: " << id; - if (indexOfNoteById(id) >= 0) { - qDebug() << "Note already present"; - update(id, json); - } - else { - qDebug() << "New position: " << newNotePosition(id); - beginInsertRows(QModelIndex(), newNotePosition(id), newNotePosition(id)); - setNote(json.toVariantMap(), id); - endInsertRows(); - //emit noteInserted(id, note); - qDebug() << "Note inserted"; - } - } -} - -void NotesModel::update(int id, const QJsonObject &json) { - if (id < 0) { - id = json.value(m_roleNames[IdRole]).toInt(-1); - } - if (id >= 0) { - qDebug() << "Updating note: " << id; - if (indexOfNoteById(id) < 0) { - qDebug() << "Note is new"; - insert(id, json); - } - else { - setNote(json.toVariantMap(), id); - emit dataChanged(index(indexOfNoteById(id)), index(indexOfNoteById(id))); - qDebug() << "Note changed"; - } - } -} - -void NotesModel::remove(int id) { - qDebug() << "Removing note: " << id; - if (indexOfNoteById(id) >= 0) { - beginRemoveRows(QModelIndex(), indexOfNoteById(id), indexOfNoteById(id)); - deleteNote(id); - endRemoveRows(); - qDebug() << "Note removed"; - } -} - -int NotesModel::indexOfNoteById(int id) const { - int index = -1; - if (m_fileDir.exists() && !account().isEmpty()) { - index = m_fileDir.entryList().indexOf(QRegExp(QString("^%1.%2$").arg(id).arg(m_fileSuffix))); - } - return index; -} - -int NotesModel::idOfNoteByINdex(int index) const { - int id = -1; - if (m_fileDir.exists() && !account().isEmpty()) { - QFileInfo fileName = m_fileDir.entryInfoList().value(index); - bool ok; - id = fileName.baseName().toInt(&ok); - if (!ok) id = -1; - } - return id; -} - QHash NotesModel::roleNames() const { return m_roleNames; } @@ -326,7 +338,7 @@ bool NotesModel::setData(const QModelIndex &index, const QVariant &value, int ro QMap NotesModel::itemData(const QModelIndex &index) const { QMap map; if (index.isValid() && index.row() < rowCount()) { - QVariantMap note = this->note(idOfNoteByINdex(index.row())); + QVariantMap note = this->getNoteFile(idOfNoteByINdex(index.row())); for (int role = IdRole; role <= ErrorMessageRole; ++role) { map.insert(role, note.value(m_roleNames[role])); } @@ -337,13 +349,13 @@ QMap NotesModel::itemData(const QModelIndex &index) const { bool NotesModel::setItemData(const QModelIndex &index, const QMap &roles) { QVariantMap note; if (index.isValid() && index.row() < rowCount()) { - note = this->note(idOfNoteByINdex(index.row())); + note = this->getNoteFile(idOfNoteByINdex(index.row())); QMapIterator i(roles); while (i.hasNext()) { i.next(); note.insert(m_roleNames[i.key()], i.value()); } - return setNote(note, idOfNoteByINdex(index.row())); + return setNoteFile(note, idOfNoteByINdex(index.row())); } return false; } diff --git a/src/apps/notes/notesmodel.h b/src/apps/notes/notesmodel.h index 46333ef..d0f0af8 100644 --- a/src/apps/notes/notesmodel.h +++ b/src/apps/notes/notesmodel.h @@ -24,8 +24,10 @@ public: void setFavoritesOnTop(bool favoritesOnTop); QString sortBy() const { return roleNames().value(m_sortByRole); } void setSortBy(const QString sortBy); + Q_INVOKABLE void clearSortBy() { setSortRole(-1); } QString searchFilter() const { return m_searchFilterString; } void setSearchFilter(const QString searchFilter); + Q_INVOKABLE void clearSearchFilter() { setFilterFixedString(""); } //Q_INVOKABLE void sort(); @@ -80,17 +82,12 @@ public: virtual QMap itemData(const QModelIndex &index) const; virtual bool setItemData(const QModelIndex &index, const QMap &roles); - int newNotePosition(const int id) const; - Q_INVOKABLE const QVariantMap note(const int id) const; - Q_INVOKABLE bool setNote(const QVariantMap& note, int id = -1); - Q_INVOKABLE bool deleteNote(const int id); - public slots: void insert(int id, const QJsonObject& json); void update(int id, const QJsonObject& json); void remove(int id); - Q_INVOKABLE int indexOfNoteById(int id) const; + Q_INVOKABLE int indexOfNoteById(int id, bool nonexistant = false) const; Q_INVOKABLE int idOfNoteByINdex(int index) const; signals: @@ -100,6 +97,14 @@ signals: private: const static QHash m_roleNames; + /* + int newNotePosition(const int id) const; + */ + Q_INVOKABLE const QVariantMap getNoteFile(const int id) const; + Q_INVOKABLE bool setNoteFile(const QVariantMap& note, int id = -1); + Q_INVOKABLE bool deleteNoteFile(const int id); + + QDir m_fileDir; const static QString m_fileSuffix; }; diff --git a/src/harbour-nextcloudnotes.cpp b/src/harbour-nextcloudnotes.cpp index a48380a..cbff0e1 100644 --- a/src/harbour-nextcloudnotes.cpp +++ b/src/harbour-nextcloudnotes.cpp @@ -2,7 +2,6 @@ #include #include #include -#include "accounthash.h" #include "nextcloudapi.h" #include "apps/abstractnextcloudapp.h" #include "apps/notes/notesapp.h" @@ -18,7 +17,6 @@ int main(int argc, char *argv[]) qDebug() << app->applicationDisplayName() << app->applicationVersion(); - AccountHash* accountHash = new AccountHash; NextcloudApi::instantiate(app); qmlRegisterSingletonType("harbour.nextcloudapi", 1, 0, "Nextcloud", NextcloudApi::provider); NotesApp::instantiate(&NextcloudApi::getInstance(), &NextcloudApi::getInstance()); @@ -33,7 +31,6 @@ int main(int argc, char *argv[]) #else view->rootContext()->setContextProperty("debug", QVariant(false)); #endif - view->rootContext()->setContextProperty("accountHash", accountHash); view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml")); view->show(); diff --git a/src/nextcloudapi.cpp b/src/nextcloudapi.cpp index 01c7b82..e14ad5a 100644 --- a/src/nextcloudapi.cpp +++ b/src/nextcloudapi.cpp @@ -152,6 +152,12 @@ void NextcloudApi::setPassword(QString password) { } } +const QString NextcloudApi::accountHash(const QString username, const QString url) { + QByteArray data = QString("%1@%2").arg(username).arg(url).toUtf8(); + QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5); + return hash.toHex(); +} + bool NextcloudApi::appInstalled(const QString& name) const { QJsonObject app = m_capabilities.value(name).toObject(); return !app.isEmpty(); diff --git a/src/nextcloudapi.h b/src/nextcloudapi.h index 9620bb5..741b140 100644 --- a/src/nextcloudapi.h +++ b/src/nextcloudapi.h @@ -150,6 +150,8 @@ public: QString password() const { return m_url.password(); } void setPassword(QString password); + Q_INVOKABLE static const QString accountHash(const QString username, const QString url); + // Class status information bool ready() const { return urlValid() && networkAccessible() && !busy() && statusInstalled() && !statusMaintenance() && loginStatus() == LoginSuccess; } bool urlValid() const { return m_url.isValid(); } diff --git a/translations/harbour-nextcloudnotes-de.ts b/translations/harbour-nextcloudnotes-de.ts index affd663..b7f6e94 100644 --- a/translations/harbour-nextcloudnotes-de.ts +++ b/translations/harbour-nextcloudnotes-de.ts @@ -413,143 +413,147 @@ SettingsPage About - Über + Über Settings - Einstellungen + Einstellungen Accounts - Benutzerkonten + No Nextcloud account yet - Noch kein Nextcloud Konto eingerichtet + + + + Account %1 + Edit - Bearbeiten + Bearbeiten Delete - Löschen + Löschen Deleting account - Lösche Konto + Add account - Konto hinzufügen + Synchronization - Synchronisierung + Auto-Sync - Auto-Sync + Periodically pull notes from the server - Notizen regelmäßig abrufen + Disabled - Deaktiviert + every - alle + Minutes - Minuten + Seconds - Sekunden - - - Appearance - Aussehen - - - Last edited - Zuletzt bearbeitet - - - Category - Kategorie - - - Title alphabetically - Alphabetisch nach Titel - - - Sort notes by - Notizen sortieren nach - - - This will also change how the notes are grouped - Dies beeinflusst auch die Gruppierung - - - Show separator - Trennlinie einblenden - - - Show a separator line between the notes - Eine Trennlinie zwischen den Notizen anzeigen - - - lines - Zeilen - - - Number of lines in the preview - Anzahl der Zeiten in der Vorschau - - - Editing - Bearbeitung - - - Monospaced font - Nichtproportionale Schrift - - - Use a monospeced font to edit a note - Nichtproportionale Schrift beim Bearbeiten benutzen - - - Capital 'X' in checkboxes - Großes "X" in Kontrollkästchen - - - For interoperability with other apps such as Joplin - Kann für die Interoperabilität mit anderen Apps (z.B. Joplin) nützlich sein + The Answer is 42 - Die Antwort lautet 42 + Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything! - Glückwunsch, du hast die Antwort auf die Frage nach dem Leben, dem Universum und dem ganzen Rest gefunden! + - Favorites on top - Favoriten oben anzeigen + Appearance + - Show notes marked as favorite above the others - Markierte Notizen vor allen anderen anzeigen + Last edited + + + + Category + Kategorie + + + Title alphabetically + No sorting - Keine Sortierung + + + + Sort notes by + + + + This will also change how the notes are grouped + + + + Favorites on top + + + + Show notes marked as favorite above the others + + + + Show separator + + + + Show a separator line between the notes + + + + lines + + + + Number of lines in the preview + + + + Editing + + + + Monospaced font + + + + Use a monospeced font to edit a note + + + + Capital 'X' in checkboxes + + + + For interoperability with other apps such as Joplin + Reset @@ -559,16 +563,12 @@ Reset app settings - - Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts. - - Cleared app data - Account %1 + Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts. diff --git a/translations/harbour-nextcloudnotes-sv.ts b/translations/harbour-nextcloudnotes-sv.ts index ee3307b..c3677bc 100644 --- a/translations/harbour-nextcloudnotes-sv.ts +++ b/translations/harbour-nextcloudnotes-sv.ts @@ -411,133 +411,105 @@ SettingsPage + + About + Om + Settings - Inställningar + Inställningar Accounts - Konton - - - About - Om + No Nextcloud account yet - Inget Nextcloud-konto ännu + - Add account - Lägg till konto + Account %1 + Edit - Redigera + Redigera Delete - Ta bort + Ta bort Deleting account - Tar bort konto + + + + Add account + Synchronization - Synkronisering + Auto-Sync - Autosynk + Periodically pull notes from the server - Hämta anteckningar från servern periodiskt + Disabled - Inaktiverad - - - Minutes - Minuter - - - Seconds - Sekunder - - - Appearance - Utseende - - - Show separator - Visa avdelare - - - Show a separator line between the notes - Visa en separatorlinje mellan anteckningarna - - - lines - rader + every - varje + - Category - Kategori + Minutes + - Title alphabetically - Titlar alfabetiskt - - - Sort notes by - Sortera anteckningar efter - - - Last edited - Senast redigerad - - - This will also change how the notes are grouped - Detta ändrar också hur anteckningarna grupperas - - - Number of lines in the preview - Antal rader i förhandsgranskningen - - - Editing - Redigering - - - Monospaced font - Monospace teckensnitt - - - Use a monospeced font to edit a note - Använd ett monospace teckensnitt för redigering - - - Capital 'X' in checkboxes - Stort "X" i kryssrutor - - - For interoperability with other apps such as Joplin - För samverkan med andra program som Joplin + Seconds + The Answer is 42 - Svaret är 42 + Congratulation you found the Answer to the Ultimate Question of Life, The Universe, and Everything! - Grattulerar! Du har funnit svaret på den ultimata frågan om livet, universum och allt! + + + + Appearance + + + + Last edited + + + + Category + Kategori + + + Title alphabetically + + + + No sorting + + + + Sort notes by + + + + This will also change how the notes are grouped + Favorites on top @@ -548,7 +520,39 @@ - No sorting + Show separator + + + + Show a separator line between the notes + + + + lines + + + + Number of lines in the preview + + + + Editing + + + + Monospaced font + + + + Use a monospeced font to edit a note + + + + Capital 'X' in checkboxes + + + + For interoperability with other apps such as Joplin @@ -559,16 +563,12 @@ Reset app settings - - Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts. - - Cleared app data - Account %1 + Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts. diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index 70d8403..e1cb01b 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -275,32 +275,32 @@ NextcloudApi - + No error - + No network connection available - + Failed to communicate with the Nextcloud server - + An error occured while establishing an encrypted connection - + Could not authenticate to the Nextcloud instance - + Unknown error @@ -599,41 +599,6 @@ Appearance - - - No sorting - - - - - Favorites on top - - - - - Show notes marked as favorite above the others - - - - - Reset - - - - - Reset app settings - - - - - Cleared app data - - - - - Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts. - - Last edited @@ -649,6 +614,11 @@ Title alphabetically + + + No sorting + + Sort notes by @@ -659,6 +629,16 @@ This will also change how the notes are grouped + + + Favorites on top + + + + + Show notes marked as favorite above the others + + Show separator @@ -704,6 +684,26 @@ For interoperability with other apps such as Joplin + + + Reset + + + + + Reset app settings + + + + + Cleared app data + + + + + Resetting the app wipes all application data from the device! This includes offline synced notes, app settings and accounts. + + SyntaxPage @@ -912,27 +912,27 @@ You can also use other markdown syntax inside them. harbour-nextcloudnotes - + Notes - + Offline - + Synced - + API error - + File error