diff --git a/harbour-nextcloudnotes.pro b/harbour-nextcloudnotes.pro index 2ff5329..1f6989a 100644 --- a/harbour-nextcloudnotes.pro +++ b/harbour-nextcloudnotes.pro @@ -18,7 +18,6 @@ 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 \ @@ -27,7 +26,9 @@ DISTFILES += qml/harbour-nextcloudnotes.qml \ translations/*.ts \ harbour-nextcloudnotes.desktop \ qml/pages/NotePage.qml \ - qml/pages/LoginPage.qml + qml/pages/NotesPage.qml \ + qml/pages/LoginDialog.qml \ + qml/pages/EditPage.qml SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 diff --git a/qml/harbour-nextcloudnotes.qml b/qml/harbour-nextcloudnotes.qml index 24e4bb2..9b0db9f 100644 --- a/qml/harbour-nextcloudnotes.qml +++ b/qml/harbour-nextcloudnotes.qml @@ -11,9 +11,19 @@ ApplicationWindow id: appSettings path: "/apps/harbour-nextcloudnotes/settings" property string lastUpdate: qsTr("never") - property url server: "https://127.0.0.1" - property string username: "test" - property string password // TODO provide password before testing. Just use revocable passwords for testing! + property url server: "" + property string username: "" + property string password: "" + property bool unsecureConnection: false + // For testing + Component.onCompleted: { + //server = "" + //username = "" + //password = "" + console.log("Server: " + server) + console.log("Username: " + username) + console.log("Password: " + password) + } } property var notes: NotesApi { @@ -25,7 +35,7 @@ ApplicationWindow onLastUpdateChanged: appSettings.lastUpdate = notes.lastUpdate } - initialPage: Component { FirstPage { } } + initialPage: Component { NotesPage { } } cover: Qt.resolvedUrl("cover/CoverPage.qml") allowedOrientations: defaultAllowedOrientations } diff --git a/qml/img/nextcloud-logo-transparent.png b/qml/img/nextcloud-logo-transparent.png new file mode 100644 index 0000000..b1db316 Binary files /dev/null and b/qml/img/nextcloud-logo-transparent.png differ diff --git a/qml/pages/EditPage.qml b/qml/pages/EditPage.qml new file mode 100644 index 0000000..bff934f --- /dev/null +++ b/qml/pages/EditPage.qml @@ -0,0 +1,30 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Page { + id: page + + property var note + + SilicaFlickable { + id: flickable + anchors.fill: parent + contentHeight: column.height + + Column { + id: column + width: parent.width// - 2*x + + PageHeader { + title: note.title + } + + TextArea { + width: parent.width + text: note.content + } + } + + VerticalScrollDecorator {} + } +} diff --git a/qml/pages/LoginDialog.qml b/qml/pages/LoginDialog.qml new file mode 100644 index 0000000..6b8f976 --- /dev/null +++ b/qml/pages/LoginDialog.qml @@ -0,0 +1,73 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Dialog { + id: loginDialog + + property url server + property string username + property string password + + canAccept: (serverField.acceptableInput && usernameField.text.length > 0 && passwordField.text.length > 0) + onAccepted: { + server = serverField.text + username = usernameField.text + password = passwordField.text + } + + Column { + width: parent.width + + DialogHeader { + id: header + //title: qsTr("Nextcloud Login") + acceptText: qsTr("Login") + } + + Image { + anchors.horizontalCenter: parent.horizontalCenter + height: Theme.itemSizeHuge + fillMode: Image.PreserveAspectFit + source: "../img/nextcloud-logo-transparent.png" + } + + TextField { + id: serverField + focus: true + width: parent.width + text: (server.toString().length > 0) ? server : "https://" + placeholderText: qsTr("Nextcloud server") + label: placeholderText + " " + qsTr("(starting with \"https://\")") + inputMethodHints: Qt.ImhUrlCharactersOnly + // regExp from https://stackoverflow.com/a/3809435 (EDIT: removed ? after https to force SSL) + validator: RegExpValidator { regExp: /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/ } // TODO disable unencrypted communication + EnterKey.enabled: acceptableInput + EnterKey.iconSource: "image://theme/icon-m-enter-next" + EnterKey.onClicked: usernameField.focus = true + } + + TextField { + id: usernameField + width: parent.width + text: (username.length > 0) ? username : "" + placeholderText: qsTr("Username") + label: placeholderText + inputMethodHints: Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase + errorHighlight: text.length === 0 && focus === true + EnterKey.enabled: text.length > 0 + EnterKey.iconSource: "image://theme/icon-m-enter-next" + EnterKey.onClicked: passwordField.focus = true + } + + PasswordField { + id: passwordField + width: parent.width + text: (password.length > 0) ? password : "" + label: placeholderText + errorHighlight: text.length === 0 && focus === true + EnterKey.enabled: text.length > 0 + EnterKey.iconSource: "image://theme/icon-m-enter-accept" + EnterKey.onClicked: loginDialog.accept() + } + } +} diff --git a/qml/pages/LoginPage.qml b/qml/pages/LoginPage.qml deleted file mode 100644 index 50499b8..0000000 --- a/qml/pages/LoginPage.qml +++ /dev/null @@ -1,48 +0,0 @@ -import QtQuick 2.0 -import Sailfish.Silica 1.0 - -Page { - id: page - - allowedOrientations: Orientation.Portrait - - SilicaFlickable { - id: webView - anchors.fill: parent - - PullDownMenu { - MenuItem { - text: qsTr("Reload") - onClicked: webView.reload() - } - } - - PageHeader { - title: qsTr("Login") - } - - Column { - TextField { - focus: true - width: parent.width - placeholderText: qsTr("https://cloud.nextcloud.com") - label: qsTr("Nextcloud server") - inputMethodHints: Qt.ImhUrlCharactersOnly - } - - TextField { - width: parent.width - placeholderText: qsTr("Username") - label: qsTr("Nextcloud user") - inputMethodHints: Qt.ImhUrlCharactersOnly - } - - TextField { - width: parent.width - placeholderText: qsTr("Password") - label: qsTr("Nextcloud App-Password") - inputMethodHints: Qt.ImhUrlCharactersOnly - } - } - } -} diff --git a/qml/pages/NotePage.qml b/qml/pages/NotePage.qml index d0f3da5..9e20026 100644 --- a/qml/pages/NotePage.qml +++ b/qml/pages/NotePage.qml @@ -5,41 +5,52 @@ Page { id: page property var note - - property int id - property string etag - property date modified - property string title - property string category - property bool favorite - property string content - property bool error - property string errorMessage - - - // The effective value will be restricted by ApplicationWindow.allowedOrientations - allowedOrientations: Orientation.All + property var markdown: [ + { regex: new RegExp(/(^#\s)(.*)$/gm), replace: '

$2

' }, + { regex: new RegExp(/(^##\s)(.*)$/gm), replace: '

$2

' }, + { regex: new RegExp(/(^###\s)(.*)$/gm), replace: '

$2

' }, + { regex: new RegExp(/(^####\s)(.*)$/gm), replace: '

$2

' }, + { regex: new RegExp(/(^#####\s)(.*)$/gm), replace: '
$2
' }, + { regex: new RegExp(/(^######\s)(.*)$/gm), replace: '
$2
' }, + { regex: new RegExp(/(^-\s)(.*)$/gm), replace: '' }, + { regex: new RegExp(/(^\d{1,}.\s)(.*)$/gm), replace: '
  1. $2
' } + ] SilicaFlickable { id: flickable anchors.fill: parent contentHeight: column.height + PullDownMenu { + quickSelect: true + MenuItem { + text: qsTr("Edit") + onClicked: pageStack.push(Qt.resolvedUrl("EditPage.qml"), { note: note } ) + } + } + Column { id: column - //x: Theme.horizontalPageMargin - width: parent.width// - 2*x + width: parent.width PageHeader { title: note.title } - TextArea { - width: parent.width - readOnly: true + LinkedLabel { + x: Theme.horizontalPageMargin + width: parent.width - 2*x + textFormat: Text.StyledText text: note.content + Component.onCompleted: { + for (var i=0; i < markdown.length; i++) { + text = text.replace(markdown[i].regex, markdown[i].replace) + } + console.log(text) + } } } + VerticalScrollDecorator {} } } diff --git a/qml/pages/FirstPage.qml b/qml/pages/NotesPage.qml similarity index 72% rename from qml/pages/FirstPage.qml rename to qml/pages/NotesPage.qml index 27c9e92..7b4e349 100644 --- a/qml/pages/FirstPage.qml +++ b/qml/pages/NotesPage.qml @@ -7,17 +7,31 @@ Page { SilicaListView { id: notesList anchors.fill: parent + spacing: Theme.paddingLarge PullDownMenu { busy: notes.busy MenuItem { text: qsTr("Settings") - onClicked: pageStack.push(Qt.resolvedUrl("Settings.qml")) + onClicked: { + var login = pageStack.push(Qt.resolvedUrl("LoginDialog.qml"), { server: appSettings.server, username: appSettings.username, password: appSettings.password } ) + login.accepted.connect(function() { + console.log(login.username + ":" + login.password + "@" + login.server) + appSettings.server = login.server + appSettings.username = login.username + appSettings.password = login.password + notes.getNotes() + }) + } } MenuItem { text: qsTr("Add note") onClicked: console.log("Add note") } + MenuItem { + text: qsTr("Update") + onClicked: notes.getNotes() + } MenuLabel { text: qsTr("Last update") + ": " + new Date(appSettings.lastUpdate).toLocaleString(Qt.locale(), Locale.ShortFormat) } @@ -34,7 +48,12 @@ Page { } currentIndex: -1 - Component.onCompleted: notes.getNotes() + Component.onCompleted: { + if (appSettings.server.toString().length > 0 && appSettings.username.length > 0 && appSettings.password.length > 0) + notes.getNotes() + } + + //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") @@ -49,7 +68,8 @@ Page { IconButton { id: isFavoriteIcon anchors.left: parent.left - anchors.top: titleLabel.top + anchors.leftMargin: Theme.paddingSmall + anchors.top: parent.top width: Theme.iconSizeMedium icon.source: (favorite ? "image://theme/icon-m-favorite-selected?" : "image://theme/icon-m-favorite?") + (note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor) @@ -67,7 +87,6 @@ Page { anchors.right: parent.right anchors.rightMargin: Theme.horizontalPageMargin anchors.top: parent.top - anchors.topMargin: Theme.paddingSmall text: title truncationMode: TruncationMode.Fade color: note.highlighted ? Theme.highlightColor : Theme.primaryColor @@ -80,11 +99,12 @@ Page { anchors.right: parent.right anchors.rightMargin: Theme.horizontalPageMargin anchors.top: titleLabel.bottom - anchors.bottomMargin: Theme.paddingSmall + anchors.topMargin: Theme.paddingMedium + height: Theme.itemSizeExtraLarge text: content font.pixelSize: Theme.fontSizeExtraSmall + textFormat: Text.PlainText wrapMode: Text.Wrap - maximumLineCount: 5 elide: Text.ElideRight color: note.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor } @@ -92,14 +112,6 @@ Page { onClicked: pageStack.push(Qt.resolvedUrl("NotePage.qml"), { note: notesList.model.get(index) } ) menu: ContextMenu { - /*Label { - id: categoryLabel - anchors.horizontalCenter: parent.horizontalCenter - text: (typeof category !== 'undefined') ? qsTr("Category") + ": " + category : "" - font.pixelSize: Theme.fontSizeSmall - color: Theme.highlightColor - visible: text.length > 0 - }*/ Label { id: modifiedLabel anchors.horizontalCenter: parent.horizontalCenter @@ -130,11 +142,18 @@ Page { } ViewPlaceholder { - enabled: notesList.count === 0 && !notes.busy + enabled: notesList.count === 0 && !notes.busy && !noLoginPlaceholder.enabled text: qsTr("No notes yet") hintText: qsTr("Pull down to add a note") } + ViewPlaceholder { + id: noLoginPlaceholder + enabled: (appSettings.server.length === 0 || appSettings.username.length === 0 || appSettings.password.length === 0) + text: qsTr("No Nextcloud account") + hintText: qsTr("Pull down to go to the settings") + } + VerticalScrollDecorator { flickable: notesList } } } diff --git a/translations/harbour-nextcloudnotes.ts b/translations/harbour-nextcloudnotes.ts index af8adc1..9dd5d46 100644 --- a/translations/harbour-nextcloudnotes.ts +++ b/translations/harbour-nextcloudnotes.ts @@ -9,7 +9,33 @@ - FirstPage + LoginDialog + + Login + + + + (starting with "https://") + + + + Username + + + + Nextcloud server + + + + + NotePage + + Edit + + + + + NotesPage Settings @@ -26,6 +52,10 @@ Nextcloud Notes + + Modified + + Delete @@ -39,42 +69,15 @@ - Modified - - - - - LoginFlow - - Reload + Update - Login + No Nextcloud account - https://cloud.nextcloud.com - - - - Nextcloud server - - - - Username - - - - Nextcloud user - - - - Password - - - - Nextcloud App-Password + Pull down to go to the settings