diff --git a/backend/ApiRequest.qml b/backend/ApiRequest.qml index 9a23d56..bd23e62 100644 --- a/backend/ApiRequest.qml +++ b/backend/ApiRequest.qml @@ -144,7 +144,7 @@ Item { } else { notification.show((xhr.status === 404) ? i18n.tr("Error 404: Could not find Tapatalk API for given URL") : i18n.tr("Connection error")) console.log((xhr.status === 404) ? "Error 404: Could not find Tapatalk API for given URL" : "Connection error") - queryExecuted(session, false, "") + queryExecuted(false, "") } } } diff --git a/backend/ForumBackend.qml b/backend/ForumBackend.qml index e3b2958..02a0c63 100644 --- a/backend/ForumBackend.qml +++ b/backend/ForumBackend.qml @@ -41,7 +41,7 @@ Object { property int postsPerPage: 10 property int topicsLoadCount: 20 - property string signature: i18n.tr("Sent from my awesome Ubuntu Touch device using the Forum Browser app") + property alias signature: settingsBackend.signature U1db.Index { database: db @@ -49,6 +49,10 @@ Object { expression: ["url", "user", "password"] } + SettingsBackend { + id: settingsBackend + } + Component { id: sessionComponent @@ -62,6 +66,8 @@ Object { property alias configModel: configModel property alias loginRequest: loginRequest + readonly property string user: (loginDbQuery.results[0].user !== undefined) ? loginDbQuery.results[0].user : "" + signal loginDone ForumConfigModel { diff --git a/backend/SettingsBackend.qml b/backend/SettingsBackend.qml new file mode 100644 index 0000000..ed52106 --- /dev/null +++ b/backend/SettingsBackend.qml @@ -0,0 +1,32 @@ +/************************************************************************* +** Forum Browser +** +** Copyright (c) 2014 Niklas Wenzel +** +** $QT_BEGIN_LICENSE:GPL$ +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; see the file COPYING. If not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +** Boston, MA 02110-1301, USA. +** +** +** $QT_END_LICENSE$ +** +*************************************************************************/ + +import QtQuick 2.2 +import Qt.labs.settings 1.0 + +Settings { + property string signature: i18n.tr("Sent from my awesome Ubuntu Touch device using the Forum Browser app") +} diff --git a/forum-app.qml b/forum-app.qml index 9846b18..193ddbc 100644 --- a/forum-app.qml +++ b/forum-app.qml @@ -42,6 +42,8 @@ MainView { useDeprecatedToolbar: false + anchorToKeyboard: true + U1db.Database { id: db path: "forums.u1db" @@ -55,6 +57,17 @@ MainView { defaults: { "name": "XDA Developers", "url": "forum.xda-developers.com", "user": "", "password": "" } } + U1db.Database { + id: draftsDb + path: "drafts.u1db" + } + + U1db.Index { + id: draftsIndex + database: draftsDb + expression: [ "forum_url", "username", "mode", "forum_id", "topic_id", "subject", "message" ] + } + PageStack { id: pageStack diff --git a/ui/AddForumPage.qml b/ui/AddForumPage.qml index 0645262..799eca6 100644 --- a/ui/AddForumPage.qml +++ b/ui/AddForumPage.qml @@ -45,7 +45,7 @@ Page { Action { id: save iconName: "ok" - text: docId !== ""?i18n.tr("Edit"):i18n.tr("Add") + text: docId !== "" ? i18n.tr("Edit") : i18n.tr("Add") onTriggered: { if (nameTextField.text !== "" && urlTextField.text !== "") { //Remove protocol from url (so that there are no multiple instances of one forum but with different prefixes) diff --git a/ui/ForumsListPage.qml b/ui/ForumsListPage.qml index 42fc560..265a3b9 100644 --- a/ui/ForumsListPage.qml +++ b/ui/ForumsListPage.qml @@ -26,8 +26,8 @@ import QtQuick 2.2 import Ubuntu.Components 1.1 -import U1db 1.0 as U1db import Ubuntu.Components.ListItems 1.0 as ListItem +import U1db 1.0 as U1db Page { id: forumsListPage @@ -40,6 +40,12 @@ Page { iconName: "add" onTriggered: pageStack.push(Qt.resolvedUrl("AddForumPage.qml")) }, + Action { + id: settingsAction + text: i18n.tr("Settings") + iconName: "settings" + onTriggered: pageStack.push(Qt.resolvedUrl("settings/SettingsPage.qml")) + }, Action { id: aboutAction text: i18n.tr("About") diff --git a/ui/components/OneLineSubtitledListItem.qml b/ui/components/OneLineSubtitledListItem.qml new file mode 100644 index 0000000..b3c7301 --- /dev/null +++ b/ui/components/OneLineSubtitledListItem.qml @@ -0,0 +1,67 @@ +/* + * Copyright 2012 Canonical Ltd. + * Copyright 2014 Niklas Wenzel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.2 +import Ubuntu.Components 1.1 +import Ubuntu.Components.ListItems 1.0 as ListItem + +ListItem.Base { + id: subtitledListItem + __height: Math.max(middleVisuals.height, units.gu(6)) + + /*! + \preliminary + The list of strings that will be shown under the label text + \qmlproperty string subText + */ + property alias subText: subLabel.text + + Item { + id: middleVisuals + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + height: childrenRect.height + label.anchors.topMargin + subLabel.anchors.bottomMargin + + LabelVisual { + id: label + text: subtitledListItem.text + selected: subtitledListItem.selected + anchors { + top: parent.top + left: parent.left + right: parent.right + } + } + LabelVisual { + id: subLabel + selected: subtitledListItem.selected + secondary: true + anchors { + + left: parent.left + right: parent.right + top: label.bottom + } + fontSize: "small" + wrapMode: Text.Wrap + maximumLineCount: 1 //NOTE: Changed the line count here (this is the only change to this file besides the removal of example code comments and fixing the imports) + } + } +} diff --git a/ui/settings/EditSignaturePage.qml b/ui/settings/EditSignaturePage.qml new file mode 100644 index 0000000..65c1c14 --- /dev/null +++ b/ui/settings/EditSignaturePage.qml @@ -0,0 +1,85 @@ +/************************************************************************* +** Forum Browser +** +** Copyright (c) 2014 Niklas Wenzel +** +** $QT_BEGIN_LICENSE:GPL$ +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; see the file COPYING. If not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +** Boston, MA 02110-1301, USA. +** +** +** $QT_END_LICENSE$ +** +*************************************************************************/ + +import QtQuick 2.2 +import Ubuntu.Components 1.1 +import Ubuntu.Components.Popups 1.0 +import Ubuntu.Components.ListItems 1.0 as ListItem +import Ubuntu.Components.Themes.Ambiance 0.1 +import "../../stringutils.js" as StringUtils +import "../../backend" +import "../components" + +Page { + id: editSignaturePage + + title: i18n.tr("Edit Signature") + + Component.onCompleted: { + signatureTextField.text = backend.signature + } + + head.actions: [ + Action { + id: saveAction + text: i18n.tr("Save") + iconName: "ok" + + onTriggered: { + backend.signature = signatureTextField.text + pageStack.pop() + } + } + ] + + head.backAction: Action { + id: cancelAction + text: i18n.tr("Cancel") + iconName: "close" + + onTriggered: { + pageStack.pop() + } + } + + TextArea { + id: signatureTextField + autoSize: false + maximumLineCount: 0 + placeholderText: i18n.tr("Enter signature or leave blank") + + anchors { + fill: parent + margins: units.gu(2) + } + + style: TextAreaStyle { + overlaySpacing: 0 + frameSpacing: 0 + background: Item {} + } + } +} diff --git a/ui/settings/SettingsPage.qml b/ui/settings/SettingsPage.qml new file mode 100644 index 0000000..f7fee49 --- /dev/null +++ b/ui/settings/SettingsPage.qml @@ -0,0 +1,48 @@ +/************************************************************************* +** Forum Browser +** +** Copyright (c) 2014 Niklas Wenzel +** +** $QT_BEGIN_LICENSE:GPL$ +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; see the file COPYING. If not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +** Boston, MA 02110-1301, USA. +** +** +** $QT_END_LICENSE$ +** +*************************************************************************/ + +import QtQuick 2.2 +import Ubuntu.Components 1.1 +import "../components" + +Page { + id: settingsPage + title: i18n.tr("Settings") + + Column { + anchors.fill: parent + + OneLineSubtitledListItem { + text: i18n.tr("Signature") + subText: backend.signature + progression: true + + onClicked: { + pageStack.push(Qt.resolvedUrl("EditSignaturePage.qml")) + } + } + } +} diff --git a/ui/viewing/MessageComposerPage.qml b/ui/viewing/MessageComposerPage.qml new file mode 100644 index 0000000..0bd28ee --- /dev/null +++ b/ui/viewing/MessageComposerPage.qml @@ -0,0 +1,258 @@ +/************************************************************************* +** Forum Browser +** +** Copyright (c) 2014 Niklas Wenzel +** +** $QT_BEGIN_LICENSE:GPL$ +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; see the file COPYING. If not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +** Boston, MA 02110-1301, USA. +** +** +** $QT_END_LICENSE$ +** +*************************************************************************/ + +import QtQuick 2.2 +import Ubuntu.Components 1.1 +import Ubuntu.Components.Popups 1.0 +import Ubuntu.Components.ListItems 1.0 as ListItem +import Ubuntu.Components.Themes.Ambiance 0.1 +import U1db 1.0 as U1db +import "../../stringutils.js" as StringUtils +import "../../backend" +import "../components" + +Page { + id: postCreationPage + + signal posted(string subject, int forumId, int topicId) + + property int forum_id: -1 + property int topic_id: -1 + + property string mode: "post" //Can be either "post" or "thread" + //Needs to be the first property set!!! + + title: (mode === "post") ? i18n.tr("New Post") : i18n.tr("New Topic") + + property var dialog + + property string docId: "" + + U1db.Query { + id: draftsQuery + index: draftsIndex + query: [ backend.currentSession.forumUrl, backend.currentSession.user, mode, forum_id, topic_id, "*", "*" ] + + onResultsChanged: { + var results = draftsQuery.results //NOTE: The first two checks of the if condition will have to be fixed when adding proper replying with quoting + if (subjectTextField.text === "" && messageTextField.text === "" && forum_id !== -1 && (mode === "thread" || topic_id !== -1) && results[0] !== undefined && results[0].subject !== undefined && results[0].message !== undefined && (results[0].subject !== "" || results[0].message !== "")) { + console.log("Filling composer with draft data") + docId = draftsQuery.documents[0] + subjectTextField.text = results[0].subject + messageTextField.text = results[0].message + } + } + } + + head.actions: [ + Action { + id: submitAction + text: i18n.tr("Submit") + iconName: "ok" + + onTriggered: submit() + + function submit() { + var message = messageTextField.text + + if (message.trim() === "") { + var errorDialog = PopupUtils.open(Qt.resolvedUrl("../components/ErrorDialog.qml")) + errorDialog.title = qsTr(i18n.tr("%1 failed")).arg(submitRequest.actionName) //for consistency ;) + errorDialog.text = i18n.tr("Please enter a message") + return + } + + if (backend.signature !== "") { + message += "\n\n" + backend.signature + } + + if (mode === "post") { + submitRequest.query = 'reply_post' + forum_id + '' + topic_id + '' + StringUtils.base64_encode(subjectTextField.text) + '' + StringUtils.base64_encode(message) + '' + } else { + submitRequest.query = 'new_topic' + forum_id + '' + StringUtils.base64_encode(subjectTextField.text) + '' + StringUtils.base64_encode(message) + '' + } + + submitRequest.start() + Qt.inputMethod.hide() + dialog = PopupUtils.open(loadingDialog) + } + } + ] + + head.backAction: Action { + id: backAction + text: i18n.tr("Back") + iconName: "back" + + onTriggered: { + if (subjectTextField.text !== "" || messageTextField.text !== "") { + var doc = { "forum_url": backend.currentSession.forumUrl, "username": backend.currentSession.user, "mode": mode, "forum_id": forum_id, "topic_id": topic_id, "subject": subjectTextField.text, "message": messageTextField.text } + if (docId === "") { + draftsDb.putDoc(doc) + } else { + draftsDb.putDoc(doc, docId) + } + } else if (docId !== "") { + draftsDb.deleteDoc(docId) + } + + pageStack.pop() + } + } + + ApiRequest { + id: submitRequest + checkSuccess: true + + onQuerySuccessResult: { + if (success) { + if (docId !== "") { + draftsDb.deleteDoc(docId) + } + + subjectTextField.enabled = false //Needed, otherwise the keyboard will show again after closing the dialog + messageTextField.enabled = false + PopupUtils.close(dialog) + + if (mode === "post") { + pageStack.pop() + posted(subjectTextField.text, forum_id, topic_id) + } else { + var idIndex = responseXml.indexOf("topic_id") + var stringTag = responseXml.indexOf("", idIndex) + var stringEndTag = responseXml.indexOf("", idIndex) + var id = parseInt(responseXml.substring(stringTag + 8, stringEndTag)) + + pageStack.pop() + posted(subjectTextField.text, forum_id, id) + } + } else { + PopupUtils.close(dialog) + } + } + } + + ListItem.Header { + id: subjectHeader + text: i18n.tr("Subject:") + + anchors { + top: parent.top + left: parent.left + right: parent.right + topMargin: units.gu(1) + } + } + + TextArea { + id: subjectTextField + width: parent.width + autoSize: true + maximumLineCount: 1 + placeholderText: i18n.tr("Enter Subject") + + anchors { + top: subjectHeader.bottom + right: parent.right + left: parent.left + topMargin: units.gu(2) + rightMargin: units.gu(2) + leftMargin: units.gu(2) + } + + style: TextAreaStyle { + overlaySpacing: 0 + frameSpacing: 0 + background: Item {} + } + + KeyNavigation.priority: KeyNavigation.BeforeItem + KeyNavigation.tab: messageTextField + } + + ListItem.Header { + id: messageHeader + text: i18n.tr("Message:") + + anchors { + top: subjectTextField.bottom + left: parent.left + right: parent.right + } + } + + TextArea { + id: messageTextField + autoSize: false + maximumLineCount: 0 + placeholderText: i18n.tr("Enter Message") + + anchors { + top: messageHeader.bottom + bottom: parent.bottom + right: parent.right + left: parent.left + topMargin: units.gu(2) + bottomMargin: units.gu(1) + rightMargin: units.gu(2) + leftMargin: units.gu(2) + } + + style: TextAreaStyle { + overlaySpacing: 0 + frameSpacing: 0 + background: Item {} + } + + KeyNavigation.priority: KeyNavigation.BeforeItem + KeyNavigation.backtab: subjectTextField + } + + Component { + id: loadingDialog + + Dialog { + id: dialog + modal: true + + Row { + width: parent.width + spacing: units.gu(2) + + ActivityIndicator { + id: loadingSpinner + running: true + anchors.verticalCenter: parent.verticalCenter + } + + Label { + text: qsTr(i18n.tr("Submitting %1...")).arg((mode === "post") ? i18n.tr("Post") : i18n.tr("Thread")) + anchors.verticalCenter: parent.verticalCenter + } + } + } + } +} diff --git a/ui/viewing/PostCreationPage.qml b/ui/viewing/PostCreationPage.qml deleted file mode 100644 index 2bcfd21..0000000 --- a/ui/viewing/PostCreationPage.qml +++ /dev/null @@ -1,143 +0,0 @@ -/************************************************************************* -** Forum Browser -** -** Copyright (c) 2014 Niklas Wenzel -** -** $QT_BEGIN_LICENSE:GPL$ -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; see the file COPYING. If not, write to -** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -** Boston, MA 02110-1301, USA. -** -** -** $QT_END_LICENSE$ -** -*************************************************************************/ - -import QtQuick 2.2 -import Ubuntu.Components 1.1 -import Ubuntu.Components.Popups 1.0 -import "../../stringutils.js" as StringUtils -import "../../backend" - -Page { - id: postCreationPage - anchors.fill: parent - - readonly property string signature: i18n.tr("Sent from my awesome Ubuntu Touch device using the Forum Browser app") - - signal posted(); - - property int forum_id: -1 - property int topic_id: -1 - - title: i18n.tr("New Post") - - Flickable { - anchors { - top: parent.top - bottom: parent.bottom - left: parent.left - right: parent.right - margins: units.gu(1) - } - - contentHeight: column.height - - Column { - id: column - height: childrenRect.height - width: parent.width - spacing: units.gu(1) - - Label { - text: i18n.tr("Subject:") - } - - TextField { - id: subjectTextField - width: parent.width - - KeyNavigation.priority: KeyNavigation.BeforeItem - KeyNavigation.tab: messageTextField - } - - Label { - text: i18n.tr("Message:") - } - - TextArea { - id: messageTextField - width: parent.width - - KeyNavigation.priority: KeyNavigation.BeforeItem - KeyNavigation.backtab: subjectTextField - } - - Row { - id: signatureRow - width: parent.width - spacing: units.gu(1) - - CheckBox { - id: appendSignatureCheckBox - checked: true - anchors.verticalCenter: parent.verticalCenter - } - - Label { - id: signatureLabel - text: backend.signature - wrapMode: Text.Wrap - - anchors.verticalCenter: parent.verticalCenter - width: parent.width - signatureRow.spacing - appendSignatureCheckBox.width - } - } - - Button { - id: submitButton - text: i18n.tr("Submit") - width: parent.width - - onClicked: submit() - - ApiRequest { - id: submitRequest - checkSuccess: true - - onQuerySuccessResult: { - if (success) { - pageStack.pop() - posted() - } - } - } - - function submit() { - var message = messageTextField.text - - if (appendSignatureCheckBox.checked) { - message += "\n\n" + backend.signature - } - - submitRequest.query = 'reply_post' + forum_id + '' + topic_id + '' + StringUtils.base64_encode(subjectTextField.text) + '' + StringUtils.base64_encode(message) + '' - - submitRequest.start() - } - } - - } - - } -} diff --git a/ui/viewing/SubForumList.qml b/ui/viewing/SubForumList.qml index a45cec7..90eee4c 100644 --- a/ui/viewing/SubForumList.qml +++ b/ui/viewing/SubForumList.qml @@ -60,9 +60,9 @@ ListView { onTriggered: { if (model.topic) { - forumsPage.pushThreadPage(model.id, text) + forumsPage.pushThreadPage(model.forum_id, model.topic_id, text) } else { - forumsPage.pushSubForumPage(model.id, text, model.can_subscribe, model.is_subscribed) + forumsPage.pushSubForumPage(model.forum_id, text, model.can_subscribe, model.is_subscribed) } } @@ -214,7 +214,7 @@ ListView { var element = get(i) //We need to declare even unused properties here //Needed when there are both topics and categories in a subforum - var pushObject = {"topic": false, "id": element.id, "name": element.name.trim(), "description": viewSubscriptions ? "" : element.description.trim(), "logo": element.logo.trim(), "author": "", "posts": -1, "has_new": 0, "can_subscribe": viewSubscriptions ? 1 : element.can_subscribe, "is_subscribed": viewSubscriptions ? 1 : element.is_subscribed} + var pushObject = { "topic": false, "forum_id": element.id, "topic_id": -1, "name": element.name.trim(), "description": viewSubscriptions ? "" : element.description.trim(), "logo": element.logo.trim(), "author": "", "posts": -1, "has_new": 0, "can_subscribe": viewSubscriptions ? 1 : element.can_subscribe, "is_subscribed": viewSubscriptions ? 1 : element.is_subscribed } if (!isForumOverview) { forumListModel.insert(i, pushObject) } else { @@ -352,7 +352,8 @@ ListView { property bool viewSubscriptions: forumsList.viewSubscriptions query: "/methodResponse/params/param/value/struct/member/value/array/data/value/struct" - XmlRole { name: "id"; query: "member[name='topic_id']/value/number()" } + XmlRole { name: "id"; query: "member[name='topic_id']/value/string/number()" } + XmlRole { name: "forum_id"; query: "member[name='forum_id']/value/string/number()" } XmlRole { name: "title"; query: "member[name='topic_title']/value/base64/string()" } // XmlRole { name: "description"; query: "member[name='short_content']/value/base64/string()" } XmlRole { name: "author"; query: "member[name='topic_author_name']/value/base64/string()" } @@ -381,7 +382,7 @@ ListView { var element = get(i); //We need to declare even unused properties here //Needed when there are both topics and categories in a subforum - forumListModel.append({"topic": true, "id": element.id, "name": element.title.trim(), "description": "", "logo": "", "author": element.author.trim(), "posts": element.posts, "has_new": element.has_new, "can_subscribe": 1, "is_subscribed": 0}); + forumListModel.append({ "topic": true, "forum_id": element.forum_id, "topic_id": element.id, "name": element.title.trim(), "description": "", "logo": "", "author": element.author.trim(), "posts": element.posts, "has_new": element.has_new, "can_subscribe": 1, "is_subscribed": 0 }); } } } diff --git a/ui/viewing/SubForumPage.qml b/ui/viewing/SubForumPage.qml index c636c98..219c8dd 100644 --- a/ui/viewing/SubForumPage.qml +++ b/ui/viewing/SubForumPage.qml @@ -42,7 +42,8 @@ PageWithBottomEdge { property alias current_forum: forumsList.current_forum property bool isForumOverview: current_forum === 0 - property int selectedId: -1 + property int selectedTopicId: -1 + property int selectedForumId: -1 property string selectedTitle: "" property bool selectedCanSubscribe: false property bool selectedIsSubscribed: false @@ -108,7 +109,7 @@ PageWithBottomEdge { iconName: "compose" visible: backend.currentSession.loggedIn && current_forum > 0 && forumsList.canPost && forumsList.mode === "" && forumsList.hasTopics //hasTopics as a workaround for disabling posting in category-only subforums; current_forum > 0 also disables the action when viewSubscriptions === true onTriggered: { - component = Qt.createComponent("ThreadCreationPage.qml") + component = Qt.createComponent("MessageComposerPage.qml") if (component.status === Component.Ready) { finishNewTopicPageCreation() @@ -118,7 +119,8 @@ PageWithBottomEdge { } function finishNewTopicPageCreation() { - var page = component.createObject(mainView, {"forum_id": current_forum}) + var page = component.createObject(mainView, { "mode": "thread" }) + page.forum_id = current_forum //Needs to be set after mode page.posted.connect(onNewTopicCreated) pageStack.push(page) } @@ -162,9 +164,8 @@ PageWithBottomEdge { } } - function onNewTopicCreated(subject, topicId) { - selectedTitle = subject - pushThreadPage(topicId) //Show thread + function onNewTopicCreated(subject, forumId, topicId) { + pushThreadPage(forumId, topicId, subject) //Show thread forumsList.reload() } @@ -225,7 +226,7 @@ PageWithBottomEdge { } function pushSubForumPage(forumId, title, canSubscribe, isSubscribed) { - selectedId = forumId + selectedForumId = forumId selectedTitle = title selectedCanSubscribe = (typeof(canSubscribe) === "bool" || typeof(canSubscribe) === "number") ? canSubscribe : true selectedIsSubscribed = (typeof(isSubscribed) === "bool" || typeof(isSubscribed) === "number") ? isSubscribed : false @@ -239,10 +240,10 @@ PageWithBottomEdge { } function finishSubForumPageCreation() { - var page = component.createObject(mainView, {"title": selectedTitle, "current_forum": selectedId, "loadingSpinnerRunning": true, "disableBottomEdge": disableBottomEdge, "canSubscribe": selectedCanSubscribe, "isSubscribed": selectedIsSubscribed}) + var page = component.createObject(mainView, {"title": selectedTitle, "current_forum": selectedForumId, "loadingSpinnerRunning": true, "disableBottomEdge": disableBottomEdge, "canSubscribe": selectedCanSubscribe, "isSubscribed": selectedIsSubscribed}) page.onIsSubscribedChanged.connect(function() { //Change is_subscribed attribute when the subscription state is changed for (var i = 0; i < forumsList.model.count; i++) { - if (forumsList.model.get(i).id === selectedId) { + if (forumsList.model.get(i).id === selectedForumId) { forumsList.model.setProperty(i, "is_subscribed", page.isSubscribed ? 1 : 0) //is_subscribed requires a number break } @@ -251,8 +252,9 @@ PageWithBottomEdge { pageStack.push(page) } - function pushThreadPage(topicId, title) { - selectedId = topicId + function pushThreadPage(forumId, topicId, title) { + selectedForumId = forumId + selectedTopicId = topicId selectedTitle = title component = Qt.createComponent("ThreadPage.qml") @@ -265,8 +267,8 @@ PageWithBottomEdge { function finishThreadPageCreation() { var vBulletinAnnouncement = backend.currentSession.configModel.isVBulletin && forumsList.mode === "ANN" - var page = component.createObject(mainView, {"title": selectedTitle, "loadingSpinnerRunning": true, "forum_id": current_forum, "vBulletinAnnouncement": vBulletinAnnouncement}) - page.current_topic = selectedId //Need to set vBulletinAnnouncement before current_topic!!! Therefore, this is executed after the creation of the Page. + var page = component.createObject(mainView, {"title": selectedTitle, "loadingSpinnerRunning": true, "forum_id": selectedForumId, "vBulletinAnnouncement": vBulletinAnnouncement}) + page.current_topic = selectedTopicId //Need to set vBulletinAnnouncement before current_topic!!! Therefore, this is executed after the creation of the Page. pageStack.push(page) } diff --git a/ui/viewing/ThreadCreationPage.qml b/ui/viewing/ThreadCreationPage.qml deleted file mode 100644 index b04737b..0000000 --- a/ui/viewing/ThreadCreationPage.qml +++ /dev/null @@ -1,147 +0,0 @@ -/************************************************************************* -** Forum Browser -** -** Copyright (c) 2014 Niklas Wenzel -** -** $QT_BEGIN_LICENSE:GPL$ -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; see the file COPYING. If not, write to -** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -** Boston, MA 02110-1301, USA. -** -** -** $QT_END_LICENSE$ -** -*************************************************************************/ - -import QtQuick 2.2 -import Ubuntu.Components 1.1 -import Ubuntu.Components.Popups 1.0 -import "../../stringutils.js" as StringUtils -import "../../backend" - -Page { - id: threadCreationPage - anchors.fill: parent - - signal posted(string subject, int topicId); - - property int forum_id: -1 - property int topic_id: -1 - - title: i18n.tr("New Topic") - - Flickable { - anchors { - top: parent.top - bottom: parent.bottom - left: parent.left - right: parent.right - margins: units.gu(1) - } - - contentHeight: column.height - - Column { - id: column - height: childrenRect.height - width: parent.width - spacing: units.gu(1) - - Label { - text: i18n.tr("Subject:") - } - - TextField { - id: subjectTextField - width: parent.width - - KeyNavigation.priority: KeyNavigation.BeforeItem - KeyNavigation.tab: messageTextField - } - - Label { - text: i18n.tr("Message:") - } - - TextArea { - id: messageTextField - width: parent.width - - KeyNavigation.priority: KeyNavigation.BeforeItem - KeyNavigation.backtab: subjectTextField - } - - Row { - id: signatureRow - width: parent.width - spacing: units.gu(1) - - CheckBox { - id: appendSignatureCheckBox - checked: true - anchors.verticalCenter: parent.verticalCenter - } - - Label { - id: signatureLabel - text: backend.signature - wrapMode: Text.Wrap - - anchors.verticalCenter: parent.verticalCenter - width: parent.width - signatureRow.spacing - appendSignatureCheckBox.width - } - } - - Button { - id: submitButton - text: i18n.tr("Submit") - width: parent.width - - onClicked: submit() - - ApiRequest { - id: submitRequest - checkSuccess: true - - onQuerySuccessResult: { - if (success) { - //Get the id of the topic - var idIndex = responseXml.indexOf("topic_id"); - var stringTag = responseXml.indexOf("", idIndex) - var stringEndTag = responseXml.indexOf("", idIndex) - var id = parseInt(responseXml.substring(stringTag + 8, stringEndTag)) - - pageStack.pop() - posted(subjectTextField.text, id) - } - } - } - - function submit() { - var message = messageTextField.text - - if (appendSignatureCheckBox.checked) { - message += "\n\n" + backend.signature - } - - submitRequest.query = 'new_topic' + forum_id + '' + StringUtils.base64_encode(subjectTextField.text) + '' + StringUtils.base64_encode(message) + '' - - submitRequest.start() - } - } - - } - - } -} diff --git a/ui/viewing/ThreadPage.qml b/ui/viewing/ThreadPage.qml index 8d0dce2..d1037f4 100644 --- a/ui/viewing/ThreadPage.qml +++ b/ui/viewing/ThreadPage.qml @@ -45,12 +45,13 @@ PageWithBottomEdge { property int pageCount: Math.floor(threadList.totalPostCount/backend.postsPerPage + (threadList.totalPostCount % backend.postsPerPage === 0 ? 0 : 1)) - bottomEdgePageSource: "PostCreationPage.qml" + bottomEdgePageSource: "MessageComposerPage.qml" bottomEdgeTitle: i18n.tr("New Post") bottomEdgeEnabled: backend.currentSession.loggedIn && threadList.canReply && !threadList.isClosed && !vBulletinAnnouncement onBottomEdgeReleased: { if (bottomEdgePage !== null) { + bottomEdgePage.mode = "post" bottomEdgePage.forum_id = forum_id bottomEdgePage.topic_id = current_topic bottomEdgePage.posted.connect(threadList.reload)