diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro
index 75db4e6..6efc7aa 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 \
diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml
new file mode 100644
index 0000000..a7ca8f6
--- /dev/null
+++ b/qml/components/ChatListViewItem.qml
@@ -0,0 +1,54 @@
+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: 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/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..e8d2221 100644
--- a/qml/components/ProfileThumbnail.qml
+++ b/qml/components/ProfileThumbnail.qml
@@ -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/chatInformationPage/ChatInformationEditArea.qml b/qml/components/chatInformationPage/ChatInformationEditArea.qml
new file mode 100644
index 0000000..fc37aad
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationEditArea.qml
@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..ad04316
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationProfilePicture.qml
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..3fa4f0d
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationProfilePictureList.qml
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..a9f5cfd
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationTabItemBase.qml
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..400ca76
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationTabItemDebug.qml
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..8ee4ae2
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml
@@ -0,0 +1,231 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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 ? delegateModel : 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)
+ }
+
+ 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..05b2454
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..6d4467c
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationTabView.qml
@@ -0,0 +1,169 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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 is prepared, but "disabled" for now
+ * to view shared media/links/…,
+ * we need message search with filters
+ */
+
+ // START: change this to enable
+ height: visible ? headerGrid.height : 0
+// height: 0
+ clip: true
+ visible: tabView.count > 1
+ // END: change this to enable
+
+ 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// + headerItem.itemIsActive
+ 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..46c250c
--- /dev/null
+++ b/qml/components/chatInformationPage/ChatInformationTextItem.qml
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..b085ae4
--- /dev/null
+++ b/qml/components/chatInformationPage/EditGroupChatPermissionsColumn.qml
@@ -0,0 +1,148 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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..bada085
--- /dev/null
+++ b/qml/components/chatInformationPage/EditSuperGroupSlowModeColumn.qml
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2020 Sebastian J. Wolf
+
+ 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/js/functions.js b/qml/js/functions.js
index ccf66f0..b8a795c 100644
--- a/qml/js/functions.js
+++ b/qml/js/functions.js
@@ -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/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..ac5da91 100644
--- a/qml/pages/ChatPage.qml
+++ b/qml/pages/ChatPage.qml
@@ -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();
@@ -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
@@ -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/OverviewPage.qml b/qml/pages/OverviewPage.qml
index bcc452c..67eea4c 100644
--- a/qml/pages/OverviewPage.qml
+++ b/qml/pages/OverviewPage.qml
@@ -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/src/chatlistmodel.cpp b/src/chatlistmodel.cpp
index ec33dde..70da9e2 100644
--- a/src/chatlistmodel.cpp
+++ b/src/chatlistmodel.cpp
@@ -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..00aed07 100644
--- a/src/chatlistmodel.h
+++ b/src/chatlistmodel.h
@@ -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..09dfea0 100644
--- a/src/chatmodel.cpp
+++ b/src/chatmodel.cpp
@@ -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..2d317e0 100644
--- a/src/chatmodel.h
+++ b/src/chatmodel.h
@@ -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/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/tdlibreceiver.cpp b/src/tdlibreceiver.cpp
index 407e633..2debac2 100644
--- a/src/tdlibreceiver.cpp
+++ b/src/tdlibreceiver.cpp
@@ -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..511520b 100644
--- a/src/tdlibreceiver.h
+++ b/src/tdlibreceiver.h
@@ -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..05d014d 100644
--- a/src/tdlibwrapper.cpp
+++ b/src/tdlibwrapper.cpp
@@ -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);
@@ -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");
diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h
index 6723470..cca025f 100644
--- a/src/tdlibwrapper.h
+++ b/src/tdlibwrapper.h
@@ -113,6 +113,7 @@ 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 sendTextMessage(const QString &chatId, 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..5b61b86 100644
--- a/translations/harbour-fernschreiber-de.ts
+++ b/translations/harbour-fernschreiber-de.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ Stummschaltung des Chats aufheben
+
+
+
+ Chat stummschalten
+
+
+
+ Unbekannt
+
+
+
+ Der Einladungslink wurde in die Zwischenablage kopiert.
+
+
+
+ %1 Mitglieder, %2 online
+
+
+
+ %1 Abonnenten
+
+
+
+ %1 Mitglieder
+
+
+
+ Gruppe verlassen
+
+
+
+ Verlasse Gruppe
+
+
+
+ group or user infotext header
+ Info
+
+
+
+ user phone number header
+ Telefonnummer
+
+
+
+ header
+ Einladungslink
+
+
+
+ Es gibt noch keinen Informationstext.
+
+
+
+ group title header
+ Chattitel
+
+
+
+ Geben Sie 1-126 Zeichen ein
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ Sie
+
+
+
+ chats you have in common with a user
+ Lade gemeinsame Chats…
+
+
+
+ Unbekannt
+
+
+
+ Button: groups in common (short)
+ Gruppen
+
+
+
+ Button: Group Members
+ Mitglieder
+
+
+
+ Lade Gruppenmitglieder…
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Einstellungen
+
+
+
+ ChatListViewItem
+
+
+ Unbekannt
+
+
+
+ Sie
+
+
+
+ Stummschaltung des Chats aufheben
+
+
+
+ Chat stummschalten
+
+
+
+ Benutzerinfos
+
+
+
+ Gruppeninfos
+
+
ChatPage
@@ -97,30 +229,6 @@
Ihre Nachricht
-
-
- war niemals online
-
-
-
- offline, zuletzt online im letzten Monat
-
-
-
- offline, zuletzt online in der letzten Woche
-
-
-
- offline, zuletzt online: %1
-
-
-
- online
-
-
-
- offline, war neulich online
-
%1 Mitglieder, %2 online
@@ -177,6 +285,10 @@
Weitergeleitete Nachricht
+
+
+ Dieser Chat ist leer.
+
CoverPage
@@ -232,6 +344,74 @@
Dokument öffnen
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+ Berechtigungen der Gruppenmitglieder
+
+
+
+ member permission
+ Nachrichten senden
+
+
+
+ member permission
+ Medien senden
+
+
+
+ member permission
+ Andere Nachrichten senden
+
+
+
+ member permission
+ Webseiten-Vorschau hinzufügen
+
+
+
+ member permission
+ Chatinformation ändern
+
+
+
+ member permission
+ Benutzer einladen
+
+
+
+ member permission
+ Nachrichten anpinnen
+
+
+
+ what can new group members do
+ Neue Mitglieder
+
+
+
+ member permission
+ Neue Mitglieder können ältere Nachrichten sehen
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+ Langsamer Modus
+
+
+
+ Aus
+
+
+
+ Legen Sie fest, wie lange jedes Mitglied zwischen zwei Nachrichten warten muss
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
hat einen Ort geschickt
+
+
+ myself
+ haben den Chattitel geändert
+
+
+
+ hat den Chattitel geändert
+
ImagePage
@@ -467,22 +656,10 @@
Unbekannt
-
-
- Sie
-
Lade Chatliste...
-
-
- Stummschaltung des Chats aufheben
-
-
-
- Chat stummschalten
-
Einstellungen
@@ -718,5 +895,58 @@
myself
haben diesen Chat verlassen
+
+
+ war niemals online
+
+
+
+ offline, zuletzt online im letzten Monat
+
+
+
+ offline, zuletzt online in der letzten Woche
+
+
+
+ offline, zuletzt online: %1
+
+
+
+ online
+
+
+
+ offline, war neulich online
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+ haben den Chattitel zu %1 geändert
+
+
+
+ hat den Chattitel zu %1 geändert
+
diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts
index 0398fdc..804501a 100644
--- a/translations/harbour-fernschreiber-es.ts
+++ b/translations/harbour-fernschreiber-es.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ habilitar notificación
+
+
+
+ deshabilitar notificación
+
+
+
+
+
+
+
+
+
+
+
+ %1 miembros, %2 en línea
+
+
+
+ %1 suscriptores
+
+
+
+ %1 miembros
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Ajustes
+
+
+
+ ChatListViewItem
+
+
+
+
+
+
+
+
+
+
+ habilitar notificación
+
+
+
+ deshabilitar notificación
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
Escribir mensaje
-
-
- nunca estuvo en línea
-
-
-
- sin línea, hace en línea: hace 1 mes
-
-
-
- sin línea, hace en línea: hace 1 semana
-
-
-
- sin línea, hace en línea: %1
-
-
-
- en línea
-
-
-
- sin línea, estuvo en línea
-
%1 miembros, %2 en línea
@@ -177,6 +285,10 @@
Mensaje reenviado
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
Abrir Documento
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
envió un lugar
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
desconocido
-
-
- Usted
-
cargando lista de charla...
-
-
- Habilitar notificación
-
-
-
- Deshabilitar notificación
-
Ajustes
@@ -718,5 +895,58 @@
myself
dejé esta charla
+
+
+ nunca estuvo en línea
+
+
+
+ sin línea, hace en línea: hace 1 mes
+
+
+
+ sin línea, hace en línea: hace 1 semana
+
+
+
+ sin línea, hace en línea: %1
+
+
+
+ en línea
+
+
+
+ sin línea, estuvo en línea
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts
index b03cc86..72629fc 100644
--- a/translations/harbour-fernschreiber-fi.ts
+++ b/translations/harbour-fernschreiber-fi.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ Poista keskustelun vaimennus
+
+
+
+ Vaimenna keskustelu
+
+
+
+ Tuntematon
+
+
+
+
+
+
+
+ %1 jäsentä, %2 paikalla
+
+
+
+ %1 tilaajaa
+
+
+
+ %1 jäsentä
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+ Tuntematon
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+ Sinä
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Asetukset
+
+
+
+ ChatListViewItem
+
+
+ Tuntematon
+
+
+
+ Sinä
+
+
+
+ Poista keskustelun vaimennus
+
+
+
+ Vaimenna keskustelu
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
Viestisi
-
-
- Ei ole ollut koskaan paikalla
-
-
-
- Poissa. Nähty viimeksi: viime kuussa
-
-
-
- Poissa. Nähty viimeksi: viime viikolla
-
-
-
- Poissa. Nähty viimeksi: %1
-
-
-
- paikalla
-
-
-
- poissa, oli hetki sitten paikalla
-
%1 jäsentä, %2 paikalla
@@ -177,6 +285,10 @@
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
Avaa dokumentti
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
Viestityyppiä ei tueta: %1
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
Tuntematon
-
-
- Sinä
-
Ladataan keskustelulistaa...
-
-
- Poista keskustelun vaimennus
-
-
-
- Vaimenna keskustelu
-
Asetukset
@@ -718,5 +895,58 @@
myself
poistuit keskustelusta
+
+
+ Ei ole ollut koskaan paikalla
+
+
+
+ Poissa. Nähty viimeksi: viime kuussa
+
+
+
+ Poissa. Nähty viimeksi: viime viikolla
+
+
+
+ Poissa. Nähty viimeksi: %1
+
+
+
+ paikalla
+
+
+
+ poissa, oli hetki sitten paikalla
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts
index 37d8ddf..c065b0c 100644
--- a/translations/harbour-fernschreiber-hu.ts
+++ b/translations/harbour-fernschreiber-hu.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ Csevegés némítás feloldása
+
+
+
+ Csevegés némítása
+
+
+
+ Ismeretlen
+
+
+
+
+
+
+
+ %1 tag, %2 online
+
+
+
+ %1 feliratkozott
+
+
+
+ %1 tag
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+ Ismeretlen
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+ Te
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Beállítások
+
+
+
+ ChatListViewItem
+
+
+ Ismeretlen
+
+
+
+ Te
+
+
+
+ Csevegés némítás feloldása
+
+
+
+ Csevegés némítása
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
Üzeneted
-
-
- soha nem volt online
-
-
-
- offline, utoljára online: múlt hónapban
-
-
-
- offline, utoljára online: múlt héten
-
-
-
- offline, utoljára online: %1
-
-
-
- online
-
-
-
- offline, nemrégen volt online
-
%1 tag, %2 online
@@ -177,6 +285,10 @@
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
Dokumentum megyitása
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
Ismeretlen
-
-
- Te
-
Csevegés lista betöltése...
-
-
- Csevegés némítás feloldása
-
-
-
- Csevegés némítása
-
Beállítások
@@ -718,5 +895,58 @@
myself
kilépett a csevegésből
+
+
+ soha nem volt online
+
+
+
+ offline, utoljára online: múlt hónapban
+
+
+
+ offline, utoljára online: múlt héten
+
+
+
+ offline, utoljára online: %1
+
+
+
+ online
+
+
+
+ offline, nemrégen volt online
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts
index f738048..2ae9096 100644
--- a/translations/harbour-fernschreiber-it.ts
+++ b/translations/harbour-fernschreiber-it.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+
+
+
+
+
+
+
+
+ Riattiva suoni chat
+
+
+
+ Silenzia chat
+
+
+
+ Sconosciuto
+
+
+
+
+
+
+
+ %1 membri, %2 online
+
+
+
+ %1 abbonati
+
+
+
+ %1 membri
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+ chats you have in common with a user
+
+
+
+
+
+
+
+
+ Tu
+
+
+
+ Sconosciuto
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Impostazioni
+
+
+
+ ChatListViewItem
+
+
+ Sconosciuto
+
+
+
+ Tu
+
+
+
+ Riattiva suoni chat
+
+
+
+ Silenzia chat
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
Tuo messaggio
-
-
- mai online
-
-
-
- offline, ultimo accesso il mese scorso
-
-
-
- offline, ultimo accesso la settimana scorsa
-
-
-
- offline, ultimo accesso: %1
-
-
-
- online
-
-
-
- offline, online di recente
-
%1 membri, %2 online
@@ -177,6 +285,10 @@
Messaggio inoltrato
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
Apri documento
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
ha inviato la posizione
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
Sconosciuto
-
-
- Tu
-
Carica lista chat...
-
-
- Riattiva suoni chat
-
-
-
- Silenzia chat
-
Impostazioni
@@ -718,5 +895,58 @@
myself
hanno lasciato questa chat
+
+
+ mai online
+
+
+
+ offline, ultimo accesso il mese scorso
+
+
+
+ offline, ultimo accesso la settimana scorsa
+
+
+
+ offline, ultimo accesso: %1
+
+
+
+ online
+
+
+
+ offline, online di recente
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts
index 2bd2d43..e083601 100644
--- a/translations/harbour-fernschreiber-pl.ts
+++ b/translations/harbour-fernschreiber-pl.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ Wyłącz wyciszenie czatu
+
+
+
+ Wycisz czat
+
+
+
+ Nieznany
+
+
+
+
+
+
+
+ $1 członków, %2 online
+
+
+
+ %1 subskrybentów
+
+
+
+ %1 czlonków
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+ Nieznany
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+ Ty
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Ustawienia
+
+
+
+ ChatListViewItem
+
+
+ Nieznany
+
+
+
+ Ty
+
+
+
+ Wyłącz wyciszenie czatu
+
+
+
+ Wycisz czat
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
Twoja wiadomość
-
-
- nigdy nie był online
-
-
-
- offline, ostatnio online: w zeszłym miesiącu
-
-
-
- offline, ostatnio online: w zeszłym tygodniu
-
-
-
- offline, ostatnio online: %1
-
-
-
- online
-
-
-
- offline, był niedawno online
-
$1 członków, %2 online
@@ -177,6 +285,10 @@
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
Otwórz dokument
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
Nieznany
-
-
- Ty
-
Ładowanie listy czatu...
-
-
- Wyłącz wyciszenie czatu
-
-
-
- Wycisz czat
-
Ustawienia
@@ -718,5 +895,58 @@
myself
opuścił ten czat
+
+
+ nigdy nie był online
+
+
+
+ offline, ostatnio online: w zeszłym miesiącu
+
+
+
+ offline, ostatnio online: w zeszłym tygodniu
+
+
+
+ offline, ostatnio online: %1
+
+
+
+ online
+
+
+
+ offline, był niedawno online
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts
index 7b1f303..99e7f7a 100644
--- a/translations/harbour-fernschreiber-ru.ts
+++ b/translations/harbour-fernschreiber-ru.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ Включить уведомления
+
+
+
+ Выключить уведомления
+
+
+
+
+
+
+
+
+
+
+
+ %1 участников, %2 онлайн
+
+
+
+ %1 подписчиков
+
+
+
+ %1 участников
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+ Вы
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ Настройки
+
+
+
+ ChatListViewItem
+
+
+
+
+
+
+ Вы
+
+
+
+ Включить уведомления
+
+
+
+ Выключить уведомления
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
Ваше сообщение
-
-
- никогда не был(а) онлайн
-
-
-
- офлайн, был(а) онлайн: в прошлом месяце
-
-
-
- офлайн, был(а) онлайн: на прошлой неделе
-
-
-
- офлайн, был(а) онлайн: %1
-
-
-
- онлайн
-
-
-
- офлайн, недавно был(а) онлайн
-
%1 участников, %2 онлайн
@@ -177,6 +285,10 @@
Пересланное сообщение
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
Открыть документ
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
отправил(а) место встречи
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
Неизвестный
-
-
- Вы
-
Загрузка чатов...
-
-
- Включить уведомления
-
-
-
- Выключить уведомления
-
Настройки
@@ -718,5 +895,58 @@
myself
покинул(а) чат
+
+
+ никогда не был(а) онлайн
+
+
+
+ офлайн, был(а) онлайн: в прошлом месяце
+
+
+
+ офлайн, был(а) онлайн: на прошлой неделе
+
+
+
+ офлайн, был(а) онлайн: %1
+
+
+
+ онлайн
+
+
+
+ офлайн, недавно был(а) онлайн
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts
index 25b5912..76e2755 100644
--- a/translations/harbour-fernschreiber-zh_CN.ts
+++ b/translations/harbour-fernschreiber-zh_CN.ts
@@ -87,6 +87,138 @@
%1
+
+ ChatInformationPage
+
+
+ 取消对话静音
+
+
+
+ 对话静音
+
+
+
+ 未知
+
+
+
+
+
+
+
+ %1 位成员, %2 在线
+
+
+
+ %1 位订阅者
+
+
+
+ %1 位成员
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+ 未知
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+ 你
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+ 设置
+
+
+
+ ChatListViewItem
+
+
+ 未知
+
+
+
+ 你
+
+
+
+ 取消对话静音
+
+
+
+ 对话静音
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
你的消息
-
-
- 完全离线
-
-
-
- 离线,上次在线时间:上月
-
-
-
- 离线,上次在线时间:上周
-
-
-
- 离线,上次在线时间: %1
-
-
-
- 在线
-
-
-
- 离线,最近在线
-
%1 位成员, %2 在线
@@ -177,6 +285,10 @@
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
打开文档
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
发送地点
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
未知
-
-
- 你
-
正在加载对话列表……
-
-
- 取消静音对话
-
-
-
- 静音对话
-
设置
@@ -718,5 +895,58 @@
myself
离开此对话
+
+
+ 完全离线
+
+
+
+ 离线,上次在线时间:上月
+
+
+
+ 离线,上次在线时间:上周
+
+
+
+ 离线,上次在线时间: %1
+
+
+
+ 在线
+
+
+
+ 离线,最近在线
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+
diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts
index 9ba73fe..845015c 100644
--- a/translations/harbour-fernschreiber.ts
+++ b/translations/harbour-fernschreiber.ts
@@ -87,6 +87,138 @@
+
+ ChatInformationPage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ group or user infotext header
+
+
+
+
+ user phone number header
+
+
+
+
+ header
+
+
+
+
+
+
+
+
+ group title header
+
+
+
+
+
+
+
+
+ ChatInformationTabItemMembersGroups
+
+
+ chats you have in common with a user
+
+
+
+
+
+
+
+
+ Button: groups in common (short)
+
+
+
+
+ Button: Group Members
+
+
+
+
+
+
+
+
+
+
+
+
+ ChatInformationTabItemSettings
+
+
+ Button: Chat Settings
+
+
+
+
+ ChatListViewItem
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ChatPage
@@ -97,30 +229,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -177,6 +285,10 @@
+
+
+
+
CoverPage
@@ -232,6 +344,74 @@
+
+ EditGroupChatPermissionsColumn
+
+
+ what can normal group members do
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ member permission
+
+
+
+
+ what can new group members do
+
+
+
+
+ member permission
+
+
+
+
+ EditSuperGroupSlowModeColumn
+
+
+
+
+
+
+
+
+
+
+
+
+
FernschreiberUtils
@@ -341,6 +521,15 @@
+
+
+ myself
+
+
+
+
+
+
ImagePage
@@ -467,22 +656,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
@@ -718,5 +895,58 @@
myself
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ channel user role
+
+
+
+
+ myself
+
+
+
+
+
+