diff --git a/README.md b/README.md index b082a92..4ed9ad9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A Telegram client for Sailfish OS ## Author -Sebastian J. Wolf [sebastian@ygriega.de](mailto:sebastian@ygriega.de) +Sebastian J. Wolf [sebastian@ygriega.de](mailto:sebastian@ygriega.de) and several contributors ## Contributions @@ -10,7 +10,7 @@ Fernschreiber wouldn't be the same without all the people helping in making it b ### Code (Features, Bugfixes, Optimizations etc.) - Chat list model, TDLib receiver, project dependencies: [Slava Monich](https://github.com/monich) -- Location support, app initialization/registration with Telegram, project dependencies: [jgibbon](https://github.com/jgibbon) +- Chat info page, location support, app initialization/registration with Telegram, project dependencies: [jgibbon](https://github.com/jgibbon) ### Logo/Icon - Designed by [Matteo](https://github.com/iamnomeutente) diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 75db4e6..5bc9469 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -34,13 +34,27 @@ SOURCES += src/harbour-fernschreiber.cpp \ DISTFILES += qml/harbour-fernschreiber.qml \ qml/components/AudioPreview.qml \ + qml/components/ChatListViewItem.qml \ qml/components/DocumentPreview.qml \ qml/components/ImagePreview.qml \ qml/components/InReplyToRow.qml \ qml/components/LocationPreview.qml \ qml/components/StickerPicker.qml \ + qml/components/PhotoTextsListItem.qml \ qml/components/WebPagePreview.qml \ + qml/components/chatInformationPage/ChatInformationEditArea.qml \ + qml/components/chatInformationPage/ChatInformationProfilePicture.qml \ + qml/components/chatInformationPage/ChatInformationProfilePictureList.qml \ + qml/components/chatInformationPage/ChatInformationTabItemBase.qml \ + qml/components/chatInformationPage/ChatInformationTabItemDebug.qml \ + qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml \ + qml/components/chatInformationPage/ChatInformationTabItemSettings.qml \ + qml/components/chatInformationPage/ChatInformationTabView.qml \ + qml/components/chatInformationPage/ChatInformationTextItem.qml \ + qml/components/chatInformationPage/EditGroupChatPermissionsColumn.qml \ + qml/components/chatInformationPage/EditSuperGroupSlowModeColumn.qml \ qml/js/functions.js \ + qml/pages/ChatInformationPage.qml \ qml/pages/ChatPage.qml \ qml/pages/CoverPage.qml \ qml/pages/InitializationPage.qml \ @@ -63,6 +77,7 @@ TRANSLATIONS += translations/harbour-fernschreiber-de.ts \ translations/harbour-fernschreiber-it.ts \ translations/harbour-fernschreiber-pl.ts \ translations/harbour-fernschreiber-ru.ts \ + translations/harbour-fernschreiber-sv.ts \ translations/harbour-fernschreiber-zh_CN.ts contains(QT_ARCH, arm) { diff --git a/images/icon-m-sticker.png b/images/icon-m-sticker.png index c9343a1..189dab3 100644 Binary files a/images/icon-m-sticker.png and b/images/icon-m-sticker.png differ diff --git a/qml/components/AppNotification.qml b/qml/components/AppNotification.qml index eca2c97..5ba5fff 100644 --- a/qml/components/AppNotification.qml +++ b/qml/components/AppNotification.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/AppNotificationItem.qml b/qml/components/AppNotificationItem.qml index 63ec600..42aa3a8 100644 --- a/qml/components/AppNotificationItem.qml +++ b/qml/components/AppNotificationItem.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/AudioPreview.qml b/qml/components/AudioPreview.qml index 7184008..831a17c 100644 --- a/qml/components/AudioPreview.qml +++ b/qml/components/AudioPreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/BackgroundProgressIndicator.qml b/qml/components/BackgroundProgressIndicator.qml index a6c8dbe..bedb440 100644 --- a/qml/components/BackgroundProgressIndicator.qml +++ b/qml/components/BackgroundProgressIndicator.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml new file mode 100644 index 0000000..2c8bc2c --- /dev/null +++ b/qml/components/ChatListViewItem.qml @@ -0,0 +1,62 @@ +import QtQuick 2.5 +import Sailfish.Silica 1.0 + +import "../js/twemoji.js" as Emoji +import "../js/functions.js" as Functions + +PhotoTextsListItem { + id: listItem + pictureThumbnail { +// forceElementUpdate: overviewPage.chatListCreated + photoData: photo_small +// replacementStringHint: primaryText.text + } + property int ownUserId + + // chat title + primaryText.text: title ? Emoji.emojify(title, Theme.fontSizeMedium) + ( display.notification_settings.mute_for > 0 ? Emoji.emojify(" 🔇", Theme.fontSizeMedium) : "" ) : qsTr("Unknown") + // last user + prologSecondaryText.text: is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), primaryText.font.pixelSize) : qsTr("You") ) : qsTr("Unknown") ) + // last message + secondaryText.text: last_message_text ? Emoji.emojify(last_message_text, Theme.fontSizeExtraSmall) : qsTr("Unknown") + // message date + tertiaryText.text: last_message_date ? Functions.getDateTimeElapsed(last_message_date) : qsTr("Unknown") + unreadCount: unread_count + + openMenuOnPressAndHold: true//chat_id != overviewPage.ownUserId + menu: ContextMenu { + MenuItem { + visible: unread_count > 0 + onClicked: { + tdLibWrapper.viewMessage(chat_id, display.last_message.id, true); + } + text: qsTr("Mark all messages as read") + } + + MenuItem { + visible: chat_id != listItem.ownUserId + onClicked: { + var newNotificationSettings = display.notification_settings; + if (newNotificationSettings.mute_for > 0) { + newNotificationSettings.mute_for = 0; + } else { + newNotificationSettings.mute_for = 6666666; + } + tdLibWrapper.setChatNotificationSettings(chat_id, newNotificationSettings); + } + text: display.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") + } + + MenuItem { + onClicked: { + if(pageStack.depth > 2) { + pageStack.pop(pageStack.find( function(page){ return(page._depth === 0)} ), PageStackAction.Immediate); + } + + pageStack.push(Qt.resolvedUrl("../pages/ChatInformationPage.qml"), { "chatInformation" : display}); + } + text: model.display.type['@type'] === "chatTypePrivate" ? qsTr("User Info") : qsTr("Group Info") + } + } + +} diff --git a/qml/components/DocumentPreview.qml b/qml/components/DocumentPreview.qml index e0d566e..9f46a09 100644 --- a/qml/components/DocumentPreview.qml +++ b/qml/components/DocumentPreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/ImagePreview.qml b/qml/components/ImagePreview.qml index affd45c..395629c 100644 --- a/qml/components/ImagePreview.qml +++ b/qml/components/ImagePreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/InReplyToRow.qml b/qml/components/InReplyToRow.qml index 20f27d5..e610775 100644 --- a/qml/components/InReplyToRow.qml +++ b/qml/components/InReplyToRow.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/LocationPreview.qml b/qml/components/LocationPreview.qml index bb83ab5..b160072 100644 --- a/qml/components/LocationPreview.qml +++ b/qml/components/LocationPreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/PhotoTextsListItem.qml b/qml/components/PhotoTextsListItem.qml new file mode 100644 index 0000000..e2ae4da --- /dev/null +++ b/qml/components/PhotoTextsListItem.qml @@ -0,0 +1,153 @@ +import QtQuick 2.5 +import Sailfish.Silica 1.0 +ListItem { + + id: chatListViewItem + + property alias primaryText: primaryText //usually chat name + property alias prologSecondaryText: prologSecondaryText //usually last sender name + property alias secondaryText: secondaryText //usually last message + property alias tertiaryText: tertiaryText //usually last message date + + property int unreadCount + property alias pictureThumbnail: pictureThumbnail + + contentHeight: mainRow.height + separator.height + 2 * Theme.paddingMedium + contentWidth: parent.width + + + + Column { + id: mainColumn + width: parent.width - ( 2 * Theme.horizontalPageMargin ) + spacing: Theme.paddingSmall + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + Row { + id: mainRow + width: parent.width + height: contentColumn.height + spacing: Theme.paddingMedium + + Column { + id: pictureColumn + width: contentColumn.height - Theme.paddingSmall + height: contentColumn.height - Theme.paddingSmall + anchors.verticalCenter: parent.verticalCenter + + Item { + id: chatListPictureItem + width: parent.width + height: parent.width + + ProfileThumbnail { + id: pictureThumbnail + replacementStringHint: primaryText.text + width: parent.width + height: parent.width + } + + Rectangle { + id: chatUnreadMessagesCountBackground + color: Theme.highlightBackgroundColor + width: Theme.fontSizeLarge + height: Theme.fontSizeLarge + anchors.right: parent.right + anchors.bottom: parent.bottom + radius: parent.width / 2 + visible: chatListViewItem.unreadCount > 0 + } + + Text { + id: chatUnreadMessagesCount + font.pixelSize: Theme.fontSizeExtraSmall + font.bold: true + color: Theme.primaryColor + anchors.centerIn: chatUnreadMessagesCountBackground + visible: chatUnreadMessagesCountBackground.visible + text: chatListViewItem.unreadCount > 99 ? "99+" : chatListViewItem.unreadCount + } + } + } + + Column { + id: contentColumn + width: parent.width * 5 / 6 - Theme.horizontalPageMargin + spacing: Theme.paddingSmall + + Text { + id: primaryText + textFormat: Text.StyledText + font.pixelSize: Theme.fontSizeMedium + color: Theme.primaryColor + elide: Text.ElideRight + width: parent.width + onTruncatedChanged: { + // There is obviously a bug in QML in truncating text with images. + // We simply remove Emojis then... + if (truncated) { + text = text.replace(/\]+\/\>/g, ""); + } + } + } + + Row { + id: additionalTextRow + width: parent.width + spacing: Theme.paddingSmall + Text { + id: prologSecondaryText + font.pixelSize: Theme.fontSizeExtraSmall + color: Theme.highlightColor + textFormat: Text.StyledText + onTruncatedChanged: { + // There is obviously a bug in QML in truncating text with images. + // We simply remove Emojis then... + if (truncated) { + text = text.replace(/\]+\/\>/g, ""); + } + } + } + Text { + id: secondaryText + font.pixelSize: Theme.fontSizeExtraSmall + color: Theme.primaryColor + width: parent.width - Theme.paddingMedium - prologSecondaryText.width + elide: Text.ElideRight + textFormat: Text.StyledText + onTruncatedChanged: { + // There is obviously a bug in QML in truncating text with images. + // We simply remove Emojis then... + if (truncated) { + text = text.replace(/\]+\/\>/g, ""); + } + } + } + } + + Text { + id: tertiaryText + width: parent.width + font.pixelSize: Theme.fontSizeTiny + color: Theme.secondaryColor + } + } + } + } + + Separator { + id: separator + anchors { + top: mainColumn.bottom + topMargin: Theme.paddingMedium + } + + width: parent.width + color: Theme.primaryColor + horizontalAlignment: Qt.AlignHCenter + } + +} diff --git a/qml/components/ProfileThumbnail.qml b/qml/components/ProfileThumbnail.qml index c22f194..9dafd91 100644 --- a/qml/components/ProfileThumbnail.qml +++ b/qml/components/ProfileThumbnail.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -27,6 +27,8 @@ Item { property variant photoData; property string replacementStringHint: "X" property bool forceElementUpdate: false + property int radius: width / 2 + property int imageStatus: -1 function getReplacementString() { if (replacementStringHint.length > 2) { @@ -109,6 +111,9 @@ Item { autoTransform: true asynchronous: true visible: false + onStatusChanged: { + profileThumbnail.imageStatus = status + } } Rectangle { @@ -116,7 +121,7 @@ Item { width: parent.width - Theme.paddingSmall height: parent.height - Theme.paddingSmall color: Theme.primaryColor - radius: parent.width / 2 + radius: profileThumbnail.radius anchors.centerIn: singleImage visible: false } diff --git a/qml/components/StickerPicker.qml b/qml/components/StickerPicker.qml index 3ff4704..8173bfe 100644 --- a/qml/components/StickerPicker.qml +++ b/qml/components/StickerPicker.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/StickerPreview.qml b/qml/components/StickerPreview.qml index 1a3a991..af22328 100644 --- a/qml/components/StickerPreview.qml +++ b/qml/components/StickerPreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/VideoPreview.qml b/qml/components/VideoPreview.qml index b7a4d2a..458550c 100644 --- a/qml/components/VideoPreview.qml +++ b/qml/components/VideoPreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/WebPagePreview.qml b/qml/components/WebPagePreview.qml index 4b8fb83..260fb61 100644 --- a/qml/components/WebPagePreview.qml +++ b/qml/components/WebPagePreview.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/components/chatInformationPage/ChatInformationEditArea.qml b/qml/components/chatInformationPage/ChatInformationEditArea.qml new file mode 100644 index 0000000..667ebb4 --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationEditArea.qml @@ -0,0 +1,102 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +Column { + id: editAreaColumn + visible: canEdit || text !== "" + property bool canEdit + property alias headerText: editAreaHeader.text + property string emptyPlaceholderText + property string text + property bool multiLine + + property bool isEditing + property Item editItem: multiLine ? editAreaTextArea : editAreaTextField + + signal saveButtonClicked(string textValue) + signal editButtonClicked() + signal textEdited(string textValue) + width: parent.width + + + SectionHeader { + id: editAreaHeader + font.pixelSize: Theme.fontSizeExtraSmall + height: parent.visible && text !== "" ? Theme.itemSizeExtraSmall : 0 + x: 0 + } + Row { + id: editAreaTextRow + width: parent.width + + TextArea { + id: editAreaTextArea + visible: editAreaColumn.isEditing && editAreaColumn.multiLine + width: parent.width - editAreaButton.width + anchors.verticalCenter: parent.verticalCenter + } + TextField { + id: editAreaTextField + visible: editAreaColumn.isEditing && !editAreaColumn.multiLine + width: parent.width - editAreaButton.width + anchors.verticalCenter: parent.verticalCenter + EnterKey.onClicked: { + editAreaColumn.isEditing = false; + editAreaColumn.saveButtonClicked(editAreaColumn.editItem.text); + } + EnterKey.iconSource: editAreaButton.icon.source + } + ChatInformationTextItem { + id: editAreaTextItem + visible: !editAreaColumn.isEditing + anchors.verticalCenter: parent.verticalCenter + text: editAreaColumn.text || editAreaColumn.emptyPlaceholderText + width: parent.width - editAreaButton.width + } + IconButton { + id: editAreaButton + visible: editAreaColumn.canEdit + width: visible ? Theme.itemSizeSmall : 0 + icon.source: editAreaColumn.isEditing ? "image://theme/icon-m-accept" : "image://theme/icon-m-edit" + anchors.verticalCenter: parent.verticalCenter + onClicked: { + if(editAreaColumn.isEditing) { + editAreaColumn.isEditing = false; + editAreaColumn.saveButtonClicked(editAreaColumn.editItem.text); + } else { + editAreaColumn.isEditing = true; + editAreaColumn.editItem.text = editAreaColumn.text; + editAreaColumn.editItem.forceActiveFocus(); + editAreaColumn.editItem.cursorPosition = editAreaColumn.editItem.text.length; + editAreaColumn.editButtonClicked(); + } + } + } + } + Connections { + target: editItem + onTextChanged: { + if(editItem.focus) { + editAreaColumn.textEdited(editItem.text) + } + } + } +} diff --git a/qml/components/chatInformationPage/ChatInformationProfilePicture.qml b/qml/components/chatInformationPage/ChatInformationProfilePicture.qml new file mode 100644 index 0000000..2c7fff8 --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationProfilePicture.qml @@ -0,0 +1,44 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "../" + +Item { + visible: imageContainer.tweenFactor > 0.8 && chatPictureDetail.imageStatus === Image.Ready + property bool isActive: imageContainer.tweenFactor === 1.0 + opacity: isActive ? 1.0 : 0.0 + Behavior on opacity { NumberAnimation {} } + ProfileThumbnail { + id: chatPictureDetail + anchors.fill: parent + photoData: (typeof chatInformation.photo !== "undefined") ? chatInformation.photo.big : "" + replacementStringHint: "" + radius: chatPictureThumbnail.radius + } + + MouseArea { + anchors.fill: parent + onClicked: { + var preparedPhotoData = {sizes:[{width:640,height: 640,photo:chatPictureDetail.photoData}]}; + pageStack.push(Qt.resolvedUrl("../../pages/ImagePage.qml"), { "photoData" : preparedPhotoData }); + } + } +} diff --git a/qml/components/chatInformationPage/ChatInformationProfilePictureList.qml b/qml/components/chatInformationPage/ChatInformationProfilePictureList.qml new file mode 100644 index 0000000..8cbc677 --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationProfilePictureList.qml @@ -0,0 +1,73 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "../" + +Item { + visible: imageContainer.tweenFactor > 0.8 && bigProfilePictureList.count > 0 + property bool isActive: imageContainer.tweenFactor === 1.0 + + opacity: isActive ? 1.0 : 0.0 + Behavior on opacity { NumberAnimation {} } + + SlideshowView { + id: bigProfilePictureList + property bool isActive: imageContainer.tweenFactor === 1.0 + width: parent.width + height: parent.height + clip: true + itemWidth: width + itemHeight: height + interactive: parent.isActive + model: chatInformationPage.chatPartnerProfilePhotos + delegate: Item { + width: bigProfilePictureList.itemWidth + height: bigProfilePictureList.itemHeight + ProfileThumbnail { + id: chatPictureDetail + photoData: modelData.sizes[modelData.sizes.length - 1].photo + replacementStringHint: "" + radius: chatPictureThumbnail.radius + anchors.fill: parent + } + MouseArea { + anchors.fill: parent + onClicked: { + pageStack.push(Qt.resolvedUrl("../../pages/ImagePage.qml"), { "photoData" : modelData }); + } + } + } + } + + Text { + visible: bigProfilePictureList.count > 1 + width: parent.width + anchors { + bottomMargin: Theme.paddingSmall + bottom: parent.bottom + } + horizontalAlignment: Text.AlignHCenter + property var baseString: new Array(bigProfilePictureList.count+1).join(" ○ ") + text: baseString.substring(0,bigProfilePictureList.currentIndex*3) + " ● " + baseString.substring((bigProfilePictureList.currentIndex+1)*3) + color: Theme.primaryColor + style: Text.Raised + styleColor: Theme.highlightDimmerColor + } +} diff --git a/qml/components/chatInformationPage/ChatInformationTabItemBase.qml b/qml/components/chatInformationPage/ChatInformationTabItemBase.qml new file mode 100644 index 0000000..a3472c4 --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationTabItemBase.qml @@ -0,0 +1,74 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "../../pages" +import "../" + +Item { + id: tabItem + property string title + property url image + property bool loading + //overrideable: + property alias loadingVisible: loadingColumn.loadingVisible + property string loadingText + + property int tabIndex: tabItem.VisualItemModel.index + property bool active: tabItem.ListView.isCurrentItem + + default property alias _data: contentItem.data + + + width: parent.width + height: tabView.maxHeight//Math.max(contentItem.height, loadingColumn.height) + opacity: active ? 1.0 : 0.0 + Behavior on opacity { PropertyAnimation {duration: 300}} + + Column { + id: loadingColumn + property bool loadingVisible: tabItem.loading + width: tabItem.width + height: loadingLabel.height + loadingBusyIndicator.height + Theme.paddingMedium + spacing: Theme.paddingMedium + topPadding: Theme.paddingLarge + anchors.top: parent.top + opacity: loadingVisible ? 1.0 : 0.0 + Behavior on opacity { NumberAnimation {} } + visible: tabItem.loading + + InfoLabel { + id: loadingLabel + text: tabItem.loadingText + } + + BusyIndicator { + id: loadingBusyIndicator + anchors.horizontalCenter: parent.horizontalCenter + running: parent.loadingVisible + size: BusyIndicatorSize.Large + } + } + Item { + id: contentItem + width: parent.width + height: childrenRect.height + } + +} diff --git a/qml/components/chatInformationPage/ChatInformationTabItemDebug.qml b/qml/components/chatInformationPage/ChatInformationTabItemDebug.qml new file mode 100644 index 0000000..6696c1c --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationTabItemDebug.qml @@ -0,0 +1,59 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import QtQml.Models 2.3 + +import "../" +import "../../pages" +import "../../js/twemoji.js" as Emoji +import "../../js/functions.js" as Functions + +ChatInformationTabItemBase { + id: tabBase + title: "debug" + image: "image://theme/icon-m-diagnostic" + SilicaFlickable { + height: tabBase.height + width: tabBase.width + contentHeight: contentColumn.height + Column { + id: contentColumn + width: tabBase.width - Theme.horizontalPageMargin * 2 + x: Theme.horizontalPageMargin + + ChatInformationTextItem { + headerText: "chatInformation" + text:chatInformationPage.chatInformation ? JSON.stringify(chatInformationPage.chatInformation, null, 2) : "" + isLinkedLabel: true + } + ChatInformationTextItem { + headerText: "groupInformation" + text: chatInformationPage.groupInformation ? JSON.stringify(chatInformationPage.groupInformation, null, 2) : "" + isLinkedLabel: true + } + + ChatInformationTextItem { + headerText: "groupFullInformation" + text: chatInformationPage.groupFullInformation ? JSON.stringify(chatInformationPage.groupFullInformation, null, 2) : "" + isLinkedLabel: true + } + } + } +} diff --git a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml new file mode 100644 index 0000000..7077a61 --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml @@ -0,0 +1,234 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import QtQml.Models 2.3 + +import "../" +import "../../pages" +import "../../js/twemoji.js" as Emoji +import "../../js/functions.js" as Functions + +ChatInformationTabItemBase { + id: tabBase + title: chatInformationPage.isPrivateChat ? qsTr("Groups", "Button: groups in common (short)") : qsTr("Members", "Button: Group Members") + image: "image://theme/icon-m-people" + loadingText: isPrivateChat ? qsTr("Loading common chats…", "chats you have in common with a user") : qsTr("Loading group members…") + loading: chatInformationPage.isSuperGroup || chatInformationPage.isPrivateChat + loadingVisible: loading && membersView.count === 0 + + property variant chatPartnerCommonGroupsIds: ([]); + + + SilicaListView { + id: membersView + model: isPrivateChat ? (chatPartnerCommonGroupsIds.length > 0 ? delegateModel : null) : chatInformationPage.membersList + clip: true + height: tabBase.height + width: tabBase.width + opacity: tabBase.loading ? (count > 0 ? 0.5 : 0.0) : 1.0 + Behavior on opacity { NumberAnimation {} } + function handleScrollIntoView(force){ + if(!tabBase.loading && !dragging && !quickScrollAnimating ) { + if(!atYBeginning) { + chatInformationPage.scrollDown() + } else { + chatInformationPage.scrollUp(force); + } + } + } + onDraggingChanged: { + handleScrollIntoView() + } + onAtYBeginningChanged: { + handleScrollIntoView() + } + onAtYEndChanged: { + if(tabBase.active && !tabBase.loading && chatInformationPage.isSuperGroup && (groupInformation.member_count > membersView.count) && membersView.atYEnd) { + tabBase.loading = true; + fetchMoreMembersTimer.start() + } + } + onQuickScrollAnimatingChanged: { + handleScrollIntoView(true) + } + ViewPlaceholder { + enabled: membersView.count === 0 + text: chatInformationPage.isPrivateChat ? qsTr("You don't have any groups in common with this user.") : qsTr("This group is empty.") + } + delegate: PhotoTextsListItem { + pictureThumbnail { + photoData: (typeof user.profile_photo !== "undefined") ? user.profile_photo.small : "" + } + width: parent.width + + // chat title isPrivateChat ? () : + primaryText.text: Emoji.emojify(Functions.getUserName(user), primaryText.font.pixelSize) + // last user + prologSecondaryText.text: "@"+(user.username !== "" ? user.username : user_id) + (user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "") + secondaryText { + horizontalAlignment: Text.AlignRight + property string statusText: Functions.getChatMemberStatusText(model.status["@type"]) + property string customText: model.status.custom_title ? Emoji.emojify(model.status.custom_title, secondaryText.font.pixelSize) : "" + text: (statusText !== "" && customText !== "") ? statusText + ", " + customText : statusText + customText + } + tertiaryText { + maximumLineCount: 1 + text: user.type["@type"] === "userTypeBot" ? (Emoji.emojify("🤖 "+bot_info.description, tertiaryText.font.pixelSize)) : Functions.getChatPartnerStatusText(user.status["@type"], user.status.was_online); + elide: Text.ElideRight + } + + onClicked: { + tdLibWrapper.createPrivateChat(user_id); + } + } + footer: Component { + Item { + property bool active: tabBase.active && chatInformationPage.isSuperGroup && (groupInformation.member_count > membersView.count) + width: tabBase.width + height: active ? Theme.itemSizeLarge : Theme.paddingMedium + + BusyIndicator { + id: loadMoreIndicator + anchors.centerIn: parent + size: BusyIndicatorSize.Small + running: parent.active + } + } + } + + VerticalScrollDecorator {} + } + + + DelegateModel { + id: delegateModel + model: chatListModel + groups: [ + DelegateModelGroup { + name: "filterGroup"; includeByDefault: true + } + ] + filterOnGroup: "filterGroup" + function hasMatch(searchInArray) { + for (var i = 0; i < searchInArray.length; i++) { + if(searchInArray[i].toLowerCase().indexOf(chatInformationPage.searchString) > -1) { + return true; + } + } + return false; + } + + function applyFilter(){ + var numberOfEntries = chatListModel.rowCount(); + var hasFilterString = !!chatInformationPage.searchString && chatInformationPage.searchString !== "" + for (var i = 0; i < numberOfEntries; i++){ + var metadata = chatListModel.get(i); + if(tabBase.chatPartnerCommonGroupsIds.indexOf(metadata.chat_id) > -1) { + items.addGroups(i, 1, "filterGroup"); + } else { + items.removeGroups(i, 1, "filterGroup"); + } + + } + } + + delegate: ChatListViewItem { + ownUserId: chatInformationPage.myUserId + + unreadCount: unread_count + onClicked: { + pageStack.pop(pageStack.find( function(page){ return(page._depth === 0)} ), PageStackAction.Immediate); + pageStack.push(Qt.resolvedUrl("../../pages/ChatPage.qml"), { "chatInformation" : display }); + } + Connections { + target: chatListModel + onChatChanged: { + if (changedChatId === chat_id) { + // Force update of some list item elements (currently only last message text seems to create problems). dataChanged() doesn't seem to trigger them all :( + secondaryText.text = last_message_text ? Emoji.emojify(last_message_text, Theme.fontSizeExtraSmall) : qsTr("Unknown") + } + } + } + } + } + + Timer { + id: fetchMoreMembersTimer + interval: 600 + property int fetchLimit: 50 + onTriggered: { + if(isSuperGroup) { + tabBase.loading = true + tdLibWrapper.getSupergroupMembers(chatInformationPage.chatPartnerGroupId, fetchLimit, membersList.count); + fetchLimit = 200 + interval = 400 + } + } + } + + Connections { + target: tdLibWrapper + + onChatMembersReceived: { + if (isSuperGroup && chatInformationPage.chatPartnerGroupId === extra) { + if(members && members.length > 0) { + for(var memberIndex in members) { + var memberData = members[memberIndex]; + var userInfo = tdLibWrapper.getUserInformation(memberData.user_id) || {user:{}, bot_info:{}}; + memberData.user = userInfo; + memberData.bot_info = memberData.bot_info || {}; + membersList.append(memberData); + } + groupInformation.member_count = totalMembers + updateGroupStatusText(); + if(membersList.count < totalMembers) { +// fetchMoreMembersTimer.start() + } + } + // if we set it directly, the views start scrolling + loadedTimer.start(); + } + } + onChatsReceived: {// common chats with user + if(isPrivateChat && chats["@extra"] === chatInformationPage.chatPartnerGroupId) { + tabBase.chatPartnerCommonGroupsIds = chats.chat_ids; + delegateModel.applyFilter(); + // if we set it directly, the views start scrolling + loadedTimer.start(); + } + } + } + Timer { + id: loadedTimer + interval: 50 + onTriggered: { + tabBase.loading = false + } + } + + Component.onCompleted: { + if(isPrivateChat) { + tdLibWrapper.getGroupsInCommon(chatInformationPage.chatPartnerGroupId, 200, 0); // we only use the first 200 + } else if(isSuperGroup) { + fetchMoreMembersTimer.start(); + } + } + +} diff --git a/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml b/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml new file mode 100644 index 0000000..9b189ba --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml @@ -0,0 +1,70 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import QtQml.Models 2.3 + +import "../" +import "../../pages" +import "../../js/twemoji.js" as Emoji +import "../../js/functions.js" as Functions + +ChatInformationTabItemBase { + id: tabBase + title: qsTr("Settings", "Button: Chat Settings") + image: "image://theme/icon-m-developer-mode" + + SilicaFlickable { + height: tabBase.height + width: tabBase.width + contentHeight: contentColumn.height + Column { + id: contentColumn + width: tabBase.width + + //permissions + + // if chatInformationPage.chatInformation.permissions.can_change_info + // - upload/change chat photo/VIDEO (hahaha) + // - description change + // - toggleSupergroupIsAllHistoryAvailable + // if ?????? can_promote_members ???? can_restrict_members + // - setChatMemberStatus + // if creator (BasicGroup) + // - upgradeBasicGroupChatToSupergroupChat + // if creator (supergroup/channel) + // - canTransferOwnership? + // - transferChatOwnership + Loader { + active: (chatInformationPage.isBasicGroup || chatInformationPage.isSuperGroup) && chatInformationPage.groupInformation && (chatInformationPage.groupInformation.status.can_restrict_members || chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator") + asynchronous: true + source: "./EditGroupChatPermissionsColumn.qml" + width: parent.width + } + + Loader { + active: chatInformationPage.isSuperGroup && chatInformationPage.groupInformation && chatInformationPage.groupInformation.status.can_restrict_members || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator" + asynchronous: true + source: "./EditSuperGroupSlowModeColumn.qml" + width: parent.width + } + + } + } +} diff --git a/qml/components/chatInformationPage/ChatInformationTabView.qml b/qml/components/chatInformationPage/ChatInformationTabView.qml new file mode 100644 index 0000000..31b35e5 --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationTabView.qml @@ -0,0 +1,166 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +import "./" +import "../" +import "../../pages" + +Item { + id: tabViewItem + property alias count: tabView.count + height: Screen.width + opacity: count > 0 ? 1.0 : 0.0 + Behavior on height { PropertyAnimation {duration: 300}} + Behavior on opacity { PropertyAnimation {duration: 300}} + + Item { + id: tabViewHeader + /* + * Tab view was prepared for + * shared media/links/…, but for this + * we need message search with filters + */ + + height: visible ? headerGrid.height : 0 + clip: true + visible: tabView.count > 1 + + anchors { + left: parent.left + right: parent.right + top: parent.top + } + + Grid { + id: headerGrid + width: parent.width + columns: tabView.count + Repeater { + model: tabView.count + delegate: BackgroundItem { + id: headerItem + property bool loaded: tabItem.image !== "" && tabItem.title !== "" + width: loaded ? (headerGrid.width / tabView.count) : 0 + opacity: loaded ? 1.0 : 0.0 + + Behavior on width { PropertyAnimation {duration: 300}} + Behavior on opacity { PropertyAnimation {duration: 300}} + height: Theme.itemSizeLarge + property ChatInformationTabItemBase tabItem: tabView.model.get(index) + property int itemIndex: index + property bool itemIsActive: tabItem.active + Icon { + id: headerIcon + source: headerItem.tabItem.image + highlighted: headerItem.pressed || headerItem.itemIsActive + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + } + } + Label { + text: headerItem.tabItem.title + width: parent.width + horizontalAlignment: Text.AlignHCenter + anchors.top: headerIcon.bottom + highlighted: headerItem.pressed || headerItem.itemIsActive + font.pixelSize: Theme.fontSizeTiny + } + onClicked: { + chatInformationPage.scrollDown() + tabView.openTab(itemIndex) + } + } + } + } + } + + ListView { + id: tabView + orientation: ListView.Horizontal + clip: true + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.StrictlyEnforceRange + highlightFollowsCurrentItem: true + boundsBehavior: Flickable.StopAtBounds + currentIndex: 0 + highlightMoveDuration: 500 + property int maxHeight: tabViewItem.height - tabViewHeader.height + + + anchors { + top: tabViewHeader.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + + function openTab(index) { + currentIndex = index; + } + model: VisualItemModel { + id: tabModel + } + } + Component { + id: membersGroupComponent + ChatInformationTabItemMembersGroups{ + width: tabView.width + } + } + Component { + id: settingsComponent + ChatInformationTabItemSettings { + width: tabView.width + } + } + Component { + id: debugComponent + ChatInformationTabItemDebug { + width: tabView.width + } + } + property var tabItems: { + var items = []; + if(!(isPrivateChat && chatPartnerGroupId === myUserId.toString())) { + items.push(membersGroupComponent); + } + if(!isPrivateChat && (groupInformation.status.can_restrict_members || groupInformation.status["@type"] === "chatMemberStatusCreator")) { + items.push(settingsComponent); + } +// items.push(debugComponent); + + return items; + } + onTabItemsChanged: fillTabItems() + + function fillTabItems() { + tabModel.clear() + for(var i in tabItems) { + tabModel.append(tabItems[i].createObject(tabModel)); + } + } + + Component.onCompleted: { + fillTabItems() + } + +} diff --git a/qml/components/chatInformationPage/ChatInformationTextItem.qml b/qml/components/chatInformationPage/ChatInformationTextItem.qml new file mode 100644 index 0000000..4cffc6e --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationTextItem.qml @@ -0,0 +1,74 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +import "../../js/twemoji.js" as Emoji +import "../../js/functions.js" as Functions + +Column { + id: textItem + property alias headerText: headerItem.text + property string text + property bool isLinkedLabel // for telephone number + width: parent.width + visible: !!text + SectionHeader { + id: headerItem + visible: text !== "" && labelLoader.status === Loader.Ready && labelLoader.item.text !== "" + height: visible ? Theme.itemSizeSmall : 0 + x: 0 + } + Loader { + id: labelLoader + active: true + asynchronous: true + sourceComponent: textItem.isLinkedLabel ? linkedLabelComponent : labelComponent + width: textItem.width + } + + Component { + id: labelComponent + Label { + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + font.pixelSize: Theme.fontSizeExtraSmall + textFormat: Text.StyledText + color: Theme.highlightColor + text: Emoji.emojify( Functions.replaceUrlsWithLinks(textItem.text).replace(/\n/g, "
"), Theme.fontSizeExtraSmall).replace(/\.\.\/js/g, "../../js") + linkColor: Theme.primaryColor + visible: text !== "" + onLinkActivated: { + Functions.handleLink(link); + } + } + } + Component { + id: linkedLabelComponent + LinkedLabel { + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + font.pixelSize: Theme.fontSizeExtraSmall + textFormat: Text.StyledText + plainText: textItem.text + visible: textItem.text !== "" + onLinkActivated: { + Functions.handleLink(link); + } + } + } +} diff --git a/qml/components/chatInformationPage/EditGroupChatPermissionsColumn.qml b/qml/components/chatInformationPage/EditGroupChatPermissionsColumn.qml new file mode 100644 index 0000000..cd19fd1 --- /dev/null +++ b/qml/components/chatInformationPage/EditGroupChatPermissionsColumn.qml @@ -0,0 +1,148 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 + + +Column { + id: chatPermissionsColumn + + function setChatPermissions(textSwitchItem) { + if(textSwitchItem.busy) {return;} + var messageSubItems = ["can_send_media_messages", "can_send_polls", "can_send_other_messages", "can_add_web_page_previews"]; + var permissionName = textSwitchItem.permissionName; + var permissionValue = !textSwitchItem.checked + textSwitchItem.busy = true; + var newPermissions = chatInformationPage.chatInformation.permissions; + if(permissionName in newPermissions) { + newPermissions[permissionName] = permissionValue; + // some permissions infer can_send_messages: + if(permissionName === "can_send_messages" && !permissionValue) { + for(var i in messageSubItems) { + newPermissions[messageSubItems[i]] = false; + } + } else if(messageSubItems.indexOf(permissionName) > -1 && permissionValue) { + newPermissions.can_send_message = true; + } + } + tdLibWrapper.setChatPermissions(chatInformationPage.chatInformation.id, newPermissions); + } + + Column { + visible: chatInformationPage.groupInformation.status.can_restrict_members || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator" + width: parent.width + + SectionHeader { + text: qsTr("Group Member Permissions", "what can normal group members do") + } + TextSwitch { + automaticCheck: false + property string permissionName: "can_send_messages" + text: qsTr("Send Messages", "member permission") + checked: chatInformationPage.chatInformation.permissions[permissionName] + onCheckedChanged: {busy = false;} + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + TextSwitch { + automaticCheck: false + property string permissionName: "can_send_media_messages" + text: qsTr("Send Media Messages", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.chatInformation.permissions[permissionName] + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + + TextSwitch { + automaticCheck: false + property string permissionName: "can_send_other_messages" + text: qsTr("Send Other Messages", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.chatInformation.permissions[permissionName] + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + + TextSwitch { + automaticCheck: false + property string permissionName: "can_add_web_page_previews" + text: qsTr("Add Web Page Previews", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.chatInformation.permissions[permissionName] + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + + TextSwitch { + automaticCheck: false + property string permissionName: "can_change_info" + text: qsTr("Change Chat Info", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.chatInformation.permissions[permissionName] + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + + TextSwitch { + automaticCheck: false + property string permissionName: "can_invite_users" + text: qsTr("Invite Users", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.chatInformation.permissions[permissionName] + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + + TextSwitch { + automaticCheck: false + property string permissionName: "can_pin_messages" + text: qsTr("Pin Messages", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.chatInformation.permissions[permissionName] + onClicked: { + chatPermissionsColumn.setChatPermissions(this) + } + } + } + + SectionHeader { + visible: historyAvailableSwitch.visible + text: qsTr("New Members", "what can new group members do") + } + + + TextSwitch { + id: historyAvailableSwitch + visible: chatInformationPage.isSuperGroup && chatInformationPage.groupInformation.status && chatInformationPage.groupInformation.status.can_change_info + automaticCheck: false + text: qsTr("New members can see older messages", "member permission") + onCheckedChanged: {busy = false;} + checked: chatInformationPage.groupFullInformation.is_all_history_available + onClicked: { + tdLibWrapper.toggleSupergroupIsAllHistoryAvailable(chatInformationPage.chatPartnerGroupId, !checked); + } + } +} diff --git a/qml/components/chatInformationPage/EditSuperGroupSlowModeColumn.qml b/qml/components/chatInformationPage/EditSuperGroupSlowModeColumn.qml new file mode 100644 index 0000000..fb51291 --- /dev/null +++ b/qml/components/chatInformationPage/EditSuperGroupSlowModeColumn.qml @@ -0,0 +1,52 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber 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 3 of the License, or + (at your option) any later version. + + Fernschreiber 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 Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 + + +Column { + SectionHeader { + text: qsTr("Slow Mode") + } + + Slider { + width: parent.width + Theme.horizontalPageMargin * 2 + x: -Theme.horizontalPageMargin + property var presetValues: [0, 10, 30, 60, 300, 900, 3600] + property int realValue: chatInformationPage.groupFullInformation.slow_mode_delay + property int realValueIndex: presetValues.indexOf(realValue) > -1 ? presetValues.indexOf(realValue) : 0 + value: realValueIndex + minimumValue: 0 + maximumValue: presetValues.length - 1 + stepSize: 1 + valueText: value === 0 ? qsTr("Off") : Format.formatDuration(presetValues[value], presetValues[value] < 3600 ? Formatter.DurationShort : Formatter.DurationLong); + onPressedChanged: { + if(!pressed && value !== realValueIndex) { + tdLibWrapper.setChatSlowModeDelay(chatInformationPage.chatInformation.id, presetValues[value]); + } + } + } + Label { + text: qsTr("Set how long every chat member has to wait between Messages") + width: parent.width - Theme.horizontalPageMargin * 2 + x: Theme.horizontalPageMargin + font.pixelSize: Theme.fontSizeSmall + color: Theme.secondaryHighlightColor + } +} diff --git a/qml/harbour-fernschreiber.qml b/qml/harbour-fernschreiber.qml index 6c8d6e4..8c756cd 100644 --- a/qml/harbour-fernschreiber.qml +++ b/qml/harbour-fernschreiber.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/js/functions.js b/qml/js/functions.js index ccf66f0..771d836 100644 --- a/qml/js/functions.js +++ b/qml/js/functions.js @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -94,8 +94,46 @@ function getMessageText(message, simple, myself) { if (message.content['@type'] === 'messageChatDeleteMember') { return myself ? qsTr("left this chat", "myself") : qsTr("left this chat"); } + if (message.content['@type'] === 'messageChatChangeTitle') { + return myself ? qsTr("changed the chat title to %1", "myself").arg(message.content.title) : qsTr("changed the chat title to %1").arg(message.content.title); + } return qsTr("Unsupported message: %1").arg(message.content['@type'].substring(7)); } + +function getChatPartnerStatusText(statusType, was_online) { + switch(statusType) { + case "userStatusEmpty": + return qsTr("was never online"); + case "userStatusLastMonth": + return qsTr("offline, last online: last month"); + case "userStatusLastWeek": + return qsTr("offline, last online: last week"); + case "userStatusOffline": + return qsTr("offline, last online: %1").arg(getDateTimeElapsed(was_online)); + case "userStatusOnline": + return qsTr("online"); + case "userStatusRecently": + return qsTr("offline, was recently online"); + } +} +function getChatMemberStatusText(statusType) { +// chatMemberStatusAdministrator, chatMemberStatusBanned, chatMemberStatusCreator, chatMemberStatusLeft, chatMemberStatusMember, and chatMemberStatusRestricted. + switch(statusType) { + case "chatMemberStatusAdministrator": + return qsTr("Admin", "channel user role"); + case "chatMemberStatusBanned": + return qsTr("Banned", "channel user role"); + case "chatMemberStatusCreator": + return qsTr("Creator", "channel user role"); + case "chatMemberStatusRestricted": + return qsTr("Restricted", "channel user role"); + case "chatMemberStatusLeft": + case "chatMemberStatusMember": + return "" + } + return statusType || ""; +} + function getShortenedCount(count) { if (count >= 1000000) { return qsTr("%1M").arg((count / 1000000).toLocaleString(Qt.locale(), 'f', 0)); @@ -226,3 +264,6 @@ function getVideoHeight(videoWidth, videoData) { return 1; } } +function replaceUrlsWithLinks(string) { + return string.replace(/((\w+):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, "$1"); +} diff --git a/qml/pages/AboutPage.qml b/qml/pages/AboutPage.qml index 1dd253e..3d92a16 100644 --- a/qml/pages/AboutPage.qml +++ b/qml/pages/AboutPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -55,7 +55,7 @@ Page { } Label { - text: "Fernschreiber 0.3" + text: "Fernschreiber 0.4" horizontalAlignment: Text.AlignHCenter font.pixelSize: Theme.fontSizeExtraLarge anchors { diff --git a/qml/pages/ChatInformationPage.qml b/qml/pages/ChatInformationPage.qml new file mode 100644 index 0000000..79e3376 --- /dev/null +++ b/qml/pages/ChatInformationPage.qml @@ -0,0 +1,463 @@ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "../components" +import "../components/chatInformationPage" +import "../js/twemoji.js" as Emoji +import "../js/functions.js" as Functions + +Page { + id: chatInformationPage + + allowedOrientations: Orientation.All + property string searchString + + property int chatOnlineMemberCount: 0; + property int myUserId: tdLibWrapper.getUserInformation().id; + + property bool isPrivateChat: false + property bool isBasicGroup: false + property bool isSuperGroup: false + property bool isChannel: false + + property string chatPartnerGroupId + + property bool userIsMember: (isPrivateChat && chatInformation["@type"]) || // should be optimized + (isBasicGroup || isSuperGroup) && ( + (groupInformation.status["@type"] === "chatMemberStatusMember") + || (groupInformation.status["@type"] === "chatMemberStatusAdministrator") + || (groupInformation.status["@type"] === "chatMemberStatusRestricted" && groupInformation.status.is_member) + || (groupInformation.status["@type"] === "chatMemberStatusCreator" && groupInformation.status.is_member) + ) + + property variant chatInformation:({}); + property variant privateChatUserInformation:({}); + property variant chatPartnerFullInformation:({}); + property variant chatPartnerProfilePhotos:([]); + property variant groupInformation: ({}); + property variant groupFullInformation: ({}); + + property alias membersList: membersList + + function initializePage() { + console.log("[ChatInformationPage] Initializing chat info page..."); + membersList.clear(); + var chatType = chatInformation.type["@type"]; + switch(chatType) { + case "chatTypePrivate": + isPrivateChat = true; + chatInformationPage.chatPartnerGroupId = chatInformation.type.user_id.toString(); + if(!privateChatUserInformation.id) { + privateChatUserInformation = tdLibWrapper.getUserInformation(chatInformationPage.chatPartnerGroupId); + } + tdLibWrapper.getUserFullInfo(chatInformationPage.chatPartnerGroupId); + tdLibWrapper.getUserProfilePhotos(chatInformationPage.chatPartnerGroupId, 100, 0); + break; + case "chatTypeBasicGroup": + isBasicGroup = true; + chatInformationPage.chatPartnerGroupId = chatInformation.type.basic_group_id.toString(); + if(!groupInformation.id) { + groupInformation = tdLibWrapper.getBasicGroup(chatInformationPage.chatPartnerGroupId); + } + tdLibWrapper.getGroupFullInfo(chatInformationPage.chatPartnerGroupId, false); + break; + case "chatTypeSupergroup": + isSuperGroup = true; + chatInformationPage.chatPartnerGroupId = chatInformation.type.supergroup_id.toString(); + if(!groupInformation.id) { + groupInformation = tdLibWrapper.getSuperGroup(chatInformationPage.chatPartnerGroupId); + } + + tdLibWrapper.getGroupFullInfo(chatInformationPage.chatPartnerGroupId, true); + isChannel = groupInformation.is_channel; + break; + } + if(!isPrivateChat) { + updateGroupStatusText(); + } + } + function scrollUp(force) { + if(force) { + // animation does not always work while quick scrolling + scrollUpTimer.start() + } else { + scrollUpAnimation.start() + } + } + function scrollDown(force) { + if(force) { + scrollDownTimer.start() + } else { + scrollDownAnimation.start() + } + } + function handleBasicGroupFullInfo(groupFullInfo) { + groupFullInformation = groupFullInfo; + membersList.clear(); + if(groupFullInfo.members && groupFullInfo.members.length > 0) { + for(var memberIndex in groupFullInfo.members) { + var memberData = groupFullInfo.members[memberIndex]; + var userInfo = tdLibWrapper.getUserInformation(memberData.user_id) || {user:{}, bot_info:{}}; + memberData.user = userInfo; + memberData.bot_info = memberData.bot_info || {}; + membersList.append(memberData); + } + groupInformation.member_count = groupFullInfo.members.length + updateGroupStatusText(); + } + } + + Connections { + target: tdLibWrapper + + onChatOnlineMemberCountUpdated: { + if ((isSuperGroup || isBasicGroup) && chatInformation.id.toString() === chatId) { + chatOnlineMemberCount = onlineMemberCount; + updateGroupStatusText(); + } + } + onSupergroupFullInfoReceived: { + if(isSuperGroup && chatInformationPage.chatPartnerGroupId === groupId) { + groupFullInformation = groupFullInfo; + } + } + onSupergroupFullInfoUpdated: { + if(isSuperGroup && chatInformationPage.chatPartnerGroupId === groupId) { + groupFullInformation = groupFullInfo; + } + } + onBasicGroupFullInfoReceived: { + if(isBasicGroup && chatInformationPage.chatPartnerGroupId === groupId) { + handleBasicGroupFullInfo(groupFullInfo) + } + } + + onBasicGroupFullInfoUpdated: { + if(isBasicGroup && chatInformationPage.chatPartnerGroupId === groupId) { + handleBasicGroupFullInfo(groupFullInfo) + } + } + onUserFullInfoReceived: { + if(isPrivateChat && userFullInfo["@extra"] === chatInformationPage.chatPartnerGroupId) { + chatPartnerFullInformation = userFullInfo; + } + } + onUserFullInfoUpdated: { + if(isPrivateChat && userId === chatInformationPage.chatPartnerGroupId) { + chatPartnerFullInformation = userFullInfo; + } + } + + onUserProfilePhotosReceived: { + if(isPrivateChat && extra === chatInformationPage.chatPartnerGroupId) { + chatPartnerProfilePhotos = photos; + } + } + onChatPermissionsUpdated: { + if (chatInformation.id.toString() === chatId) { + // set whole object to trigger change + var newInformation = chatInformation; + newInformation.permissions = permissions + chatInformation = newInformation + } + } + onChatTitleUpdated: { + if (chatInformation.id.toString() === chatId) { + // set whole object to trigger change + var newInformation = chatInformation; + newInformation.title = title + chatInformation = newInformation + } + } + } + Component.onCompleted: initializePage(); + + ListModel { + id: membersList + } + + AppNotification { + id: infoNotification + } + SilicaFlickable { + id: pageFlickable + anchors.fill: parent + + PullDownMenu { + MenuItem { + visible: (isBasicGroup || isSuperGroup) && userIsMember + text: qsTr("Leave Group") + onClicked: { + // ensure it's done even if the page is closed: + var remorse = Remorse.popupAction(appWindow, qsTr("Leaving chat"), (function(chatid) { + return function() { + tdLibWrapper.leaveChat(chatid); + // this does not care about the response (ideally type "ok" without further reference) for now + pageStack.pop(pageStack.find( function(page){ return(page._depth === 0)} )); + }; + }(chatInformation.id.toString()))) + } + } + MenuItem { + visible: userIsMember + onClicked: { + var newNotificationSettings = chatInformation.notification_settings; + if (newNotificationSettings.mute_for > 0) { + newNotificationSettings.mute_for = 0; + } else { + newNotificationSettings.mute_for = 6666666; + } + tdLibWrapper.setChatNotificationSettings(chat_id, newNotificationSettings); + } + text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") + } + // MenuItem { //TODO Implement + // visible: !userIsMember + // onClicked: { + // tdLibWrapper.joinChat(chat_id); + // } + // text: qsTr("Join Chat") + // } + } + // header + PageHeader { + id: headerItem + z: 5 + Item { + id: imageContainer + property bool hasImage: typeof chatInformation.photo !== "undefined" + property int minDimension: chatInformationPage.isLandscape ? Theme.itemSizeSmall : Theme.itemSizeMedium + property int maxDimension: Screen.width / 2 + property int minX: Theme.horizontalPageMargin + property int maxX: (chatInformationPage.width - maxDimension)/2 + property int minY: (parent.height - minDimension)/2 + property int maxY: parent.height + property double tweenFactor: { + if(!hasImage) { + return 0 + } + return 1 - Math.max(0, Math.min(1, contentFlickable.contentY / maxDimension)) + } + + function getEased(min,max,factor) { + return min + (max-min)*factor + } + width: getEased(minDimension,maxDimension, tweenFactor) + height: width + x: getEased(minX,maxX, tweenFactor) + y: getEased(minY,maxY, tweenFactor) + + ProfileThumbnail { + id: chatPictureThumbnail + photoData: imageContainer.hasImage ? chatInformation.photo.small : "" + replacementStringHint: headerItem.title + width: parent.width + height: width + radius: imageContainer.minDimension / 2 + opacity: profilePictureLoader.status !== Loader.Ready || profilePictureLoader.item.opacity < 1 ? 1.0 : 0.0 + } + Loader { + id: profilePictureLoader + active: imageContainer.hasImage + asynchronous: true + anchors.fill: chatPictureThumbnail + source: chatInformationPage.isPrivateChat + ? "../components/chatInformationPage/ChatInformationProfilePictureList.qml" + : "../components/chatInformationPage/ChatInformationProfilePicture.qml" + } + } + leftMargin: imageContainer.minDimension + Theme.horizontalPageMargin + Theme.paddingMedium + title: chatInformation.title !== "" ? Emoji.emojify(chatInformation.title, Theme.fontSizeLarge) : qsTr("Unknown") + description: chatInformationPage.isPrivateChat ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : "" + } + + SilicaFlickable { + id: contentFlickable + contentHeight: groupInfoItem.height + tabViewLoader.height + clip: true + interactive: true//groupInfoItem.height > pageFlickable.height * 0.5 + + anchors { + top: headerItem.bottom + bottom: parent.bottom + left: parent.left + right: parent.right + } + NumberAnimation { + id: scrollDownAnimation + target: contentFlickable + to: groupInfoItem.height + property: "contentY" + duration: 500 + easing.type: Easing.InOutCubic + } + NumberAnimation { + id: scrollUpAnimation + target: contentFlickable + to: 0 + property: "contentY" + duration: 500 + easing.type: Easing.InOutCubic + property Timer scrollUpTimer: Timer { + id: scrollUpTimer + interval: 50 + onTriggered: { + contentFlickable.scrollToTop() + } + } + property Timer scrollDownTimer: Timer { + id: scrollDownTimer + interval: 50 + onTriggered: { + contentFlickable.scrollToBottom() + } + } + } + + Column { + id: groupInfoItem + bottomPadding: Theme.paddingLarge + topPadding: Theme.paddingLarge + anchors { + top: parent.top + left: parent.left + leftMargin: Theme.horizontalPageMargin + right: parent.right + rightMargin: Theme.horizontalPageMargin + } + + Item { //large image placeholder + width: parent.width + height: imageContainer.hasImage ? imageContainer.maxDimension : 0 + } + + ChatInformationEditArea { + visible: canEdit + canEdit: !chatInformationPage.isPrivateChat && chatInformationPage.groupInformation.status && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator") + headerText: qsTr("Chat Title", "group title header") + text: chatInformation.title + + onSaveButtonClicked: { + if(!editItem.errorHighlight) { + tdLibWrapper.setChatTitle(chatInformationPage.chatInformation.id, textValue); + } else { + isEditing = true + } + } + + onTextEdited: { + if(textValue.length > 0 && textValue.length < 129) { + editItem.errorHighlight = false + editItem.label = "" + editItem.placeholderText = "" + } else { + editItem.label = qsTr("Enter 1-128 characters") + editItem.placeholderText = editItem.label + editItem.errorHighlight = true + } + } + } + ChatInformationEditArea { + canEdit: (chatInformationPage.isPrivateChat && chatInformationPage.privateChatUserInformation.id === chatInformationPage.myUserId) || ((chatInformationPage.isBasicGroup || chatInformationPage.isSuperGroup) && chatInformationPage.groupInformation && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator")) + emptyPlaceholderText: qsTr("There is no information text available, yet.") + headerText: qsTr("Info", "group or user infotext header") + multiLine: true + text: (chatInformationPage.isPrivateChat ? chatInformationPage.chatPartnerFullInformation.bio : chatInformationPage.groupFullInformation.description) || "" + onSaveButtonClicked: { + if(chatInformationPage.isPrivateChat) { // own bio + tdLibWrapper.setBio(textValue); + } else { // group info + tdLibWrapper.setChatDescription(chatInformationPage.chatInformation.id, textValue); + } + } + } + + ChatInformationTextItem { + headerText: qsTr("Phone Number", "user phone number header") + text: (chatInformationPage.isPrivateChat && chatInformationPage.privateChatUserInformation.phone_number ? "+"+chatInformationPage.privateChatUserInformation.phone_number : "") || "" + isLinkedLabel: true + } + + SectionHeader { + font.pixelSize: Theme.fontSizeExtraSmall + visible: !!inviteLinkItem.text + height: visible ? Theme.itemSizeExtraSmall : 0 + text: qsTr("Invite Link", "header") + x: 0 + } + + Row { + width: parent.width + visible: !!inviteLinkItem.text + ChatInformationTextItem { + id: inviteLinkItem + text: !isPrivateChat ? groupFullInformation.invite_link : "" + width: parent.width - inviteLinkButton.width + } + IconButton { + id: inviteLinkButton + icon.source: "image://theme/icon-m-clipboard" + anchors.verticalCenter: inviteLinkItem.verticalCenter + onClicked: { + inviteLinkField.selectAll(); + inviteLinkField.copy(); + inviteLinkField.select(0,0); + infoNotification.show(qsTr("The Invite Link has been copied to the clipboard.")); + } + TextField { + id: inviteLinkField + width: 0 + height: 0 + text: groupFullInformation.invite_link ? groupFullInformation.invite_link : "" + visible: false + readOnly: true + opacity: 0 + } + } + } + + Item { + width: parent.width + height: Theme.paddingLarge + } + + Separator { + width: parent.width + color: Theme.primaryColor + horizontalAlignment: Qt.AlignHCenter + opacity: (tabViewLoader.status === Loader.Ready && tabViewLoader.item.count > 0) ? 1.0 : 0.0 + + Behavior on opacity { PropertyAnimation {duration: 500}} + } + } + + Loader { + id: tabViewLoader + asynchronous: true + active: true + anchors { + left: parent.left + right: parent.right + top: groupInfoItem.bottom + } + sourceComponent: Component { + ChatInformationTabView { + id: tabView + height: tabView.count > 0 ? chatInformationPage.height - headerItem.height : 0 + } + } + } + } + } + function updateGroupStatusText() { + if (chatOnlineMemberCount > 0) { + headerItem.description = qsTr("%1 members, %2 online").arg(Functions.getShortenedCount(groupInformation.member_count)).arg(Functions.getShortenedCount(chatOnlineMemberCount)); + } else { + if (isChannel) { + headerItem.description = qsTr("%1 subscribers").arg(Functions.getShortenedCount(groupInformation.member_count)); + } else { + headerItem.description = qsTr("%1 members").arg(Functions.getShortenedCount(groupInformation.member_count)); + } + } + } + +} diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index c108784..6350048 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -46,23 +46,9 @@ Page { property variant emojiProposals; function updateChatPartnerStatusText() { - if (chatPartnerInformation.status['@type'] === "userStatusEmpty" ) { - chatStatusText.text = qsTr("was never online"); - } - if (chatPartnerInformation.status['@type'] === "userStatusLastMonth" ) { - chatStatusText.text = qsTr("offline, last online: last month"); - } - if (chatPartnerInformation.status['@type'] === "userStatusLastWeek" ) { - chatStatusText.text = qsTr("offline, last online: last week"); - } - if (chatPartnerInformation.status['@type'] === "userStatusOffline" ) { - chatStatusText.text = qsTr("offline, last online: %1").arg(Functions.getDateTimeElapsed(chatPartnerInformation.status.was_online)); - } - if (chatPartnerInformation.status['@type'] === "userStatusOnline" ) { - chatStatusText.text = qsTr("online"); - } - if (chatPartnerInformation.status['@type'] === "userStatusRecently" ) { - chatStatusText.text = qsTr("offline, was recently online"); + var statusText = Functions.getChatPartnerStatusText(chatPartnerInformation.status['@type'], chatPartnerInformation.status.was_online); + if(statusText) { + chatStatusText.text = statusText; } } @@ -109,6 +95,9 @@ Page { function getMessageStatusText(message, listItemIndex, lastReadSentIndex) { var messageStatusSuffix = ""; + if(!message) { + return ""; + } if (message.edit_date > 0) { messageStatusSuffix += " - " + qsTr("edited"); @@ -221,19 +210,26 @@ Page { initializePage(); } + Component.onDestruction: { + tdLibWrapper.closeChat(chatInformation.id); + } + onStatusChanged: { - if (status === PageStatus.Activating) { + switch(status) { + case PageStatus.Activating: tdLibWrapper.openChat(chatInformation.id); - } - if (status === PageStatus.Active) { + break; + case PageStatus.Active: + console.log("CHAT opendirectly?", chatPage.isInitialized) if (!chatPage.isInitialized) { chatModel.initialize(chatInformation); chatPage.isInitialized = true; } + break; +// case PageStatus.Deactivating: +// tdLibWrapper.closeChat(chatInformation.id); } - if (status === PageStatus.Deactivating) { - tdLibWrapper.closeChat(chatInformation.id); - } + } Connections { @@ -277,6 +273,14 @@ Page { target: chatModel onMessagesReceived: { console.log("[ChatPage] Messages received, view has " + chatView.count + " messages, setting view to index " + modelIndex + ", own messages were read before index " + lastReadSentIndex); + if(totalCount === 0) { + console.log("[ChatPage] actually, skipping that: No Messages in Chat."); + + chatView.positionViewAtEnd(); + chatPage.loading = false; + return; + } + chatView.lastReadSentIndex = lastReadSentIndex; if (modelIndex === (chatView.count - 1)) { chatView.positionViewAtEnd(); @@ -286,7 +290,7 @@ Page { chatPage.loading = false; if (chatView.height > chatView.contentHeight) { console.log("[ChatPage] Chat content quite small..."); - tdLibWrapper.viewMessage(chatInformation.id, chatModel.getMessage(chatView.count - 1).id); + tdLibWrapper.viewMessage(chatInformation.id, chatModel.getMessage(chatView.count - 1).id, false); } } onNewMessageReceived: { @@ -336,7 +340,7 @@ Page { Timer { id: chatContactTimeUpdater interval: 60000 - running: true + running: isPrivateChat repeat: true onTriggered: { updateChatPartnerStatusText(); @@ -373,7 +377,14 @@ Page { muteChatMenuItem.text = chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat"); } } - + BackgroundItem { + id: headerMouseArea + height: headerRow.height + width: parent.width + onClicked: { + pageStack.push(Qt.resolvedUrl("../pages/ChatInformationPage.qml"), { "chatInformation" : chatInformation, "privateChatUserInformation": chatPartnerInformation, "groupInformation": chatGroupInformation, "chatOnlineMemberCount": chatOnlineMemberCount}); + } + } Column { id: chatColumn width: parent.width @@ -427,7 +438,7 @@ Page { textFormat: Text.StyledText font.pixelSize: Theme.fontSizeExtraSmall font.family: Theme.fontFamilyHeading - color: Theme.secondaryColor + color: headerMouseArea.pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor elide: Text.ElideRight width: parent.width maximumLineCount: 1 @@ -487,7 +498,7 @@ Page { function handleScrollPositionChanged() { console.log("Current position: " + chatView.contentY); - tdLibWrapper.viewMessage(chatInformation.id, chatView.itemAt(chatView.contentX, ( chatView.contentY + chatView.height - Theme.horizontalPageMargin )).myMessage.id); + tdLibWrapper.viewMessage(chatInformation.id, chatView.itemAt(chatView.contentX, ( chatView.contentY + chatView.height - Theme.horizontalPageMargin )).myMessage.id, false); } onContentYChanged: { @@ -958,6 +969,11 @@ Page { } VerticalScrollDecorator {} + + ViewPlaceholder { + enabled: chatView.count === 0 + text: qsTr("This chat is empty.") + } } Column { @@ -1157,7 +1173,7 @@ Page { property bool isPicture: false; property bool isVideo: false; property bool isDocument: false; - property variant fileProperties; + property variant fileProperties:({}); IconButton { id: removeAttachmentsIconButton diff --git a/qml/pages/CoverPage.qml b/qml/pages/CoverPage.qml index 7534181..633779f 100644 --- a/qml/pages/CoverPage.qml +++ b/qml/pages/CoverPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/pages/ImagePage.qml b/qml/pages/ImagePage.qml index 338b3fb..2072e0f 100644 --- a/qml/pages/ImagePage.qml +++ b/qml/pages/ImagePage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/pages/InitializationPage.qml b/qml/pages/InitializationPage.qml index 46ec314..9493792 100644 --- a/qml/pages/InitializationPage.qml +++ b/qml/pages/InitializationPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -147,7 +147,7 @@ Page { TextField { id: phoneNumberTextField - placeholderText: "Use the international format, e.g. +4912342424242" + placeholderText: qsTr("Use the international format, e.g. %1").arg("+4912342424242") inputMethodHints: Qt.ImhDialableCharactersOnly labelVisible: false width: parent.width diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index bcc452c..f3533f5 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -152,6 +152,16 @@ Page { chatListCreatedTimer.restart(); } } + onChatReceived: { + if(chat["@extra"] === "openDirectly") { + console.log("ON CHAT RECEIVED", JSON.stringify(chat, null, 2)); + if (status !== PageStatus.Active) { + pageStack.pop(pageStack.find( function(page){ return(page._depth === 0)} ), PageStackAction.Immediate); + } + // if we get a new chat (no messages?), we can not use the provided data + pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : tdLibWrapper.getChat(chat.id) }); + } + } } Component.onCompleted: { @@ -219,31 +229,12 @@ Page { Behavior on opacity { NumberAnimation {} } model: chatListModel - delegate: ListItem { - - id: chatListViewItem - - contentHeight: chatListRow.height + chatListSeparator.height + 2 * Theme.paddingMedium - contentWidth: parent.width + delegate: ChatListViewItem { + pictureThumbnail.forceElementUpdate: overviewPage.chatListCreated + ownUserId: overviewPage.ownUserId onClicked: { - pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : display }); - } - - showMenuOnPressAndHold: chat_id != overviewPage.ownUserId - menu: ContextMenu { - MenuItem { - onClicked: { - var newNotificationSettings = display.notification_settings; - if (newNotificationSettings.mute_for > 0) { - newNotificationSettings.mute_for = 0; - } else { - newNotificationSettings.mute_for = 6666666; - } - tdLibWrapper.setChatNotificationSettings(chat_id, newNotificationSettings); - } - text: display.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") - } + pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : display }); } Connections { @@ -251,151 +242,10 @@ Page { onChatChanged: { if (overviewPage.chatListCreated && changedChatId === chat_id) { // Force update of some list item elements (currently only last message text seems to create problems). dataChanged() doesn't seem to trigger them all :( - chatListLastMessageText.text = last_message_text ? Emoji.emojify(last_message_text, Theme.fontSizeExtraSmall) : qsTr("Unknown") + secondaryText.text = last_message_text ? Emoji.emojify(last_message_text, Theme.fontSizeExtraSmall) : qsTr("Unknown") } } } - - Column { - id: chatListColumn - width: parent.width - ( 2 * Theme.horizontalPageMargin ) - spacing: Theme.paddingSmall - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter - } - - Row { - id: chatListRow - width: parent.width - height: chatListContentColumn.height - spacing: Theme.paddingMedium - - Column { - id: chatListPictureColumn - width: chatListContentColumn.height - Theme.paddingSmall - height: chatListContentColumn.height - Theme.paddingSmall - anchors.verticalCenter: parent.verticalCenter - - Item { - id: chatListPictureItem - width: parent.width - height: parent.width - - ProfileThumbnail { - id: chatListPictureThumbnail - photoData: photo_small - replacementStringHint: chatListNameText.text - width: parent.width - height: parent.width - forceElementUpdate: overviewPage.chatListCreated - } - - Rectangle { - id: chatUnreadMessagesCountBackground - color: Theme.highlightBackgroundColor - width: Theme.fontSizeLarge - height: Theme.fontSizeLarge - anchors.right: parent.right - anchors.bottom: parent.bottom - radius: parent.width / 2 - visible: unread_count > 0 - } - - Text { - id: chatUnreadMessagesCount - font.pixelSize: Theme.fontSizeExtraSmall - font.bold: true - color: Theme.primaryColor - anchors.centerIn: chatUnreadMessagesCountBackground - visible: chatUnreadMessagesCountBackground.visible - text: unread_count > 99 ? "99+" : unread_count - } - } - } - - Column { - id: chatListContentColumn - width: parent.width * 5 / 6 - Theme.horizontalPageMargin - spacing: Theme.paddingSmall - - Text { - id: chatListNameText - text: title ? Emoji.emojify(title, Theme.fontSizeMedium) + ( display.notification_settings.mute_for > 0 ? Emoji.emojify(" 🔇", Theme.fontSizeMedium) : "" ) : qsTr("Unknown") - textFormat: Text.StyledText - font.pixelSize: Theme.fontSizeMedium - color: Theme.primaryColor - elide: Text.ElideRight - width: parent.width - onTruncatedChanged: { - // There is obviously a bug in QML in truncating text with images. - // We simply remove Emojis then... - if (truncated) { - text = text.replace(/\]+\/\>/g, ""); - } - } - } - - Row { - id: chatListLastMessageRow - width: parent.width - spacing: Theme.paddingSmall - Text { - id: chatListLastUserText - text: is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== overviewPage.ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), font.pixelSize) : qsTr("You") ) : qsTr("Unknown") ) - font.pixelSize: Theme.fontSizeExtraSmall - color: Theme.highlightColor - textFormat: Text.StyledText - onTruncatedChanged: { - // There is obviously a bug in QML in truncating text with images. - // We simply remove Emojis then... - if (truncated) { - text = text.replace(/\]+\/\>/g, ""); - } - } - } - Text { - id: chatListLastMessageText - text: last_message_text ? Emoji.emojify(last_message_text, Theme.fontSizeExtraSmall) : qsTr("Unknown") - font.pixelSize: Theme.fontSizeExtraSmall - color: Theme.primaryColor - width: parent.width - Theme.paddingMedium - chatListLastUserText.width - elide: Text.ElideRight - textFormat: Text.StyledText - onTruncatedChanged: { - // There is obviously a bug in QML in truncating text with images. - // We simply remove Emojis then... - if (truncated) { - text = text.replace(/\]+\/\>/g, ""); - } - } - } - } - - Text { - id: messageContactTimeElapsedText - text: last_message_date ? Functions.getDateTimeElapsed(last_message_date) : qsTr("Unknown") - font.pixelSize: Theme.fontSizeTiny - color: Theme.secondaryColor - } - } - } - - } - - Separator { - id: chatListSeparator - - anchors { - top: chatListColumn.bottom - topMargin: Theme.paddingMedium - } - - width: parent.width - color: Theme.primaryColor - horizontalAlignment: Qt.AlignHCenter - } - } ViewPlaceholder { diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml index f044f9c..0e73bf8 100644 --- a/qml/pages/SettingsPage.qml +++ b/qml/pages/SettingsPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/qml/pages/VideoPage.qml b/qml/pages/VideoPage.qml index 928bcef..4d939d1 100644 --- a/qml/pages/VideoPage.qml +++ b/qml/pages/VideoPage.qml @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/rpm/harbour-fernschreiber.spec b/rpm/harbour-fernschreiber.spec index 2054851..bf51b3a 100644 --- a/rpm/harbour-fernschreiber.spec +++ b/rpm/harbour-fernschreiber.spec @@ -11,8 +11,8 @@ Name: harbour-fernschreiber # << macros Summary: Fernschreiber is a Telegram client for Sailfish OS -Version: 0.3 -Release: 2 +Version: 0.4 +Release: 1 Group: Qt/Qt License: LICENSE URL: http://werkwolf.eu/ diff --git a/rpm/harbour-fernschreiber.yaml b/rpm/harbour-fernschreiber.yaml index 21c163a..e3a95af 100644 --- a/rpm/harbour-fernschreiber.yaml +++ b/rpm/harbour-fernschreiber.yaml @@ -1,7 +1,7 @@ Name: harbour-fernschreiber Summary: Fernschreiber is a Telegram client for Sailfish OS -Version: 0.3 -Release: 2 +Version: 0.4 +Release: 1 # The contents of the Group field should be one of the groups listed here: # https://github.com/mer-tools/spectacle/blob/master/data/GROUPS Group: Qt/Qt diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index ec33dde..b45c82c 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -352,6 +352,21 @@ void ChatListModel::redrawModel() layoutChanged(); } +QVariantMap ChatListModel::get(int row) +{ + + QHash names = roleNames(); + QHashIterator i(names); + QVariantMap res; + QModelIndex idx = index(row, 0); + while (i.hasNext()) { + i.next(); + QVariant data = idx.data(i.key()); + res[i.value()] = data; + } + return res; +} + int ChatListModel::updateChatOrder(int chatIndex) { ChatData *chat = chatList.at(chatIndex); diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index 3f0945d..c4d9dfd 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -37,6 +37,7 @@ public: virtual QVariant data(const QModelIndex &index, int role) const override; Q_INVOKABLE void redrawModel(); + Q_INVOKABLE QVariantMap get(int row); bool showAllChats() const; void setShowAllChats(bool showAll); diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index 2eb9963..7525c8e 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -28,7 +28,7 @@ ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) this->tdLibWrapper = tdLibWrapper; this->inReload = false; this->inIncrementalUpdate = false; - connect(this->tdLibWrapper, SIGNAL(messagesReceived(QVariantList)), this, SLOT(handleMessagesReceived(QVariantList))); + connect(this->tdLibWrapper, SIGNAL(messagesReceived(QVariantList, int)), this, SLOT(handleMessagesReceived(QVariantList, int))); connect(this->tdLibWrapper, SIGNAL(newMessageReceived(QString, QVariantMap)), this, SLOT(handleNewMessageReceived(QString, QVariantMap))); connect(this->tdLibWrapper, SIGNAL(chatReadInboxUpdated(QString, QString, int)), this, SLOT(handleChatReadInboxUpdated(QString, QString, int))); connect(this->tdLibWrapper, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SLOT(handleChatReadOutboxUpdated(QString, QString))); @@ -72,9 +72,11 @@ void ChatModel::initialize(const QVariantMap &chatInformation) { qDebug() << "[ChatModel] Initializing chat model..."; this->chatInformation = chatInformation; + beginResetModel(); this->messages.clear(); this->messageIndexMap.clear(); this->messagesToBeAdded.clear(); + endResetModel(); this->chatId = chatInformation.value("id").toString(); tdLibWrapper->getChatHistory(this->chatId); } @@ -113,7 +115,7 @@ bool compareMessages(const QVariant &message1, const QVariant &message2) } } -void ChatModel::handleMessagesReceived(const QVariantList &messages) +void ChatModel::handleMessagesReceived(const QVariantList &messages, const int &totalCount) { qDebug() << "[ChatModel] Receiving new messages :)" << messages.size(); @@ -126,7 +128,7 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages) this->inIncrementalUpdate = false; emit messagesIncrementalUpdate(listInboxPosition, listOutboxPosition); } else { - emit messagesReceived(listInboxPosition, listOutboxPosition); + emit messagesReceived(listInboxPosition, listOutboxPosition, totalCount); } } else { this->messagesMutex.lock(); @@ -157,7 +159,7 @@ void ChatModel::handleMessagesReceived(const QVariantList &messages) this->inIncrementalUpdate = false; emit messagesIncrementalUpdate(listInboxPosition, listOutboxPosition); } else { - emit messagesReceived(listInboxPosition, listOutboxPosition); + emit messagesReceived(listInboxPosition, listOutboxPosition, totalCount); } } } diff --git a/src/chatmodel.h b/src/chatmodel.h index 7f57c7b..de17095 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -42,7 +42,7 @@ public: Q_INVOKABLE QVariantMap getMessage(const int &index); signals: - void messagesReceived(const int &modelIndex, const int &lastReadSentIndex); + void messagesReceived(const int &modelIndex, const int &lastReadSentIndex, const int &totalCount); void messagesIncrementalUpdate(const int &modelIndex, const int &lastReadSentIndex); void newMessageReceived(const QVariantMap &message); void unreadCountUpdated(const int &unreadCount, const QString &lastReadInboxMessageId); @@ -52,7 +52,7 @@ signals: void messagesDeleted(); public slots: - void handleMessagesReceived(const QVariantList &messages); + void handleMessagesReceived(const QVariantList &messages, const int &totalCount); void handleNewMessageReceived(const QString &chatId, const QVariantMap &message); void handleChatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, const int &unreadCount); void handleChatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); diff --git a/src/dbusadaptor.cpp b/src/dbusadaptor.cpp index 4978061..5d46b54 100644 --- a/src/dbusadaptor.cpp +++ b/src/dbusadaptor.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/dbusadaptor.h b/src/dbusadaptor.h index c3bbbc1..7e5f9db 100644 --- a/src/dbusadaptor.h +++ b/src/dbusadaptor.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/dbusinterface.cpp b/src/dbusinterface.cpp index ed31609..ab38826 100644 --- a/src/dbusinterface.cpp +++ b/src/dbusinterface.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/dbusinterface.h b/src/dbusinterface.h index 16281c5..8c3add7 100644 --- a/src/dbusinterface.h +++ b/src/dbusinterface.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/emojisearchworker.cpp b/src/emojisearchworker.cpp index 5e97d0b..c239157 100644 --- a/src/emojisearchworker.cpp +++ b/src/emojisearchworker.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/emojisearchworker.h b/src/emojisearchworker.h index c728b07..25a785d 100644 --- a/src/emojisearchworker.h +++ b/src/emojisearchworker.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/fernschreiberutils.cpp b/src/fernschreiberutils.cpp index 2a9ed3d..b52122e 100644 --- a/src/fernschreiberutils.cpp +++ b/src/fernschreiberutils.cpp @@ -51,5 +51,8 @@ QString FernschreiberUtils::getMessageShortText(const QVariantMap &messageConten if (contentType == "messageChatDeleteMember") { return myself ? tr("left this chat", "myself") : tr("left this chat"); } + if (contentType == "messageChatChangeTitle") { + return myself ? tr("changed the chat title", "myself") : tr("changed the chat title"); + } return tr("Unsupported message: %1").arg(contentType.mid(7)); } diff --git a/src/harbour-fernschreiber.cpp b/src/harbour-fernschreiber.cpp index babb531..a17c420 100644 --- a/src/harbour-fernschreiber.cpp +++ b/src/harbour-fernschreiber.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/notificationmanager.cpp b/src/notificationmanager.cpp index 1300c88..fc0ba1f 100644 --- a/src/notificationmanager.cpp +++ b/src/notificationmanager.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/notificationmanager.h b/src/notificationmanager.h index 7e1c123..9cb3020 100644 --- a/src/notificationmanager.h +++ b/src/notificationmanager.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/stickermanager.cpp b/src/stickermanager.cpp index b27871f..92b63f6 100644 --- a/src/stickermanager.cpp +++ b/src/stickermanager.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/stickermanager.h b/src/stickermanager.h index f4378a3..3aae40f 100644 --- a/src/stickermanager.h +++ b/src/stickermanager.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index 407e633..cb80fe1 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -41,6 +41,7 @@ namespace { const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id"); const QString TYPE("@type"); + const QString EXTRA("@extra"); const QString TYPE_CHAT_POSITION("chatPosition"); const QString TYPE_CHAT_LIST_MAIN("chatListMain"); } @@ -99,11 +100,22 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren handlers.insert("updateMessageContent", &TDLibReceiver::processUpdateMessageContent); handlers.insert("updateDeleteMessages", &TDLibReceiver::processUpdateDeleteMessages); handlers.insert("chats", &TDLibReceiver::processChats); + handlers.insert("chat", &TDLibReceiver::processChat); handlers.insert("updateRecentStickers", &TDLibReceiver::processUpdateRecentStickers); handlers.insert("stickers", &TDLibReceiver::processStickers); handlers.insert("updateInstalledStickerSets", &TDLibReceiver::processUpdateInstalledStickerSets); handlers.insert("stickerSets", &TDLibReceiver::processStickerSets); handlers.insert("stickerSet", &TDLibReceiver::processStickerSet); + handlers.insert("chatMembers", &TDLibReceiver::processChatMembers); + handlers.insert("userFullInfo", &TDLibReceiver::processUserFullInfo); + handlers.insert("updateUserFullInfo", &TDLibReceiver::processUpdateUserFullInfo); + handlers.insert("basicGroupFullInfo", &TDLibReceiver::processBasicGroupFullInfo); + handlers.insert("updateBasicGroupFullInfo", &TDLibReceiver::processUpdateBasicGroupFullInfo); + handlers.insert("supergroupFullInfo", &TDLibReceiver::processSupergroupFullInfo); + handlers.insert("updateSupergroupFullInfo", &TDLibReceiver::processUpdateSupergroupFullInfo); + handlers.insert("userProfilePhotos", &TDLibReceiver::processUserProfilePhotos); + handlers.insert("updateChatPermissions", &TDLibReceiver::processUpdateChatPermissions); + handlers.insert("updateChatTitle", &TDLibReceiver::processUpdateChatTitle); } void TDLibReceiver::setActive(const bool &active) @@ -302,7 +314,7 @@ void TDLibReceiver::processChatOnlineMemberCountUpdated(const QVariantMap &recei void TDLibReceiver::processMessages(const QVariantMap &receivedInformation) { LOG("Received new messages, amount: " << receivedInformation.value("total_count").toString()); - emit messagesReceived(receivedInformation.value("messages").toList()); + emit messagesReceived(receivedInformation.value("messages").toList(), receivedInformation.value("total_count").toInt()); } void TDLibReceiver::processUpdateNewMessage(const QVariantMap &receivedInformation) @@ -375,6 +387,11 @@ void TDLibReceiver::processChats(const QVariantMap &receivedInformation) emit chats(receivedInformation); } +void TDLibReceiver::processChat(const QVariantMap &receivedInformation) +{ + emit chat(receivedInformation); +} + void TDLibReceiver::processUpdateRecentStickers(const QVariantMap &receivedInformation) { LOG("Recent stickers updated"); @@ -404,3 +421,76 @@ void TDLibReceiver::processStickerSet(const QVariantMap &receivedInformation) LOG("Received a sticker set..."); emit stickerSet(receivedInformation); } +void TDLibReceiver::processChatMembers(const QVariantMap &receivedInformation) +{ + LOG("Received super group members"); + const QString extra = receivedInformation.value(EXTRA).toString(); + emit chatMembers(extra, receivedInformation.value("members").toList(), receivedInformation.value("total_count").toInt()); +} + +void TDLibReceiver::processUserFullInfo(const QVariantMap &receivedInformation) +{ + + LOG("Received UserFullInfo"); + + emit userFullInfo(receivedInformation); +} + +void TDLibReceiver::processUpdateUserFullInfo(const QVariantMap &receivedInformation) +{ + + LOG("Received UserFullInfoUpdate"); + + emit userFullInfoUpdated(receivedInformation.value("user_id").toString(), receivedInformation.value("user_full_info").toMap()); +} + +void TDLibReceiver::processBasicGroupFullInfo(const QVariantMap &receivedInformation) +{ + + LOG("Received BasicGroupFullInfo"); + const QString groupId = receivedInformation.value(EXTRA).toString(); + + emit basicGroupFullInfo(groupId, receivedInformation); +} +void TDLibReceiver::processUpdateBasicGroupFullInfo(const QVariantMap &receivedInformation) +{ + LOG("Received BasicGroupFullInfoUpdate"); + const QString groupId = receivedInformation.value("basic_group_id").toString(); + + emit basicGroupFullInfoUpdated(groupId, receivedInformation.value("basic_group_full_info").toMap()); +} + +void TDLibReceiver::processSupergroupFullInfo(const QVariantMap &receivedInformation) +{ + LOG("Received SuperGroupFullInfoUpdate"); + const QString groupId = receivedInformation.value(EXTRA).toString(); + + emit supergroupFullInfo(groupId, receivedInformation); +} + +void TDLibReceiver::processUpdateSupergroupFullInfo(const QVariantMap &receivedInformation) +{ + + LOG("Received SuperGroupFullInfoUpdate"); + const QString groupId = receivedInformation.value("supergroup_id").toString(); + + emit supergroupFullInfoUpdated(groupId, receivedInformation.value("supergroup_full_info").toMap()); +} + +void TDLibReceiver::processUserProfilePhotos(const QVariantMap &receivedInformation) +{ + const QString extra = receivedInformation.value(EXTRA).toString(); + emit userProfilePhotos(extra, receivedInformation.value("photos").toList(), receivedInformation.value("total_count").toInt()); +} + +void TDLibReceiver::processUpdateChatPermissions(const QVariantMap &receivedInformation) +{ + emit chatPermissionsUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("permissions").toMap()); +} + +void TDLibReceiver::processUpdateChatTitle(const QVariantMap &receivedInformation) +{ + + LOG("Received UpdateChatTitle"); + emit chatTitleUpdated(receivedInformation.value("chat_id").toString(), receivedInformation.value("title").toString()); +} diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index 8aac1ba..a8eb27a 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -53,7 +53,7 @@ signals: void basicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void superGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void chatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount); - void messagesReceived(const QVariantList &messages); + void messagesReceived(const QVariantList &messages, const int &totalCount); void newMessageReceived(const QString &chatId, const QVariantMap &message); void messageInformation(const QString &messageId, const QVariantMap &message); void messageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message); @@ -64,12 +64,22 @@ signals: void messageContentUpdated(const QString &chatId, const QString &messageId, const QVariantMap &newContent); void messagesDeleted(const QString &chatId, const QVariantList &messageIds); void chats(const QVariantMap &chats); + void chat(const QVariantMap &chats); void recentStickersUpdated(const QVariantList &stickerIds); void stickers(const QVariantList &stickers); void installedStickerSetsUpdated(const QVariantList &stickerSetIds); void stickerSets(const QVariantList &stickerSets); void stickerSet(const QVariantMap &stickerSet); - + void chatMembers(const QString &extra, const QVariantList &members, const int &totalMembers); + void userFullInfo(const QVariantMap &userFullInfo); + void userFullInfoUpdated(const QString &userId,const QVariantMap &userFullInfo); + void basicGroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo); + void basicGroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); + void supergroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo); + void supergroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); + void userProfilePhotos(const QString &extra, const QVariantList &photos, const int &totalPhotos); + void chatPermissionsUpdated(const QString &chatId, const QVariantMap &chatPermissions); + void chatTitleUpdated(const QString &chatId, const QString &title); private: typedef void (TDLibReceiver::*Handler)(const QVariantMap &); @@ -108,11 +118,22 @@ private: void processUpdateMessageContent(const QVariantMap &receivedInformation); void processUpdateDeleteMessages(const QVariantMap &receivedInformation); void processChats(const QVariantMap &receivedInformation); + void processChat(const QVariantMap &receivedInformation); void processUpdateRecentStickers(const QVariantMap &receivedInformation); void processStickers(const QVariantMap &receivedInformation); void processUpdateInstalledStickerSets(const QVariantMap &receivedInformation); void processStickerSets(const QVariantMap &receivedInformation); void processStickerSet(const QVariantMap &receivedInformation); + void processChatMembers(const QVariantMap &receivedInformation); + void processUserFullInfo(const QVariantMap &receivedInformation); + void processUpdateUserFullInfo(const QVariantMap &receivedInformation); + void processBasicGroupFullInfo(const QVariantMap &receivedInformation); + void processUpdateBasicGroupFullInfo(const QVariantMap &receivedInformation); + void processSupergroupFullInfo(const QVariantMap &receivedInformation); + void processUpdateSupergroupFullInfo(const QVariantMap &receivedInformation); + void processUserProfilePhotos(const QVariantMap &receivedInformation); + void processUpdateChatPermissions(const QVariantMap &receivedInformation); + void processUpdateChatTitle(const QVariantMap &receivedInformation); }; #endif // TDLIBRECEIVER_H diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index d694ad4..c1d6ffc 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -42,6 +42,7 @@ namespace { const QString STATUS("status"); const QString _TYPE("@type"); + const QString _EXTRA("@extra"); } TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent) @@ -76,7 +77,7 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent) connect(this->tdLibReceiver, SIGNAL(basicGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleBasicGroupUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(superGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleSuperGroupUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chatOnlineMemberCountUpdated(QString, int)), this, SLOT(handleChatOnlineMemberCountUpdated(QString, int))); - connect(this->tdLibReceiver, SIGNAL(messagesReceived(QVariantList)), this, SLOT(handleMessagesReceived(QVariantList))); + connect(this->tdLibReceiver, SIGNAL(messagesReceived(QVariantList, int)), this, SLOT(handleMessagesReceived(QVariantList, int))); connect(this->tdLibReceiver, SIGNAL(newMessageReceived(QString, QVariantMap)), this, SLOT(handleNewMessageReceived(QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(messageInformation(QString, QVariantMap)), this, SLOT(handleMessageInformation(QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(messageSendSucceeded(QString, QString, QVariantMap)), this, SLOT(handleMessageSendSucceeded(QString, QString, QVariantMap))); @@ -87,11 +88,24 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent) connect(this->tdLibReceiver, SIGNAL(messageContentUpdated(QString, QString, QVariantMap)), this, SLOT(handleMessageContentUpdated(QString, QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(messagesDeleted(QString, QVariantList)), this, SLOT(handleMessagesDeleted(QString, QVariantList))); connect(this->tdLibReceiver, SIGNAL(chats(QVariantMap)), this, SLOT(handleChats(QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(chat(QVariantMap)), this, SLOT(handleChat(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(recentStickersUpdated(QVariantList)), this, SLOT(handleRecentStickersUpdated(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickers(QVariantList)), this, SLOT(handleStickers(QVariantList))); connect(this->tdLibReceiver, SIGNAL(installedStickerSetsUpdated(QVariantList)), this, SLOT(handleInstalledStickerSetsUpdated(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickerSets(QVariantList)), this, SLOT(handleStickerSets(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickerSet(QVariantMap)), this, SLOT(handleStickerSet(QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(chatMembers(QString, QVariantList, int)), this, SLOT(handleChatMembers(QString, QVariantList, int))); + connect(this->tdLibReceiver, SIGNAL(userFullInfo(QVariantMap)), this, SLOT(handleUserFullInfo(QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(userFullInfoUpdated(QString, QVariantMap)), this, SLOT(handleUserFullInfoUpdated(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(basicGroupFullInfo(QString, QVariantMap)), this, SLOT(handleBasicGroupFullInfo(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(basicGroupFullInfoUpdated(QString, QVariantMap)), this, SLOT(handleBasicGroupFullInfoUpdated(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(supergroupFullInfo(QString, QVariantMap)), this, SLOT(handleSupergroupFullInfo(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(supergroupFullInfoUpdated(QString, QVariantMap)), this, SLOT(handleSupergroupFullInfoUpdated(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(userProfilePhotos(QString, QVariantList, int)), this, SLOT(handleUserProfilePhotos(QString, QVariantList, int))); + connect(this->tdLibReceiver, SIGNAL(userProfilePhotos(QString, QVariantList, int)), this, SLOT(handleUserProfilePhotos(QString, QVariantList, int))); + connect(this->tdLibReceiver, SIGNAL(chatPermissionsUpdated(QString, QVariantMap)), this, SLOT(handleChatPermissionsUpdated(QString, QVariantMap))); + + connect(this->tdLibReceiver, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString))); connect(&emojiSearchWorker, SIGNAL(searchCompleted(QString, QVariantList)), this, SLOT(handleEmojiSearchCompleted(QString, QVariantList))); @@ -222,6 +236,15 @@ void TDLibWrapper::closeChat(const QString &chatId) this->sendRequest(requestObject); } +void TDLibWrapper::leaveChat(const QString &chatId) +{ + LOG("Leaving chat " << chatId); + QVariantMap requestObject; + requestObject.insert(_TYPE, "leaveChat"); + requestObject.insert("chat_id", chatId); + this->sendRequest(requestObject); +} + void TDLibWrapper::getChatHistory(const QString &chatId, const qlonglong &fromMessageId, const int &offset, const int &limit, const bool &onlyLocal) { LOG("Retrieving chat history" << chatId << fromMessageId << offset << limit << onlyLocal); @@ -235,13 +258,13 @@ void TDLibWrapper::getChatHistory(const QString &chatId, const qlonglong &fromMe this->sendRequest(requestObject); } -void TDLibWrapper::viewMessage(const QString &chatId, const QString &messageId) +void TDLibWrapper::viewMessage(const QString &chatId, const QString &messageId, const bool &force = false) { LOG("Mark message as viewed" << chatId << messageId); QVariantMap requestObject; requestObject.insert(_TYPE, "viewMessages"); requestObject.insert("chat_id", chatId); - requestObject.insert("force_read", false); + requestObject.insert("force_read", force); QVariantList messageIds; messageIds.append(messageId); requestObject.insert("message_ids", messageIds); @@ -468,6 +491,137 @@ void TDLibWrapper::getStickerSet(const QString &setId) requestObject.insert("set_id", setId); this->sendRequest(requestObject); } +void TDLibWrapper::getSupergroupMembers(const QString &groupId, const int &limit = 200, const int &offset = 0) +{ + LOG("Retrieving SupergroupMembers"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "getSupergroupMembers"); + requestObject.insert(_EXTRA, groupId); + requestObject.insert("supergroup_id", groupId); + requestObject.insert("offset", offset); + requestObject.insert("limit", limit); + this->sendRequest(requestObject); +} + +void TDLibWrapper::getGroupFullInfo(const QString &groupId, const bool &isSuperGroup) +{ + LOG("Retrieving GroupFullInfo"); + QVariantMap requestObject; + if(isSuperGroup) { + requestObject.insert(_TYPE, "getSupergroupFullInfo"); + requestObject.insert("supergroup_id", groupId); + } else { + requestObject.insert(_TYPE, "getBasicGroupFullInfo"); + requestObject.insert("basic_group_id", groupId); + } + requestObject.insert(_EXTRA, groupId); + this->sendRequest(requestObject); +} + +void TDLibWrapper::getUserFullInfo(const QString &userId) +{ + LOG("Retrieving UserFullInfo"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "getUserFullInfo"); + requestObject.insert(_EXTRA, userId); + requestObject.insert("user_id", userId); + this->sendRequest(requestObject); +} + +void TDLibWrapper::createPrivateChat(const QString &userId) +{ + LOG("Creating Private Chat"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "createPrivateChat"); + requestObject.insert("user_id", userId); + requestObject.insert(_EXTRA, "openDirectly"); //gets matched in qml + this->sendRequest(requestObject); +} + +void TDLibWrapper::getGroupsInCommon(const QString &userId, const int &limit, const int &offset) +{ + LOG("Retrieving Groups in Common"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "getGroupsInCommon"); + requestObject.insert(_EXTRA, userId); + requestObject.insert("user_id", userId); + requestObject.insert("offset", offset); + requestObject.insert("limit", limit); + this->sendRequest(requestObject); +} + +void TDLibWrapper::getUserProfilePhotos(const QString &userId, const int &limit, const int &offset) +{ + LOG("Retrieving User Profile Photos"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "getUserProfilePhotos"); + requestObject.insert(_EXTRA, userId); + requestObject.insert("user_id", userId); + requestObject.insert("offset", offset); + requestObject.insert("limit", limit); + this->sendRequest(requestObject); +} + +void TDLibWrapper::setChatPermissions(const QString &chatId, const QVariantMap &chatPermissions) +{ + LOG("Setting Chat Permissions"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setChatPermissions"); + requestObject.insert(_EXTRA, chatId); + requestObject.insert("chat_id", chatId); + requestObject.insert("permissions", chatPermissions); + this->sendRequest(requestObject); +} + +void TDLibWrapper::setChatSlowModeDelay(const QString &chatId, const int &delay) +{ + + LOG("Setting Chat Slow Mode Delay"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setChatSlowModeDelay"); + requestObject.insert("chat_id", chatId); + requestObject.insert("slow_mode_delay", delay); + this->sendRequest(requestObject); +} + +void TDLibWrapper::setChatDescription(const QString &chatId, const QString &description) +{ + LOG("Setting Chat Description"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setChatDescription"); + requestObject.insert("chat_id", chatId); + requestObject.insert("description", description); + this->sendRequest(requestObject); +} + +void TDLibWrapper::setChatTitle(const QString &chatId, const QString &title) +{ + LOG("Setting Chat Title"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setChatTitle"); + requestObject.insert("chat_id", chatId); + requestObject.insert("title", title); + this->sendRequest(requestObject); +} + +void TDLibWrapper::setBio(const QString &bio) +{ + LOG("Setting Bio"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "setBio"); + requestObject.insert("bio", bio); + this->sendRequest(requestObject); +} + +void TDLibWrapper::toggleSupergroupIsAllHistoryAvailable(const QString &groupId, const bool &isAllHistoryAvailable) +{ + LOG("Toggling SupergroupIsAllHistoryAvailable"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "toggleSupergroupIsAllHistoryAvailable"); + requestObject.insert("supergroup_id", groupId); + requestObject.insert("is_all_history_available", isAllHistoryAvailable); + this->sendRequest(requestObject); +} void TDLibWrapper::searchEmoji(const QString &queryString) { @@ -759,9 +913,9 @@ void TDLibWrapper::handleChatOnlineMemberCountUpdated(const QString &chatId, con emit chatOnlineMemberCountUpdated(chatId, onlineMemberCount); } -void TDLibWrapper::handleMessagesReceived(const QVariantList &messages) +void TDLibWrapper::handleMessagesReceived(const QVariantList &messages, const int &totalCount) { - emit messagesReceived(messages); + emit messagesReceived(messages, totalCount); } void TDLibWrapper::handleNewMessageReceived(const QString &chatId, const QVariantMap &message) @@ -814,6 +968,11 @@ void TDLibWrapper::handleChats(const QVariantMap &chats) emit this->chatsReceived(chats); } +void TDLibWrapper::handleChat(const QVariantMap &chat) +{ + emit this->chatReceived(chat); +} + void TDLibWrapper::handleRecentStickersUpdated(const QVariantList &stickerIds) { emit this->recentStickersUpdated(stickerIds); @@ -850,6 +1009,56 @@ void TDLibWrapper::handleEmojiSearchCompleted(const QString &queryString, const emit emojiSearchSuccessful(resultList); } +void TDLibWrapper::handleChatMembers(const QString &extra, const QVariantList &members, const int &totalMembers) +{ + emit this->chatMembersReceived(extra, members, totalMembers); +} + +void TDLibWrapper::handleUserFullInfo(const QVariantMap &userFullInfo) +{ + emit this->userFullInfoReceived(userFullInfo); +} + +void TDLibWrapper::handleUserFullInfoUpdated(const QString &userId, const QVariantMap &userFullInfo) +{ + emit this->userFullInfoUpdated(userId, userFullInfo); +} + +void TDLibWrapper::handleBasicGroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo) +{ + emit this->basicGroupFullInfoReceived(groupId, groupFullInfo); +} + +void TDLibWrapper::handleBasicGroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo) +{ + emit this->basicGroupFullInfoUpdated(groupId, groupFullInfo); +} + +void TDLibWrapper::handleSupergroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo) +{ + emit this->supergroupFullInfoReceived(groupId, groupFullInfo); +} + +void TDLibWrapper::handleSupergroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo) +{ + emit this->supergroupFullInfoUpdated(groupId, groupFullInfo); +} + +void TDLibWrapper::handleUserProfilePhotos(const QString &extra, const QVariantList &photos, const int &totalPhotos) +{ + emit this->userProfilePhotosReceived(extra, photos, totalPhotos); +} + +void TDLibWrapper::handleChatPermissionsUpdated(const QString &chatId, const QVariantMap permissions) +{ + emit this->chatPermissionsUpdated(chatId, permissions); +} + +void TDLibWrapper::handleChatTitleUpdated(const QString &chatId, const QString title) +{ + emit this->chatTitleUpdated(chatId, title); +} + void TDLibWrapper::setInitialParameters() { LOG("Sending initial parameters to TD Lib"); @@ -867,7 +1076,7 @@ void TDLibWrapper::setInitialParameters() QSettings hardwareSettings("/etc/hw-release", QSettings::NativeFormat); initialParameters.insert("device_model", hardwareSettings.value("NAME", "Unknown Mobile Device").toString()); initialParameters.insert("system_version", QSysInfo::prettyProductName()); - initialParameters.insert("application_version", "0.3"); + initialParameters.insert("application_version", "0.4"); // initialParameters.insert("use_test_dc", true); requestObject.insert("parameters", initialParameters); this->sendRequest(requestObject); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 6723470..d440b04 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Sebastian J. Wolf + Copyright (C) 2020 Sebastian J. Wolf and other contributors This file is part of Fernschreiber. @@ -113,8 +113,9 @@ public: Q_INVOKABLE void downloadFile(const QString &fileId); Q_INVOKABLE void openChat(const QString &chatId); Q_INVOKABLE void closeChat(const QString &chatId); + Q_INVOKABLE void leaveChat(const QString &chatId); Q_INVOKABLE void getChatHistory(const QString &chatId, const qlonglong &fromMessageId = 0, const int &offset = 0, const int &limit = 50, const bool &onlyLocal = false); - Q_INVOKABLE void viewMessage(const QString &chatId, const QString &messageId); + Q_INVOKABLE void viewMessage(const QString &chatId, const QString &messageId, const bool &force); Q_INVOKABLE void sendTextMessage(const QString &chatId, const QString &message, const QString &replyToMessageId = "0"); Q_INVOKABLE void sendPhotoMessage(const QString &chatId, const QString &filePath, const QString &message, const QString &replyToMessageId = "0"); Q_INVOKABLE void sendVideoMessage(const QString &chatId, const QString &filePath, const QString &message, const QString &replyToMessageId = "0"); @@ -129,6 +130,18 @@ public: Q_INVOKABLE void getRecentStickers(); Q_INVOKABLE void getInstalledStickerSets(); Q_INVOKABLE void getStickerSet(const QString &setId); + Q_INVOKABLE void getSupergroupMembers(const QString &groupId, const int &limit, const int &offset); + Q_INVOKABLE void getGroupFullInfo(const QString &groupId, const bool &isSuperGroup); + Q_INVOKABLE void getUserFullInfo(const QString &userId); + Q_INVOKABLE void createPrivateChat(const QString &userId); + Q_INVOKABLE void getGroupsInCommon(const QString &userId, const int &limit, const int &offset); + Q_INVOKABLE void getUserProfilePhotos(const QString &userId, const int &limit, const int &offset); + Q_INVOKABLE void setChatPermissions(const QString &chatId, const QVariantMap &chatPermissions); + Q_INVOKABLE void setChatSlowModeDelay(const QString &chatId, const int &delay); + Q_INVOKABLE void setChatDescription(const QString &chatId, const QString &description); + Q_INVOKABLE void setChatTitle(const QString &chatId, const QString &title); + Q_INVOKABLE void setBio(const QString &bio); + Q_INVOKABLE void toggleSupergroupIsAllHistoryAvailable(const QString &groupId, const bool &isAllHistoryAvailable); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); @@ -155,7 +168,7 @@ signals: void basicGroupUpdated(qlonglong groupId); void superGroupUpdated(qlonglong groupId); void chatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount); - void messagesReceived(const QVariantList &messages); + void messagesReceived(const QVariantList &messages, const int &totalCount); void newMessageReceived(const QString &chatId, const QVariantMap &message); void copyToDownloadsSuccessful(const QString &fileName, const QString &filePath); void copyToDownloadsError(const QString &fileName, const QString &filePath); @@ -168,12 +181,23 @@ signals: void messageContentUpdated(const QString &chatId, const QString &messageId, const QVariantMap &newContent); void messagesDeleted(const QString &chatId, const QVariantList &messageIds); void chatsReceived(const QVariantMap &chats); + void chatReceived(const QVariantMap &chat); void recentStickersUpdated(const QVariantList &stickerIds); void stickersReceived(const QVariantList &stickers); void installedStickerSetsUpdated(const QVariantList &stickerSetIds); void stickerSetsReceived(const QVariantList &stickerSets); void stickerSetReceived(const QVariantMap &stickerSet); void emojiSearchSuccessful(const QVariantList &result); + void chatMembersReceived(const QString &extra, const QVariantList &members, const int &totalMembers); + void userFullInfoReceived(const QVariantMap &userFullInfo); + void userFullInfoUpdated(const QString &userId, const QVariantMap &userFullInfo); + void basicGroupFullInfoReceived(const QString &groupId, const QVariantMap &groupFullInfo); + void supergroupFullInfoReceived(const QString &groupId, const QVariantMap &groupFullInfo); + void basicGroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); + void supergroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); + void userProfilePhotosReceived(const QString &extra, const QVariantList &photos, const int &totalPhotos); + void chatPermissionsUpdated(const QString &chatId, const QVariantMap &permissions); + void chatTitleUpdated(const QString &chatId, const QString &title); public slots: void handleVersionDetected(const QString &version); @@ -193,7 +217,7 @@ public slots: void handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void handleSuperGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void handleChatOnlineMemberCountUpdated(const QString &chatId, const int &onlineMemberCount); - void handleMessagesReceived(const QVariantList &messages); + void handleMessagesReceived(const QVariantList &messages, const int &totalCount); void handleNewMessageReceived(const QString &chatId, const QVariantMap &message); void handleMessageInformation(const QString &messageId, const QVariantMap &message); void handleMessageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message); @@ -204,12 +228,23 @@ public slots: void handleMessageContentUpdated(const QString &chatId, const QString &messageId, const QVariantMap &newContent); void handleMessagesDeleted(const QString &chatId, const QVariantList &messageIds); void handleChats(const QVariantMap &chats); + void handleChat(const QVariantMap &chat); void handleRecentStickersUpdated(const QVariantList &stickerIds); void handleStickers(const QVariantList &stickers); void handleInstalledStickerSetsUpdated(const QVariantList &stickerSetIds); void handleStickerSets(const QVariantList &stickerSets); void handleStickerSet(const QVariantMap &stickerSet); void handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList); + void handleChatMembers(const QString &extra, const QVariantList &members, const int &totalMembers); + void handleUserFullInfo(const QVariantMap &userFullInfo); + void handleUserFullInfoUpdated(const QString &userId, const QVariantMap &userFullInfo); + void handleBasicGroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo); + void handleBasicGroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); + void handleSupergroupFullInfo(const QString &groupId, const QVariantMap &groupFullInfo); + void handleSupergroupFullInfoUpdated(const QString &groupId, const QVariantMap &groupFullInfo); + void handleUserProfilePhotos(const QString &extra, const QVariantList &photos, const int &totalPhotos); + void handleChatPermissionsUpdated(const QString &chatId, const QVariantMap permissions); + void handleChatTitleUpdated(const QString &chatId, const QString title); private: void setInitialParameters(); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 90804d6..780593a 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + Stummschaltung des Chats aufheben + + + Mute Chat + Chat stummschalten + + + Unknown + Unbekannt + + + The Invite Link has been copied to the clipboard. + Der Einladungslink wurde in die Zwischenablage kopiert. + + + %1 members, %2 online + %1 Mitglieder, %2 online + + + %1 subscribers + %1 Abonnenten + + + %1 members + %1 Mitglieder + + + Leave Group + Gruppe verlassen + + + Leaving chat + Verlasse Gruppe + + + Info + group or user infotext header + Info + + + Phone Number + user phone number header + Telefonnummer + + + Invite Link + header + Einladungslink + + + There is no information text available, yet. + Es gibt noch keinen Informationstext. + + + Chat Title + group title header + Chattitel + + + Enter 1-128 characters + Geben Sie 1-126 Zeichen ein + + + + ChatInformationTabItemMembersGroups + + You + Sie + + + Loading common chats… + chats you have in common with a user + Lade gemeinsame Chats… + + + Unknown + Unbekannt + + + Groups + Button: groups in common (short) + Gruppen + + + Members + Button: Group Members + Mitglieder + + + Loading group members… + Lade Gruppenmitglieder… + + + You don't have any groups in common with this user. + Sie haben mit diesem Benutzer keine gemeinsamen Gruppen. + + + This group is empty. + Diese Gruppe ist leer. + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Einstellungen + + + + ChatListViewItem + + Unknown + Unbekannt + + + You + Sie + + + Unmute Chat + Stummschaltung des Chats aufheben + + + Mute Chat + Chat stummschalten + + + User Info + Benutzerinfos + + + Group Info + Gruppeninfos + + + Mark all messages as read + Nachrichten als gelesen markieren + + ChatPage @@ -97,30 +241,6 @@ Your message Ihre Nachricht - - was never online - war niemals online - - - offline, last online: last month - offline, zuletzt online im letzten Monat - - - offline, last online: last week - offline, zuletzt online in der letzten Woche - - - offline, last online: %1 - offline, zuletzt online: %1 - - - online - online - - - offline, was recently online - offline, war neulich online - %1 members, %2 online %1 Mitglieder, %2 online @@ -177,6 +297,10 @@ Forwarded Message Weitergeleitete Nachricht + + This chat is empty. + Dieser Chat ist leer. + CoverPage @@ -232,6 +356,74 @@ Dokument öffnen + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + Berechtigungen der Gruppenmitglieder + + + Send Messages + member permission + Nachrichten senden + + + Send Media Messages + member permission + Medien senden + + + Send Other Messages + member permission + Andere Nachrichten senden + + + Add Web Page Previews + member permission + Webseiten-Vorschau hinzufügen + + + Change Chat Info + member permission + Chatinformation ändern + + + Invite Users + member permission + Benutzer einladen + + + Pin Messages + member permission + Nachrichten anpinnen + + + New Members + what can new group members do + Neue Mitglieder + + + New members can see older messages + member permission + Neue Mitglieder können ältere Nachrichten sehen + + + + EditSuperGroupSlowModeColumn + + Slow Mode + Langsamer Modus + + + Off + Aus + + + Set how long every chat member has to wait between Messages + Legen Sie fest, wie lange jedes Mitglied zwischen zwei Nachrichten warten muss + + FernschreiberUtils @@ -341,6 +533,15 @@ sent a venue hat einen Ort geschickt + + changed the chat title + myself + haben den Chattitel geändert + + + changed the chat title + hat den Chattitel geändert + ImagePage @@ -422,6 +623,10 @@ User Registration Benutzerregistrierung + + Use the international format, e.g. %1 + Nutzen Sie das internationale Format, z.B. %1 + LocationPreview @@ -467,22 +672,10 @@ Unknown Unbekannt - - You - Sie - Loading chat list... Lade Chatliste... - - Unmute Chat - Stummschaltung des Chats aufheben - - - Mute Chat - Chat stummschalten - Settings Einstellungen @@ -718,5 +911,58 @@ myself haben diesen Chat verlassen + + was never online + war niemals online + + + offline, last online: last month + offline, zuletzt online im letzten Monat + + + offline, last online: last week + offline, zuletzt online in der letzten Woche + + + offline, last online: %1 + offline, zuletzt online: %1 + + + online + online + + + offline, was recently online + offline, war neulich online + + + Admin + channel user role + Administrator + + + Banned + channel user role + Verbannt + + + Creator + channel user role + Urheber + + + Restricted + channel user role + Eingeschränkt + + + changed the chat title to %1 + myself + haben den Chattitel zu %1 geändert + + + changed the chat title to %1 + hat den Chattitel zu %1 geändert + diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 0398fdc..c85a3da 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + habilitar notificación + + + Mute Chat + deshabilitar notificación + + + Unknown + + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + %1 miembros, %2 en línea + + + %1 subscribers + %1 suscriptores + + + %1 members + %1 miembros + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Ajustes + + + + ChatListViewItem + + Unknown + + + + You + + + + Unmute Chat + habilitar notificación + + + Mute Chat + deshabilitar notificación + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message Escribir mensaje - - was never online - nunca estuvo en línea - - - offline, last online: last month - sin línea, hace en línea: hace 1 mes - - - offline, last online: last week - sin línea, hace en línea: hace 1 semana - - - offline, last online: %1 - sin línea, hace en línea: %1 - - - online - en línea - - - offline, was recently online - sin línea, estuvo en línea - %1 members, %2 online %1 miembros, %2 en línea @@ -177,6 +297,10 @@ Forwarded Message Mensaje reenviado + + This chat is empty. + + CoverPage @@ -232,6 +356,74 @@ Abrir Documento + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils @@ -341,6 +533,15 @@ sent a venue envió un lugar + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -422,6 +623,10 @@ User Registration Registro de usuario + + Use the international format, e.g. %1 + + LocationPreview @@ -467,22 +672,10 @@ Unknown desconocido - - You - Usted - Loading chat list... cargando lista de charla... - - Unmute Chat - Habilitar notificación - - - Mute Chat - Deshabilitar notificación - Settings Ajustes @@ -718,5 +911,58 @@ myself dejé esta charla + + was never online + nunca estuvo en línea + + + offline, last online: last month + sin línea, hace en línea: hace 1 mes + + + offline, last online: last week + sin línea, hace en línea: hace 1 semana + + + offline, last online: %1 + sin línea, hace en línea: %1 + + + online + en línea + + + offline, was recently online + sin línea, estuvo en línea + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + + diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index b03cc86..6645016 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + Poista keskustelun vaimennus + + + Mute Chat + Vaimenna keskustelu + + + Unknown + Tuntematon + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + %1 jäsentä, %2 paikalla + + + %1 subscribers + %1 tilaajaa + + + %1 members + %1 jäsentä + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + Tuntematon + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + Sinä + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Asetukset + + + + ChatListViewItem + + Unknown + Tuntematon + + + You + Sinä + + + Unmute Chat + Poista keskustelun vaimennus + + + Mute Chat + Vaimenna keskustelu + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message Viestisi - - was never online - Ei ole ollut koskaan paikalla - - - offline, last online: last month - Poissa. Nähty viimeksi: viime kuussa - - - offline, last online: last week - Poissa. Nähty viimeksi: viime viikolla - - - offline, last online: %1 - Poissa. Nähty viimeksi: %1 - - - online - paikalla - - - offline, was recently online - poissa, oli hetki sitten paikalla - %1 members, %2 online %1 jäsentä, %2 paikalla @@ -177,6 +297,10 @@ Forwarded Message + + This chat is empty. + + CoverPage @@ -232,6 +356,74 @@ Avaa dokumentti + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils @@ -341,6 +533,15 @@ Unsupported message: %1 Viestityyppiä ei tueta: %1 + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -422,6 +623,10 @@ Register User Rekisteröi käyttäjätili + + Use the international format, e.g. %1 + + LocationPreview @@ -467,22 +672,10 @@ Unknown Tuntematon - - You - Sinä - Loading chat list... Ladataan keskustelulistaa... - - Unmute Chat - Poista keskustelun vaimennus - - - Mute Chat - Vaimenna keskustelu - Settings Asetukset @@ -718,5 +911,58 @@ myself poistuit keskustelusta + + was never online + Ei ole ollut koskaan paikalla + + + offline, last online: last month + Poissa. Nähty viimeksi: viime kuussa + + + offline, last online: last week + Poissa. Nähty viimeksi: viime viikolla + + + offline, last online: %1 + Poissa. Nähty viimeksi: %1 + + + online + paikalla + + + offline, was recently online + poissa, oli hetki sitten paikalla + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + + diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 37d8ddf..5955b06 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + Csevegés némítás feloldása + + + Mute Chat + Csevegés némítása + + + Unknown + Ismeretlen + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + %1 tag, %2 online + + + %1 subscribers + %1 feliratkozott + + + %1 members + %1 tag + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + Ismeretlen + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + Te + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Beállítások + + + + ChatListViewItem + + Unknown + Ismeretlen + + + You + Te + + + Unmute Chat + Csevegés némítás feloldása + + + Mute Chat + Csevegés némítása + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message Üzeneted - - was never online - soha nem volt online - - - offline, last online: last month - offline, utoljára online: múlt hónapban - - - offline, last online: last week - offline, utoljára online: múlt héten - - - offline, last online: %1 - offline, utoljára online: %1 - - - online - online - - - offline, was recently online - offline, nemrégen volt online - %1 members, %2 online %1 tag, %2 online @@ -177,6 +297,10 @@ Forwarded Message + + This chat is empty. + + CoverPage @@ -232,6 +356,74 @@ Dokumentum megyitása + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils @@ -341,6 +533,15 @@ sent a venue + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -422,6 +623,10 @@ User Registration + + Use the international format, e.g. %1 + + LocationPreview @@ -467,22 +672,10 @@ Unknown Ismeretlen - - You - Te - Loading chat list... Csevegés lista betöltése... - - Unmute Chat - Csevegés némítás feloldása - - - Mute Chat - Csevegés némítása - Settings Beállítások @@ -718,5 +911,58 @@ myself kilépett a csevegésből + + was never online + soha nem volt online + + + offline, last online: last month + offline, utoljára online: múlt hónapban + + + offline, last online: last week + offline, utoljára online: múlt héten + + + offline, last online: %1 + offline, utoljára online: %1 + + + online + online + + + offline, was recently online + offline, nemrégen volt online + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + + diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 5cf2b41..6d212a5 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Leave Group + + + + Leaving chat + + + + Unmute Chat + Riattiva suoni chat + + + Mute Chat + Silenzia chat + + + Unknown + Sconosciuto + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + %1 membri, %2 online + + + %1 subscribers + %1 abbonati + + + %1 members + %1 membri + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading common chats… + chats you have in common with a user + + + + Loading group members… + + + + You + Tu + + + Unknown + Sconosciuto + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Impostazioni + + + + ChatListViewItem + + Unknown + Sconosciuto + + + You + Tu + + + Unmute Chat + Riattiva suoni chat + + + Mute Chat + Silenzia chat + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message Tuo messaggio - - was never online - mai online - - - offline, last online: last month - offline, ultimo accesso il mese scorso - - - offline, last online: last week - offline, ultimo accesso la settimana scorsa - - - offline, last online: %1 - offline, ultimo accesso: %1 - - - online - online - - - offline, was recently online - offline, online di recente - %1 members, %2 online %1 membri, %2 online @@ -177,6 +297,10 @@ Forwarded Message Messaggio inoltrato + + This chat is empty. + + CoverPage @@ -232,6 +356,74 @@ Apri documento + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils @@ -341,6 +533,15 @@ sent a venue ha inviato la posizione + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -422,6 +623,10 @@ User Registration Registrazione utente + + Use the international format, e.g. %1 + + LocationPreview @@ -467,22 +672,10 @@ Unknown Sconosciuto - - You - Tu - Loading chat list... Carica lista chat... - - Unmute Chat - Riattiva suoni chat - - - Mute Chat - Silenzia chat - Settings Impostazioni @@ -718,5 +911,58 @@ myself hanno lasciato questa chat + + was never online + mai online + + + offline, last online: last month + offline, ultimo accesso il mese scorso + + + offline, last online: last week + offline, ultimo accesso la settimana scorsa + + + offline, last online: %1 + offline, ultimo accesso: %1 + + + online + online + + + offline, was recently online + offline, online di recente + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + + diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 2bd2d43..83b1565 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + Wyłącz wyciszenie czatu + + + Mute Chat + Wycisz czat + + + Unknown + Nieznany + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + $1 członków, %2 online + + + %1 subscribers + %1 subskrybentów + + + %1 members + %1 czlonków + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + Nieznany + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + Ty + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Ustawienia + + + + ChatListViewItem + + Unknown + Nieznany + + + You + Ty + + + Unmute Chat + Wyłącz wyciszenie czatu + + + Mute Chat + Wycisz czat + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message Twoja wiadomość - - was never online - nigdy nie był online - - - offline, last online: last month - offline, ostatnio online: w zeszłym miesiącu - - - offline, last online: last week - offline, ostatnio online: w zeszłym tygodniu - - - offline, last online: %1 - offline, ostatnio online: %1 - - - online - online - - - offline, was recently online - offline, był niedawno online - %1 members, %2 online $1 członków, %2 online @@ -177,6 +297,10 @@ Forwarded Message + + This chat is empty. + + CoverPage @@ -232,16 +356,84 @@ Otwórz dokument + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils sent a picture myself - wyślij obraz + wysłałem obraz sent a picture - wyślij obraz + wysłał obraz sent a video @@ -250,87 +442,87 @@ sent a video - wyślij film + wysłał film sent an animation myself - wyślij animację + wysłałem animację sent an animation - wyślij animację + wysłał animację sent a voice note - wyślij notatke głosową + wysłał notatke głosową sent a document myself - wyślij dokument + wysłałem dokument sent a document - wyślij dokument + wysłał dokument sent a location myself - wyślij lokalizację + wysłałem lokalizację sent a location - wyślij lokalizację + wysłał lokalizację have registered with Telegram myself - + zostałem zarejestrowany w Telegram has registered with Telegram - zarejestrował się w Telegramie + zarejestrował się w Telegramie joined this chat myself - dołaczył do tego czatu + dołaczyłem do tego czatu joined this chat - dołaczył do tego czatu + dołaczył do tego czatu were added to this chat myself - + zostałem dodany do tego czatu was added to this chat - został dodany do tego czatu + został dodany do tego czatu left this chat myself - opuścił ten czat + opuściłem ten czat left this chat - opuścił ten czat + opuścił ten czat Unsupported message: %1 - Nieobsługiwana wiadomość: %1 + Nieobsługiwana wiadomość: %1 Sticker: %1 - Naklejka: %1 + Naklejka: %1 sent a voice note myself - wyślij notatke głosową + wysłałem notatke głosową sent a venue @@ -341,6 +533,15 @@ sent a venue + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -408,18 +609,22 @@ Register User - + Zarejestruj użytkownika Enter your First Name - + Wprowadź swoje imię Enter your Last Name - + wprowadź swoje nazwisko User Registration + Rejestracja użytkownika + + + Use the international format, e.g. %1 @@ -427,7 +632,7 @@ LocationPreview Install Pure Maps to inspect this location. - + Zainstaluj Pure Maps, aby sprawdzić tę lokalizację. @@ -467,29 +672,17 @@ Unknown Nieznany - - You - Ty - Loading chat list... Ładowanie listy czatu... - - Unmute Chat - Wyłącz wyciszenie czatu - - - Mute Chat - Wycisz czat - Settings Ustawienia You don't have any chats yet. - + Nie masz jeszcze żadnych czatów. @@ -512,11 +705,11 @@ Appearance - + Wygląd Show stickers as images - + Pokaż naklejki jako obrazy Show background for stickers and align them centrally like images @@ -547,11 +740,11 @@ StickerPicker Recently used - + Ostatnio użyty Loading stickers... - + Ładowanie naklejek... @@ -662,27 +855,27 @@ sent a picture myself - wyślij obraz + wysłałem obraz sent a video myself - wyślij film + wysłałem film sent an animation myself - wyślij animację + wysłałem animację sent an audio myself - wyślij dźwięk + wysłałem dźwięk sent a voice note myself - wyślij notatke głosową + wysłałem notatke głosową sent a document @@ -701,22 +894,75 @@ have registered with Telegram - + został zarejestowany w Telegram joined this chat myself - dołaczył do tego czatu + dołaczyłem do tego czatu were added to this chat myself - + zostałem dodany do czatu left this chat myself - opuścił ten czat + opuściłem ten czat + + + was never online + nigdy nie był online + + + offline, last online: last month + offline, ostatnio online: w zeszłym miesiącu + + + offline, last online: last week + offline, ostatnio online: w zeszłym tygodniu + + + offline, last online: %1 + offline, ostatnio online: %1 + + + online + online + + + offline, was recently online + offline, był niedawno online + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 7b1f303..263552a 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + Включить уведомления + + + Mute Chat + Выключить уведомления + + + Unknown + + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + %1 участников, %2 онлайн + + + %1 subscribers + %1 подписчиков + + + %1 members + %1 участников + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + Вы + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Настройки + + + + ChatListViewItem + + Unknown + + + + You + Вы + + + Unmute Chat + Включить уведомления + + + Mute Chat + Выключить уведомления + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message Ваше сообщение - - was never online - никогда не был(а) онлайн - - - offline, last online: last month - офлайн, был(а) онлайн: в прошлом месяце - - - offline, last online: last week - офлайн, был(а) онлайн: на прошлой неделе - - - offline, last online: %1 - офлайн, был(а) онлайн: %1 - - - online - онлайн - - - offline, was recently online - офлайн, недавно был(а) онлайн - %1 members, %2 online %1 участников, %2 онлайн @@ -177,6 +297,10 @@ Forwarded Message Пересланное сообщение + + This chat is empty. + + CoverPage @@ -232,6 +356,74 @@ Открыть документ + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils @@ -341,6 +533,15 @@ sent a venue отправил(а) место встречи + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -422,6 +623,10 @@ Register User Зарегистрироваться + + Use the international format, e.g. %1 + + LocationPreview @@ -467,22 +672,10 @@ Unknown Неизвестный - - You - Вы - Loading chat list... Загрузка чатов... - - Unmute Chat - Включить уведомления - - - Mute Chat - Выключить уведомления - Settings Настройки @@ -718,5 +911,58 @@ myself покинул(а) чат + + was never online + никогда не был(а) онлайн + + + offline, last online: last month + офлайн, был(а) онлайн: в прошлом месяце + + + offline, last online: last week + офлайн, был(а) онлайн: на прошлой неделе + + + offline, last online: %1 + офлайн, был(а) онлайн: %1 + + + online + онлайн + + + offline, was recently online + офлайн, недавно был(а) онлайн + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + + diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts new file mode 100644 index 0000000..f447068 --- /dev/null +++ b/translations/harbour-fernschreiber-sv.ts @@ -0,0 +1,968 @@ + + + + + AboutPage + + About Fernschreiber + Om Fernschreiber + + + A Telegram client for Sailfish OS + En Telegram-klient för Sailfish OS + + + Send E-Mail + Skicka e-post + + + Licensed under GNU GPLv3 + Licensierad under GNU GPLv3 + + + Sources on GitHub + Källor på GitHub + + + Terms of Service + Tjänstevillkor + + + Privacy Policy + Sekretesspolicy + + + Credits + Medverkande + + + This project uses the Telegram Database Library (TDLib). Thanks for making it available under the conditions of the Boost Software License 1.0! + Detta projekt använder Telegram Database Library (TDLib). Tack för att det gjorts tillgängligt under villkoren för Boost Software License 1.0! + + + Open Telegram Database Library on GitHub + Öppna Telegram Database Library på GitHub + + + About Telegram + Om Telegram + + + This product uses the Telegram API but is not endorsed or certified by Telegram. + Denna produkt använder Telegrams API men är inte godkänt eller certifierat av Telegram. + + + TDLib version %1 + TDLib version %1 + + + Logged in as %1 + Inloggad som %1 + + + Phone number: +%1 + Telefonnummer: +%1 + + + This project uses twemoji. Copyright 2018 Twitter, Inc. and other contributors. Thanks for making it available under the conditions of the MIT License (coding) and CC-BY 4.0 (graphics)! + Detta projekt använder twemoji. Copyright 2018 Twitter, Inc. och andra medverkande. Tack för att det gjorts tillgängligt under villkoren för MIT License (kodning) och CC-BY 4.0 (grafik)! + + + Open twemoji on GitHub + Öppna twemoji på GitHub + + + By Sebastian J. Wolf and <a href="https://github.com/Wunderfitz/harbour-fernschreiber#contributions">other contributors</a> + Av Sebastian J. Wolf och <a href="https://github.com/Wunderfitz/harbour-fernschreiber#contributions">andra medverkande</a> + + + + BackgroundProgressIndicator + + %1 % + %1 % + + + %1 + %1 + + + + ChatInformationPage + + Unmute Chat + Slå på chatten + + + Mute Chat + Stäng av chatten + + + Unknown + Okänd + + + The Invite Link has been copied to the clipboard. + Inbjudningslänken har kopierats till urklipp. + + + %1 members, %2 online + %1 medlemmar, %2 inloggade + + + %1 subscribers + %1 prenumeranter + + + %1 members + %1 medlemmar + + + Leave Group + Lämna gruppen + + + Leaving chat + Lämnar chatten + + + Info + group or user infotext header + Info + + + Phone Number + user phone number header + Telefonnummer + + + Invite Link + header + Inbjudningslänk + + + There is no information text available, yet. + Det finns ingen informationstext än. + + + Chat Title + group title header + Chattnamn + + + Enter 1-128 characters + Ange 1-128 tecken + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + Läser in gemensamma chattar... + + + Unknown + Okänd + + + Groups + Button: groups in common (short) + Grupper + + + Members + Button: Group Members + Medlemmar + + + Loading group members… + Läser in gruppmedlemmar... + + + You + Du + + + You don't have any groups in common with this user. + Du har inga grupper gemensamt med denna användare. + + + This group is empty. + Denna grupp är tom. + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + Inställningar + + + + ChatListViewItem + + Unknown + Okänd + + + You + Du + + + Unmute Chat + Slå på chatten + + + Mute Chat + Stäng av chatten + + + User Info + Användarinfo + + + Group Info + Gruppinfo + + + Mark all messages as read + Markera alla meddelanden som lästa + + + + ChatPage + + Unknown + Okänd + + + Your message + Ditt meddelande + + + %1 members, %2 online + %1 medlem(mar), %2 inloggad(e) + + + %1 members + %1 medlem(mar) + + + %1 subscribers + %1 prenumerant(er) + + + Reply to Message + Svara på meddelandet + + + You + Du + + + Loading messages... + Läser in meddelanden... + + + Unmute Chat + Slå på chatten + + + Mute Chat + Stäng av chatten + + + Edit Message + Redigera meddelandet + + + edited + redigerade + + + Deleting message + Tar bort meddelande + + + Delete Message + Ta bort meddelandet + + + Uploading... + Ladda upp... + + + Forwarded Message + Vidarebefordrat meddelande + + + This chat is empty. + Denna chatt är tom. + + + + CoverPage + + unread message + oläst meddelande + + + unread messages + olästa meddelanden + + + in + i + + + Waiting for network... + Väntar på nätverket... + + + Connecting to network... + Ansluter till nätverket... + + + Connecting to proxy... + Ansluter till proxy... + + + Connected + Ansluten + + + Updating content... + Uppdaterar innehåll... + + + chat + chatt + + + chats + chattar + + + + DocumentPreview + + Download Document + Ladda ner dokument + + + Open Document + Öppna dokument + + + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + Gruppmedlemmars rättigheter + + + Send Messages + member permission + Skicka meddelanden + + + Send Media Messages + member permission + Skicka mediameddelanden + + + Send Other Messages + member permission + Skicka andra meddelanden + + + Add Web Page Previews + member permission + Lägga till förhandsvisning av webbsida + + + Change Chat Info + member permission + Ändra chattinformation + + + Invite Users + member permission + Bjuda in användare + + + Pin Messages + member permission + Fästa meddelanden + + + New Members + what can new group members do + Nya medlemmar + + + New members can see older messages + member permission + Nya medlemmar kan se gamla meddelanden + + + + EditSuperGroupSlowModeColumn + + Slow Mode + Långsamt läge + + + Off + Av + + + Set how long every chat member has to wait between Messages + Ange hur länge varje chatmedlem måste vänta mellan meddelanden + + + + FernschreiberUtils + + sent a picture + myself + skickade en bild + + + sent a picture + skickade en bild + + + sent a video + myself + skickade en video + + + sent a video + skickade en video + + + sent an animation + myself + skickade en animering + + + sent an animation + skickade en animering + + + sent a voice note + skickade en röstanteckning + + + sent a document + myself + skickade ett dokument + + + sent a document + skickade ett dokument + + + sent a location + myself + skickade en plats + + + sent a location + Skickade en plats + + + have registered with Telegram + myself + har registrerats på Telegram + + + has registered with Telegram + har registrerats på Telegram + + + joined this chat + myself + anslöt till denna chat + + + joined this chat + anslöt till denna chat + + + were added to this chat + myself + lades till i denna chatt + + + was added to this chat + lades till i denna chatt + + + left this chat + myself + lämnade denna chatt + + + left this chat + lämnade denna chatt + + + Unsupported message: %1 + Mededelande som inte stöds: %1 + + + Sticker: %1 + Dekal: %1 + + + sent a voice note + myself + skickade en röstanteckning + + + sent a venue + myself + skickade en mötesplats + + + sent a venue + skickade en mötesplats + + + changed the chat title + myself + ändrade chattnamnet + + + changed the chat title + ändrade chattnamnet + + + + ImagePage + + Download Picture + Ladda ner bild + + + Download of %1 successful. + Nerladdning av %1 slutförd. + + + Download failed. + Nerladdningen misslyckades. + + + + InReplyToRow + + You + Du + + + + InitializationPage + + OK + OK + + + Welcome to Fernschreiber! + Välkommen till Fernschreiber! + + + Please enter your phone number to continue. + Ange ditt telefonnummer för att förtsätta. + + + Continue + Fortsätt + + + Please enter the code that you received: + Ange koden du mottog: + + + Loading... + Läser in... + + + Unable to authenticate you with the entered code. + Det gick inte att autentisera dig med angiven kod. + + + Enter code again + Ange koden igen + + + Restart authentication + Starta om autentisering + + + Please enter your password: + Ange ditt lösenord: + + + User Registration + Användarregistrering + + + Enter your First Name + Ange ditt förnamn + + + Enter your Last Name + Ange ditt efternamn + + + Register User + Registrera användaren + + + Use the international format, e.g. %1 + Använd internationellt format, t.ex. %1 + + + + LocationPreview + + Install Pure Maps to inspect this location. + Installera Pure Maps för att inspektera den här platsen. + + + + NotificationManager + + %1 unread messages + %1 oläst(a) meddelande(n) + + + + OverviewPage + + About Fernschreiber + Om Fernschreiber + + + Fernschreiber + Fernschreiber + + + Waiting for network... + Väntar på nätverk... + + + Connecting to network... + Ansluter till nätverket... + + + Connecting to proxy... + Ansluter till proxy... + + + Updating content... + Uppdaterar innehåll... + + + Unknown + Okänd + + + Loading chat list... + Läser in chattlistan... + + + Settings + Inställningar + + + You don't have any chats yet. + Du har inga chattar än. + + + + SettingsPage + + Settings + Inställningar + + + Behavior + Beteende + + + Send message by enter + Skicka meddelanden med retur + + + Send your message by pressing the enter key + Skicka meddelanden genom att trycka på returknappen + + + Appearance + Utseende + + + Show stickers as images + Visa dekaler som bilder + + + Show background for stickers and align them centrally like images + Visa bakgrund för dekaler och justera dem centralt som bilder + + + Notification feedback + Aviseringsåterkoppling + + + All events + Alla händelser + + + Only new events + Endast nya händelser + + + None + Inget + + + Use non-graphical feedback (sound, vibration) for notifications + Använd icke-grafisk återkoppling (ljud, vibration) för avisering + + + + StickerPicker + + Recently used + Nyligen använt + + + Loading stickers... + Läser in dekaler... + + + + VideoPage + + Download Video + Ladda ner video + + + Download of %1 successful. + Nerladdning av %1 slutförd. + + + Download failed. + Nerladdning misslyckades. + + + + functions + + Video: %1 + Video: %1 + + + has registered with Telegram + har registrerats i Telegram + + + Picture: %1 + Bild: %1 + + + Sticker: %1 + Dekal: %1 + + + Audio: %1 + Ljud: %1 + + + Voice Note: %1 + Ljudmeddelande: %1 + + + Animation: %1 + Animering: %1 + + + Unsupported message: %1 + Meeddelande som inte stöds: %1 + + + Document: %1 + Dokument: %1 + + + sent a picture + skickade en bild + + + sent a video + skickade en video + + + sent an animation + skickade en animering + + + sent an audio + skickade en ljudfil + + + sent a voice note + skickade ett röstanteckning + + + sent a document + skickade ett dokument + + + sent a location + skickade en plats + + + joined this chat + anslöt till den här chatten + + + was added to this chat + lades till i den här chatten + + + left this chat + lämnade den här chatten + + + %1M + %1M + + + %1K + %1K + + + sent a venue + skickade en mötesplats + + + sent a picture + myself + skickade en bild + + + sent a video + myself + skickade en video + + + sent an animation + myself + skickade en animering + + + sent an audio + myself + skickade en ljudfil + + + sent a voice note + myself + skickade en röstanteckning + + + sent a document + myself + skickade ett dokument + + + sent a location + myself + skickade en plats + + + sent a venue + myself + skickade en mötesplats + + + have registered with Telegram + har registrerats i Telegram + + + joined this chat + myself + anslöt till den här chatten + + + were added to this chat + myself + lades till i den här chatten + + + left this chat + myself + lämnade den här chatten + + + was never online + var aldrig inloggad + + + offline, last online: last month + utloggad, inloggad senast: Förra månaden + + + offline, last online: last week + utloggad, inloggad senast: Förra veckan + + + offline, last online: %1 + utloggad, inloggad senast: %1 + + + online + utloggad + + + offline, was recently online + utloggad, var nyligen inloggad + + + Admin + channel user role + Admin + + + Banned + channel user role + Bannlyst + + + Creator + channel user role + Skapare + + + Restricted + channel user role + Begränsad + + + changed the chat title to %1 + myself + ändrade chattnamnet till %1 + + + changed the chat title to %1 + ändrade chattnamnet till %1 + + + diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 25b5912..a18810d 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -49,7 +49,7 @@ This product uses the Telegram API but is not endorsed or certified by Telegram. - 该项目使用 Telegram API ,但未被 Telegram 批准及背书。 + 该项目使用 Telegram API ,但未得到 Telegram 批准或背书。 TDLib version %1 @@ -61,7 +61,7 @@ Phone number: +%1 - 电话号码:+%1 + 电话号码:+%1 This project uses twemoji. Copyright 2018 Twitter, Inc. and other contributors. Thanks for making it available under the conditions of the MIT License (coding) and CC-BY 4.0 (graphics)! @@ -73,7 +73,7 @@ By Sebastian J. Wolf and <a href="https://github.com/Wunderfitz/harbour-fernschreiber#contributions">other contributors</a> - 开发者为 Sebastian J. Wolf 及 <ahref="https://github.com/Wunderfitz/harbour-fernschreiber#contributions">其他贡献者</a> + 开发者 Sebastian J. Wolf and <a href="https://github.com/Wunderfitz/harbour-fernschreiber#contributions">其它贡献者</a> @@ -87,6 +87,150 @@ %1 + + ChatInformationPage + + Unmute Chat + 取消对话静音 + + + Mute Chat + 对话静音 + + + Unknown + 未知 + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + %1 位成员, %2 在线 + + + %1 subscribers + %1 位订阅者 + + + %1 members + %1 位成员 + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + 未知 + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + 设置 + + + + ChatListViewItem + + Unknown + 未知 + + + You + + + + Unmute Chat + 取消对话静音 + + + Mute Chat + 对话静音 + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,33 +241,9 @@ Your message 你的消息 - - was never online - 完全离线 - - - offline, last online: last month - 离线,上次在线时间:上月 - - - offline, last online: last week - 离线,上次在线时间:上周 - - - offline, last online: %1 - 离线,上次在线时间: %1 - - - online - 在线 - - - offline, was recently online - 离线,最近在线 - %1 members, %2 online - %1 位成员, %2 在线 + %1 位成员, %2 位在线 %1 members @@ -143,7 +263,7 @@ Loading messages... - 加载消息中…… + 正在加载消息… Unmute Chat @@ -171,10 +291,14 @@ Uploading... - 正在上传…… + 正在上传… Forwarded Message + 转发消息 + + + This chat is empty. @@ -194,15 +318,15 @@ Waiting for network... - 等候网络连接…… + 等候网络连接… Connecting to network... - 连接到网络…… + 连接到网络… Connecting to proxy... - 连接到代理…… + 连接到代理… Connected @@ -210,7 +334,7 @@ Updating content... - 正在更新内容…… + 正在更新内容… chat @@ -232,114 +356,191 @@ 打开文档 + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils sent a picture myself - 发送照片 + 发送照片 sent a picture - 发送照片 + 发送照片 sent a video myself - 发送视频 + 发送视频 sent a video - 发送视频 + 发送视频 sent an animation myself - 发送动画 + 发送动画 sent an animation - 发送动画 + 发送动画 sent a voice note - + 发送语言留言 sent a document myself - 发送文档 + 发送文档 sent a document - 发送文档 + 发送文档 sent a location myself - 发送位置 + 发送位置 sent a location - 发送位置 + 发送位置 have registered with Telegram myself - 已注册到 Telegram + 已注册到 Telegram has registered with Telegram - 已注册到 Telegram + 已注册到 Telegram joined this chat myself - + 已加入此对话 joined this chat - + 已加入此对话 were added to this chat myself - 已经加入到此对话之中 + 已经加入到此对话之中 was added to this chat - 已加入到此对话 + 已加入到此对话 left this chat myself - 离开此对话 + 离开此对话 left this chat - 离开此对话 + 离开此对话 Unsupported message: %1 - 未读消息: %1 + 未读消息: %1 Sticker: %1 - 贴纸: %1 + 表情贴图: %1 sent a voice note myself - + 发送视频留言 sent a venue myself - 发送地点 + 发送地点 sent a venue - 发送地点 + 发送地点 + + + changed the chat title + myself + + + + changed the chat title + @@ -384,11 +585,11 @@ Please enter the code that you received: - 请输入你收到的验证码: + 请输入你收到的验证码: Loading... - 正在加载…… + 正在加载… Unable to authenticate you with the entered code. @@ -404,22 +605,26 @@ Please enter your password: - 请输入你的密码: + 请输入你的密码: Register User - + 注册用户 Enter your First Name - + 输入你的名字 Enter your Last Name - + 输入你的姓氏 User Registration + 用户注册 + + + Use the international format, e.g. %1 @@ -449,39 +654,27 @@ Waiting for network... - 等候网络连接: + 等候网络连接… Connecting to network... - 正在连接到网络…… + 正在连接到网络… Connecting to proxy... - 正在连接到代理…… + 正在连接到代理… Updating content... - 正在更新内容…… + 正在更新内容… Unknown 未知 - - You - - Loading chat list... - 正在加载对话列表…… - - - Unmute Chat - 取消静音对话 - - - Mute Chat - 静音对话 + 正在加载对话列表… Settings @@ -489,7 +682,7 @@ You don't have any chats yet. - + 你尚无任何对话。 @@ -512,46 +705,46 @@ Appearance - + 外观 Show stickers as images - + 像图片那样显示表情贴图 Show background for stickers and align them centrally like images - + 显示表情贴图背景并像图片那样自动居中 Notification feedback - + 通知反馈 All events - + 全部事件 Only new events - + 仅新事件 None - + Use non-graphical feedback (sound, vibration) for notifications - + 使用非图像反馈进行通知(例如声音及振动) StickerPicker Recently used - + 最近使用 Loading stickers... - + 正在加载表情贴图… @@ -625,7 +818,7 @@ sent a voice note - 发送语言 + 发送语音留言 sent a document @@ -653,7 +846,7 @@ %1K - %1T + %1K sent a venue @@ -718,5 +911,58 @@ myself 离开此对话 + + was never online + 完全离线 + + + offline, last online: last month + 离线,上次在线时间:上月 + + + offline, last online: last week + 离线,上次在线时间:上周 + + + offline, last online: %1 + 离线,上次在线时间: %1 + + + online + 在线 + + + offline, was recently online + 离线,最近在线 + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + + diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 9ba73fe..da0dd42 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -87,6 +87,150 @@ + + ChatInformationPage + + Unmute Chat + + + + Mute Chat + + + + Unknown + + + + The Invite Link has been copied to the clipboard. + + + + %1 members, %2 online + + + + %1 subscribers + + + + %1 members + + + + Leave Group + + + + Leaving chat + + + + Info + group or user infotext header + + + + Phone Number + user phone number header + + + + Invite Link + header + + + + There is no information text available, yet. + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + + ChatInformationTabItemMembersGroups + + Loading common chats… + chats you have in common with a user + + + + Unknown + + + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + + + Loading group members… + + + + You + + + + You don't have any groups in common with this user. + + + + This group is empty. + + + + + ChatInformationTabItemSettings + + Settings + Button: Chat Settings + + + + + ChatListViewItem + + Unknown + + + + You + + + + Unmute Chat + + + + Mute Chat + + + + User Info + + + + Group Info + + + + Mark all messages as read + + + ChatPage @@ -97,30 +241,6 @@ Your message - - was never online - - - - offline, last online: last month - - - - offline, last online: last week - - - - offline, last online: %1 - - - - online - - - - offline, was recently online - - %1 members, %2 online @@ -177,6 +297,10 @@ Forwarded Message + + This chat is empty. + + CoverPage @@ -232,6 +356,74 @@ + + EditGroupChatPermissionsColumn + + Group Member Permissions + what can normal group members do + + + + Send Messages + member permission + + + + Send Media Messages + member permission + + + + Send Other Messages + member permission + + + + Add Web Page Previews + member permission + + + + Change Chat Info + member permission + + + + Invite Users + member permission + + + + Pin Messages + member permission + + + + New Members + what can new group members do + + + + New members can see older messages + member permission + + + + + EditSuperGroupSlowModeColumn + + Slow Mode + + + + Off + + + + Set how long every chat member has to wait between Messages + + + FernschreiberUtils @@ -341,6 +533,15 @@ sent a venue + + changed the chat title + myself + + + + changed the chat title + + ImagePage @@ -422,6 +623,10 @@ Register User + + Use the international format, e.g. %1 + + LocationPreview @@ -467,22 +672,10 @@ Unknown - - You - - Loading chat list... - - Unmute Chat - - - - Mute Chat - - Settings @@ -718,5 +911,58 @@ myself + + was never online + + + + offline, last online: last month + + + + offline, last online: last week + + + + offline, last online: %1 + + + + online + + + + offline, was recently online + + + + Admin + channel user role + + + + Banned + channel user role + + + + Creator + channel user role + + + + Restricted + channel user role + + + + changed the chat title to %1 + myself + + + + changed the chat title to %1 + +