From 72c49c3777f4a4bc7c8001420207dd01a9ffd021 Mon Sep 17 00:00:00 2001 From: molan-git Date: Thu, 18 Jun 2020 18:40:24 +0200 Subject: [PATCH] new features / ui improvements - add Toots to bookmarks --- harbour-tooter.pro | 3 +- qml/images/icon-s-bookmark.svg | 9 + qml/lib/API.js | 2 + qml/lib/Worker.js | 1 + qml/pages/ConversationPage.qml | 701 +++++++++++------------ qml/pages/MainPage.qml | 3 +- qml/pages/ProfilePage.qml | 38 +- qml/pages/components/ItemUser.qml | 5 +- qml/pages/components/MediaBlock.qml | 26 +- qml/pages/components/MiniHeader.qml | 3 +- qml/pages/components/ProfileHeader.qml | 39 +- qml/pages/components/VisualContainer.qml | 71 ++- translations/harbour-tooter-de.ts | 12 + translations/harbour-tooter-el.ts | 12 + translations/harbour-tooter-es.ts | 26 +- translations/harbour-tooter-fr.ts | 12 + translations/harbour-tooter-it.ts | 91 +-- translations/harbour-tooter-nl.ts | 38 +- translations/harbour-tooter-nl_BE.ts | 12 + translations/harbour-tooter-oc.ts | 12 + translations/harbour-tooter-pl.ts | 12 + translations/harbour-tooter-ru.ts | 12 + translations/harbour-tooter-sr.ts | 12 + translations/harbour-tooter-sv.ts | 12 + translations/harbour-tooter-zh_CN.ts | 12 + translations/harbour-tooter.ts | 20 +- 26 files changed, 706 insertions(+), 490 deletions(-) create mode 100644 qml/images/icon-s-bookmark.svg diff --git a/harbour-tooter.pro b/harbour-tooter.pro index 7ec9265..a78b746 100644 --- a/harbour-tooter.pro +++ b/harbour-tooter.pro @@ -75,6 +75,7 @@ DISTFILES += qml/harbour-tooter.qml \ qml/lib/API.js \ qml/images/icon-s-bot.svg \ qml/images/icon-s-following \ + qml/images/icon-s-bookmark \ qml/images/icon-m-emoji.svg \ qml/images/icon-m-profile.svg \ qml/images/icon-l-profile.svg \ @@ -93,7 +94,7 @@ SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 # to disable building translations every time, comment out the # following CONFIG line -# CONFIG += sailfishapp_i18n +CONFIG += sailfishapp_i18n TRANSLATIONS += translations/harbour-tooter.ts \ translations/harbour-tooter-de.ts \ diff --git a/qml/images/icon-s-bookmark.svg b/qml/images/icon-s-bookmark.svg new file mode 100644 index 0000000..6a7cba2 --- /dev/null +++ b/qml/images/icon-s-bookmark.svg @@ -0,0 +1,9 @@ + + icon-s-bookmark + + + + + + + diff --git a/qml/lib/API.js b/qml/lib/API.js index cbbb579..1f80f11 100644 --- a/qml/lib/API.js +++ b/qml/lib/API.js @@ -95,6 +95,8 @@ var tootParser = function(data){ ret.reblogged = data.reblogged ? true : false ret.status_reblogs_count = data.reblogs_count ? data.reblogs_count : false + ret.bookmarked = data.bookmarked ? true : false + ret.muted = data.muted ? true : false ret.sensitive = data.sensitive ? true : false ret.visibility = data.visibility ? data.visibility : false diff --git a/qml/lib/Worker.js b/qml/lib/Worker.js index c8cfb23..268c024 100644 --- a/qml/lib/Worker.js +++ b/qml/lib/Worker.js @@ -152,6 +152,7 @@ function parseAccounts(collection, prefix, data) { // Optional attributes //res[prefix + 'account_fields'] = data["fields"] res[prefix + 'account_bot'] = data["bot"] + res[prefix + 'account_group'] = data["group"] res[prefix + 'account_source'] = data["source"] //console.log(JSON.stringify(res)) diff --git a/qml/pages/ConversationPage.qml b/qml/pages/ConversationPage.qml index f54a0a6..674a76c 100644 --- a/qml/pages/ConversationPage.qml +++ b/qml/pages/ConversationPage.qml @@ -6,73 +6,74 @@ import "./components/" Page { - id: conversationPage + id: conversationPage property string type property string description: "" property string headerTitle: "" - property string suggestedUser: "" - property ListModel suggestedModel - property string toot_id: "" + property string suggestedUser: "" + property ListModel suggestedModel + property string toot_id: "" property string toot_url: "" property string toot_uri: "" property int tootMaxChar: 500; property bool bot: false //otherwise ReferenceError ProfileHeader.qml property bool followed_by: false //otherwise ReferenceError ProfileHeader.qml property bool locked: false //otherwise ReferenceError ProfileHeader.qml + property bool group: false //otherwise ReferenceError ProfileHeader.qml property ListModel mdl - allowedOrientations: Orientation.All - onSuggestedUserChanged: { - console.log(suggestedUser) - suggestedModel = Qt.createQmlObject( - 'import QtQuick 2.0; ListModel { }', - Qt.application, 'InternalQmlObject' - ) - predictionList.visible = false - if (suggestedUser.length > 0) { - var msg = { - "action": 'accounts/search', - "method": 'GET', - "model": suggestedModel, - "mode": "append", - "params": [{ - "name": "q", - "data": suggestedUser - }], - "conf": Logic.conf - } - worker.sendMessage(msg) - predictionList.visible = true - } - } + allowedOrientations: Orientation.All + onSuggestedUserChanged: { + console.log(suggestedUser) + suggestedModel = Qt.createQmlObject( + 'import QtQuick 2.0; ListModel { }', + Qt.application, 'InternalQmlObject' + ) + predictionList.visible = false + if (suggestedUser.length > 0) { + var msg = { + "action": 'accounts/search', + "method": 'GET', + "model": suggestedModel, + "mode": "append", + "params": [{ + "name": "q", + "data": suggestedUser + }], + "conf": Logic.conf + } + worker.sendMessage(msg) + predictionList.visible = true + } + } - ListModel { - id: mediaModel - onCountChanged: { - btnAddImage.enabled = mediaModel.count < 4 - } - } + ListModel { + id: mediaModel + onCountChanged: { + btnAddImage.enabled = mediaModel.count < 4 + } + } - WorkerScript { - id: worker - source: "../lib/Worker.js" - onMessage: { - console.log(JSON.stringify(messageObject)) - } - } + WorkerScript { + id: worker + source: "../lib/Worker.js" + onMessage: { + console.log(JSON.stringify(messageObject)) + } + } - ProfileHeader { - id: header - visible: false - } + ProfileHeader { + id: header + visible: false + } SilicaListView { id: myList - header: PageHeader { + header: PageHeader { title: headerTitle // pageTitle pushed from MainPage.qml or VisualContainer.qml - } - clip: true + } + clip: true anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right @@ -81,25 +82,25 @@ Page { } else { hiddenPanel.top } - model: mdl - section { - property: 'section' - delegate: SectionHeader { - height: Theme.itemSizeExtraSmall - text: Format.formatDate(section, Formatter.DateMedium) - } - } - delegate: VisualContainer { - } - onCountChanged: { - if (mdl) - for (var i = 0; i < mdl.count; i++) { - if (mdl.get(i).status_id === toot_id) { - console.log(mdl.get(i).status_id) - positionViewAtIndex(i, ListView.Center) - } - } - } + model: mdl + section { + property: 'section' + delegate: SectionHeader { + height: Theme.itemSizeExtraSmall + text: Format.formatDate(section, Formatter.DateMedium) + } + } + delegate: VisualContainer { + } + onCountChanged: { + if (mdl) + for (var i = 0; i < mdl.count; i++) { + if (mdl.get(i).status_id === toot_id) { + console.log(mdl.get(i).status_id) + positionViewAtIndex(i, ListView.Center) + } + } + } PullDownMenu { id: pulleyConversation @@ -133,9 +134,9 @@ Page { } } - Rectangle { - id: predictionList - visible: false + Rectangle { + id: predictionList + visible: false color: Theme.highlightDimmerColor height: parent.height - panel.height - (Theme.paddingLarge * 4.5) anchors { @@ -151,27 +152,27 @@ Page { SilicaListView { rotation: 180 anchors.fill: parent - model: suggestedModel - clip: true + model: suggestedModel + clip: true quickScroll: false VerticalScrollDecorator {} - delegate: ItemUser { + delegate: ItemUser { rotation: 180 - onClicked: { - var start = toot.cursorPosition - while (toot.text[start] !== "@" && start > 0) { - start-- - } - textOperations.text = toot.text - textOperations.cursorPosition = toot.cursorPosition - textOperations.moveCursorSelection(start - 1, TextInput.SelectWords) - toot.text = textOperations.text.substring(0, textOperations.selectionStart) - + ' @' - + model.account_acct - + ' ' - + textOperations.text.substring(textOperations.selectionEnd).trim() + onClicked: { + var start = toot.cursorPosition + while (toot.text[start] !== "@" && start > 0) { + start-- + } + textOperations.text = toot.text + textOperations.cursorPosition = toot.cursorPosition + textOperations.moveCursorSelection(start - 1, TextInput.SelectWords) + toot.text = textOperations.text.substring(0, textOperations.selectionStart) + + ' @' + + model.account_acct + + ' ' + + textOperations.text.substring(textOperations.selectionEnd).trim() - toot.cursorPosition = toot.text.indexOf('@' + model.account_acct) + toot.cursorPosition = toot.text.indexOf('@' + model.account_acct) } } onCountChanged: { @@ -182,82 +183,80 @@ Page { } } - DockedPanel { - id: panel - width: parent.width + DockedPanel { + id: panel + width: parent.width height: progressBar.height + toot.height + (mediaModel.count ? uploadedImages.height : 0) - + btnContentWarning.height + Theme.paddingMedium - + (warningContent.visible ? warningContent.height : 0) + + btnContentWarning.height + Theme.paddingMedium + + (warningContent.visible ? warningContent.height : 0) dock: Dock.Bottom - open: if (type == "new") { - true - } else false + open: true animationDuration: 300 Rectangle { - width: parent.width - height: progressBar.height - color: Theme.highlightBackgroundColor - opacity: 0.2 - anchors { - left: parent.left - right: parent.right - top: parent.top - } - } + width: parent.width + height: progressBar.height + color: Theme.highlightBackgroundColor + opacity: 0.2 + anchors { + left: parent.left + right: parent.right + top: parent.top + } + } - Rectangle { - id: progressBar - width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0 + Rectangle { + id: progressBar + width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0 height: Theme.itemSizeSmall * 0.05 - color: Theme.highlightBackgroundColor - opacity: 0.7 - anchors { - left: parent.left + color: Theme.highlightBackgroundColor + opacity: 0.7 + anchors { + left: parent.left top: parent.top - } - } + } + } - TextField { - id: warningContent - visible: false - height: visible ? implicitHeight : 0 - anchors { + TextField { + id: warningContent + visible: false + height: visible ? implicitHeight : 0 + anchors { top: parent.top - topMargin: Theme.paddingMedium - left: parent.left - right: parent.right - } - autoScrollEnabled: true - labelVisible: false + topMargin: Theme.paddingMedium + left: parent.left + right: parent.right + } + autoScrollEnabled: true + labelVisible: false font.pixelSize: Theme.fontSizeSmall placeholderText: qsTr("Write your warning here") placeholderColor: palette.highlightColor color: palette.highlightColor - horizontalAlignment: Text.AlignLeft - EnterKey.onClicked: {} - } + horizontalAlignment: Text.AlignLeft + EnterKey.onClicked: {} + } - TextInput { - id: textOperations - visible: false - } + TextInput { + id: textOperations + visible: false + } - TextArea { - id: toot - anchors { - top: warningContent.bottom - topMargin: Theme.paddingMedium - left: parent.left + TextArea { + id: toot + anchors { + top: warningContent.bottom + topMargin: Theme.paddingMedium + left: parent.left right: parent.right rightMargin: Theme.paddingLarge * 2 - } - autoScrollEnabled: true - labelVisible: false + } + autoScrollEnabled: true + labelVisible: false text: description !== "" && (description.charAt(0) === '@' - || description.charAt( - 0) === '#') ? description + ' ' : '' + || description.charAt( + 0) === '#') ? description + ' ' : '' height: if (type !== "reply") { Math.max(conversationPage.height / 3, Math.min(conversationPage.height * 0.65, implicitHeight)) } @@ -268,269 +267,269 @@ Page { placeholderText: qsTr("What's on your mind?") font.pixelSize: Theme.fontSizeSmall EnterKey.onClicked: {} - onTextChanged: { - textOperations.text = toot.text - textOperations.cursorPosition = toot.cursorPosition - textOperations.selectWord() - textOperations.select( - textOperations.selectionStart ? textOperations.selectionStart - 1 : 0, - textOperations.selectionEnd) - //console.log(textOperations.text.substr(textOperations.selectionStart, textOperations.selectionEnd)) - console.log(toot.text.length) - suggestedUser = "" - if (textOperations.selectedText.charAt(0) === "@") { - suggestedUser = textOperations.selectedText.trim().substring(1) - } - } - } + onTextChanged: { + textOperations.text = toot.text + textOperations.cursorPosition = toot.cursorPosition + textOperations.selectWord() + textOperations.select( + textOperations.selectionStart ? textOperations.selectionStart - 1 : 0, + textOperations.selectionEnd) + //console.log(textOperations.text.substr(textOperations.selectionStart, textOperations.selectionEnd)) + console.log(toot.text.length) + suggestedUser = "" + if (textOperations.selectedText.charAt(0) === "@") { + suggestedUser = textOperations.selectedText.trim().substring(1) + } + } + } - IconButton { - id: btnSmileys + IconButton { + id: btnSmileys property string selection opacity: 0.7 icon { + source: "../../qml/images/icon-m-emoji.svg?" color: Theme.secondaryColor width: Theme.iconSizeSmallPlus fillMode: Image.PreserveAspectFit - source: "../../qml/images/icon-m-emoji.svg" } - anchors { + anchors { top: warningContent.bottom - bottom: bottom.top - right: parent.right - rightMargin: Theme.paddingSmall - } + bottom: bottom.top + right: parent.right + rightMargin: Theme.paddingSmall + } onSelectionChanged: { console.log(selection) } onClicked: pageStack.push(emojiSelect) - } + } - SilicaGridView { - id: uploadedImages - width: parent.width + SilicaGridView { + id: uploadedImages + width: parent.width anchors.top: bottom.toot - anchors.bottom: parent.bottom + anchors.bottom: parent.bottom height: mediaModel.count ? Theme.itemSizeExtraLarge : 0 model: mediaModel - cellWidth: uploadedImages.width / 4 + cellWidth: uploadedImages.width / 4 cellHeight: Theme.itemSizeExtraLarge - delegate: BackgroundItem { - id: myDelegate - width: uploadedImages.cellWidth - height: uploadedImages.cellHeight - RemorseItem { + delegate: BackgroundItem { + id: myDelegate + width: uploadedImages.cellWidth + height: uploadedImages.cellHeight + RemorseItem { id: remorse - } + } - Image { - anchors.fill: parent - fillMode: Image.PreserveAspectCrop - source: model.preview_url - } - onClicked: { - var idx = index - console.log(idx) - //mediaModel.remove(idx) - remorse.execute(myDelegate, qsTr("Delete"), function () { - mediaModel.remove(idx) - }) - } - } - add: Transition { - NumberAnimation { - property: "opacity" - from: 0 - to: 1.0 - duration: 800 - } - } - remove: Transition { - NumberAnimation { - property: "opacity" - from: 1.0 - to: 0 - duration: 800 - } - } - displaced: Transition { - NumberAnimation { - properties: "x,y" - duration: 800 - easing.type: Easing.InOutBack - } - } - } + Image { + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: model.preview_url + } + onClicked: { + var idx = index + console.log(idx) + //mediaModel.remove(idx) + remorse.execute(myDelegate, qsTr("Delete"), function () { + mediaModel.remove(idx) + }) + } + } + add: Transition { + NumberAnimation { + property: "opacity" + from: 0 + to: 1.0 + duration: 800 + } + } + remove: Transition { + NumberAnimation { + property: "opacity" + from: 1.0 + to: 0 + duration: 800 + } + } + displaced: Transition { + NumberAnimation { + properties: "x,y" + duration: 800 + easing.type: Easing.InOutBack + } + } + } - IconButton { - id: btnContentWarning - anchors { + IconButton { + id: btnContentWarning + anchors { top: toot.bottom topMargin: -Theme.paddingSmall * 1.5 - left: parent.left - leftMargin: Theme.paddingMedium - } - icon.source: "image://theme/icon-s-warning?" - + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor)) - onClicked: warningContent.visible = !warningContent.visible - } + left: parent.left + leftMargin: Theme.paddingMedium + } + icon.source: "image://theme/icon-s-warning?" + + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor)) + onClicked: warningContent.visible = !warningContent.visible + } - IconButton { - id: btnAddImage - enabled: mediaModel.count < 4 - anchors { + IconButton { + id: btnAddImage + enabled: mediaModel.count < 4 + anchors { top: toot.bottom topMargin: -Theme.paddingSmall * 1.5 - left: btnContentWarning.right - leftMargin: Theme.paddingSmall - } - icon.source: "image://theme/icon-s-attach?" - + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor)) - onClicked: { - btnAddImage.enabled = false - var once = true - var imagePicker = pageStack.push("Sailfish.Pickers.ImagePickerPage", {"allowedOrientations": Orientation.All}) - imagePicker.selectedContentChanged.connect(function () { - var imagePath = imagePicker.selectedContent - console.log(imagePath) - imageUploader.setUploadUrl(Logic.conf.instance + "/api/v1/media") - imageUploader.setFile(imagePath) - imageUploader.setAuthorizationHeader(Logic.conf.api_user_token) - imageUploader.upload() - }) - } - } + left: btnContentWarning.right + leftMargin: Theme.paddingSmall + } + icon.source: "image://theme/icon-s-attach?" + + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor)) + onClicked: { + btnAddImage.enabled = false + var once = true + var imagePicker = pageStack.push("Sailfish.Pickers.ImagePickerPage", {"allowedOrientations": Orientation.All}) + imagePicker.selectedContentChanged.connect(function () { + var imagePath = imagePicker.selectedContent + console.log(imagePath) + imageUploader.setUploadUrl(Logic.conf.instance + "/api/v1/media") + imageUploader.setFile(imagePath) + imageUploader.setAuthorizationHeader(Logic.conf.api_user_token) + imageUploader.upload() + }) + } + } - ImageUploader { - id: imageUploader - onProgressChanged: { - console.log("progress " + progress) - uploadProgress.width = parent.width * progress - } - onSuccess: { - uploadProgress.width = 0 - console.log(replyData) - mediaModel.append(JSON.parse(replyData)) - } - onFailure: { - uploadProgress.width = 0 - btnAddImage.enabled = true - console.log(status) - console.log(statusText) - } - } + ImageUploader { + id: imageUploader + onProgressChanged: { + console.log("progress " + progress) + uploadProgress.width = parent.width * progress + } + onSuccess: { + uploadProgress.width = 0 + console.log(replyData) + mediaModel.append(JSON.parse(replyData)) + } + onFailure: { + uploadProgress.width = 0 + btnAddImage.enabled = true + console.log(status) + console.log(statusText) + } + } - ComboBox { + ComboBox { id: privacy - anchors { + anchors { top: toot.bottom topMargin: -Theme.paddingSmall * 1.5 - left: btnAddImage.right + left: btnAddImage.right right: btnSend.left } menu: ContextMenu { - MenuItem { + MenuItem { text: qsTr("Public") - } - MenuItem { + } + MenuItem { text: qsTr("Unlisted") - } - MenuItem { + } + MenuItem { text: qsTr("Followers-only") - } - MenuItem { + } + MenuItem { text: qsTr("Direct") - } - } - } + } + } + } - IconButton { - id: btnSend - icon.source: "image://theme/icon-m-send?" - + (pressed ? Theme.highlightColor : Theme.primaryColor) - anchors { + IconButton { + id: btnSend + icon.source: "image://theme/icon-m-send?" + + (pressed ? Theme.highlightColor : Theme.primaryColor) + anchors { top: toot.bottom topMargin: -Theme.paddingSmall * 1.5 - right: parent.right + right: parent.right rightMargin: Theme.paddingSmall - } - enabled: toot.text !== "" && toot.text.length < tootMaxChar && uploadProgress.width == 0 - onClicked: { + } + enabled: toot.text !== "" && toot.text.length < tootMaxChar && uploadProgress.width == 0 + onClicked: { var visibility = ["public", "unlisted", "private", "direct"] - var media_ids = [] - for (var k = 0; k < mediaModel.count; k++) { - console.log(mediaModel.get(k).id) - media_ids.push(mediaModel.get(k).id) - } - var msg = { - "action": 'statuses', - "method": 'POST', - "model": mdl, - "mode": "append", - "params": { - "status": toot.text, - "visibility": visibility[privacy.currentIndex], - "media_ids": media_ids - }, - "conf": Logic.conf - } - if (toot_id) - msg.params['in_reply_to_id'] = (toot_id) + "" + var media_ids = [] + for (var k = 0; k < mediaModel.count; k++) { + console.log(mediaModel.get(k).id) + media_ids.push(mediaModel.get(k).id) + } + var msg = { + "action": 'statuses', + "method": 'POST', + "model": mdl, + "mode": "append", + "params": { + "status": toot.text, + "visibility": visibility[privacy.currentIndex], + "media_ids": media_ids + }, + "conf": Logic.conf + } + if (toot_id) + msg.params['in_reply_to_id'] = (toot_id) + "" - if (warningContent.visible && warningContent.text.length > 0) { - msg.params['sensitive'] = 1 - msg.params['spoiler_text'] = warningContent.text - } + if (warningContent.visible && warningContent.text.length > 0) { + msg.params['sensitive'] = 1 + msg.params['spoiler_text'] = warningContent.text + } worker.sendMessage(msg) warningContent.text = "" toot.text = "" mediaModel.clear() sentBanner.showText(qsTr("Toot sent!")) - } - } + } + } - Rectangle { - id: uploadProgress - color: Theme.highlightBackgroundColor + Rectangle { + id: uploadProgress + color: Theme.highlightBackgroundColor anchors.bottom: parent.bottom - anchors.left: parent.left + anchors.left: parent.left height: Theme.itemSizeSmall * 0.05 - } - } + } + } - Component.onCompleted: { - toot.cursorPosition = toot.text.length - if (mdl.count > 0) { - var setIndex = 0 - switch (mdl.get(0).status_visibility) { - case "unlisted": - setIndex = 1 - break - case "private": - setIndex = 2 - break - case "direct": - privacy.enabled = false - setIndex = 3 - break - default: - privacy.enabled = true - setIndex = 0 - } - privacy.currentIndex = setIndex - } + Component.onCompleted: { + toot.cursorPosition = toot.text.length + if (mdl.count > 0) { + var setIndex = 0 + switch (mdl.get(0).status_visibility) { + case "unlisted": + setIndex = 1 + break + case "private": + setIndex = 2 + break + case "direct": + privacy.enabled = false + setIndex = 3 + break + default: + privacy.enabled = true + setIndex = 0 + } + privacy.currentIndex = setIndex + } - console.log(JSON.stringify()) + console.log(JSON.stringify()) - worker.sendMessage({ - "action": 'statuses/' + mdl.get(0).status_id + '/context', - "method": 'GET', - "model": mdl, - "params": { }, - "conf": Logic.conf - }) - } + worker.sendMessage({ + "action": 'statuses/' + mdl.get(0).status_id + '/context', + "method": 'GET', + "model": mdl, + "params": { }, + "conf": Logic.conf + }) + } BackgroundItem { id: hiddenPanel @@ -587,7 +586,7 @@ Page { EmojiSelect { id: emojiSelect - } + } InfoBanner { id: sentBanner diff --git a/qml/pages/MainPage.qml b/qml/pages/MainPage.qml index 6ccd4f0..a0bed46 100644 --- a/qml/pages/MainPage.qml +++ b/qml/pages/MainPage.qml @@ -184,7 +184,8 @@ Page { "following_count": model.account_following_count, "statuses_count": model.account_statuses_count, "locked": model.account_locked, - "bot": model.account_bot + "bot": model.account_bot, + "group": model.account_group }) } } diff --git a/qml/pages/ProfilePage.qml b/qml/pages/ProfilePage.qml index f0c0206..0cf7bd5 100644 --- a/qml/pages/ProfilePage.qml +++ b/qml/pages/ProfilePage.qml @@ -21,6 +21,7 @@ Page { property int followers_count property bool locked: false property bool bot: false + property bool group: false property bool following: false property bool followed_by: false property bool requested: false @@ -68,16 +69,9 @@ Page { case 'following_count': following_count = messageObject.data break; - case 'acct': - // line below was commented out, reason unknown - // username = messageObject.data - break; - case 'locked': - locked = messageObject.data - break; - case 'bot': - bot = messageObject.data - break; + /* case 'acct': + username = messageObject.data + break; */ case 'created_at': created_at = messageObject.data break; @@ -99,10 +93,7 @@ Page { break; case 'blocking': blocking = messageObject.data - followers_count = followers_count + (blocking ? -1 : 0) - break; - case 'followed_by': - followed_by = messageObject.data + // followers_count = followers_count + (blocking ? -1 : 0) break; } } @@ -121,13 +112,6 @@ Page { } worker.sendMessage(msg) - // reason for crashes when opening ProfilePage.qml - /* msg = { - 'action' : "accounts/"+user_id, - 'conf' : Logic.conf - } - worker.sendMessage(msg) */ - } else { var instance = Logic.conf['instance'].split("//") msg = { @@ -160,13 +144,10 @@ Page { } } - ExpandingSectionGroup { // ProfilePage ExpandingSection + // ProfilePage ExpandingSection + ExpandingSectionGroup { id: profileExpander - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - } + anchors.bottom: parent.bottom ExpandingSection { id: expandingSection1 @@ -174,13 +155,12 @@ Page { //: If there's no good translation for "About", use "Details" (in details about profile). qsTr("About") content.sourceComponent: Column { - height: Math.min( txtContainer, parent.height * 0.7 ) spacing: Theme.paddingLarge Item { id: txtContainer width: parent.width - height: Math.min( txtNote.height, parent.height * 0.55 ) + height: profilePage.isPortrait ? Math.min( txtNote.height, parent.height * 0.5 ) : Math.min( txtNote.height, parent.height * 0.2 ) visible: { if ((note.text === "") || ( note.text === "

" )) { false diff --git a/qml/pages/components/ItemUser.qml b/qml/pages/components/ItemUser.qml index 29a3cca..4357a97 100644 --- a/qml/pages/components/ItemUser.qml +++ b/qml/pages/components/ItemUser.qml @@ -31,7 +31,7 @@ BackgroundItem { size: BusyIndicatorSize.Small opacity: img.status === Image.Ready ? 0.0 : 1.0 Behavior on opacity { FadeAnimator {} } - running: avatar.status !== Image.Ready; + running: avatar.status !== Image.Ready anchors.centerIn: parent } @@ -105,6 +105,7 @@ BackgroundItem { "following_count": model.account_following_count, "statuses_count": model.account_statuses_count, "locked": model.account_locked, - "bot": model.account_bot + "bot": model.account_bot, + "group": model.account_group } ) } diff --git a/qml/pages/components/MediaBlock.qml b/qml/pages/components/MediaBlock.qml index 650bfdb..0e60884 100644 --- a/qml/pages/components/MediaBlock.qml +++ b/qml/pages/components/MediaBlock.qml @@ -32,8 +32,8 @@ Item { break; case 2: - placeholder1.visible = true; - placeholder2.visible = true; + placeholder1.visible = true + placeholder2.visible = true placeholder1.width = (holder.width-Theme.paddingSmall)/2 placeholder1.height = placeholder1.width placeholder2.width = placeholder1.width @@ -43,10 +43,10 @@ Item { break; case 3: - placeholder1.visible = true; - placeholder2.visible = true; - placeholder3.visible = true; - placeholder4.visible = false; + placeholder1.visible = true + placeholder2.visible = true + placeholder3.visible = true + placeholder4.visible = false placeholder1.width = holder.width - Theme.paddingSmall - Theme.itemSizeLarge; placeholder1.height = Theme.itemSizeLarge*2+Theme.paddingSmall @@ -59,16 +59,16 @@ Item { break; case 4: - placeholder1.visible = true; - placeholder2.visible = true; - placeholder3.visible = true; - placeholder4.visible = true; + placeholder1.visible = true + placeholder2.visible = true + placeholder3.visible = true + placeholder4.visible = true placeholder1.width = placeholder2.width = placeholder3.width = placeholder4.width = (holder.width - 3*Theme.paddingSmall)/4 placeholder1.height = placeholder2.height = placeholder3.height = placeholder4.height = Theme.itemSizeLarge*2+Theme.paddingSmall - placeholder2.x = 1*(placeholder1.width)+ 1*Theme.paddingSmall; - placeholder3.x = 2*(placeholder1.width)+ 2*Theme.paddingSmall; - placeholder4.x = 3*(placeholder1.width)+ 3*Theme.paddingSmall; + placeholder2.x = 1*(placeholder1.width)+ 1*Theme.paddingSmall + placeholder3.x = 2*(placeholder1.width)+ 2*Theme.paddingSmall + placeholder4.x = 3*(placeholder1.width)+ 3*Theme.paddingSmall holder.height = placeholder1.height break; diff --git a/qml/pages/components/MiniHeader.qml b/qml/pages/components/MiniHeader.qml index 6347664..aa4f5e2 100644 --- a/qml/pages/components/MiniHeader.qml +++ b/qml/pages/components/MiniHeader.qml @@ -20,10 +20,11 @@ Item { anchors.left: parent.left } - Image { + Icon { id: icnBot visible: account_bot source: "../../images/icon-s-bot.svg?" + ( pressed ? Theme.highlightColor : Theme.primaryColor ) + color: Theme.primaryColor width: account_bot ? Theme.iconSizeExtraSmall * 1.3 : 0 height: width y: Theme.paddingLarge diff --git a/qml/pages/components/ProfileHeader.qml b/qml/pages/components/ProfileHeader.qml index de85db0..8410136 100644 --- a/qml/pages/components/ProfileHeader.qml +++ b/qml/pages/components/ProfileHeader.qml @@ -12,7 +12,7 @@ Item { property string bg: "" width: parent.width - height: avatarImage.height + Theme.paddingLarge*3 + infoLbl.height + Theme.paddingLarge + height: avatarImage.height + Theme.paddingLarge*3 + infoLbl.height Rectangle { id: bgImage @@ -27,7 +27,6 @@ Item { asynchronous: true fillMode: Image.PreserveAspectCrop source: bg - opacity: 0.8 anchors.fill: parent } } @@ -40,11 +39,11 @@ Item { ? Theme.highlightColor : Theme.primaryColor) else image - width: description === "" ? Theme.iconSizeMedium : Theme.iconSizeLarge + width: Theme.iconSizeLarge height: width anchors { left: parent.left - leftMargin: Theme.paddingLarge + leftMargin: Theme.horizontalPageMargin top: parent.top topMargin: Theme.paddingLarge * 1.5 } @@ -69,11 +68,11 @@ Item { Column { anchors { top: parent.top - topMargin: Theme.paddingLarge * 1.5 + topMargin: Theme.paddingLarge left: avatarImage.right - leftMargin: Theme.paddingLarge + leftMargin: Theme.horizontalPageMargin right: parent.right - rightMargin: Theme.paddingLarge + rightMargin: Theme.horizontalPageMargin verticalCenter: parent.verticalCenter } @@ -106,14 +105,32 @@ Item { id: infoLbl spacing: Theme.paddingLarge layoutDirection: Qt.RightToLeft - height: followed_by || locked || bot ? Theme.iconSizeSmall + Theme.paddingSmall : 0 + height: followed_by || locked || bot || group ? Theme.iconSizeSmall + Theme.paddingSmall : 0 anchors { top: avatarImage.bottom - topMargin: Theme.paddingLarge + topMargin: Theme.paddingMedium left: parent.left - leftMargin: Theme.paddingLarge + leftMargin: Theme.horizontalPageMargin right: parent.right - rightMargin: Theme.paddingLarge + rightMargin: Theme.horizontalPageMargin + } + + Rectangle { + id: groupBg + visible: (group ? true : false) + radius: Theme.paddingSmall + color: Theme.secondaryHighlightColor + width: groupLbl.width + 2*Theme.paddingLarge + height: parent.height + + Label { + id: groupLbl + text: qsTr("Group") + font.pixelSize: Theme.fontSizeExtraSmall + color: Theme.primaryColor + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } } Rectangle { diff --git a/qml/pages/components/VisualContainer.qml b/qml/pages/components/VisualContainer.qml index 98d5217..cd81ef3 100644 --- a/qml/pages/components/VisualContainer.qml +++ b/qml/pages/components/VisualContainer.qml @@ -93,7 +93,8 @@ BackgroundItem { "following_count": model.account_following_count, "statuses_count": model.account_statuses_count, "locked": model.account_locked, - "bot": model.account_bot + "bot": model.account_bot, + "group": model.account_group } ) } } @@ -123,7 +124,7 @@ BackgroundItem { visible: status_visibility === "direct" width: Theme.iconSizeMedium height: width - source: "image://theme/icon-m-mail" + source: "../../images/icon-m-mail.svg?" anchors { horizontalCenter: avatar.horizontalCenter top: avatar.bottom @@ -172,7 +173,8 @@ BackgroundItem { "following_count": model.reblog_account_following_count, "statuses_count": model.reblog_account_statuses_count, "locked": model.reblog_account_locked, - "bot": model.reblog_account_bot + "bot": model.reblog_account_bot, + "group": model.reblog_account_group } ) } } @@ -213,7 +215,7 @@ BackgroundItem { Theme.paddingLarge } else if (myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) { Math.min( implicitHeight, Theme.itemSizeExtraLarge * 1.5 ) - } else content.length ? (contentWarningLabel.paintedHeight > paintedHeight ? contentWarningLabel.paintedHeight : paintedHeight) : 0 + } else content.length ? ( contentWarningLabel.paintedHeight > paintedHeight ? contentWarningLabel.paintedHeight : paintedHeight ) : 0 anchors { left: miniHeader.left right: miniHeader.right @@ -249,6 +251,7 @@ BackgroundItem { // Content warning cover for Toots Rectangle { + id: contentWarningBg color: Theme.highlightDimmerColor visible: status_spoiler_text.length > 0 anchors.fill: parent @@ -320,7 +323,7 @@ BackgroundItem { model.reblogged = !model.reblogged } - Image { + Icon { id: icRT source: "image://theme/icon-s-retweet?" + (!model.reblogged ? Theme.highlightColor : Theme.primaryColor) width: Theme.iconSizeExtraSmall @@ -347,9 +350,9 @@ BackgroundItem { MenuItem { id: mnuFavourite visible: model.type !== "follow" - text: typeof model.favourited !== "undefined" && model.favourited ? qsTr("Unfavorite") : qsTr("Favorite") + text: typeof model.status_favourited !== "undefined" && model.status_favourited ? qsTr("Unfavorite") : qsTr("Favorite") onClicked: { - var status = typeof model.favourited !== "undefined" && model.favourited + var status = typeof model.status_favourited !== "undefined" && model.status_favourited worker.sendMessage({ "conf" : Logic.conf, "params" : [], @@ -358,25 +361,25 @@ BackgroundItem { "action" : "statuses/"+model.status_id+"/" + (status ? "unfavourite" : "favourite") }) model.status_favourites_count = !status ? model.status_favourites_count+1 : (model.status_favourites_count > 0 ? model.status_favourites_count-1 : model.status_favourites_count); - model.favourited = !model.favourited + model.status_favourited = !model.status_favourited } - Image { + Icon { id: icFA + source: "image://theme/icon-s-favorite?" + (!model.status_favourited ? Theme.highlightColor : Theme.primaryColor) + width: Theme.iconSizeExtraSmall + height: width anchors { leftMargin: Theme.horizontalPageMargin left: parent.left verticalCenter: parent.verticalCenter } - width: Theme.iconSizeExtraSmall - height: width - source: "image://theme/icon-s-favorite?" + (!model.favourited ? Theme.highlightColor : Theme.primaryColor) } Label { - text: status_favourites_count // from API.js + text: status_favourites_count font.pixelSize: Theme.fontSizeExtraSmall - color: !model.favourited ? Theme.highlightColor : Theme.primaryColor + color: !model.status_favourited ? Theme.highlightColor : Theme.primaryColor anchors { left: icFA.right leftMargin: Theme.paddingMedium @@ -385,6 +388,36 @@ BackgroundItem { } } + MenuItem { + id: mnuBookmark + visible: model.type !== "follow" + text: typeof model.status_bookmarked !== "undefined" && model.status_bookmarked ? qsTr("Remove Bookmark") : qsTr("Bookmark") + onClicked: { + var status = typeof model.status_bookmarked !== "undefined" && model.status_bookmarked + worker.sendMessage({ + "conf" : Logic.conf, + "params" : [], + "method" : "POST", + "bgAction": true, + "action" : "statuses/"+model.status_id+"/" + (status ? "unbookmark" : "bookmark") + }) + model.status_bookmarked = !model.status_bookmarked + } + + Icon { + source: "../../images/icon-s-bookmark.svg?" + color: !model.status_bookmarked ? Theme.highlightColor : Theme.primaryColor + width: Theme.iconSizeExtraSmall + height: width + anchors { + left: parent.left + leftMargin: Theme.horizontalPageMargin + Theme.paddingMedium + verticalCenter: parent.verticalCenter + } + } + } + + MenuItem { id: mnuMention visible: model.type === "follow" @@ -397,16 +430,16 @@ BackgroundItem { }) } - Image { + Icon { id: icMT + source: "image://theme/icon-s-chat?" + (!model.status_favourited ? Theme.highlightColor : Theme.primaryColor) + width: Theme.iconSizeExtraSmall + height: width anchors { - leftMargin: Theme.horizontalPageMargin + leftMargin: Theme.horizontalPageMargin + Theme.paddingMedium left: parent.left verticalCenter: parent.verticalCenter } - width: Theme.iconSizeExtraSmall - height: width - source: "image://theme/icon-s-chat?" + (!model.favourited ? Theme.highlightColor : Theme.primaryColor) } } } diff --git a/translations/harbour-tooter-de.ts b/translations/harbour-tooter-de.ts index c593d66..f41bab8 100644 --- a/translations/harbour-tooter-de.ts +++ b/translations/harbour-tooter-de.ts @@ -203,6 +203,10 @@ Follows you Folgt dir + + Group + Gruppe + ProfilePage @@ -384,5 +388,13 @@ Conversation Konversation + + Remove Bookmark + Lesezeichen entfernen + + + Bookmark + Lesezeichen + diff --git a/translations/harbour-tooter-el.ts b/translations/harbour-tooter-el.ts index ed641fd..7e70cd2 100644 --- a/translations/harbour-tooter-el.ts +++ b/translations/harbour-tooter-el.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-es.ts b/translations/harbour-tooter-es.ts index 27c26c2..d538f0d 100644 --- a/translations/harbour-tooter-es.ts +++ b/translations/harbour-tooter-es.ts @@ -62,11 +62,11 @@ Reply "Reply" will show the Toot text entry Panel. "Hide Reply" closes it. Alternative: Use "Close Reply" - + Respuesta Hide Reply - + Cerrar respuesta @@ -201,7 +201,11 @@ Follows you - + Te sigue + + + Group + Grupo @@ -234,7 +238,7 @@ Requested Is a button. Keep it as short as possible. - + Requerido Follow @@ -267,7 +271,7 @@ Mention - + Mencionar @@ -378,11 +382,19 @@ Mention - + Mencionar Conversation - + Conversación + + + Remove Bookmark + Eliminar marcador + + + Bookmark + Marcador diff --git a/translations/harbour-tooter-fr.ts b/translations/harbour-tooter-fr.ts index 500e6e0..6f2dcba 100644 --- a/translations/harbour-tooter-fr.ts +++ b/translations/harbour-tooter-fr.ts @@ -203,6 +203,10 @@ Follows you Vous suit + + Group + Groupe + ProfilePage @@ -384,5 +388,13 @@ Conversation Conversation + + Remove Bookmark + Retirer marque-page + + + Bookmark + Ajouter aux marque-pages + diff --git a/translations/harbour-tooter-it.ts b/translations/harbour-tooter-it.ts index bcd2957..2f3bd50 100644 --- a/translations/harbour-tooter-it.ts +++ b/translations/harbour-tooter-it.ts @@ -4,23 +4,23 @@ API - + favourited ha apprezzato - + followed you ha iniziato a seguirti - + boosted ha condiviso - + said ha detto @@ -28,59 +28,59 @@ ConversationPage - + Copy Link to Clipboard Use the translation of "Copy Link" for a shorter PullDownMenu label Copia link - + Reply "Reply" will show the Toot text entry Panel. "Hide Reply" closes it. Alternative: Use "Close Reply" Risposta - + Hide Reply Chiudere Risposta - + Write your warning here Contenuto avviso - + What's on your mind? A cosa stai pensando? - + Delete Elimina - + Public Pubblico - + Unlisted Non elencato - + Followers-only Solo ai seguaci - + Direct Diretto - + Toot sent! Toot è stato pubblicato! @@ -175,7 +175,7 @@ @utente o #termine - + New Toot Nuovo toot @@ -238,12 +238,17 @@ ProfileHeader - + + Group + Gruppo + + + Follows you Ti segue - + Bot Bot @@ -251,79 +256,79 @@ ProfilePage - + About If there's no good translation for "About", use "Details" (in details about profile). Dettagli - + Followers Will show as: "35 Followers" Seguaci - + Following Will show as: "23 Following" Segue - + Statuses Will show as: "115 Statuses" Toots - - + + Mention Menzionare - + Unfollow Is a button. Keep it as short as possible. Smetti di seguire - + Requested Is a button. Keep it as short as possible. Richiesto - + Follow Is a button. Keep it as short as possible. Segui - + Unmute Is a button. Keep it as short as possible. Non silenziare - + Mute Is a button. Keep it as short as possible. Silenzia - + Unblock Is a button. Keep it as short as possible. Sblocca - + Block Is a button. Keep it as short as possible. Blocca - + Open in Browser Aprire nel browser @@ -440,33 +445,43 @@ VisualContainer - + Unboost Annulla condivisione - + Boost Condividi - + Unfavorite Annulla apprezzamento - + Favorite Apprezzato - + Remove Bookmark + Elimina segnalibro + + + + Bookmark + Aggiungi segnalibro + + + + Mention Menzionare - + Conversation Conversazione diff --git a/translations/harbour-tooter-nl.ts b/translations/harbour-tooter-nl.ts index a3259b1..e24485a 100644 --- a/translations/harbour-tooter-nl.ts +++ b/translations/harbour-tooter-nl.ts @@ -29,11 +29,11 @@ Write your warning here - + Waarschuwingstekst What's on your mind? - + Wat wil je kwijt? Delete @@ -41,32 +41,32 @@ Public - + Openbaar Unlisted - + Minder openbaar Followers-only - + Alleen volgers Direct - + Direct Toot sent! - + Toot verzonden! Reply "Reply" will show the Toot text entry Panel. "Hide Reply" closes it. Alternative: Use "Close Reply" - + Antwoord Hide Reply - + Antwoord verbergen @@ -106,7 +106,7 @@ Enter a valid Mastodon instance URL - + Geldig Mastodon URL Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust — whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly. @@ -201,7 +201,11 @@ Follows you - + Volgt jou + + + Group + Groep @@ -267,7 +271,7 @@ Mention - Vermelden + Vermelden @@ -382,7 +386,15 @@ Conversation - + Conversatie + + + Remove Bookmark + Bookmarken + + + Bookmark + Bladwijzer verwijderen diff --git a/translations/harbour-tooter-nl_BE.ts b/translations/harbour-tooter-nl_BE.ts index 52517c9..9c9ccf0 100644 --- a/translations/harbour-tooter-nl_BE.ts +++ b/translations/harbour-tooter-nl_BE.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-oc.ts b/translations/harbour-tooter-oc.ts index 69ca0d0..70c903b 100644 --- a/translations/harbour-tooter-oc.ts +++ b/translations/harbour-tooter-oc.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-pl.ts b/translations/harbour-tooter-pl.ts index fedaf9c..9a2caba 100644 --- a/translations/harbour-tooter-pl.ts +++ b/translations/harbour-tooter-pl.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-ru.ts b/translations/harbour-tooter-ru.ts index 9171ede..105378a 100644 --- a/translations/harbour-tooter-ru.ts +++ b/translations/harbour-tooter-ru.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-sr.ts b/translations/harbour-tooter-sr.ts index d80e7d8..aab50f1 100644 --- a/translations/harbour-tooter-sr.ts +++ b/translations/harbour-tooter-sr.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-sv.ts b/translations/harbour-tooter-sv.ts index d99d520..67ea6cf 100644 --- a/translations/harbour-tooter-sv.ts +++ b/translations/harbour-tooter-sv.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter-zh_CN.ts b/translations/harbour-tooter-zh_CN.ts index 5d18598..a00b9e4 100644 --- a/translations/harbour-tooter-zh_CN.ts +++ b/translations/harbour-tooter-zh_CN.ts @@ -203,6 +203,10 @@ Follows you + + Group + + ProfilePage @@ -384,5 +388,13 @@ Conversation + + Remove Bookmark + + + + Bookmark + + diff --git a/translations/harbour-tooter.ts b/translations/harbour-tooter.ts index 8005ce9..e3b0909 100644 --- a/translations/harbour-tooter.ts +++ b/translations/harbour-tooter.ts @@ -62,11 +62,11 @@ Reply "Reply" will show the Toot text entry Panel. "Hide Reply" closes it. Alternative: Use "Close Reply" - + Reply Hide Reply - + Hide Reply @@ -201,7 +201,11 @@ Follows you - + Follows you + + + Group + Group @@ -382,7 +386,15 @@ Conversation - + Conversation + + + Remove Bookmark + Remove Bookmark + + + Bookmark + Bookmark