From 53b94e99e242940485bcbf6a0b47640b235f31cf Mon Sep 17 00:00:00 2001 From: Scharel Clemens Date: Tue, 16 Oct 2018 23:52:28 +0200 Subject: [PATCH] API Implemented in javascript. Currently just readonly functionality. No possibility to set user credentials --- harbour-nextcloudnotes.desktop | 13 ++ harbour-nextcloudnotes.pro | 43 ++++++ ...d-notes.png => harbour-nextcloudnotes.png} | Bin ...d-notes.png => harbour-nextcloudnotes.png} | Bin ...d-notes.png => harbour-nextcloudnotes.png} | Bin ...d-notes.png => harbour-nextcloudnotes.png} | Bin ...d-notes.qml => harbour-nextcloudnotes.qml} | 15 +-- qml/pages/FirstPage.qml | 45 ++++--- qml/pages/NotePage.qml | 7 +- qml/pages/{JSONListModel.qml => NotesApi.qml} | 123 ++++++++++++------ ...s.in => harbour-nextcloudnotes.changes.in} | 4 +- ... => harbour-nextcloudnotes.changes.run.in} | 2 +- ...notes.spec => harbour-nextcloudnotes.spec} | 4 +- ...notes.yaml => harbour-nextcloudnotes.yaml} | 2 +- ...d-notes.cpp => harbour-nextcloudnotes.cpp} | 6 +- ...tes-de.ts => harbour-nextcloudnotes-de.ts} | 14 +- ...oud-notes.ts => harbour-nextcloudnotes.ts} | 10 +- 17 files changed, 195 insertions(+), 93 deletions(-) create mode 100644 harbour-nextcloudnotes.desktop create mode 100644 harbour-nextcloudnotes.pro rename icons/108x108/{harbour-nextcloud-notes.png => harbour-nextcloudnotes.png} (100%) rename icons/128x128/{harbour-nextcloud-notes.png => harbour-nextcloudnotes.png} (100%) rename icons/172x172/{harbour-nextcloud-notes.png => harbour-nextcloudnotes.png} (100%) rename icons/86x86/{harbour-nextcloud-notes.png => harbour-nextcloudnotes.png} (100%) rename qml/{harbour-nextcloud-notes.qml => harbour-nextcloudnotes.qml} (51%) rename qml/pages/{JSONListModel.qml => NotesApi.qml} (59%) rename rpm/{harbour-nextcloud-notes.changes.in => harbour-nextcloudnotes.changes.in} (75%) rename rpm/{harbour-nextcloud-notes.changes.run.in => harbour-nextcloudnotes.changes.run.in} (90%) rename rpm/{harbour-nextcloud-notes.spec => harbour-nextcloudnotes.spec} (94%) rename rpm/{harbour-nextcloud-notes.yaml => harbour-nextcloudnotes.yaml} (97%) rename src/{harbour-nextcloud-notes.cpp => harbour-nextcloudnotes.cpp} (72%) rename translations/{harbour-nextcloud-notes-de.ts => harbour-nextcloudnotes-de.ts} (77%) rename translations/{harbour-nextcloud-notes.ts => harbour-nextcloudnotes.ts} (83%) diff --git a/harbour-nextcloudnotes.desktop b/harbour-nextcloudnotes.desktop new file mode 100644 index 0000000..73efaf7 --- /dev/null +++ b/harbour-nextcloudnotes.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Type=Application +X-Nemo-Application-Type=silica-qt5 +Icon=harbour-nextcloudnotes +Exec=harbour-nextcloudnotes +Name=harbour-nextcloudnotes +# translation example: +# your app name in German locale (de) +# +# Remember to comment out the following line, if you do not want to use +# a different app name in German locale (de). +Name[de]=harbour-nextcloudnotes +Name[de_DE]=harbour-nextcloudnotes.desktop diff --git a/harbour-nextcloudnotes.pro b/harbour-nextcloudnotes.pro new file mode 100644 index 0000000..6d6fac6 --- /dev/null +++ b/harbour-nextcloudnotes.pro @@ -0,0 +1,43 @@ +# NOTICE: +# +# Application name defined in TARGET has a corresponding QML filename. +# If name defined in TARGET is changed, the following needs to be done +# to match new name: +# - corresponding QML filename must be changed +# - desktop icon filename must be changed +# - desktop filename must be changed +# - icon definition filename in desktop file must be changed +# - translation filenames have to be changed + +# The name of your application +TARGET = harbour-nextcloudnotes + +CONFIG += sailfishapp + +SOURCES += src/harbour-nextcloudnotes.cpp + +DISTFILES += qml/harbour-nextcloudnotes.qml \ + qml/cover/CoverPage.qml \ + qml/pages/FirstPage.qml \ + qml/pages/NotesApi.qml \ + rpm/harbour-nextcloudnotes.changes.in \ + rpm/harbour-nextcloudnotes.changes.run.in \ + rpm/harbour-nextcloudnotes.spec \ + rpm/harbour-nextcloudnotes.yaml \ + translations/*.ts \ + harbour-nextcloudnotes.desktop \ + qml/pages/NotePage.qml + +SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 + +# to disable building translations every time, comment out the +# following CONFIG line +CONFIG += sailfishapp_i18n + +# German translation is enabled as an example. If you aren't +# planning to localize your app, remember to comment out the +# following TRANSLATIONS line. And also do not forget to +# modify the localized app name in the the .desktop file. +TRANSLATIONS += translations/harbour-nextcloudnotes-de.ts + +HEADERS += diff --git a/icons/108x108/harbour-nextcloud-notes.png b/icons/108x108/harbour-nextcloudnotes.png similarity index 100% rename from icons/108x108/harbour-nextcloud-notes.png rename to icons/108x108/harbour-nextcloudnotes.png diff --git a/icons/128x128/harbour-nextcloud-notes.png b/icons/128x128/harbour-nextcloudnotes.png similarity index 100% rename from icons/128x128/harbour-nextcloud-notes.png rename to icons/128x128/harbour-nextcloudnotes.png diff --git a/icons/172x172/harbour-nextcloud-notes.png b/icons/172x172/harbour-nextcloudnotes.png similarity index 100% rename from icons/172x172/harbour-nextcloud-notes.png rename to icons/172x172/harbour-nextcloudnotes.png diff --git a/icons/86x86/harbour-nextcloud-notes.png b/icons/86x86/harbour-nextcloudnotes.png similarity index 100% rename from icons/86x86/harbour-nextcloud-notes.png rename to icons/86x86/harbour-nextcloudnotes.png diff --git a/qml/harbour-nextcloud-notes.qml b/qml/harbour-nextcloudnotes.qml similarity index 51% rename from qml/harbour-nextcloud-notes.qml rename to qml/harbour-nextcloudnotes.qml index 16d4d39..5a894dc 100644 --- a/qml/harbour-nextcloud-notes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -9,21 +9,20 @@ ApplicationWindow ConfigurationGroup { id: appSettings - path: "/apps/harbour-nextcloud-notes/settings" + path: "/apps/harbour-nextcloudnotes/settings" property string lastUpdate: qsTr("never") - property url nextcloudServer: "https://cloud.scharel.name" - property string username: "scharel" - property string password: "" + property url server: "https://cloud.scharel.name" + "/index.php/apps/notes/api/v0.2/notes" + property string username: "test" + property string password // TODO provide password before testing } - property var notesModel: JSONListModel { - url: appSettings.nextcloudServer + "/index.php/apps/notes/api/v0.2/notes" + property var notes: NotesApi { name: "notes" saveFile: false } Connections { - target: notesModel - onLastUpdateChanged: appSettings.lastUpdate = notesModel.lastUpdate + target: notes + onLastUpdateChanged: appSettings.lastUpdate = notes.lastUpdate } initialPage: Component { FirstPage { } } diff --git a/qml/pages/FirstPage.qml b/qml/pages/FirstPage.qml index ab94ffa..471c554 100644 --- a/qml/pages/FirstPage.qml +++ b/qml/pages/FirstPage.qml @@ -1,6 +1,5 @@ import QtQuick 2.0 import Sailfish.Silica 1.0 -//import harbour.nextcloudnotes 0.1 Page { id: page @@ -10,7 +9,7 @@ Page { anchors.fill: parent PullDownMenu { - busy: notesModel.busy + busy: notes.busy MenuItem { text: qsTr("Settings") onClicked: pageStack.push(Qt.resolvedUrl("Settings.qml")) @@ -20,42 +19,33 @@ Page { onClicked: console.log("Add note") } MenuLabel { - text: qsTr("Last update") + ": " + appSettings.lastUpdate + text: qsTr("Last update") + ": " + new Date(appSettings.lastUpdate).toLocaleString(Qt.locale(), Locale.ShortFormat) } } header: SearchField { width: parent.width placeholderText: qsTr("Nextcloud Notes") - onTextChanged: notesModel.search(text.toLowerCase()) + onTextChanged: notes.search(text.toLowerCase()) EnterKey.iconSource: "image://theme/icon-m-enter-close" EnterKey.onClicked: focus = false - enabled: notesModel.json.length > 0 + enabled: notes.json.length > 0 } currentIndex: -1 - Component.onCompleted: notesModel.update() + Component.onCompleted: notes.getNotes() + //Component.onCompleted: notes.getNote("1212725") + //Component.onCompleted: notes.createNote("Hello World!", "Test") + //Component.onCompleted: notes.updateNote(1212725, "# Hello World!\nIs this working?", "Test") + //Component.onCompleted: notes.deleteNote(1212725) - model: notesModel + model: notes.model delegate: ListItem { id: note contentHeight: Theme.itemSizeMedium - onClicked: { - pageStack.push(Qt.resolvedUrl("NotePage.qml"), - {id: id, - etag: etag, - modified: modified, - title: title, - category: category, - favorite: favorite, - content: content, - error: error, - errorMessage: errorMessage}) - } - IconButton { id: isFavoriteIcon x: Theme.horizontalPageMargin @@ -66,6 +56,7 @@ Page { onClicked: { console.log("Toggle favorite") favorite = !favorite + notes.updateNote(id, {'favorite': favorite} ) } } @@ -86,11 +77,13 @@ Page { anchors.leftMargin: Theme.paddingSmall anchors.right: parent.right anchors.top: parent.verticalCenter - text: new Date(modified * 1000).toLocaleDateString() + text: new Date(modified * 1000).toLocaleString(Qt.locale(), Locale.ShortFormat) font.pixelSize: Theme.fontSizeExtraSmall color: note.highlighted ? Theme.highlightColor : Theme.primaryColor } + onClicked: pageStack.push(Qt.resolvedUrl("NotePage.qml"), { note: notesList.model.get(index) } ) + menu: ContextMenu { Text { id: descriptionText @@ -114,17 +107,23 @@ Page { section.criteria: ViewSection.FullString section.labelPositioning: ViewSection.InlineLabels section.delegate: SectionHeader { - text: section.empty ? qsTr("No category") : section + text: section } BusyIndicator { id: busyIndicator anchors.centerIn: parent size: BusyIndicatorSize.Large - visible: notesList.count === 0 + visible: notesList.count === 0 && notes.busy running: visible } + ViewPlaceholder { + enabled: notesList.count === 0 && !notes.busy + text: qsTr("No notes yet") + hintText: qsTr("Pull down to add a note") + } + VerticalScrollDecorator { flickable: notesList } } } diff --git a/qml/pages/NotePage.qml b/qml/pages/NotePage.qml index 9fdb72d..d0f3da5 100644 --- a/qml/pages/NotePage.qml +++ b/qml/pages/NotePage.qml @@ -4,6 +4,8 @@ import Sailfish.Silica 1.0 Page { id: page + property var note + property int id property string etag property date modified @@ -29,14 +31,13 @@ Page { width: parent.width// - 2*x PageHeader { - title: page.title + title: note.title } TextArea { - id: note width: parent.width readOnly: true - text: page.content + text: note.content } } VerticalScrollDecorator {} diff --git a/qml/pages/JSONListModel.qml b/qml/pages/NotesApi.qml similarity index 59% rename from qml/pages/JSONListModel.qml rename to qml/pages/NotesApi.qml index b7efa4e..f415ddc 100644 --- a/qml/pages/JSONListModel.qml +++ b/qml/pages/NotesApi.qml @@ -1,17 +1,87 @@ import QtQuick 2.0 import Sailfish.Silica 1.0 -import Nemo.Configuration 1.0 -ListModel { - property url url - property string json +Item { property string name + property var model: ListModel { } + + property string json property string file: StandardPaths.data + "/" + name + ".json" property bool saveFile: false property bool busy: false - property int status: 200 property date lastUpdate: new Date(0) + function callApi(method, data) { + busy = true + + var endpoint = "" + if (data && (method === "GET" || method === "PUT" || method === "DELETE")) + if (data.id) + endpoint = "/" + data.id + + var apiReq = new XMLHttpRequest + apiReq.open(method, appSettings.server + endpoint, true) + apiReq.setRequestHeader('User-Agent', 'SailfishOS/harbour-lidderbuch') + apiReq.setRequestHeader('OCS-APIRequest', 'true') + apiReq.setRequestHeader("Content-Type", "application/json"); + apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(appSettings.username + ":" + appSettings.password)) + apiReq.onreadystatechange = function() { + if (apiReq.readyState === XMLHttpRequest.DONE) { + if (apiReq.status === 200) { + console.log("Successfull request!") + console.log(apiReq.responseText) + // TODO handle non arrays + var elements = JSON.parse(apiReq.responseText) + for (var element in elements) { + model.append(elements[element]) + } + } + else if (apiReq.status === 404) { + console.log("Note does not exist!") + } + else { + console.log("Unknown error: " + apiReq.statusText + " (" + apiReq.status + ")") + } + busy = false + } + } + if (method === "GET") { + apiReq.send() + } + else if (method === "POST" || method === "PUT" || method === "DELETE") { + apiReq.send(JSON.stringify(data)) + } + else { + console.log("Unsupported method: " + method) + apiReq.abort() + } + } + + function getNotes() { + callApi("GET") + } + + function getNote(id) { + if (id) + callApi("GET", { 'id': id } ) + } + + function createNote(data) { + callApi("POST", data) + } + + function updateNote(id, data) { + if (id) { + data.id = id + callApi("PUT", data) + } + } + + function deleteNote(id) { + if (id) + callApi("DELETE", { 'id': id } ) + } + onJsonChanged: refresh() function flush() { @@ -19,7 +89,7 @@ ListModel { var filePut = new XMLHttpRequest filePut.open("PUT", file) filePut.send(json) - clear() + model.clear() lastUpdate = new Date(0) status = 200 } @@ -29,7 +99,7 @@ ListModel { } function search(query) { - clear() + model.clear() var elements = parseJson() for (var element in elements) { elements[element].section = "" @@ -40,7 +110,7 @@ ListModel { } } if (query === "" || match) - append(elements[element]) + model.append(elements[element]) } } @@ -53,43 +123,12 @@ ListModel { return null } else { - clear() + model.clear() return elements } } - function update() { - busy = true - var apiReq = new XMLHttpRequest - apiReq.open("GET", url, true)//, appSettings.username, appSettings.password) - apiReq.setRequestHeader('User-Agent', 'SailfishOS/harbour-lidderbuch') - apiReq.setRequestHeader('OCS-APIRequest', 'true') - apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(appSettings.username + ":" + appSettings.password)) - apiReq.onreadystatechange = function() { - if (apiReq.readyState === XMLHttpRequest.DONE) { - if (apiReq.status === 200) { - console.log("Successfully loaded " + url) - json = apiReq.responseText - //console.log(json) - if (saveFile) { - var filePut = new XMLHttpRequest - filePut.open("PUT", file) - filePut.send(json) - } - lastUpdate = new Date() - } - else { - console.log("Error loading " + url + " - " + apiReq.status) - //lastUpdate = new Date(0) - } - status = apiReq.status - busy = false - } - } - apiReq.send() - } - - Component.onCompleted: { + /*Component.onCompleted: { if (saveFile) { if (name === "") { saveFile = false @@ -113,5 +152,5 @@ ListModel { fileReq.send() } } - } + }*/ } diff --git a/rpm/harbour-nextcloud-notes.changes.in b/rpm/harbour-nextcloudnotes.changes.in similarity index 75% rename from rpm/harbour-nextcloud-notes.changes.in rename to rpm/harbour-nextcloudnotes.changes.in index 8bf39db..f6b9d1d 100644 --- a/rpm/harbour-nextcloud-notes.changes.in +++ b/rpm/harbour-nextcloudnotes.changes.in @@ -1,4 +1,4 @@ -# Rename this file as harbour-nextcloud-notes.changes to include changelog +# Rename this file as harbour-nextcloudnotes.changes to include changelog # entries in your RPM file. # # Add new changelog entries following the format below. @@ -7,7 +7,7 @@ # # Alternatively, if your changelog is automatically generated (e.g. with # the git-change-log command provided with Sailfish OS SDK), create a -# harbour-nextcloud-notes.changes.run script to let mb2 run the required commands for you. +# harbour-nextcloudnotes.changes.run script to let mb2 run the required commands for you. # * date Author's Name version-release # - Summary of changes diff --git a/rpm/harbour-nextcloud-notes.changes.run.in b/rpm/harbour-nextcloudnotes.changes.run.in similarity index 90% rename from rpm/harbour-nextcloud-notes.changes.run.in rename to rpm/harbour-nextcloudnotes.changes.run.in index 25b26aa..5088574 100644 --- a/rpm/harbour-nextcloud-notes.changes.run.in +++ b/rpm/harbour-nextcloudnotes.changes.run.in @@ -1,6 +1,6 @@ #!/bin/bash # -# Rename this file as harbour-nextcloud-notes.changes.run to let mb2 automatically +# Rename this file as harbour-nextcloudnotes.changes.run to let mb2 automatically # generate changelog from well formatted Git commit messages and tag # annotations. diff --git a/rpm/harbour-nextcloud-notes.spec b/rpm/harbour-nextcloudnotes.spec similarity index 94% rename from rpm/harbour-nextcloud-notes.spec rename to rpm/harbour-nextcloudnotes.spec index 04edb7c..52788a4 100644 --- a/rpm/harbour-nextcloud-notes.spec +++ b/rpm/harbour-nextcloudnotes.spec @@ -3,7 +3,7 @@ # Generated by: spectacle version 0.27 # -Name: harbour-nextcloud-notes +Name: harbour-nextcloudnotes # >> macros # << macros @@ -19,7 +19,7 @@ Group: Qt/Qt License: LICENSE URL: http://example.org/ Source0: %{name}-%{version}.tar.bz2 -Source100: harbour-nextcloud-notes.yaml +Source100: harbour-nextcloudnotes.yaml Requires: sailfishsilica-qt5 >= 0.10.9 BuildRequires: pkgconfig(sailfishapp) >= 1.0.2 BuildRequires: pkgconfig(Qt5Core) diff --git a/rpm/harbour-nextcloud-notes.yaml b/rpm/harbour-nextcloudnotes.yaml similarity index 97% rename from rpm/harbour-nextcloud-notes.yaml rename to rpm/harbour-nextcloudnotes.yaml index 1d63232..9c7a3be 100644 --- a/rpm/harbour-nextcloud-notes.yaml +++ b/rpm/harbour-nextcloudnotes.yaml @@ -1,4 +1,4 @@ -Name: harbour-nextcloud-notes +Name: harbour-nextcloudnotes Summary: Nextcloud Notes Version: 0.1 Release: 1 diff --git a/src/harbour-nextcloud-notes.cpp b/src/harbour-nextcloudnotes.cpp similarity index 72% rename from src/harbour-nextcloud-notes.cpp rename to src/harbour-nextcloudnotes.cpp index a97eb14..b351b70 100644 --- a/src/harbour-nextcloud-notes.cpp +++ b/src/harbour-nextcloudnotes.cpp @@ -8,16 +8,16 @@ int main(int argc, char *argv[]) { QGuiApplication* app = SailfishApp::application(argc, argv); app->setApplicationDisplayName("Nextcloud Notes"); - app->setApplicationName("harbour-nextcloud-notes"); + app->setApplicationName("harbour-nextcloudnotes"); app->setApplicationVersion("0.1"); app->setOrganizationDomain("https://github.com/scharel"); - app->setOrganizationName("harbour-nextcloud-notes"); + app->setOrganizationName("harbour-nextcloudnotes"); qDebug() << app->applicationDisplayName() << app->applicationVersion(); QQuickView* view = SailfishApp::createView(); - view->setSource(SailfishApp::pathTo("qml/harbour-nextcloud-notes.qml")); + view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml")); view->show(); return app->exec(); diff --git a/translations/harbour-nextcloud-notes-de.ts b/translations/harbour-nextcloudnotes-de.ts similarity index 77% rename from translations/harbour-nextcloud-notes-de.ts rename to translations/harbour-nextcloudnotes-de.ts index b29fbb1..223d9e8 100644 --- a/translations/harbour-nextcloud-notes-de.ts +++ b/translations/harbour-nextcloudnotes-de.ts @@ -18,6 +18,10 @@ Add note Neue Notiz + + Last update + Zuletzt aktualisiert + Nextcloud Notes Nextcloud Notizen @@ -27,16 +31,16 @@ Löschen - No category - Ohne Kategorie + No notes yet + Noch keine Notizen - Last update - Zuletzt aktualisiert + Pull down to add a note + Herunterziehen um eine neue Notiz zu erzeugen - harbour-nextcloud-notes + harbour-nextcloudnotes never noch nie diff --git a/translations/harbour-nextcloud-notes.ts b/translations/harbour-nextcloudnotes.ts similarity index 83% rename from translations/harbour-nextcloud-notes.ts rename to translations/harbour-nextcloudnotes.ts index 63f653e..17e687f 100644 --- a/translations/harbour-nextcloud-notes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -18,6 +18,10 @@ Add note + + Last update + + Nextcloud Notes @@ -27,16 +31,16 @@ - No category + No notes yet - Last update + Pull down to add a note - harbour-nextcloud-notes + harbour-nextcloudnotes never